r328567 - [MS] Fix late-parsed template infinite loop in eager instantiation

Reid Kleckner via cfe-commits cfe-commits at lists.llvm.org
Mon Mar 26 11:22:47 PDT 2018


Author: rnk
Date: Mon Mar 26 11:22:47 2018
New Revision: 328567

URL: http://llvm.org/viewvc/llvm-project?rev=328567&view=rev
Log:
[MS] Fix late-parsed template infinite loop in eager instantiation

Summary:
This fixes PR33561 and PR34185.

Don't store pending template instantiations for late-parsed templates in
the normal PendingInstantiations queue. Instead, use a separate list
that will only be parsed and instantiated at end of TU when late
template parsing actually works and doesn't infinite loop.

Reviewers: rsmith, thakis, hans

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D44846

Added:
    cfe/trunk/test/PCH/late-parsed-instantiations.cpp
    cfe/trunk/test/SemaTemplate/late-parsing-eager-instantiation.cpp
Modified:
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Sema/Sema.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=328567&r1=328566&r2=328567&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Mon Mar 26 11:22:47 2018
@@ -7550,6 +7550,10 @@ public:
   /// but have not yet been performed.
   std::deque<PendingImplicitInstantiation> PendingInstantiations;
 
+  /// Queue of implicit template instantiations that cannot be performed
+  /// eagerly.
+  SmallVector<PendingImplicitInstantiation, 1> LateParsedInstantiations;
+
   class GlobalEagerInstantiationScope {
   public:
     GlobalEagerInstantiationScope(Sema &S, bool Enabled)

Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=328567&r1=328566&r2=328567&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Mon Mar 26 11:22:47 2018
@@ -850,6 +850,20 @@ void Sema::ActOnEndOfTranslationUnit() {
   if (PP.isCodeCompletionEnabled())
     return;
 
+  // Transfer late parsed template instantiations over to the pending template
+  // instantiation list. During normal compliation, the late template parser
+  // will be installed and instantiating these templates will succeed.
+  //
+  // If we are building a TU prefix for serialization, it is also safe to
+  // transfer these over, even though they are not parsed. The end of the TU
+  // should be outside of any eager template instantiation scope, so when this
+  // AST is deserialized, these templates will not be parsed until the end of
+  // the combined TU.
+  PendingInstantiations.insert(PendingInstantiations.end(),
+                               LateParsedInstantiations.begin(),
+                               LateParsedInstantiations.end());
+  LateParsedInstantiations.clear();
+
   // Complete translation units and modules define vtables and perform implicit
   // instantiations. PCH files do not.
   if (TUKind != TU_Prefix) {
@@ -879,8 +893,13 @@ void Sema::ActOnEndOfTranslationUnit() {
       PendingInstantiations.insert(PendingInstantiations.begin(),
                                    Pending.begin(), Pending.end());
     }
+
     PerformPendingInstantiations();
 
+    assert(LateParsedInstantiations.empty() &&
+           "end of TU template instantiation should not create more "
+           "late-parsed templates");
+
     if (LateTemplateParserCleanup)
       LateTemplateParserCleanup(OpaqueParser);
 

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=328567&r1=328566&r2=328567&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Mon Mar 26 11:22:47 2018
@@ -3837,8 +3837,8 @@ void Sema::InstantiateFunctionDefinition
   if (PatternDecl->isLateTemplateParsed() &&
       !LateTemplateParser) {
     Function->setInstantiationIsPending(true);
-    PendingInstantiations.push_back(
-      std::make_pair(Function, PointOfInstantiation));
+    LateParsedInstantiations.push_back(
+        std::make_pair(Function, PointOfInstantiation));
     return;
   }
 

Added: cfe/trunk/test/PCH/late-parsed-instantiations.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/late-parsed-instantiations.cpp?rev=328567&view=auto
==============================================================================
--- cfe/trunk/test/PCH/late-parsed-instantiations.cpp (added)
+++ cfe/trunk/test/PCH/late-parsed-instantiations.cpp Mon Mar 26 11:22:47 2018
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -fdelayed-template-parsing -std=c++14 -emit-pch %s -o %t.pch -verify
+// RUN: %clang_cc1 -fdelayed-template-parsing -std=c++14 -include-pch %t.pch %s -verify
+
+#ifndef HEADER_INCLUDED
+
+#define HEADER_INCLUDED
+
+// pr33561
+class ArrayBuffer;
+template <typename T> class Trans_NS_WTF_RefPtr {
+public:
+  ArrayBuffer *operator->() { return nullptr; }
+};
+Trans_NS_WTF_RefPtr<ArrayBuffer> get();
+template <typename _Visitor>
+constexpr void visit(_Visitor __visitor) {
+  __visitor(get()); // expected-note {{in instantiation}}
+}
+class ArrayBuffer {
+  char data() {
+    visit([](auto buffer) -> char { // expected-note {{in instantiation}}
+      buffer->data();
+    }); // expected-warning {{control reaches end of non-void lambda}}
+  } // expected-warning {{control reaches end of non-void function}}
+};
+
+#else
+
+// expected-no-diagnostics
+
+#endif

Added: cfe/trunk/test/SemaTemplate/late-parsing-eager-instantiation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/late-parsing-eager-instantiation.cpp?rev=328567&view=auto
==============================================================================
--- cfe/trunk/test/SemaTemplate/late-parsing-eager-instantiation.cpp (added)
+++ cfe/trunk/test/SemaTemplate/late-parsing-eager-instantiation.cpp Mon Mar 26 11:22:47 2018
@@ -0,0 +1,40 @@
+// RUN: %clang_cc1 -std=c++14 -verify %s
+
+// pr33561
+class ArrayBuffer;
+template <typename T> class Trans_NS_WTF_RefPtr {
+public:
+  ArrayBuffer *operator->() { return nullptr; }
+};
+Trans_NS_WTF_RefPtr<ArrayBuffer> get();
+template <typename _Visitor>
+constexpr void visit(_Visitor __visitor) {
+  __visitor(get()); // expected-note {{in instantiation}}
+}
+class ArrayBuffer {
+  char data() {
+    visit([](auto buffer) -> char { // expected-note {{in instantiation}}
+      buffer->data();
+    }); // expected-warning {{control reaches end of non-void lambda}}
+  } // expected-warning {{control reaches end of non-void function}}
+};
+
+// pr34185
+template <typename Promise> struct coroutine_handle {
+  Promise &promise() const { return
+    *static_cast<Promise *>(nullptr); // expected-warning {{binding dereferenced null}}
+  }
+};
+
+template <typename Promise> auto GetCurrenPromise() {
+  struct Awaiter { // expected-note {{in instantiation}}
+    void await_suspend(coroutine_handle<Promise> h) {
+      h.promise(); // expected-note {{in instantiation}}
+    }
+  };
+  return Awaiter{};
+}
+
+void foo() {
+  auto &&p = GetCurrenPromise<int>(); // expected-note {{in instantiation}}
+}




More information about the cfe-commits mailing list