Changes in src/SymTab/Validate.cc [620cb95:4040425]
- File:
-
- 1 edited
-
src/SymTab/Validate.cc (modified) (13 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/SymTab/Validate.cc
r620cb95 r4040425 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 21:50:04 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Mon Feb 22 12:26:37201613 // Update Count : 2 9711 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Mar 2 17:31:39 2016 13 // Update Count : 226 14 14 // 15 15 … … 54 54 #include "MakeLibCfa.h" 55 55 #include "TypeEquality.h" 56 #include "Autogen.h"57 56 #include "ResolvExpr/typeops.h" 58 57 … … 102 101 virtual void visit( StructInstType *structInst ); 103 102 virtual void visit( UnionInstType *unionInst ); 104 virtual void visit( ContextInstType *contextInst );103 virtual void visit( TraitInstType *contextInst ); 105 104 virtual void visit( StructDecl *structDecl ); 106 105 virtual void visit( UnionDecl *unionDecl ); … … 125 124 126 125 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 127 161 }; 128 162 … … 158 192 virtual Declaration *mutate( UnionDecl * unionDecl ); 159 193 virtual Declaration *mutate( EnumDecl * enumDecl ); 160 virtual Declaration *mutate( ContextDecl * contextDecl );194 virtual Declaration *mutate( TraitDecl * contextDecl ); 161 195 162 196 template<typename AggDecl> … … 166 200 TypedefMap typedefNames; 167 201 int scopeLevel; 168 };169 170 class VerifyCtorDtor : public Visitor {171 public:172 /// ensure that constructors and destructors have at least one173 /// parameter, the first of which must be a pointer, and no174 /// return values.175 static void verify( std::list< Declaration * > &translationUnit );176 177 // VerifyCtorDtor() {}178 179 virtual void visit( FunctionDecl *funcDecl );180 private:181 202 }; 182 203 … … 190 211 acceptAll( translationUnit, pass2 ); 191 212 ReturnChecker::checkFunctionReturns( translationUnit ); 192 autogenerateRoutines( translationUnit );213 AutogenerateRoutines::autogenerateRoutines( translationUnit ); 193 214 acceptAll( translationUnit, pass3 ); 194 VerifyCtorDtor::verify( translationUnit );195 215 } 196 216 … … 202 222 type->accept( pass2 ); 203 223 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 204 238 } 205 239 … … 370 404 } 371 405 372 void Pass2::visit( ContextInstType *contextInst ) {406 void Pass2::visit( TraitInstType *contextInst ) { 373 407 Parent::visit( contextInst ); 374 ContextDecl *ctx = indexer->lookupContext( contextInst->get_name() );408 TraitDecl *ctx = indexer->lookupTrait( contextInst->get_name() ); 375 409 if ( ! ctx ) { 376 410 throw SemanticError( "use of undeclared context " + contextInst->get_name() ); … … 378 412 for ( std::list< TypeDecl * >::const_iterator i = ctx->get_parameters().begin(); i != ctx->get_parameters().end(); ++i ) { 379 413 for ( std::list< DeclarationWithType * >::const_iterator assert = (*i )->get_assertions().begin(); assert != (*i )->get_assertions().end(); ++assert ) { 380 if ( ContextInstType *otherCtx = dynamic_cast< ContextInstType * >(*assert ) ) {414 if ( TraitInstType *otherCtx = dynamic_cast< TraitInstType * >(*assert ) ) { 381 415 cloneAll( otherCtx->get_members(), contextInst->get_members() ); 382 416 } else { … … 442 476 while ( ! toBeDone.empty() ) { 443 477 for ( std::list< DeclarationWithType * >::iterator assertion = toBeDone.begin(); assertion != toBeDone.end(); ++assertion ) { 444 if ( ContextInstType *ctx = dynamic_cast< ContextInstType * >( (*assertion )->get_type() ) ) {478 if ( TraitInstType *ctx = dynamic_cast< TraitInstType * >( (*assertion )->get_type() ) ) { 445 479 for ( std::list< Declaration * >::const_iterator i = ctx->get_members().begin(); i != ctx->get_members().end(); ++i ) { 446 480 DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *i ); … … 479 513 } 480 514 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 481 904 void ReturnChecker::checkFunctionReturns( std::list< Declaration * > & translationUnit ) { 482 905 ReturnChecker checker; … … 652 1075 } 653 1076 654 Declaration *EliminateTypedef::mutate( ContextDecl * contextDecl ) {1077 Declaration *EliminateTypedef::mutate( TraitDecl * contextDecl ) { 655 1078 Mutator::mutate( contextDecl ); 656 1079 return handleAggregate( contextDecl ); 657 1080 } 658 1081 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 statements683 // to cause desired behaviour684 // 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 a686 // complicated expression with side effects (see: malloc). idea: add temporary variable687 // that is assigned address of constructed object in ctor argument position and688 // return the temporary. It should also be done after all implicit ctors are689 // added, so not in this pass!690 }691 1082 } // namespace SymTab 692 1083
Note:
See TracChangeset
for help on using the changeset viewer.