When recursively instantiating function templates, keep track of the
instantiation stack so that we provide a full instantiation
backtrace. Previously, we performed all of the instantiations implied
by the recursion, but each looked like a "top-level" instantiation.
The included test case tests the previous fix for the instantiation of
DeclRefExprs. Note that the "instantiated from" diagnostics still
don't tell us which template arguments we're instantiating with.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@74540 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 42c4329..308a78c 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -29,9 +29,9 @@
#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 {
@@ -2581,7 +2581,7 @@
/// \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();
@@ -2636,7 +2636,8 @@
const TemplateArgumentList &TemplateArgs);
void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
- FunctionDecl *Function);
+ FunctionDecl *Function,
+ bool Recursive = false);
void InstantiateVariableDefinition(VarDecl *Var);
NamedDecl *InstantiateCurrentDeclRef(NamedDecl *D);
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 1c5b760..d66b002 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -5641,7 +5641,7 @@
// instantiated, naturally).
if (Function->getInstantiatedFromMemberFunction() ||
Function->getPrimaryTemplate())
- PendingImplicitInstantiations.push(std::make_pair(Function, Loc));
+ PendingImplicitInstantiations.push_back(std::make_pair(Function, Loc));
}
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 7053bba..769e0d2 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -663,10 +663,19 @@
/// \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;
@@ -689,6 +698,13 @@
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
@@ -717,6 +733,15 @@
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
@@ -859,11 +884,11 @@
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
}
diff --git a/test/CXX/basic/basic.def.odr/p2-typeid.cpp b/test/CXX/basic/basic.def.odr/p2-typeid.cpp
index 7eb10ef..881212d 100644
--- a/test/CXX/basic/basic.def.odr/p2-typeid.cpp
+++ b/test/CXX/basic/basic.def.odr/p2-typeid.cpp
@@ -32,5 +32,5 @@
xnpr.g(NonPoly());
// Triggers an error (as it should);
- xpr.g(Poly());
+ xpr.g(Poly()); // expected-note{{instantiation of member function}}
}
diff --git a/test/SemaTemplate/recursive-template-instantiation.cpp b/test/SemaTemplate/recursive-template-instantiation.cpp
new file mode 100644
index 0000000..7c88d50
--- /dev/null
+++ b/test/SemaTemplate/recursive-template-instantiation.cpp
@@ -0,0 +1,10 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<typename T> void f(T* t) {
+ f(*t); // expected-error{{no matching function}}\
+ // expected-note 3{{requested here}}
+}
+
+void test_f(int ****p) {
+ f(p); // expected-note{{requested here}}
+}