Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/Lvalue.cc

    r9aaac6e9 r08fc48f  
    1717#include <string>                        // for string
    1818
    19 #include "Common/PassVisitor.h"
    2019#include "Common/SemanticError.h"        // for SemanticError
    2120#include "GenPoly.h"                     // for isPolyType
    2221#include "Lvalue.h"
    23 
    2422#include "Parser/LinkageSpec.h"          // for Spec, isBuiltin, Intrinsic
    2523#include "ResolvExpr/TypeEnvironment.h"  // for AssertionSet, OpenVarSet
    2624#include "ResolvExpr/Unify.h"            // for unify
    27 #include "ResolvExpr/typeops.h"
    28 #include "SymTab/Autogen.h"
    2925#include "SymTab/Indexer.h"              // for Indexer
    3026#include "SynTree/Declaration.h"         // for Declaration, FunctionDecl
     
    3531#include "SynTree/Visitor.h"             // for Visitor, acceptAll
    3632
    37 #if 0
    38 #define PRINT(x) x
    39 #else
    40 #define PRINT(x)
    41 #endif
    42 
    4333namespace GenPoly {
    4434        namespace {
    45                 // TODO: fold this into the general createDeref function??
    46                 Expression * mkDeref( Expression * arg ) {
    47                         if ( SymTab::dereferenceOperator ) {
    48                                 VariableExpr * deref = new VariableExpr( SymTab::dereferenceOperator );
    49                                 deref->set_result( new PointerType( Type::Qualifiers(), deref->get_result() ) );
    50                                 Type * base = InitTweak::getPointerBase( arg->get_result() );
    51                                 assertf( base, "expected pointer type in dereference (type was %s)", toString( arg->get_result() ).c_str() );
    52                                 ApplicationExpr * ret = new ApplicationExpr( deref, { arg } );
    53                                 delete ret->get_result();
    54                                 ret->set_result( base->clone() );
    55                                 ret->get_result()->set_lvalue( true );
    56                                 return ret;
    57                         } else {
    58                                 return UntypedExpr::createDeref( arg );
    59                         }
    60                 }
    61 
    62                 struct ReferenceConversions final {
    63                         Expression * postmutate( CastExpr * castExpr );
    64                         Expression * postmutate( AddressExpr * addrExpr );
     35                /// Replace uses of lvalue returns with appropriate pointers
     36                class Pass1 : public Mutator {
     37                  public:
     38                        Pass1();
     39
     40                        virtual Expression *mutate( ApplicationExpr *appExpr );
     41                        virtual Statement *mutate( ReturnStmt *appExpr );
     42                        virtual DeclarationWithType *mutate( FunctionDecl *funDecl );
     43                  private:
     44                        DeclarationWithType* retval;
    6545                };
    6646
    67                 /// Intrinsic functions that take reference parameters don't REALLY take reference parameters -- their reference arguments must always be implicitly dereferenced.
    68                 struct FixIntrinsicArgs final {
    69                         Expression * postmutate( ApplicationExpr * appExpr );
    70                 };
    71 
    72                 struct FixIntrinsicResult final : public WithGuards {
    73                         Expression * postmutate( ApplicationExpr * appExpr );
    74                         void premutate( FunctionDecl * funcDecl );
    75                         bool inIntrinsic = false;
    76                 };
    77 
    78                 /// Replace reference types with pointer types
    79                 struct ReferenceTypeElimination final {
    80                         Type * postmutate( ReferenceType * refType );
     47                /// Replace declarations of lvalue returns with appropriate pointers
     48                class Pass2 : public Visitor {
     49                  public:
     50                        virtual void visit( FunctionType *funType );
     51                  private:
    8152                };
    8253
     
    8455                /// https://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Lvalues.html#Lvalues
    8556                /// Replaces &(a,b) with (a, &b), &(a ? b : c) with (a ? &b : &c)
    86                 struct GeneralizedLvalue final : public WithVisitorRef<GeneralizedLvalue> {
    87                         Expression * postmutate( AddressExpr * addressExpr );
    88                         Expression * postmutate( MemberExpr * memExpr );
     57                class GeneralizedLvalue : public Mutator {
     58                        typedef Mutator Parent;
     59
     60                        virtual Expression * mutate( MemberExpr * memExpr );
     61                        virtual Expression * mutate( AddressExpr * addressExpr );
    8962
    9063                        template<typename Func>
    9164                        Expression * applyTransformation( Expression * expr, Expression * arg, Func mkExpr );
    9265                };
    93 
    94                 /// Removes redundant &*/*& pattern that this pass can generate
    95                 struct CollapseAddrDeref final {
    96                         Expression * postmutate( AddressExpr * addressExpr );
    97                         Expression * postmutate( ApplicationExpr * appExpr );
    98                 };
    99 
    100                 struct AddrRef final : public WithGuards {
    101                         void premutate( AddressExpr * addrExpr );
    102                         Expression * postmutate( AddressExpr * addrExpr );
    103                         void premutate( Expression * expr );
    104 
    105                         bool first = true;
    106                         bool current = false;
    107                         int refDepth = 0;
    108                 };
    10966        } // namespace
    11067
    111         static bool referencesEliminated = false;
    112         // used by UntypedExpr::createDeref to determine whether result type of dereference should be ReferenceType or value type.
    113         bool referencesPermissable() {
    114                 return ! referencesEliminated;
     68        void convertLvalue( std::list< Declaration* >& translationUnit ) {
     69                Pass1 p1;
     70                Pass2 p2;
     71                GeneralizedLvalue genLval;
     72                mutateAll( translationUnit, p1 );
     73                acceptAll( translationUnit, p2 );
     74                mutateAll( translationUnit, genLval );
    11575        }
    11676
    117         void convertLvalue( std::list< Declaration* >& translationUnit ) {
    118                 PassVisitor<ReferenceConversions> refCvt;
    119                 PassVisitor<ReferenceTypeElimination> elim;
    120                 PassVisitor<GeneralizedLvalue> genLval;
    121                 PassVisitor<FixIntrinsicArgs> fixer;
    122                 PassVisitor<CollapseAddrDeref> collapser;
    123                 PassVisitor<AddrRef> addrRef;
    124                 PassVisitor<FixIntrinsicResult> intrinsicResults;
    125                 mutateAll( translationUnit, intrinsicResults );
    126                 mutateAll( translationUnit, addrRef );
    127                 mutateAll( translationUnit, refCvt );
    128                 mutateAll( translationUnit, fixer );
    129                 mutateAll( translationUnit, collapser );
    130                 mutateAll( translationUnit, genLval );
    131                 mutateAll( translationUnit, elim );  // last because other passes need reference types to work
    132 
    133                 // from this point forward, no other pass should create reference types.
    134                 referencesEliminated = true;
    135         }
    136 
    13777        Expression * generalizedLvalue( Expression * expr ) {
    138                 PassVisitor<GeneralizedLvalue> genLval;
     78                GeneralizedLvalue genLval;
    13979                return expr->acceptMutator( genLval );
    14080        }
    14181
    14282        namespace {
    143                 // true for intrinsic function calls that return a reference
    144                 bool isIntrinsicReference( Expression * expr ) {
    145                         if ( UntypedExpr * untyped = dynamic_cast< UntypedExpr * >( expr ) ) {
    146                                 std::string fname = InitTweak::getFunctionName( untyped );
    147                                 // known intrinsic-reference prelude functions
    148                                 return fname == "*?" || fname == "?[?]";
    149                         } else if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( expr ) ) {
    150                                 if ( DeclarationWithType * func = InitTweak::getFunction( appExpr ) ) {
    151                                         // use type of return variable rather than expr result type, since it may have been changed to a pointer type
    152                                         FunctionType * ftype = GenPoly::getFunctionType( func->get_type() );
    153                                         Type * ret = ftype->get_returnVals().empty() ? nullptr : ftype->get_returnVals().front()->get_type();
    154                                         return func->get_linkage() == LinkageSpec::Intrinsic && dynamic_cast<ReferenceType *>( ret );
     83                Type* isLvalueRet( FunctionType *function ) {
     84                        if ( function->get_returnVals().empty() ) return 0;
     85                        Type *ty = function->get_returnVals().front()->get_type();
     86                        return ty->get_lvalue() ? ty : 0;
     87                }
     88
     89                bool isIntrinsicApp( ApplicationExpr *appExpr ) {
     90                        if ( VariableExpr *varExpr = dynamic_cast< VariableExpr* >( appExpr->get_function() ) ) {
     91                                return varExpr->get_var()->get_linkage() == LinkageSpec::Intrinsic;
     92                        } else {
     93                                return false;
     94                        } // if
     95                }
     96
     97                Pass1::Pass1() {
     98                }
     99
     100                DeclarationWithType * Pass1::mutate( FunctionDecl *funcDecl ) {
     101                        if ( funcDecl->get_statements() ) {
     102                                DeclarationWithType* oldRetval = retval;
     103                                retval = 0;
     104                                if ( ! LinkageSpec::isBuiltin( funcDecl->get_linkage() ) && isLvalueRet( funcDecl->get_functionType() ) ) {
     105                                        retval = funcDecl->get_functionType()->get_returnVals().front();
    155106                                }
    156                         }
    157                         return false;
    158                 }
    159 
    160                 Expression * FixIntrinsicResult::postmutate( ApplicationExpr * appExpr ) {
    161                         if ( isIntrinsicReference( appExpr ) ) {
    162                                 // eliminate reference types from intrinsic applications - now they return lvalues
    163                                 Type * result = appExpr->get_result();
    164                                 appExpr->set_result( result->stripReferences()->clone() );
    165                                 appExpr->get_result()->set_lvalue( true );
    166                                 if ( ! inIntrinsic ) {
    167                                         // when not in an intrinsic function, add a cast to
    168                                         // don't add cast when in an intrinsic function, since they already have the cast
    169                                         Expression * ret = new CastExpr( appExpr, result );
    170                                         ret->set_env( appExpr->get_env() );
    171                                         appExpr->set_env( nullptr );
    172                                         return ret;
     107                                // fix expressions and return statements in this function
     108                                funcDecl->set_statements( funcDecl->get_statements()->acceptMutator( *this ) );
     109                                retval = oldRetval;
     110                        } // if
     111                        return funcDecl;
     112                }
     113
     114                Expression * Pass1::mutate( ApplicationExpr *appExpr ) {
     115                        appExpr->get_function()->acceptMutator( *this );
     116                        mutateAll( appExpr->get_args(), *this );
     117
     118                        PointerType *pointer = safe_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() );
     119                        FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() );
     120
     121                        Type *funType = isLvalueRet( function );
     122                        if ( funType && ! isIntrinsicApp( appExpr ) ) {
     123                                Expression *expr = appExpr;
     124                                Type *appType = appExpr->get_result();
     125                                if ( isPolyType( funType ) && ! isPolyType( appType ) ) {
     126                                        // make sure cast for polymorphic type is inside dereference
     127                                        expr = new CastExpr( appExpr, new PointerType( Type::Qualifiers(), appType->clone() ) );
    173128                                }
    174                                 delete result;
    175                         }
    176                         return appExpr;
    177                 }
    178 
    179                 void FixIntrinsicResult::premutate( FunctionDecl * funcDecl ) {
    180                         GuardValue( inIntrinsic );
    181                         inIntrinsic =  funcDecl->linkage == LinkageSpec::Intrinsic;
    182                 }
    183 
    184                 Expression * FixIntrinsicArgs::postmutate( ApplicationExpr * appExpr ) {
    185                         // intrinsic functions don't really take reference-typed parameters, so they require an implicit dereference on their arguments.
    186                         if ( DeclarationWithType * function = InitTweak::getFunction( appExpr ) ) {
    187                                 FunctionType * ftype = GenPoly::getFunctionType( function->get_type() );
    188                                 assertf( ftype, "Function declaration does not have function type." );
    189                                 // can be of differing lengths only when function is variadic
    190                                 assertf( ftype->get_parameters().size() == appExpr->get_args().size() || ftype->get_isVarArgs(), "ApplicationExpr args do not match formal parameter type." );
    191 
    192 
    193                                 unsigned int i = 0;
    194                                 const unsigned int end = ftype->get_parameters().size();
    195                                 for ( auto p : unsafe_group_iterate( appExpr->get_args(), ftype->get_parameters() ) ) {
    196                                         if (i == end) break;
    197                                         Expression *& arg = std::get<0>( p );
    198                                         Type * formal = std::get<1>( p )->get_type();
    199                                         PRINT(
    200                                                 std::cerr << "pair<0>: " << arg << std::endl;
    201                                                 std::cerr << "pair<1>: " << formal << std::endl;
    202                                         )
    203                                         if ( dynamic_cast<ReferenceType*>( formal ) ) {
    204                                                 if ( isIntrinsicReference( arg ) ) { // do not combine conditions, because that changes the meaning of the else if
    205                                                         if ( function->get_linkage() != LinkageSpec::Intrinsic ) { // intrinsic functions that turn pointers into references
    206                                                                 // if argument is dereference or array subscript, the result isn't REALLY a reference, so it's not necessary to fix the argument
    207                                                                 PRINT(
    208                                                                         std::cerr << "===is intrinsic arg in non-intrinsic call - adding address" << std::endl;
    209                                                                 )
    210                                                                 arg = new AddressExpr( arg );
    211                                                         }
    212                                                 } else if ( function->get_linkage() == LinkageSpec::Intrinsic ) {
    213                                                         // std::cerr << "===adding deref to arg" << std::endl;
    214                                                         // if the parameter is a reference, add a dereference to the reference-typed argument.
    215                                                         Type * baseType = InitTweak::getPointerBase( arg->get_result() );
    216                                                         assertf( baseType, "parameter is reference, arg must be pointer or reference: %s", toString( arg->get_result() ).c_str() );
    217                                                         PointerType * ptrType = new PointerType( Type::Qualifiers(), baseType->clone() );
    218                                                         delete arg->get_result();
    219                                                         arg->set_result( ptrType );
    220                                                         arg = mkDeref( arg );
    221                                                 }
    222                                         }
    223                                         ++i;
    224                                 }
    225                         }
    226                         return appExpr;
    227                 }
    228 
    229                 // idea: &&&E: get outer &, inner &
    230                 // at inner &, record depth D of reference type
    231                 // at outer &, add D derefs.
    232                 void AddrRef::premutate( Expression * ) {
    233                         GuardValue( current );
    234                         GuardValue( first );
    235                         current = false;
    236                         first = true;
    237                 }
    238 
    239                 void AddrRef::premutate( AddressExpr * ) {
    240                         GuardValue( current );
    241                         GuardValue( first );
    242                         current = first;
    243                         first = false;
    244                         if ( current ) {
    245                                 GuardValue( refDepth );
    246                                 refDepth = 0;
    247                         }
    248                 }
    249 
    250                 Expression * AddrRef::postmutate( AddressExpr * addrExpr ) {
    251                         if ( refDepth == 0 ) {
    252                                 if ( ! isIntrinsicReference( addrExpr->get_arg() ) ) {
    253                                         // try to avoid ?[?]
    254                                         refDepth = addrExpr->get_arg()->get_result()->referenceDepth();
    255                                 }
    256                         }
    257                         if ( current ) {
    258                                 Expression * ret = addrExpr;
    259                                 while ( refDepth ) {
    260                                         ret = mkDeref( ret );
    261                                         refDepth--;
    262                                 }
    263                                 return ret;
    264                         }
    265                         return addrExpr;
    266                 }
    267 
    268                 Expression * ReferenceConversions::postmutate( AddressExpr * addrExpr ) {
    269                         // Inner expression may have been lvalue to reference conversion, which becomes an address expression.
    270                         // In this case, remove the outer address expression and return the argument.
    271                         // TODO: It's possible that this might catch too much and require a more sophisticated check.
    272                         return addrExpr;
    273                 }
    274 
    275                 Expression * ReferenceConversions::postmutate( CastExpr * castExpr ) {
    276                         // xxx - is it possible to convert directly between reference types with a different base? E.g.,
    277                         //   int x;
    278                         //   (double&)x;
    279                         // At the moment, I am working off of the assumption that this is illegal, thus the cast becomes redundant
    280                         // after this pass, so trash the cast altogether. If that changes, care must be taken to insert the correct
    281                         // pointer casts in the right places.
    282 
    283                         // conversion to reference type
    284                         if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( castExpr->get_result() ) ) {
    285                                 (void)refType;
    286                                 if ( ReferenceType * otherRef = dynamic_cast< ReferenceType * >( castExpr->get_arg()->get_result() ) ) {
    287                                         // nothing to do if casting from reference to reference.
    288                                         (void)otherRef;
    289                                         PRINT( std::cerr << "convert reference to reference -- nop" << std::endl; )
    290                                         if ( isIntrinsicReference( castExpr->get_arg() ) ) {
    291                                                 Expression * callExpr = castExpr->get_arg();
    292                                                 PRINT(
    293                                                         std::cerr << "but arg is deref -- &" << std::endl;
    294                                                         std::cerr << callExpr << std::endl;
    295                                                 )
    296                                                 callExpr = new AddressExpr( callExpr ); // this doesn't work properly for multiple casts
    297                                                 delete callExpr->get_result();
    298                                                 callExpr->set_result( refType->clone() );
    299                                                 // move environment out to new top-level
    300                                                 callExpr->set_env( castExpr->get_env() );
    301                                                 castExpr->set_arg( nullptr );
    302                                                 castExpr->set_env( nullptr );
    303                                                 delete castExpr;
    304                                                 return callExpr;
    305                                         }
    306                                         int depth1 = refType->referenceDepth();
    307                                         int depth2 = otherRef->referenceDepth();
    308                                         int diff = depth1-depth2;
    309                                         if ( diff == 0 ) {
    310                                                 assertf( depth1 == depth2, "non-intrinsic reference with cast of reference to reference not yet supported: %d %d %s", depth1, depth2, toString( castExpr ).c_str() );
    311                                                 PRINT( std::cerr << castExpr << std::endl; )
    312                                                 return castExpr;
    313                                         } else if ( diff < 0 ) {
    314                                                 Expression * ret = castExpr->get_arg();
    315                                                 for ( int i = 0; i < diff; ++i ) {
    316                                                         ret = mkDeref( ret );
    317                                                 }
    318                                                 ret->set_env( castExpr->get_env() );
    319                                                 delete ret->get_result();
    320                                                 ret->set_result( castExpr->get_result() );
    321                                                 castExpr->set_env( nullptr );
    322                                                 castExpr->set_arg( nullptr );
    323                                                 castExpr->set_result( nullptr );
    324                                                 delete castExpr;
    325                                                 return ret;
    326                                         } else if ( diff > 0 ) {
    327                                                 Expression * ret = castExpr->get_arg();
    328                                                 for ( int i = 0; i < diff; ++i ) {
    329                                                         ret = new AddressExpr( ret );
    330                                                 }
    331                                                 ret->set_env( castExpr->get_env() );
    332                                                 delete ret->get_result();
    333                                                 ret->set_result( castExpr->get_result() );
    334                                                 castExpr->set_env( nullptr );
    335                                                 castExpr->set_arg( nullptr );
    336                                                 castExpr->set_result( nullptr );
    337                                                 delete castExpr;
    338                                                 return ret;
    339                                         }
    340 
    341                                         assertf( depth1 == depth2, "non-intrinsic reference with cast of reference to reference not yet supported: %d %d %s", depth1, depth2, toString( castExpr ).c_str() );
    342                                         PRINT( std::cerr << castExpr << std::endl; )
    343                                         return castExpr;
    344                                 } else if ( castExpr->get_arg()->get_result()->get_lvalue() ) {
    345                                         // conversion from lvalue to reference
    346                                         // xxx - keep cast, but turn into pointer cast??
    347                                         // xxx - memory
    348                                         PRINT(
    349                                                 std::cerr << "convert lvalue to reference -- &" << std::endl;
    350                                                 std::cerr << castExpr->get_arg() << std::endl;
    351                                         )
    352                                         AddressExpr * ret = new AddressExpr( castExpr->get_arg() );
    353                                         if ( refType->get_base()->get_qualifiers() != castExpr->get_arg()->get_result()->get_qualifiers() ) {
    354                                                 // must keep cast if cast-to type is different from the actual type
    355                                                 castExpr->set_arg( ret );
    356                                                 return castExpr;
    357                                         }
    358                                         ret->set_env( castExpr->get_env() );
    359                                         delete ret->get_result();
    360                                         ret->set_result( castExpr->get_result() );
    361                                         castExpr->set_env( nullptr );
    362                                         castExpr->set_arg( nullptr );
    363                                         castExpr->set_result( nullptr );
    364                                         delete castExpr;
    365                                         return ret;
     129                                UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) );
     130                                deref->set_result( appType->clone() );
     131                                appExpr->set_result( new PointerType( Type::Qualifiers(), appType ) );
     132                                deref->get_args().push_back( expr );
     133                                return deref;
     134                        } else {
     135                                return appExpr;
     136                        } // if
     137                }
     138
     139                Statement * Pass1::mutate(ReturnStmt *retStmt) {
     140                        if ( retval && retStmt->get_expr() ) {
     141                                if ( retStmt->get_expr()->get_result()->get_lvalue() ) {
     142                                        // ***** Code Removal ***** because casts may be stripped already
     143
     144                                        // strip casts because not allowed to take address of cast
     145                                        // while ( CastExpr *castExpr = dynamic_cast< CastExpr* >( retStmt->get_expr() ) ) {
     146                                        //      retStmt->set_expr( castExpr->get_arg() );
     147                                        //      retStmt->get_expr()->set_env( castExpr->get_env() );
     148                                        //      castExpr->set_env( 0 );
     149                                        //      castExpr->set_arg( 0 );
     150                                        //      delete castExpr;
     151                                        // } // while
     152                                        retStmt->set_expr( new AddressExpr( retStmt->get_expr()->acceptMutator( *this ) ) );
    366153                                } else {
    367                                         // rvalue to reference conversion -- introduce temporary
    368                                 }
    369                                 assertf( false, "Only conversions to reference from lvalue are currently supported: %s", toString( castExpr ).c_str() );
    370                         } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( castExpr->get_arg()->get_result() ) ) {
    371                                 (void)refType;
    372                                 // conversion from reference to rvalue
    373                                 PRINT(
    374                                         std::cerr << "convert reference to rvalue -- *" << std::endl;
    375                                         std::cerr << "was = " << castExpr << std::endl;
    376                                 )
    377                                 Expression * ret = castExpr->get_arg();
    378                                 TypeSubstitution * env = castExpr->get_env();
    379                                 castExpr->set_env( nullptr );
    380                                 if ( ! isIntrinsicReference( ret ) ) {
    381                                         // dereference if not already dereferenced
    382                                         ret = mkDeref( ret );
    383                                 }
    384                                 if ( ResolvExpr::typesCompatibleIgnoreQualifiers( castExpr->get_result(), castExpr->get_arg()->get_result()->stripReferences(), SymTab::Indexer() ) ) {
    385                                         // can remove cast if types are compatible, changing expression type to value type
    386                                         ret->set_result( castExpr->get_result()->clone() );
    387                                         castExpr->set_arg( nullptr );
    388                                         delete castExpr;
    389                                 } else {
    390                                         // must keep cast if types are different
    391                                         castExpr->set_arg( ret );
    392                                         ret = castExpr;
    393                                 }
    394                                 ret->set_env( env );
    395                                 PRINT( std::cerr << "now: " << ret << std::endl; )
    396                                 return ret;
    397                         }
    398                         return castExpr;
    399                 }
    400 
    401                 Type * ReferenceTypeElimination::postmutate( ReferenceType * refType ) {
    402                         Type * base = refType->get_base();
    403                         Type::Qualifiers qualifiers = refType->get_qualifiers();
    404                         refType->set_base( nullptr );
    405                         delete refType;
    406                         return new PointerType( qualifiers, base );
     154                                        throw SemanticError( "Attempt to return non-lvalue from an lvalue-qualified function" );
     155                                } // if
     156                        } // if
     157                        return retStmt;
     158                }
     159
     160                void Pass2::visit( FunctionType *funType ) {
     161                        std::string typeName;
     162                        if ( isLvalueRet( funType ) ) {
     163                                DeclarationWithType *retParm = funType->get_returnVals().front();
     164
     165                                // make a new parameter that is a pointer to the type of the old return value
     166                                retParm->set_type( new PointerType( Type::Qualifiers(), retParm->get_type() ) );
     167                        } // if
     168
     169                        Visitor::visit( funType );
    407170                }
    408171
     
    412175                                Expression * arg1 = commaExpr->get_arg1()->clone();
    413176                                Expression * arg2 = commaExpr->get_arg2()->clone();
    414                                 Expression * ret = new CommaExpr( arg1, mkExpr( arg2 )->acceptMutator( *visitor ) );
     177                                Expression * ret = new CommaExpr( arg1, mkExpr( arg2 ) );
    415178                                ret->set_env( expr->get_env() );
    416179                                expr->set_env( nullptr );
    417180                                delete expr;
    418                                 return ret;
     181                                return ret->acceptMutator( *this );
    419182                        } else if ( ConditionalExpr * condExpr = dynamic_cast< ConditionalExpr * >( arg ) ) {
    420183                                Expression * arg1 = condExpr->get_arg1()->clone();
    421184                                Expression * arg2 = condExpr->get_arg2()->clone();
    422185                                Expression * arg3 = condExpr->get_arg3()->clone();
    423                                 ConditionalExpr * ret = new ConditionalExpr( arg1, mkExpr( arg2 )->acceptMutator( *visitor ), mkExpr( arg3 )->acceptMutator( *visitor ) );
     186                                ConditionalExpr * ret = new ConditionalExpr( arg1, mkExpr( arg2 ), mkExpr( arg3 ) );
    424187                                ret->set_env( expr->get_env() );
    425188                                expr->set_env( nullptr );
     
    434197                                unify( ret->get_arg2()->get_result(), ret->get_arg3()->get_result(), newEnv, needAssertions, haveAssertions, openVars, SymTab::Indexer(), commonType );
    435198                                ret->set_result( commonType ? commonType : ret->get_arg2()->get_result()->clone() );
    436                                 return ret;
     199                                return ret->acceptMutator( *this );
    437200                        }
    438201                        return expr;
    439202                }
    440203
    441                 Expression * GeneralizedLvalue::postmutate( MemberExpr * memExpr ) {
     204                Expression * GeneralizedLvalue::mutate( MemberExpr * memExpr ) {
     205                        Parent::mutate( memExpr );
    442206                        return applyTransformation( memExpr, memExpr->get_aggregate(), [=]( Expression * aggr ) { return new MemberExpr( memExpr->get_member(), aggr ); } );
    443207                }
    444208
    445                 Expression * GeneralizedLvalue::postmutate( AddressExpr * addrExpr ) {
     209                Expression * GeneralizedLvalue::mutate( AddressExpr * addrExpr ) {
     210                        addrExpr = safe_dynamic_cast< AddressExpr * >( Parent::mutate( addrExpr ) );
    446211                        return applyTransformation( addrExpr, addrExpr->get_arg(), []( Expression * arg ) { return new AddressExpr( arg ); } );
    447                 }
    448 
    449                 Expression * CollapseAddrDeref::postmutate( AddressExpr * addrExpr ) {
    450                         Expression * arg = addrExpr->get_arg();
    451                         if ( isIntrinsicReference( arg ) ) {
    452                                 std::string fname = InitTweak::getFunctionName( arg );
    453                                 if ( fname == "*?" ) {
    454                                         Expression *& arg0 = InitTweak::getCallArg( arg, 0 );
    455                                         Expression * ret = arg0;
    456                                         ret->set_env( addrExpr->get_env() );
    457                                         arg0 = nullptr;
    458                                         addrExpr->set_env( nullptr );
    459                                         delete addrExpr;
    460                                         return ret;
    461                                 }
    462                         }
    463                         return addrExpr;
    464                 }
    465 
    466                 Expression * CollapseAddrDeref::postmutate( ApplicationExpr * appExpr ) {
    467                         if ( isIntrinsicReference( appExpr ) ) {
    468                                 std::string fname = InitTweak::getFunctionName( appExpr );
    469                                 if ( fname == "*?" ) {
    470                                         Expression * arg = InitTweak::getCallArg( appExpr, 0 );
    471                                         // xxx - this isn't right, because it can remove casts that should be there...
    472                                         // while ( CastExpr * castExpr = dynamic_cast< CastExpr * >( arg ) ) {
    473                                         //      arg = castExpr->get_arg();
    474                                         // }
    475                                         if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( arg ) ) {
    476                                                 Expression * ret = addrExpr->get_arg();
    477                                                 ret->set_env( appExpr->get_env() );
    478                                                 addrExpr->set_arg( nullptr );
    479                                                 appExpr->set_env( nullptr );
    480                                                 delete appExpr;
    481                                                 return ret;
    482                                         }
    483                                 }
    484                         }
    485                         return appExpr;
    486212                }
    487213        } // namespace
Note: See TracChangeset for help on using the changeset viewer.