[llvm-branch-commits] [clang] release/22.x: [clang] CodeGen: fix ConstantExpr LValue emission (#181057) (PR #182476)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Feb 20 03:28:09 PST 2026


https://github.com/llvmbot created https://github.com/llvm/llvm-project/pull/182476

Backport a3b51529d1948dee37b5bb44d49fa82b9ea37157

Requested by: @Il-Capitano

>From 1174d8742485f69b6a351ccbe4c9bb8137ebc5b4 Mon Sep 17 00:00:00 2001
From: Matheus Izvekov <mizvekov at gmail.com>
Date: Thu, 12 Feb 2026 22:07:48 -0300
Subject: [PATCH] [clang] CodeGen: fix ConstantExpr LValue emission (#181057)

This fixes a regression introduced in #161029, though not the fault of
that patch, only by incidental changes regarding the preservation of
constant expression nodes.

The LValue emission of ConstantExpr was doing strange things with
regards to what type corresponds to the result of the constant
expression, which are not justified by any tests or in the discussions
of the relevant patches.

See

https://github.com/llvm/llvm-project/commit/09669e6c5fa1e8db9c1091cc264640fb0377d6b6
and https://github.com/llvm/llvm-project/pull/78041 and
https://github.com/llvm/llvm-project/commit/51e4aa87e05c45bebf9658a47980b1934c88be31

This simplifies it to just use the expression type.

Since this regression was never released, there are no release notes.

Fixes #177807

(cherry picked from commit a3b51529d1948dee37b5bb44d49fa82b9ea37157)
---
 clang/lib/CodeGen/CGExpr.cpp              | 14 ++----------
 clang/test/CodeGenCXX/cxx2a-consteval.cpp | 27 +++++++++++++++++++++--
 clang/test/CodeGenCXX/template-cxx20.cpp  | 13 ++++++++++-
 3 files changed, 39 insertions(+), 15 deletions(-)

diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 999726340aaed..56e2569c8122f 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -1701,14 +1701,6 @@ LValue CodeGenFunction::EmitLValue(const Expr *E,
   return LV;
 }
 
-static QualType getConstantExprReferredType(const FullExpr *E,
-                                            const ASTContext &Ctx) {
-  const Expr *SE = E->getSubExpr()->IgnoreImplicit();
-  if (isa<OpaqueValueExpr>(SE))
-    return SE->getType();
-  return cast<CallExpr>(SE)->getCallReturnType(Ctx)->getPointeeType();
-}
-
 LValue CodeGenFunction::EmitLValueHelper(const Expr *E,
                                          KnownNonNull_t IsKnownNonNull) {
   ApplyDebugLocation DL(*this, E);
@@ -1746,10 +1738,8 @@ LValue CodeGenFunction::EmitLValueHelper(const Expr *E,
     return EmitDeclRefLValue(cast<DeclRefExpr>(E));
   case Expr::ConstantExprClass: {
     const ConstantExpr *CE = cast<ConstantExpr>(E);
-    if (llvm::Value *Result = ConstantEmitter(*this).tryEmitConstantExpr(CE)) {
-      QualType RetType = getConstantExprReferredType(CE, getContext());
-      return MakeNaturalAlignAddrLValue(Result, RetType);
-    }
+    if (llvm::Value *Result = ConstantEmitter(*this).tryEmitConstantExpr(CE))
+      return MakeNaturalAlignPointeeAddrLValue(Result, CE->getType());
     return EmitLValue(cast<ConstantExpr>(E)->getSubExpr(), IsKnownNonNull);
   }
   case Expr::ParenExprClass:
diff --git a/clang/test/CodeGenCXX/cxx2a-consteval.cpp b/clang/test/CodeGenCXX/cxx2a-consteval.cpp
index bfeabc946da41..ace603ffe5713 100644
--- a/clang/test/CodeGenCXX/cxx2a-consteval.cpp
+++ b/clang/test/CodeGenCXX/cxx2a-consteval.cpp
@@ -2,16 +2,17 @@
 // RUN: FileCheck -check-prefix=EVAL -input-file=%t.ll %s
 // RUN: FileCheck -check-prefix=EVAL-STATIC -input-file=%t.ll %s
 // RUN: FileCheck -check-prefix=EVAL-FN -input-file=%t.ll %s
+// RUN: FileCheck -check-prefix=EVAL-FN-NONEXPR -input-file=%t.ll %s
 //
 // RUN: %clang_cc1 -emit-llvm %s -Dconsteval="" -std=c++2a -triple x86_64-unknown-linux-gnu -o %t.ll
 // RUN: FileCheck -check-prefix=EXPR -input-file=%t.ll %s
 
-// RUN: %clang_cc1 -emit-llvm %s -std=c++2a -triple x86_64-unknown-linux-gnu -o %t.ll -fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 -emit-llvm %s -DEXPR -std=c++2a -triple x86_64-unknown-linux-gnu -o %t.ll -fexperimental-new-constant-interpreter
 // RUN: FileCheck -check-prefix=EVAL -input-file=%t.ll %s
 // RUN: FileCheck -check-prefix=EVAL-STATIC -input-file=%t.ll %s
 // RUN: FileCheck -check-prefix=EVAL-FN -input-file=%t.ll %s
 //
-// RUN: %clang_cc1 -emit-llvm %s -Dconsteval="" -std=c++2a -triple x86_64-unknown-linux-gnu -o %t.ll -fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 -emit-llvm %s -DEXPR -Dconsteval="" -std=c++2a -triple x86_64-unknown-linux-gnu -o %t.ll -fexperimental-new-constant-interpreter
 // RUN: FileCheck -check-prefix=EXPR -input-file=%t.ll %s
 
 // there is two version of symbol checks to ensure
@@ -259,6 +260,28 @@ int test_UserConvOverload_ceval() {
   return test_UserConvOverload_helper_ceval(UserConv());
 }
 
+#ifndef EXPR
+namespace virt {
+struct A { alignas(32) char a[32]; };
+struct B : virtual A {
+  long long x, y;
+};
+struct C { virtual void v(); };
+struct D : C, B {};
+
+extern D d;
+consteval B& c() { return d; }
+long long f() { return c().y; }
+
+// Make sure the non-virtual alignment is used.
+
+// EVAL-FN-NONEXPR-LABEL: define {{.*}} i64 @_ZN4virt1fEv()
+// EVAL-FN-NONEXPR-NEXT: entry:
+// EVAL-FN-NONEXPR-NEXT: load i64, ptr getelementptr inbounds nuw (%"struct.virt::B", ptr getelementptr (i8, ptr @_ZN4virt1dE, i64 8), i32 0, i32 2), align 8
+// EVAL-FN-NONEXPR-NEXT: ret i64
+} // namespace virt
+#endif
+
 consteval void void_test() {}
 void void_call() { // EVAL-FN-LABEL: define {{.*}} @_Z9void_call
   // EVAL-FN-NOT: call
diff --git a/clang/test/CodeGenCXX/template-cxx20.cpp b/clang/test/CodeGenCXX/template-cxx20.cpp
index aeb1cc915145f..0e603ac1e0f2f 100644
--- a/clang/test/CodeGenCXX/template-cxx20.cpp
+++ b/clang/test/CodeGenCXX/template-cxx20.cpp
@@ -20,5 +20,16 @@ namespace GH161029_regression1 {
   void h() {
     g<decltype([](auto) -> void { s.U(); }), 0>();
   }
-  // CHECK: call void @_ZN20GH161029_regression11SINS_6TagSetINS_1EELS2_0EEEE1UEv
+  // CHECK-DAG: call void @_ZN20GH161029_regression11SINS_6TagSetINS_1EELS2_0EEEE1UEv
+}
+
+namespace GH177807 {
+  template<int &G> void foo() {
+    [](auto ...A) {
+      (((void)A, G), ...) = 1234;
+    }(0);
+  }
+  int i = 0;
+  template void foo<i>();
+  // CHECK-DAG: store i32 1234, ptr @_ZN8GH1778071iE, align 4
 }



More information about the llvm-branch-commits mailing list