Skip to content

Commit

Permalink
Revert "[clang] Reject flexible array member in a union in C++"
Browse files Browse the repository at this point in the history
This reverts commit 22e2db6.

Broke buildbots on Windows. It seems standard headers on Windows contain
flexible array members in unions
  • Loading branch information
Fznamznon committed May 3, 2023
1 parent 32032cb commit 7178ee1
Show file tree
Hide file tree
Showing 11 changed files with 100 additions and 22 deletions.
1 change: 0 additions & 1 deletion clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
---------------------------
Expand Down
3 changes: 2 additions & 1 deletion clang/include/clang/Basic/DiagnosticGroups.td
Original file line number Diff line number Diff line change
Expand Up @@ -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">;
Expand Down Expand Up @@ -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,
Expand Down
8 changes: 5 additions & 3 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -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">;
Expand All @@ -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"
Expand Down
9 changes: 7 additions & 2 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Sema/SemaInit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
54 changes: 54 additions & 0 deletions clang/test/Layout/aix-power-alignment-typedef.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 2 additions & 2 deletions clang/test/Sema/MicrosoftExtensions.c
Original file line number Diff line number Diff line change
Expand Up @@ -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}} */
};
};

Expand Down
3 changes: 0 additions & 3 deletions clang/test/Sema/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -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}}
4 changes: 2 additions & 2 deletions clang/test/SemaCXX/flexible-array-test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand Down
32 changes: 26 additions & 6 deletions clang/test/SemaCXX/gnu-flags.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -63,6 +70,19 @@ namespace rcm {
};
}


#if ALL || FLEXIBLEARRAYUNIONMEMBER
// expected-warning@+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@+4 {{in-class initializer for static data member is not a constant expression; folding it to a constant is a GNU extension}}
#endif
Expand Down
2 changes: 1 addition & 1 deletion clang/test/SemaObjCXX/flexible-array.mm
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down

0 comments on commit 7178ee1

Please sign in to comment.