[C++20][Modules] Fix false compilation error with constexpr by dmpolukhin · Pull Request #143168 · llvm/llvm-project (original) (raw)
@llvm/pr-subscribers-clang
@llvm/pr-subscribers-clang-modules
Author: Dmitry Polukhin (dmpolukhin)
Changes
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.
Full diff: https://github.com/llvm/llvm-project/pull/143168.diff
2 Files Affected:
- (modified) clang/lib/AST/ExprConstant.cpp (+1-1)
- (added) clang/test/Modules/constexpr-initialization-failure.cpp (+44)
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 struct A {
- union {
- struct {
T x, y, z;
- };
- };
- constexpr A(T, T, T) : x(), y(), z() {} +}; +typedef A 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);