Changeset b1e63ac5 for src/SymTab
- Timestamp:
- Jul 4, 2017, 9:40:16 AM (8 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
- Children:
- 208e5be
- Parents:
- 9c951e3 (diff), f7cb0bc (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - Location:
- src/SymTab
- Files:
-
- 8 edited
-
Autogen.cc (modified) (8 diffs)
-
Autogen.h (modified) (4 diffs)
-
FixFunction.cc (modified) (1 diff)
-
ImplementationType.cc (modified) (4 diffs)
-
Indexer.cc (modified) (6 diffs)
-
Indexer.h (modified) (1 diff)
-
Mangler.cc (modified) (3 diffs)
-
Validate.cc (modified) (23 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/SymTab/Autogen.cc
r9c951e3 rb1e63ac5 9 9 // Author : Rob Schluntz 10 10 // Created On : Thu Mar 03 15:45:56 2016 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Fri Mar 17 09:41:08201713 // Update Count : 6 011 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Jun 28 15:30:00 2017 13 // Update Count : 61 14 14 // 15 15 … … 263 263 // E ?=?(E volatile*, int), 264 264 // ?=?(E _Atomic volatile*, int); 265 void makeEnumFunctions( Enum Decl *enumDecl, EnumInstType *refType, unsigned int functionNesting, std::list< Declaration * > &declsToAdd ) {265 void makeEnumFunctions( EnumInstType *refType, unsigned int functionNesting, std::list< Declaration * > &declsToAdd ) { 266 266 267 267 // T ?=?(E *, E); … … 401 401 /// generates struct constructors, destructor, and assignment functions 402 402 void makeStructFunctions( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd, const std::vector< FuncData > & data ) { 403 // Builtins do not use autogeneration. 404 if ( aggregateDecl->get_linkage() == LinkageSpec::Builtin || 405 aggregateDecl->get_linkage() == LinkageSpec::BuiltinC ) { 406 return; 407 } 408 403 409 // Make function polymorphic in same parameters as generic struct, if applicable 404 410 const std::list< TypeDecl* > & typeParams = aggregateDecl->get_parameters(); // List of type variables to be placed on the generated functions … … 487 493 488 494 /// generates the body of a union assignment/copy constructor/field constructor 489 void makeUnionAssignBody( FunctionDecl * funcDecl , bool isDynamicLayout) {495 void makeUnionAssignBody( FunctionDecl * funcDecl ) { 490 496 FunctionType * ftype = funcDecl->get_functionType(); 491 497 assert( ftype->get_parameters().size() == 2 ); … … 507 513 // Make function polymorphic in same parameters as generic union, if applicable 508 514 const std::list< TypeDecl* > & typeParams = aggregateDecl->get_parameters(); // List of type variables to be placed on the generated functions 509 bool isDynamicLayout = hasDynamicLayout( aggregateDecl ); // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for struct) 510 515 511 516 // default ctor/dtor need only first parameter 512 517 // void ?{}(T *); void ^?{}(T *); … … 534 539 FunctionDecl *dtorDecl = genFunc( "^?{}", dtorType, functionNesting ); 535 540 536 makeUnionAssignBody( assignDecl , isDynamicLayout);541 makeUnionAssignBody( assignDecl ); 537 542 538 543 // body of assignment and copy ctor is the same 539 makeUnionAssignBody( copyCtorDecl , isDynamicLayout);544 makeUnionAssignBody( copyCtorDecl ); 540 545 541 546 // create a constructor which takes the first member type as a parameter. … … 552 557 FunctionDecl * ctor = genFunc( "?{}", memCtorType, functionNesting ); 553 558 554 makeUnionAssignBody( ctor , isDynamicLayout);559 makeUnionAssignBody( ctor ); 555 560 memCtors.push_back( ctor ); 556 561 // only generate a ctor for the first field … … 579 584 EnumInstType *enumInst = new EnumInstType( Type::Qualifiers(), enumDecl->get_name() ); 580 585 // enumInst->set_baseEnum( enumDecl ); 581 makeEnumFunctions( enum Decl, enumInst, functionNesting, declsToAddAfter );586 makeEnumFunctions( enumInst, functionNesting, declsToAddAfter ); 582 587 } 583 588 } -
src/SymTab/Autogen.h
r9c951e3 rb1e63ac5 10 10 // Created On : Sun May 17 21:53:34 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Mar 17 09:10:41201713 // Update Count : 912 // Last Modified On : Wed Jun 21 17:25:26 2017 13 // Update Count : 14 14 14 // 15 15 … … 43 43 template< typename OutputIterator > 44 44 Statement * genScalarCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast = false ) { 45 // want to be able to generate assignment, ctor, and dtor generically,46 // so fname is either ?=?, ?{}, or ^?{}47 UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) );45 // want to be able to generate assignment, ctor, and dtor generically, 46 // so fname is either ?=?, ?{}, or ^?{} 47 UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) ); 48 48 49 // do something special for unnamed members 50 dstParam = new AddressExpr( dstParam ); 51 if ( addCast ) { 52 // cast to T* with qualifiers removed, so that qualified objects can be constructed 53 // and destructed with the same functions as non-qualified objects. 54 // unfortunately, lvalue is considered a qualifier. For AddressExpr to resolve, its argument 55 // must have an lvalue qualified type, so remove all qualifiers except lvalue. If we ever 56 // remove lvalue as a qualifier, this can change to 57 // type->get_qualifiers() = Type::Qualifiers(); 58 assert( type ); 59 Type * castType = type->clone(); 60 // castType->get_qualifiers() -= Type::Qualifiers(true, true, true, false, true, false); 61 castType->get_qualifiers() -= Type::Qualifiers( Type::Const | Type::Volatile | Type::Restrict | Type::Atomic ); 62 castType->set_lvalue( true ); // xxx - might not need this 63 dstParam = new CastExpr( dstParam, new PointerType( Type::Qualifiers(), castType ) ); 64 } 65 fExpr->get_args().push_back( dstParam ); 49 // do something special for unnamed members 50 dstParam = new AddressExpr( dstParam ); 51 if ( addCast ) { 52 // cast to T* with qualifiers removed, so that qualified objects can be constructed 53 // and destructed with the same functions as non-qualified objects. 54 // unfortunately, lvalue is considered a qualifier. For AddressExpr to resolve, its argument 55 // must have an lvalue qualified type, so remove all qualifiers except lvalue. If we ever 56 // remove lvalue as a qualifier, this can change to 57 // type->get_qualifiers() = Type::Qualifiers(); 58 assert( type ); 59 Type * castType = type->clone(); 60 castType->get_qualifiers() -= Type::Qualifiers( Type::Const | Type::Volatile | Type::Restrict | Type::Atomic ); 61 castType->set_lvalue( true ); // xxx - might not need this 62 dstParam = new CastExpr( dstParam, new PointerType( Type::Qualifiers(), castType ) ); 63 } 64 fExpr->get_args().push_back( dstParam ); 66 65 67 Statement * listInit = srcParam.buildListInit( fExpr );66 Statement * listInit = srcParam.buildListInit( fExpr ); 68 67 69 std::list< Expression * > args = *++srcParam;70 fExpr->get_args().splice( fExpr->get_args().end(), args );68 std::list< Expression * > args = *++srcParam; 69 fExpr->get_args().splice( fExpr->get_args().end(), args ); 71 70 72 *out++ = new ExprStmt( noLabels, fExpr );71 *out++ = new ExprStmt( noLabels, fExpr ); 73 72 74 srcParam.clearArrayIndices();73 srcParam.clearArrayIndices(); 75 74 76 return listInit;75 return listInit; 77 76 } 78 77 … … 88 87 Expression * begin, * end, * update, * cmp; 89 88 if ( forward ) { 90 // generate: for ( int i = 0; i < 0; ++i )91 begin = new ConstantExpr( Constant ( new ZeroType( emptyQualifiers ), "0") );89 // generate: for ( int i = 0; i < N; ++i ) 90 begin = new ConstantExpr( Constant::from_int( 0 ) ); 92 91 end = array->get_dimension()->clone(); 93 92 cmp = new NameExpr( "?<?" ); … … 97 96 begin = new UntypedExpr( new NameExpr( "?-?" ) ); 98 97 ((UntypedExpr*)begin)->get_args().push_back( array->get_dimension()->clone() ); 99 ((UntypedExpr*)begin)->get_args().push_back( new ConstantExpr( Constant ( new OneType( emptyQualifiers ), "1") ) );100 end = new ConstantExpr( Constant ( new ZeroType( emptyQualifiers ), "0") );98 ((UntypedExpr*)begin)->get_args().push_back( new ConstantExpr( Constant::from_int( 1 ) ) ); 99 end = new ConstantExpr( Constant::from_int( 0 ) ); 101 100 cmp = new NameExpr( "?>=?" ); 102 101 update = new NameExpr( "--?" ); 103 102 } 104 103 105 ObjectDecl *index = new ObjectDecl( indexName.newName(), Type::StorageClasses(), LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), new SingleInit( begin , std::list<Expression*>()) );104 ObjectDecl *index = new ObjectDecl( indexName.newName(), Type::StorageClasses(), LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), new SingleInit( begin ) ); 106 105 107 106 UntypedExpr *cond = new UntypedExpr( cmp ); -
src/SymTab/FixFunction.cc
r9c951e3 rb1e63ac5 24 24 25 25 DeclarationWithType * FixFunction::mutate(FunctionDecl *functionDecl) { 26 ObjectDecl *pointer = new ObjectDecl( functionDecl->get_name(), functionDecl->get_storageClasses(), functionDecl->get_linkage(), 0, new PointerType( Type::Qualifiers(), functionDecl->get_type() ->clone()), 0, functionDecl->get_attributes() );26 ObjectDecl *pointer = new ObjectDecl( functionDecl->get_name(), functionDecl->get_storageClasses(), functionDecl->get_linkage(), 0, new PointerType( Type::Qualifiers(), functionDecl->get_type() ), 0, functionDecl->get_attributes() ); 27 27 functionDecl->get_attributes().clear(); 28 // can't delete function type because it may contain assertions, but can't transfer ownership without a clone since set_type checks for nullptr 29 functionDecl->set_type( functionDecl->get_type()->clone() ); 28 30 delete functionDecl; 29 31 return pointer; -
src/SymTab/ImplementationType.cc
r9c951e3 rb1e63ac5 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // ImplementationType.cc -- 7 // ImplementationType.cc -- 8 8 // 9 9 // Author : Richard C. Bilson … … 61 61 } 62 62 63 void ImplementationType::visit(VoidType *voidType) { 64 } 65 66 void ImplementationType::visit(BasicType *basicType) { 67 } 63 void ImplementationType::visit( __attribute__((unused)) VoidType *voidType ) {} 64 void ImplementationType::visit( __attribute__((unused)) BasicType *basicType ) {} 68 65 69 66 void ImplementationType::visit(PointerType *pointerType) { … … 79 76 } 80 77 81 void ImplementationType::visit(FunctionType *functionType) { 82 /// FunctionType *newType = functionType->clone(); 83 /// for ( std::list< DeclarationWithType* >::iterator i = newType->get_parameters().begin(); i != newType->get_parameters().end(); ++i ) { 84 /// i->set_type( implementationType( i->get_type(), indexer ) ); 85 /// } 86 /// for ( std::list< DeclarationWithType* >::iterator i = newType->get_parameters().begin(); i != newType->get_parameters().end(); ++i ) { 87 /// i->set_type( implementationType( i->get_type(), indexer ) ); 88 /// } 89 } 90 91 void ImplementationType::visit(StructInstType *aggregateUseType) { 92 } 93 94 void ImplementationType::visit(UnionInstType *aggregateUseType) { 95 } 96 97 void ImplementationType::visit(EnumInstType *aggregateUseType) { 98 } 99 100 void ImplementationType::visit(TraitInstType *aggregateUseType) { 101 } 78 void ImplementationType::visit( __attribute__((unused)) FunctionType *functionType ) {} 79 void ImplementationType::visit( __attribute__((unused)) StructInstType * aggregateUseType ) {} 80 void ImplementationType::visit( __attribute__((unused)) UnionInstType * aggregateUseType ) {} 81 void ImplementationType::visit( __attribute__((unused)) EnumInstType * aggregateUseType ) {} 82 void ImplementationType::visit( __attribute__((unused)) TraitInstType * aggregateUseType ) {} 102 83 103 84 void ImplementationType::visit(TypeInstType *inst) { … … 111 92 112 93 void ImplementationType::visit(TupleType *tupleType) { 113 TupleType *newType = new TupleType( Type::Qualifiers() );94 std::list< Type * > types; 114 95 for ( std::list< Type* >::iterator i = tupleType->get_types().begin(); i != tupleType->get_types().end(); ++i ) { 115 96 Type *implType = implementationType( *i, indexer ); 116 97 implType->get_qualifiers() |= tupleType->get_qualifiers(); 117 newType->get_types().push_back( implType );98 types.push_back( implType ); 118 99 } // for 119 result = new Type;100 result = new TupleType( Type::Qualifiers(), types ); 120 101 } 121 102 122 void ImplementationType::visit(VarArgsType *varArgsType) { 123 } 124 125 void ImplementationType::visit(ZeroType *zeroType) { 126 } 127 128 void ImplementationType::visit(OneType *oneType) { 129 } 103 void ImplementationType::visit( __attribute__((unused)) VarArgsType *varArgsType ) {} 104 void ImplementationType::visit( __attribute__((unused)) ZeroType *zeroType ) {} 105 void ImplementationType::visit( __attribute__((unused)) OneType *oneType ) {} 130 106 } // namespace SymTab 131 107 -
src/SymTab/Indexer.cc
r9c951e3 rb1e63ac5 124 124 }; 125 125 // properties for this type 126 bool userDefinedFunc = false; // any user-defined function found 127 bool userDefinedCtor = false; // any user-defined constructor found 128 bool userDefinedDtor = false; // any user-defined destructor found 129 bool userDefinedCopyFunc = false; // user-defined copy ctor found 126 bool existsUserDefinedFunc = false; // any user-defined function found 127 bool existsUserDefinedCtor = false; // any user-defined constructor found 128 bool existsUserDefinedDtor = false; // any user-defined destructor found 129 bool existsUserDefinedCopyFunc = false; // user-defined copy ctor found 130 bool existsUserDefinedDefaultCtor = false; // user-defined default ctor found 130 131 std::list< DeclBall > decls; 131 132 … … 138 139 bool isCopyFunc = InitTweak::isCopyFunction( function, function->get_name() ); 139 140 decls.push_back( DeclBall{ function, isUserDefinedFunc, isDefaultCtor, isDtor, isCopyFunc } ); 140 userDefinedFunc = userDefinedFunc || isUserDefinedFunc; 141 userDefinedCtor = userDefinedCtor || (isUserDefinedFunc && InitTweak::isConstructor( function->get_name() ) ); 142 userDefinedDtor = userDefinedDtor || (isUserDefinedFunc && isDtor); 143 userDefinedCopyFunc = userDefinedCopyFunc || (isUserDefinedFunc && isCopyFunc); 141 existsUserDefinedFunc = existsUserDefinedFunc || isUserDefinedFunc; 142 existsUserDefinedCtor = existsUserDefinedCtor || (isUserDefinedFunc && InitTweak::isConstructor( function->get_name() ) ); 143 existsUserDefinedDtor = existsUserDefinedDtor || (isUserDefinedFunc && isDtor); 144 existsUserDefinedCopyFunc = existsUserDefinedCopyFunc || (isUserDefinedFunc && isCopyFunc); 145 existsUserDefinedDefaultCtor = existsUserDefinedDefaultCtor || (isUserDefinedFunc && isDefaultCtor); 144 146 return *this; 145 147 } … … 164 166 } 165 167 166 // if a type contains user defined ctor/dtor s, then special rules trigger, which determine167 // the set of ctor/dtor sthat are seen by the requester. In particular, if the user defines168 // if a type contains user defined ctor/dtor/assign, then special rules trigger, which determine 169 // the set of ctor/dtor/assign that are seen by the requester. In particular, if the user defines 168 170 // a default ctor, then the generated default ctor should never be seen, likewise for copy ctor 169 171 // and dtor. If the user defines any ctor/dtor, then no generated field ctors should be seen. 170 // If the user defines any ctor then the generated default ctor should not be seen. 172 // If the user defines any ctor then the generated default ctor should not be seen (intrinsic default 173 // ctor must be overridden exactly). 171 174 for ( std::pair< const std::string, ValueType > & pair : funcMap ) { 172 175 ValueType & val = pair.second; 173 176 for ( ValueType::DeclBall ball : val.decls ) { 174 if ( ! val.userDefinedFunc || ball.isUserDefinedFunc || (! val.userDefinedCtor && ball.isDefaultCtor) || (! val.userDefinedCopyFunc && ball.isCopyFunc) || (! val.userDefinedDtor && ball.isDtor) ) { 177 bool noUserDefinedFunc = ! val.existsUserDefinedFunc; 178 bool isUserDefinedFunc = ball.isUserDefinedFunc; 179 bool isAcceptableDefaultCtor = (! val.existsUserDefinedCtor || (! val.existsUserDefinedDefaultCtor && ball.decl->get_linkage() == LinkageSpec::Intrinsic)) && ball.isDefaultCtor; // allow default constructors only when no user-defined constructors exist, except in the case of intrinsics, which require exact overrides 180 bool isAcceptableCopyFunc = ! val.existsUserDefinedCopyFunc && ball.isCopyFunc; // handles copy ctor and assignment operator 181 bool isAcceptableDtor = ! val.existsUserDefinedDtor && ball.isDtor; 182 if ( noUserDefinedFunc || isUserDefinedFunc || isAcceptableDefaultCtor || isAcceptableCopyFunc || isAcceptableDtor ) { 175 183 // decl conforms to the rules described above, so it should be seen by the requester 176 184 out.push_back( ball.decl ); … … 278 286 addType( typeDecl ); 279 287 acceptAll( typeDecl->get_assertions(), *this ); 288 acceptNewScope( typeDecl->get_init(), *this ); 280 289 } 281 290 … … 487 496 } 488 497 489 void Indexer::visit( UntypedValofExpr *valofExpr ) {490 acceptNewScope( valofExpr->get_result(), *this );491 maybeAccept( valofExpr->get_body(), *this );492 }493 494 498 void Indexer::visit( RangeExpr *rangeExpr ) { 495 499 maybeAccept( rangeExpr->get_low(), *this ); … … 510 514 acceptNewScope( tupleExpr->get_result(), *this ); 511 515 maybeAccept( tupleExpr->get_tuple(), *this ); 512 }513 514 void Indexer::visit( MemberTupleExpr *tupleExpr ) {515 acceptNewScope( tupleExpr->get_result(), *this );516 maybeAccept( tupleExpr->get_member(), *this );517 maybeAccept( tupleExpr->get_aggregate(), *this );518 516 } 519 517 -
src/SymTab/Indexer.h
r9c951e3 rb1e63ac5 69 69 virtual void visit( ConstructorExpr * ctorExpr ); 70 70 virtual void visit( CompoundLiteralExpr *compLitExpr ); 71 virtual void visit( UntypedValofExpr *valofExpr );72 71 virtual void visit( RangeExpr *rangeExpr ); 73 72 virtual void visit( UntypedTupleExpr *tupleExpr ); 74 73 virtual void visit( TupleExpr *tupleExpr ); 75 74 virtual void visit( TupleIndexExpr *tupleExpr ); 76 virtual void visit( MemberTupleExpr *tupleExpr );77 75 virtual void visit( TupleAssignExpr *tupleExpr ); 78 76 virtual void visit( StmtExpr * stmtExpr ); -
src/SymTab/Mangler.cc
r9c951e3 rb1e63ac5 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 21:40:29 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Fri Mar 17 09:40:01201713 // Update Count : 2 011 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Jun 28 15:31:00 2017 13 // Update Count : 21 14 14 // 15 15 … … 72 72 } else { 73 73 // if we add another kind of overridable function, this has to change 74 assert( false );74 assert( false && "unknown overrideable linkage" ); 75 75 } // if 76 76 } … … 236 236 } 237 237 238 void Mangler::visit( ZeroType *zeroType ) {238 void Mangler::visit( __attribute__((unused)) ZeroType *zeroType ) { 239 239 mangleName << "Z"; 240 240 } 241 241 242 void Mangler::visit( OneType *oneType ) {242 void Mangler::visit( __attribute__((unused)) OneType *oneType ) { 243 243 mangleName << "O"; 244 244 } -
src/SymTab/Validate.cc
r9c951e3 rb1e63ac5 38 38 // definition occurs later in the input. 39 39 40 #include <algorithm> 41 #include <iterator> 40 42 #include <list> 41 #include <iterator> 43 44 #include "CodeGen/CodeGenerator.h" 45 46 #include "Common/PassVisitor.h" 42 47 #include "Common/ScopedMap.h" 48 #include "Common/UniqueName.h" 43 49 #include "Common/utility.h" 44 #include "Common/UniqueName.h" 50 45 51 #include "Concurrency/Keywords.h" 46 #include "Validate.h" 47 #include "SynTree/Visitor.h" 48 #include "SynTree/Mutator.h" 49 #include "SynTree/Type.h" 50 #include "SynTree/Expression.h" 51 #include "SynTree/Statement.h" 52 #include "SynTree/TypeSubstitution.h" 53 #include "Indexer.h" 52 53 #include "GenPoly/DeclMutator.h" 54 55 #include "InitTweak/InitTweak.h" 56 57 #include "AddVisit.h" 58 #include "Autogen.h" 54 59 #include "FixFunction.h" 55 60 // #include "ImplementationType.h" 56 #include "GenPoly/DeclMutator.h" 57 #include "AddVisit.h" 61 #include "Indexer.h" 58 62 #include "MakeLibCfa.h" 59 63 #include "TypeEquality.h" 60 #include "Autogen.h" 64 #include "Validate.h" 65 61 66 #include "ResolvExpr/typeops.h" 62 #include <algorithm> 63 #include "InitTweak/InitTweak.h" 64 #include "CodeGen/CodeGenerator.h" 67 68 #include "SynTree/Attribute.h" 69 #include "SynTree/Expression.h" 70 #include "SynTree/Mutator.h" 71 #include "SynTree/Statement.h" 72 #include "SynTree/Type.h" 73 #include "SynTree/TypeSubstitution.h" 74 #include "SynTree/Visitor.h" 65 75 66 76 #define debugPrint( x ) if ( doDebug ) { std::cout << x; } … … 96 106 97 107 /// Fix return types so that every function returns exactly one value 98 class ReturnTypeFixer final : public Visitor { 99 public: 100 typedef Visitor Parent; 101 using Parent::visit; 102 108 struct ReturnTypeFixer { 103 109 static void fix( std::list< Declaration * > &translationUnit ); 104 110 105 v irtual voidvisit( FunctionDecl * functionDecl );106 v irtual voidvisit( FunctionType * ftype );111 void postvisit( FunctionDecl * functionDecl ); 112 void postvisit( FunctionType * ftype ); 107 113 }; 108 114 109 115 /// Replaces enum types by int, and function or array types in function parameter and return lists by appropriate pointers. 110 class EnumAndPointerDecayPass final : public Visitor { 111 typedef Visitor Parent; 112 virtual void visit( EnumDecl *aggregateDecl ); 113 virtual void visit( FunctionType *func ); 116 struct EnumAndPointerDecay { 117 void previsit( EnumDecl *aggregateDecl ); 118 void previsit( FunctionType *func ); 114 119 }; 115 120 … … 119 124 public: 120 125 LinkReferenceToTypes( bool doDebug, const Indexer *indexer ); 121 private:122 126 using Parent::visit; 123 127 void visit( EnumInstType *enumInst ) final; … … 129 133 void visit( UnionDecl *unionDecl ) final; 130 134 void visit( TypeInstType *typeInst ) final; 131 135 private: 132 136 const Indexer *indexer; 133 137 … … 140 144 }; 141 145 142 /// Replaces array and function types in forall lists by appropriate pointer type 143 class Pass3final : public Indexer {146 /// Replaces array and function types in forall lists by appropriate pointer type and assigns each Object and Function declaration a unique ID. 147 class ForallPointerDecay final : public Indexer { 144 148 typedef Indexer Parent; 145 149 public: 146 150 using Parent::visit; 147 Pass3( const Indexer *indexer );148 private: 151 ForallPointerDecay( const Indexer *indexer ); 152 149 153 virtual void visit( ObjectDecl *object ) override; 150 154 virtual void visit( FunctionDecl *func ) override; … … 153 157 }; 154 158 155 class ReturnChecker : public Visitor { 156 public: 159 struct ReturnChecker : public WithGuards { 157 160 /// Checks that return statements return nothing if their return type is void 158 161 /// and return something if the return type is non-void. 159 162 static void checkFunctionReturns( std::list< Declaration * > & translationUnit ); 160 private: 161 virtual void visit( FunctionDecl * functionDecl ); 162 virtual void visit( ReturnStmt * returnStmt ); 163 164 std::list< DeclarationWithType * > returnVals; 163 164 void previsit( FunctionDecl * functionDecl ); 165 void previsit( ReturnStmt * returnStmt ); 166 167 typedef std::list< DeclarationWithType * > ReturnVals; 168 ReturnVals returnVals; 165 169 }; 166 170 … … 198 202 }; 199 203 200 class VerifyCtorDtorAssign : public Visitor { 201 public: 204 struct VerifyCtorDtorAssign { 202 205 /// ensure that constructors, destructors, and assignment have at least one 203 206 /// parameter, the first of which must be a pointer, and that ctor/dtors have no … … 205 208 static void verify( std::list< Declaration * > &translationUnit ); 206 209 207 virtual void visit( FunctionDecl *funcDecl ); 208 }; 209 210 class ArrayLength : public Visitor { 211 public: 210 void previsit( FunctionDecl *funcDecl ); 211 }; 212 213 /// ensure that generic types have the correct number of type arguments 214 struct ValidateGenericParameters { 215 void previsit( StructInstType * inst ); 216 void previsit( UnionInstType * inst ); 217 }; 218 219 struct ArrayLength { 212 220 /// for array types without an explicit length, compute the length and store it so that it 213 221 /// is known to the rest of the phases. For example, … … 219 227 static void computeLength( std::list< Declaration * > & translationUnit ); 220 228 221 v irtual voidvisit( ObjectDecl * objDecl );222 }; 223 224 class CompoundLiteral final : public GenPoly::DeclMutator{229 void previsit( ObjectDecl * objDecl ); 230 }; 231 232 struct CompoundLiteral final : public WithDeclsToAdd, public WithVisitorRef<CompoundLiteral> { 225 233 Type::StorageClasses storageClasses; 226 234 227 using GenPoly::DeclMutator::mutate; 228 DeclarationWithType * mutate( ObjectDecl *objectDecl ) final; 229 Expression *mutate( CompoundLiteralExpr *compLitExpr ) final; 235 void premutate( ObjectDecl *objectDecl ); 236 Expression * postmutate( CompoundLiteralExpr *compLitExpr ); 230 237 }; 231 238 232 239 void validate( std::list< Declaration * > &translationUnit, bool doDebug ) { 233 EnumAndPointerDecayPassepc;240 PassVisitor<EnumAndPointerDecay> epc; 234 241 LinkReferenceToTypes lrt( doDebug, 0 ); 235 Pass3 pass3( 0 );236 CompoundLiteralcompoundliteral;237 238 HoistStruct::hoistStruct( translationUnit ); 242 ForallPointerDecay fpd( 0 ); 243 PassVisitor<CompoundLiteral> compoundliteral; 244 PassVisitor<ValidateGenericParameters> genericParams; 245 239 246 EliminateTypedef::eliminateTypedef( translationUnit ); 247 HoistStruct::hoistStruct( translationUnit ); // must happen after EliminateTypedef, so that aggregate typedefs occur in the correct order 240 248 ReturnTypeFixer::fix( translationUnit ); // must happen before autogen 241 249 acceptAll( translationUnit, lrt ); // must happen before autogen, because sized flag needs to propagate to generated functions 250 acceptAll( translationUnit, genericParams ); // check as early as possible - can't happen before LinkReferenceToTypes 242 251 acceptAll( translationUnit, epc ); // must happen before VerifyCtorDtorAssign, because void return objects should not exist 243 252 VerifyCtorDtorAssign::verify( translationUnit ); // must happen before autogen, because autogen examines existing ctor/dtors 244 253 Concurrency::applyKeywords( translationUnit ); 245 autogenerateRoutines( translationUnit ); // moved up, used to be below compoundLiteral - currently needs EnumAndPointerDecay Pass254 autogenerateRoutines( translationUnit ); // moved up, used to be below compoundLiteral - currently needs EnumAndPointerDecay 246 255 Concurrency::implementMutexFuncs( translationUnit ); 247 256 Concurrency::implementThreadStarter( translationUnit ); 248 257 ReturnChecker::checkFunctionReturns( translationUnit ); 249 compoundliteral.mutateDeclarationList( translationUnit);250 acceptAll( translationUnit, pass3);258 mutateAll( translationUnit, compoundliteral ); 259 acceptAll( translationUnit, fpd ); 251 260 ArrayLength::computeLength( translationUnit ); 252 261 } 253 262 254 263 void validateType( Type *type, const Indexer *indexer ) { 255 EnumAndPointerDecayPassepc;264 PassVisitor<EnumAndPointerDecay> epc; 256 265 LinkReferenceToTypes lrt( false, indexer ); 257 Pass3 pass3( indexer );266 ForallPointerDecay fpd( indexer ); 258 267 type->accept( epc ); 259 268 type->accept( lrt ); 260 type->accept( pass3);269 type->accept( fpd ); 261 270 } 262 271 … … 337 346 } 338 347 339 void EnumAndPointerDecay Pass::visit( EnumDecl *enumDecl ) {348 void EnumAndPointerDecay::previsit( EnumDecl *enumDecl ) { 340 349 // Set the type of each member of the enumeration to be EnumConstant 341 350 for ( std::list< Declaration * >::iterator i = enumDecl->get_members().begin(); i != enumDecl->get_members().end(); ++i ) { … … 344 353 obj->set_type( new EnumInstType( Type::Qualifiers( Type::Const ), enumDecl->get_name() ) ); 345 354 } // for 346 Parent::visit( enumDecl );347 355 } 348 356 … … 351 359 void fixFunctionList( DWTList & dwts, FunctionType * func ) { 352 360 // the only case in which "void" is valid is where it is the only one in the list; then it should be removed 353 // entirely other fix ups are handled by the FixFunction class361 // entirely. other fix ups are handled by the FixFunction class 354 362 typedef typename DWTList::iterator DWTIterator; 355 363 DWTIterator begin( dwts.begin() ), end( dwts.end() ); … … 370 378 for ( ; i != end; ++i ) { 371 379 FixFunction fixer; 372 *i = (*i )->acceptMutator( fixer );380 *i = (*i)->acceptMutator( fixer ); 373 381 if ( fixer.get_isVoid() ) { 374 382 throw SemanticError( "invalid type void in function type ", func ); … … 379 387 } 380 388 381 void EnumAndPointerDecay Pass::visit( FunctionType *func ) {389 void EnumAndPointerDecay::previsit( FunctionType *func ) { 382 390 // Fix up parameters and return types 383 391 fixFunctionList( func->get_parameters(), func ); 384 392 fixFunctionList( func->get_returnVals(), func ); 385 Visitor::visit( func );386 393 } 387 394 … … 496 503 void LinkReferenceToTypes::visit( StructDecl *structDecl ) { 497 504 // visit struct members first so that the types of self-referencing members are updated properly 505 // xxx - need to ensure that type parameters match up between forward declarations and definition (most importantly, number of type parameters and and their defaults) 498 506 Parent::visit( structDecl ); 499 507 if ( ! structDecl->get_members().empty() ) { … … 529 537 } 530 538 531 Pass3::Pass3( const Indexer *other_indexer ) : Indexer( false ) {539 ForallPointerDecay::ForallPointerDecay( const Indexer *other_indexer ) : Indexer( false ) { 532 540 if ( other_indexer ) { 533 541 indexer = other_indexer; … … 567 575 } 568 576 569 void Pass3::visit( ObjectDecl *object ) {577 void ForallPointerDecay::visit( ObjectDecl *object ) { 570 578 forallFixer( object->get_type() ); 571 579 if ( PointerType *pointer = dynamic_cast< PointerType * >( object->get_type() ) ) { … … 576 584 } 577 585 578 void Pass3::visit( FunctionDecl *func ) {586 void ForallPointerDecay::visit( FunctionDecl *func ) { 579 587 forallFixer( func->get_type() ); 580 588 Parent::visit( func ); … … 583 591 584 592 void ReturnChecker::checkFunctionReturns( std::list< Declaration * > & translationUnit ) { 585 ReturnCheckerchecker;593 PassVisitor<ReturnChecker> checker; 586 594 acceptAll( translationUnit, checker ); 587 595 } 588 596 589 void ReturnChecker:: visit( FunctionDecl * functionDecl ) {590 std::list< DeclarationWithType * > oldReturnVals = returnVals;597 void ReturnChecker::previsit( FunctionDecl * functionDecl ) { 598 GuardValue( returnVals ); 591 599 returnVals = functionDecl->get_functionType()->get_returnVals(); 592 Visitor::visit( functionDecl ); 593 returnVals = oldReturnVals; 594 } 595 596 void ReturnChecker::visit( ReturnStmt * returnStmt ) { 600 } 601 602 void ReturnChecker::previsit( ReturnStmt * returnStmt ) { 597 603 // Previously this also checked for the existence of an expr paired with no return values on 598 604 // the function return type. This is incorrect, since you can have an expression attached to … … 804 810 805 811 void VerifyCtorDtorAssign::verify( std::list< Declaration * > & translationUnit ) { 806 VerifyCtorDtorAssignverifier;812 PassVisitor<VerifyCtorDtorAssign> verifier; 807 813 acceptAll( translationUnit, verifier ); 808 814 } 809 815 810 void VerifyCtorDtorAssign:: visit( FunctionDecl * funcDecl ) {816 void VerifyCtorDtorAssign::previsit( FunctionDecl * funcDecl ) { 811 817 FunctionType * funcType = funcDecl->get_functionType(); 812 818 std::list< DeclarationWithType * > &returnVals = funcType->get_returnVals(); … … 826 832 } 827 833 } 828 829 Visitor::visit( funcDecl ); 830 } 831 832 DeclarationWithType * CompoundLiteral::mutate( ObjectDecl *objectDecl ) { 834 } 835 836 template< typename Aggr > 837 void validateGeneric( Aggr * inst ) { 838 std::list< TypeDecl * > * params = inst->get_baseParameters(); 839 if ( params != NULL ) { 840 std::list< Expression * > & args = inst->get_parameters(); 841 842 // insert defaults arguments when a type argument is missing (currently only supports missing arguments at the end of the list). 843 // A substitution is used to ensure that defaults are replaced correctly, e.g., 844 // forall(otype T, otype alloc = heap_allocator(T)) struct vector; 845 // vector(int) v; 846 // after insertion of default values becomes 847 // vector(int, heap_allocator(T)) 848 // and the substitution is built with T=int so that after substitution, the result is 849 // vector(int, heap_allocator(int)) 850 TypeSubstitution sub; 851 auto paramIter = params->begin(); 852 for ( size_t i = 0; paramIter != params->end(); ++paramIter, ++i ) { 853 if ( i < args.size() ) { 854 TypeExpr * expr = safe_dynamic_cast< TypeExpr * >( *std::next( args.begin(), i ) ); 855 sub.add( (*paramIter)->get_name(), expr->get_type()->clone() ); 856 } else if ( i == args.size() ) { 857 Type * defaultType = (*paramIter)->get_init(); 858 if ( defaultType ) { 859 args.push_back( new TypeExpr( defaultType->clone() ) ); 860 sub.add( (*paramIter)->get_name(), defaultType->clone() ); 861 } 862 } 863 } 864 865 sub.apply( inst ); 866 if ( args.size() < params->size() ) throw SemanticError( "Too few type arguments in generic type ", inst ); 867 if ( args.size() > params->size() ) throw SemanticError( "Too many type arguments in generic type ", inst ); 868 } 869 } 870 871 void ValidateGenericParameters::previsit( StructInstType * inst ) { 872 validateGeneric( inst ); 873 } 874 875 void ValidateGenericParameters::previsit( UnionInstType * inst ) { 876 validateGeneric( inst ); 877 } 878 879 void CompoundLiteral::premutate( ObjectDecl *objectDecl ) { 833 880 storageClasses = objectDecl->get_storageClasses(); 834 DeclarationWithType * temp = Mutator::mutate( objectDecl ); 835 return temp; 836 } 837 838 Expression *CompoundLiteral::mutate( CompoundLiteralExpr *compLitExpr ) { 881 } 882 883 Expression *CompoundLiteral::postmutate( CompoundLiteralExpr *compLitExpr ) { 839 884 // transform [storage_class] ... (struct S){ 3, ... }; 840 885 // into [storage_class] struct S temp = { 3, ... }; 841 886 static UniqueName indexName( "_compLit" ); 842 887 843 ObjectDecl *tempvar = new ObjectDecl( indexName.newName(), storageClasses, LinkageSpec::C, 0, compLitExpr->get_result(), compLitExpr->get_initializer() );844 compLitExpr->set_result( 0);845 compLitExpr->set_initializer( 0);888 ObjectDecl *tempvar = new ObjectDecl( indexName.newName(), storageClasses, LinkageSpec::C, nullptr, compLitExpr->get_result(), compLitExpr->get_initializer() ); 889 compLitExpr->set_result( nullptr ); 890 compLitExpr->set_initializer( nullptr ); 846 891 delete compLitExpr; 847 DeclarationWithType * newtempvar = mutate( tempvar ); 848 addDeclaration( newtempvar ); // add modified temporary to current block 849 return new VariableExpr( newtempvar ); 892 declsToAddBefore.push_back( tempvar ); // add modified temporary to current block 893 return new VariableExpr( tempvar ); 850 894 } 851 895 852 896 void ReturnTypeFixer::fix( std::list< Declaration * > &translationUnit ) { 853 ReturnTypeFixerfixer;897 PassVisitor<ReturnTypeFixer> fixer; 854 898 acceptAll( translationUnit, fixer ); 855 899 } 856 900 857 void ReturnTypeFixer::visit( FunctionDecl * functionDecl ) { 858 Parent::visit( functionDecl ); 901 void ReturnTypeFixer::postvisit( FunctionDecl * functionDecl ) { 859 902 FunctionType * ftype = functionDecl->get_functionType(); 860 903 std::list< DeclarationWithType * > & retVals = ftype->get_returnVals(); … … 867 910 ret->set_name( toString( "_retval_", CodeGen::genName( functionDecl ) ) ); 868 911 } 869 } 870 } 871 872 void ReturnTypeFixer::visit( FunctionType * ftype ) { 912 ret->get_attributes().push_back( new Attribute( "unused" ) ); 913 } 914 } 915 916 void ReturnTypeFixer::postvisit( FunctionType * ftype ) { 873 917 // xxx - need to handle named return values - this information needs to be saved somehow 874 918 // so that resolution has access to the names. … … 888 932 889 933 void ArrayLength::computeLength( std::list< Declaration * > & translationUnit ) { 890 ArrayLengthlen;934 PassVisitor<ArrayLength> len; 891 935 acceptAll( translationUnit, len ); 892 936 } 893 937 894 void ArrayLength:: visit( ObjectDecl * objDecl ) {938 void ArrayLength::previsit( ObjectDecl * objDecl ) { 895 939 if ( ArrayType * at = dynamic_cast< ArrayType * >( objDecl->get_type() ) ) { 896 940 if ( at->get_dimension() != nullptr ) return;
Note:
See TracChangeset
for help on using the changeset viewer.