llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: None (StefanPaulet) <details> <summary>Changes</summary> Some eager instantiations may try to instantiate a forward declared templated function before it is defined. This introduces one more attempt to instantiate at the end of the TU. Resolves #<!-- -->115731 --- Full diff: https://github.com/llvm/llvm-project/pull/117167.diff 4 Files Affected: - (modified) clang/include/clang/Sema/Sema.h (+7-4) - (modified) clang/lib/Sema/Sema.cpp (+1-1) - (modified) clang/lib/Sema/SemaTemplateInstantiateDecl.cpp (+8-6) - (added) clang/test/SemaTemplate/instantiate-function-delayed.cpp (+26) ``````````diff 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 `````````` </details> https://github.com/llvm/llvm-project/pull/117167 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits