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. /// The primitive diagnostic helpers.
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) { DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) {
DiagnosticBuilder DB = Diags.Report(FullSourceLoc(Loc, SourceMgr), 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); DB << PostDiagnosticHook(PrintInstantiationStackHook, this);
return DB; return DB;
} }
@ -1691,6 +1694,15 @@ public:
llvm::SmallVector<ActiveTemplateInstantiation, 16> llvm::SmallVector<ActiveTemplateInstantiation, 16>
ActiveTemplateInstantiations; 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 /// \brief A stack object to be created when performing template
/// instantiation. /// instantiation.
/// ///

View File

@ -56,7 +56,10 @@ Sema::InstantiatingTemplate::~InstantiatingTemplate() {
/// \brief Post-diagnostic hook for printing the instantiation stack. /// \brief Post-diagnostic hook for printing the instantiation stack.
void Sema::PrintInstantiationStackHook(unsigned, void *Cookie) { 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 /// \brief Prints the current instantiation stack through a series of
@ -503,7 +506,7 @@ Sema::InstantiateBaseSpecifiers(
for (ClassTemplateSpecializationDecl::base_class_iterator for (ClassTemplateSpecializationDecl::base_class_iterator
Base = ClassTemplate->getTemplatedDecl()->bases_begin(), Base = ClassTemplate->getTemplatedDecl()->bases_begin(),
BaseEnd = ClassTemplate->getTemplatedDecl()->bases_end(); BaseEnd = ClassTemplate->getTemplatedDecl()->bases_end();
Base != BaseEnd && !Invalid; ++Base) { Base != BaseEnd; ++Base) {
if (!Base->getType()->isDependentType()) { if (!Base->getType()->isDependentType()) {
// FIXME: Allocate via ASTContext // FIXME: Allocate via ASTContext
InstantiatedBases.push_back(new CXXBaseSpecifier(*Base)); InstantiatedBases.push_back(new CXXBaseSpecifier(*Base));
@ -533,7 +536,8 @@ Sema::InstantiateBaseSpecifiers(
Invalid = true; Invalid = true;
} }
if (AttachBaseSpecifiers(ClassTemplateSpec, &InstantiatedBases[0], if (!Invalid &&
AttachBaseSpecifiers(ClassTemplateSpec, &InstantiatedBases[0],
InstantiatedBases.size())) InstantiatedBases.size()))
Invalid = true; Invalid = true;

View File

@ -1,5 +1,5 @@
// RUN: clang -fsyntax-only -verify %s // 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}} \ template<typename T> struct B : A<T*> { }; // expected-error{{implicit instantiation of undefined template}} \
// expected-error{{implicit instantiation of undefined template 'struct A<X *>'}} // expected-error{{implicit instantiation of undefined template 'struct A<X *>'}}
@ -21,3 +21,12 @@ typedef struct { } X;
void g() { void g() {
(void)sizeof(B<X>); // expected-note{{in instantiation of template class 'struct B<X>' requested here}} (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}}
}