https://github.com/StefanPaulet updated 
https://github.com/llvm/llvm-project/pull/117167

>From 54199baf4a6a205e0b85f9f528a90b8170a960fa Mon Sep 17 00:00:00 2001
From: StefanPaulet <tudor.stefan.pau...@gmail.com>
Date: Thu, 21 Nov 2024 15:32:56 +0200
Subject: [PATCH 1/4] [clang] Allow delayed function instantiation at TU end if
 initial instantiation fails

---
 clang/include/clang/Sema/Sema.h               | 11 +++++---
 clang/lib/Sema/Sema.cpp                       |  2 +-
 .../lib/Sema/SemaTemplateInstantiateDecl.cpp  | 14 +++++-----
 .../instantiate-function-delayed.cpp          | 26 +++++++++++++++++++
 4 files changed, 42 insertions(+), 11 deletions(-)
 create mode 100644 clang/test/SemaTemplate/instantiate-function-delayed.cpp

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 6ea6c67447b6f0..ce27260bc78801 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -13523,7 +13523,9 @@ class Sema final : public SemaBase {
           S.PendingLocalImplicitInstantiations);
     }
 
-    void perform() { S.PerformPendingInstantiations(/*LocalOnly=*/true); }
+    void perform(bool AtEndOfTU = false) {
+      S.PerformPendingInstantiations(/*LocalOnly=*/true, AtEndOfTU);
+    }
 
     ~LocalEagerInstantiationScope() {
       assert(S.PendingLocalImplicitInstantiations.empty() &&
@@ -13568,10 +13570,10 @@ class Sema final : public SemaBase {
       S.SavedVTableUses.back().swap(S.VTableUses);
     }
 
-    void perform() {
+    void perform(bool AtEndOfTU = false) {
       if (Enabled) {
         S.DefineUsedVTables();
-        S.PerformPendingInstantiations();
+        S.PerformPendingInstantiations(false, AtEndOfTU);
       }
     }
 
@@ -13790,7 +13792,8 @@ class Sema final : public SemaBase {
 
   /// Performs template instantiation for all implicit template
   /// instantiations we have seen until this point.
-  void PerformPendingInstantiations(bool LocalOnly = false);
+  void PerformPendingInstantiations(bool LocalOnly = false,
+                                    bool AtEndOfTU = false);
 
   TemplateParameterList *
   SubstTemplateParams(TemplateParameterList *Params, DeclContext *Owner,
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 942e7ece4283e3..c97a253239df2b 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -1138,7 +1138,7 @@ void 
Sema::ActOnEndOfTranslationUnitFragment(TUFragmentKind Kind) {
 
   {
     llvm::TimeTraceScope TimeScope("PerformPendingInstantiations");
-    PerformPendingInstantiations();
+    PerformPendingInstantiations(false, true);
   }
 
   emitDeferredDiags();
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp 
b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 10efde7c3fe540..0f9a39062750bc 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -5267,9 +5267,9 @@ void Sema::InstantiateFunctionDefinition(SourceLocation 
PointOfInstantiation,
 
   // This class may have local implicit instantiations that need to be
   // instantiation within this scope.
-  LocalInstantiations.perform();
+  LocalInstantiations.perform(AtEndOfTU);
   Scope.Exit();
-  GlobalInstantiations.perform();
+  GlobalInstantiations.perform(AtEndOfTU);
 }
 
 VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation(
@@ -5612,9 +5612,9 @@ void Sema::InstantiateVariableDefinition(SourceLocation 
PointOfInstantiation,
 
       // This variable may have local implicit instantiations that need to be
       // instantiated within this scope.
-      LocalInstantiations.perform();
+      LocalInstantiations.perform(AtEndOfTU);
       Local.Exit();
-      GlobalInstantiations.perform();
+      GlobalInstantiations.perform(AtEndOfTU);
     }
   } else {
     assert(Var->isStaticDataMember() && PatternDecl->isStaticDataMember() &&
@@ -6448,7 +6448,7 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, 
NamedDecl *D,
   return D;
 }
 
-void Sema::PerformPendingInstantiations(bool LocalOnly) {
+void Sema::PerformPendingInstantiations(bool LocalOnly, bool AtEndOfTU) {
   std::deque<PendingImplicitInstantiation> delayedPCHInstantiations;
   while (!PendingLocalImplicitInstantiations.empty() ||
          (!LocalOnly && !PendingInstantiations.empty())) {
@@ -6476,9 +6476,11 @@ void Sema::PerformPendingInstantiations(bool LocalOnly) {
             });
       } else {
         InstantiateFunctionDefinition(/*FIXME:*/ Inst.second, Function, true,
-                                      DefinitionRequired, true);
+                                      DefinitionRequired, AtEndOfTU);
         if (Function->isDefined())
           Function->setInstantiationIsPending(false);
+        else if (!AtEndOfTU)
+          LateParsedInstantiations.push_back(Inst);
       }
       // Definition of a PCH-ed template declaration may be available only in 
the TU.
       if (!LocalOnly && LangOpts.PCHInstantiateTemplates &&
diff --git a/clang/test/SemaTemplate/instantiate-function-delayed.cpp 
b/clang/test/SemaTemplate/instantiate-function-delayed.cpp
new file mode 100644
index 00000000000000..286248b48603b7
--- /dev/null
+++ b/clang/test/SemaTemplate/instantiate-function-delayed.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -std=c++20 -verify %s
+// expected-no-diagnostics
+
+template <typename T>
+auto foo(T const& arg) -> T;
+
+template <typename Fp, typename Vis>
+auto dispatch(Fp fp, Vis vis) {
+  return fp(vis);
+}
+
+auto baz(int v) {
+  auto callable = []<typename Arg>(Arg const& arg) -> int {
+    return foo(arg);
+  };
+  return dispatch(callable, v);
+}
+
+template <typename T>
+auto foo(T const& arg) -> T {
+  return arg;
+}
+
+int main() {
+  return baz(5);
+}
\ No newline at end of file

>From 2f1f6bbf0c24e409c7317afb2fd5a4e4ea488de4 Mon Sep 17 00:00:00 2001
From: StefanPaulet <65234821+stefanpau...@users.noreply.github.com>
Date: Thu, 21 Nov 2024 16:56:53 +0200
Subject: [PATCH 2/4] Apply suggestions from code review

Co-authored-by: Timm Baeder <tbae...@redhat.com>
---
 clang/lib/Sema/Sema.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index c97a253239df2b..78b531a0394562 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -1138,7 +1138,7 @@ void 
Sema::ActOnEndOfTranslationUnitFragment(TUFragmentKind Kind) {
 
   {
     llvm::TimeTraceScope TimeScope("PerformPendingInstantiations");
-    PerformPendingInstantiations(false, true);
+    PerformPendingInstantiations(/*LocalOnly=*/false, /*AtEndOfTU=*/true);
   }
 
   emitDeferredDiags();

>From 8ed13b61cebb90ef3336ffca50eb9013c9710c2e Mon Sep 17 00:00:00 2001
From: StefanPaulet <tudor.stefan.pau...@gmail.com>
Date: Fri, 22 Nov 2024 11:51:22 +0200
Subject: [PATCH 3/4] Resolved issue that produced CI fail

---
 clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp 
b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 0f9a39062750bc..85443c9adddb9d 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -5763,9 +5763,9 @@ void Sema::InstantiateVariableDefinition(SourceLocation 
PointOfInstantiation,
 
   // This variable may have local implicit instantiations that need to be
   // instantiated within this scope.
-  LocalInstantiations.perform();
+  LocalInstantiations.perform(AtEndOfTU);
   Local.Exit();
-  GlobalInstantiations.perform();
+  GlobalInstantiations.perform(AtEndOfTU);
 }
 
 void
@@ -6529,7 +6529,7 @@ void Sema::PerformPendingInstantiations(bool LocalOnly, 
bool AtEndOfTU) {
     // Instantiate static data member definitions or variable template
     // specializations.
     InstantiateVariableDefinition(/*FIXME:*/ Inst.second, Var, true,
-                                  DefinitionRequired, true);
+                                  DefinitionRequired, AtEndOfTU);
   }
 
   if (!LocalOnly && LangOpts.PCHInstantiateTemplates)

>From ef9a4803ef9828cae150faca8d46dda7c2d4a44b Mon Sep 17 00:00:00 2001
From: StefanPaulet <tudor.stefan.pau...@gmail.com>
Date: Fri, 22 Nov 2024 13:18:12 +0200
Subject: [PATCH 4/4] Resolved issue that produced CI fail

---
 clang/include/clang/Sema/Sema.h               | 16 ++++++------
 clang/lib/Sema/Sema.cpp                       |  3 ++-
 clang/lib/Sema/SemaExpr.cpp                   |  3 +--
 .../lib/Sema/SemaTemplateInstantiateDecl.cpp  | 25 +++++++++----------
 4 files changed, 23 insertions(+), 24 deletions(-)

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index ce27260bc78801..fd1008efcecc4a 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -865,6 +865,8 @@ class Sema final : public SemaBase {
   /// checks.
   const TranslationUnitKind TUKind;
 
+  bool AtEndOfTU = false;
+
   /// Translation Unit Scope - useful to Objective-C actions that need
   /// to lookup file scope declarations in the "ordinary" C decl namespace.
   /// For example, user-defined classes, built-in "id" type, etc.
@@ -13523,8 +13525,8 @@ class Sema final : public SemaBase {
           S.PendingLocalImplicitInstantiations);
     }
 
-    void perform(bool AtEndOfTU = false) {
-      S.PerformPendingInstantiations(/*LocalOnly=*/true, AtEndOfTU);
+    void perform() {
+      S.PerformPendingInstantiations(/*LocalOnly=*/true);
     }
 
     ~LocalEagerInstantiationScope() {
@@ -13570,10 +13572,10 @@ class Sema final : public SemaBase {
       S.SavedVTableUses.back().swap(S.VTableUses);
     }
 
-    void perform(bool AtEndOfTU = false) {
+    void perform() {
       if (Enabled) {
         S.DefineUsedVTables();
-        S.PerformPendingInstantiations(false, AtEndOfTU);
+        S.PerformPendingInstantiations(false);
       }
     }
 
@@ -13684,8 +13686,7 @@ class Sema final : public SemaBase {
   void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
                                      FunctionDecl *Function,
                                      bool Recursive = false,
-                                     bool DefinitionRequired = false,
-                                     bool AtEndOfTU = false);
+                                     bool DefinitionRequired = false);
   VarTemplateSpecializationDecl *BuildVarTemplateInstantiation(
       VarTemplateDecl *VarTemplate, VarDecl *FromVar,
       const TemplateArgumentList *PartialSpecArgs,
@@ -13792,8 +13793,7 @@ class Sema final : public SemaBase {
 
   /// Performs template instantiation for all implicit template
   /// instantiations we have seen until this point.
-  void PerformPendingInstantiations(bool LocalOnly = false,
-                                    bool AtEndOfTU = false);
+  void PerformPendingInstantiations(bool LocalOnly = false);
 
   TemplateParameterList *
   SubstTemplateParams(TemplateParameterList *Params, DeclContext *Owner,
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 78b531a0394562..f53ea801a8d1ff 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -1138,7 +1138,7 @@ void 
Sema::ActOnEndOfTranslationUnitFragment(TUFragmentKind Kind) {
 
   {
     llvm::TimeTraceScope TimeScope("PerformPendingInstantiations");
-    PerformPendingInstantiations(/*LocalOnly=*/false, /*AtEndOfTU=*/true);
+    PerformPendingInstantiations(/*LocalOnly=*/false);
   }
 
   emitDeferredDiags();
@@ -1160,6 +1160,7 @@ void 
Sema::ActOnEndOfTranslationUnitFragment(TUFragmentKind Kind) {
 void Sema::ActOnEndOfTranslationUnit() {
   assert(DelayedDiagnostics.getCurrentPool() == nullptr
          && "reached end of translation unit with a pool attached?");
+  AtEndOfTU = true;
 
   // If code completion is enabled, don't perform any end-of-translation-unit
   // work.
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 6c7472ce92703b..bfab8286769424 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -21054,8 +21054,7 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
           // precedes this use.
           InstantiateFunctionDefinition(E->getBeginLoc(), FD,
                                         /*Recursive=*/false,
-                                        /*DefinitionRequired=*/true,
-                                        /*AtEndOfTU=*/false);
+                                        /*DefinitionRequired=*/true);
         }
         // Produce a properly-typed reference to the function.
         CXXScopeSpec SS;
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp 
b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 85443c9adddb9d..bb2f19d6e44179 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -513,7 +513,7 @@ static void instantiateOMPDeclareVariantAttr(
           return;
         S.InstantiateFunctionDefinition(
             New->getLocation(), SubstFD, /* Recursive */ true,
-            /* DefinitionRequired */ false, /* AtEndOfTU */ false);
+            /* DefinitionRequired */ false);
         SubstFD->setInstantiationIsPending(!SubstFD->isDefined());
         E = DeclRefExpr::Create(S.Context, NestedNameSpecifierLoc(),
                                 SourceLocation(), SubstFD,
@@ -4932,8 +4932,7 @@ FunctionDecl *Sema::InstantiateFunctionDeclaration(
 void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
                                          FunctionDecl *Function,
                                          bool Recursive,
-                                         bool DefinitionRequired,
-                                         bool AtEndOfTU) {
+                                         bool DefinitionRequired) {
   if (Function->isInvalidDecl() || isa<CXXDeductionGuideDecl>(Function))
     return;
 
@@ -5267,9 +5266,9 @@ void Sema::InstantiateFunctionDefinition(SourceLocation 
PointOfInstantiation,
 
   // This class may have local implicit instantiations that need to be
   // instantiation within this scope.
-  LocalInstantiations.perform(AtEndOfTU);
+  LocalInstantiations.perform();
   Scope.Exit();
-  GlobalInstantiations.perform(AtEndOfTU);
+  GlobalInstantiations.perform();
 }
 
 VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation(
@@ -5612,9 +5611,9 @@ void Sema::InstantiateVariableDefinition(SourceLocation 
PointOfInstantiation,
 
       // This variable may have local implicit instantiations that need to be
       // instantiated within this scope.
-      LocalInstantiations.perform(AtEndOfTU);
+      LocalInstantiations.perform();
       Local.Exit();
-      GlobalInstantiations.perform(AtEndOfTU);
+      GlobalInstantiations.perform();
     }
   } else {
     assert(Var->isStaticDataMember() && PatternDecl->isStaticDataMember() &&
@@ -5763,9 +5762,9 @@ void Sema::InstantiateVariableDefinition(SourceLocation 
PointOfInstantiation,
 
   // This variable may have local implicit instantiations that need to be
   // instantiated within this scope.
-  LocalInstantiations.perform(AtEndOfTU);
+  LocalInstantiations.perform();
   Local.Exit();
-  GlobalInstantiations.perform(AtEndOfTU);
+  GlobalInstantiations.perform();
 }
 
 void
@@ -6448,7 +6447,7 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, 
NamedDecl *D,
   return D;
 }
 
-void Sema::PerformPendingInstantiations(bool LocalOnly, bool AtEndOfTU) {
+void Sema::PerformPendingInstantiations(bool LocalOnly) {
   std::deque<PendingImplicitInstantiation> delayedPCHInstantiations;
   while (!PendingLocalImplicitInstantiations.empty() ||
          (!LocalOnly && !PendingInstantiations.empty())) {
@@ -6470,13 +6469,13 @@ void Sema::PerformPendingInstantiations(bool LocalOnly, 
bool AtEndOfTU) {
         getASTContext().forEachMultiversionedFunctionVersion(
             Function, [this, Inst, DefinitionRequired](FunctionDecl *CurFD) {
               InstantiateFunctionDefinition(/*FIXME:*/ Inst.second, CurFD, 
true,
-                                            DefinitionRequired, true);
+                                            DefinitionRequired);
               if (CurFD->isDefined())
                 CurFD->setInstantiationIsPending(false);
             });
       } else {
         InstantiateFunctionDefinition(/*FIXME:*/ Inst.second, Function, true,
-                                      DefinitionRequired, AtEndOfTU);
+                                      DefinitionRequired);
         if (Function->isDefined())
           Function->setInstantiationIsPending(false);
         else if (!AtEndOfTU)
@@ -6529,7 +6528,7 @@ void Sema::PerformPendingInstantiations(bool LocalOnly, 
bool AtEndOfTU) {
     // Instantiate static data member definitions or variable template
     // specializations.
     InstantiateVariableDefinition(/*FIXME:*/ Inst.second, Var, true,
-                                  DefinitionRequired, AtEndOfTU);
+                                  DefinitionRequired, true);
   }
 
   if (!LocalOnly && LangOpts.PCHInstantiateTemplates)

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to