[clang] [C++20][Modules] Fix false compilation error with constexpr (PR #143168)
Dmitry Polukhin via cfe-commits
cfe-commits at lists.llvm.org
Fri Jun 6 09:30:56 PDT 2025
https://github.com/dmpolukhin created https://github.com/llvm/llvm-project/pull/143168
Use canonical field decl when evaluating constexpr to avoid resetting computed union value due to using different instances of the merged field decl. Pointer to the field comparison `Value->isUnion() && Value->getUnionField() != FD` few lines below requires stable ID for the field and canonical decl seems to be good option.
>From 010a6934319f265721ae56baebcbb442bbdb7997 Mon Sep 17 00:00:00 2001
From: Dmitry Polukhin <dmitry.polukhin at gmail.com>
Date: Fri, 23 May 2025 14:22:21 -0700
Subject: [PATCH] [C++20][Modules] Fix false compilation error with constexpr
Use cannonical field decl when evaluating constexpr to avoid resetting
computed union value due to using different instances of merged decls.
---
clang/lib/AST/ExprConstant.cpp | 2 +-
.../constexpr-initialization-failure.cpp | 44 +++++++++++++++++++
2 files changed, 45 insertions(+), 1 deletion(-)
create mode 100644 clang/test/Modules/constexpr-initialization-failure.cpp
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index d1cc722fb7945..8f7016d8256fb 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -6781,7 +6781,7 @@ static bool HandleConstructorCall(const Expr *E, const LValue &This,
// and make sure we've initialized every step along it.
auto IndirectFieldChain = IFD->chain();
for (auto *C : IndirectFieldChain) {
- FD = cast<FieldDecl>(C);
+ FD = cast<FieldDecl>(C)->getCanonicalDecl();
CXXRecordDecl *CD = cast<CXXRecordDecl>(FD->getParent());
// Switch the union field if it differs. This happens if we had
// preceding zero-initialization, and we're now initializing a union
diff --git a/clang/test/Modules/constexpr-initialization-failure.cpp b/clang/test/Modules/constexpr-initialization-failure.cpp
new file mode 100644
index 0000000000000..8ff20f2fc8ac6
--- /dev/null
+++ b/clang/test/Modules/constexpr-initialization-failure.cpp
@@ -0,0 +1,44 @@
+// RUN: rm -fR %t
+// RUN: split-file %s %t
+// RUN: cd %t
+// RUN: %clang_cc1 -verify -w -std=c++20 -fmodule-name=h1.h -emit-header-unit -xc++-user-header h1.h -o h1.pcm
+// RUN: %clang_cc1 -verify -w -std=c++20 -fmodule-map-file=module.modulemap -fmodule-file=h1.h=h1.pcm main.cpp -o main.o
+
+//--- module.modulemap
+module "h1.h" {
+ header "h1.h"
+ export *
+}
+
+//--- h0.h
+// expected-no-diagnostics
+#pragma once
+
+template <typename T> struct A {
+ union {
+ struct {
+ T x, y, z;
+ };
+ };
+ constexpr A(T, T, T) : x(), y(), z() {}
+};
+typedef A<float> packed_vec3;
+
+//--- h1.h
+// expected-no-diagnostics
+#pragma once
+
+#include "h0.h"
+
+constexpr packed_vec3 kMessThingsUp = packed_vec3(5.0f, 5.0f, 5.0f);
+
+//--- main.cpp
+// expected-no-diagnostics
+#include "h0.h"
+
+static_assert(sizeof(packed_vec3) == sizeof(float) * 3);
+static_assert(alignof(packed_vec3) == sizeof(float));
+
+import "h1.h";
+
+constexpr packed_vec3 kDefaultHalfExtents = packed_vec3(5.0f, 5.0f, 5.0f);
More information about the cfe-commits
mailing list