Changes in src/SymTab/Validate.cc [d24d4e1:ce8c12f]
- File:
-
- 1 edited
-
src/SymTab/Validate.cc (modified) (24 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/SymTab/Validate.cc
rd24d4e1 rce8c12f 38 38 // definition occurs later in the input. 39 39 40 #include < algorithm>40 #include <list> 41 41 #include <iterator> 42 #include <list>43 44 #include "CodeGen/CodeGenerator.h"45 46 #include "Common/PassVisitor.h"47 42 #include "Common/ScopedMap.h" 43 #include "Common/utility.h" 48 44 #include "Common/UniqueName.h" 49 #include "Common/utility.h"50 51 45 #include "Concurrency/Keywords.h" 52 53 #include "GenPoly/DeclMutator.h" 54 55 #include "InitTweak/InitTweak.h" 56 57 #include "AddVisit.h" 58 #include "Autogen.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" 59 54 #include "FixFunction.h" 60 55 // #include "ImplementationType.h" 61 #include "Indexer.h" 56 #include "GenPoly/DeclMutator.h" 57 #include "AddVisit.h" 62 58 #include "MakeLibCfa.h" 63 59 #include "TypeEquality.h" 64 #include "Validate.h" 65 60 #include "Autogen.h" 66 61 #include "ResolvExpr/typeops.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" 62 #include <algorithm> 63 #include "InitTweak/InitTweak.h" 64 #include "CodeGen/CodeGenerator.h" 75 65 76 66 #define debugPrint( x ) if ( doDebug ) { std::cout << x; } … … 106 96 107 97 /// Fix return types so that every function returns exactly one value 108 struct ReturnTypeFixer { 98 class ReturnTypeFixer final : public Visitor { 99 public: 100 typedef Visitor Parent; 101 using Parent::visit; 102 109 103 static void fix( std::list< Declaration * > &translationUnit ); 110 104 111 v oid postvisit( FunctionDecl * functionDecl );112 v oid postvisit( FunctionType * ftype );105 virtual void visit( FunctionDecl * functionDecl ); 106 virtual void visit( FunctionType * ftype ); 113 107 }; 114 108 115 109 /// Replaces enum types by int, and function or array types in function parameter and return lists by appropriate pointers. 116 struct EnumAndPointerDecay { 117 void previsit( EnumDecl *aggregateDecl ); 118 void previsit( FunctionType *func ); 110 class EnumAndPointerDecayPass final : public Visitor { 111 typedef Visitor Parent; 112 virtual void visit( EnumDecl *aggregateDecl ); 113 virtual void visit( FunctionType *func ); 119 114 }; 120 115 … … 124 119 public: 125 120 LinkReferenceToTypes( bool doDebug, const Indexer *indexer ); 121 private: 126 122 using Parent::visit; 127 123 void visit( EnumInstType *enumInst ) final; … … 133 129 void visit( UnionDecl *unionDecl ) final; 134 130 void visit( TypeInstType *typeInst ) final; 135 private: 131 136 132 const Indexer *indexer; 137 133 … … 144 140 }; 145 141 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 ForallPointerDecayfinal : public Indexer {142 /// Replaces array and function types in forall lists by appropriate pointer type 143 class Pass3 final : public Indexer { 148 144 typedef Indexer Parent; 149 145 public: 150 146 using Parent::visit; 151 ForallPointerDecay( const Indexer *indexer );152 147 Pass3( const Indexer *indexer ); 148 private: 153 149 virtual void visit( ObjectDecl *object ) override; 154 150 virtual void visit( FunctionDecl *func ) override; … … 157 153 }; 158 154 159 struct ReturnChecker : public WithGuards { 155 class ReturnChecker : public Visitor { 156 public: 160 157 /// Checks that return statements return nothing if their return type is void 161 158 /// and return something if the return type is non-void. 162 159 static void checkFunctionReturns( std::list< Declaration * > & translationUnit ); 163 164 void previsit( FunctionDecl * functionDecl ); 165 void previsit( ReturnStmt * returnStmt ); 166 167 typedef std::list< DeclarationWithType * > ReturnVals; 168 ReturnVals returnVals; 160 private: 161 virtual void visit( FunctionDecl * functionDecl ); 162 virtual void visit( ReturnStmt * returnStmt ); 163 164 std::list< DeclarationWithType * > returnVals; 169 165 }; 170 166 … … 202 198 }; 203 199 204 struct VerifyCtorDtorAssign { 200 class VerifyCtorDtorAssign : public Visitor { 201 public: 205 202 /// ensure that constructors, destructors, and assignment have at least one 206 203 /// parameter, the first of which must be a pointer, and that ctor/dtors have no … … 208 205 static void verify( std::list< Declaration * > &translationUnit ); 209 206 210 v oid previsit( FunctionDecl *funcDecl );207 virtual void visit( FunctionDecl *funcDecl ); 211 208 }; 212 209 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 { 210 class ArrayLength : public Visitor { 211 public: 220 212 /// for array types without an explicit length, compute the length and store it so that it 221 213 /// is known to the rest of the phases. For example, … … 227 219 static void computeLength( std::list< Declaration * > & translationUnit ); 228 220 229 v oid previsit( ObjectDecl * objDecl );221 virtual void visit( ObjectDecl * objDecl ); 230 222 }; 231 223 232 struct CompoundLiteral final : public WithDeclsToAdd, public WithVisitorRef<CompoundLiteral>{224 class CompoundLiteral final : public GenPoly::DeclMutator { 233 225 Type::StorageClasses storageClasses; 234 226 235 void premutate( ObjectDecl *objectDecl ); 236 Expression * postmutate( CompoundLiteralExpr *compLitExpr ); 227 using GenPoly::DeclMutator::mutate; 228 DeclarationWithType * mutate( ObjectDecl *objectDecl ) final; 229 Expression *mutate( CompoundLiteralExpr *compLitExpr ) final; 237 230 }; 238 231 239 232 void validate( std::list< Declaration * > &translationUnit, bool doDebug ) { 240 PassVisitor<EnumAndPointerDecay>epc;233 EnumAndPointerDecayPass epc; 241 234 LinkReferenceToTypes lrt( doDebug, 0 ); 242 ForallPointerDecay fpd( 0 );243 PassVisitor<CompoundLiteral>compoundliteral;244 PassVisitor<ValidateGenericParameters> genericParams; 245 235 Pass3 pass3( 0 ); 236 CompoundLiteral compoundliteral; 237 238 HoistStruct::hoistStruct( translationUnit ); 246 239 EliminateTypedef::eliminateTypedef( translationUnit ); 247 HoistStruct::hoistStruct( translationUnit ); // must happen after EliminateTypedef, so that aggregate typedefs occur in the correct order248 240 ReturnTypeFixer::fix( translationUnit ); // must happen before autogen 249 241 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 LinkReferenceToTypes251 242 acceptAll( translationUnit, epc ); // must happen before VerifyCtorDtorAssign, because void return objects should not exist 252 243 VerifyCtorDtorAssign::verify( translationUnit ); // must happen before autogen, because autogen examines existing ctor/dtors 253 244 Concurrency::applyKeywords( translationUnit ); 254 autogenerateRoutines( translationUnit ); // moved up, used to be below compoundLiteral - currently needs EnumAndPointerDecay 245 autogenerateRoutines( translationUnit ); // moved up, used to be below compoundLiteral - currently needs EnumAndPointerDecayPass 255 246 Concurrency::implementMutexFuncs( translationUnit ); 256 247 Concurrency::implementThreadStarter( translationUnit ); 257 248 ReturnChecker::checkFunctionReturns( translationUnit ); 258 mutateAll( translationUnit, compoundliteral);259 acceptAll( translationUnit, fpd);249 compoundliteral.mutateDeclarationList( translationUnit ); 250 acceptAll( translationUnit, pass3 ); 260 251 ArrayLength::computeLength( translationUnit ); 261 252 } 262 253 263 254 void validateType( Type *type, const Indexer *indexer ) { 264 PassVisitor<EnumAndPointerDecay>epc;255 EnumAndPointerDecayPass epc; 265 256 LinkReferenceToTypes lrt( false, indexer ); 266 ForallPointerDecay fpd( indexer );257 Pass3 pass3( indexer ); 267 258 type->accept( epc ); 268 259 type->accept( lrt ); 269 type->accept( fpd);260 type->accept( pass3 ); 270 261 } 271 262 … … 346 337 } 347 338 348 void EnumAndPointerDecay ::previsit( EnumDecl *enumDecl ) {339 void EnumAndPointerDecayPass::visit( EnumDecl *enumDecl ) { 349 340 // Set the type of each member of the enumeration to be EnumConstant 350 341 for ( std::list< Declaration * >::iterator i = enumDecl->get_members().begin(); i != enumDecl->get_members().end(); ++i ) { … … 353 344 obj->set_type( new EnumInstType( Type::Qualifiers( Type::Const ), enumDecl->get_name() ) ); 354 345 } // for 346 Parent::visit( enumDecl ); 355 347 } 356 348 … … 359 351 void fixFunctionList( DWTList & dwts, FunctionType * func ) { 360 352 // the only case in which "void" is valid is where it is the only one in the list; then it should be removed 361 // entirely .other fix ups are handled by the FixFunction class353 // entirely other fix ups are handled by the FixFunction class 362 354 typedef typename DWTList::iterator DWTIterator; 363 355 DWTIterator begin( dwts.begin() ), end( dwts.end() ); … … 378 370 for ( ; i != end; ++i ) { 379 371 FixFunction fixer; 380 *i = (*i )->acceptMutator( fixer );372 *i = (*i )->acceptMutator( fixer ); 381 373 if ( fixer.get_isVoid() ) { 382 374 throw SemanticError( "invalid type void in function type ", func ); … … 387 379 } 388 380 389 void EnumAndPointerDecay ::previsit( FunctionType *func ) {381 void EnumAndPointerDecayPass::visit( FunctionType *func ) { 390 382 // Fix up parameters and return types 391 383 fixFunctionList( func->get_parameters(), func ); 392 384 fixFunctionList( func->get_returnVals(), func ); 385 Visitor::visit( func ); 393 386 } 394 387 … … 503 496 void LinkReferenceToTypes::visit( StructDecl *structDecl ) { 504 497 // 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)506 498 Parent::visit( structDecl ); 507 499 if ( ! structDecl->get_members().empty() ) { … … 537 529 } 538 530 539 ForallPointerDecay::ForallPointerDecay( const Indexer *other_indexer ) : Indexer( false ) {531 Pass3::Pass3( const Indexer *other_indexer ) : Indexer( false ) { 540 532 if ( other_indexer ) { 541 533 indexer = other_indexer; … … 575 567 } 576 568 577 void ForallPointerDecay::visit( ObjectDecl *object ) {569 void Pass3::visit( ObjectDecl *object ) { 578 570 forallFixer( object->get_type() ); 579 571 if ( PointerType *pointer = dynamic_cast< PointerType * >( object->get_type() ) ) { … … 584 576 } 585 577 586 void ForallPointerDecay::visit( FunctionDecl *func ) {578 void Pass3::visit( FunctionDecl *func ) { 587 579 forallFixer( func->get_type() ); 588 580 Parent::visit( func ); … … 591 583 592 584 void ReturnChecker::checkFunctionReturns( std::list< Declaration * > & translationUnit ) { 593 PassVisitor<ReturnChecker>checker;585 ReturnChecker checker; 594 586 acceptAll( translationUnit, checker ); 595 587 } 596 588 597 void ReturnChecker:: previsit( FunctionDecl * functionDecl ) {598 GuardValue( returnVals );589 void ReturnChecker::visit( FunctionDecl * functionDecl ) { 590 std::list< DeclarationWithType * > oldReturnVals = returnVals; 599 591 returnVals = functionDecl->get_functionType()->get_returnVals(); 600 } 601 602 void ReturnChecker::previsit( ReturnStmt * returnStmt ) { 592 Visitor::visit( functionDecl ); 593 returnVals = oldReturnVals; 594 } 595 596 void ReturnChecker::visit( ReturnStmt * returnStmt ) { 603 597 // Previously this also checked for the existence of an expr paired with no return values on 604 598 // the function return type. This is incorrect, since you can have an expression attached to … … 810 804 811 805 void VerifyCtorDtorAssign::verify( std::list< Declaration * > & translationUnit ) { 812 PassVisitor<VerifyCtorDtorAssign>verifier;806 VerifyCtorDtorAssign verifier; 813 807 acceptAll( translationUnit, verifier ); 814 808 } 815 809 816 void VerifyCtorDtorAssign:: previsit( FunctionDecl * funcDecl ) {810 void VerifyCtorDtorAssign::visit( FunctionDecl * funcDecl ) { 817 811 FunctionType * funcType = funcDecl->get_functionType(); 818 812 std::list< DeclarationWithType * > &returnVals = funcType->get_returnVals(); … … 824 818 } 825 819 PointerType * ptrType = dynamic_cast< PointerType * >( params.front()->get_type() ); 826 if ( ! ptrType || ptrType->is_array() ) { 820 ReferenceType * refType = dynamic_cast< ReferenceType * >( params.front()->get_type() ); 821 if ( ( ! ptrType && ! refType ) || ( ptrType && ptrType->is_array() ) ) { 827 822 throw SemanticError( "First parameter of a constructor, destructor, or assignment function must be a pointer ", funcDecl ); 828 823 } … … 831 826 } 832 827 } 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 ) { 828 829 Visitor::visit( funcDecl ); 830 } 831 832 DeclarationWithType * CompoundLiteral::mutate( ObjectDecl *objectDecl ) { 879 833 storageClasses = objectDecl->get_storageClasses(); 880 } 881 882 Expression *CompoundLiteral::postmutate( CompoundLiteralExpr *compLitExpr ) { 834 DeclarationWithType * temp = Mutator::mutate( objectDecl ); 835 return temp; 836 } 837 838 Expression *CompoundLiteral::mutate( CompoundLiteralExpr *compLitExpr ) { 883 839 // transform [storage_class] ... (struct S){ 3, ... }; 884 840 // into [storage_class] struct S temp = { 3, ... }; 885 841 static UniqueName indexName( "_compLit" ); 886 842 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);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 ); 890 846 delete compLitExpr; 891 declsToAddBefore.push_back( tempvar ); // add modified temporary to current block 892 return new VariableExpr( tempvar ); 847 DeclarationWithType * newtempvar = mutate( tempvar ); 848 addDeclaration( newtempvar ); // add modified temporary to current block 849 return new VariableExpr( newtempvar ); 893 850 } 894 851 895 852 void ReturnTypeFixer::fix( std::list< Declaration * > &translationUnit ) { 896 PassVisitor<ReturnTypeFixer>fixer;853 ReturnTypeFixer fixer; 897 854 acceptAll( translationUnit, fixer ); 898 855 } 899 856 900 void ReturnTypeFixer::postvisit( FunctionDecl * functionDecl ) { 857 void ReturnTypeFixer::visit( FunctionDecl * functionDecl ) { 858 Parent::visit( functionDecl ); 901 859 FunctionType * ftype = functionDecl->get_functionType(); 902 860 std::list< DeclarationWithType * > & retVals = ftype->get_returnVals(); … … 909 867 ret->set_name( toString( "_retval_", CodeGen::genName( functionDecl ) ) ); 910 868 } 911 ret->get_attributes().push_back( new Attribute( "unused" ) ); 912 } 913 } 914 915 void ReturnTypeFixer::postvisit( FunctionType * ftype ) { 869 } 870 } 871 872 void ReturnTypeFixer::visit( FunctionType * ftype ) { 916 873 // xxx - need to handle named return values - this information needs to be saved somehow 917 874 // so that resolution has access to the names. … … 931 888 932 889 void ArrayLength::computeLength( std::list< Declaration * > & translationUnit ) { 933 PassVisitor<ArrayLength>len;890 ArrayLength len; 934 891 acceptAll( translationUnit, len ); 935 892 } 936 893 937 void ArrayLength:: previsit( ObjectDecl * objDecl ) {894 void ArrayLength::visit( ObjectDecl * objDecl ) { 938 895 if ( ArrayType * at = dynamic_cast< ArrayType * >( objDecl->get_type() ) ) { 939 896 if ( at->get_dimension() != nullptr ) return;
Note:
See TracChangeset
for help on using the changeset viewer.