Changes in / [42655e8:a715b5c]


Ignore:
Files:
14 edited

Legend:

Unmodified
Added
Removed
  • libcfa/prelude/builtins.c

    r42655e8 ra715b5c  
    111111static inline unsigned int ?\=?( unsigned int & x, unsigned long int y ) { x = x \ y; return x; }
    112112
     113// type that wraps a pointer and a destructor-like function - used in generating implicit destructor calls for struct members in user-defined functions
     114forall(dtype T)
     115struct __Destructor {
     116  T * object;
     117  void (*dtor)(T *);
     118};
     119
     120// defined destructor in the case that non-generated code wants to use __Destructor
     121forall(dtype T)
     122static inline void ^?{}(__Destructor(T) & x) {
     123        if (x.object && x.dtor) {
     124          x.dtor(x.object);
     125        }
     126}
     127
     128// easy interface into __Destructor's destructor for easy codegen purposes
     129extern "C" {
     130  forall(dtype T)
     131  static inline void __destroy_Destructor(__Destructor(T) * dtor) {
     132    ^(*dtor){};
     133  }
     134}
     135
    113136// Local Variables: //
    114137// mode: c //
  • src/ControlStruct/ExceptTranslate.cc

    r42655e8 ra715b5c  
    319319                        }
    320320
    321                         block->push_back( handler->get_body() );
    322                         handler->set_body( nullptr );
     321                        block->push_back( handler->body );
     322                        handler->body = nullptr;
    323323
    324324                        std::list<Statement *> caseBody
  • src/InitTweak/FixInit.cc

    r42655e8 ra715b5c  
    5454#include "SynTree/Type.h"              // for Type, Type::StorageClasses
    5555#include "SynTree/TypeSubstitution.h"  // for TypeSubstitution, operator<<
     56#include "SynTree/DeclReplacer.h"      // for DeclReplacer
    5657#include "SynTree/Visitor.h"           // for acceptAll, maybeAccept
    5758
     
    162163                        using Parent::previsit;
    163164
    164                         void previsit( ObjectDecl * objDecl );
    165165                        void previsit( FunctionDecl * funcDecl );
    166166
    167                         void previsit( CompoundStmt * compoundStmt );
    168                         void postvisit( CompoundStmt * compoundStmt );
    169                         void previsit( ReturnStmt * returnStmt );
    170167                        void previsit( BranchStmt * stmt );
    171168                private:
     
    207204                        static void generate( std::list< Declaration * > & translationUnit );
    208205
     206                        void premutate( StructDecl * structDecl );
     207
    209208                        void premutate( FunctionDecl * funcDecl );
    210209                        DeclarationWithType * postmutate( FunctionDecl * funcDecl );
     
    228227                        bool isCtor = false; // true if current function is a constructor
    229228                        StructDecl * structDecl = nullptr;
     229
     230                        // special built-in functions necessary for this to work
     231                        StructDecl * dtorStruct = nullptr;
     232                        FunctionDecl * dtorStructDestroy = nullptr;
    230233                };
    231234
     
    732735                }
    733736
     737                DeclarationWithType * getDtorFunc( ObjectDecl * objDecl, Statement * input, std::list< Statement * > & stmtsToAdd ) {
     738                        // unwrap implicit statement wrapper
     739                        Statement * dtor = input;
     740                        if ( ImplicitCtorDtorStmt * implicit = dynamic_cast< ImplicitCtorDtorStmt * >( input ) ) {
     741                                // dtor = implicit->callStmt;
     742                                // implicit->callStmt = nullptr;
     743                        }
     744                        assert( dtor );
     745                        std::list< Expression * > matches;
     746                        collectCtorDtorCalls( dtor, matches );
     747
     748                        if ( dynamic_cast< ExprStmt * >( dtor ) ) {
     749                                // only one destructor call in the expression
     750                                if ( matches.size() == 1 ) {
     751                                        DeclarationWithType * func = getFunction( matches.front() );
     752                                        assertf( func, "getFunction failed to find function in %s", toString( matches.front() ).c_str() );
     753
     754                                        // cleanup argument must be a function, not an object (including function pointer)
     755                                        if ( FunctionDecl * dtorFunc = dynamic_cast< FunctionDecl * > ( func ) ) {
     756                                                if ( dtorFunc->type->forall.empty() ) {
     757                                                        // simple case where the destructor is a monomorphic function call - can simply
     758                                                        // use that function as the cleanup function.
     759                                                        delete dtor;
     760                                                        return func;
     761                                                }
     762                                        }
     763                                }
     764                        }
     765
     766                        // otherwise the cleanup is more complicated - need to build a single argument cleanup function that
     767                        // wraps the more complicated code.
     768                        static UniqueName dtorNamer( "__cleanup_dtor" );
     769                        FunctionDecl * dtorFunc = FunctionDecl::newFunction( dtorNamer.newName(), SymTab::genDefaultType( objDecl->type->stripReferences(), false ), new CompoundStmt() );
     770                        stmtsToAdd.push_back( new DeclStmt( dtorFunc ) );
     771
     772                        // the original code contains uses of objDecl - replace them with the newly generated 'this' parameter.
     773                        ObjectDecl * thisParam = getParamThis( dtorFunc->type );
     774                        Expression * replacement = new VariableExpr( thisParam );
     775
     776                        Type * base = replacement->result->stripReferences();
     777                        if ( dynamic_cast< ArrayType * >( base ) || dynamic_cast< TupleType * > ( base ) ) {
     778                                // need to cast away reference for array types, since the destructor is generated without the reference type,
     779                                // and for tuple types since tuple indexing does not work directly on a reference
     780                                replacement = new CastExpr( replacement, base->clone() );
     781                        }
     782                        DeclReplacer::replace( dtor, { std::make_pair( objDecl, replacement ) } );
     783                        dtorFunc->statements->push_back( strict_dynamic_cast<Statement *>( dtor ) );
     784
     785                        return dtorFunc;
     786                }
     787
    734788                DeclarationWithType * FixInit::postmutate( ObjectDecl *objDecl ) {
    735789                        // since this removes the init field from objDecl, it must occur after children are mutated (i.e. postmutate)
     
    844898                                                        ctorInit->ctor = nullptr;
    845899                                                }
     900
     901                                                Statement * dtor = ctorInit->dtor;
     902                                                if ( dtor ) {
     903                                                        ImplicitCtorDtorStmt * implicit = strict_dynamic_cast< ImplicitCtorDtorStmt * >( dtor );
     904                                                        Statement * dtorStmt = implicit->callStmt;
     905
     906                                                        // don't need to call intrinsic dtor, because it does nothing, but
     907                                                        // non-intrinsic dtors must be called
     908                                                        if ( ! isIntrinsicSingleArgCallStmt( dtorStmt ) ) {
     909                                                                // set dtor location to the object's location for error messages
     910                                                                DeclarationWithType * dtorFunc = getDtorFunc( objDecl, dtorStmt, stmtsToAddBefore );
     911                                                                objDecl->attributes.push_back( new Attribute( "cleanup", { new VariableExpr( dtorFunc ) } ) );
     912                                                                ctorInit->dtor = nullptr;
     913                                                        } // if
     914                                                }
    846915                                        } // if
    847916                                } else if ( Initializer * init = ctorInit->init ) {
     
    886955
    887956
    888                 template<typename Iterator, typename OutputIterator>
    889                 void insertDtors( Iterator begin, Iterator end, OutputIterator out ) {
    890                         for ( Iterator it = begin ; it != end ; ++it ) {
    891                                 // extract destructor statement from the object decl and insert it into the output. Note that this is
    892                                 // only called on lists of non-static objects with implicit non-intrinsic dtors, so if the user manually
    893                                 // calls an intrinsic dtor then the call must (and will) still be generated since the argument may
    894                                 // contain side effects.
    895                                 ObjectDecl * objDecl = *it;
    896                                 ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() );
    897                                 assert( ctorInit && ctorInit->get_dtor() );
    898                                 *out++ = ctorInit->get_dtor()->clone();
    899                         } // for
    900                 }
    901 
    902                 void InsertDtors::previsit( ObjectDecl * objDecl ) {
    903                         // remember non-static destructed objects so that their destructors can be inserted later
    904                         if ( ! objDecl->get_storageClasses().is_static ) {
    905                                 if ( ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() ) ) {
    906                                         // a decision should have been made by the resolver, so ctor and init are not both non-NULL
    907                                         assert( ! ctorInit->get_ctor() || ! ctorInit->get_init() );
    908                                         Statement * dtor = ctorInit->get_dtor();
    909                                         // don't need to call intrinsic dtor, because it does nothing, but
    910                                         // non-intrinsic dtors must be called
    911                                         if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) {
    912                                                 // set dtor location to the object's location for error messages
    913                                                 ctorInit->dtor->location = objDecl->location;
    914                                                 reverseDeclOrder.front().push_front( objDecl );
    915                                         } // if
    916                                 } // if
    917                         } // if
    918                 }
    919 
    920957                void InsertDtors::previsit( FunctionDecl * funcDecl ) {
    921958                        // each function needs to have its own set of labels
     
    930967                }
    931968
    932                 void InsertDtors::previsit( CompoundStmt * compoundStmt ) {
    933                         // visit statements - this will also populate reverseDeclOrder list.  don't want to dump all destructors
    934                         // when block is left, just the destructors associated with variables defined in this block, so push a new
    935                         // list to the top of the stack so that we can differentiate scopes
    936                         reverseDeclOrder.push_front( OrderedDecls() );
    937                         Parent::previsit( compoundStmt );
    938                 }
    939 
    940                 void InsertDtors::postvisit( CompoundStmt * compoundStmt ) {
    941                         // add destructors for the current scope that we're exiting, unless the last statement is a return, which
    942                         // causes unreachable code warnings
    943                         std::list< Statement * > & statements = compoundStmt->get_kids();
    944                         if ( ! statements.empty() && ! dynamic_cast< ReturnStmt * >( statements.back() ) ) {
    945                                 insertDtors( reverseDeclOrder.front().begin(), reverseDeclOrder.front().end(), back_inserter( statements ) );
    946                         }
    947                         reverseDeclOrder.pop_front();
    948                 }
    949 
    950                 void InsertDtors::previsit( ReturnStmt * ) {
    951                         // return exits all scopes, so dump destructors for all scopes
    952                         for ( OrderedDecls & od : reverseDeclOrder ) {
    953                                 insertDtors( od.begin(), od.end(), back_inserter( stmtsToAddBefore ) );
    954                         } // for
    955                 }
    956 
    957969                // Handle break/continue/goto in the same manner as C++.  Basic idea: any objects that are in scope at the
    958970                // BranchStmt but not at the labelled (target) statement must be destructed.  If there are any objects in scope
     
    982994                        if ( ! diff.empty() ) {
    983995                                SemanticError( stmt, std::string("jump to label '") + stmt->get_target().get_name() + "' crosses initialization of " + (*diff.begin())->get_name() + " " );
    984                         } // if
    985                         // S_G-S_L results in set of objects that must be destructed
    986                         diff.clear();
    987                         std::set_difference( curVars.begin(), curVars.end(), lvars.begin(), lvars.end(), std::inserter( diff, diff.end() ) );
    988                         DTOR_PRINT(
    989                                 std::cerr << "S_G-S_L = " << printSet( diff ) << std::endl;
    990                         )
    991                         if ( ! diff.empty() ) {
    992                                 // create an auxilliary set for fast lookup -- can't make diff a set, because diff ordering should be consistent for error messages.
    993                                 std::unordered_set<ObjectDecl *> needsDestructor( diff.begin(), diff.end() );
    994 
    995                                 // go through decl ordered list of objectdecl. for each element that occurs in diff, output destructor
    996                                 OrderedDecls ordered;
    997                                 for ( OrderedDecls & rdo : reverseDeclOrder ) {
    998                                         // add elements from reverseDeclOrder into ordered if they occur in diff - it is key that this happens in reverse declaration order.
    999                                         copy_if( rdo.begin(), rdo.end(), back_inserter( ordered ), [&]( ObjectDecl * objDecl ) { return needsDestructor.count( objDecl ); } );
    1000                                 } // for
    1001                                 insertDtors( ordered.begin(), ordered.end(), back_inserter( stmtsToAddBefore ) );
    1002996                        } // if
    1003997                }
     
    10251019                }
    10261020
     1021                void GenStructMemberCalls::premutate( StructDecl * structDecl ) {
     1022                        if ( ! dtorStruct && structDecl->name == "__Destructor" ) {
     1023                                dtorStruct = structDecl;
     1024                        }
     1025                }
     1026
    10271027                void GenStructMemberCalls::premutate( FunctionDecl * funcDecl ) {
    10281028                        GuardValue( function );
     
    10371037                        unhandled.clear();
    10381038                        usedUninit.clear();
     1039
     1040                        if ( ! dtorStructDestroy && funcDecl->name == "__destroy_Destructor" ) {
     1041                                dtorStructDestroy = funcDecl;
     1042                                return;
     1043                        }
    10391044
    10401045                        function = funcDecl;
     
    10481053                                if ( structType ) {
    10491054                                        structDecl = structType->get_baseStruct();
     1055                                        if ( structDecl == dtorStruct ) return;
    10501056                                        for ( Declaration * member : structDecl->get_members() ) {
    10511057                                                if ( ObjectDecl * field = dynamic_cast< ObjectDecl * >( member ) ) {
     
    11161122                                                        callStmt->acceptMutator( *visitor );
    11171123                                                        if ( isCtor ) {
    1118                                                                 function->get_statements()->push_front( callStmt );
    1119                                                         } else {
     1124                                                                function->statements->push_front( callStmt );
     1125                                                        } else { // TODO: don't generate destructor function/object for intrinsic calls
    11201126                                                                // destructor statements should be added at the end
    1121                                                                 function->get_statements()->push_back( callStmt );
     1127                                                                // function->get_statements()->push_back( callStmt );
     1128
     1129                                                                // __Destructor _dtor0 = { (void *)&b.a1, (void (*)(void *)_destroy_A };
     1130                                                                std::list< Statement * > stmtsToAdd;
     1131
     1132                                                                static UniqueName memberDtorNamer = { "__memberDtor" };
     1133                                                                assertf( dtorStruct, "builtin __Destructor not found." );
     1134                                                                assertf( dtorStructDestroy, "builtin __destroy_Destructor not found." );
     1135
     1136                                                                Expression * thisExpr = new CastExpr( new AddressExpr( new VariableExpr( thisParam ) ), new PointerType( Type::Qualifiers(), new VoidType( Type::Qualifiers() ) ) );
     1137                                                                Expression * dtorExpr = new VariableExpr( getDtorFunc( thisParam, callStmt, stmtsToAdd ) );
     1138
     1139                                                                // cast destructor pointer to void (*)(void *), to silence GCC incompatible pointer warnings
     1140                                                                FunctionType * dtorFtype = new FunctionType( Type::Qualifiers(), false );
     1141                                                                dtorFtype->parameters.push_back( ObjectDecl::newObject( "", new PointerType( Type::Qualifiers(), new VoidType( Type::Qualifiers() ) ), nullptr ) );
     1142                                                                Type * dtorType = new PointerType( Type::Qualifiers(), dtorFtype );
     1143
     1144                                                                ObjectDecl * destructor = ObjectDecl::newObject( memberDtorNamer.newName(), new StructInstType( Type::Qualifiers(), dtorStruct ), new ListInit( { new SingleInit( thisExpr ), new SingleInit( new CastExpr( dtorExpr, dtorType ) ) } ) );
     1145                                                                function->statements->push_front( new DeclStmt( destructor ) );
     1146                                                                destructor->attributes.push_back( new Attribute( "cleanup", { new VariableExpr( dtorStructDestroy ) } ) );
     1147
     1148                                                                function->statements->kids.splice( function->statements->kids.begin(), stmtsToAdd );
    11221149                                                        }
    11231150                                                } catch ( SemanticErrorException & error ) {
  • src/InitTweak/InitTweak.cc

    r42655e8 ra715b5c  
    339339                std::list< Expression * > matches;
    340340                collectCtorDtorCalls( stmt, matches );
    341                 assert( matches.size() <= 1 );
     341                assertf( matches.size() <= 1, "%zd constructor/destructors found in %s", matches.size(), toString( stmt ).c_str() );
    342342                return matches.size() == 1 ? matches.front() : nullptr;
    343343        }
  • src/Makefile.am

    r42655e8 ra715b5c  
    9494  CodeGen/CodeGenerator.cc \
    9595  CodeGen/FixMain.cc \
     96  CodeGen/Generate.cc \
    9697  CodeGen/GenType.cc \
    9798  CodeGen/OperatorTable.cc \
  • src/Makefile.in

    r42655e8 ra715b5c  
    182182        SynTree/DeclReplacer.$(OBJEXT) CompilationState.$(OBJEXT) \
    183183        CodeGen/CodeGenerator.$(OBJEXT) CodeGen/FixMain.$(OBJEXT) \
    184         CodeGen/GenType.$(OBJEXT) CodeGen/OperatorTable.$(OBJEXT) \
    185         Common/Assert.$(OBJEXT) Common/Eval.$(OBJEXT) \
    186         Common/SemanticError.$(OBJEXT) Common/UniqueName.$(OBJEXT) \
    187         Concurrency/Keywords.$(OBJEXT) \
     184        CodeGen/Generate.$(OBJEXT) CodeGen/GenType.$(OBJEXT) \
     185        CodeGen/OperatorTable.$(OBJEXT) Common/Assert.$(OBJEXT) \
     186        Common/Eval.$(OBJEXT) Common/SemanticError.$(OBJEXT) \
     187        Common/UniqueName.$(OBJEXT) Concurrency/Keywords.$(OBJEXT) \
    188188        ControlStruct/ForExprMutator.$(OBJEXT) \
    189189        ControlStruct/LabelFixer.$(OBJEXT) \
     
    621621  CodeGen/CodeGenerator.cc \
    622622  CodeGen/FixMain.cc \
     623  CodeGen/Generate.cc \
    623624  CodeGen/GenType.cc \
    624625  CodeGen/OperatorTable.cc \
     
    797798        CodeGen/$(DEPDIR)/$(am__dirstamp)
    798799CodeGen/FixMain.$(OBJEXT): CodeGen/$(am__dirstamp) \
     800        CodeGen/$(DEPDIR)/$(am__dirstamp)
     801CodeGen/Generate.$(OBJEXT): CodeGen/$(am__dirstamp) \
    799802        CodeGen/$(DEPDIR)/$(am__dirstamp)
    800803CodeGen/GenType.$(OBJEXT): CodeGen/$(am__dirstamp) \
     
    987990clean-cfa_cpplibPROGRAMS:
    988991        -test -z "$(cfa_cpplib_PROGRAMS)" || rm -f $(cfa_cpplib_PROGRAMS)
    989 CodeGen/Generate.$(OBJEXT): CodeGen/$(am__dirstamp) \
    990         CodeGen/$(DEPDIR)/$(am__dirstamp)
    991992CodeGen/FixNames.$(OBJEXT): CodeGen/$(am__dirstamp) \
    992993        CodeGen/$(DEPDIR)/$(am__dirstamp)
  • src/SymTab/Autogen.cc

    r42655e8 ra715b5c  
    4545        /// Data used to generate functions generically. Specifically, the name of the generated function and a function which generates the routine protoype
    4646        struct FuncData {
    47                 typedef FunctionType * (*TypeGen)( Type * );
     47                typedef FunctionType * (*TypeGen)( Type *, bool );
    4848                FuncData( const std::string & fname, const TypeGen & genType ) : fname( fname ), genType( genType ) {}
    4949                std::string fname;
     
    231231
    232232        /// given type T, generate type of default ctor/dtor, i.e. function type void (*) (T *)
    233         FunctionType * genDefaultType( Type * paramType ) {
    234                 const auto & typeParams = getGenericParams( paramType );
     233        FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic ) {
    235234                FunctionType *ftype = new FunctionType( Type::Qualifiers(), false );
    236                 cloneAll( typeParams, ftype->forall );
     235                if ( maybePolymorphic ) {
     236                        // only copy in
     237                        const auto & typeParams = getGenericParams( paramType );
     238                        cloneAll( typeParams, ftype->forall );
     239                }
    237240                ObjectDecl *dstParam = new ObjectDecl( "_dst", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), paramType->clone() ), nullptr );
    238241                ftype->parameters.push_back( dstParam );
     
    241244
    242245        /// given type T, generate type of copy ctor, i.e. function type void (*) (T *, T)
    243         FunctionType * genCopyType( Type * paramType ) {
    244                 FunctionType *ftype = genDefaultType( paramType );
     246        FunctionType * genCopyType( Type * paramType, bool maybePolymorphic ) {
     247                FunctionType *ftype = genDefaultType( paramType, maybePolymorphic );
    245248                ObjectDecl *srcParam = new ObjectDecl( "_src", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, paramType->clone(), nullptr );
    246249                ftype->parameters.push_back( srcParam );
     
    249252
    250253        /// given type T, generate type of assignment, i.e. function type T (*) (T *, T)
    251         FunctionType * genAssignType( Type * paramType ) {
    252                 FunctionType *ftype = genCopyType( paramType );
     254        FunctionType * genAssignType( Type * paramType, bool maybePolymorphic ) {
     255                FunctionType *ftype = genCopyType( paramType, maybePolymorphic );
    253256                ObjectDecl *returnVal = new ObjectDecl( "_ret", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, paramType->clone(), nullptr );
    254257                ftype->returnVals.push_back( returnVal );
     
    308311                for ( const FuncData & d : data ) {
    309312                        // generate a function (?{}, ?=?, ^?{}) based on the current FuncData.
    310                         FunctionType * ftype = d.genType( type );
     313                        FunctionType * ftype = d.genType( type, true );
    311314
    312315                        // destructor for concurrent type must be mutex
  • src/SymTab/Autogen.h

    r42655e8 ra715b5c  
    4545        extern FunctionDecl * dereferenceOperator;
    4646
    47         // generate the type of an assignment function for paramType
    48         FunctionType * genAssignType( Type * paramType );
    49 
    50         // generate the type of a default constructor or destructor for paramType
    51         FunctionType * genDefaultType( Type * paramType );
    52 
    53         // generate the type of a copy constructor for paramType
    54         FunctionType * genCopyType( Type * paramType );
     47        /// generate the type of an assignment function for paramType.
     48        /// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic
     49        FunctionType * genAssignType( Type * paramType, bool maybePolymorphic = true );
     50
     51        /// generate the type of a default constructor or destructor for paramType.
     52        /// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic
     53        FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic = true );
     54
     55        /// generate the type of a copy constructor for paramType.
     56        /// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic
     57        FunctionType * genCopyType( Type * paramType, bool maybePolymorphic = true );
    5558
    5659        /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls.
  • src/SymTab/Validate.cc

    r42655e8 ra715b5c  
    13331333        void FindSpecialDeclarations::previsit( FunctionDecl * funcDecl ) {
    13341334                if ( ! dereferenceOperator ) {
    1335                         if ( funcDecl->get_name() == "*?" && funcDecl->get_linkage() == LinkageSpec::Intrinsic ) {
    1336                                 FunctionType * ftype = funcDecl->get_functionType();
    1337                                 if ( ftype->get_parameters().size() == 1 && ftype->get_parameters().front()->get_type()->get_qualifiers() == Type::Qualifiers() ) {
    1338                                         dereferenceOperator = funcDecl;
     1335                        // find and remember the intrinsic dereference operator for object pointers
     1336                        if ( funcDecl->name == "*?" && funcDecl->linkage == LinkageSpec::Intrinsic ) {
     1337                                FunctionType * ftype = funcDecl->type;
     1338                                if ( ftype->parameters.size() == 1 ) {
     1339                                        PointerType * ptrType = strict_dynamic_cast<PointerType *>( ftype->parameters.front()->get_type() );
     1340                                        if ( ptrType->base->get_qualifiers() == Type::Qualifiers() ) {
     1341                                                TypeInstType * inst = dynamic_cast<TypeInstType *>( ptrType->base );
     1342                                                if ( inst && ! inst->get_isFtype() ) {
     1343                                                        dereferenceOperator = funcDecl;
     1344                                                }
     1345                                        }
    13391346                                }
    13401347                        }
  • src/SynTree/DeclReplacer.cc

    r42655e8 ra715b5c  
    3838                        void previsit( TypeInstType * inst );
    3939                };
     40
     41                /// Mutator that replaces uses of declarations with arbitrary expressions, according to the supplied mapping
     42                struct ExprDeclReplacer {
     43                private:
     44                        const ExprMap & exprMap;
     45                        bool debug;
     46                public:
     47                        ExprDeclReplacer( const ExprMap & exprMap, bool debug = false );
     48
     49                        // replace variable with new node from expr map
     50                        Expression * postmutate( VariableExpr * varExpr );
     51                };
    4052        }
    4153
     
    5365                DeclMap declMap;
    5466                replace( node, declMap, typeMap, debug );
     67        }
     68
     69        void replace( BaseSyntaxNode *& node, const ExprMap & exprMap, bool debug ) {
     70                PassVisitor<ExprDeclReplacer> replacer( exprMap, debug );
     71                node = maybeMutate( node, replacer );
    5572        }
    5673
     
    7996                        }
    8097                }
     98
     99                ExprDeclReplacer::ExprDeclReplacer( const ExprMap & exprMap, bool debug ) : exprMap( exprMap ), debug( debug ) {}
     100
     101                Expression * ExprDeclReplacer::postmutate( VariableExpr * varExpr ) {
     102                        if ( exprMap.count( varExpr->var ) ) {
     103                                Expression * replacement = exprMap.at( varExpr->var )->clone();
     104                                if ( debug ) {
     105                                        std::cerr << "replacing variable reference: " << (void*)varExpr->var << " " << varExpr->var << " with " << (void*)replacement << " " << replacement << std::endl;
     106                                }
     107                                std::swap( varExpr->env, replacement->env );
     108                                delete varExpr;
     109                                return replacement;
     110                        }
     111                        return varExpr;
     112                }
    81113        }
    82114} // namespace VarExprReplacer
  • src/SynTree/DeclReplacer.h

    r42655e8 ra715b5c  
    2626        typedef std::map< DeclarationWithType *, DeclarationWithType * > DeclMap;
    2727        typedef std::map< TypeDecl *, TypeDecl * > TypeMap;
     28        typedef std::map< DeclarationWithType *, Expression * > ExprMap;
    2829
    2930        void replace( BaseSyntaxNode * node, const DeclMap & declMap, bool debug = false );
    3031        void replace( BaseSyntaxNode * node, const TypeMap & typeMap, bool debug = false );
    3132        void replace( BaseSyntaxNode * node, const DeclMap & declMap, const TypeMap & typeMap, bool debug = false );
     33
     34        void replace( BaseSyntaxNode *& node, const ExprMap & exprMap, bool debug = false);
     35        template<typename T>
     36                void replace( T *& node, const ExprMap & exprMap, bool debug = false ) {
     37                if ( ! node ) return;
     38                BaseSyntaxNode * arg = node;
     39                replace( arg, exprMap, debug );
     40                node = dynamic_cast<T *>( arg );
     41                assertf( node, "DeclReplacer fundamentally changed the type of its argument." );
     42        }
    3243}
    3344
  • tests/raii/.expect/memberCtors-ERR1.txt

    r42655e8 ra715b5c  
    1 raii/memberCtors.c:71:1 error: in void ?{}(B &b), field a2 used before being constructed
     1raii/memberCtors.c:92:1 error: in void ?{}(B &b), field a2 used before being constructed
  • tests/raii/.expect/memberCtors.txt

    r42655e8 ra715b5c  
    11Before declaration of b1
    2 constructing int
    3 constructing int
    4 constructing int
    5 constructing int
    6 constructing int
    7 constructing int
    8 begin construct B
     2constructing int id: 0
     3constructing int id: 1
     4constructing int id: 2
     5default construct A 0
     6constructing int id: 3
     7constructing int id: 4
     8constructing int id: 5
     9default construct A 1
     10begin construct B id: 0
    911assign b.a2
    10 constructing int
    11 constructing int
    12 begin construct A
    13 construct a.x
    14 constructing int: 1001
    15 assign a.y
    16 assigning int: 0 0
    17 end construct A
    18 copy constructing int: 0
    19 copy constructing int: 0
    20 begin copy construct A
    21 copy construct this.x
    22 copy constructing int: 1001
    23 assign this.y
    24 copy constructing int: 0
    25 destructing int: 0
    26 destructing int: 0
    27 end copy construct A
    28 begin ?=? A
    29 copy constructing int: 1001
    30 destructing int: 1001
    31 destructing int: 1001
    32 copy constructing int: 0
    33 destructing int: 0
    34 destructing int: 0
    35 copy constructing int: 0
    36 destructing int: 0
    37 destructing int: 0
     12constructing int id: 6
     13constructing int id: 7
     14begin construct A id: 2
     15construct a.x
     16constructing int: 1001 id: 8
     17assign a.y
     18assigning int: 0 0 id: 6
     19end construct A
     20copy constructing int: 0 id: 9
     21copy constructing int: 0 id: 10
     22begin copy construct A id: 3
     23copy construct this.x
     24copy constructing int: 1001 id: 11
     25assign this.y
     26copy constructing int: 0 id: 12
     27destructing int: 0 id: 12
     28destructing int: 0 id: 12
     29end copy construct A
     30begin ?=? A id: 0
     31copy constructing int: 1001 id: 13
     32destructing int: 1001 id: 13
     33destructing int: 1001 id: 13
     34copy constructing int: 0 id: 14
     35destructing int: 0 id: 14
     36destructing int: 0 id: 14
     37copy constructing int: 0 id: 15
     38destructing int: 0 id: 15
     39destructing int: 0 id: 15
    3840end ?=? A
    39 copy constructing int: 0
    40 copy constructing int: 0
    41 begin copy construct A
    42 copy construct this.x
    43 copy constructing int: 1001
    44 assign this.y
    45 copy constructing int: 0
    46 destructing int: 0
    47 destructing int: 0
    48 end copy construct A
    49 destructing int: 0
    50 destructing int: 0
    51 destructing int: 1001
    52 destructing int: 0
    53 destructing int: 0
    54 destructing int: 1001
     41copy constructing int: 0 id: 16
     42copy constructing int: 0 id: 17
     43begin copy construct A id: 4
     44copy construct this.x
     45copy constructing int: 1001 id: 18
     46assign this.y
     47copy constructing int: 0 id: 19
     48destructing int: 0 id: 19
     49destructing int: 0 id: 19
     50end copy construct A
     51destructing int: 0 id: 17
     52destructing int: 0 id: 19
     53destructing int: 1001 id: 18
     54destructing int: 0 id: 10
     55destructing int: 0 id: 12
     56destructing int: 1001 id: 11
    5557construct b.a1
    56 constructing int
    57 constructing int
    58 begin construct A
    59 construct a.x
    60 constructing int: 1000
    61 assign a.y
    62 assigning int: 0 0
     58constructing int id: 20
     59constructing int id: 21
     60begin construct A id: 5
     61construct a.x
     62constructing int: 1000 id: 22
     63assign a.y
     64assigning int: 0 0 id: 20
    6365end construct A
    6466end construct B
    65 destructing int: 0
    66 destructing int: 0
    67 destructing int: 1001
     67destructing int: 0 id: 7
     68destructing int: 0 id: 6
     69destructing int: 1001 id: 8
    6870Before declaration of b2
    69 copy constructing int: 0
    70 copy constructing int: 0
    71 begin copy construct A
    72 copy construct this.x
    73 copy constructing int: 1000
    74 assign this.y
    75 copy constructing int: 0
    76 destructing int: 0
    77 destructing int: 0
    78 end copy construct A
    79 copy constructing int: 0
    80 copy constructing int: 0
    81 begin copy construct A
    82 copy construct this.x
    83 copy constructing int: 1001
    84 assign this.y
    85 copy constructing int: 0
    86 destructing int: 0
    87 destructing int: 0
    88 end copy construct A
    89 copy constructing int: 0
    90 copy constructing int: 0
    91 begin copy construct A
    92 copy construct this.x
    93 copy constructing int: 0
    94 assign this.y
    95 copy constructing int: 0
    96 destructing int: 0
    97 destructing int: 0
     71copy constructing int: 0 id: 23
     72copy constructing int: 0 id: 24
     73begin copy construct A id: 6
     74copy construct this.x
     75copy constructing int: 1000 id: 25
     76assign this.y
     77copy constructing int: 0 id: 26
     78destructing int: 0 id: 26
     79destructing int: 0 id: 26
     80end copy construct A
     81copy constructing int: 0 id: 27
     82copy constructing int: 0 id: 28
     83begin copy construct A id: 7
     84copy construct this.x
     85copy constructing int: 1001 id: 29
     86assign this.y
     87copy constructing int: 0 id: 30
     88destructing int: 0 id: 30
     89destructing int: 0 id: 30
     90end copy construct A
     91copy constructing int: 0 id: 31
     92copy constructing int: 0 id: 32
     93begin copy construct A id: 8
     94copy construct this.x
     95copy constructing int: 0 id: 33
     96assign this.y
     97copy constructing int: 0 id: 34
     98destructing int: 0 id: 34
     99destructing int: 0 id: 34
    98100end copy construct A
    99101End of main
    100 constructing int
    101 constructing int
    102 begin construct A
    103 construct a.x
    104 constructing int: 999
    105 assign a.y
    106 assigning int: 0 0
    107 end construct A
    108 copy constructing int: 0
    109 copy constructing int: 0
    110 begin copy construct A
    111 copy construct this.x
    112 copy constructing int: 999
    113 assign this.y
    114 copy constructing int: 0
    115 destructing int: 0
    116 destructing int: 0
    117 end copy construct A
    118 begin ?=? A
    119 copy constructing int: 999
    120 destructing int: 999
    121 destructing int: 999
    122 copy constructing int: 0
    123 destructing int: 0
    124 destructing int: 0
    125 copy constructing int: 0
    126 destructing int: 0
    127 destructing int: 0
     102begin destruct B id: 1
     103constructing int id: 35
     104constructing int id: 36
     105begin construct A id: 9
     106construct a.x
     107constructing int: 999 id: 37
     108assign a.y
     109assigning int: 0 0 id: 35
     110end construct A
     111copy constructing int: 0 id: 38
     112copy constructing int: 0 id: 39
     113begin copy construct A id: 10
     114copy construct this.x
     115copy constructing int: 999 id: 40
     116assign this.y
     117copy constructing int: 0 id: 41
     118destructing int: 0 id: 41
     119destructing int: 0 id: 41
     120end copy construct A
     121begin ?=? A id: 7
     122copy constructing int: 999 id: 42
     123destructing int: 999 id: 42
     124destructing int: 999 id: 42
     125copy constructing int: 0 id: 43
     126destructing int: 0 id: 43
     127destructing int: 0 id: 43
     128copy constructing int: 0 id: 44
     129destructing int: 0 id: 44
     130destructing int: 0 id: 44
    128131end ?=? A
    129 copy constructing int: 0
    130 copy constructing int: 0
    131 begin copy construct A
    132 copy construct this.x
    133 copy constructing int: 999
    134 assign this.y
    135 copy constructing int: 0
    136 destructing int: 0
    137 destructing int: 0
    138 end copy construct A
    139 destructing int: 0
    140 destructing int: 0
    141 destructing int: 999
    142 destructing int: 0
    143 destructing int: 0
    144 destructing int: 999
    145 destructing int: 0
    146 destructing int: 0
    147 destructing int: 1000
    148 destructing int: 0
    149 destructing int: 0
    150 destructing int: 999
    151 destructing int: 0
    152 destructing int: 0
    153 destructing int: 0
    154 destructing int: 0
    155 destructing int: 0
    156 destructing int: 999
    157 constructing int
    158 constructing int
    159 begin construct A
    160 construct a.x
    161 constructing int: 999
    162 assign a.y
    163 assigning int: 0 0
    164 end construct A
    165 copy constructing int: 0
    166 copy constructing int: 0
    167 begin copy construct A
    168 copy construct this.x
    169 copy constructing int: 999
    170 assign this.y
    171 copy constructing int: 0
    172 destructing int: 0
    173 destructing int: 0
    174 end copy construct A
    175 begin ?=? A
    176 copy constructing int: 999
    177 destructing int: 999
    178 destructing int: 999
    179 copy constructing int: 0
    180 destructing int: 0
    181 destructing int: 0
    182 copy constructing int: 0
    183 destructing int: 0
    184 destructing int: 0
     132copy constructing int: 0 id: 45
     133copy constructing int: 0 id: 46
     134begin copy construct A id: 11
     135copy construct this.x
     136copy constructing int: 999 id: 47
     137assign this.y
     138copy constructing int: 0 id: 48
     139destructing int: 0 id: 48
     140destructing int: 0 id: 48
     141end copy construct A
     142destructing int: 0 id: 46
     143destructing int: 0 id: 48
     144destructing int: 999 id: 47
     145destructing int: 0 id: 39
     146destructing int: 0 id: 41
     147destructing int: 999 id: 40
     148destructing int: 0 id: 24
     149destructing int: 0 id: 26
     150destructing int: 1000 id: 25
     151end destruct B
     152destructing int: 0 id: 36
     153destructing int: 0 id: 35
     154destructing int: 999 id: 37
     155destructing int: 0 id: 32
     156destructing int: 0 id: 34
     157destructing int: 0 id: 33
     158destructing int: 0 id: 44
     159destructing int: 0 id: 43
     160destructing int: 999 id: 42
     161begin destruct B id: 2
     162constructing int id: 49
     163constructing int id: 50
     164begin construct A id: 12
     165construct a.x
     166constructing int: 999 id: 51
     167assign a.y
     168assigning int: 0 0 id: 49
     169end construct A
     170copy constructing int: 0 id: 52
     171copy constructing int: 0 id: 53
     172begin copy construct A id: 13
     173copy construct this.x
     174copy constructing int: 999 id: 54
     175assign this.y
     176copy constructing int: 0 id: 55
     177destructing int: 0 id: 55
     178destructing int: 0 id: 55
     179end copy construct A
     180begin ?=? A id: 0
     181copy constructing int: 999 id: 56
     182destructing int: 999 id: 56
     183destructing int: 999 id: 56
     184copy constructing int: 0 id: 57
     185destructing int: 0 id: 57
     186destructing int: 0 id: 57
     187copy constructing int: 0 id: 58
     188destructing int: 0 id: 58
     189destructing int: 0 id: 58
    185190end ?=? A
    186 copy constructing int: 0
    187 copy constructing int: 0
    188 begin copy construct A
    189 copy construct this.x
    190 copy constructing int: 999
    191 assign this.y
    192 copy constructing int: 0
    193 destructing int: 0
    194 destructing int: 0
    195 end copy construct A
    196 destructing int: 0
    197 destructing int: 0
    198 destructing int: 999
    199 destructing int: 0
    200 destructing int: 0
    201 destructing int: 999
    202 destructing int: 0
    203 destructing int: 0
    204 destructing int: 1000
    205 destructing int: 0
    206 destructing int: 0
    207 destructing int: 999
    208 destructing int: 0
    209 destructing int: 0
    210 destructing int: 0
    211 destructing int: 0
    212 destructing int: 0
    213 destructing int: 999
     191copy constructing int: 0 id: 59
     192copy constructing int: 0 id: 60
     193begin copy construct A id: 14
     194copy construct this.x
     195copy constructing int: 999 id: 61
     196assign this.y
     197copy constructing int: 0 id: 62
     198destructing int: 0 id: 62
     199destructing int: 0 id: 62
     200end copy construct A
     201destructing int: 0 id: 60
     202destructing int: 0 id: 62
     203destructing int: 999 id: 61
     204destructing int: 0 id: 53
     205destructing int: 0 id: 55
     206destructing int: 999 id: 54
     207destructing int: 0 id: 21
     208destructing int: 0 id: 20
     209destructing int: 1000 id: 22
     210end destruct B
     211destructing int: 0 id: 50
     212destructing int: 0 id: 49
     213destructing int: 999 id: 51
     214destructing int: 0 id: 5
     215destructing int: 0 id: 4
     216destructing int: 0 id: 3
     217destructing int: 0 id: 58
     218destructing int: 0 id: 57
     219destructing int: 999 id: 56
  • tests/raii/memberCtors.c

    r42655e8 ra715b5c  
    11struct WrappedInt {
    22  int x;
     3  int id;
    34};
     5int intID = 0;
    46
    57void ?{}(WrappedInt & this) {
    6   printf("constructing int\n");
     8  this.id = intID++;
     9  printf("constructing int id: %d\n", this.id);
    710  this.x = 0;
    811}
    912
    1013void ?{}(WrappedInt & this, WrappedInt other) {
    11   printf("copy constructing int: %d\n", other.x);
     14  this.id = intID++;
     15  printf("copy constructing int: %d id: %d\n", other.x, this.id);
    1216  this.x = other.x;
    1317}
    1418
    1519void ?{}(WrappedInt & this, int x) {
    16   printf("constructing int: %d\n", x);
     20  this.id = intID++;
     21  printf("constructing int: %d id: %d\n", x, this.id);
    1722  this.x = x;
    1823}
    1924
    2025void ^?{}(WrappedInt & this) {
    21   printf("destructing int: %d\n", this.x);
     26  printf("destructing int: %d id: %d\n", this.x, this.id);
    2227}
    2328
    24 void ?=?(WrappedInt & this, int x) {
    25   printf("assigning int: %d %d\n", this.x, x);
     29/* WrappedInt */ void ?=?(WrappedInt & this, int x) {
     30  printf("assigning int: %d %d id: %d\n", this.x, x, this.id);
    2631  this.x = x;
     32  // return this;
    2733}
     34
     35// WrappedInt ?=?(WrappedInt & this, WrappedInt other) {
     36//   printf("assigning int: %d %d\n", this.x, other.x);
     37//   this.x = other.x;
     38//   return this;
     39// }
    2840
    2941struct A {
    3042  WrappedInt x, y, z;
     43  int id;
    3144};
     45int AID = 0;
    3246
    3347void ?{}(A & a) {
    3448  // currently must define default ctor, since there's no "= default" syntax
     49  a.id = AID++;
     50  printf("default construct A %d\n", a.id);
    3551}
    3652
    3753void ?{}(A & a, int x) {
    38   printf("begin construct A\n");
     54  a.id = AID++;
     55  printf("begin construct A id: %d\n", a.id);
    3956  printf("construct a.x\n");
    4057  (a.x){ x+999 };
     
    4562
    4663void ?{}(A & this, A other) {
    47   printf("begin copy construct A\n");
     64  this.id = AID++;
     65  printf("begin copy construct A id: %d\n", this.id);
    4866  printf("copy construct this.x\n");
    4967  (this.x){ other.x };
     
    5472
    5573A ?=?(A & this, A other) {
    56   printf("begin ?=? A\n");
     74  printf("begin ?=? A id: %d\n", this.id);
    5775  this.x = other.x;
    5876  this.y = other.y;
     
    6482struct B {
    6583  A a1, a2, a3;
     84  int id;
    6685};
     86int BID = 0;
    6787
    6888void ?{}(B & b) {
    69   printf("begin construct B\n");
     89  b.id = BID++;
     90  printf("begin construct B id: %d\n", b.id);
    7091  printf("assign b.a2\n");
    7192  b.a2 = (A) { 2 };
     
    79100
    80101void ^?{}(B & b) {
     102  b.id = BID++;
     103  printf("begin destruct B id: %d\n", b.id);
    81104  b.a2 = (A) { 0 };
    82105  ^(b.a1){};
     106  printf("end destruct B\n");
    83107} // a2, a3 never destructed - will be automatically destructed
    84108
    85109int main() {
    86110  printf("Before declaration of b1\n");
    87   B b1;
     111  B b1;  // b1 = { { 1000, 0, 0 }, { 1001, 0, 0 }, { 0, 0, 0 } }
    88112  printf("Before declaration of b2\n");
    89113  B b2 = b1;
Note: See TracChangeset for help on using the changeset viewer.