diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Sema/Sema.cpp | 40 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 30 |
2 files changed, 37 insertions, 33 deletions
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 6ca8be2999..8297b3155a 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -378,30 +378,22 @@ void Sema::ActOnEndOfTranslationUnit() { } } - bool SomethingChanged; - do { - SomethingChanged = false; - - // If DefinedUsedVTables ends up marking any virtual member functions it - // might lead to more pending template instantiations, which we then need - // to instantiate. - if (DefineUsedVTables()) - SomethingChanged = true; - - // C++: Perform implicit template instantiations. - // - // FIXME: When we perform these implicit instantiations, we do not - // carefully keep track of the point of instantiation (C++ [temp.point]). - // This means that name lookup that occurs within the template - // instantiation will always happen at the end of the translation unit, - // so it will find some names that should not be found. Although this is - // common behavior for C++ compilers, it is technically wrong. In the - // future, we either need to be able to filter the results of name lookup - // or we need to perform template instantiations earlier. - if (PerformPendingInstantiations()) - SomethingChanged = true; - - } while (SomethingChanged); + // If DefinedUsedVTables ends up marking any virtual member functions it + // might lead to more pending template instantiations, which we then need + // to instantiate. + DefineUsedVTables(); + + // C++: Perform implicit template instantiations. + // + // FIXME: When we perform these implicit instantiations, we do not + // carefully keep track of the point of instantiation (C++ [temp.point]). + // This means that name lookup that occurs within the template + // instantiation will always happen at the end of the translation unit, + // so it will find some names that should not be found. Although this is + // common behavior for C++ compilers, it is technically wrong. In the + // future, we either need to be able to filter the results of name lookup + // or we need to perform template instantiations earlier. + PerformPendingInstantiations(); } // Remove file scoped decls that turned out to be used. diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index bf1e4996ec..adf9b2f3cb 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2481,9 +2481,13 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, PerformPendingInstantiations(); // Restore the set of pending vtables. + assert(VTableUses.empty() && + "VTableUses should be empty before it is discarded."); VTableUses.swap(SavedVTableUses); // Restore the set of pending implicit instantiations. + assert(PendingInstantiations.empty() && + "PendingInstantiations should be empty before it is discarded."); PendingInstantiations.swap(SavedPendingInstantiations); } } @@ -2557,9 +2561,12 @@ void Sema::InstantiateStaticDataMemberDefinition( // If we're performing recursive template instantiation, create our own // queue of pending implicit instantiations that we will instantiate later, // while we're still within our own instantiation context. + llvm::SmallVector<VTableUse, 16> SavedVTableUses; std::deque<PendingImplicitInstantiation> SavedPendingInstantiations; - if (Recursive) + if (Recursive) { + VTableUses.swap(SavedVTableUses); PendingInstantiations.swap(SavedPendingInstantiations); + } // Enter the scope of this instantiation. We don't use // PushDeclContext because we don't have a scope. @@ -2581,11 +2588,23 @@ void Sema::InstantiateStaticDataMemberDefinition( } if (Recursive) { + // Define any newly required vtables. + DefineUsedVTables(); + // Instantiate any pending implicit instantiations found during the // instantiation of this template. PerformPendingInstantiations(); + // Restore the set of pending vtables. + assert(VTableUses.empty() && + "VTableUses should be empty before it is discarded, " + "while instantiating static data member."); + VTableUses.swap(SavedVTableUses); + // Restore the set of pending implicit instantiations. + assert(PendingInstantiations.empty() && + "PendingInstantiations should be empty before it is discarded, " + "while instantiating static data member."); PendingInstantiations.swap(SavedPendingInstantiations); } } @@ -3181,10 +3200,7 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, /// \brief Performs template instantiation for all implicit template /// instantiations we have seen until this point. -/// -/// \returns true if anything was instantiated. -bool Sema::PerformPendingInstantiations(bool LocalOnly) { - bool InstantiatedAnything = false; +void Sema::PerformPendingInstantiations(bool LocalOnly) { while (!PendingLocalImplicitInstantiations.empty() || (!LocalOnly && !PendingInstantiations.empty())) { PendingImplicitInstantiation Inst; @@ -3205,7 +3221,6 @@ bool Sema::PerformPendingInstantiations(bool LocalOnly) { TSK_ExplicitInstantiationDefinition; InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function, true, DefinitionRequired); - InstantiatedAnything = true; continue; } @@ -3242,10 +3257,7 @@ bool Sema::PerformPendingInstantiations(bool LocalOnly) { TSK_ExplicitInstantiationDefinition; InstantiateStaticDataMemberDefinition(/*FIXME:*/Inst.second, Var, true, DefinitionRequired); - InstantiatedAnything = true; } - - return InstantiatedAnything; } void Sema::PerformDependentDiagnostics(const DeclContext *Pattern, |