Changeset 3403534 for src/InitTweak


Ignore:
Timestamp:
Sep 4, 2016, 10:34:35 PM (9 years ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, ctor, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
Children:
f04a8b81
Parents:
28307be (diff), b16898e (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg2:software/cfa/cfa-cc

Location:
src/InitTweak
Files:
13 deleted
4 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/FixInit.cc

    r28307be r3403534  
    3131#include "SynTree/Mutator.h"
    3232#include "SymTab/Indexer.h"
     33#include "SymTab/Autogen.h"
    3334#include "GenPoly/PolyMutator.h"
    3435#include "SynTree/AddStmtVisitor.h"
     
    176177                };
    177178
    178                 class WarnStructMembers : public Visitor {
     179                class GenStructMemberCalls : public SymTab::Indexer {
    179180                  public:
    180                         typedef Visitor Parent;
    181                         /// warn if a user-defined constructor or destructor is missing calls for
    182                         /// a struct member or if a member is used before constructed
    183                         static void warnings( std::list< Declaration * > & translationUnit );
     181                        typedef Indexer Parent;
     182                        /// generate default/copy ctor and dtor calls for user-defined struct ctor/dtors
     183                        /// for any member that is missing a corresponding ctor/dtor call.
     184                        /// error if a member is used before constructed
     185                        static void generate( std::list< Declaration * > & translationUnit );
    184186
    185187                        virtual void visit( FunctionDecl * funcDecl );
     
    188190                        virtual void visit( ApplicationExpr * appExpr );
    189191
     192                        SemanticError errors;
    190193                  private:
    191194                        void handleFirstParam( Expression * firstParam );
     195                        template< typename... Params >
     196                        void emit( const Params &... params );
    192197
    193198                        FunctionDecl * function = 0;
    194                         std::set< DeclarationWithType * > unhandled;
     199                        std::set< DeclarationWithType * > unhandled, usedUninit;
    195200                        ObjectDecl * thisParam = 0;
     201                        bool isCtor = false; // true if current function is a constructor
     202                        StructDecl * structDecl = 0;
     203                };
     204
     205                // very simple resolver-like mutator class - used to
     206                // resolve UntypedExprs that are found within newly
     207                // generated constructor/destructor calls
     208                class MutatingResolver : public Mutator {
     209                  public:
     210                        MutatingResolver( SymTab::Indexer & indexer ) : indexer( indexer ) {}
     211
     212                        virtual DeclarationWithType* mutate( ObjectDecl *objectDecl );
     213
     214                        virtual Expression* mutate( UntypedExpr *untypedExpr );
     215                        private:
     216                        SymTab::Indexer & indexer;
    196217                };
    197218        } // namespace
     
    209230                FixCopyCtors::fixCopyCtors( translationUnit );
    210231
    211                 WarnStructMembers::warnings( translationUnit );
     232                GenStructMemberCalls::generate( translationUnit );
    212233        }
    213234
     
    254275                }
    255276
    256                 void WarnStructMembers::warnings( std::list< Declaration * > & translationUnit ) {
    257                         if ( true ) { // fix this condition to skip this pass if warnings aren't enabled
    258                                 WarnStructMembers warner;
    259                                 acceptAll( translationUnit, warner );
     277                void GenStructMemberCalls::generate( std::list< Declaration * > & translationUnit ) {
     278                        GenStructMemberCalls warner;
     279                        acceptAll( translationUnit, warner );
     280
     281                        // visitor doesn't throw so that it can collect all errors
     282                        if ( ! warner.errors.isEmpty() ) {
     283                                throw warner.errors;
    260284                        }
    261285                }
     
    528552                                                        FunctionDecl * dtorCaller = new FunctionDecl( objDecl->get_mangleName() + dtorCallerNamer.newName(), DeclarationNode::Static, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ), false, false );
    529553                                                        dtorCaller->fixUniqueId();
    530                                                         dtorCaller->get_statements()->get_kids().push_back( dtorStmt );
     554                                                        dtorCaller->get_statements()->push_back( dtorStmt );
    531555
    532556                                                        // atexit(dtor_atexit);
     
    543567                                                        // at global scope and there could be multiple function-scoped
    544568                                                        // static variables with the same name in different functions.
     569                                                        // Note: it isn't sufficient to modify only the mangleName, because
     570                                                        // then subsequent Indexer passes can choke on seeing the object's name
     571                                                        // if another object has the same name and type. An unfortunate side-effect
     572                                                        // of renaming the object is that subsequent NameExprs may fail to resolve,
     573                                                        // but there shouldn't be any remaining past this point.
    545574                                                        static UniqueName staticNamer( "_static_var" );
    546                                                         objDecl->set_mangleName( objDecl->get_mangleName() + staticNamer.newName() );
     575                                                        objDecl->set_name( objDecl->get_name() + staticNamer.newName() );
     576                                                        objDecl->set_mangleName( SymTab::Mangler::mangle( objDecl ) );
    547577
    548578                                                        objDecl->set_init( NULL );
     
    709739                }
    710740
    711                 void WarnStructMembers::visit( FunctionDecl * funcDecl ) {
    712                         WarnStructMembers old = *this;
    713                         *this = WarnStructMembers();
     741                void GenStructMemberCalls::visit( FunctionDecl * funcDecl ) {
     742                        ValueGuard< FunctionDecl * > oldFunction( funcDecl );
     743                        ValueGuard< std::set< DeclarationWithType * > > oldUnhandled( unhandled );
     744                        ValueGuard< std::set< DeclarationWithType * > > oldUsedUninit( usedUninit );
     745                        ValueGuard< ObjectDecl * > oldThisParam( thisParam );
     746                        ValueGuard< bool > oldIsCtor( isCtor );
     747                        ValueGuard< StructDecl * > oldStructDecl( structDecl );
     748
     749                        // need to start with fresh sets
     750                        unhandled.clear();
     751                        usedUninit.clear();
    714752
    715753                        function = funcDecl;
    716                         if ( checkWarnings( funcDecl ) ) {
    717                                 FunctionType * type = funcDecl->get_functionType();
     754                        isCtor = isConstructor( function->get_name() );
     755                        if ( checkWarnings( function ) ) {
     756                                FunctionType * type = function->get_functionType();
    718757                                assert( ! type->get_parameters().empty() );
    719758                                thisParam = safe_dynamic_cast< ObjectDecl * >( type->get_parameters().front() );
     
    721760                                StructInstType * structType = dynamic_cast< StructInstType * >( ptrType->get_base() );
    722761                                if ( structType ) {
    723                                         StructDecl * structDecl = structType->get_baseStruct();
     762                                        structDecl = structType->get_baseStruct();
    724763                                        for ( Declaration * member : structDecl->get_members() ) {
    725764                                                if ( ObjectDecl * field = dynamic_cast< ObjectDecl * >( member ) ) {
     
    731770                                }
    732771                        }
    733                         Parent::visit( funcDecl );
    734 
    735                         for ( DeclarationWithType * member : unhandled ) {
    736                                 // emit a warning for each unhandled member
    737                                 warn( "in ", CodeGen::genType( function->get_functionType(), function->get_name(), false ), ", member ", member->get_name(), " may not have been ", isConstructor( funcDecl->get_name() ) ? "constructed" : "destructed" );
     772                        Parent::visit( function );
     773
     774                        // remove the unhandled objects from usedUninit, because a call is inserted
     775                        // to handle them - only objects that are later constructed are used uninitialized.
     776                        std::set< DeclarationWithType * > diff;
     777                        std::set_difference( usedUninit.begin(), usedUninit.end(), unhandled.begin(), unhandled.end(), std::inserter( diff, diff.begin() ) );
     778                        for ( DeclarationWithType * member : diff ) {
     779                                emit( "in ", CodeGen::genType( function->get_functionType(), function->get_name(), false ), ", field ", member->get_name(), " used before being constructed" );
    738780                        }
    739781
    740                         *this = old;
    741                 }
    742 
    743                 void WarnStructMembers::visit( ApplicationExpr * appExpr ) {
     782                        if ( ! unhandled.empty() ) {
     783                                // need to explicitly re-add function parameters in order to resolve copy constructors
     784                                enterScope();
     785                                maybeAccept( function->get_functionType(), *this );
     786
     787                                // need to iterate through members in reverse in order for
     788                                // ctor/dtor statements to come out in the right order
     789                                for ( Declaration * member : reverseIterate( structDecl->get_members() ) ) {
     790                                        DeclarationWithType * field = dynamic_cast< DeclarationWithType * >( member );
     791                                        // skip non-DWT members
     792                                        if ( ! field ) continue;
     793                                        // skip handled members
     794                                        if ( ! unhandled.count( field ) ) continue;
     795
     796                                        // insert and resolve default/copy constructor call for each field that's unhandled
     797                                        std::list< Statement * > stmt;
     798                                        UntypedExpr * deref = new UntypedExpr( new NameExpr( "*?" ) );
     799                                        deref->get_args().push_back( new VariableExpr( thisParam ) );
     800
     801                                        Expression * arg2 = 0;
     802                                        if ( isCopyConstructor( function ) ) {
     803                                                // if copy ctor, need to pass second-param-of-this-function.field
     804                                                std::list< DeclarationWithType * > & params = function->get_functionType()->get_parameters();
     805                                                assert( params.size() == 2 );
     806                                                arg2 = new MemberExpr( field, new VariableExpr( params.back() ) );
     807                                        }
     808                                        InitExpander srcParam( arg2 );
     809                                        SymTab::genImplicitCall( srcParam, new MemberExpr( field, deref ), function->get_name(), back_inserter( stmt ), field, isCtor );
     810
     811                                        assert( stmt.size() <= 1 );
     812                                        if ( stmt.size() == 1 ) {
     813                                                Statement * callStmt = stmt.front();
     814
     815                                                MutatingResolver resolver( *this );
     816                                                try {
     817                                                        callStmt->acceptMutator( resolver );
     818                                                        if ( isCtor ) {
     819                                                                function->get_statements()->push_front( callStmt );
     820                                                        } else {
     821                                                                // destructor statements should be added at the end
     822                                                                function->get_statements()->push_back( callStmt );
     823                                                        }
     824                                                } catch ( SemanticError & error ) {
     825                                                        emit( "in ", CodeGen::genType( function->get_functionType(), function->get_name(), false ), ", field ", field->get_name(), " not explicitly ", isCtor ? "constructed" : "destructed",  " and no ", isCtor ? "default constructor" : "destructor", " found" );
     826                                                }
     827                                        }
     828                                }
     829                                leaveScope();
     830                        }
     831                }
     832
     833                void GenStructMemberCalls::visit( ApplicationExpr * appExpr ) {
    744834                        if ( ! checkWarnings( function ) ) return;
    745835
     
    760850                                        handleFirstParam( firstParam );
    761851                                }
    762                         } else if ( fname == "?=?" && isIntrinsicCallExpr( appExpr ) ) {
    763                                 // forgive use of intrinsic assignment to construct, since instrinsic constructors
    764                                 // codegen as assignment anyway.
    765                                 assert( appExpr->get_args().size() == 2 );
    766                                 handleFirstParam( appExpr->get_args().front() );
    767852                        }
    768853
     
    770855                }
    771856
    772                 void WarnStructMembers::handleFirstParam( Expression * firstParam ) {
     857                void GenStructMemberCalls::handleFirstParam( Expression * firstParam ) {
    773858                        using namespace std;
    774859                        if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( firstParam ) ) {
     
    787872                }
    788873
    789                 void WarnStructMembers::visit( MemberExpr * memberExpr ) {
     874                void GenStructMemberCalls::visit( MemberExpr * memberExpr ) {
    790875                        if ( ! checkWarnings( function ) ) return;
    791                         if ( ! isConstructor( function->get_name() ) ) return;
     876                        if ( ! isCtor ) return;
    792877
    793878                        if ( ApplicationExpr * deref = dynamic_cast< ApplicationExpr * >( memberExpr->get_aggregate() ) ) {
     
    797882                                                        if ( unhandled.count( memberExpr->get_member() ) ) {
    798883                                                                // emit a warning because a member was used before it was constructed
    799                                                                 warn( "in ", CodeGen::genType( function->get_functionType(), function->get_name(), false ), ", member ", memberExpr->get_member()->get_name(), " used before being constructed" );
     884                                                                usedUninit.insert( memberExpr->get_member() );
    800885                                                        }
    801886                                                }
     
    805890                        Parent::visit( memberExpr );
    806891                }
     892
     893                template< typename Visitor, typename... Params >
     894                void error( Visitor & v, const Params &... params ) {
     895                        v.errors.append( toString( params... ) );
     896                }
     897
     898                template< typename... Params >
     899                void GenStructMemberCalls::emit( const Params &... params ) {
     900                        // toggle warnings vs. errors here.
     901                        // warn( params... );
     902                        error( *this, params... );
     903                }
     904
     905                DeclarationWithType * MutatingResolver::mutate( ObjectDecl *objectDecl ) {
     906                        // add object to the indexer assumes that there will be no name collisions
     907                        // in generated code. If this changes, add mutate methods for entities with
     908                        // scope and call {enter,leave}Scope explicitly.
     909                        objectDecl->accept( indexer );
     910                        return objectDecl;
     911                }
     912
     913                Expression* MutatingResolver::mutate( UntypedExpr *untypedExpr ) {
     914                        return safe_dynamic_cast< ApplicationExpr * >( ResolvExpr::findVoidExpression( untypedExpr, indexer ) );
     915                }
    807916        } // namespace
    808917} // namespace InitTweak
  • src/InitTweak/GenInit.cc

    r28307be r3403534  
    2525#include "SynTree/Mutator.h"
    2626#include "SymTab/Autogen.h"
     27#include "SymTab/Mangler.h"
    2728#include "GenPoly/PolyMutator.h"
    2829#include "GenPoly/DeclMutator.h"
     30#include "GenPoly/ScopedSet.h"
    2931
    3032namespace InitTweak {
     
    5557        class CtorDtor : public GenPoly::PolyMutator {
    5658          public:
     59                typedef GenPoly::PolyMutator Parent;
     60                using Parent::mutate;
    5761                /// create constructor and destructor statements for object declarations.
    5862                /// the actual call statements will be added in after the resolver has run
     
    6569                // should not traverse into any of these declarations to find objects
    6670                // that need to be constructed or destructed
    67                 virtual Declaration* mutate( StructDecl *aggregateDecl ) { return aggregateDecl; }
     71                virtual Declaration* mutate( StructDecl *aggregateDecl );
    6872                virtual Declaration* mutate( UnionDecl *aggregateDecl ) { return aggregateDecl; }
    6973                virtual Declaration* mutate( EnumDecl *aggregateDecl ) { return aggregateDecl; }
     
    7478                virtual Type * mutate( FunctionType *funcType ) { return funcType; }
    7579
    76           protected:
     80                virtual CompoundStmt * mutate( CompoundStmt * compoundStmt );
     81
     82          private:
     83                // set of mangled type names for which a constructor or destructor exists in the current scope.
     84                // these types require a ConstructorInit node to be generated, anything else is a POD type and thus
     85                // should not have a ConstructorInit generated.
     86
     87                bool isManaged( ObjectDecl * objDecl ) const ; // determine if object is managed
     88                void handleDWT( DeclarationWithType * dwt ); // add type to managed if ctor/dtor
     89                GenPoly::ScopedSet< std::string > managedTypes;
     90                bool inFunction = false;
    7791        };
    7892
     
    142156
    143157        DeclarationWithType* ReturnFixer::mutate( FunctionDecl *functionDecl ) {
    144                 std::list<DeclarationWithType*> oldReturnVals = returnVals;
    145                 std::string oldFuncName = funcName;
     158                ValueGuard< std::list<DeclarationWithType*> > oldReturnVals( returnVals );
     159                ValueGuard< std::string > oldFuncName( funcName );
    146160
    147161                FunctionType * type = functionDecl->get_functionType();
     
    149163                funcName = functionDecl->get_name();
    150164                DeclarationWithType * decl = Mutator::mutate( functionDecl );
    151                 returnVals = oldReturnVals;
    152                 funcName = oldFuncName;
    153165                return decl;
    154166        }
     
    197209
    198210        DeclarationWithType * HoistArrayDimension::mutate( FunctionDecl *functionDecl ) {
    199                 bool oldInFunc = inFunction;
     211                ValueGuard< bool > oldInFunc( inFunction );
    200212                inFunction = true;
    201213                DeclarationWithType * decl = Parent::mutate( functionDecl );
    202                 inFunction = oldInFunc;
    203214                return decl;
    204215        }
     
    209220        }
    210221
     222        bool CtorDtor::isManaged( ObjectDecl * objDecl ) const {
     223                Type * type = objDecl->get_type();
     224                while ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
     225                        type = at->get_base();
     226                }
     227                return managedTypes.find( SymTab::Mangler::mangle( type ) ) != managedTypes.end();
     228        }
     229
     230        void CtorDtor::handleDWT( DeclarationWithType * dwt ) {
     231                // if this function is a user-defined constructor or destructor, mark down the type as "managed"
     232                if ( ! LinkageSpec::isOverridable( dwt->get_linkage() ) && isCtorDtor( dwt->get_name() ) ) {
     233                        std::list< DeclarationWithType * > & params = GenPoly::getFunctionType( dwt->get_type() )->get_parameters();
     234                        assert( ! params.empty() );
     235                        PointerType * type = safe_dynamic_cast< PointerType * >( params.front()->get_type() );
     236                        managedTypes.insert( SymTab::Mangler::mangle( type->get_base() ) );
     237                }
     238        }
     239
    211240        DeclarationWithType * CtorDtor::mutate( ObjectDecl * objDecl ) {
    212                 // hands off if designated, if @=, or if extern
    213                 if ( tryConstruct( objDecl ) ) {
     241                handleDWT( objDecl );
     242                // hands off if @=, extern, builtin, etc.
     243                // if global but initializer is not constexpr, always try to construct, since this is not legal C
     244                if ( ( tryConstruct( objDecl ) && isManaged( objDecl ) ) || (! inFunction && ! isConstExpr( objDecl->get_init() ) ) ) {
     245                        // constructed objects cannot be designated
     246                        if ( isDesignated( objDecl->get_init() ) ) throw SemanticError( "Cannot include designations in the initializer for a managed Object. If this is really what you want, then initialize with @=.", objDecl );
     247                        // xxx - constructed objects should not have initializers nested too deeply
     248
    214249                        // call into genImplicitCall from Autogen.h to generate calls to ctor/dtor
    215250                        // for each constructable object
     
    241276                        }
    242277                }
    243                 return Mutator::mutate( objDecl );
     278                return Parent::mutate( objDecl );
    244279        }
    245280
    246281        DeclarationWithType * CtorDtor::mutate( FunctionDecl *functionDecl ) {
     282                ValueGuard< bool > oldInFunc = inFunction;
     283                inFunction = true;
     284
     285                handleDWT( functionDecl );
     286
     287                managedTypes.beginScope();
     288                // go through assertions and recursively add seen ctor/dtors
     289                for ( TypeDecl * tyDecl : functionDecl->get_functionType()->get_forall() ) {
     290                        for ( DeclarationWithType *& assertion : tyDecl->get_assertions() ) {
     291                                assertion = assertion->acceptMutator( *this );
     292                        }
     293                }
    247294                // parameters should not be constructed and destructed, so don't mutate FunctionType
    248295                mutateAll( functionDecl->get_oldDecls(), *this );
    249296                functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) );
     297
     298                managedTypes.endScope();
    250299                return functionDecl;
    251300        }
     301
     302        Declaration* CtorDtor::mutate( StructDecl *aggregateDecl ) {
     303                // don't construct members, but need to take note if there is a managed member,
     304                // because that means that this type is also managed
     305                for ( Declaration * member : aggregateDecl->get_members() ) {
     306                        if ( ObjectDecl * field = dynamic_cast< ObjectDecl * >( member ) ) {
     307                                if ( isManaged( field ) ) {
     308                                        managedTypes.insert( SymTab::Mangler::mangle( aggregateDecl ) );
     309                                        break;
     310                                }
     311                        }
     312                }
     313                return aggregateDecl;
     314        }
     315
     316        CompoundStmt * CtorDtor::mutate( CompoundStmt * compoundStmt ) {
     317                managedTypes.beginScope();
     318                CompoundStmt * stmt = Parent::mutate( compoundStmt );
     319                managedTypes.endScope();
     320                return stmt;
     321        }
     322
    252323} // namespace InitTweak
    253324
  • src/InitTweak/InitTweak.cc

    r28307be r3403534  
    77#include "SynTree/Attribute.h"
    88#include "GenPoly/GenPoly.h"
     9#include "ResolvExpr/typeops.h"
    910
    1011namespace InitTweak {
     
    7980        public:
    8081                ExprImpl( Expression * expr ) : arg( expr ) {}
     82
     83                ~ExprImpl() { delete arg; }
    8184
    8285                virtual std::list< Expression * > next( std::list< Expression * > & indices ) {
     
    122125
    123126        void InitExpander::clearArrayIndices() {
     127                deleteAll( indices );
    124128                indices.clear();
    125129        }
     
    228232                return ! LinkageSpec::isBuiltin( objDecl->get_linkage() ) &&
    229233                        (objDecl->get_init() == NULL ||
    230                                 ( objDecl->get_init() != NULL && objDecl->get_init()->get_maybeConstructed() )) &&
    231                         ! isDesignated( objDecl->get_init() )
     234                                ( objDecl->get_init() != NULL && objDecl->get_init()->get_maybeConstructed() ))
    232235                        && objDecl->get_storageClass() != DeclarationNode::Extern;
    233236        }
     
    387390                virtual void visit( ApplicationExpr *applicationExpr ) { isConstExpr = false; }
    388391                virtual void visit( UntypedExpr *untypedExpr ) { isConstExpr = false; }
    389                 virtual void visit( NameExpr *nameExpr ) { isConstExpr = false; }
    390                 virtual void visit( CastExpr *castExpr ) { isConstExpr = false; }
     392                virtual void visit( NameExpr *nameExpr ) {
     393                        // xxx - temporary hack, because 0 and 1 really should be constexprs, even though they technically aren't in Cforall today
     394                        if ( nameExpr->get_name() != "0" && nameExpr->get_name() != "1" ) isConstExpr = false;
     395                }
     396                // virtual void visit( CastExpr *castExpr ) { isConstExpr = false; }
     397                virtual void visit( AddressExpr *addressExpr ) {
     398                        // address of a variable or member expression is constexpr
     399                        Expression * arg = addressExpr->get_arg();
     400                        if ( ! dynamic_cast< NameExpr * >( arg) && ! dynamic_cast< VariableExpr * >( arg ) && ! dynamic_cast< MemberExpr * >( arg ) && ! dynamic_cast< UntypedMemberExpr * >( arg ) ) isConstExpr = false;
     401                }
    391402                virtual void visit( LabelAddressExpr *labAddressExpr ) { isConstExpr = false; }
    392403                virtual void visit( UntypedMemberExpr *memberExpr ) { isConstExpr = false; }
    393404                virtual void visit( MemberExpr *memberExpr ) { isConstExpr = false; }
    394405                virtual void visit( VariableExpr *variableExpr ) { isConstExpr = false; }
    395                 virtual void visit( ConstantExpr *constantExpr ) { /* bottom out */ }
    396406                // these might be okay?
    397407                // virtual void visit( SizeofExpr *sizeofExpr );
     
    436446        bool isDestructor( const std::string & str ) { return str == "^?{}"; }
    437447        bool isCtorDtor( const std::string & str ) { return isConstructor( str ) || isDestructor( str ); }
     448
     449        FunctionDecl * isCopyConstructor( Declaration * decl ) {
     450                FunctionDecl * function = dynamic_cast< FunctionDecl * >( decl );
     451                if ( ! function ) return 0;
     452                if ( ! isConstructor( function->get_name() ) ) return 0;
     453                FunctionType * ftype = function->get_functionType();
     454                if ( ftype->get_parameters().size() != 2 ) return 0;
     455
     456                Type * t1 = ftype->get_parameters().front()->get_type();
     457                Type * t2 = ftype->get_parameters().back()->get_type();
     458                PointerType * ptrType = dynamic_cast< PointerType * > ( t1 );
     459                assert( ptrType );
     460
     461                if ( ResolvExpr::typesCompatible( ptrType->get_base(), t2, SymTab::Indexer() ) ) {
     462                        return function;
     463                } else {
     464                        return 0;
     465                }
     466        }
    438467}
  • src/InitTweak/InitTweak.h

    r28307be r3403534  
    2929        bool isDestructor( const std::string & );
    3030        bool isCtorDtor( const std::string & );
     31
     32        FunctionDecl * isCopyConstructor( Declaration * decl );
    3133
    3234        /// transform Initializer into an argument list that can be passed to a call expression
Note: See TracChangeset for help on using the changeset viewer.