Changes in src/SymTab/Validate.cc [74d1804:b644d6f]
- File:
-
- 1 edited
-
src/SymTab/Validate.cc (modified) (16 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/SymTab/Validate.cc
r74d1804 rb644d6f 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 : Wed May 11 13:17:52201613 // Update Count : 2 9711 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Apr 13 16:39:30 2016 13 // Update Count : 251 14 14 // 15 15 … … 56 56 #include "MakeLibCfa.h" 57 57 #include "TypeEquality.h" 58 #include "Autogen.h"59 58 #include "ResolvExpr/typeops.h" 60 59 … … 123 122 124 123 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 125 155 }; 126 156 … … 162 192 template<typename AggDecl> 163 193 void addImplicitTypedef( AggDecl * aggDecl ); 164 194 165 195 typedef std::map< std::string, std::pair< TypedefDecl *, int > > TypedefMap; 166 196 TypedefMap typedefNames; 167 197 int scopeLevel; 168 198 }; 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 virtual void visit( FunctionDecl *funcDecl );178 };179 199 180 200 class CompoundLiteral : public GenPoly::DeclMutator { … … 197 217 ReturnChecker::checkFunctionReturns( translationUnit ); 198 218 mutateAll( translationUnit, compoundliteral ); 199 autogenerateRoutines( translationUnit );219 AutogenerateRoutines::autogenerateRoutines( translationUnit ); 200 220 acceptAll( translationUnit, pass3 ); 201 VerifyCtorDtor::verify( translationUnit );202 221 } 203 222 … … 209 228 type->accept( pass2 ); 210 229 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 211 244 } 212 245 … … 279 312 void Pass1::visit( EnumDecl *enumDecl ) { 280 313 // Set the type of each member of the enumeration to be EnumConstant 314 281 315 for ( std::list< Declaration * >::iterator i = enumDecl->get_members().begin(); i != enumDecl->get_members().end(); ++i ) { 282 316 ObjectDecl * obj = dynamic_cast< ObjectDecl * >( *i ); 283 317 assert( obj ); 284 obj->set_type( new EnumInstType( Type::Qualifiers( true, false, false, false, false, false ), enumDecl->get_name() ) ); 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 ) ; 285 321 } // for 286 322 Parent::visit( enumDecl ); … … 288 324 289 325 namespace { 290 template< typename DWT List>291 void fixFunctionList( DWT List & dwts, FunctionType *func ) {326 template< typename DWTIterator > 327 void fixFunctionList( DWTIterator begin, DWTIterator end, FunctionType *func ) { 292 328 // the only case in which "void" is valid is where it is the only one in the list; then it should be removed 293 329 // entirely other fix ups are handled by the FixFunction class 294 typedef typename DWTList::iterator DWTIterator;295 DWTIterator begin( dwts.begin() ), end( dwts.end() );296 330 if ( begin == end ) return; 297 331 FixFunction fixer; 298 332 DWTIterator i = begin; 299 *i = (*i )->acceptMutator( fixer );333 *i = (*i )->acceptMutator( fixer ); 300 334 if ( fixer.get_isVoid() ) { 301 335 DWTIterator j = i; 302 336 ++i; 303 dwts.erase( j );337 func->get_parameters().erase( j ); 304 338 if ( i != end ) { 305 339 throw SemanticError( "invalid type void in function type ", func ); … … 320 354 void Pass1::visit( FunctionType *func ) { 321 355 // Fix up parameters and return types 322 fixFunctionList( func->get_parameters() , func );323 fixFunctionList( func->get_returnVals() , func );356 fixFunctionList( func->get_parameters().begin(), func->get_parameters().end(), func ); 357 fixFunctionList( func->get_returnVals().begin(), func->get_returnVals().end(), func ); 324 358 Visitor::visit( func ); 325 359 } … … 384 418 385 419 void Pass2::visit( StructDecl *structDecl ) { 386 // visit struct members first so that the types of self-referencing members are updated properly387 Parent::visit( structDecl );388 420 if ( ! structDecl->get_members().empty() ) { 389 421 ForwardStructsType::iterator fwds = forwardStructs.find( structDecl->get_name() ); … … 395 427 } // if 396 428 } // if 429 Indexer::visit( structDecl ); 397 430 } 398 431 399 432 void Pass2::visit( UnionDecl *unionDecl ) { 400 Parent::visit( unionDecl );401 433 if ( ! unionDecl->get_members().empty() ) { 402 434 ForwardUnionsType::iterator fwds = forwardUnions.find( unionDecl->get_name() ); … … 408 440 } // if 409 441 } // if 442 Indexer::visit( unionDecl ); 410 443 } 411 444 … … 470 503 } 471 504 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 472 878 void ReturnChecker::checkFunctionReturns( std::list< Declaration * > & translationUnit ) { 473 879 ReturnChecker checker; … … 483 889 484 890 void ReturnChecker::visit( ReturnStmt * returnStmt ) { 485 // Previously this also checked for the existence of an expr paired with no return values on486 // the function return type. This is incorrect, since you can have an expression attached to487 // a return statement in a void-returning function in C. The expression is treated as if it488 // were cast to void.489 891 if ( returnStmt->get_expr() == NULL && returnVals.size() != 0 ) { 490 892 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 ); 491 895 } 492 896 } … … 629 1033 return aggDecl; 630 1034 } 631 1035 632 1036 template<typename AggDecl> 633 1037 void EliminateTypedef::addImplicitTypedef( AggDecl * aggDecl ) { … … 668 1072 } 669 1073 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 * > ¶ms = 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 statements694 // to cause desired behaviour695 // 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 a697 // complicated expression with side effects (see: malloc). idea: add temporary variable698 // that is assigned address of constructed object in ctor argument position and699 // return the temporary. It should also be done after all implicit ctors are700 // added, so not in this pass!701 }702 703 1074 DeclarationWithType * CompoundLiteral::mutate( ObjectDecl *objectDecl ) { 704 1075 storageclass = objectDecl->get_storageClass();
Note:
See TracChangeset
for help on using the changeset viewer.