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.pau...@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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits