forked from OSchip/llvm-project
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:
parent
79fc0e9250
commit
2a72edd413
|
@ -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.
|
||||||
///
|
///
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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}}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue