which introduces the ``bool``, ``static_assert``, ``alignas``, ``alignof``,
and ``thread_local`` keywords in C2x.
+- Implemented `WG14 N2900 <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2900.htm>`_
+ and `WG14 N3011 <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3011.htm>`_
+ which allows for empty braced initialization in C.
+
+ .. code-block:: c
+
+ struct S { int x, y } s = {}; // Initializes s.x and s.y to 0
+
+ As part of this change, the ``-Wgnu-empty-initializer`` warning group was
+ removed, as this is no longer a GNU extension but a C2x extension. You can
+ use ``-Wno-c2x-extensions`` to silence the extension warning instead.
+
Non-comprehensive list of changes in this release
-------------------------------------------------
- Clang now saves the address of ABI-indirect function parameters on the stack,
def warn_missing_type_specifier : Warning<
"type specifier missing, defaults to 'int'">,
InGroup<ImplicitInt>, DefaultIgnore;
+
+def ext_c_empty_initializer : Extension<
+ "use of an empty initializer is a C2x extension">, InGroup<C2x>;
+def warn_c2x_compat_empty_initializer : Warning<
+ "use of an empty initializer is incompatible with C standards before C2x">,
+ InGroup<CPre2xCompat>, DefaultIgnore;
}
let CategoryName = "Nullability Issue" in {
def Exceptions : DiagGroup<"exceptions">;
def DeclarationAfterStatement : DiagGroup<"declaration-after-statement">;
-def GNUEmptyInitializer : DiagGroup<"gnu-empty-initializer">;
def GNUEmptyStruct : DiagGroup<"gnu-empty-struct">;
def ExtraTokens : DiagGroup<"extra-tokens">;
def CXX98CompatExtraSemi : DiagGroup<"c++98-compat-extra-semi">;
GNUBinaryLiteral, GNUCaseRange,
GNUComplexInteger, GNUCompoundLiteralInitializer,
GNUConditionalOmittedOperand, GNUDesignator,
- GNUEmptyInitializer, GNUEmptyStruct,
+ GNUEmptyStruct,
VLAExtension, GNUFlexibleArrayInitializer,
GNUFlexibleArrayUnionMember, GNUFoldingConstant,
GNUImaginaryConstant, GNUIncludeNext,
InGroup<GNUStatementExpressionFromMacroExpansion>;
def ext_gnu_conditional_expr : Extension<
"use of GNU ?: conditional expression extension, omitting middle operand">, InGroup<GNUConditionalOmittedOperand>;
-def ext_gnu_empty_initializer : Extension<
- "use of GNU empty initializer extension">, InGroup<GNUEmptyInitializer>;
def ext_gnu_array_range : Extension<"use of GNU array range extension">,
InGroup<GNUDesignator>;
def ext_gnu_missing_equal_designator : ExtWarn<
LValue DestLV = CGF.MakeAddrLValue(Dest.getAddress(), ExprToVisit->getType());
// Handle initialization of an array.
- if (ExprToVisit->getType()->isArrayType()) {
+ if (ExprToVisit->getType()->isConstantArrayType()) {
auto AType = cast<llvm::ArrayType>(Dest.getAddress().getElementType());
EmitArrayInit(Dest.getAddress(), AType, ExprToVisit->getType(), ExprToVisit,
InitExprs, ArrayFiller);
return;
+ } else if (ExprToVisit->getType()->isVariableArrayType()) {
+ // A variable array type that has an initializer can only do empty
+ // initialization. And because this feature is not exposed as an extension
+ // in C++, we can safely memset the array memory to zero.
+ assert(InitExprs.size() == 0 &&
+ "you can only use an empty initializer with VLAs");
+ CGF.EmitNullInitialization(Dest.getAddress(), ExprToVisit->getType());
+ return;
}
assert(ExprToVisit->getType()->isRecordType() &&
/// initializer: [C99 6.7.8]
/// '{' initializer-list '}'
/// '{' initializer-list ',' '}'
-/// [GNU] '{' '}'
+/// [C2x] '{' '}'
///
/// initializer-list:
/// designation[opt] initializer ...[opt]
ExprVector InitExprs;
if (Tok.is(tok::r_brace)) {
- // Empty initializers are a C++ feature and a GNU extension to C.
- if (!getLangOpts().CPlusPlus)
- Diag(LBraceLoc, diag::ext_gnu_empty_initializer);
+ // Empty initializers are a C++ feature and a GNU extension to C before C2x.
+ if (!getLangOpts().CPlusPlus) {
+ Diag(LBraceLoc, getLangOpts().C2x
+ ? diag::warn_c2x_compat_empty_initializer
+ : diag::ext_c_empty_initializer);
+ }
// Match the '}'.
return Actions.ActOnInitList(LBraceLoc, std::nullopt, ConsumeBrace());
}
SourceRange(LParenLoc, LiteralExpr->getSourceRange().getEnd())))
return ExprError();
if (literalType->isVariableArrayType()) {
- if (!tryToFixVariablyModifiedVarType(TInfo, literalType, LParenLoc,
- diag::err_variable_object_no_init)) {
+ // C2x 6.7.9p4: An entity of variable length array type shall not be
+ // initialized except by an empty initializer.
+ //
+ // The C extension warnings are issued from ParseBraceInitializer() and
+ // do not need to be issued here. However, we continue to issue an error
+ // in the case there are initializers or we are compiling C++. We allow
+ // use of VLAs in C++, but it's not clear we want to allow {} to zero
+ // init a VLA in C++ in all cases (such as with non-trivial constructors).
+ // FIXME: should we allow this construct in C++ when it makes sense to do
+ // so?
+ std::optional<unsigned> NumInits;
+ if (const auto *ILE = dyn_cast<InitListExpr>(LiteralExpr))
+ NumInits = ILE->getNumInits();
+ if ((LangOpts.CPlusPlus || NumInits.value_or(0)) &&
+ !tryToFixVariablyModifiedVarType(TInfo, literalType, LParenLoc,
+ diag::err_variable_object_no_init))
return ExprError();
- }
}
} else if (!literalType->isDependentType() &&
RequireCompleteType(LParenLoc, literalType,
unsigned &StructuredIndex) {
if (Index >= IList->getNumInits()) {
if (!VerifyOnly) {
- if (DeclType->isSizelessBuiltinType())
- SemaRef.Diag(IList->getBeginLoc(),
- SemaRef.getLangOpts().CPlusPlus11
- ? diag::warn_cxx98_compat_empty_sizeless_initializer
- : diag::err_empty_sizeless_initializer)
- << DeclType << IList->getSourceRange();
- else
- SemaRef.Diag(IList->getBeginLoc(),
- SemaRef.getLangOpts().CPlusPlus11
- ? diag::warn_cxx98_compat_empty_scalar_initializer
- : diag::err_empty_scalar_initializer)
- << IList->getSourceRange();
+ if (SemaRef.getLangOpts().CPlusPlus) {
+ if (DeclType->isSizelessBuiltinType())
+ SemaRef.Diag(IList->getBeginLoc(),
+ SemaRef.getLangOpts().CPlusPlus11
+ ? diag::warn_cxx98_compat_empty_sizeless_initializer
+ : diag::err_empty_sizeless_initializer)
+ << DeclType << IList->getSourceRange();
+ else
+ SemaRef.Diag(IList->getBeginLoc(),
+ SemaRef.getLangOpts().CPlusPlus11
+ ? diag::warn_cxx98_compat_empty_scalar_initializer
+ : diag::err_empty_scalar_initializer)
+ << IList->getSourceRange();
+ }
}
- hadError = !SemaRef.getLangOpts().CPlusPlus11;
+ hadError =
+ SemaRef.getLangOpts().CPlusPlus && !SemaRef.getLangOpts().CPlusPlus11;
++Index;
++StructuredIndex;
return;
// Check for VLAs; in standard C it would be possible to check this
// earlier, but I don't know where clang accepts VLAs (gcc accepts
// them in all sorts of strange places).
- if (!VerifyOnly)
- SemaRef.Diag(VAT->getSizeExpr()->getBeginLoc(),
- diag::err_variable_object_no_init)
- << VAT->getSizeExpr()->getSourceRange();
- hadError = true;
+ bool HasErr = IList->getNumInits() != 0 || SemaRef.getLangOpts().CPlusPlus;
+ if (!VerifyOnly) {
+ // C2x 6.7.9p4: An entity of variable length array type shall not be
+ // initialized except by an empty initializer.
+ //
+ // The C extension warnings are issued from ParseBraceInitializer() and
+ // do not need to be issued here. However, we continue to issue an error
+ // in the case there are initializers or we are compiling C++. We allow
+ // use of VLAs in C++, but it's not clear we want to allow {} to zero
+ // init a VLA in C++ in all cases (such as with non-trivial constructors).
+ // FIXME: should we allow this construct in C++ when it makes sense to do
+ // so?
+ if (HasErr)
+ SemaRef.Diag(VAT->getSizeExpr()->getBeginLoc(),
+ diag::err_variable_object_no_init)
+ << VAT->getSizeExpr()->getSourceRange();
+ }
+ hadError = HasErr;
++Index;
++StructuredIndex;
return;
--- /dev/null
+// RUN: %clang_cc1 -std=c2x -fsyntax-only -Wpre-c2x-compat -verify=compat %s
+// RUN: %clang_cc1 -std=c17 -fsyntax-only -pedantic -Wno-comment -verify=pedantic %s
+
+/* WG14 N2900: yes
+ * Consistent, Warningless, and Intuitive Initialization with {}
+ */
+
+/* WG14 N3011: yes
+ * Consistent, Warningless, and Intuitive Initialization with {}
+ */
+void test(void) {
+ struct S { int x, y; } s = {}; // compat-warning {{use of an empty initializer is incompatible with C standards before C2x}} \
+ pedantic-warning {{use of an empty initializer is a C2x extension}}
+ int i = {}; // compat-warning {{use of an empty initializer is incompatible with C standards before C2x}} \
+ pedantic-warning {{use of an empty initializer is a C2x extension}}
+ int j = (int){}; // compat-warning {{use of an empty initializer is incompatible with C standards before C2x}} \
+ pedantic-warning {{use of an empty initializer is a C2x extension}}
+ int unknown_size[] = {}; // pedantic-warning {{zero size arrays are an extension}} \
+ pedantic-warning {{use of an empty initializer is a C2x extension}} \
+ compat-warning {{use of an empty initializer is incompatible with C standards before C2x}}
+ int vla[i] = {}; // compat-warning {{use of an empty initializer is incompatible with C standards before C2x}} \
+ pedantic-warning {{use of an empty initializer is a C2x extension}}
+ int *compound_literal_vla = (int[i]){}; // compat-warning {{use of an empty initializer is incompatible with C standards before C2x}} \
+ pedantic-warning {{use of an empty initializer is a C2x extension}}
+
+ struct T {
+ int i;
+ struct S s;
+ } t1 = { 1, {} }; // compat-warning {{use of an empty initializer is incompatible with C standards before C2x}} \
+ pedantic-warning {{use of an empty initializer is a C2x extension}}
+
+ struct T t2 = {
+ 1, {
+ 2, {} // compat-warning {{use of an empty initializer is incompatible with C standards before C2x}} \
+ pedantic-warning {{use of an empty initializer is a C2x extension}}
+ }
+ };
+
+ struct T t3 = {
+ (int){}, // compat-warning {{use of an empty initializer is incompatible with C standards before C2x}} \
+ pedantic-warning {{use of an empty initializer is a C2x extension}}
+ {} // compat-warning {{use of an empty initializer is incompatible with C standards before C2x}} \
+ pedantic-warning {{use of an empty initializer is a C2x extension}}
+ };
+
+ // Ensure that zero initialization does what you'd expect in a constant expr.
+ // FIXME: the "not an ICE" warning is incorrect for C2x, but we don't yet
+ // implement WG14 N3038.
+ _Static_assert((int){} == 0, "what?"); // compat-warning {{use of an empty initializer is incompatible with C standards before C2x}} \
+ pedantic-warning {{use of an empty initializer is a C2x extension}} \
+ pedantic-warning {{expression is not an integer constant expression; folding it to a constant is a GNU extension}}
+}
+
--- /dev/null
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -std=c2x -verify -emit-llvm %s -o - | FileCheck %s
+// expected-no-diagnostics
+
+struct S { int x, y; };
+struct T {
+ int i;
+ struct S s;
+};
+
+// CHECK: @[[CONST_T1:.+]] = private unnamed_addr constant %struct.T { i32 1, %struct.S zeroinitializer }
+// CHECK: @[[CONST_T2:.+]] = private unnamed_addr constant %struct.T { i32 1, %struct.S { i32 2, i32 0 } }
+
+void test_struct() {
+ struct S s = {};
+ // CHECK: define {{.*}} void @test_struct
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[S:.+]] = alloca %struct.S
+ // CHECK-NEXT: call void @llvm.memset.p0.i64({{.*}}%[[S]], i8 0, i64 8, i1 false)
+}
+
+void test_var() {
+ int i = {};
+ // CHECK: define {{.*}} void @test_var
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[I:.+]] = alloca i32
+ // CHECK-NEXT: store i32 0, ptr %[[I]]
+}
+
+void test_simple_compound_literal() {
+ int j = (int){};
+ // CHECK: define {{.*}} void @test_simple_compound_literal
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[J:.+]] = alloca i32
+ // CHECK-NEXT: %[[COMPOUND:.+]] = alloca i32
+ // CHECK-NEXT: store i32 0, ptr %[[COMPOUND]]
+ // CHECK-NEXT: %[[MEM:.+]] = load i32, ptr %[[COMPOUND]]
+ // CHECK-NEXT: store i32 %[[MEM]], ptr %[[J]]
+}
+
+void test_zero_size_array() {
+ int unknown_size[] = {};
+ // CHECK: define {{.*}} void @test_zero_size_array
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[UNKNOWN:.+]] = alloca [0 x i32]
+}
+
+void test_vla() {
+ int num_elts = 12;
+ int vla[num_elts] = {};
+ // CHECK: define {{.*}} void @test_vla
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[NUM_ELTS_PTR:.+]] = alloca i32
+ // CHECK: %[[VLA_EXPR:.+]] = alloca i64
+ // CHECK-NEXT: store i32 12, ptr %[[NUM_ELTS_PTR]]
+ // CHECK-NEXT: %[[NUM_ELTS:.+]] = load i32, ptr %[[NUM_ELTS_PTR]]
+ // CHECK-NEXT: %[[NUM_ELTS_EXT:.+]] = zext i32 %[[NUM_ELTS]] to i64
+ // CHECK: %[[VLA:.+]] = alloca i32, i64 %[[NUM_ELTS_EXT]]
+ // CHECK-NEXT: store i64 %[[NUM_ELTS_EXT]], ptr %[[VLA_EXPR]]
+ // CHECK-NEXT: %[[BYTES_TO_COPY:.+]] = mul nuw i64 %[[NUM_ELTS_EXT]], 4
+ // CHECK-NEXT: call void @llvm.memset.p0.i64(ptr {{.*}} %[[VLA]], i8 0, i64 %[[BYTES_TO_COPY]], i1 false)
+}
+
+void test_zero_size_vla() {
+ int num_elts = 0;
+ int vla[num_elts] = {};
+ // CHECK: define {{.*}} void @test_zero_size_vla
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[NUM_ELTS_PTR:.+]] = alloca i32
+ // CHECK: %[[VLA_EXPR:.+]] = alloca i64
+ // CHECK-NEXT: store i32 0, ptr %[[NUM_ELTS_PTR]]
+ // CHECK-NEXT: %[[NUM_ELTS:.+]] = load i32, ptr %[[NUM_ELTS_PTR]]
+ // CHECK-NEXT: %[[NUM_ELTS_EXT:.+]] = zext i32 %[[NUM_ELTS]] to i64
+ // CHECK: %[[VLA:.+]] = alloca i32, i64 %[[NUM_ELTS_EXT]]
+ // CHECK-NEXT: store i64 %[[NUM_ELTS_EXT]], ptr %[[VLA_EXPR]]
+ // CHECK-NEXT: %[[BYTES_TO_COPY:.+]] = mul nuw i64 %[[NUM_ELTS_EXT]], 4
+ // CHECK-NEXT: call void @llvm.memset.p0.i64(ptr {{.*}} %[[VLA]], i8 0, i64 %[[BYTES_TO_COPY]], i1 false)
+}
+
+void test_compound_literal_vla() {
+ int num_elts = 12;
+ int *compound_literal_vla = (int[num_elts]){};
+ // CHECK: define {{.*}} void @test_compound_literal_vla
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[NUM_ELTS_PTR:.+]] = alloca i32
+ // CHECK-NEXT: %[[COMP_LIT_VLA:.+]] = alloca ptr
+ // CHECK-NEXT: %[[COMP_LIT:.+]] = alloca i32
+ // CHECK-NEXT: store i32 12, ptr %[[NUM_ELTS_PTR]]
+ // CHECK-NEXT: %[[NUM_ELTS:.+]] = load i32, ptr %[[NUM_ELTS_PTR]]
+ // CHECK-NEXT: %[[NUM_ELTS_EXT:.+]] = zext i32 %[[NUM_ELTS]] to i64
+ // CHECK-NEXT: %[[BYTES_TO_COPY:.+]] = mul nuw i64 %[[NUM_ELTS_EXT]], 4
+ // CHECK-NEXT: call void @llvm.memset.p0.i64(ptr {{.*}} %[[COMP_LIT]], i8 0, i64 %[[BYTES_TO_COPY]], i1 false)
+ // CHECK-NEXT: store ptr %[[COMP_LIT]], ptr %[[COMP_LIT_VLA]]
+}
+
+void test_nested_structs() {
+ struct T t1 = { 1, {} };
+ struct T t2 = { 1, { 2, {} } };
+ struct T t3 = { (int){}, {} };
+ // CHECK: define {{.*}} void @test_nested_structs
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[T1:.+]] = alloca %struct.T
+ // CHECK-NEXT: %[[T2:.+]] = alloca %struct.T
+ // CHECK-NEXT: %[[T3:.+]] = alloca %struct.T
+ // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr {{.*}} %[[T1]], ptr {{.*}} @[[CONST_T1]], i64 12, i1 false)
+ // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr {{.*}} %[[T2]], ptr {{.*}} @[[CONST_T2]], i64 12, i1 false)
+ // CHECK-NEXT: call void @llvm.memset.p0.i64(ptr {{.*}} %[[T3]], i8 0, i64 12, i1 false)
+}
+
+void test_vla_of_nested_structs(int num_elts) {
+ struct T t3[num_elts] = {};
+ // CHECK: define {{.*}} void @test_vla_of_nested_structs(i32 noundef %[[NUM_ELTS_PARAM:.+]])
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: %[[NUM_ELTS_PTR:.+]] = alloca i32
+ // CHECK: %[[VLA_EXPR:.+]] = alloca i64
+ // CHECK-NEXT: store i32 %[[NUM_ELTS_PARAM]], ptr %[[NUM_ELTS_PTR]]
+ // CHECK-NEXT: %[[NUM_ELTS_LOCAL:.+]] = load i32, ptr %[[NUM_ELTS_PTR]]
+ // CHECK-NEXT: %[[NUM_ELTS_EXT:.+]] = zext i32 %[[NUM_ELTS_LOCAL]] to i64
+ // CHECK: %[[VLA:.+]] = alloca %struct.T, i64 %[[NUM_ELTS_EXT]]
+ // CHECK-NEXT: store i64 %[[NUM_ELTS_EXT]], ptr %[[VLA_EXPR]]
+ // CHECK-NEXT: %[[COPY_BYTES:.+]] = mul nuw i64 %[[NUM_ELTS_EXT]], 12
+ // CHECK-NEXT: call void @llvm.memset.p0.i64(ptr {{.*}} %[[VLA]], i8 0, i64 %[[COPY_BYTES]], i1 false)
+}
-// RUN: %clang_cc1 -std=gnu99 -fsyntax-only -pedantic -verify %s
+// RUN: %clang_cc1 -std=gnu99 -fsyntax-only -pedantic -verify=expected,pedantic %s
// RUN: %clang_cc1 -std=gnu99 -fsyntax-only -Wgnu -Wc11-extensions -verify %s
// REQUIRES: LP64
{ 2, 4, 6 },
{ 3, 5, 7 },
{ 4, 6, 8 },
- { }, // expected-warning{{use of GNU empty initializer extension}} expected-warning{{excess elements in array initializer}}
+ { }, // pedantic-warning{{use of an empty initializer is a C2x extension}} expected-warning{{excess elements in array initializer}}
};
int y4[4][3] = {
{ 1, 3, 5, 2 }, // expected-warning{{excess elements in array initializer}}
char c3[5] = { "Hello" };
char c4[4] = { "Hello" }; //expected-warning{{initializer-string for char array is too long}}
- int i3[] = {}; //expected-warning{{zero size arrays are an extension}} expected-warning{{use of GNU empty initializer extension}}
+ int i3[] = {}; //expected-warning{{zero size arrays are an extension}} pedantic-warning{{use of an empty initializer is a C2x extension}}
}
void variableArrayInit(void) {
char r8[5] = "5char";
char r9[5] = "6chars"; //expected-warning{{initializer-string for char array is too long}}
unsigned char r10[] = __extension__ (_Generic(0, int: (__extension__ "foo" )));
-int r11[0] = {}; //expected-warning{{zero size arrays are an extension}} expected-warning{{use of GNU empty initializer extension}}
+int r11[0] = {}; //expected-warning{{zero size arrays are an extension}} pedantic-warning{{use of an empty initializer is a C2x extension}}
// Some struct tests
void autoStructTest(void) {
struct bittest{int : 31, a, :21, :12, b;};
struct bittest bittestvar = {1, 2, 3, 4}; //expected-warning{{excess elements in struct initializer}}
-// Not completely sure what should happen here...
-int u1 = {}; //expected-warning{{use of GNU empty initializer extension}} expected-error{{scalar initializer cannot be empty}}
+int u1 = {}; //pedantic-warning{{use of an empty initializer is a C2x extension}}
int u2 = {{3}}; //expected-warning{{too many braces around scalar initializer}}
// PR2362
struct teststruct invalid1 = { 1, 2 }; // expected-warning {{excess elements}}
_Complex float invalid2 = { 1, 2, 3 }; // expected-warning {{specifying real and imaginary components is an extension}} \
// expected-warning {{excess elements in scalar initializer}}
-_Complex float invalid3 = {}; // expected-error {{scalar initializer cannot be empty}} \
- // expected-warning {{GNU empty initializer}}
+_Complex float invalid3 = {}; // expected-warning {{use of an empty initializer is a C2x extension}}
// Check incomplete array sizing
static long *p3 = (long []){2,"x"}; // expected-error {{incompatible pointer to integer conversion initializing 'long' with an expression of type 'char[2]'}}
typedef struct { } cache_t; // expected-warning{{empty struct is a GNU extension}}
-static cache_t clo_I1_cache = ((cache_t) { } ); // expected-warning{{use of GNU empty initializer extension}}
+static cache_t clo_I1_cache = ((cache_t) { } ); // expected-warning{{use of an empty initializer is a C2x extension}}
typedef struct Test {int a;int b;} Test;
static Test* ll = &(Test) {0,0};
struct one x3 = {5, {1, 2, 3}}; // expected-error{{initialization of flexible array member is not allowed}}
struct one x3a = { 5 };
struct one x3b = { .a = 5 };
- struct one x3c = { 5, {} }; // expected-warning{{use of GNU empty initializer extension}} \
+ struct one x3c = { 5, {} }; // expected-warning{{use of an empty initializer is a C2x extension}} \
// expected-warning{{flexible array initialization is a GNU extension}} \
// expected-warning{{zero size arrays are an extension}}
}
struct foo a = { 1, { 2, 3, 4 } }; // expected-warning{{flexible array initialization is a GNU extension}}
struct bar b = { { 1, { 2, 3, 4 } } }; // expected-error{{initialization of flexible array member is not allowed}}
struct bar c = { { 1, { } } }; // // expected-warning{{flexible array initialization is a GNU extension}} \
- // expected-warning{{use of GNU empty initializer extension}} \
+ // expected-warning{{use of an empty initializer is a C2x extension}} \
// expected-warning{{zero size arrays are an extension}}
struct foo d[1] = { { 1, { 2, 3, 4 } } }; // expected-warning{{'struct foo' may not be used as an array element due to flexible array member}} \
// expected-error{{initialization of flexible array member is not allowed}}
struct foo desig_foo = { .y = {2, 3, 4} }; // expected-warning{{flexible array initialization is a GNU extension}}
-struct bar desig_bar = { .z.y = { } }; // expected-warning{{use of GNU empty initializer extension}} \
+struct bar desig_bar = { .z.y = { } }; // expected-warning{{use of an empty initializer is a C2x extension}} \
// expected-warning{{zero size arrays are an extension}} \
// expected-warning{{flexible array initialization is a GNU extension}}
struct bar desig_bar2 = { .z.y = { 2, 3, 4} }; // expected-error{{initialization of flexible array member is not allowed}}
// RUN: %clang_cc1 -fsyntax-only -verify %s -DALL -Wgnu
// RUN: %clang_cc1 -fsyntax-only -verify %s -DALL -Wno-gnu \
// RUN: -Wgnu-alignof-expression -Wgnu-case-range -Wgnu-complex-integer -Wgnu-conditional-omitted-operand \
-// RUN: -Wgnu-empty-initializer -Wgnu-label-as-value -Wgnu-statement-expression \
+// RUN: -Wgnu-label-as-value -Wgnu-statement-expression \
// RUN: -Wgnu-compound-literal-initializer -Wgnu-flexible-array-initializer \
// RUN: -Wgnu-redeclared-enum -Wgnu-folding-constant -Wgnu-empty-struct \
// RUN: -Wgnu-union-cast -Wgnu-variable-sized-type-not-at-end
// RUN: %clang_cc1 -fsyntax-only -verify %s -DNONE -Wgnu \
// RUN: -Wno-gnu-alignof-expression -Wno-gnu-case-range -Wno-gnu-complex-integer -Wno-gnu-conditional-omitted-operand \
-// RUN: -Wno-gnu-empty-initializer -Wno-gnu-label-as-value -Wno-gnu-statement-expression \
+// RUN: -Wno-gnu-label-as-value -Wno-gnu-statement-expression \
// RUN: -Wno-gnu-compound-literal-initializer -Wno-gnu-flexible-array-initializer \
// RUN: -Wno-gnu-redeclared-enum -Wno-gnu-folding-constant -Wno-gnu-empty-struct \
// RUN: -Wno-gnu-union-cast -Wno-gnu-variable-sized-type-not-at-end
// %clang_cc1 -fsyntax-only -verify %s -DCASERANGE -Wno-gnu -Wgnu-case-range
// %clang_cc1 -fsyntax-only -verify %s -DCOMPLEXINT -Wno-gnu -Wgnu-complex-integer
// %clang_cc1 -fsyntax-only -verify %s -DOMITTEDOPERAND -Wno-gnu -Wgnu-conditional-omitted-operand
-// %clang_cc1 -fsyntax-only -verify %s -DEMPTYINIT -Wno-gnu -Wgnu-empty-initializer
// %clang_cc1 -fsyntax-only -verify %s -DLABELVALUE -Wno-gnu -Wgnu-label-as-value
// %clang_cc1 -fsyntax-only -verify %s -DSTATEMENTEXP -Wno-gnu -Wgnu-statement-expression
// %clang_cc1 -fsyntax-only -verify %s -DSTATEMENTEXPMACRO -Wno-gnu -Wgnu-statement-expression-from-macro-expansion
static const char* omittedoperand = (const char*)0 ?: "Null";
-#if ALL || EMPTYINIT
-// expected-warning@+3 {{use of GNU empty initializer extension}}
-#endif
-
-struct { int x; } emptyinit = {};
-
-
#if ALL || LABELVALUE
// expected-warning@+6 {{use of GNU address-of-label extension}}
// expected-warning@+7 {{use of GNU indirect-goto extension}}
svint8_t init_int8 = local_int8;
svint8_t bad_init_int8 = for; // expected-error {{expected expression}}
- int empty_brace_init_int = {}; // expected-error {{scalar initializer cannot be empty}}
- svint8_t empty_brace_init_int8 = {}; // expected-error {{initializer for sizeless type 'svint8_t' (aka '__SVInt8_t') cannot be empty}}
+ int empty_brace_init_int = {};
+ svint8_t empty_brace_init_int8 = {};
svint8_t brace_init_int8 = {local_int8};
svint8_t bad_brace_init_int8_1 = {local_int8, 0}; // expected-warning {{excess elements in initializer for indivisible sizeless type 'svint8_t'}}
svint8_t bad_brace_init_int8_2 = {0}; // expected-error {{incompatible type 'int'}}
jump_over_a2:;
goto jump_over_a3;
- char a3[ksize] = {}; // expected-warning {{variable length array folded to constant array as an extension}} expected-warning{{use of GNU empty initializer}}
+ char a3[ksize] = {}; // expected-warning {{variable length array folded to constant array as an extension}} expected-warning{{use of an empty initializer is a C2x extension}}
jump_over_a3:;
goto jump_over_a4; // expected-error{{cannot jump from this goto statement to its label}}
char a4[ksize][2]; // expected-note{{variable length array}}
jump_over_a4:;
- char a5[ksize][2] = {}; // expected-warning {{variable length array folded to constant array as an extension}} expected-warning{{use of GNU empty initializer}}
+ char a5[ksize][2] = {}; // expected-warning {{variable length array folded to constant array as an extension}} expected-warning{{use of an empty initializer is a C2x extension}}
int a6[ksize] = {1,2,3,4}; // expected-warning{{variable length array folded to constant array as an extension}}
@property unsigned length;
@end
void test7(Test7 *t) {
- char data[t.length] = {}; // expected-error {{variable-sized object may not be initialized}}
+ char data[t.length] = {};
}
intel_sub_group_avc_sic_result_t result_sic = ss;
intel_sub_group_avc_ime_result_single_reference_streamout_t sstreamout = v;
intel_sub_group_avc_ime_result_dual_reference_streamout_t dstreamin_list = {0x0, 0x1};
- intel_sub_group_avc_ime_dual_reference_streamin_t dstreamin_list2 = {};
intel_sub_group_avc_ime_single_reference_streamin_t dstreamin_list3 = {c};
intel_sub_group_avc_ime_dual_reference_streamin_t dstreamin_list4 = {1};
#ifdef EXT
-// expected-error@-14 {{initializing '__private intel_sub_group_avc_mce_payload_t' with an expression of incompatible type 'int'}}
-// expected-error@-14 {{initializing '__private intel_sub_group_avc_ime_payload_t' with an expression of incompatible type 'int'}}
-// expected-error@-14 {{initializing '__private intel_sub_group_avc_ref_payload_t' with an expression of incompatible type '__private float'}}
-// expected-error@-14 {{initializing '__private intel_sub_group_avc_sic_payload_t' with an expression of incompatible type '__private struct st'}}
-// expected-error@-14 {{initializing '__private intel_sub_group_avc_mce_result_t' with an expression of incompatible type 'int'}}
-// expected-error@-14 {{initializing '__private intel_sub_group_avc_ime_result_t' with an expression of incompatible type 'int'}}
-// expected-error@-14 {{initializing '__private intel_sub_group_avc_ref_result_t' with an expression of incompatible type '__private float'}}
-// expected-error@-14 {{initializing '__private intel_sub_group_avc_sic_result_t' with an expression of incompatible type '__private struct st'}}
-// expected-error@-14 {{initializing '__private intel_sub_group_avc_ime_result_single_reference_streamout_t' with an expression of incompatible type '__private void *__private'}}
-// expected-warning@-14 {{excess elements in struct initializer}}
-// expected-error@-14 {{scalar initializer cannot be empty}}
-// expected-error@-14 {{initializing '__private intel_sub_group_avc_ime_single_reference_streamin_t' with an expression of incompatible type '__private char'}}
-// expected-error@-14 {{initializing '__private intel_sub_group_avc_ime_dual_reference_streamin_t' with an expression of incompatible type 'int'}}
+// expected-error@-13 {{initializing '__private intel_sub_group_avc_mce_payload_t' with an expression of incompatible type 'int'}}
+// expected-error@-13 {{initializing '__private intel_sub_group_avc_ime_payload_t' with an expression of incompatible type 'int'}}
+// expected-error@-13 {{initializing '__private intel_sub_group_avc_ref_payload_t' with an expression of incompatible type '__private float'}}
+// expected-error@-13 {{initializing '__private intel_sub_group_avc_sic_payload_t' with an expression of incompatible type '__private struct st'}}
+// expected-error@-13 {{initializing '__private intel_sub_group_avc_mce_result_t' with an expression of incompatible type 'int'}}
+// expected-error@-13 {{initializing '__private intel_sub_group_avc_ime_result_t' with an expression of incompatible type 'int'}}
+// expected-error@-13 {{initializing '__private intel_sub_group_avc_ref_result_t' with an expression of incompatible type '__private float'}}
+// expected-error@-13 {{initializing '__private intel_sub_group_avc_sic_result_t' with an expression of incompatible type '__private struct st'}}
+// expected-error@-13 {{initializing '__private intel_sub_group_avc_ime_result_single_reference_streamout_t' with an expression of incompatible type '__private void *__private'}}
+// expected-warning@-13 {{excess elements in struct initializer}}
+// expected-error@-13 {{initializing '__private intel_sub_group_avc_ime_single_reference_streamin_t' with an expression of incompatible type '__private char'}}
+// expected-error@-13 {{initializing '__private intel_sub_group_avc_ime_dual_reference_streamin_t' with an expression of incompatible type 'int'}}
#else
-// expected-error@-28 {{use of undeclared identifier 'intel_sub_group_avc_mce_payload_t'}}
-// expected-error@-28 {{use of undeclared identifier 'intel_sub_group_avc_ime_payload_t'}}
-// expected-error@-28 {{use of undeclared identifier 'intel_sub_group_avc_ref_payload_t'}}
-// expected-error@-28 {{use of undeclared identifier 'intel_sub_group_avc_sic_payload_t'}}
-// expected-error@-28 {{use of undeclared identifier 'intel_sub_group_avc_mce_result_t'}}
-// expected-error@-28 {{use of undeclared identifier 'intel_sub_group_avc_ime_result_t'}}
-// expected-error@-28 {{use of undeclared identifier 'intel_sub_group_avc_ref_result_t'}}
-// expected-error@-28 {{use of undeclared identifier 'intel_sub_group_avc_sic_result_t'}}
-// expected-error@-28 {{use of undeclared identifier 'intel_sub_group_avc_ime_result_single_reference_streamout_t'}}
-// expected-error@-28 {{use of undeclared identifier 'intel_sub_group_avc_ime_result_dual_reference_streamout_t'}}
-// expected-error@-28 {{use of undeclared identifier 'intel_sub_group_avc_ime_dual_reference_streamin_t'}}
-// expected-error@-28 {{use of undeclared identifier 'intel_sub_group_avc_ime_single_reference_streamin_t'}}
-// expected-error@-28 {{use of undeclared identifier 'intel_sub_group_avc_ime_dual_reference_streamin_t'}}
+// expected-error@-26 {{use of undeclared identifier 'intel_sub_group_avc_mce_payload_t'}}
+// expected-error@-26 {{use of undeclared identifier 'intel_sub_group_avc_ime_payload_t'}}
+// expected-error@-26 {{use of undeclared identifier 'intel_sub_group_avc_ref_payload_t'}}
+// expected-error@-26 {{use of undeclared identifier 'intel_sub_group_avc_sic_payload_t'}}
+// expected-error@-26 {{use of undeclared identifier 'intel_sub_group_avc_mce_result_t'}}
+// expected-error@-26 {{use of undeclared identifier 'intel_sub_group_avc_ime_result_t'}}
+// expected-error@-26 {{use of undeclared identifier 'intel_sub_group_avc_ref_result_t'}}
+// expected-error@-26 {{use of undeclared identifier 'intel_sub_group_avc_sic_result_t'}}
+// expected-error@-26 {{use of undeclared identifier 'intel_sub_group_avc_ime_result_single_reference_streamout_t'}}
+// expected-error@-26 {{use of undeclared identifier 'intel_sub_group_avc_ime_result_dual_reference_streamout_t'}}
+// expected-error@-26 {{use of undeclared identifier 'intel_sub_group_avc_ime_single_reference_streamin_t'}}
+// expected-error@-26 {{use of undeclared identifier 'intel_sub_group_avc_ime_dual_reference_streamin_t'}}
#endif
}
</tr>
<tr> <!-- Feb 2022 -->
<td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2900.htm">N2900</a></td>
- <td class="unknown" align="center">Unknown</td>
+ <td class="unreleased" align="center">Clang 17</td>
</tr>
<tr> <!-- Jul 2022 -->
<td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3011.htm">N3011</a></td>
- <td class="unknown" align="center">Unknown</td>
+ <td class="unreleased" align="center">Clang 17</td>
</tr>
<tr id="typeof">
<td rowspan="3">Not-so-magic: typeof</td>