]> granicus.if.org Git - clang/commitdiff
Fix tracking of whether the previous template instantiation stack matches the current...
authorRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 23 Feb 2017 02:09:03 +0000 (02:09 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 23 Feb 2017 02:09:03 +0000 (02:09 +0000)
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
lib/Sema/SemaDecl.cpp
lib/Sema/SemaTemplateInstantiate.cpp
test/CXX/drs/dr4xx.cpp
test/SemaCXX/cxx1y-generic-lambdas.cpp
test/SemaCXX/libstdcxx_pair_swap_hack.cpp
test/SemaCXX/make_integer_seq.cpp

index f55c48d3d7291d85737349b4a48a3ca3658cbbc1..c26eea566f0bf6fc000624160811efd58cc87df1 100644 (file)
@@ -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();
index 2e5e34d7f899ff28cc32ef0ded044e5dd5b57917..62bcabc2903ea8c9b77a6f0ef5dc08a4145d5cae 100644 (file)
@@ -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;
index 94e79f5c50df8ba29ccdbc3fdcd7173953d8f3e0..7b09b77da326e1df4c47f076833dd2e1074802c8 100644 (file)
@@ -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));
index 6046c4afefd555d5cc8a027f59889afcf47cd329..3ea226a745f6b4a8c670fa1481586b81d2e7de6d 100644 (file)
@@ -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 {};
index 3774e8d3834b6da6d9afe058702e87d27251a84f..1993c6e1853dd06679f18dc40db31802d8412da9 100644 (file)
@@ -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
index 9f9c71a50ce103ad54345cd3586e0eb28411a65a..dff599b6d5b661543f263a9eabdcdcdc336b4589 100644 (file)
@@ -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
index a9b8d2b23cb50f48d81a0961efdbdc840250ae5d..8f72ce15eef476ab7cf7b8baf81d2cc215fcfb55 100644 (file)
@@ -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}}