Ignore:
Timestamp:
Oct 29, 2019, 4:01:24 PM (6 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
773db65, 9421f3d8
Parents:
7951100 (diff), 8364209 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/Lvalue.cc

    r7951100 rb067d9b  
    2121#include "Lvalue.h"
    2222
     23#include "InitTweak/InitTweak.h"
    2324#include "Parser/LinkageSpec.h"          // for Spec, isBuiltin, Intrinsic
    2425#include "ResolvExpr/TypeEnvironment.h"  // for AssertionSet, OpenVarSet
    2526#include "ResolvExpr/Unify.h"            // for unify
    2627#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
    3536
    3637#if 0
     
    4445                // TODO: fold this into the general createDeref function??
    4546                Expression * mkDeref( Expression * arg ) {
    46                         if ( SymTab::dereferenceOperator ) {
     47                        if ( Validate::dereferenceOperator ) {
    4748                                // 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
    48                                 VariableExpr * deref = new VariableExpr( SymTab::dereferenceOperator );
     49                                VariableExpr * deref = new VariableExpr( Validate::dereferenceOperator );
    4950                                deref->result = new PointerType( Type::Qualifiers(), deref->result );
    5051                                Type * base = InitTweak::getPointerBase( arg->result );
     
    5354                                delete ret->result;
    5455                                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 a reference
     148                // true for intrinsic function calls that return an lvalue in C
    149149                bool isIntrinsicReference( Expression * expr ) {
     150                        // known intrinsic-reference prelude functions
     151                        static std::set<std::string> lvalueFunctions = { "*?", "?[?]" };
    150152                        if ( UntypedExpr * untyped = dynamic_cast< UntypedExpr * >( expr ) ) {
    151153                                std::string fname = InitTweak::getFunctionName( untyped );
    152                                 // known intrinsic-reference prelude functions
    153                                 return fname == "*?" || fname == "?[?]";
     154                                return lvalueFunctions.count(fname);
    154155                        } else if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( expr ) ) {
    155156                                if ( DeclarationWithType * func = InitTweak::getFunction( appExpr ) ) {
    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 );
     157                                        return func->linkage == LinkageSpec::Intrinsic && lvalueFunctions.count(func->name);
    160158                                }
    161159                        }
     
    168166                                ReferenceType * result = strict_dynamic_cast< ReferenceType * >( appExpr->result );
    169167                                appExpr->result = result->base->clone();
    170                                 appExpr->result->set_lvalue( true );
    171168                                if ( ! inIntrinsic ) {
    172169                                        // when not in an intrinsic function, add a cast to
     
    197194                                unsigned int i = 0;
    198195                                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;
    201200                                        Expression *& arg = std::get<0>( p );
    202201                                        Type * formal = std::get<1>( p )->get_type();
     
    212211                                                // TODO: it's likely that the second condition should be ... && ! isIntrinsicReference( arg ), but this requires investigation.
    213212
    214                                                 if ( function->get_linkage() != LinkageSpec::Intrinsic && isIntrinsicReference( arg ) ) {
     213                                                if ( function->linkage != LinkageSpec::Intrinsic && isIntrinsicReference( arg ) ) {
    215214                                                        // needed for definition of prelude functions, etc.
    216215                                                        // if argument is dereference or array subscript, the result isn't REALLY a reference, but non-intrinsic functions expect a reference: take address
     
    228227                                                        arg = new AddressExpr( arg );
    229228                                                // } else if ( function->get_linkage() == LinkageSpec::Intrinsic && InitTweak::getPointerBase( arg->result ) ) {
    230                                                 } else if ( function->get_linkage() == LinkageSpec::Intrinsic && arg->result->referenceDepth() != 0 ) {
     229                                                } else if ( function->linkage == LinkageSpec::Intrinsic && arg->result->referenceDepth() != 0 ) {
    231230                                                        // argument is a 'real' reference, but function expects a C lvalue: add a dereference to the reference-typed argument
    232231                                                        PRINT(
     
    243242                                        }
    244243                                        ++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 ) );
    357359                        int depth1 = destType->referenceDepth();
    358360                        int depth2 = srcType->referenceDepth();
    359361                        int diff = depth1 - depth2;
    360362
    361                         if ( diff > 0 && ! srcType->get_lvalue() ) {
     363                        if ( diff > 0 && ! castExpr->arg->get_lvalue() ) {
    362364                                // rvalue to reference conversion -- introduce temporary
    363365                                // know that reference depth of cast argument is 0, need to introduce n temporaries for reference depth of n, e.g.
     
    403405                                        ret = new AddressExpr( ret );
    404406                                }
    405                                 if ( srcType->get_lvalue() && ! ResolvExpr::typesCompatible( srcType, strict_dynamic_cast<ReferenceType *>( destType )->base, SymTab::Indexer() ) ) {
     407                                if ( castExpr->arg->get_lvalue() && ! ResolvExpr::typesCompatible( srcType, strict_dynamic_cast<ReferenceType *>( destType )->base, SymTab::Indexer() ) ) {
    406408                                        // must keep cast if cast-to type is different from the actual type
    407409                                        castExpr->arg = ret;
     
    432434                                delete ret->result;
    433435                                ret->result = castExpr->result;
    434                                 ret->result->set_lvalue( true ); // ensure result is lvalue
     436                                assert( ret->get_lvalue() ); // ensure result is lvalue
    435437                                castExpr->env = nullptr;
    436438                                castExpr->arg = nullptr;
Note: See TracChangeset for help on using the changeset viewer.