From 1a04b13fd8f7b63a60f34c0e64dd184559ba8c74 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Thu, 23 Feb 2017 02:09:03 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@295921 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Sema/Sema.h | 50 ++++------------------- lib/Sema/SemaDecl.cpp | 3 -- lib/Sema/SemaTemplateInstantiate.cpp | 6 +++ test/CXX/drs/dr4xx.cpp | 4 +- test/SemaCXX/cxx1y-generic-lambdas.cpp | 2 +- test/SemaCXX/libstdcxx_pair_swap_hack.cpp | 2 +- test/SemaCXX/make_integer_seq.cpp | 2 +- 7 files changed, 17 insertions(+), 52 deletions(-) diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index f55c48d3d7..c26eea566f 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -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(); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 2e5e34d7f8..62bcabc290 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -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; diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 94e79f5c50..7b09b77da3 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -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)); diff --git a/test/CXX/drs/dr4xx.cpp b/test/CXX/drs/dr4xx.cpp index 6046c4afef..3ea226a745 100644 --- a/test/CXX/drs/dr4xx.cpp +++ b/test/CXX/drs/dr4xx.cpp @@ -35,9 +35,7 @@ namespace dr401 { // dr401: yes }; A *b; // expected-note {{default argument}} - // FIXME: We're missing the "in instantiation of" note for the default - // argument here. - A *d; + A *d; // expected-note {{in instantiation of default argument}} struct E { template class A : public T {}; diff --git a/test/SemaCXX/cxx1y-generic-lambdas.cpp b/test/SemaCXX/cxx1y-generic-lambdas.cpp index 3774e8d383..1993c6e185 100644 --- a/test/SemaCXX/cxx1y-generic-lambdas.cpp +++ b/test/SemaCXX/cxx1y-generic-lambdas.cpp @@ -912,7 +912,7 @@ struct X1 { template template int X1::X2::fooG3(T (*fp)(U)) { return 0; } -X1::X2 x2; //expected-note 3{{in instantiation of}} +X1::X2 x2; //expected-note {{in instantiation of}} int run1 = x2.fooG2(); int run2 = x2.fooG3(); } // end ns diff --git a/test/SemaCXX/libstdcxx_pair_swap_hack.cpp b/test/SemaCXX/libstdcxx_pair_swap_hack.cpp index 9f9c71a50c..dff599b6d5 100644 --- a/test/SemaCXX/libstdcxx_pair_swap_hack.cpp +++ b/test/SemaCXX/libstdcxx_pair_swap_hack.cpp @@ -88,7 +88,7 @@ namespace sad { CLASS 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 diff --git a/test/SemaCXX/make_integer_seq.cpp b/test/SemaCXX/make_integer_seq.cpp index a9b8d2b23c..8f72ce15ee 100644 --- a/test/SemaCXX/make_integer_seq.cpp +++ b/test/SemaCXX/make_integer_seq.cpp @@ -43,7 +43,7 @@ enum Color : int { Red, Blue }; using illformed1 = ErrorSeq; // expected-note{{in instantiation}} -using illformed2 = ErrorSeq; +using illformed2 = ErrorSeq; // expected-note{{in instantiation}} template void f() {} __make_integer_seq x; // expected-error{{template template parameter must be a class template or type alias template}} -- 2.50.1