Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/Lvalue.cc

    rb4f8808 r6b8c4a8  
    2121#include "Lvalue.h"
    2222
    23 #include "InitTweak/InitTweak.h"
    2423#include "Parser/LinkageSpec.h"          // for Spec, isBuiltin, Intrinsic
    2524#include "ResolvExpr/TypeEnvironment.h"  // for AssertionSet, OpenVarSet
    2625#include "ResolvExpr/Unify.h"            // for unify
    2726#include "ResolvExpr/typeops.h"
     27#include "SymTab/Autogen.h"
    2828#include "SymTab/Indexer.h"              // for Indexer
    2929#include "SynTree/Declaration.h"         // for Declaration, FunctionDecl
     
    3333#include "SynTree/Type.h"                // for PointerType, Type, FunctionType
    3434#include "SynTree/Visitor.h"             // for Visitor, acceptAll
    35 #include "Validate/FindSpecialDecls.h"   // for dereferenceOperator
    3635
    3736#if 0
     
    4544                // TODO: fold this into the general createDeref function??
    4645                Expression * mkDeref( Expression * arg ) {
    47                         if ( Validate::dereferenceOperator ) {
     46                        if ( SymTab::dereferenceOperator ) {
    4847                                // note: reference depth can be arbitrarily deep here, so peel off the outermost pointer/reference, not just pointer because they are effecitvely equivalent in this pass
    49                                 VariableExpr * deref = new VariableExpr( Validate::dereferenceOperator );
     48                                VariableExpr * deref = new VariableExpr( SymTab::dereferenceOperator );
    5049                                deref->result = new PointerType( Type::Qualifiers(), deref->result );
    5150                                Type * base = InitTweak::getPointerBase( arg->result );
     
    5453                                delete ret->result;
    5554                                ret->result = base->clone();
     55                                ret->result->set_lvalue( true );
    5656                                return ret;
    5757                        } else {
     
    146146
    147147        namespace {
    148                 // true for intrinsic function calls that return an lvalue in C
     148                // true for intrinsic function calls that return a reference
    149149                bool isIntrinsicReference( Expression * expr ) {
    150                         // known intrinsic-reference prelude functions
    151                         static std::set<std::string> lvalueFunctions = { "*?", "?[?]" };
    152150                        if ( UntypedExpr * untyped = dynamic_cast< UntypedExpr * >( expr ) ) {
    153151                                std::string fname = InitTweak::getFunctionName( untyped );
    154                                 return lvalueFunctions.count(fname);
     152                                // known intrinsic-reference prelude functions
     153                                return fname == "*?" || fname == "?[?]";
    155154                        } else if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( expr ) ) {
    156155                                if ( DeclarationWithType * func = InitTweak::getFunction( appExpr ) ) {
    157                                         return func->linkage == LinkageSpec::Intrinsic && lvalueFunctions.count(func->name);
     156                                        // use type of return variable rather than expr result type, since it may have been changed to a pointer type
     157                                        FunctionType * ftype = GenPoly::getFunctionType( func->get_type() );
     158                                        Type * ret = ftype->returnVals.empty() ? nullptr : ftype->returnVals.front()->get_type();
     159                                        return func->linkage == LinkageSpec::Intrinsic && dynamic_cast<ReferenceType *>( ret );
    158160                                }
    159161                        }
     
    166168                                ReferenceType * result = strict_dynamic_cast< ReferenceType * >( appExpr->result );
    167169                                appExpr->result = result->base->clone();
     170                                appExpr->result->set_lvalue( true );
    168171                                if ( ! inIntrinsic ) {
    169172                                        // when not in an intrinsic function, add a cast to
     
    194197                                unsigned int i = 0;
    195198                                const unsigned int end = ftype->parameters.size();
    196 
    197                                 /// The for loop may eagerly dereference the iterators and fail on empty lists
    198                                 if(i == end) { return appExpr; }
    199199                                for ( auto p : unsafe_group_iterate( appExpr->args, ftype->parameters ) ) {
     200                                        if (i == end) break;
    200201                                        Expression *& arg = std::get<0>( p );
    201202                                        Type * formal = std::get<1>( p )->get_type();
     
    211212                                                // TODO: it's likely that the second condition should be ... && ! isIntrinsicReference( arg ), but this requires investigation.
    212213
    213                                                 if ( function->linkage != LinkageSpec::Intrinsic && isIntrinsicReference( arg ) ) {
     214                                                if ( function->get_linkage() != LinkageSpec::Intrinsic && isIntrinsicReference( arg ) ) {
    214215                                                        // needed for definition of prelude functions, etc.
    215216                                                        // if argument is dereference or array subscript, the result isn't REALLY a reference, but non-intrinsic functions expect a reference: take address
     
    227228                                                        arg = new AddressExpr( arg );
    228229                                                // } else if ( function->get_linkage() == LinkageSpec::Intrinsic && InitTweak::getPointerBase( arg->result ) ) {
    229                                                 } else if ( function->linkage == LinkageSpec::Intrinsic && arg->result->referenceDepth() != 0 ) {
     230                                                } else if ( function->get_linkage() == LinkageSpec::Intrinsic && arg->result->referenceDepth() != 0 ) {
    230231                                                        // argument is a 'real' reference, but function expects a C lvalue: add a dereference to the reference-typed argument
    231232                                                        PRINT(
     
    242243                                        }
    243244                                        ++i;
    244                                         if (i == end) break;
    245245                                }
    246246                        }
     
    355355                        Type * destType = castExpr->result;
    356356                        Type * srcType = castExpr->arg->result;
    357                         assertf( destType, "Cast to no type in: %s", toCString( castExpr ) );
    358                         assertf( srcType, "Cast from no type in: %s", toCString( castExpr ) );
    359357                        int depth1 = destType->referenceDepth();
    360358                        int depth2 = srcType->referenceDepth();
    361359                        int diff = depth1 - depth2;
    362360
    363                         if ( diff > 0 && ! castExpr->arg->get_lvalue() ) {
     361                        if ( diff > 0 && ! srcType->get_lvalue() ) {
    364362                                // rvalue to reference conversion -- introduce temporary
    365363                                // know that reference depth of cast argument is 0, need to introduce n temporaries for reference depth of n, e.g.
     
    405403                                        ret = new AddressExpr( ret );
    406404                                }
    407                                 if ( castExpr->arg->get_lvalue() && ! ResolvExpr::typesCompatible( srcType, strict_dynamic_cast<ReferenceType *>( destType )->base, SymTab::Indexer() ) ) {
     405                                if ( srcType->get_lvalue() && ! ResolvExpr::typesCompatible( srcType, strict_dynamic_cast<ReferenceType *>( destType )->base, SymTab::Indexer() ) ) {
    408406                                        // must keep cast if cast-to type is different from the actual type
    409407                                        castExpr->arg = ret;
     
    434432                                delete ret->result;
    435433                                ret->result = castExpr->result;
    436                                 assert( ret->get_lvalue() ); // ensure result is lvalue
     434                                ret->result->set_lvalue( true ); // ensure result is lvalue
    437435                                castExpr->env = nullptr;
    438436                                castExpr->arg = nullptr;
Note: See TracChangeset for help on using the changeset viewer.