Changes in src/SymTab/Validate.cc [98735ef:a9a259c]
- File:
-
- 1 edited
-
src/SymTab/Validate.cc (modified) (14 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/SymTab/Validate.cc
r98735ef ra9a259c 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 Jan 27 22:03:12201613 // Update Count : 2 2511 // Last Modified By : Rob Schluntz 12 // Last Modified On : Mon Feb 22 12:26:37 2016 13 // Update Count : 297 14 14 // 15 15 … … 202 202 }; 203 203 204 class VerifyCtorDtor : public Visitor { 205 public: 206 /// ensure that constructors and destructors have at least one 207 /// parameter, the first of which must be a pointer, and no 208 /// return values. 209 static void verify( std::list< Declaration * > &translationUnit ); 210 211 // VerifyCtorDtor() {} 212 213 virtual void visit( FunctionDecl *funcDecl ); 214 private: 215 }; 216 204 217 void validate( std::list< Declaration * > &translationUnit, bool doDebug ) { 205 218 Pass1 pass1; … … 213 226 AutogenerateRoutines::autogenerateRoutines( translationUnit ); 214 227 acceptAll( translationUnit, pass3 ); 228 VerifyCtorDtor::verify( translationUnit ); 215 229 } 216 230 … … 521 535 522 536 template< typename OutputIterator > 523 void makeScalar Assignment( ObjectDecl *srcParam, ObjectDecl *dstParam, DeclarationWithType *member, OutputIterator out ) {537 void makeScalarFunction( ObjectDecl *srcParam, ObjectDecl *dstParam, DeclarationWithType *member, std::string fname, OutputIterator out ) { 524 538 ObjectDecl *obj = dynamic_cast<ObjectDecl *>( member ); 525 539 // unnamed bit fields are not copied as they cannot be accessed 526 540 if ( obj != NULL && obj->get_name() == "" && obj->get_bitfieldWidth() != NULL ) return; 527 541 528 UntypedExpr *assignExpr = new UntypedExpr( new NameExpr( "?=?" ) ); 542 // want to be able to generate assignment, ctor, and dtor generically, 543 // so fname is either ?=?, ?{}, or ^?{} 544 UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) ); 529 545 530 546 UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) ); … … 533 549 // do something special for unnamed members 534 550 Expression *dstselect = new AddressExpr( new MemberExpr( member, derefExpr ) ); 535 assignExpr->get_args().push_back( dstselect );551 fExpr->get_args().push_back( dstselect ); 536 552 537 553 Expression *srcselect = new MemberExpr( member, new VariableExpr( srcParam ) ); 538 assignExpr->get_args().push_back( srcselect );539 540 *out++ = new ExprStmt( noLabels, assignExpr );554 fExpr->get_args().push_back( srcselect ); 555 556 *out++ = new ExprStmt( noLabels, fExpr ); 541 557 } 542 558 543 559 template< typename OutputIterator > 544 void makeArray Assignment( ObjectDecl *srcParam, ObjectDecl *dstParam, DeclarationWithType *member, ArrayType *array, OutputIterator out ) {560 void makeArrayFunction( ObjectDecl *srcParam, ObjectDecl *dstParam, DeclarationWithType *member, ArrayType *array, std::string fname, OutputIterator out ) { 545 561 static UniqueName indexName( "_index" ); 546 562 … … 565 581 inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) ); 566 582 567 UntypedExpr *assignExpr = new UntypedExpr( new NameExpr( "?=?" ) ); 583 // want to be able to generate assignment, ctor, and dtor generically, 584 // so fname is either ?=?, ?{}, or ^?{} 585 UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) ); 568 586 569 587 UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) ); … … 574 592 dstIndex->get_args().push_back( dstselect ); 575 593 dstIndex->get_args().push_back( new VariableExpr( index ) ); 576 assignExpr->get_args().push_back( dstIndex );594 fExpr->get_args().push_back( dstIndex ); 577 595 578 596 Expression *srcselect = new MemberExpr( member, new VariableExpr( srcParam ) ); … … 580 598 srcIndex->get_args().push_back( srcselect ); 581 599 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 ) );600 fExpr->get_args().push_back( srcIndex ); 601 602 *out++ = new ForStmt( noLabels, initList, cond, inc, new ExprStmt( noLabels, fExpr ) ); 585 603 } 586 604 … … 732 750 // assign to both destination and return value 733 751 if ( ArrayType *array = dynamic_cast< ArrayType * >( fixedMember->get_type() ) ) { 734 makeArray Assignment( srcParam, dstParam, fixedMember, array, back_inserter( assignDecl->get_statements()->get_kids() ) );735 makeArray Assignment( srcParam, returnVal, fixedMember, array, back_inserter( assignDecl->get_statements()->get_kids() ) );752 makeArrayFunction( srcParam, dstParam, fixedMember, array, "?=?", back_inserter( assignDecl->get_statements()->get_kids() ) ); 753 makeArrayFunction( srcParam, returnVal, fixedMember, array, "?=?", back_inserter( assignDecl->get_statements()->get_kids() ) ); 736 754 } else { 737 makeScalar Assignment( srcParam, dstParam, fixedMember, back_inserter( assignDecl->get_statements()->get_kids() ) );738 makeScalar Assignment( srcParam, returnVal, fixedMember, back_inserter( assignDecl->get_statements()->get_kids() ) );755 makeScalarFunction( srcParam, dstParam, fixedMember, "?=?", back_inserter( assignDecl->get_statements()->get_kids() ) ); 756 makeScalarFunction( srcParam, returnVal, fixedMember, "?=?", back_inserter( assignDecl->get_statements()->get_kids() ) ); 739 757 } // if 740 758 } else { 741 759 // assign to destination 742 760 if ( ArrayType *array = dynamic_cast< ArrayType * >( dwt->get_type() ) ) { 743 makeArray Assignment( srcParam, dstParam, dwt, array, back_inserter( assignDecl->get_statements()->get_kids() ) );761 makeArrayFunction( srcParam, dstParam, dwt, array, "?=?", back_inserter( assignDecl->get_statements()->get_kids() ) ); 744 762 } else { 745 makeScalar Assignment( srcParam, dstParam, dwt, back_inserter( assignDecl->get_statements()->get_kids() ) );763 makeScalarFunction( srcParam, dstParam, dwt, "?=?", back_inserter( assignDecl->get_statements()->get_kids() ) ); 746 764 } // if 747 765 } // if … … 753 771 } 754 772 755 Declaration *makeUnionAssignment( UnionDecl *aggregateDecl, UnionInstType *refType, unsigned int functionNesting ) { 773 void makeStructCtorDtor( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd ) { 774 FunctionType *ctorType = new FunctionType( Type::Qualifiers(), false ); 775 776 // Make function polymorphic in same parameters as generic struct, if applicable 777 bool isGeneric = false; // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for union) 778 std::list< TypeDecl* >& genericParams = aggregateDecl->get_parameters(); 779 std::list< Expression* > structParams; // List of matching parameters to put on types 780 for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) { 781 isGeneric = true; 782 TypeDecl *typeParam = (*param)->clone(); 783 ctorType->get_forall().push_back( typeParam ); 784 structParams.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam ) ) ); 785 } 786 787 ObjectDecl *thisParam = new ObjectDecl( "_this", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), cloneWithParams( refType, structParams ) ), 0 ); 788 ctorType->get_parameters().push_back( thisParam ); 789 790 // Routines at global scope marked "static" to prevent multiple definitions is separate translation units 791 // because each unit generates copies of the default routines for each aggregate. 792 FunctionDecl *ctorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, ctorType, 0, true, false ); 793 FunctionDecl *copyCtorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, ctorType->clone(), 0, true, false ); 794 FunctionDecl *dtorDecl = new FunctionDecl( "^?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, ctorType->clone(), 0, true, false ); 795 ctorDecl->fixUniqueId(); 796 copyCtorDecl->fixUniqueId(); 797 dtorDecl->fixUniqueId(); 798 799 // add definitions 800 // TODO: add in calls to default constructors and destructors for fields 801 ctorDecl->set_statements( new CompoundStmt( noLabels ) ); 802 copyCtorDecl->set_statements( new CompoundStmt( noLabels ) ); 803 dtorDecl->set_statements( new CompoundStmt( noLabels ) ); 804 declsToAdd.push_back( ctorDecl ); 805 declsToAdd.push_back( copyCtorDecl ); 806 declsToAdd.push_back( dtorDecl ); 807 808 ObjectDecl * srcParam = new ObjectDecl( "_other", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, structParams ), 0 ); 809 copyCtorDecl->get_functionType()->get_parameters().push_back( srcParam ); 810 for ( std::list< Declaration * >::const_iterator member = aggregateDecl->get_members().begin(); member != aggregateDecl->get_members().end(); ++member ) { 811 if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member ) ) { 812 // query the type qualifiers of this field and skip assigning it if it is marked const. 813 // If it is an array type, we need to strip off the array layers to find its qualifiers. 814 Type * type = dwt->get_type(); 815 while ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) { 816 type = at->get_base(); 817 } 818 819 if ( type->get_qualifiers().isConst ) { 820 // don't assign const members 821 continue; 822 } 823 824 if ( ArrayType *array = dynamic_cast< ArrayType * >( dwt->get_type() ) ) { 825 makeArrayFunction( srcParam, thisParam, dwt, array, "?{}", back_inserter( copyCtorDecl->get_statements()->get_kids() ) ); 826 // if ( isGeneric ) makeArrayFunction( srcParam, returnVal, dwt, array, back_inserter( copyCtorDecl->get_statements()->get_kids() ) ); 827 } else { 828 makeScalarFunction( srcParam, thisParam, dwt, "?{}", back_inserter( copyCtorDecl->get_statements()->get_kids() ) ); 829 // if ( isGeneric ) makeScalarCtor( srcParam, returnVal, dwt, back_inserter( copyCtorDecl->get_statements()->get_kids() ) ); 830 } // if 831 } // if 832 } // for 833 // if ( ! isGeneric ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) ); 834 } 835 836 void makeUnionFunctions( UnionDecl *aggregateDecl, UnionInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd ) { 756 837 FunctionType *assignType = new FunctionType( Type::Qualifiers(), false ); 757 838 … … 767 848 } 768 849 850 ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), cloneWithParams( refType, unionParams ) ), 0 ); 851 assignType->get_parameters().push_back( dstParam ); 852 853 // default ctor/dtor need only first parameter 854 FunctionType * ctorType = assignType->clone(); 855 FunctionType * dtorType = assignType->clone(); 856 857 ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, unionParams ), 0 ); 858 assignType->get_parameters().push_back( srcParam ); 859 860 // copy ctor needs both parameters 861 FunctionType * copyCtorType = assignType->clone(); 862 863 // assignment needs both and return value 769 864 ObjectDecl *returnVal = new ObjectDecl( "_ret", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, unionParams ), 0 ); 770 865 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 866 778 867 // Routines at global scope marked "static" to prevent multiple definitions is separate translation units 779 868 // because each unit generates copies of the default routines for each aggregate. 780 869 FunctionDecl *assignDecl = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, assignType, new CompoundStmt( noLabels ), true, false ); 870 FunctionDecl *ctorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, ctorType, new CompoundStmt( noLabels ), true, false ); 871 FunctionDecl *copyCtorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, copyCtorType, NULL, true, false ); 872 FunctionDecl *dtorDecl = new FunctionDecl( "^?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, dtorType, new CompoundStmt( noLabels ), true, false ); 873 781 874 assignDecl->fixUniqueId(); 875 ctorDecl->fixUniqueId(); 876 copyCtorDecl->fixUniqueId(); 877 dtorDecl->fixUniqueId(); 782 878 783 879 makeUnionFieldsAssignment( srcParam, dstParam, cloneWithParams( refType, unionParams ), back_inserter( assignDecl->get_statements()->get_kids() ) ); 784 880 if ( isGeneric ) makeUnionFieldsAssignment( srcParam, returnVal, cloneWithParams( refType, unionParams ), back_inserter( assignDecl->get_statements()->get_kids() ) ); 785 881 786 882 if ( ! isGeneric ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) ); 787 883 788 return assignDecl; 884 // body of assignment and copy ctor is the same 885 copyCtorDecl->set_statements( assignDecl->get_statements()->clone() ); 886 887 declsToAdd.push_back( assignDecl ); 888 declsToAdd.push_back( ctorDecl ); 889 declsToAdd.push_back( copyCtorDecl ); 890 declsToAdd.push_back( dtorDecl ); 789 891 } 790 892 … … 802 904 StructInstType structInst( Type::Qualifiers(), structDecl->get_name() ); 803 905 structInst.set_baseStruct( structDecl ); 906 804 907 declsToAdd.push_back( makeStructAssignment( structDecl, &structInst, functionNesting ) ); 908 makeStructCtorDtor( structDecl, &structInst, functionNesting, declsToAdd ); 805 909 structsDone.insert( structDecl->get_name() ); 806 910 } // if … … 811 915 UnionInstType unionInst( Type::Qualifiers(), unionDecl->get_name() ); 812 916 unionInst.set_baseUnion( unionDecl ); 813 declsToAdd.push_back( makeUnionAssignment( unionDecl, &unionInst, functionNesting ));917 makeUnionFunctions( unionDecl, &unionInst, functionNesting, declsToAdd ); 814 918 } // if 815 919 } … … 1080 1184 } 1081 1185 1186 void VerifyCtorDtor::verify( std::list< Declaration * > & translationUnit ) { 1187 VerifyCtorDtor verifier; 1188 acceptAll( translationUnit, verifier ); 1189 } 1190 1191 void VerifyCtorDtor::visit( FunctionDecl * funcDecl ) { 1192 FunctionType * funcType = funcDecl->get_functionType(); 1193 std::list< DeclarationWithType * > &returnVals = funcType->get_returnVals(); 1194 std::list< DeclarationWithType * > ¶ms = funcType->get_parameters(); 1195 1196 if ( funcDecl->get_name() == "?{}" || funcDecl->get_name() == "^?{}" ) { 1197 if ( params.size() == 0 ) { 1198 throw SemanticError( "Constructors and destructors require at least one parameter ", funcDecl ); 1199 } 1200 if ( ! dynamic_cast< PointerType * >( params.front()->get_type() ) ) { 1201 throw SemanticError( "First parameter of a constructor or destructor must be a pointer ", funcDecl ); 1202 } 1203 if ( returnVals.size() != 0 ) { 1204 throw SemanticError( "Constructors and destructors cannot have explicit return values ", funcDecl ); 1205 } 1206 } 1207 1208 Visitor::visit( funcDecl ); 1209 // original idea: modify signature of ctor/dtors and insert appropriate return statements 1210 // to cause desired behaviour 1211 // new idea: add comma exprs to every ctor call to produce first parameter. 1212 // this requires some memoization of the first parameter, because it can be a 1213 // complicated expression with side effects (see: malloc). idea: add temporary variable 1214 // that is assigned address of constructed object in ctor argument position and 1215 // return the temporary. It should also be done after all implicit ctors are 1216 // added, so not in this pass! 1217 } 1082 1218 } // namespace SymTab 1083 1219
Note:
See TracChangeset
for help on using the changeset viewer.