Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/SymTab/Validate.cc

    rb644d6f r74d1804  
    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 Apr 13 16:39:30 2016
    13 // Update Count     : 251
     11// Last Modified By : Rob Schluntz
     12// Last Modified On : Wed May 11 13:17:52 2016
     13// Update Count     : 297
    1414//
    1515
     
    5656#include "MakeLibCfa.h"
    5757#include "TypeEquality.h"
     58#include "Autogen.h"
    5859#include "ResolvExpr/typeops.h"
    5960
     
    122123
    123124                const Indexer *indexer;
    124         };
    125 
    126         class AutogenerateRoutines : public Visitor {
    127           public:
    128                 /// Generates assignment operators for aggregate types as required
    129                 static void autogenerateRoutines( std::list< Declaration * > &translationUnit );
    130 
    131                 std::list< Declaration * > &get_declsToAdd() { return declsToAdd; }
    132 
    133                 virtual void visit( EnumDecl *enumDecl );
    134                 virtual void visit( StructDecl *structDecl );
    135                 virtual void visit( UnionDecl *structDecl );
    136                 virtual void visit( TypeDecl *typeDecl );
    137                 virtual void visit( TraitDecl *ctxDecl );
    138                 virtual void visit( FunctionDecl *functionDecl );
    139 
    140                 virtual void visit( FunctionType *ftype );
    141                 virtual void visit( PointerType *ftype );
    142 
    143                 virtual void visit( CompoundStmt *compoundStmt );
    144                 virtual void visit( SwitchStmt *switchStmt );
    145                 virtual void visit( ChooseStmt *chooseStmt );
    146                 // virtual void visit( CaseStmt *caseStmt );
    147 
    148                 AutogenerateRoutines() : functionNesting( 0 ) {}
    149           private:
    150                 template< typename StmtClass > void visitStatement( StmtClass *stmt );
    151 
    152                 std::list< Declaration * > declsToAdd;
    153                 std::set< std::string > structsDone;
    154                 unsigned int functionNesting;                   // current level of nested functions
    155125        };
    156126
     
    192162                template<typename AggDecl>
    193163                void addImplicitTypedef( AggDecl * aggDecl );
    194                
     164
    195165                typedef std::map< std::string, std::pair< TypedefDecl *, int > > TypedefMap;
    196166                TypedefMap typedefNames;
    197167                int scopeLevel;
    198168        };
     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                virtual void visit( FunctionDecl *funcDecl );
     178};
    199179
    200180        class CompoundLiteral : public GenPoly::DeclMutator {
     
    217197                ReturnChecker::checkFunctionReturns( translationUnit );
    218198                mutateAll( translationUnit, compoundliteral );
    219                 AutogenerateRoutines::autogenerateRoutines( translationUnit );
     199                autogenerateRoutines( translationUnit );
    220200                acceptAll( translationUnit, pass3 );
     201                VerifyCtorDtor::verify( translationUnit );
    221202        }
    222203
     
    228209                type->accept( pass2 );
    229210                type->accept( pass3 );
    230         }
    231 
    232         template< typename Visitor >
    233         void acceptAndAdd( std::list< Declaration * > &translationUnit, Visitor &visitor, bool addBefore ) {
    234                 std::list< Declaration * >::iterator i = translationUnit.begin();
    235                 while ( i != translationUnit.end() ) {
    236                         (*i)->accept( visitor );
    237                         std::list< Declaration * >::iterator next = i;
    238                         next++;
    239                         if ( ! visitor.get_declsToAdd().empty() ) {
    240                                 translationUnit.splice( addBefore ? i : next, visitor.get_declsToAdd() );
    241                         } // if
    242                         i = next;
    243                 } // while
    244211        }
    245212
     
    312279        void Pass1::visit( EnumDecl *enumDecl ) {
    313280                // Set the type of each member of the enumeration to be EnumConstant
    314 
    315281                for ( std::list< Declaration * >::iterator i = enumDecl->get_members().begin(); i != enumDecl->get_members().end(); ++i ) {
    316282                        ObjectDecl * obj = dynamic_cast< ObjectDecl * >( *i );
    317283                        assert( obj );
    318                         // obj->set_type( new EnumInstType( Type::Qualifiers( true, false, false, false, false, false ), enumDecl->get_name() ) );
    319                         BasicType * enumType = new BasicType( Type::Qualifiers(), BasicType::SignedInt );
    320                         obj->set_type( enumType ) ;
     284                        obj->set_type( new EnumInstType( Type::Qualifiers( true, false, false, false, false, false ), enumDecl->get_name() ) );
    321285                } // for
    322286                Parent::visit( enumDecl );
     
    324288
    325289        namespace {
    326                 template< typename DWTIterator >
    327                 void fixFunctionList( DWTIterator begin, DWTIterator end, FunctionType *func ) {
     290                template< typename DWTList >
     291                void fixFunctionList( DWTList & dwts, FunctionType * func ) {
    328292                        // the only case in which "void" is valid is where it is the only one in the list; then it should be removed
    329293                        // entirely other fix ups are handled by the FixFunction class
     294                        typedef typename DWTList::iterator DWTIterator;
     295                        DWTIterator begin( dwts.begin() ), end( dwts.end() );
    330296                        if ( begin == end ) return;
    331297                        FixFunction fixer;
    332298                        DWTIterator i = begin;
    333                         *i = (*i )->acceptMutator( fixer );
     299                        *i = (*i)->acceptMutator( fixer );
    334300                        if ( fixer.get_isVoid() ) {
    335301                                DWTIterator j = i;
    336302                                ++i;
    337                                 func->get_parameters().erase( j );
     303                                dwts.erase( j );
    338304                                if ( i != end ) {
    339305                                        throw SemanticError( "invalid type void in function type ", func );
     
    354320        void Pass1::visit( FunctionType *func ) {
    355321                // Fix up parameters and return types
    356                 fixFunctionList( func->get_parameters().begin(), func->get_parameters().end(), func );
    357                 fixFunctionList( func->get_returnVals().begin(), func->get_returnVals().end(), func );
     322                fixFunctionList( func->get_parameters(), func );
     323                fixFunctionList( func->get_returnVals(), func );
    358324                Visitor::visit( func );
    359325        }
     
    418384
    419385        void Pass2::visit( StructDecl *structDecl ) {
     386                // visit struct members first so that the types of self-referencing members are updated properly
     387                Parent::visit( structDecl );
    420388                if ( ! structDecl->get_members().empty() ) {
    421389                        ForwardStructsType::iterator fwds = forwardStructs.find( structDecl->get_name() );
     
    427395                        } // if
    428396                } // if
    429                 Indexer::visit( structDecl );
    430397        }
    431398
    432399        void Pass2::visit( UnionDecl *unionDecl ) {
     400                Parent::visit( unionDecl );
    433401                if ( ! unionDecl->get_members().empty() ) {
    434402                        ForwardUnionsType::iterator fwds = forwardUnions.find( unionDecl->get_name() );
     
    440408                        } // if
    441409                } // if
    442                 Indexer::visit( unionDecl );
    443410        }
    444411
     
    503470        }
    504471
    505         static const std::list< std::string > noLabels;
    506 
    507         void AutogenerateRoutines::autogenerateRoutines( std::list< Declaration * > &translationUnit ) {
    508                 AutogenerateRoutines visitor;
    509                 acceptAndAdd( translationUnit, visitor, false );
    510         }
    511 
    512         template< typename OutputIterator >
    513         void makeScalarAssignment( ObjectDecl *srcParam, ObjectDecl *dstParam, DeclarationWithType *member, OutputIterator out ) {
    514                 ObjectDecl *obj = dynamic_cast<ObjectDecl *>( member );
    515                 // unnamed bit fields are not copied as they cannot be accessed
    516                 if ( obj != NULL && obj->get_name() == "" && obj->get_bitfieldWidth() != NULL ) return;
    517 
    518                 UntypedExpr *assignExpr = new UntypedExpr( new NameExpr( "?=?" ) );
    519 
    520                 UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
    521                 derefExpr->get_args().push_back( new VariableExpr( dstParam ) );
    522 
    523                 // do something special for unnamed members
    524                 Expression *dstselect = new AddressExpr( new MemberExpr( member, derefExpr ) );
    525                 assignExpr->get_args().push_back( dstselect );
    526 
    527                 Expression *srcselect = new MemberExpr( member, new VariableExpr( srcParam ) );
    528                 assignExpr->get_args().push_back( srcselect );
    529 
    530                 *out++ = new ExprStmt( noLabels, assignExpr );
    531         }
    532 
    533         template< typename OutputIterator >
    534         void makeArrayAssignment( ObjectDecl *srcParam, ObjectDecl *dstParam, DeclarationWithType *member, ArrayType *array, OutputIterator out ) {
    535                 static UniqueName indexName( "_index" );
    536 
    537                 // for a flexible array member nothing is done -- user must define own assignment
    538                 if ( ! array->get_dimension() ) return;
    539 
    540                 ObjectDecl *index = new ObjectDecl( indexName.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), 0 );
    541                 *out++ = new DeclStmt( noLabels, index );
    542 
    543                 UntypedExpr *init = new UntypedExpr( new NameExpr( "?=?" ) );
    544                 init->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
    545                 init->get_args().push_back( new NameExpr( "0" ) );
    546                 Statement *initStmt = new ExprStmt( noLabels, init );
    547                 std::list<Statement *> initList;
    548                 initList.push_back( initStmt );
    549 
    550                 UntypedExpr *cond = new UntypedExpr( new NameExpr( "?<?" ) );
    551                 cond->get_args().push_back( new VariableExpr( index ) );
    552                 cond->get_args().push_back( array->get_dimension()->clone() );
    553 
    554                 UntypedExpr *inc = new UntypedExpr( new NameExpr( "++?" ) );
    555                 inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
    556 
    557                 UntypedExpr *assignExpr = new UntypedExpr( new NameExpr( "?=?" ) );
    558 
    559                 UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
    560                 derefExpr->get_args().push_back( new VariableExpr( dstParam ) );
    561 
    562                 Expression *dstselect = new MemberExpr( member, derefExpr );
    563                 UntypedExpr *dstIndex = new UntypedExpr( new NameExpr( "?+?" ) );
    564                 dstIndex->get_args().push_back( dstselect );
    565                 dstIndex->get_args().push_back( new VariableExpr( index ) );
    566                 assignExpr->get_args().push_back( dstIndex );
    567 
    568                 Expression *srcselect = new MemberExpr( member, new VariableExpr( srcParam ) );
    569                 UntypedExpr *srcIndex = new UntypedExpr( new NameExpr( "?[?]" ) );
    570                 srcIndex->get_args().push_back( srcselect );
    571                 srcIndex->get_args().push_back( new VariableExpr( index ) );
    572                 assignExpr->get_args().push_back( srcIndex );
    573 
    574                 *out++ = new ForStmt( noLabels, initList, cond, inc, new ExprStmt( noLabels, assignExpr ) );
    575         }
    576 
    577         template< typename OutputIterator >
    578         void makeUnionFieldsAssignment( ObjectDecl *srcParam, ObjectDecl *dstParam, UnionInstType *unionType, OutputIterator out ) {
    579                 UntypedExpr *copy = new UntypedExpr( new NameExpr( "__builtin_memcpy" ) );
    580                 copy->get_args().push_back( new VariableExpr( dstParam ) );
    581                 copy->get_args().push_back( new AddressExpr( new VariableExpr( srcParam ) ) );
    582                 copy->get_args().push_back( new SizeofExpr( unionType ) );
    583 
    584                 *out++ = new ExprStmt( noLabels, copy );
    585         }
    586 
    587         //E ?=?(E volatile*, int),
    588         //  ?=?(E _Atomic volatile*, int);
    589         void makeEnumAssignment( EnumDecl *enumDecl, EnumInstType *refType, unsigned int functionNesting, std::list< Declaration * > &declsToAdd ) {
    590                 FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
    591 
    592                 ObjectDecl *returnVal = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, refType->clone(), 0 );
    593                 assignType->get_returnVals().push_back( returnVal );
    594 
    595                 // need two assignment operators with different types
    596                 FunctionType * assignType2 = assignType->clone();
    597 
    598                 // E ?=?(E volatile *, E)
    599                 Type *etype = refType->clone();
    600                 // etype->get_qualifiers() += Type::Qualifiers(false, true, false, false, false, false);
    601 
    602                 ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), etype ), 0 );
    603                 assignType->get_parameters().push_back( dstParam );
    604 
    605                 ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, etype->clone(), 0 );
    606                 assignType->get_parameters().push_back( srcParam );
    607 
    608                 // E ?=?(E volatile *, int)
    609                 assignType2->get_parameters().push_back( dstParam->clone() );
    610                 BasicType * paramType = new BasicType(Type::Qualifiers(), BasicType::SignedInt);
    611                 ObjectDecl *srcParam2 = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, paramType, 0 );
    612                 assignType2->get_parameters().push_back( srcParam2 );
    613 
    614                 // Routines at global scope marked "static" to prevent multiple definitions is separate translation units
    615                 // because each unit generates copies of the default routines for each aggregate.
    616 
    617                 // since there is no definition, these should not be inline
    618                 // make these intrinsic so that the code generator does not make use of them
    619                 FunctionDecl *assignDecl = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, assignType, 0, false, false );
    620                 assignDecl->fixUniqueId();
    621                 FunctionDecl *assignDecl2 = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, assignType2, 0, false, false );
    622                 assignDecl2->fixUniqueId();
    623 
    624                 // these should be built in the same way that the prelude
    625                 // functions are, so build a list containing the prototypes
    626                 // and allow MakeLibCfa to autogenerate the bodies.
    627                 std::list< Declaration * > assigns;
    628                 assigns.push_back( assignDecl );
    629                 assigns.push_back( assignDecl2 );
    630 
    631                 LibCfa::makeLibCfa( assigns );
    632 
    633                 // need to remove the prototypes, since this may be nested in a routine
    634                 for (int start = 0, end = assigns.size()/2; start < end; start++) {
    635                         delete assigns.front();
    636                         assigns.pop_front();
    637                 } // for
    638 
    639                 declsToAdd.insert( declsToAdd.begin(), assigns.begin(), assigns.end() );
    640         }
    641 
    642         /// Clones a reference type, replacing any parameters it may have with a clone of the provided list
    643         template< typename GenericInstType >
    644         GenericInstType *cloneWithParams( GenericInstType *refType, const std::list< Expression* >& params ) {
    645                 GenericInstType *clone = refType->clone();
    646                 clone->get_parameters().clear();
    647                 cloneAll( params, clone->get_parameters() );
    648                 return clone;
    649         }
    650 
    651         /// Creates a new type decl that's the same as src, but renamed and with only the ?=? assertion (for complete types only)
    652         TypeDecl *cloneAndRename( TypeDecl *src, const std::string &name ) {
    653                 TypeDecl *dst = new TypeDecl( name, src->get_storageClass(), 0, src->get_kind() );
    654 
    655                 if ( src->get_kind() == TypeDecl::Any ) {
    656                         // just include assignment operator assertion
    657                         TypeInstType *assignParamType = new TypeInstType( Type::Qualifiers(), name, dst );
    658                         FunctionType *assignFunctionType = new FunctionType( Type::Qualifiers(), false );
    659                         assignFunctionType->get_returnVals().push_back(
    660                                 new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, assignParamType->clone(), 0 ) );
    661                         assignFunctionType->get_parameters().push_back(
    662                                 new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), assignParamType->clone() ), 0 ) );
    663                         assignFunctionType->get_parameters().push_back(
    664                                 new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, assignParamType, 0 ) );
    665                         FunctionDecl *assignAssert = new FunctionDecl( "?=?", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, assignFunctionType, 0, false, false );
    666                         dst->get_assertions().push_back( assignAssert );
    667                 }
    668 
    669                 return dst;
    670         }
    671 
    672         Declaration *makeStructAssignment( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting ) {
    673                 FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
    674 
    675                 // Make function polymorphic in same parameters as generic struct, if applicable
    676                 bool isGeneric = false;  // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for union)
    677                 std::list< TypeDecl* >& genericParams = aggregateDecl->get_parameters();
    678                 std::list< Expression* > structParams;  // List of matching parameters to put on types
    679                 TypeSubstitution genericSubs; // Substitutions to make to member types of struct
    680                 for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) {
    681                         isGeneric = true;
    682                         TypeDecl *typeParam = cloneAndRename( *param, "_autoassign_" + aggregateDecl->get_name() + "_" + (*param)->get_name() );
    683                         assignType->get_forall().push_back( typeParam );
    684                         TypeInstType *newParamType = new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam );
    685                         genericSubs.add( (*param)->get_name(), newParamType );
    686                         structParams.push_back( new TypeExpr( newParamType ) );
    687                 }
    688 
    689                 ObjectDecl *returnVal = new ObjectDecl( "_ret", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, structParams ), 0 );
    690                 assignType->get_returnVals().push_back( returnVal );
    691 
    692                 ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), cloneWithParams( refType, structParams ) ), 0 );
    693                 assignType->get_parameters().push_back( dstParam );
    694 
    695                 ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, structParams ), 0 );
    696                 assignType->get_parameters().push_back( srcParam );
    697 
    698                 // Routines at global scope marked "static" to prevent multiple definitions is separate translation units
    699                 // because each unit generates copies of the default routines for each aggregate.
    700                 FunctionDecl *assignDecl = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, assignType, new CompoundStmt( noLabels ), true, false );
    701                 assignDecl->fixUniqueId();
    702 
    703                 for ( std::list< Declaration * >::const_iterator member = aggregateDecl->get_members().begin(); member != aggregateDecl->get_members().end(); ++member ) {
    704                         if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member ) ) {
    705                                 // query the type qualifiers of this field and skip assigning it if it is marked const.
    706                                 // If it is an array type, we need to strip off the array layers to find its qualifiers.
    707                                 Type * type = dwt->get_type();
    708                                 while ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
    709                                         type = at->get_base();
    710                                 }
    711 
    712                                 if ( type->get_qualifiers().isConst ) {
    713                                         // don't assign const members
    714                                         continue;
    715                                 }
    716 
    717                                 if ( isGeneric ) {
    718                                         // rewrite member type in terms of the type variables on this operator
    719                                         DeclarationWithType *fixedMember = dwt->clone();
    720                                         genericSubs.apply( fixedMember );
    721 
    722                                         // assign to both destination and return value
    723                                         if ( ArrayType *array = dynamic_cast< ArrayType * >( fixedMember->get_type() ) ) {
    724                                                 makeArrayAssignment( srcParam, dstParam, fixedMember, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
    725                                                 makeArrayAssignment( srcParam, returnVal, fixedMember, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
    726                                         } else {
    727                                                 makeScalarAssignment( srcParam, dstParam, fixedMember, back_inserter( assignDecl->get_statements()->get_kids() ) );
    728                                                 makeScalarAssignment( srcParam, returnVal, fixedMember, back_inserter( assignDecl->get_statements()->get_kids() ) );
    729                                         } // if
    730                                 } else {
    731                                         // assign to destination
    732                                         if ( ArrayType *array = dynamic_cast< ArrayType * >( dwt->get_type() ) ) {
    733                                                 makeArrayAssignment( srcParam, dstParam, dwt, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
    734                                         } else {
    735                                                 makeScalarAssignment( srcParam, dstParam, dwt, back_inserter( assignDecl->get_statements()->get_kids() ) );
    736                                         } // if
    737                                 } // if
    738                         } // if
    739                 } // for
    740                 if ( ! isGeneric ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
    741 
    742                 return assignDecl;
    743         }
    744 
    745         Declaration *makeUnionAssignment( UnionDecl *aggregateDecl, UnionInstType *refType, unsigned int functionNesting ) {
    746                 FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
    747 
    748                 // Make function polymorphic in same parameters as generic union, if applicable
    749                 bool isGeneric = false;  // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for struct)
    750                 std::list< TypeDecl* >& genericParams = aggregateDecl->get_parameters();
    751                 std::list< Expression* > unionParams;  // List of matching parameters to put on types
    752                 for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) {
    753                         isGeneric = true;
    754                         TypeDecl *typeParam = cloneAndRename( *param, "_autoassign_" + aggregateDecl->get_name() + "_" + (*param)->get_name() );
    755                         assignType->get_forall().push_back( typeParam );
    756                         unionParams.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam ) ) );
    757                 }
    758 
    759                 ObjectDecl *returnVal = new ObjectDecl( "_ret", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, unionParams ), 0 );
    760                 assignType->get_returnVals().push_back( returnVal );
    761 
    762                 ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), cloneWithParams( refType, unionParams ) ), 0 );
    763                 assignType->get_parameters().push_back( dstParam );
    764 
    765                 ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, unionParams ), 0 );
    766                 assignType->get_parameters().push_back( srcParam );
    767 
    768                 // Routines at global scope marked "static" to prevent multiple definitions is separate translation units
    769                 // because each unit generates copies of the default routines for each aggregate.
    770                 FunctionDecl *assignDecl = new FunctionDecl( "?=?",  functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, assignType, new CompoundStmt( noLabels ), true, false );
    771                 assignDecl->fixUniqueId();
    772 
    773                 makeUnionFieldsAssignment( srcParam, dstParam, cloneWithParams( refType, unionParams ), back_inserter( assignDecl->get_statements()->get_kids() ) );
    774                 if ( isGeneric ) makeUnionFieldsAssignment( srcParam, returnVal, cloneWithParams( refType, unionParams ), back_inserter( assignDecl->get_statements()->get_kids() ) );
    775                
    776                 if ( ! isGeneric ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
    777 
    778                 return assignDecl;
    779         }
    780 
    781         void AutogenerateRoutines::visit( EnumDecl *enumDecl ) {
    782                 if ( ! enumDecl->get_members().empty() ) {
    783                         EnumInstType *enumInst = new EnumInstType( Type::Qualifiers(), enumDecl->get_name() );
    784                         // enumInst->set_baseEnum( enumDecl );
    785                         // declsToAdd.push_back(
    786                         makeEnumAssignment( enumDecl, enumInst, functionNesting, declsToAdd );
    787                 }
    788         }
    789 
    790         void AutogenerateRoutines::visit( StructDecl *structDecl ) {
    791                 if ( ! structDecl->get_members().empty() && structsDone.find( structDecl->get_name() ) == structsDone.end() ) {
    792                         StructInstType structInst( Type::Qualifiers(), structDecl->get_name() );
    793                         structInst.set_baseStruct( structDecl );
    794                         declsToAdd.push_back( makeStructAssignment( structDecl, &structInst, functionNesting ) );
    795                         structsDone.insert( structDecl->get_name() );
    796                 } // if
    797         }
    798 
    799         void AutogenerateRoutines::visit( UnionDecl *unionDecl ) {
    800                 if ( ! unionDecl->get_members().empty() ) {
    801                         UnionInstType unionInst( Type::Qualifiers(), unionDecl->get_name() );
    802                         unionInst.set_baseUnion( unionDecl );
    803                         declsToAdd.push_back( makeUnionAssignment( unionDecl, &unionInst, functionNesting ) );
    804                 } // if
    805         }
    806 
    807         void AutogenerateRoutines::visit( TypeDecl *typeDecl ) {
    808                 CompoundStmt *stmts = 0;
    809                 TypeInstType *typeInst = new TypeInstType( Type::Qualifiers(), typeDecl->get_name(), false );
    810                 typeInst->set_baseType( typeDecl );
    811                 ObjectDecl *src = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, typeInst->clone(), 0 );
    812                 ObjectDecl *dst = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), typeInst->clone() ), 0 );
    813                 if ( typeDecl->get_base() ) {
    814                         stmts = new CompoundStmt( std::list< Label >() );
    815                         UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) );
    816                         assign->get_args().push_back( new CastExpr( new VariableExpr( dst ), new PointerType( Type::Qualifiers(), typeDecl->get_base()->clone() ) ) );
    817                         assign->get_args().push_back( new CastExpr( new VariableExpr( src ), typeDecl->get_base()->clone() ) );
    818                         stmts->get_kids().push_back( new ReturnStmt( std::list< Label >(), assign ) );
    819                 } // if
    820                 FunctionType *type = new FunctionType( Type::Qualifiers(), false );
    821                 type->get_returnVals().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, typeInst, 0 ) );
    822                 type->get_parameters().push_back( dst );
    823                 type->get_parameters().push_back( src );
    824                 FunctionDecl *func = new FunctionDecl( "?=?", DeclarationNode::NoStorageClass, LinkageSpec::AutoGen, type, stmts, false, false );
    825                 declsToAdd.push_back( func );
    826         }
    827 
    828         void addDecls( std::list< Declaration * > &declsToAdd, std::list< Statement * > &statements, std::list< Statement * >::iterator i ) {
    829                 for ( std::list< Declaration * >::iterator decl = declsToAdd.begin(); decl != declsToAdd.end(); ++decl ) {
    830                         statements.insert( i, new DeclStmt( noLabels, *decl ) );
    831                 } // for
    832                 declsToAdd.clear();
    833         }
    834 
    835         void AutogenerateRoutines::visit( FunctionType *) {
    836                 // ensure that we don't add assignment ops for types defined as part of the function
    837         }
    838 
    839         void AutogenerateRoutines::visit( PointerType *) {
    840                 // ensure that we don't add assignment ops for types defined as part of the pointer
    841         }
    842 
    843         void AutogenerateRoutines::visit( TraitDecl *) {
    844                 // ensure that we don't add assignment ops for types defined as part of the context
    845         }
    846 
    847         template< typename StmtClass >
    848         inline void AutogenerateRoutines::visitStatement( StmtClass *stmt ) {
    849                 std::set< std::string > oldStructs = structsDone;
    850                 addVisit( stmt, *this );
    851                 structsDone = oldStructs;
    852         }
    853 
    854         void AutogenerateRoutines::visit( FunctionDecl *functionDecl ) {
    855                 maybeAccept( functionDecl->get_functionType(), *this );
    856                 acceptAll( functionDecl->get_oldDecls(), *this );
    857                 functionNesting += 1;
    858                 maybeAccept( functionDecl->get_statements(), *this );
    859                 functionNesting -= 1;
    860         }
    861 
    862         void AutogenerateRoutines::visit( CompoundStmt *compoundStmt ) {
    863                 visitStatement( compoundStmt );
    864         }
    865 
    866         void AutogenerateRoutines::visit( SwitchStmt *switchStmt ) {
    867                 visitStatement( switchStmt );
    868         }
    869 
    870         void AutogenerateRoutines::visit( ChooseStmt *switchStmt ) {
    871                 visitStatement( switchStmt );
    872         }
    873 
    874         // void AutogenerateRoutines::visit( CaseStmt *caseStmt ) {
    875         //      visitStatement( caseStmt );
    876         // }
    877 
    878472        void ReturnChecker::checkFunctionReturns( std::list< Declaration * > & translationUnit ) {
    879473                ReturnChecker checker;
     
    889483
    890484        void ReturnChecker::visit( ReturnStmt * returnStmt ) {
     485                // Previously this also checked for the existence of an expr paired with no return values on
     486                // the  function return type. This is incorrect, since you can have an expression attached to
     487                // a return statement in a void-returning function in C. The expression is treated as if it
     488                // were cast to void.
    891489                if ( returnStmt->get_expr() == NULL && returnVals.size() != 0 ) {
    892490                        throw SemanticError( "Non-void function returns no values: " , returnStmt );
    893                 } else if ( returnStmt->get_expr() != NULL && returnVals.size() == 0 ) {
    894                         throw SemanticError( "void function returns values: " , returnStmt );
    895491                }
    896492        }
     
    1033629                return aggDecl;
    1034630        }
    1035        
     631
    1036632        template<typename AggDecl>
    1037633        void EliminateTypedef::addImplicitTypedef( AggDecl * aggDecl ) {
     
    1072668        }
    1073669
     670        void VerifyCtorDtor::verify( std::list< Declaration * > & translationUnit ) {
     671                VerifyCtorDtor verifier;
     672                acceptAll( translationUnit, verifier );
     673        }
     674
     675        void VerifyCtorDtor::visit( FunctionDecl * funcDecl ) {
     676                FunctionType * funcType = funcDecl->get_functionType();
     677                std::list< DeclarationWithType * > &returnVals = funcType->get_returnVals();
     678                std::list< DeclarationWithType * > &params = funcType->get_parameters();
     679
     680                if ( funcDecl->get_name() == "?{}" || funcDecl->get_name() == "^?{}" ) {
     681                        if ( params.size() == 0 ) {
     682                                throw SemanticError( "Constructors and destructors require at least one parameter ", funcDecl );
     683                        }
     684                        if ( ! dynamic_cast< PointerType * >( params.front()->get_type() ) ) {
     685                                throw SemanticError( "First parameter of a constructor or destructor must be a pointer ", funcDecl );
     686                        }
     687                        if ( returnVals.size() != 0 ) {
     688                                throw SemanticError( "Constructors and destructors cannot have explicit return values ", funcDecl );
     689                        }
     690                }
     691
     692                Visitor::visit( funcDecl );
     693                // original idea: modify signature of ctor/dtors and insert appropriate return statements
     694                // to cause desired behaviour
     695                // new idea: add comma exprs to every ctor call to produce first parameter.
     696                // this requires some memoization of the first parameter, because it can be a
     697                // complicated expression with side effects (see: malloc). idea: add temporary variable
     698                // that is assigned address of constructed object in ctor argument position and
     699                // return the temporary. It should also be done after all implicit ctors are
     700                // added, so not in this pass!
     701        }
     702
    1074703        DeclarationWithType * CompoundLiteral::mutate( ObjectDecl *objectDecl ) {
    1075704                storageclass = objectDecl->get_storageClass();
Note: See TracChangeset for help on using the changeset viewer.