summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-03-10 18:52:44 +0000
committerDouglas Gregor <dgregor@apple.com>2009-03-10 18:52:44 +0000
commit27b152fa7443f4e24630b997c07def6b0c23925a (patch)
tree478ae818f13c3655240bf0805502c5ee12840331
parent98137534e612c274ba270af99d73429043957e53 (diff)
downloadclang-27b152fa7443f4e24630b997c07def6b0c23925a.tar.gz
If we run into multiple errors within the same template instantiation,
only print the template instantiation backtrace for the first error. Also, if a base class has failed to type-check during instantiation, just drop that base class and continue on to check other base classes. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66563 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/Sema.h14
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp10
-rw-r--r--test/SemaTemplate/instantiation-backtrace.cpp11
3 files changed, 30 insertions, 5 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index c662301da3..d68924c7c0 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -243,7 +243,10 @@ public:
/// The primitive diagnostic helpers.
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) {
DiagnosticBuilder DB = Diags.Report(FullSourceLoc(Loc, SourceMgr), DiagID);
- if (!Diags.isBuiltinNote(DiagID) && !ActiveTemplateInstantiations.empty())
+ if (!Diags.isBuiltinNote(DiagID) &&
+ !ActiveTemplateInstantiations.empty() &&
+ ActiveTemplateInstantiations.back().Entity
+ != LastTemplateInstantiationErrorContext)
DB << PostDiagnosticHook(PrintInstantiationStackHook, this);
return DB;
}
@@ -1691,6 +1694,15 @@ public:
llvm::SmallVector<ActiveTemplateInstantiation, 16>
ActiveTemplateInstantiations;
+ /// \brief The last template from which a template instantiation
+ /// error or warning was produced.
+ ///
+ /// This value is used to suppress printing of redundant template
+ /// instantiation backtraces when there are multiple errors in the
+ /// same instantiation. FIXME: Does this belong in Sema? It's tough
+ /// to implement it anywhere else.
+ ClassTemplateSpecializationDecl *LastTemplateInstantiationErrorContext;
+
/// \brief A stack object to be created when performing template
/// instantiation.
///
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 4a12b07766..057b256ddd 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -56,7 +56,10 @@ Sema::InstantiatingTemplate::~InstantiatingTemplate() {
/// \brief Post-diagnostic hook for printing the instantiation stack.
void Sema::PrintInstantiationStackHook(unsigned, void *Cookie) {
- static_cast<Sema*>(Cookie)->PrintInstantiationStack();
+ Sema &SemaRef = *static_cast<Sema*>(Cookie);
+ SemaRef.PrintInstantiationStack();
+ SemaRef.LastTemplateInstantiationErrorContext
+ = SemaRef.ActiveTemplateInstantiations.back().Entity;
}
/// \brief Prints the current instantiation stack through a series of
@@ -503,7 +506,7 @@ Sema::InstantiateBaseSpecifiers(
for (ClassTemplateSpecializationDecl::base_class_iterator
Base = ClassTemplate->getTemplatedDecl()->bases_begin(),
BaseEnd = ClassTemplate->getTemplatedDecl()->bases_end();
- Base != BaseEnd && !Invalid; ++Base) {
+ Base != BaseEnd; ++Base) {
if (!Base->getType()->isDependentType()) {
// FIXME: Allocate via ASTContext
InstantiatedBases.push_back(new CXXBaseSpecifier(*Base));
@@ -533,7 +536,8 @@ Sema::InstantiateBaseSpecifiers(
Invalid = true;
}
- if (AttachBaseSpecifiers(ClassTemplateSpec, &InstantiatedBases[0],
+ if (!Invalid &&
+ AttachBaseSpecifiers(ClassTemplateSpec, &InstantiatedBases[0],
InstantiatedBases.size()))
Invalid = true;
diff --git a/test/SemaTemplate/instantiation-backtrace.cpp b/test/SemaTemplate/instantiation-backtrace.cpp
index f8aabff097..10c2de0381 100644
--- a/test/SemaTemplate/instantiation-backtrace.cpp
+++ b/test/SemaTemplate/instantiation-backtrace.cpp
@@ -1,5 +1,5 @@
// RUN: clang -fsyntax-only -verify %s
-template<typename T> struct A; // expected-note 2{{template is declared here}}
+template<typename T> struct A; // expected-note 4{{template is declared here}}
template<typename T> struct B : A<T*> { }; // expected-error{{implicit instantiation of undefined template}} \
// expected-error{{implicit instantiation of undefined template 'struct A<X *>'}}
@@ -21,3 +21,12 @@ typedef struct { } X;
void g() {
(void)sizeof(B<X>); // expected-note{{in instantiation of template class 'struct B<X>' requested here}}
}
+
+template<typename T>
+struct G : A<T>, // expected-error{{implicit instantiation of undefined template 'struct A<int>'}}
+ A<T*> // expected-error{{implicit instantiation of undefined template 'struct A<int *>'}}
+ { };
+
+void h() {
+ (void)sizeof(G<int>); // expected-note{{in instantiation of template class 'struct G<int>' requested here}}
+}