[clang] 7178ee1 - Revert "[clang] Reject flexible array member in a union in C++"

Mariya Podchishchaeva via cfe-commits cfe-commits at lists.llvm.org
Wed May 3 06:27:28 PDT 2023


Author: Mariya Podchishchaeva
Date: 2023-05-03T09:25:03-04:00
New Revision: 7178ee190235bd5b6cc7c71d3ccc061d4b12656b

URL: https://github.com/llvm/llvm-project/commit/7178ee190235bd5b6cc7c71d3ccc061d4b12656b
DIFF: https://github.com/llvm/llvm-project/commit/7178ee190235bd5b6cc7c71d3ccc061d4b12656b.diff

LOG: Revert "[clang] Reject flexible array member in a union in C++"

This reverts commit 22e2db6010b029ebd4c6d3d1fd30224d8b3109ef.

Broke buildbots on Windows. It seems standard headers on Windows contain
flexible array members in unions

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/include/clang/Basic/DiagnosticGroups.td
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/lib/Sema/SemaDecl.cpp
    clang/lib/Sema/SemaInit.cpp
    clang/test/Layout/aix-power-alignment-typedef.cpp
    clang/test/Sema/MicrosoftExtensions.c
    clang/test/Sema/init.c
    clang/test/SemaCXX/flexible-array-test.cpp
    clang/test/SemaCXX/gnu-flags.cpp
    clang/test/SemaObjCXX/flexible-array.mm

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 416d816796514..8d0a9c96a9579 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -55,7 +55,6 @@ C++ Specific Potentially Breaking Changes
 -----------------------------------------
 - Clang won't search for coroutine_traits in std::experimental namespace any more.
   Clang will only search for std::coroutine_traits for coroutines then.
-- Clang now rejects unions containing a flexible array member.
 
 ABI Changes in This Version
 ---------------------------

diff  --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index 4313948515752..0ee43fb8837a1 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -267,6 +267,7 @@ def ExtraSemi : DiagGroup<"extra-semi", [CXX98CompatExtraSemi,
                                          CXX11ExtraSemi]>;
 
 def GNUFlexibleArrayInitializer : DiagGroup<"gnu-flexible-array-initializer">;
+def GNUFlexibleArrayUnionMember : DiagGroup<"gnu-flexible-array-union-member">;
 def GNUFoldingConstant : DiagGroup<"gnu-folding-constant">;
 def FormatInsufficientArgs : DiagGroup<"format-insufficient-args">;
 def FormatExtraArgs : DiagGroup<"format-extra-args">;
