https://github.com/cor3ntin updated https://github.com/llvm/llvm-project/pull/140699
>From 2b62227227310785e74c71961e36cd0ab7b799d1 Mon Sep 17 00:00:00 2001 From: Corentin Jabot <corentinja...@gmail.com> Date: Tue, 20 May 2025 11:44:59 +0200 Subject: [PATCH 1/2] [Clang] Use correct evaluation contexts when instantiating a var without initializer The evaluation context was improperly set up, such that we were trying to setup cleanups for a global var at the point of use, which lead to incorrect diagnostics about the variable not being capturable. Fixes #140632 Fixes #140622 --- clang/docs/ReleaseNotes.rst | 1 + .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 26 ++++++------- .../CodeGenCXX/cxx1y-variable-template.cpp | 12 +++++- .../cxx1y-variable-templates_top_level.cpp | 37 +++++++++++++++++-- 4 files changed, 58 insertions(+), 18 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index f04cb7b91788c..8e6cf62e11752 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -746,6 +746,7 @@ Bug Fixes to C++ Support - Fixed bug in constant evaluation that would allow using the value of a reference in its own initializer in C++23 mode (#GH131330). - Clang could incorrectly instantiate functions in discarded contexts (#GH140449) +- Fix instantiation of default-initialized variable template specialization. (#GH140632) (#GH140622) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index b12085c6f6935..d1f313e9cb487 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -6069,22 +6069,20 @@ void Sema::InstantiateVariableInitializer( else if (OldVar->isInline()) Var->setImplicitlyInline(); - if (OldVar->getInit()) { - EnterExpressionEvaluationContext Evaluated( - *this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, Var); + ContextRAII SwitchContext(*this, Var->getDeclContext()); - currentEvaluationContext().InLifetimeExtendingContext = - parentEvaluationContext().InLifetimeExtendingContext; - currentEvaluationContext().RebuildDefaultArgOrDefaultInit = - parentEvaluationContext().RebuildDefaultArgOrDefaultInit; - // Instantiate the initializer. - ExprResult Init; + EnterExpressionEvaluationContext Evaluated( + *this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, Var); + currentEvaluationContext().InLifetimeExtendingContext = + parentEvaluationContext().InLifetimeExtendingContext; + currentEvaluationContext().RebuildDefaultArgOrDefaultInit = + parentEvaluationContext().RebuildDefaultArgOrDefaultInit; - { - ContextRAII SwitchContext(*this, Var->getDeclContext()); - Init = SubstInitializer(OldVar->getInit(), TemplateArgs, - OldVar->getInitStyle() == VarDecl::CallInit); - } + if (OldVar->getInit()) { + // Instantiate the initializer. + ExprResult Init = + SubstInitializer(OldVar->getInit(), TemplateArgs, + OldVar->getInitStyle() == VarDecl::CallInit); if (!Init.isInvalid()) { Expr *InitExpr = Init.get(); diff --git a/clang/test/CodeGenCXX/cxx1y-variable-template.cpp b/clang/test/CodeGenCXX/cxx1y-variable-template.cpp index 7c0351881f198..885107ee95d88 100644 --- a/clang/test/CodeGenCXX/cxx1y-variable-template.cpp +++ b/clang/test/CodeGenCXX/cxx1y-variable-template.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++1y -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -std=c++1y -Wno-unused-value -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s // Check that we keep the 'extern' when we instantiate the definition of this // variable template specialization. @@ -18,6 +18,16 @@ int init_arr(); template<typename T> template<typename U> template<typename V> int Outer<T>::Inner<U>::arr[sizeof(T) + sizeof(U) + sizeof(V)] = { init_arr() }; int *p = Outer<char[100]>::Inner<char[20]>::arr<char[3]>; +//CHECK : @_ZN8GH1406221gIiEE = linkonce_odr constant %"struct.GH140622::S" zeroinitializer +namespace GH140622 { +template <typename> struct S {}; +template <typename T> constexpr S<T> g; +void test() { + constexpr auto x = 42; + x, g<int>; +} +} + namespace PR35456 { // CHECK: @_ZN7PR354561nILi0EEE = linkonce_odr global i32 0 template<int> int n; diff --git a/clang/test/SemaCXX/cxx1y-variable-templates_top_level.cpp b/clang/test/SemaCXX/cxx1y-variable-templates_top_level.cpp index 1fe0ce9aabf29..aada11dd5f9be 100644 --- a/clang/test/SemaCXX/cxx1y-variable-templates_top_level.cpp +++ b/clang/test/SemaCXX/cxx1y-variable-templates_top_level.cpp @@ -1,6 +1,8 @@ -// RUN: %clang_cc1 -std=c++98 -verify -fsyntax-only -Wno-c++11-extensions -Wno-c++1y-extensions %s -DPRECXX11 -// RUN: %clang_cc1 -std=c++11 -verify -fsyntax-only -Wno-c++1y-extensions %s -// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only %s +// RUN: %clang_cc1 -std=c++98 -verify -fsyntax-only -Wno-unused-value -Wno-c++11-extensions -Wno-c++1y-extensions %s -DPRECXX11 +// RUN: %clang_cc1 -std=c++11 -verify -fsyntax-only -Wno-unused-value -Wno-c++1y-extensions %s +// RUN: %clang_cc1 -std=c++17 -verify -fsyntax-only -Wno-unused-value %s +// RUN: %clang_cc1 -std=c++2c -verify -fsyntax-only -Wno-unused-value %s + #ifdef PRECXX11 #define CONST const @@ -510,3 +512,32 @@ template <> auto b<0, 0, 0> = b<0, 0, 0>; // expected-error {{variable template } #endif + +#if __cplusplus > 201702L +namespace GH140622 { +template <typename> struct S {}; + +struct Outer { + template <typename T> + static constexpr S<T> g; +}; + +template <typename T> +struct OuterTpl { + static constexpr S<T> f; + template <typename U> + static constexpr S<U> g; +}; + +template <typename T> +constexpr S<T> g; + +void test() { + constexpr auto x = 42; + x, g<int>, + Outer::g<int>, + OuterTpl<int>::f, + OuterTpl<int>::g<int>; +} +} +#endif >From f771a802dde44ff4d096dc6dfd6bb97748356c64 Mon Sep 17 00:00:00 2001 From: Corentin Jabot <corentinja...@gmail.com> Date: Tue, 20 May 2025 14:04:02 +0200 Subject: [PATCH 2/2] remove space --- clang/test/CodeGenCXX/cxx1y-variable-template.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/test/CodeGenCXX/cxx1y-variable-template.cpp b/clang/test/CodeGenCXX/cxx1y-variable-template.cpp index 885107ee95d88..329b6c0cb86ae 100644 --- a/clang/test/CodeGenCXX/cxx1y-variable-template.cpp +++ b/clang/test/CodeGenCXX/cxx1y-variable-template.cpp @@ -18,7 +18,7 @@ int init_arr(); template<typename T> template<typename U> template<typename V> int Outer<T>::Inner<U>::arr[sizeof(T) + sizeof(U) + sizeof(V)] = { init_arr() }; int *p = Outer<char[100]>::Inner<char[20]>::arr<char[3]>; -//CHECK : @_ZN8GH1406221gIiEE = linkonce_odr constant %"struct.GH140622::S" zeroinitializer +//CHECK: @_ZN8GH1406221gIiEE = linkonce_odr constant %"struct.GH140622::S" zeroinitializer namespace GH140622 { template <typename> struct S {}; template <typename T> constexpr S<T> g; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits