Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/SymTab/Validate.cc

    r7528ba1 r98735ef  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 21:50:04 2015
    11 // Last Modified By : Rob Schluntz
    12 // Last Modified On : Mon Feb 22 12:26:37 2016
    13 // Update Count     : 297
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Wed Jan 27 22:03:12 2016
     13// Update Count     : 225
    1414//
    1515
     
    202202        };
    203203
    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 
    217204        void validate( std::list< Declaration * > &translationUnit, bool doDebug ) {
    218205                Pass1 pass1;
     
    226213                AutogenerateRoutines::autogenerateRoutines( translationUnit );
    227214                acceptAll( translationUnit, pass3 );
    228                 VerifyCtorDtor::verify( translationUnit );
    229215        }
    230216
     
    396382                // it's not a semantic error if the struct is not found, just an implicit forward declaration
    397383                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() );
    399385                        structInst->set_baseStruct( st );
    400386                } // if
     
    673659        }
    674660
     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
    675682        Declaration *makeStructAssignment( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting ) {
    676683                FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
     
    680687                std::list< TypeDecl* >& genericParams = aggregateDecl->get_parameters();
    681688                std::list< Expression* > structParams;  // List of matching parameters to put on types
     689                TypeSubstitution genericSubs; // Substitutions to make to member types of struct
    682690                for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) {
    683691                        isGeneric = true;
    684                         TypeDecl *typeParam = (*param)->clone();
     692                        TypeDecl *typeParam = cloneAndRename( *param, "_autoassign_" + aggregateDecl->get_name() + "_" + (*param)->get_name() );
    685693                        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 ) );
    687697                }
    688698
     
    715725                                }
    716726
    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
    720740                                } 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
    723747                                } // if
    724748                        } // if
     
    727751
    728752                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;
    790753        }
    791754
     
    799762                for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) {
    800763                        isGeneric = true;
    801                         TypeDecl *typeParam = (*param)->clone();
     764                        TypeDecl *typeParam = cloneAndRename( *param, "_autoassign_" + aggregateDecl->get_name() + "_" + (*param)->get_name() );
    802765                        assignType->get_forall().push_back( typeParam );
    803766                        unionParams.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam ) ) );
     
    820783                makeUnionFieldsAssignment( srcParam, dstParam, cloneWithParams( refType, unionParams ), back_inserter( assignDecl->get_statements()->get_kids() ) );
    821784                if ( isGeneric ) makeUnionFieldsAssignment( srcParam, returnVal, cloneWithParams( refType, unionParams ), back_inserter( assignDecl->get_statements()->get_kids() ) );
    822 
     785               
    823786                if ( ! isGeneric ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
    824787
     
    839802                        StructInstType structInst( Type::Qualifiers(), structDecl->get_name() );
    840803                        structInst.set_baseStruct( structDecl );
    841 
    842804                        declsToAdd.push_back( makeStructAssignment( structDecl, &structInst, functionNesting ) );
    843                         makeStructCtorDtor( structDecl, &structInst, functionNesting, declsToAdd );
    844805                        structsDone.insert( structDecl->get_name() );
    845806                } // if
     
    11191080        }
    11201081
    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 * > &params = 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         }
    11531082} // namespace SymTab
    11541083
Note: See TracChangeset for help on using the changeset viewer.