Changes in src/SymTab/Validate.cc [4040425:620cb95]
- File:
-
- 1 edited
-
src/SymTab/Validate.cc (modified) (13 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/SymTab/Validate.cc
r4040425 r620cb95 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 21:50:04 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Wed Mar 2 17:31:39201613 // Update Count : 2 2611 // Last Modified By : Rob Schluntz 12 // Last Modified On : Mon Feb 22 12:26:37 2016 13 // Update Count : 297 14 14 // 15 15 … … 54 54 #include "MakeLibCfa.h" 55 55 #include "TypeEquality.h" 56 #include "Autogen.h" 56 57 #include "ResolvExpr/typeops.h" 57 58 … … 101 102 virtual void visit( StructInstType *structInst ); 102 103 virtual void visit( UnionInstType *unionInst ); 103 virtual void visit( TraitInstType *contextInst );104 virtual void visit( ContextInstType *contextInst ); 104 105 virtual void visit( StructDecl *structDecl ); 105 106 virtual void visit( UnionDecl *unionDecl ); … … 124 125 125 126 const Indexer *indexer; 126 };127 128 class AutogenerateRoutines : public Visitor {129 public:130 /// Generates assignment operators for aggregate types as required131 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 functions161 127 }; 162 128 … … 192 158 virtual Declaration *mutate( UnionDecl * unionDecl ); 193 159 virtual Declaration *mutate( EnumDecl * enumDecl ); 194 virtual Declaration *mutate( TraitDecl * contextDecl );160 virtual Declaration *mutate( ContextDecl * contextDecl ); 195 161 196 162 template<typename AggDecl> … … 200 166 TypedefMap typedefNames; 201 167 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: 202 181 }; 203 182 … … 211 190 acceptAll( translationUnit, pass2 ); 212 191 ReturnChecker::checkFunctionReturns( translationUnit ); 213 AutogenerateRoutines::autogenerateRoutines( translationUnit );192 autogenerateRoutines( translationUnit ); 214 193 acceptAll( translationUnit, pass3 ); 194 VerifyCtorDtor::verify( translationUnit ); 215 195 } 216 196 … … 222 202 type->accept( pass2 ); 223 203 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 } // if236 i = next;237 } // while238 204 } 239 205 … … 404 370 } 405 371 406 void Pass2::visit( TraitInstType *contextInst ) {372 void Pass2::visit( ContextInstType *contextInst ) { 407 373 Parent::visit( contextInst ); 408 TraitDecl *ctx = indexer->lookupTrait( contextInst->get_name() );374 ContextDecl *ctx = indexer->lookupContext( contextInst->get_name() ); 409 375 if ( ! ctx ) { 410 376 throw SemanticError( "use of undeclared context " + contextInst->get_name() ); … … 412 378 for ( std::list< TypeDecl * >::const_iterator i = ctx->get_parameters().begin(); i != ctx->get_parameters().end(); ++i ) { 413 379 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 ) ) { 415 381 cloneAll( otherCtx->get_members(), contextInst->get_members() ); 416 382 } else { … … 476 442 while ( ! toBeDone.empty() ) { 477 443 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() ) ) { 479 445 for ( std::list< Declaration * >::const_iterator i = ctx->get_members().begin(); i != ctx->get_members().end(); ++i ) { 480 446 DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *i ); … … 513 479 } 514 480 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 accessed526 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 members534 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 assignment548 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 types606 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 units625 // because each unit generates copies of the default routines for each aggregate.626 627 // since there is no definition, these should not be inline628 // make these intrinsic so that the code generator does not make use of them629 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 prelude635 // functions are, so build a list containing the prototypes636 // 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 routine644 for (int start = 0, end = assigns.size()/2; start < end; start++) {645 delete assigns.front();646 assigns.pop_front();647 } // for648 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 list653 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 assertion667 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 applicable686 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 types689 TypeSubstitution genericSubs; // Substitutions to make to member types of struct690 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 units709 // 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 members724 continue;725 }726 727 if ( isGeneric ) {728 // rewrite member type in terms of the type variables on this operator729 DeclarationWithType *fixedMember = dwt->clone();730 genericSubs.apply( fixedMember );731 732 // assign to both destination and return value733 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 } // if740 } else {741 // assign to destination742 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 } // if747 } // if748 } // if749 } // for750 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 applicable759 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 types762 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 units779 // 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 } // if807 }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 } // if815 }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 } // if830 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 } // for842 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 function847 }848 849 void AutogenerateRoutines::visit( PointerType *) {850 // ensure that we don't add assignment ops for types defined as part of the pointer851 }852 853 void AutogenerateRoutines::visit( TraitDecl *) {854 // ensure that we don't add assignment ops for types defined as part of the context855 }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 904 481 void ReturnChecker::checkFunctionReturns( std::list< Declaration * > & translationUnit ) { 905 482 ReturnChecker checker; … … 1075 652 } 1076 653 1077 Declaration *EliminateTypedef::mutate( TraitDecl * contextDecl ) {654 Declaration *EliminateTypedef::mutate( ContextDecl * contextDecl ) { 1078 655 Mutator::mutate( contextDecl ); 1079 656 return handleAggregate( contextDecl ); 1080 657 } 1081 658 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 * > ¶ms = 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 } 1082 691 } // namespace SymTab 1083 692
Note:
See TracChangeset
for help on using the changeset viewer.