forked from OSchip/llvm-project
Fix tracking of whether the previous template instantiation stack matches the current one.
Rather than attempting to compare whether the previous and current top of context stack are "equal" (which fails for a number of reasons, such as the context stack entries containing pointers to objects on the stack, or reaching the same "top of stack" entry through two different paths), track the depth of context stack at which we last emitted a note and invalidate it when we pop the context stack to less than that depth. This causes us to emit some missing "in instantiation of" notes and to stop emitting redundant "in instantiation of" stacks matching the previous stack in rare cases. llvm-svn: 295921
This commit is contained in:
parent
dfec3c8e95
commit
73c3c21fae
|
@ -6922,39 +6922,6 @@ public:
|
|||
/// \brief Determines whether this template is an actual instantiation
|
||||
/// that should be counted toward the maximum instantiation depth.
|
||||
bool isInstantiationRecord() const;
|
||||
|
||||
friend bool operator==(const CodeSynthesisContext &X,
|
||||
const CodeSynthesisContext &Y) {
|
||||
if (X.Kind != Y.Kind)
|
||||
return false;
|
||||
|
||||
if (X.Entity != Y.Entity)
|
||||
return false;
|
||||
|
||||
switch (X.Kind) {
|
||||
case TemplateInstantiation:
|
||||
case ExceptionSpecInstantiation:
|
||||
return true;
|
||||
|
||||
case PriorTemplateArgumentSubstitution:
|
||||
case DefaultTemplateArgumentChecking:
|
||||
return X.Template == Y.Template && X.TemplateArgs == Y.TemplateArgs;
|
||||
|
||||
case DefaultTemplateArgumentInstantiation:
|
||||
case ExplicitTemplateArgumentSubstitution:
|
||||
case DeducedTemplateArgumentSubstitution:
|
||||
case DefaultFunctionArgumentInstantiation:
|
||||
return X.TemplateArgs == Y.TemplateArgs;
|
||||
|
||||
}
|
||||
|
||||
llvm_unreachable("Invalid InstantiationKind!");
|
||||
}
|
||||
|
||||
friend bool operator!=(const CodeSynthesisContext &X,
|
||||
const CodeSynthesisContext &Y) {
|
||||
return !(X == Y);
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief List of active code synthesis contexts.
|
||||
|
@ -7004,14 +6971,13 @@ public:
|
|||
// FIXME: Should we have a similar limit for other forms of synthesis?
|
||||
unsigned NonInstantiationEntries;
|
||||
|
||||
/// \brief The last template from which a template instantiation
|
||||
/// \brief The depth of the context stack at the point when the most recent
|
||||
/// 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.
|
||||
CodeSynthesisContext LastTemplateInstantiationErrorContext;
|
||||
/// This value is used to suppress printing of redundant context stacks
|
||||
/// when there are multiple errors or warnings in the same instantiation.
|
||||
// FIXME: Does this belong in Sema? It's tough to implement it anywhere else.
|
||||
unsigned LastEmittedCodeSynthesisContextDepth = 0;
|
||||
|
||||
/// \brief The current index into pack expansion arguments that will be
|
||||
/// used for substitution of parameter packs.
|
||||
|
@ -7192,11 +7158,9 @@ public:
|
|||
|
||||
void PrintContextStack() {
|
||||
if (!CodeSynthesisContexts.empty() &&
|
||||
CodeSynthesisContexts.back() !=
|
||||
LastTemplateInstantiationErrorContext) {
|
||||
CodeSynthesisContexts.size() != LastEmittedCodeSynthesisContextDepth) {
|
||||
PrintInstantiationStack();
|
||||
LastTemplateInstantiationErrorContext =
|
||||
CodeSynthesisContexts.back();
|
||||
LastEmittedCodeSynthesisContextDepth = CodeSynthesisContexts.size();
|
||||
}
|
||||
}
|
||||
void PrintInstantiationStack();
|
||||
|
|
|
@ -11774,9 +11774,6 @@ static void RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator,
|
|||
|
||||
Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,
|
||||
SkipBodyInfo *SkipBody) {
|
||||
// Clear the last template instantiation error context.
|
||||
LastTemplateInstantiationErrorContext = CodeSynthesisContext();
|
||||
|
||||
if (!D)
|
||||
return D;
|
||||
FunctionDecl *FD = nullptr;
|
||||
|
|
|
@ -369,6 +369,12 @@ void Sema::InstantiatingTemplate::Clear() {
|
|||
SemaRef.CodeSynthesisContextLookupModules.pop_back();
|
||||
}
|
||||
|
||||
// If we've left the code synthesis context for the current context stack,
|
||||
// stop remembering that we've emitted that stack.
|
||||
if (SemaRef.CodeSynthesisContexts.size() ==
|
||||
SemaRef.LastEmittedCodeSynthesisContextDepth)
|
||||
SemaRef.LastEmittedCodeSynthesisContextDepth = 0;
|
||||
|
||||
if (!AlreadyInstantiating)
|
||||
SemaRef.InstantiatingSpecializations.erase(
|
||||
std::make_pair(Active.Entity, Active.Kind));
|
||||
|
|
|
@ -35,9 +35,7 @@ namespace dr401 { // dr401: yes
|
|||
};
|
||||
|
||||
A<B> *b; // expected-note {{default argument}}
|
||||
// FIXME: We're missing the "in instantiation of" note for the default
|
||||
// argument here.
|
||||
A<D> *d;
|
||||
A<D> *d; // expected-note {{in instantiation of default argument}}
|
||||
|
||||
struct E {
|
||||
template<class T, class U = typename T::type> class A : public T {};
|
||||
|
|
|
@ -912,7 +912,7 @@ struct X1 {
|
|||
template<class T>
|
||||
template<class U>
|
||||
int X1::X2<T>::fooG3(T (*fp)(U)) { return 0; }
|
||||
X1::X2<int> x2; //expected-note 3{{in instantiation of}}
|
||||
X1::X2<int> x2; //expected-note {{in instantiation of}}
|
||||
int run1 = x2.fooG2();
|
||||
int run2 = x2.fooG3();
|
||||
} // end ns
|
||||
|
|
|
@ -88,7 +88,7 @@ namespace sad {
|
|||
|
||||
CLASS<int, int> pi;
|
||||
|
||||
static_assert(!noexcept(pi.swap(pi)), ""); // expected-note {{in instantiation of}}
|
||||
static_assert(!noexcept(pi.swap(pi)), ""); // expected-note 2{{in instantiation of exception specification for 'swap'}}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -43,7 +43,7 @@ enum Color : int { Red,
|
|||
Blue };
|
||||
using illformed1 = ErrorSeq<Color, Blue>; // expected-note{{in instantiation}}
|
||||
|
||||
using illformed2 = ErrorSeq<int, -5>;
|
||||
using illformed2 = ErrorSeq<int, -5>; // expected-note{{in instantiation}}
|
||||
|
||||
template <typename T, T N> void f() {}
|
||||
__make_integer_seq<f, int, 0> x; // expected-error{{template template parameter must be a class template or type alias template}}
|
||||
|
|
Loading…
Reference in New Issue