Changes in src/SymTab/Validate.cc [ce8c12f:d24d4e1]
- File:
-
- 1 edited
-
src/SymTab/Validate.cc (modified) (24 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/SymTab/Validate.cc
rce8c12f rd24d4e1 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(); … … 818 824 } 819 825 PointerType * ptrType = dynamic_cast< PointerType * >( params.front()->get_type() ); 820 ReferenceType * refType = dynamic_cast< ReferenceType * >( params.front()->get_type() ); 821 if ( ( ! ptrType && ! refType ) || ( ptrType && ptrType->is_array() ) ) { 826 if ( ! ptrType || ptrType->is_array() ) { 822 827 throw SemanticError( "First parameter of a constructor, destructor, or assignment function must be a pointer ", funcDecl ); 823 828 } … … 826 831 } 827 832 } 828 829 Visitor::visit( funcDecl ); 830 } 831 832 DeclarationWithType * CompoundLiteral::mutate( ObjectDecl *objectDecl ) { 833 } 834 835 template< typename Aggr > 836 void validateGeneric( Aggr * inst ) { 837 std::list< TypeDecl * > * params = inst->get_baseParameters(); 838 if ( params != NULL ) { 839 std::list< Expression * > & args = inst->get_parameters(); 840 841 // insert defaults arguments when a type argument is missing (currently only supports missing arguments at the end of the list). 842 // A substitution is used to ensure that defaults are replaced correctly, e.g., 843 // forall(otype T, otype alloc = heap_allocator(T)) struct vector; 844 // vector(int) v; 845 // after insertion of default values becomes 846 // vector(int, heap_allocator(T)) 847 // and the substitution is built with T=int so that after substitution, the result is 848 // vector(int, heap_allocator(int)) 849 TypeSubstitution sub; 850 auto paramIter = params->begin(); 851 for ( size_t i = 0; paramIter != params->end(); ++paramIter, ++i ) { 852 if ( i < args.size() ) { 853 TypeExpr * expr = safe_dynamic_cast< TypeExpr * >( *std::next( args.begin(), i ) ); 854 sub.add( (*paramIter)->get_name(), expr->get_type()->clone() ); 855 } else if ( i == args.size() ) { 856 Type * defaultType = (*paramIter)->get_init(); 857 if ( defaultType ) { 858 args.push_back( new TypeExpr( defaultType->clone() ) ); 859 sub.add( (*paramIter)->get_name(), defaultType->clone() ); 860 } 861 } 862 } 863 864 sub.apply( inst ); 865 if ( args.size() < params->size() ) throw SemanticError( "Too few type arguments in generic type ", inst ); 866 if ( args.size() > params->size() ) throw SemanticError( "Too many type arguments in generic type ", inst ); 867 } 868 } 869 870 void ValidateGenericParameters::previsit( StructInstType * inst ) { 871 validateGeneric( inst ); 872 } 873 874 void ValidateGenericParameters::previsit( UnionInstType * inst ) { 875 validateGeneric( inst ); 876 } 877 878 void CompoundLiteral::premutate( ObjectDecl *objectDecl ) { 833 879 storageClasses = objectDecl->get_storageClasses(); 834 DeclarationWithType * temp = Mutator::mutate( objectDecl ); 835 return temp; 836 } 837 838 Expression *CompoundLiteral::mutate( CompoundLiteralExpr *compLitExpr ) { 880 } 881 882 Expression *CompoundLiteral::postmutate( CompoundLiteralExpr *compLitExpr ) { 839 883 // transform [storage_class] ... (struct S){ 3, ... }; 840 884 // into [storage_class] struct S temp = { 3, ... }; 841 885 static UniqueName indexName( "_compLit" ); 842 886 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);887 ObjectDecl *tempvar = new ObjectDecl( indexName.newName(), storageClasses, LinkageSpec::C, nullptr, compLitExpr->get_result(), compLitExpr->get_initializer() ); 888 compLitExpr->set_result( nullptr ); 889 compLitExpr->set_initializer( nullptr ); 846 890 delete compLitExpr; 847 DeclarationWithType * newtempvar = mutate( tempvar ); 848 addDeclaration( newtempvar ); // add modified temporary to current block 849 return new VariableExpr( newtempvar ); 891 declsToAddBefore.push_back( tempvar ); // add modified temporary to current block 892 return new VariableExpr( tempvar ); 850 893 } 851 894 852 895 void ReturnTypeFixer::fix( std::list< Declaration * > &translationUnit ) { 853 ReturnTypeFixerfixer;896 PassVisitor<ReturnTypeFixer> fixer; 854 897 acceptAll( translationUnit, fixer ); 855 898 } 856 899 857 void ReturnTypeFixer::visit( FunctionDecl * functionDecl ) { 858 Parent::visit( functionDecl ); 900 void ReturnTypeFixer::postvisit( FunctionDecl * functionDecl ) { 859 901 FunctionType * ftype = functionDecl->get_functionType(); 860 902 std::list< DeclarationWithType * > & retVals = ftype->get_returnVals(); … … 867 909 ret->set_name( toString( "_retval_", CodeGen::genName( functionDecl ) ) ); 868 910 } 869 } 870 } 871 872 void ReturnTypeFixer::visit( FunctionType * ftype ) { 911 ret->get_attributes().push_back( new Attribute( "unused" ) ); 912 } 913 } 914 915 void ReturnTypeFixer::postvisit( FunctionType * ftype ) { 873 916 // xxx - need to handle named return values - this information needs to be saved somehow 874 917 // so that resolution has access to the names. … … 888 931 889 932 void ArrayLength::computeLength( std::list< Declaration * > & translationUnit ) { 890 ArrayLengthlen;933 PassVisitor<ArrayLength> len; 891 934 acceptAll( translationUnit, len ); 892 935 } 893 936 894 void ArrayLength:: visit( ObjectDecl * objDecl ) {937 void ArrayLength::previsit( ObjectDecl * objDecl ) { 895 938 if ( ArrayType * at = dynamic_cast< ArrayType * >( objDecl->get_type() ) ) { 896 939 if ( at->get_dimension() != nullptr ) return;
Note:
See TracChangeset
for help on using the changeset viewer.