[clang] [Clang] Use correct evaluation contexts when instantiating a var without initializer (PR #140699)

2025-05-20 Thread Shafik Yaghmour via cfe-commits

https://github.com/shafik commented:

It would also be nice to get a reduction for: 
https://github.com/llvm/llvm-project/issues/140632 and see if we can add a test 
for that if it looks significantly different from the other cases.

https://github.com/llvm/llvm-project/pull/140699
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Use correct evaluation contexts when instantiating a var without initializer (PR #140699)

2025-05-20 Thread Shafik Yaghmour via cfe-commits


@@ -18,6 +18,16 @@ int init_arr();
 template template template int 
Outer::Inner::arr[sizeof(T) + sizeof(U) + sizeof(V)] = { init_arr() };
 int *p = Outer::Inner::arr;
 
+//CHECK: @_ZN8GH1406221gIiEE = linkonce_odr constant %"struct.GH140622::S" 
zeroinitializer
+namespace GH140622 {
+template  struct S {};
+template  constexpr S g;
+void test() {
+constexpr auto x = 42;

shafik wrote:

As I pointed out here: 
https://github.com/llvm/llvm-project/issues/140622#issuecomment-2892633775

this also happens when the local is *const*, so it is worth testing that case 
and the non const/constexpr case.

https://github.com/llvm/llvm-project/pull/140699
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Use correct evaluation contexts when instantiating a var without initializer (PR #140699)

2025-05-20 Thread Shafik Yaghmour via cfe-commits

https://github.com/shafik edited 
https://github.com/llvm/llvm-project/pull/140699
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Use correct evaluation contexts when instantiating a var without initializer (PR #140699)

2025-05-20 Thread via cfe-commits

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 
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 template template int 
Outer::Inner::arr[sizeof(T) + sizeof(U) + sizeof(V)] = { init_arr() };
 int *p = Outer::Inner::arr;
 
+//CHECK : @_ZN8GH1406221gIiEE = linkonce_odr constant %"struct.GH140622::S" 
zeroinitializer
+namespace GH140622 {
+template  struct S {};
+template  constexpr S g;
+void test() {
+constexpr auto x = 42;
+x, g;
+}
+}
+
 namespace PR35456 {
 // CHECK: @_ZN7PR354561nILi0EEE = linkonce_odr global i32 0
 template 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 

[clang] [Clang] Use correct evaluation contexts when instantiating a var without initializer (PR #140699)

2025-05-20 Thread via cfe-commits

https://github.com/cor3ntin closed 
https://github.com/llvm/llvm-project/pull/140699
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Use correct evaluation contexts when instantiating a var without initializer (PR #140699)

2025-05-20 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: cor3ntin (cor3ntin)


Changes

The evaluation context was improperly set up, such that we were trying to set 
up cleanups for a global variable at the point of use, which led to incorrect 
diagnostics about the variable not being capturable.

Fixes #140632
Fixes #140622

---
Full diff: https://github.com/llvm/llvm-project/pull/140699.diff


4 Files Affected:

- (modified) clang/docs/ReleaseNotes.rst (+1) 
- (modified) clang/lib/Sema/SemaTemplateInstantiateDecl.cpp (+12-14) 
- (modified) clang/test/CodeGenCXX/cxx1y-variable-template.cpp (+11-1) 
- (modified) clang/test/SemaCXX/cxx1y-variable-templates_top_level.cpp (+34-3) 


``diff
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 template template int 
Outer::Inner::arr[sizeof(T) + sizeof(U) + sizeof(V)] = { init_arr() };
 int *p = Outer::Inner::arr;
 
+//CHECK : @_ZN8GH1406221gIiEE = linkonce_odr constant %"struct.GH140622::S" 
zeroinitializer
+namespace GH140622 {
+template  struct S {};
+template  constexpr S g;
+void test() {
+constexpr auto x = 42;
+x, g;
+}
+}
+
 namespace PR35456 {
 // CHECK: @_ZN7PR354561nILi0EEE = linkonce_odr global i32 0
 template 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-exten

[clang] [Clang] Use correct evaluation contexts when instantiating a var without initializer (PR #140699)

2025-05-20 Thread via cfe-commits

https://github.com/cor3ntin created 
https://github.com/llvm/llvm-project/pull/140699

The evaluation context was improperly set up, such that we were trying to set 
up cleanups for a global variable at the point of use, which led to incorrect 
diagnostics about the variable not being capturable.

Fixes #140632
Fixes #140622

>From 2b62227227310785e74c71961e36cd0ab7b799d1 Mon Sep 17 00:00:00 2001
From: Corentin Jabot 
Date: Tue, 20 May 2025 11:44:59 +0200
Subject: [PATCH] [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 template template int 
Outer::Inner::arr[sizeof(T) + sizeof(U) + sizeof(V)] = { init_arr() };
 int *p = Outer::Inner::arr;
 
+//CHECK : @_ZN8GH1406221gIiEE = linkonce_odr constant %"struct.GH140622::S" 
zeroinitializer
+namespace GH140622 {
+template  struct S {};
+template  constexpr S g;
+void test() {
+constexpr auto x = 42;
+x, g;
+}
+}
+
 namespace PR35456 {
 // CHECK: @_ZN7PR354561nILi0EEE = linkonce_odr global i32 0
 template 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++1