Changes in src/SymTab/Validate.cc [98735ef:7528ba1]
- File:
-
- 1 edited
-
src/SymTab/Validate.cc (modified) (12 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/SymTab/Validate.cc
r98735ef r7528ba1 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 … … 382 396 // it's not a semantic error if the struct is not found, just an implicit forward declaration 383 397 if ( st ) { 384 //assert( ! structInst->get_baseStruct() || structInst->get_baseStruct()->get_members().empty() || ! st->get_members().empty() );398 assert( ! structInst->get_baseStruct() || structInst->get_baseStruct()->get_members().empty() || ! st->get_members().empty() ); 385 399 structInst->set_baseStruct( st ); 386 400 } // if … … 659 673 } 660 674 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 675 Declaration *makeStructAssignment( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting ) { 683 676 FunctionType *assignType = new FunctionType( Type::Qualifiers(), false ); … … 687 680 std::list< TypeDecl* >& genericParams = aggregateDecl->get_parameters(); 688 681 std::list< Expression* > structParams; // List of matching parameters to put on types 689 TypeSubstitution genericSubs; // Substitutions to make to member types of struct690 682 for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) { 691 683 isGeneric = true; 692 TypeDecl *typeParam = cloneAndRename( *param, "_autoassign_" + aggregateDecl->get_name() + "_" + (*param)->get_name());684 TypeDecl *typeParam = (*param)->clone(); 693 685 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 ) ); 686 structParams.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam ) ) ); 697 687 } 698 688 … … 725 715 } 726 716 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 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() ) ); 740 720 } 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 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() ) ); 747 723 } // if 748 724 } // if … … 751 727 752 728 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 applicable 736 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 types 739 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 units 750 // 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 definitions 757 // TODO: add in calls to default constructors and destructors for fields 758 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 members 775 // 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 // } // if 785 // } // if 786 // } // for 787 // if ( ! isGeneric ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) ); 788 789 // return assignDecl; 753 790 } 754 791 … … 762 799 for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) { 763 800 isGeneric = true; 764 TypeDecl *typeParam = cloneAndRename( *param, "_autoassign_" + aggregateDecl->get_name() + "_" + (*param)->get_name());801 TypeDecl *typeParam = (*param)->clone(); 765 802 assignType->get_forall().push_back( typeParam ); 766 803 unionParams.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam ) ) ); … … 783 820 makeUnionFieldsAssignment( srcParam, dstParam, cloneWithParams( refType, unionParams ), back_inserter( assignDecl->get_statements()->get_kids() ) ); 784 821 if ( isGeneric ) makeUnionFieldsAssignment( srcParam, returnVal, cloneWithParams( refType, unionParams ), back_inserter( assignDecl->get_statements()->get_kids() ) ); 785 822 786 823 if ( ! isGeneric ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) ); 787 824 … … 802 839 StructInstType structInst( Type::Qualifiers(), structDecl->get_name() ); 803 840 structInst.set_baseStruct( structDecl ); 841 804 842 declsToAdd.push_back( makeStructAssignment( structDecl, &structInst, functionNesting ) ); 843 makeStructCtorDtor( structDecl, &structInst, functionNesting, declsToAdd ); 805 844 structsDone.insert( structDecl->get_name() ); 806 845 } // if … … 1080 1119 } 1081 1120 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 statements 1145 // to cause desired behaviour 1146 // 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 a 1148 // complicated expression with side effects (see: malloc). idea: add temporary variable 1149 // that is assigned address of constructed object in ctor argument position and 1150 // return the temporary. It should also be done after all implicit ctors are 1151 // added, so not in this pass! 1152 } 1082 1153 } // namespace SymTab 1083 1154
Note:
See TracChangeset
for help on using the changeset viewer.