@@ -1136,7 +1137,7 @@ def GNU : DiagGroup<"gnu", [GNUAlignofExpression, GNUAnonymousStruct,
                             GNUConditionalOmittedOperand, GNUDesignator,
                             GNUEmptyStruct,
                             VLAExtension, GNUFlexibleArrayInitializer,
-                            GNUFoldingConstant,
+                            GNUFlexibleArrayUnionMember, GNUFoldingConstant,
                             GNUImaginaryConstant, GNUIncludeNext,
                             GNULabelsAsValue, GNULineMarker, GNUNullPointerArithmetic,
                             GNUOffsetofExtensions, GNUPointerArith,

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index c3cb6740a5131..17585752edf8e 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6232,9 +6232,6 @@ def ext_variable_sized_type_in_struct : ExtWarn<
 
 def ext_c99_flexible_array_member : Extension<
   "flexible array members are a C99 feature">, InGroup<C99>;
-// Flexible array members in unions are not supported, but union case is still
-// present in the diagnostic so it matches TagTypeKind enum and can be emitted
-// with Diag(...) << ... << SomeTagDecl->getTagKind().
 def err_flexible_array_virtual_base : Error<
   "flexible array member %0 not allowed in "
   "%select{struct|interface|union|class|enum}1 which has a virtual base class">;
@@ -6257,10 +6254,15 @@ def ext_flexible_array_empty_aggregate_ms : Extension<
   InGroup<MicrosoftFlexibleArray>;
 def err_flexible_array_union : Error<
   "flexible array member %0 in a union is not allowed">;
+def ext_flexible_array_union_ms : Extension<
+  "flexible array member %0 in a union is a Microsoft extension">,
+  InGroup<MicrosoftFlexibleArray>;
 def ext_flexible_array_empty_aggregate_gnu : Extension<
   "flexible array member %0 in otherwise empty "
   "%select{struct|interface|union|class|enum}1 is a GNU extension">,
   InGroup<GNUEmptyStruct>;
+def ext_flexible_array_union_gnu : Extension<
+  "flexible array member %0 in a union is a GNU extension">, InGroup<GNUFlexibleArrayUnionMember>;
 
 def err_flexible_array_not_at_end : Error<
   "flexible array member %0 with type %1 is not at the end of"

diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index a5bab074d08e3..4cdf2982b99d5 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -18690,7 +18690,8 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
       if (Record) {
         // Flexible array member.
         // Microsoft and g++ is more permissive regarding flexible array.
-        // It will accept flexible array as the sole element of a struct/class.
+        // It will accept flexible array in union and also
+        // as the sole element of a struct/class.
         unsigned DiagID = 0;
         if (!Record->isUnion() && !IsLastField) {
           Diag(FD->getLocation(), diag::err_flexible_array_not_at_end)
@@ -18700,7 +18701,11 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
           EnclosingDecl->setInvalidDecl();
           continue;
         } else if (Record->isUnion())
-          DiagID = diag::err_flexible_array_union;
+          DiagID = getLangOpts().MicrosoftExt
+                       ? diag::ext_flexible_array_union_ms
+                       : getLangOpts().CPlusPlus
+                             ? diag::ext_flexible_array_union_gnu
+                             : diag::err_flexible_array_union;
         else if (NumNamedMembers < 1)
           DiagID = getLangOpts().MicrosoftExt
                        ? diag::ext_flexible_array_empty_aggregate_ms

diff  --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index c8beae3f52e39..2d5d31f99e500 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -805,7 +805,7 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity,
       // order to leave them uninitialized, the ILE is expanded and the extra
       // fields are then filled with NoInitExpr.
       unsigned NumElems = numStructUnionElements(ILE->getType());
-      if (!RDecl->isUnion() && RDecl->hasFlexibleArrayMember())
+      if (RDecl->hasFlexibleArrayMember())
         ++NumElems;
       if (!VerifyOnly && ILE->getNumInits() < NumElems)
         ILE->resizeInits(SemaRef.Context, NumElems);

diff  --git a/clang/test/Layout/aix-power-alignment-typedef.cpp b/clang/test/Layout/aix-power-alignment-typedef.cpp
index e509a1d4c6abd..908415e72e38d 100644
--- a/clang/test/Layout/aix-power-alignment-typedef.cpp
+++ b/clang/test/Layout/aix-power-alignment-typedef.cpp
@@ -19,3 +19,57 @@ int b = sizeof(A);
 
 } // namespace test1
 
+namespace test2 {
+typedef double Dbl __attribute__((__aligned__(2)));
+typedef Dbl DblArr[];
+
+union U {
+  DblArr da;
+  char x;
+};
+
+int x = sizeof(U);
+
+// CHECK:          0 | union test2::U
+// CHECK-NEXT:     0 |   DblArr da
+// CHECK-NEXT:     0 |   char x
+// CHECK-NEXT:       | [sizeof=2, dsize=2, align=2, preferredalign=2,
+// CHECK-NEXT:       |  nvsize=2, nvalign=2, preferrednvalign=2]
+
+} // namespace test2
+
+namespace test3 {
+typedef double DblArr[] __attribute__((__aligned__(2)));
+
+union U {
+  DblArr da;
+  char x;
+};
+
+int x = sizeof(U);
+
+// CHECK:          0 | union test3::U
+// CHECK-NEXT:     0 |   DblArr da
+// CHECK-NEXT:     0 |   char x
+// CHECK-NEXT:       | [sizeof=2, dsize=2, align=2, preferredalign=2,
+// CHECK-NEXT:       |  nvsize=2, nvalign=2, preferrednvalign=2]
+
+} // namespace test3
+
+namespace test4 {
+typedef double Dbl __attribute__((__aligned__(2)));
+
+union U {
+  Dbl DblArr[];
+  char x;
+};
+
+int x = sizeof(U);
+
+// CHECK:          0 | union test4::U
+// CHECK-NEXT:     0 |   Dbl[] DblArr
+// CHECK-NEXT:     0 |   char x
+// CHECK-NEXT:       | [sizeof=2, dsize=2, align=2, preferredalign=2,
+// CHECK-NEXT:       |  nvsize=2, nvalign=2, preferrednvalign=2]
+
+} // namespace test4

diff  --git a/clang/test/Sema/MicrosoftExtensions.c b/clang/test/Sema/MicrosoftExtensions.c
index 82a441e40023e..50077d9031488 100644
--- a/clang/test/Sema/MicrosoftExtensions.c
+++ b/clang/test/Sema/MicrosoftExtensions.c
@@ -14,8 +14,8 @@ struct PR28407
 struct C {
    int l;
    union {
-       int c1[];   /* expected-error {{flexible array member 'c1' in a union is not allowed}} */
-       char c2[];  /* expected-error {{flexible array member 'c2' in a union is not allowed}} */
+       int c1[];   /* expected-warning {{flexible array member 'c1' in a union is a Microsoft extension}}  */
+       char c2[];  /* expected-warning {{flexible array member 'c2' in a union is a Microsoft extension}} */
    };
 };
 

diff  --git a/clang/test/Sema/init.c b/clang/test/Sema/init.c
index a487a8dda50eb..7aee651aba225 100644
--- a/clang/test/Sema/init.c
+++ b/clang/test/Sema/init.c
@@ -164,6 +164,3 @@ struct vortexstruct vortexvar = { "asdf" };
 
 typedef struct { uintptr_t x : 2; } StructWithBitfield;
 StructWithBitfield bitfieldvar = { (uintptr_t)&bitfieldvar }; // expected-error {{initializer element is not a compile-time constant}}
-
-// GH61746
-union { char x[]; } r = {0}; // expected-error {{flexible array member 'x' in a union is not allowed}}

diff  --git a/clang/test/SemaCXX/flexible-array-test.cpp b/clang/test/SemaCXX/flexible-array-test.cpp
index c52e0b50471d9..19f130288b610 100644
--- a/clang/test/SemaCXX/flexible-array-test.cpp
+++ b/clang/test/SemaCXX/flexible-array-test.cpp
@@ -16,7 +16,7 @@ void QMap<Key, T>::insert(const Key &, const T &avalue)
 
 struct Rec {
   union { // expected-warning-re {{variable sized type '{{.*}}' not at the end of a struct or class is a GNU extension}}
-    int u0[]; // expected-error {{flexible array member 'u0' in a union is not allowed}}
+    int u0[];
   };
   int x;
 } rec;
@@ -63,7 +63,7 @@ class A {
 
 union B {
   int s;
-  char c[]; // expected-error {{flexible array member 'c' in a union is not allowed}}
+  char c[];
 };
 
 class C {

diff  --git a/clang/test/SemaCXX/gnu-flags.cpp b/clang/test/SemaCXX/gnu-flags.cpp
index 6ab619851ff90..3cd18cabe9700 100644
--- a/clang/test/SemaCXX/gnu-flags.cpp
+++ b/clang/test/SemaCXX/gnu-flags.cpp
@@ -8,27 +8,34 @@
 
 // RUN: %clang_cc1 -fsyntax-only -verify %s -DALL -Wno-gnu \
 // RUN:   -Wgnu-anonymous-struct -Wredeclared-class-member \
-// RUN:   -Wgnu-folding-constant -Wgnu-empty-struct
+// RUN:   -Wgnu-flexible-array-union-member -Wgnu-folding-constant \
+// RUN:   -Wgnu-empty-struct
 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s -DALL -Wno-gnu \
 // RUN:   -Wgnu-anonymous-struct -Wredeclared-class-member \
-// RUN:   -Wgnu-folding-constant -Wgnu-empty-struct
+// RUN:   -Wgnu-flexible-array-union-member -Wgnu-folding-constant \
+// RUN:   -Wgnu-empty-struct
 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s -DALL -Wno-gnu \
 // RUN:   -Wgnu-anonymous-struct -Wredeclared-class-member \
-// RUN:   -Wgnu-folding-constant -Wgnu-empty-struct
+// RUN:   -Wgnu-flexible-array-union-member -Wgnu-folding-constant \
+// RUN:   -Wgnu-empty-struct
 
 // RUN: %clang_cc1 -fsyntax-only -verify %s -DNONE -Wgnu \
 // RUN:   -Wno-gnu-anonymous-struct -Wno-redeclared-class-member \
-// RUN:   -Wno-gnu-folding-constant -Wno-gnu-empty-struct
+// RUN:   -Wno-gnu-flexible-array-union-member -Wno-gnu-folding-constant \
+// RUN:   -Wno-gnu-empty-struct
 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s -DNONE -Wgnu \
 // RUN:   -Wno-gnu-anonymous-struct -Wno-redeclared-class-member \
-// RUN:   -Wno-gnu-folding-constant -Wno-gnu-empty-struct
+// RUN:   -Wno-gnu-flexible-array-union-member -Wno-gnu-folding-constant \
+// RUN:   -Wno-gnu-empty-struct
 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s -DNONE -Wgnu \
 // RUN:   -Wno-gnu-anonymous-struct -Wno-redeclared-class-member \
-// RUN:   -Wno-gnu-folding-constant -Wno-gnu-empty-struct
+// RUN:   -Wno-gnu-flexible-array-union-member -Wno-gnu-folding-constant \
+// RUN:   -Wno-gnu-empty-struct
 
 // Additional disabled tests:
 // %clang_cc1 -fsyntax-only -verify %s -DANONYMOUSSTRUCT -Wno-gnu -Wgnu-anonymous-struct
 // %clang_cc1 -fsyntax-only -verify %s -DREDECLAREDCLASSMEMBER -Wno-gnu -Wredeclared-class-member
+// %clang_cc1 -fsyntax-only -verify %s -DFLEXIBLEARRAYUNIONMEMBER -Wno-gnu -Wgnu-flexible-array-union-member
 // %clang_cc1 -fsyntax-only -verify %s -DFOLDINGCONSTANT -Wno-gnu -Wgnu-folding-constant
 // %clang_cc1 -fsyntax-only -verify %s -DEMPTYSTRUCT -Wno-gnu -Wgnu-empty-struct
 
@@ -63,6 +70,19 @@ namespace rcm {
   };
 }
 
+
+#if ALL || FLEXIBLEARRAYUNIONMEMBER
+// expected-warning at +6 {{flexible array member 'c1' in a union is a GNU extension}}
+#endif
+
+struct faum {
+   int l;
+   union {
+       int c1[];
+   };
+};
+
+
 #if (ALL || FOLDINGCONSTANT) && (__cplusplus <= 199711L) // C++03 or earlier modes
 // expected-warning at +4 {{in-class initializer for static data member is not a constant expression; folding it to a constant is a GNU extension}}
 #endif

diff  --git a/clang/test/SemaObjCXX/flexible-array.mm b/clang/test/SemaObjCXX/flexible-array.mm
index 831d6667fabd1..5537876c3039f 100644
--- a/clang/test/SemaObjCXX/flexible-array.mm
+++ b/clang/test/SemaObjCXX/flexible-array.mm
@@ -4,7 +4,7 @@
 
 union VariableSizeUnion {
   int s;
-  char c[]; //expected-error {{flexible array member 'c' in a union is not allowed}}
+  char c[];
 };
 
 @interface LastUnionIvar {


        


More information about the cfe-commits mailing list