Changeset a3323db1


Ignore:
Timestamp:
Apr 17, 2018, 11:06:04 AM (4 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
aaron-thesis, arm-eh, cleanup-dtors, deferred_resn, demangler, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, with_gc
Children:
c0bf94e
Parents:
5f08961d
Message:

add a cast to every address-of function argument and initializer [fixes #84]

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/Lvalue.cc

    r5f08961d ra3323db1  
    9898                };
    9999
    100                 struct AddrRef final : public WithGuards {
     100                struct AddrRef final : public WithGuards, public WithVisitorRef<AddrRef>, public WithShortCircuiting {
    101101                        void premutate( AddressExpr * addrExpr );
    102102                        Expression * postmutate( AddressExpr * addrExpr );
    103103                        void premutate( Expression * expr );
     104                        void premutate( ApplicationExpr * appExpr );
     105                        void premutate( SingleInit * init );
     106
     107                        void handleNonAddr( Expression * );
    104108
    105109                        bool first = true;
    106110                        bool current = false;
    107111                        int refDepth = 0;
     112                        bool addCast = false;
    108113                };
    109114        } // namespace
     
    208213                                                if ( function->get_linkage() != LinkageSpec::Intrinsic && isIntrinsicReference( arg ) ) {
    209214                                                        // if argument is dereference or array subscript, the result isn't REALLY a reference, but non-intrinsic functions expect a reference: take address
     215
     216                                                        // NOTE: previously, this condition fixed
     217                                                        //   void f(int *&);
     218                                                        //   int & x = ...;
     219                                                        //   f(&x);
     220                                                        // But now this is taken care of by a reference cast added by AddrRef. Need to find a new
     221                                                        // example or remove this branch.
     222
    210223                                                        PRINT(
    211224                                                                std::cerr << "===is intrinsic arg in non-intrinsic call - adding address" << std::endl;
     
    233246
    234247                // idea: &&&E: get outer &, inner &
    235                 // at inner &, record depth D of reference type
     248                // at inner &, record depth D of reference type of argument of &
    236249                // at outer &, add D derefs.
    237                 void AddrRef::premutate( Expression * ) {
     250                void AddrRef::handleNonAddr( Expression * ) {
     251                        // non-address-of: reset status variables:
     252                        // * current expr is NOT the first address-of expr in an address-of chain
     253                        // * next seen address-of expr IS the first in the chain.
    238254                        GuardValue( current );
    239255                        GuardValue( first );
     
    242258                }
    243259
     260                void AddrRef::premutate( Expression * expr ) {
     261                        handleNonAddr( expr );
     262                        GuardValue( addCast );
     263                        addCast = false;
     264                }
     265
    244266                void AddrRef::premutate( AddressExpr * ) {
    245267                        GuardValue( current );
    246268                        GuardValue( first );
    247                         current = first;
    248                         first = false;
    249                         if ( current ) {
     269                        current = first; // is this the first address-of in the chain?
     270                        first = false;   // from here out, no longer possible for next address-of to be first in chain
     271                        if ( current ) { // this is the outermost address-of in a chain
    250272                                GuardValue( refDepth );
    251                                 refDepth = 0;
     273                                refDepth = 0;  // set depth to 0 so that postmutate can find the innermost address-of easily
    252274                        }
    253275                }
     
    255277                Expression * AddrRef::postmutate( AddressExpr * addrExpr ) {
    256278                        if ( refDepth == 0 ) {
     279                                // this is the innermost address-of in a chain, record depth D
    257280                                if ( ! isIntrinsicReference( addrExpr->arg ) ) {
    258281                                        // try to avoid ?[?]
     282                                        // xxx - is this condition still necessary? intrinsicReferences should have a cast around them at this point, so I don't think this condition ever fires.
    259283                                        refDepth = addrExpr->arg->result->referenceDepth();
    260                                 }
    261                         }
    262                         if ( current ) {
     284                                } else {
     285                                        assertf( false, "AddrRef : address-of should not have intrinsic reference argument: %s", toCString( addrExpr->arg ) );
     286                                }
     287                        }
     288                        if ( current ) { // this is the outermost address-of in a chain
    263289                                Expression * ret = addrExpr;
    264290                                while ( refDepth ) {
     291                                        // add one dereference for each
    265292                                        ret = mkDeref( ret );
    266293                                        refDepth--;
    267294                                }
     295
     296                                if ( addCast ) {
     297                                        return new CastExpr( ret, addrExpr->result->clone() );
     298                                }
    268299                                return ret;
    269300                        }
    270301                        return addrExpr;
    271302                }
     303
     304                void AddrRef::premutate( ApplicationExpr * appExpr ) {
     305                        visit_children = false;
     306                        GuardValue( addCast );
     307                        handleNonAddr( appExpr );
     308                        for ( Expression *& arg : appExpr->args ) {
     309                                // each argument with address-of requires a cast
     310                                addCast = true;
     311                                arg = arg->acceptMutator( *visitor );
     312                        }
     313                }
     314
     315                void AddrRef::premutate( SingleInit * ) {
     316                        GuardValue( addCast );
     317                        // each initialization context with address-of requires a cast
     318                        addCast = true;
     319                }
     320
    272321
    273322                Expression * ReferenceConversions::postmutate( AddressExpr * addrExpr ) {
Note: See TracChangeset for help on using the changeset viewer.