Changes in src/SymTab/Validate.cc [7528ba1:98735ef]
- File:
-
- 1 edited
-
src/SymTab/Validate.cc (modified) (12 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/SymTab/Validate.cc
r7528ba1 r98735ef 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 Jan 27 22:03:12 2016 13 // Update Count : 225 14 14 // 15 15 … … 202 202 }; 203 203 204 class VerifyCtorDtor : public Visitor {205 public:206 /// ensure that constructors and destructors have at least one207 /// parameter, the first of which must be a pointer, and no208 /// return values.209 static void verify( std::list< Declaration * > &translationUnit );210 211 // VerifyCtorDtor() {}212 213 virtual void visit( FunctionDecl *funcDecl );214 private:215 };216 217 204 void validate( std::list< Declaration * > &translationUnit, bool doDebug ) { 218 205 Pass1 pass1; … … 226 213 AutogenerateRoutines::autogenerateRoutines( translationUnit ); 227 214 acceptAll( translationUnit, pass3 ); 228 VerifyCtorDtor::verify( translationUnit );229 215 } 230 216 … … 396 382 // it's not a semantic error if the struct is not found, just an implicit forward declaration 397 383 if ( st ) { 398 assert( ! structInst->get_baseStruct() || structInst->get_baseStruct()->get_members().empty() || ! st->get_members().empty() );384 //assert( ! structInst->get_baseStruct() || structInst->get_baseStruct()->get_members().empty() || ! st->get_members().empty() ); 399 385 structInst->set_baseStruct( st ); 400 386 } // if … … 673 659 } 674 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 675 682 Declaration *makeStructAssignment( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting ) { 676 683 FunctionType *assignType = new FunctionType( Type::Qualifiers(), false ); … … 680 687 std::list< TypeDecl* >& genericParams = aggregateDecl->get_parameters(); 681 688 std::list< Expression* > structParams; // List of matching parameters to put on types 689 TypeSubstitution genericSubs; // Substitutions to make to member types of struct 682 690 for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) { 683 691 isGeneric = true; 684 TypeDecl *typeParam = (*param)->clone();692 TypeDecl *typeParam = cloneAndRename( *param, "_autoassign_" + aggregateDecl->get_name() + "_" + (*param)->get_name() ); 685 693 assignType->get_forall().push_back( typeParam ); 686 structParams.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeParam->get_name(), 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 ) ); 687 697 } 688 698 … … 715 725 } 716 726 717 if ( ArrayType *array = dynamic_cast< ArrayType * >( dwt->get_type() ) ) { 718 makeArrayAssignment( srcParam, dstParam, dwt, array, back_inserter( assignDecl->get_statements()->get_kids() ) ); 719 if ( isGeneric ) makeArrayAssignment( srcParam, returnVal, dwt, array, back_inserter( assignDecl->get_statements()->get_kids() ) ); 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 720 740 } else { 721 makeScalarAssignment( srcParam, dstParam, dwt, back_inserter( assignDecl->get_statements()->get_kids() ) ); 722 if ( isGeneric ) makeScalarAssignment( srcParam, returnVal, dwt, back_inserter( assignDecl->get_statements()->get_kids() ) ); 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 723 747 } // if 724 748 } // if … … 727 751 728 752 return assignDecl; 729 }730 731 732 void makeStructCtorDtor( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd ) {733 FunctionType *ctorType = new FunctionType( Type::Qualifiers(), false );734 735 // Make function polymorphic in same parameters as generic struct, if applicable736 bool isGeneric = false; // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for union)737 std::list< TypeDecl* >& genericParams = aggregateDecl->get_parameters();738 std::list< Expression* > structParams; // List of matching parameters to put on types739 for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) {740 isGeneric = true;741 TypeDecl *typeParam = (*param)->clone();742 ctorType->get_forall().push_back( typeParam );743 structParams.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam ) ) );744 }745 746 ObjectDecl *thisParam = new ObjectDecl( "_this", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), cloneWithParams( refType, structParams ) ), 0 );747 ctorType->get_parameters().push_back( thisParam );748 749 // Routines at global scope marked "static" to prevent multiple definitions is separate translation units750 // because each unit generates copies of the default routines for each aggregate.751 FunctionDecl *ctorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, ctorType, 0, true, false );752 FunctionDecl *dtorDecl = new FunctionDecl( "^?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, ctorType, 0, true, false );753 ctorDecl->fixUniqueId();754 dtorDecl->fixUniqueId();755 756 // add definitions757 // TODO: add in calls to default constructors and destructors for fields758 ctorDecl->set_statements( new CompoundStmt( noLabels ) );759 dtorDecl->set_statements( new CompoundStmt( noLabels ) );760 declsToAdd.push_back( ctorDecl );761 declsToAdd.push_back( dtorDecl );762 763 764 // for ( std::list< Declaration * >::const_iterator member = aggregateDecl->get_members().begin(); member != aggregateDecl->get_members().end(); ++member ) {765 // if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member ) ) {766 // // query the type qualifiers of this field and skip assigning it if it is marked const.767 // // If it is an array type, we need to strip off the array layers to find its qualifiers.768 // Type * type = dwt->get_type();769 // while ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {770 // type = at->get_base();771 // }772 773 // if ( type->get_qualifiers().isConst ) {774 // // don't assign const members775 // continue;776 // }777 778 // if ( ArrayType *array = dynamic_cast< ArrayType * >( dwt->get_type() ) ) {779 // makeArrayAssignment( srcParam, dstParam, dwt, array, back_inserter( assignDecl->get_statements()->get_kids() ) );780 // if ( isGeneric ) makeArrayAssignment( srcParam, returnVal, dwt, array, back_inserter( assignDecl->get_statements()->get_kids() ) );781 // } else {782 // makeScalarAssignment( srcParam, dstParam, dwt, back_inserter( assignDecl->get_statements()->get_kids() ) );783 // if ( isGeneric ) makeScalarAssignment( srcParam, returnVal, dwt, back_inserter( assignDecl->get_statements()->get_kids() ) );784 // } // if785 // } // if786 // } // for787 // if ( ! isGeneric ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );788 789 // return assignDecl;790 753 } 791 754 … … 799 762 for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) { 800 763 isGeneric = true; 801 TypeDecl *typeParam = (*param)->clone();764 TypeDecl *typeParam = cloneAndRename( *param, "_autoassign_" + aggregateDecl->get_name() + "_" + (*param)->get_name() ); 802 765 assignType->get_forall().push_back( typeParam ); 803 766 unionParams.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam ) ) ); … … 820 783 makeUnionFieldsAssignment( srcParam, dstParam, cloneWithParams( refType, unionParams ), back_inserter( assignDecl->get_statements()->get_kids() ) ); 821 784 if ( isGeneric ) makeUnionFieldsAssignment( srcParam, returnVal, cloneWithParams( refType, unionParams ), back_inserter( assignDecl->get_statements()->get_kids() ) ); 822 785 823 786 if ( ! isGeneric ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) ); 824 787 … … 839 802 StructInstType structInst( Type::Qualifiers(), structDecl->get_name() ); 840 803 structInst.set_baseStruct( structDecl ); 841 842 804 declsToAdd.push_back( makeStructAssignment( structDecl, &structInst, functionNesting ) ); 843 makeStructCtorDtor( structDecl, &structInst, functionNesting, declsToAdd );844 805 structsDone.insert( structDecl->get_name() ); 845 806 } // if … … 1119 1080 } 1120 1081 1121 void VerifyCtorDtor::verify( std::list< Declaration * > & translationUnit ) {1122 VerifyCtorDtor verifier;1123 acceptAll( translationUnit, verifier );1124 }1125 1126 void VerifyCtorDtor::visit( FunctionDecl * funcDecl ) {1127 FunctionType * funcType = funcDecl->get_functionType();1128 std::list< DeclarationWithType * > &returnVals = funcType->get_returnVals();1129 std::list< DeclarationWithType * > ¶ms = funcType->get_parameters();1130 1131 if ( funcDecl->get_name() == "?{}" || funcDecl->get_name() == "^?{}" ) {1132 if ( params.size() == 0 ) {1133 throw SemanticError( "Constructors and destructors require at least one parameter ", funcDecl );1134 }1135 if ( ! dynamic_cast< PointerType * >( params.front()->get_type() ) ) {1136 throw SemanticError( "First parameter of a constructor or destructor must be a pointer ", funcDecl );1137 }1138 if ( returnVals.size() != 0 ) {1139 throw SemanticError( "Constructors and destructors cannot have explicit return values ", funcDecl );1140 }1141 }1142 1143 Visitor::visit( funcDecl );1144 // original idea: modify signature of ctor/dtors and insert appropriate return statements1145 // to cause desired behaviour1146 // new idea: add comma exprs to every ctor call to produce first parameter.1147 // this requires some memoization of the first parameter, because it can be a1148 // complicated expression with side effects (see: malloc). idea: add temporary variable1149 // that is assigned address of constructed object in ctor argument position and1150 // return the temporary. It should also be done after all implicit ctors are1151 // added, so not in this pass!1152 }1153 1082 } // namespace SymTab 1154 1083
Note:
See TracChangeset
for help on using the changeset viewer.