[clang] [Clang] Use correct evaluation contexts when instantiating a var without initializer (PR #140699)
via cfe-commits
cfe-commits at lists.llvm.org
Tue May 20 05:04:35 PDT 2025
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 <corentinjabot at 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 <corentinjabot at 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;
More information about the cfe-commits
mailing list