diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -55,6 +55,7 @@ ----------------------------------------- - 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 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -267,7 +267,6 @@ 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">; @@ -1137,7 +1136,7 @@ GNUConditionalOmittedOperand, GNUDesignator, GNUEmptyStruct, VLAExtension, GNUFlexibleArrayInitializer, - GNUFlexibleArrayUnionMember, GNUFoldingConstant, + GNUFoldingConstant, GNUImaginaryConstant, GNUIncludeNext, GNULabelsAsValue, GNULineMarker, GNUNullPointerArithmetic, GNUOffsetofExtensions, GNUPointerArith, diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -6244,15 +6244,10 @@ InGroup; 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; 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; -def ext_flexible_array_union_gnu : Extension< - "flexible array member %0 in a union is a GNU extension">, InGroup; 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 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -18690,8 +18690,7 @@ if (Record) { // Flexible array member. // Microsoft and g++ is more permissive regarding flexible array. - // It will accept flexible array in union and also - // as the sole element of a struct/class. + // It will accept flexible array 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) @@ -18701,11 +18700,7 @@ EnclosingDecl->setInvalidDecl(); continue; } else if (Record->isUnion()) - DiagID = getLangOpts().MicrosoftExt - ? diag::ext_flexible_array_union_ms - : getLangOpts().CPlusPlus - ? diag::ext_flexible_array_union_gnu - : diag::err_flexible_array_union; + DiagID = 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 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -805,7 +805,7 @@ // 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->hasFlexibleArrayMember()) + if (!RDecl->isUnion() && 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 --- a/clang/test/Layout/aix-power-alignment-typedef.cpp +++ b/clang/test/Layout/aix-power-alignment-typedef.cpp @@ -19,57 +19,3 @@ } // 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 --- a/clang/test/Sema/MicrosoftExtensions.c +++ b/clang/test/Sema/MicrosoftExtensions.c @@ -14,8 +14,8 @@ struct C { int l; union { - 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}} */ + 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}} */ }; }; diff --git a/clang/test/Sema/init.c b/clang/test/Sema/init.c --- a/clang/test/Sema/init.c +++ b/clang/test/Sema/init.c @@ -164,3 +164,6 @@ 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 --- a/clang/test/SemaCXX/flexible-array-test.cpp +++ b/clang/test/SemaCXX/flexible-array-test.cpp @@ -16,7 +16,7 @@ struct Rec { union { // expected-warning-re {{variable sized type '{{.*}}' not at the end of a struct or class is a GNU extension}} - int u0[]; + int u0[]; // expected-error {{flexible array member 'u0' in a union is not allowed}} }; int x; } rec; @@ -63,7 +63,7 @@ union B { int s; - char c[]; + char c[]; // expected-error {{flexible array member 'c' in a union is not allowed}} }; class C { diff --git a/clang/test/SemaCXX/gnu-flags.cpp b/clang/test/SemaCXX/gnu-flags.cpp --- a/clang/test/SemaCXX/gnu-flags.cpp +++ b/clang/test/SemaCXX/gnu-flags.cpp @@ -8,34 +8,27 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -DALL -Wno-gnu \ // RUN: -Wgnu-anonymous-struct -Wredeclared-class-member \ -// RUN: -Wgnu-flexible-array-union-member -Wgnu-folding-constant \ -// RUN: -Wgnu-empty-struct +// RUN: -Wgnu-folding-constant -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-flexible-array-union-member -Wgnu-folding-constant \ -// RUN: -Wgnu-empty-struct +// RUN: -Wgnu-folding-constant -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-flexible-array-union-member -Wgnu-folding-constant \ -// RUN: -Wgnu-empty-struct +// RUN: -Wgnu-folding-constant -Wgnu-empty-struct // RUN: %clang_cc1 -fsyntax-only -verify %s -DNONE -Wgnu \ // RUN: -Wno-gnu-anonymous-struct -Wno-redeclared-class-member \ -// RUN: -Wno-gnu-flexible-array-union-member -Wno-gnu-folding-constant \ -// RUN: -Wno-gnu-empty-struct +// RUN: -Wno-gnu-folding-constant -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-flexible-array-union-member -Wno-gnu-folding-constant \ -// RUN: -Wno-gnu-empty-struct +// RUN: -Wno-gnu-folding-constant -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-flexible-array-union-member -Wno-gnu-folding-constant \ -// RUN: -Wno-gnu-empty-struct +// RUN: -Wno-gnu-folding-constant -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 @@ -70,19 +63,6 @@ }; } - -#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 diff --git a/clang/test/SemaObjCXX/flexible-array.mm b/clang/test/SemaObjCXX/flexible-array.mm --- a/clang/test/SemaObjCXX/flexible-array.mm +++ b/clang/test/SemaObjCXX/flexible-array.mm @@ -4,7 +4,7 @@ union VariableSizeUnion { int s; - char c[]; + char c[]; //expected-error {{flexible array member 'c' in a union is not allowed}} }; @interface LastUnionIvar {