[clang] [clang] Allow delayed function instantiation at TU end if initial instantiation fails (PR #117167)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Nov 22 03:18:45 PST 2024
https://github.com/StefanPaulet updated https://github.com/llvm/llvm-project/pull/117167
>From d4ab1ecd5672f7bd3e90230b1739deb981e6353c Mon Sep 17 00:00:00 2001
From: StefanPaulet <tudor.stefan.paulet at gmail.com>
Date: Thu, 21 Nov 2024 15:32:56 +0200
Subject: [PATCH] [clang] Allow delayed function instantiation at TU end if
initial instantiation fails
---
clang/include/clang/Sema/Sema.h | 11 +++++---
clang/lib/Sema/Sema.cpp | 3 ++-
clang/lib/Sema/SemaExpr.cpp | 3 +--
.../lib/Sema/SemaTemplateInstantiateDecl.cpp | 11 ++++----
.../instantiate-function-delayed.cpp | 26 +++++++++++++++++++
5 files changed, 42 insertions(+), 12 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..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,7 +13525,9 @@ class Sema final : public SemaBase {
S.PendingLocalImplicitInstantiations);
}
- void perform() { S.PerformPendingInstantiations(/*LocalOnly=*/true); }
+ void perform() {
+ S.PerformPendingInstantiations(/*LocalOnly=*/true);
+ }
~LocalEagerInstantiationScope() {
assert(S.PendingLocalImplicitInstantiations.empty() &&
@@ -13571,7 +13575,7 @@ class Sema final : public SemaBase {
void perform() {
if (Enabled) {
S.DefineUsedVTables();
- S.PerformPendingInstantiations();
+ S.PerformPendingInstantiations(false);
}
}
@@ -13682,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,
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 942e7ece4283e3..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();
+ 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 10efde7c3fe540..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;
@@ -6470,15 +6469,17 @@ void Sema::PerformPendingInstantiations(bool LocalOnly) {
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, true);
+ DefinitionRequired);
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
More information about the cfe-commits
mailing list