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