[clang] 22e2db6 - [clang] Reject flexible array member in a union in C++
Mariya Podchishchaeva via cfe-commits
cfe-commits at lists.llvm.org
Wed May 3 05:59:05 PDT 2023
Author: Mariya Podchishchaeva
Date: 2023-05-03T08:54:35-04:00
New Revision: 22e2db6010b029ebd4c6d3d1fd30224d8b3109ef
URL: https://github.com/llvm/llvm-project/commit/22e2db6010b029ebd4c6d3d1fd30224d8b3109ef
DIFF: https://github.com/llvm/llvm-project/commit/22e2db6010b029ebd4c6d3d1fd30224d8b3109ef.diff
LOG: [clang] Reject flexible array member in a union in C++
It was rejected in C, and in a strange way accepted in C++. However, the
support was never properly tested and fully implemented, so just reject
it in C++ mode as well.
This change also fixes crash on attempt to initialize union with flexible
array member. Due to missing check on union, there was a null expression
added to init list that caused crash later.
Fixes https://github.com/llvm/llvm-project/issues/61746
Reviewed By: aaron.ballman
Differential Revision: https://reviews.llvm.org/D147626
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 8d0a9c96a9579..416d816796514 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -55,6 +55,7 @@ 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 0ee43fb8837a1..4313948515752 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -267,7 +267,6 @@ 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">;
@@ -1137,7 +1136,7 @@ def GNU : DiagGroup<"gnu", [GNUAlignofExpression, GNUAnonymousStruct,
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
index 17585752edf8e..c3cb6740a5131 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6232,6 +6232,9 @@ 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">;
@@ -6254,15 +6257,10 @@ 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 4cdf2982b99d5..a5bab074d08e3 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -18690,8 +18690,7 @@ 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 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 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
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
index 2d5d31f99e500..c8beae3f52e39 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->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
index 908415e72e38d..e509a1d4c6abd 100644
--- a/clang/test/Layout/aix-power-alignment-typedef.cpp
+++ b/clang/test/Layout/aix-power-alignment-typedef.cpp
@@ -19,57 +19,3 @@ 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 50077d9031488..82a441e40023e 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-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
index 7aee651aba225..a487a8dda50eb 100644
--- a/clang/test/Sema/init.c
+++ b/clang/test/Sema/init.c
@@ -164,3 +164,6 @@ 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 19f130288b610..c52e0b50471d9 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[];
+ int u0[]; // expected-error {{flexible array member 'u0' in a union is not allowed}}
};
int x;
} rec;
@@ -63,7 +63,7 @@ class A {
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
index 3cd18cabe9700..6ab619851ff90 100644
--- 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 @@ 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 5537876c3039f..831d6667fabd1 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[];
+ char c[]; //expected-error {{flexible array member 'c' in a union is not allowed}}
};
@interface LastUnionIvar {
More information about the cfe-commits
mailing list