Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/SymTab/Validate.cc

    r4040425 r620cb95  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 21:50:04 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Mar  2 17:31:39 2016
    13 // Update Count     : 226
     11// Last Modified By : Rob Schluntz
     12// Last Modified On : Mon Feb 22 12:26:37 2016
     13// Update Count     : 297
    1414//
    1515
     
    5454#include "MakeLibCfa.h"
    5555#include "TypeEquality.h"
     56#include "Autogen.h"
    5657#include "ResolvExpr/typeops.h"
    5758
     
    101102                virtual void visit( StructInstType *structInst );
    102103                virtual void visit( UnionInstType *unionInst );
    103                 virtual void visit( TraitInstType *contextInst );
     104                virtual void visit( ContextInstType *contextInst );
    104105                virtual void visit( StructDecl *structDecl );
    105106                virtual void visit( UnionDecl *unionDecl );
     
    124125
    125126                const Indexer *indexer;
    126         };
    127 
    128         class AutogenerateRoutines : public Visitor {
    129           public:
    130                 /// Generates assignment operators for aggregate types as required
    131                 static void autogenerateRoutines( std::list< Declaration * > &translationUnit );
    132 
    133                 std::list< Declaration * > &get_declsToAdd() { return declsToAdd; }
    134 
    135                 virtual void visit( EnumDecl *enumDecl );
    136                 virtual void visit( StructDecl *structDecl );
    137                 virtual void visit( UnionDecl *structDecl );
    138                 virtual void visit( TypeDecl *typeDecl );
    139                 virtual void visit( TraitDecl *ctxDecl );
    140                 virtual void visit( FunctionDecl *functionDecl );
    141 
    142                 virtual void visit( FunctionType *ftype );
    143                 virtual void visit( PointerType *ftype );
    144 
    145                 virtual void visit( CompoundStmt *compoundStmt );
    146                 virtual void visit( IfStmt *ifStmt );
    147                 virtual void visit( WhileStmt *whileStmt );
    148                 virtual void visit( ForStmt *forStmt );
    149                 virtual void visit( SwitchStmt *switchStmt );
    150                 virtual void visit( ChooseStmt *chooseStmt );
    151                 virtual void visit( CaseStmt *caseStmt );
    152                 virtual void visit( CatchStmt *catchStmt );
    153 
    154                 AutogenerateRoutines() : functionNesting( 0 ) {}
    155           private:
    156                 template< typename StmtClass > void visitStatement( StmtClass *stmt );
    157 
    158                 std::list< Declaration * > declsToAdd;
    159                 std::set< std::string > structsDone;
    160                 unsigned int functionNesting;                   // current level of nested functions
    161127        };
    162128
     
    192158                virtual Declaration *mutate( UnionDecl * unionDecl );
    193159                virtual Declaration *mutate( EnumDecl * enumDecl );
    194                 virtual Declaration *mutate( TraitDecl * contextDecl );
     160                virtual Declaration *mutate( ContextDecl * contextDecl );
    195161
    196162                template<typename AggDecl>
     
    200166                TypedefMap typedefNames;
    201167                int scopeLevel;
     168        };
     169
     170        class VerifyCtorDtor : public Visitor {
     171        public:
     172                /// ensure that constructors and destructors have at least one
     173                /// parameter, the first of which must be a pointer, and no
     174                /// return values.
     175                static void verify( std::list< Declaration * > &translationUnit );
     176
     177                // VerifyCtorDtor() {}
     178
     179                virtual void visit( FunctionDecl *funcDecl );
     180        private:
    202181        };
    203182
     
    211190                acceptAll( translationUnit, pass2 );
    212191                ReturnChecker::checkFunctionReturns( translationUnit );
    213                 AutogenerateRoutines::autogenerateRoutines( translationUnit );
     192                autogenerateRoutines( translationUnit );
    214193                acceptAll( translationUnit, pass3 );
     194                VerifyCtorDtor::verify( translationUnit );
    215195        }
    216196
     
    222202                type->accept( pass2 );
    223203                type->accept( pass3 );
    224         }
    225 
    226         template< typename Visitor >
    227         void acceptAndAdd( std::list< Declaration * > &translationUnit, Visitor &visitor, bool addBefore ) {
    228                 std::list< Declaration * >::iterator i = translationUnit.begin();
    229                 while ( i != translationUnit.end() ) {
    230                         (*i)->accept( visitor );
    231                         std::list< Declaration * >::iterator next = i;
    232                         next++;
    233                         if ( ! visitor.get_declsToAdd().empty() ) {
    234                                 translationUnit.splice( addBefore ? i : next, visitor.get_declsToAdd() );
    235                         } // if
    236                         i = next;
    237                 } // while
    238204        }
    239205
     
    404370        }
    405371
    406         void Pass2::visit( TraitInstType *contextInst ) {
     372        void Pass2::visit( ContextInstType *contextInst ) {
    407373                Parent::visit( contextInst );
    408                 TraitDecl *ctx = indexer->lookupTrait( contextInst->get_name() );
     374                ContextDecl *ctx = indexer->lookupContext( contextInst->get_name() );
    409375                if ( ! ctx ) {
    410376                        throw SemanticError( "use of undeclared context " + contextInst->get_name() );
     
    412378                for ( std::list< TypeDecl * >::const_iterator i = ctx->get_parameters().begin(); i != ctx->get_parameters().end(); ++i ) {
    413379                        for ( std::list< DeclarationWithType * >::const_iterator assert = (*i )->get_assertions().begin(); assert != (*i )->get_assertions().end(); ++assert ) {
    414                                 if ( TraitInstType *otherCtx = dynamic_cast< TraitInstType * >(*assert ) ) {
     380                                if ( ContextInstType *otherCtx = dynamic_cast< ContextInstType * >(*assert ) ) {
    415381                                        cloneAll( otherCtx->get_members(), contextInst->get_members() );
    416382                                } else {
     
    476442                        while ( ! toBeDone.empty() ) {
    477443                                for ( std::list< DeclarationWithType * >::iterator assertion = toBeDone.begin(); assertion != toBeDone.end(); ++assertion ) {
    478                                         if ( TraitInstType *ctx = dynamic_cast< TraitInstType * >( (*assertion )->get_type() ) ) {
     444                                        if ( ContextInstType *ctx = dynamic_cast< ContextInstType * >( (*assertion )->get_type() ) ) {
    479445                                                for ( std::list< Declaration * >::const_iterator i = ctx->get_members().begin(); i != ctx->get_members().end(); ++i ) {
    480446                                                        DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *i );
     
    513479        }
    514480
    515         static const std::list< std::string > noLabels;
    516 
    517         void AutogenerateRoutines::autogenerateRoutines( std::list< Declaration * > &translationUnit ) {
    518                 AutogenerateRoutines visitor;
    519                 acceptAndAdd( translationUnit, visitor, false );
    520         }
    521 
    522         template< typename OutputIterator >
    523         void makeScalarAssignment( ObjectDecl *srcParam, ObjectDecl *dstParam, DeclarationWithType *member, OutputIterator out ) {
    524                 ObjectDecl *obj = dynamic_cast<ObjectDecl *>( member );
    525                 // unnamed bit fields are not copied as they cannot be accessed
    526                 if ( obj != NULL && obj->get_name() == "" && obj->get_bitfieldWidth() != NULL ) return;
    527 
    528                 UntypedExpr *assignExpr = new UntypedExpr( new NameExpr( "?=?" ) );
    529 
    530                 UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
    531                 derefExpr->get_args().push_back( new VariableExpr( dstParam ) );
    532 
    533                 // do something special for unnamed members
    534                 Expression *dstselect = new AddressExpr( new MemberExpr( member, derefExpr ) );
    535                 assignExpr->get_args().push_back( dstselect );
    536 
    537                 Expression *srcselect = new MemberExpr( member, new VariableExpr( srcParam ) );
    538                 assignExpr->get_args().push_back( srcselect );
    539 
    540                 *out++ = new ExprStmt( noLabels, assignExpr );
    541         }
    542 
    543         template< typename OutputIterator >
    544         void makeArrayAssignment( ObjectDecl *srcParam, ObjectDecl *dstParam, DeclarationWithType *member, ArrayType *array, OutputIterator out ) {
    545                 static UniqueName indexName( "_index" );
    546 
    547                 // for a flexible array member nothing is done -- user must define own assignment
    548                 if ( ! array->get_dimension() ) return;
    549 
    550                 ObjectDecl *index = new ObjectDecl( indexName.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), 0 );
    551                 *out++ = new DeclStmt( noLabels, index );
    552 
    553                 UntypedExpr *init = new UntypedExpr( new NameExpr( "?=?" ) );
    554                 init->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
    555                 init->get_args().push_back( new NameExpr( "0" ) );
    556                 Statement *initStmt = new ExprStmt( noLabels, init );
    557                 std::list<Statement *> initList;
    558                 initList.push_back( initStmt );
    559 
    560                 UntypedExpr *cond = new UntypedExpr( new NameExpr( "?<?" ) );
    561                 cond->get_args().push_back( new VariableExpr( index ) );
    562                 cond->get_args().push_back( array->get_dimension()->clone() );
    563 
    564                 UntypedExpr *inc = new UntypedExpr( new NameExpr( "++?" ) );
    565                 inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
    566 
    567                 UntypedExpr *assignExpr = new UntypedExpr( new NameExpr( "?=?" ) );
    568 
    569                 UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
    570                 derefExpr->get_args().push_back( new VariableExpr( dstParam ) );
    571 
    572                 Expression *dstselect = new MemberExpr( member, derefExpr );
    573                 UntypedExpr *dstIndex = new UntypedExpr( new NameExpr( "?+?" ) );
    574                 dstIndex->get_args().push_back( dstselect );
    575                 dstIndex->get_args().push_back( new VariableExpr( index ) );
    576                 assignExpr->get_args().push_back( dstIndex );
    577 
    578                 Expression *srcselect = new MemberExpr( member, new VariableExpr( srcParam ) );
    579                 UntypedExpr *srcIndex = new UntypedExpr( new NameExpr( "?[?]" ) );
    580                 srcIndex->get_args().push_back( srcselect );
    581                 srcIndex->get_args().push_back( new VariableExpr( index ) );
    582                 assignExpr->get_args().push_back( srcIndex );
    583 
    584                 *out++ = new ForStmt( noLabels, initList, cond, inc, new ExprStmt( noLabels, assignExpr ) );
    585         }
    586 
    587         template< typename OutputIterator >
    588         void makeUnionFieldsAssignment( ObjectDecl *srcParam, ObjectDecl *dstParam, UnionInstType *unionType, OutputIterator out ) {
    589                 UntypedExpr *copy = new UntypedExpr( new NameExpr( "__builtin_memcpy" ) );
    590                 copy->get_args().push_back( new VariableExpr( dstParam ) );
    591                 copy->get_args().push_back( new AddressExpr( new VariableExpr( srcParam ) ) );
    592                 copy->get_args().push_back( new SizeofExpr( unionType ) );
    593 
    594                 *out++ = new ExprStmt( noLabels, copy );
    595         }
    596 
    597         //E ?=?(E volatile*, int),
    598         //  ?=?(E _Atomic volatile*, int);
    599         void makeEnumAssignment( EnumDecl *enumDecl, EnumInstType *refType, unsigned int functionNesting, std::list< Declaration * > &declsToAdd ) {
    600                 FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
    601 
    602                 ObjectDecl *returnVal = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, refType->clone(), 0 );
    603                 assignType->get_returnVals().push_back( returnVal );
    604 
    605                 // need two assignment operators with different types
    606                 FunctionType * assignType2 = assignType->clone();
    607 
    608                 // E ?=?(E volatile *, E)
    609                 Type *etype = refType->clone();
    610                 // etype->get_qualifiers() += Type::Qualifiers(false, true, false, false, false, false);
    611 
    612                 ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), etype ), 0 );
    613                 assignType->get_parameters().push_back( dstParam );
    614 
    615                 ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, etype->clone(), 0 );
    616                 assignType->get_parameters().push_back( srcParam );
    617 
    618                 // E ?=?(E volatile *, int)
    619                 assignType2->get_parameters().push_back( dstParam->clone() );
    620                 BasicType * paramType = new BasicType(Type::Qualifiers(), BasicType::SignedInt);
    621                 ObjectDecl *srcParam2 = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, paramType, 0 );
    622                 assignType2->get_parameters().push_back( srcParam2 );
    623 
    624                 // Routines at global scope marked "static" to prevent multiple definitions is separate translation units
    625                 // because each unit generates copies of the default routines for each aggregate.
    626 
    627                 // since there is no definition, these should not be inline
    628                 // make these intrinsic so that the code generator does not make use of them
    629                 FunctionDecl *assignDecl = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, assignType, 0, false, false );
    630                 assignDecl->fixUniqueId();
    631                 FunctionDecl *assignDecl2 = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, assignType2, 0, false, false );
    632                 assignDecl2->fixUniqueId();
    633 
    634                 // these should be built in the same way that the prelude
    635                 // functions are, so build a list containing the prototypes
    636                 // and allow MakeLibCfa to autogenerate the bodies.
    637                 std::list< Declaration * > assigns;
    638                 assigns.push_back( assignDecl );
    639                 assigns.push_back( assignDecl2 );
    640 
    641                 LibCfa::makeLibCfa( assigns );
    642 
    643                 // need to remove the prototypes, since this may be nested in a routine
    644                 for (int start = 0, end = assigns.size()/2; start < end; start++) {
    645                         delete assigns.front();
    646                         assigns.pop_front();
    647                 } // for
    648 
    649                 declsToAdd.insert( declsToAdd.begin(), assigns.begin(), assigns.end() );
    650         }
    651 
    652         /// Clones a reference type, replacing any parameters it may have with a clone of the provided list
    653         template< typename GenericInstType >
    654         GenericInstType *cloneWithParams( GenericInstType *refType, const std::list< Expression* >& params ) {
    655                 GenericInstType *clone = refType->clone();
    656                 clone->get_parameters().clear();
    657                 cloneAll( params, clone->get_parameters() );
    658                 return clone;
    659         }
    660 
    661         /// Creates a new type decl that's the same as src, but renamed and with only the ?=? assertion (for complete types only)
    662         TypeDecl *cloneAndRename( TypeDecl *src, const std::string &name ) {
    663                 TypeDecl *dst = new TypeDecl( name, src->get_storageClass(), 0, src->get_kind() );
    664 
    665                 if ( src->get_kind() == TypeDecl::Any ) {
    666                         // just include assignment operator assertion
    667                         TypeInstType *assignParamType = new TypeInstType( Type::Qualifiers(), name, dst );
    668                         FunctionType *assignFunctionType = new FunctionType( Type::Qualifiers(), false );
    669                         assignFunctionType->get_returnVals().push_back(
    670                                 new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, assignParamType->clone(), 0 ) );
    671                         assignFunctionType->get_parameters().push_back(
    672                                 new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), assignParamType->clone() ), 0 ) );
    673                         assignFunctionType->get_parameters().push_back(
    674                                 new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, assignParamType, 0 ) );
    675                         FunctionDecl *assignAssert = new FunctionDecl( "?=?", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, assignFunctionType, 0, false, false );
    676                         dst->get_assertions().push_back( assignAssert );
    677                 }
    678 
    679                 return dst;
    680         }
    681 
    682         Declaration *makeStructAssignment( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting ) {
    683                 FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
    684 
    685                 // Make function polymorphic in same parameters as generic struct, if applicable
    686                 bool isGeneric = false;  // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for union)
    687                 std::list< TypeDecl* >& genericParams = aggregateDecl->get_parameters();
    688                 std::list< Expression* > structParams;  // List of matching parameters to put on types
    689                 TypeSubstitution genericSubs; // Substitutions to make to member types of struct
    690                 for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) {
    691                         isGeneric = true;
    692                         TypeDecl *typeParam = cloneAndRename( *param, "_autoassign_" + aggregateDecl->get_name() + "_" + (*param)->get_name() );
    693                         assignType->get_forall().push_back( typeParam );
    694                         TypeInstType *newParamType = new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam );
    695                         genericSubs.add( (*param)->get_name(), newParamType );
    696                         structParams.push_back( new TypeExpr( newParamType ) );
    697                 }
    698 
    699                 ObjectDecl *returnVal = new ObjectDecl( "_ret", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, structParams ), 0 );
    700                 assignType->get_returnVals().push_back( returnVal );
    701 
    702                 ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), cloneWithParams( refType, structParams ) ), 0 );
    703                 assignType->get_parameters().push_back( dstParam );
    704 
    705                 ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, structParams ), 0 );
    706                 assignType->get_parameters().push_back( srcParam );
    707 
    708                 // Routines at global scope marked "static" to prevent multiple definitions is separate translation units
    709                 // because each unit generates copies of the default routines for each aggregate.
    710                 FunctionDecl *assignDecl = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, assignType, new CompoundStmt( noLabels ), true, false );
    711                 assignDecl->fixUniqueId();
    712 
    713                 for ( std::list< Declaration * >::const_iterator member = aggregateDecl->get_members().begin(); member != aggregateDecl->get_members().end(); ++member ) {
    714                         if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member ) ) {
    715                                 // query the type qualifiers of this field and skip assigning it if it is marked const.
    716                                 // If it is an array type, we need to strip off the array layers to find its qualifiers.
    717                                 Type * type = dwt->get_type();
    718                                 while ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
    719                                         type = at->get_base();
    720                                 }
    721 
    722                                 if ( type->get_qualifiers().isConst ) {
    723                                         // don't assign const members
    724                                         continue;
    725                                 }
    726 
    727                                 if ( isGeneric ) {
    728                                         // rewrite member type in terms of the type variables on this operator
    729                                         DeclarationWithType *fixedMember = dwt->clone();
    730                                         genericSubs.apply( fixedMember );
    731 
    732                                         // assign to both destination and return value
    733                                         if ( ArrayType *array = dynamic_cast< ArrayType * >( fixedMember->get_type() ) ) {
    734                                                 makeArrayAssignment( srcParam, dstParam, fixedMember, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
    735                                                 makeArrayAssignment( srcParam, returnVal, fixedMember, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
    736                                         } else {
    737                                                 makeScalarAssignment( srcParam, dstParam, fixedMember, back_inserter( assignDecl->get_statements()->get_kids() ) );
    738                                                 makeScalarAssignment( srcParam, returnVal, fixedMember, back_inserter( assignDecl->get_statements()->get_kids() ) );
    739                                         } // if
    740                                 } else {
    741                                         // assign to destination
    742                                         if ( ArrayType *array = dynamic_cast< ArrayType * >( dwt->get_type() ) ) {
    743                                                 makeArrayAssignment( srcParam, dstParam, dwt, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
    744                                         } else {
    745                                                 makeScalarAssignment( srcParam, dstParam, dwt, back_inserter( assignDecl->get_statements()->get_kids() ) );
    746                                         } // if
    747                                 } // if
    748                         } // if
    749                 } // for
    750                 if ( ! isGeneric ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
    751 
    752                 return assignDecl;
    753         }
    754 
    755         Declaration *makeUnionAssignment( UnionDecl *aggregateDecl, UnionInstType *refType, unsigned int functionNesting ) {
    756                 FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
    757 
    758                 // Make function polymorphic in same parameters as generic union, if applicable
    759                 bool isGeneric = false;  // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for struct)
    760                 std::list< TypeDecl* >& genericParams = aggregateDecl->get_parameters();
    761                 std::list< Expression* > unionParams;  // List of matching parameters to put on types
    762                 for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) {
    763                         isGeneric = true;
    764                         TypeDecl *typeParam = cloneAndRename( *param, "_autoassign_" + aggregateDecl->get_name() + "_" + (*param)->get_name() );
    765                         assignType->get_forall().push_back( typeParam );
    766                         unionParams.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam ) ) );
    767                 }
    768 
    769                 ObjectDecl *returnVal = new ObjectDecl( "_ret", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, unionParams ), 0 );
    770                 assignType->get_returnVals().push_back( returnVal );
    771 
    772                 ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), cloneWithParams( refType, unionParams ) ), 0 );
    773                 assignType->get_parameters().push_back( dstParam );
    774 
    775                 ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, unionParams ), 0 );
    776                 assignType->get_parameters().push_back( srcParam );
    777 
    778                 // Routines at global scope marked "static" to prevent multiple definitions is separate translation units
    779                 // because each unit generates copies of the default routines for each aggregate.
    780                 FunctionDecl *assignDecl = new FunctionDecl( "?=?",  functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, assignType, new CompoundStmt( noLabels ), true, false );
    781                 assignDecl->fixUniqueId();
    782 
    783                 makeUnionFieldsAssignment( srcParam, dstParam, cloneWithParams( refType, unionParams ), back_inserter( assignDecl->get_statements()->get_kids() ) );
    784                 if ( isGeneric ) makeUnionFieldsAssignment( srcParam, returnVal, cloneWithParams( refType, unionParams ), back_inserter( assignDecl->get_statements()->get_kids() ) );
    785                
    786                 if ( ! isGeneric ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
    787 
    788                 return assignDecl;
    789         }
    790 
    791         void AutogenerateRoutines::visit( EnumDecl *enumDecl ) {
    792                 if ( ! enumDecl->get_members().empty() ) {
    793                         EnumInstType *enumInst = new EnumInstType( Type::Qualifiers(), enumDecl->get_name() );
    794                         // enumInst->set_baseEnum( enumDecl );
    795                         // declsToAdd.push_back(
    796                         makeEnumAssignment( enumDecl, enumInst, functionNesting, declsToAdd );
    797                 }
    798         }
    799 
    800         void AutogenerateRoutines::visit( StructDecl *structDecl ) {
    801                 if ( ! structDecl->get_members().empty() && structsDone.find( structDecl->get_name() ) == structsDone.end() ) {
    802                         StructInstType structInst( Type::Qualifiers(), structDecl->get_name() );
    803                         structInst.set_baseStruct( structDecl );
    804                         declsToAdd.push_back( makeStructAssignment( structDecl, &structInst, functionNesting ) );
    805                         structsDone.insert( structDecl->get_name() );
    806                 } // if
    807         }
    808 
    809         void AutogenerateRoutines::visit( UnionDecl *unionDecl ) {
    810                 if ( ! unionDecl->get_members().empty() ) {
    811                         UnionInstType unionInst( Type::Qualifiers(), unionDecl->get_name() );
    812                         unionInst.set_baseUnion( unionDecl );
    813                         declsToAdd.push_back( makeUnionAssignment( unionDecl, &unionInst, functionNesting ) );
    814                 } // if
    815         }
    816 
    817         void AutogenerateRoutines::visit( TypeDecl *typeDecl ) {
    818                 CompoundStmt *stmts = 0;
    819                 TypeInstType *typeInst = new TypeInstType( Type::Qualifiers(), typeDecl->get_name(), false );
    820                 typeInst->set_baseType( typeDecl );
    821                 ObjectDecl *src = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, typeInst->clone(), 0 );
    822                 ObjectDecl *dst = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), typeInst->clone() ), 0 );
    823                 if ( typeDecl->get_base() ) {
    824                         stmts = new CompoundStmt( std::list< Label >() );
    825                         UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) );
    826                         assign->get_args().push_back( new CastExpr( new VariableExpr( dst ), new PointerType( Type::Qualifiers(), typeDecl->get_base()->clone() ) ) );
    827                         assign->get_args().push_back( new CastExpr( new VariableExpr( src ), typeDecl->get_base()->clone() ) );
    828                         stmts->get_kids().push_back( new ReturnStmt( std::list< Label >(), assign ) );
    829                 } // if
    830                 FunctionType *type = new FunctionType( Type::Qualifiers(), false );
    831                 type->get_returnVals().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, typeInst, 0 ) );
    832                 type->get_parameters().push_back( dst );
    833                 type->get_parameters().push_back( src );
    834                 FunctionDecl *func = new FunctionDecl( "?=?", DeclarationNode::NoStorageClass, LinkageSpec::AutoGen, type, stmts, false, false );
    835                 declsToAdd.push_back( func );
    836         }
    837 
    838         void addDecls( std::list< Declaration * > &declsToAdd, std::list< Statement * > &statements, std::list< Statement * >::iterator i ) {
    839                 for ( std::list< Declaration * >::iterator decl = declsToAdd.begin(); decl != declsToAdd.end(); ++decl ) {
    840                         statements.insert( i, new DeclStmt( noLabels, *decl ) );
    841                 } // for
    842                 declsToAdd.clear();
    843         }
    844 
    845         void AutogenerateRoutines::visit( FunctionType *) {
    846                 // ensure that we don't add assignment ops for types defined as part of the function
    847         }
    848 
    849         void AutogenerateRoutines::visit( PointerType *) {
    850                 // ensure that we don't add assignment ops for types defined as part of the pointer
    851         }
    852 
    853         void AutogenerateRoutines::visit( TraitDecl *) {
    854                 // ensure that we don't add assignment ops for types defined as part of the context
    855         }
    856 
    857         template< typename StmtClass >
    858         inline void AutogenerateRoutines::visitStatement( StmtClass *stmt ) {
    859                 std::set< std::string > oldStructs = structsDone;
    860                 addVisit( stmt, *this );
    861                 structsDone = oldStructs;
    862         }
    863 
    864         void AutogenerateRoutines::visit( FunctionDecl *functionDecl ) {
    865                 maybeAccept( functionDecl->get_functionType(), *this );
    866                 acceptAll( functionDecl->get_oldDecls(), *this );
    867                 functionNesting += 1;
    868                 maybeAccept( functionDecl->get_statements(), *this );
    869                 functionNesting -= 1;
    870         }
    871 
    872         void AutogenerateRoutines::visit( CompoundStmt *compoundStmt ) {
    873                 visitStatement( compoundStmt );
    874         }
    875 
    876         void AutogenerateRoutines::visit( IfStmt *ifStmt ) {
    877                 visitStatement( ifStmt );
    878         }
    879 
    880         void AutogenerateRoutines::visit( WhileStmt *whileStmt ) {
    881                 visitStatement( whileStmt );
    882         }
    883 
    884         void AutogenerateRoutines::visit( ForStmt *forStmt ) {
    885                 visitStatement( forStmt );
    886         }
    887 
    888         void AutogenerateRoutines::visit( SwitchStmt *switchStmt ) {
    889                 visitStatement( switchStmt );
    890         }
    891 
    892         void AutogenerateRoutines::visit( ChooseStmt *switchStmt ) {
    893                 visitStatement( switchStmt );
    894         }
    895 
    896         void AutogenerateRoutines::visit( CaseStmt *caseStmt ) {
    897                 visitStatement( caseStmt );
    898         }
    899 
    900         void AutogenerateRoutines::visit( CatchStmt *cathStmt ) {
    901                 visitStatement( cathStmt );
    902         }
    903 
    904481        void ReturnChecker::checkFunctionReturns( std::list< Declaration * > & translationUnit ) {
    905482                ReturnChecker checker;
     
    1075652        }
    1076653
    1077                 Declaration *EliminateTypedef::mutate( TraitDecl * contextDecl ) {
     654                Declaration *EliminateTypedef::mutate( ContextDecl * contextDecl ) {
    1078655                Mutator::mutate( contextDecl );
    1079656                return handleAggregate( contextDecl );
    1080657        }
    1081658
     659        void VerifyCtorDtor::verify( std::list< Declaration * > & translationUnit ) {
     660                VerifyCtorDtor verifier;
     661                acceptAll( translationUnit, verifier );
     662        }
     663
     664        void VerifyCtorDtor::visit( FunctionDecl * funcDecl ) {
     665                FunctionType * funcType = funcDecl->get_functionType();
     666                std::list< DeclarationWithType * > &returnVals = funcType->get_returnVals();
     667                std::list< DeclarationWithType * > &params = funcType->get_parameters();
     668
     669                if ( funcDecl->get_name() == "?{}" || funcDecl->get_name() == "^?{}" ) {
     670                        if ( params.size() == 0 ) {
     671                                throw SemanticError( "Constructors and destructors require at least one parameter ", funcDecl );
     672                        }
     673                        if ( ! dynamic_cast< PointerType * >( params.front()->get_type() ) ) {
     674                                throw SemanticError( "First parameter of a constructor or destructor must be a pointer ", funcDecl );
     675                        }
     676                        if ( returnVals.size() != 0 ) {
     677                                throw SemanticError( "Constructors and destructors cannot have explicit return values ", funcDecl );
     678                        }
     679                }
     680
     681                Visitor::visit( funcDecl );
     682                // original idea: modify signature of ctor/dtors and insert appropriate return statements
     683                // to cause desired behaviour
     684                // new idea: add comma exprs to every ctor call to produce first parameter.
     685                // this requires some memoization of the first parameter, because it can be a
     686                // complicated expression with side effects (see: malloc). idea: add temporary variable
     687                // that is assigned address of constructed object in ctor argument position and
     688                // return the temporary. It should also be done after all implicit ctors are
     689                // added, so not in this pass!
     690        }
    1082691} // namespace SymTab
    1083692
Note: See TracChangeset for help on using the changeset viewer.