[clang] [clang] Allow class with anonymous union member to be const-default-constructible even if a union member has a default member initializer (#95854) (PR #96301)
Rajveer Singh Bharadwaj via cfe-commits
cfe-commits at lists.llvm.org
Tue Aug 13 05:52:04 PDT 2024
https://github.com/Rajveer100 updated https://github.com/llvm/llvm-project/pull/96301
>From 13648d1c897f73b04ada715fe7d1f9338c2e3591 Mon Sep 17 00:00:00 2001
From: Rajveer <rajveer.developer at icloud.com>
Date: Fri, 21 Jun 2024 18:26:36 +0530
Subject: [PATCH] [clang] Allow class with anonymous union member to be
const-default-constructible even if a union member has a default member
initializer (#95854)
Resolves #95854
Clang incorrectly considers a class with an anonymous union member to not be
const-default-constructible even if a union member has a default member initializer.
```
struct A {
union {
int n = 0;
int m;
};
};
const A a;
```
-- As per https://eel.is/c++draft/dcl.init#general-8.3
---
clang/docs/ReleaseNotes.rst | 3 +++
clang/include/clang/AST/DeclCXX.h | 8 +++++---
clang/lib/AST/DeclCXX.cpp | 9 ++++++++-
clang/test/SemaCXX/GH95854.cpp | 19 +++++++++++++++++++
4 files changed, 35 insertions(+), 4 deletions(-)
create mode 100644 clang/test/SemaCXX/GH95854.cpp
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 39e1b0fcb09bbd..6994a74a35c43c 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -219,6 +219,9 @@ Bug Fixes to C++ Support
- Fixed a bug when diagnosing ambiguous explicit specializations of constrained member functions.
- Fixed an assertion failure when selecting a function from an overload set that includes a
specialization of a conversion function template.
+- Clang incorrectly considers a class with an anonymous union member to not be
+ const-default-constructible even if a union member has a default member initializer.
+ (#GH95854).
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h
index 0d72cc6a08dcb4..81105e32d40240 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -1161,8 +1161,9 @@ class CXXRecordDecl : public RecordDecl {
/// value-initialized [...] A program that calls for [...]
/// value-initialization of an entity of reference type is ill-formed.
bool hasUninitializedReferenceMember() const {
- return !isUnion() && !hasUserDeclaredConstructor() &&
- data().HasUninitializedReferenceMember;
+ return (!isUnion() && !hasUserDeclaredConstructor() &&
+ data().HasUninitializedReferenceMember) ||
+ needsImplicitDefaultConstructor();
}
/// Whether this class is a POD-type (C++ [class]p4)
@@ -1396,7 +1397,8 @@ class CXXRecordDecl : public RecordDecl {
bool allowConstDefaultInit() const {
return !data().HasUninitializedFields ||
!(data().HasDefaultedDefaultConstructor ||
- needsImplicitDefaultConstructor());
+ needsImplicitDefaultConstructor()) ||
+ (isUnion() && isEmpty());
}
/// Determine whether this class has a destructor which has no
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 9a3ede426e9143..e8597adcf6fd4a 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -1057,6 +1057,9 @@ void CXXRecordDecl::addedMember(Decl *D) {
if (isUnion() && !Field->isAnonymousStructOrUnion())
data().HasVariantMembers = true;
+ if (isUnion() && IsFirstField)
+ data().HasUninitializedFields = true;
+
// C++0x [class]p9:
// A POD struct is a class that is both a trivial class and a
// standard-layout class, and has no non-static data members of type
@@ -1125,7 +1128,11 @@ void CXXRecordDecl::addedMember(Decl *D) {
data().DefaultedCopyConstructorIsDeleted = true;
}
- if (!Field->hasInClassInitializer() && !Field->isMutable()) {
+ if (isUnion() && !Field->isMutable()) {
+ if (Field->hasInClassInitializer()) {
+ data().HasUninitializedFields = false;
+ }
+ } else if (!Field->hasInClassInitializer() && !Field->isMutable()) {
if (CXXRecordDecl *FieldType = T->getAsCXXRecordDecl()) {
if (FieldType->hasDefinition() && !FieldType->allowConstDefaultInit())
data().HasUninitializedFields = true;
diff --git a/clang/test/SemaCXX/GH95854.cpp b/clang/test/SemaCXX/GH95854.cpp
new file mode 100644
index 00000000000000..68fcf1397dd901
--- /dev/null
+++ b/clang/test/SemaCXX/GH95854.cpp
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify %s
+
+struct A {
+ union {
+ int n = 0;
+ int m;
+ };
+};
+const A a;
+
+struct B {
+ union {
+ struct {
+ int n = 5;
+ int m;
+ };
+ };
+};
+const B b; // expected-error {{default initialization of an object of const type 'const B' without a user-provided default constructor}}
More information about the cfe-commits
mailing list