https://github.com/Rajveer100 updated https://github.com/llvm/llvm-project/pull/96301
>From cbd6e832fbbc905d52926e268d7ba8568df80df1 Mon Sep 17 00:00:00 2001 From: Rajveer <rajveer.develo...@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/lib/AST/DeclCXX.cpp | 8 +++++- clang/test/SemaCXX/GH95854.cpp | 51 ++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 clang/test/SemaCXX/GH95854.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index b7a6ace8bb895d..21f8d47cb36099 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -539,6 +539,9 @@ Bug Fixes to C++ Support - Fix erroneous templated array size calculation leading to crashes in generated code. (#GH41441) - During the lookup for a base class name, non-type names are ignored. (#GH16855) - Fix a crash when recovering an invalid expression involving an explicit object member conversion operator. (#GH112559) +- Clang incorrectly considered 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/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 08615d4393f5d1..34bb200e43360c 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -1060,6 +1060,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 @@ -1128,7 +1131,10 @@ 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..aa470c6ac8e5b4 --- /dev/null +++ b/clang/test/SemaCXX/GH95854.cpp @@ -0,0 +1,51 @@ +// 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}} + +struct S { + int i; + int j; +}; + +struct T { + T() = default; +}; + +struct C { + union { + S s; + }; +}; + +struct D { + union { + T s; + }; +}; + +const C c; // expected-error {{default initialization of an object of const type 'const C' without a user-provided default constructor}} +const D d; // expected-error {{default initialization of an object of const type 'const D' without a user-provided default constructor}} + +struct E { + union { + int n; + int m=0; + }; +}; +const E e; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits