Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/SymTab/Validate.cc

    r98735ef r7528ba1  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 21:50:04 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jan 27 22:03:12 2016
    13 // Update Count     : 225
     11// Last Modified By : Rob Schluntz
     12// Last Modified On : Mon Feb 22 12:26:37 2016
     13// Update Count     : 297
    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
    204217        void validate( std::list< Declaration * > &translationUnit, bool doDebug ) {
    205218                Pass1 pass1;
     
    213226                AutogenerateRoutines::autogenerateRoutines( translationUnit );
    214227                acceptAll( translationUnit, pass3 );
     228                VerifyCtorDtor::verify( translationUnit );
    215229        }
    216230
     
    382396                // it's not a semantic error if the struct is not found, just an implicit forward declaration
    383397                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() );
    385399                        structInst->set_baseStruct( st );
    386400                } // if
     
    659673        }
    660674
    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 
    682675        Declaration *makeStructAssignment( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting ) {
    683676                FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
     
    687680                std::list< TypeDecl* >& genericParams = aggregateDecl->get_parameters();
    688681                std::list< Expression* > structParams;  // List of matching parameters to put on types
    689                 TypeSubstitution genericSubs; // Substitutions to make to member types of struct
    690682                for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) {
    691683                        isGeneric = true;
    692                         TypeDecl *typeParam = cloneAndRename( *param, "_autoassign_" + aggregateDecl->get_name() + "_" + (*param)->get_name() );
     684                        TypeDecl *typeParam = (*param)->clone();
    693685                        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 ) ) );
    697687                }
    698688
     
    725715                                }
    726716
    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() ) );
    740720                                } 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() ) );
    747723                                } // if
    748724                        } // if
     
    751727
    752728                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;
    753790        }
    754791
     
    762799                for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) {
    763800                        isGeneric = true;
    764                         TypeDecl *typeParam = cloneAndRename( *param, "_autoassign_" + aggregateDecl->get_name() + "_" + (*param)->get_name() );
     801                        TypeDecl *typeParam = (*param)->clone();
    765802                        assignType->get_forall().push_back( typeParam );
    766803                        unionParams.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam ) ) );
     
    783820                makeUnionFieldsAssignment( srcParam, dstParam, cloneWithParams( refType, unionParams ), back_inserter( assignDecl->get_statements()->get_kids() ) );
    784821                if ( isGeneric ) makeUnionFieldsAssignment( srcParam, returnVal, cloneWithParams( refType, unionParams ), back_inserter( assignDecl->get_statements()->get_kids() ) );
    785                
     822
    786823                if ( ! isGeneric ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
    787824
     
    802839                        StructInstType structInst( Type::Qualifiers(), structDecl->get_name() );
    803840                        structInst.set_baseStruct( structDecl );
     841
    804842                        declsToAdd.push_back( makeStructAssignment( structDecl, &structInst, functionNesting ) );
     843                        makeStructCtorDtor( structDecl, &structInst, functionNesting, declsToAdd );
    805844                        structsDone.insert( structDecl->get_name() );
    806845                } // if
     
    10801119        }
    10811120
     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        }
    10821153} // namespace SymTab
    10831154
Note: See TracChangeset for help on using the changeset viewer.