This revision was automatically updated to reflect the committed changes.
Closed by commit rL328567: [MS] Fix late-parsed template infinite loop in eager 
instantiation (authored by rnk, committed by ).
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D44846?vs=139663&id=139828#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D44846

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

Index: cfe/trunk/include/clang/Sema/Sema.h
===================================================================
--- cfe/trunk/include/clang/Sema/Sema.h
+++ cfe/trunk/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)
Index: cfe/trunk/test/SemaTemplate/late-parsing-eager-instantiation.cpp
===================================================================
--- cfe/trunk/test/SemaTemplate/late-parsing-eager-instantiation.cpp
+++ cfe/trunk/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: cfe/trunk/test/PCH/late-parsed-instantiations.cpp
===================================================================
--- cfe/trunk/test/PCH/late-parsed-instantiations.cpp
+++ cfe/trunk/test/PCH/late-parsed-instantiations.cpp
@@ -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
Index: cfe/trunk/lib/Sema/Sema.cpp
===================================================================
--- cfe/trunk/lib/Sema/Sema.cpp
+++ cfe/trunk/lib/Sema/Sema.cpp
@@ -850,6 +850,20 @@
   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 @@
       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);
 
Index: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
===================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ cfe/trunk/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;
   }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to