#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/OwningPtr.h"
+#include <deque>
#include <list>
#include <string>
-#include <queue>
#include <vector>
namespace llvm {
/// \brief The queue of implicit template instantiations that are required
/// but have not yet been performed.
- std::queue<PendingImplicitInstantiation> PendingImplicitInstantiations;
+ std::deque<PendingImplicitInstantiation> PendingImplicitInstantiations;
void PerformPendingImplicitInstantiations();
const TemplateArgumentList &TemplateArgs);
void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
- FunctionDecl *Function);
+ FunctionDecl *Function,
+ bool Recursive = false);
void InstantiateVariableDefinition(VarDecl *Var);
NamedDecl *InstantiateCurrentDeclRef(NamedDecl *D);
/// \brief Instantiate the definition of the given function from its
/// template.
///
+/// \param PointOfInstantiation the point at which the instantiation was
+/// required. Note that this is not precisely a "point of instantiation"
+/// for the function, but it's close.
+///
/// \param Function the already-instantiated declaration of a
-/// function.
+/// function template specialization or member function of a class template
+/// specialization.
+///
+/// \param Recursive if true, recursively instantiates any functions that
+/// are required by this instantiation.
void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
- FunctionDecl *Function) {
+ FunctionDecl *Function,
+ bool Recursive) {
if (Function->isInvalidDecl())
return;
if (Inst)
return;
+ // 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.
+ std::deque<PendingImplicitInstantiation> SavedPendingImplicitInstantiations;
+ if (Recursive)
+ PendingImplicitInstantiations.swap(SavedPendingImplicitInstantiations);
+
ActOnStartOfFunctionDef(0, DeclPtrTy::make(Function));
// Introduce a new scope where local variable instantiations will be
DeclGroupRef DG(Function);
Consumer.HandleTopLevelDecl(DG);
+
+ if (Recursive) {
+ // Instantiate any pending implicit instantiations found during the
+ // instantiation of this template.
+ PerformPendingImplicitInstantiations();
+
+ // Restore the set of pending implicit instantiations.
+ PendingImplicitInstantiations.swap(SavedPendingImplicitInstantiations);
+ }
}
/// \brief Instantiate the definition of the given variable from its
void Sema::PerformPendingImplicitInstantiations() {
while (!PendingImplicitInstantiations.empty()) {
PendingImplicitInstantiation Inst = PendingImplicitInstantiations.front();
- PendingImplicitInstantiations.pop();
+ PendingImplicitInstantiations.pop_front();
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Inst.first))
if (!Function->getBody())
- InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function);
+ InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function, true);
// FIXME: instantiate static member variables
}