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.

llvm-svn: 66563
This commit is contained in:
Douglas Gregor 2009-03-10 18:52:44 +00:00
parent 79fc0e9250
commit 2a72edd413
3 changed files with 30 additions and 5 deletions

View File

@ -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.
///

View File

@ -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;

View File

@ -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}}
}