[PATCH] D44846: [MS] Fix late-parsed template infinite loop in eager instantiation

Reid Kleckner via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Fri Mar 23 13:57:40 PDT 2018


rnk created this revision.
rnk added reviewers: rsmith, thakis, hans.

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.


https://reviews.llvm.org/D44846

Files:
  clang/include/clang/Sema/Sema.h
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/test/SemaTemplate/late-parsing-eager-instantiation.cpp


Index: clang/test/SemaTemplate/late-parsing-eager-instantiation.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaTemplate/late-parsing-eager-instantiation.cpp
@@ -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}}
+}
Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
===================================================================
--- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -3837,8 +3837,8 @@
   if (PatternDecl->isLateTemplateParsed() &&
       !LateTemplateParser) {
     Function->setInstantiationIsPending(true);
-    PendingInstantiations.push_back(
-      std::make_pair(Function, PointOfInstantiation));
+    LateParsedInstantiations.push_back(
+        std::make_pair(Function, PointOfInstantiation));
     return;
   }
 
Index: clang/lib/Sema/Sema.cpp
===================================================================
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -879,8 +879,20 @@
       PendingInstantiations.insert(PendingInstantiations.begin(),
                                    Pending.begin(), Pending.end());
     }
+
+    // Now that we are at the end of the TU and we have the late template
+    // parser, transfer late parsed instantiations onto PendingInstantiations.
+    PendingInstantiations.insert(PendingInstantiations.end(),
+                                 LateParsedInstantiations.begin(),
+                                 LateParsedInstantiations.end());
+    LateParsedInstantiations.clear();
+
     PerformPendingInstantiations();
 
+    assert(LateParsedInstantiations.empty() &&
+           "end of TU template instantiation should not create more "
+           "late-parsed templates");
+
     if (LateTemplateParserCleanup)
       LateTemplateParserCleanup(OpaqueParser);
 
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -7550,6 +7550,10 @@
   /// 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)


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D44846.139648.patch
Type: text/x-patch
Size: 3614 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20180323/fffb930a/attachment.bin>


More information about the cfe-commits mailing list