// Tests for initialization in C99 or later, mainly for designators.
//
// See C99 6.7.8 "Initialization".
/* lint1-flags: -Sw -X 351 */
void use(const void *);
typedef struct any {
const void *value;
} any;
// C99 6.7.8p11 says "optionally enclosed in braces". Whether this wording
// means "a single pair of braces" or "as many pairs of braces as you want"
// is left for interpretation to the reader.
int scalar_without_braces = 3;
int scalar_with_optional_braces = { 3 };
int scalar_with_too_many_braces = {{ 3 }};
/* expect+1: error: too many initializers for 'int' [174] */
int scalar_with_too_many_initializers = { 3, 5 };
// See initialization_expr, 'handing over to INIT'.
void
struct_initialization_via_assignment(any arg)
{
any local = arg;
use(&local);
}
// See initialization_expr, initialization_init_array_from_string.
char static_duration[] = "static duration";
signed char static_duration_signed[] = "static duration";
unsigned char static_duration_unsigned[] = "static duration";
int static_duration_wchar[] = L"static duration";
// See init_expr.
void
initialization_by_braced_string(void)
{
any local = { "hello" };
use(&local);
}
void
initialization_by_redundantly_braced_string(void)
{
any local = {{{{ "hello" }}}};
use(&local);
}
/*
* Only scalar expressions and string literals may be enclosed by additional
* braces. Since 'arg' is a struct, this is a compile-time error.
*/
void
initialization_with_too_many_braces(any arg)
{
/* expect+1: error: cannot initialize 'pointer to const void' from 'struct any' [185] */
any local = { arg };
use(&arg);
}
// Some of the following examples are mentioned in the introduction comment
// in init.c.
int number = 12345;
int number_with_braces_and_comma = {
12345,
};
int array_with_fixed_size[3] = {
111,
222,
333,
/* expect+1: error: too many array initializers, expected 3 [173] */
444,
};
// See update_type_of_array_of_unknown_size.
int array_of_unknown_size[] = {
111,
222,
333,
};
struct point point_with_mixed_designators = {
.x = 3,
4,
/* expect+1: error: too many struct/union initializers [172] */
5,
.x = 3,
};
/*
* Before cgram.y 1.230 from 2021-06-20, the grammar allowed either of the
* operators '.' or '->' to be used for the designators and had extra code
* to ensure that only '.' was actually used.
*/
struct point origin = {
.x = 0,
/* expect+1: error: syntax error '->' [249] */
->y = 0,
};
/* Ensure that the parser can recover from the parse error. */
struct point pythagoras = { 3, 4 };
int array_with_designator[] = {
111,
/* expect+1: error: syntax error 'designator '.member' is only for struct/union' [249] */
.member = 222,
333,
};
/*
* C99 6.7.8p11 says that the initializer of a scalar can be "optionally
* enclosed in braces". It does not explicitly set an upper limit on the
* number of braces. It also doesn't restrict the term "initializer" to only
* mean the "outermost initializer". 6.7.8p13 defines that a brace for a
* structure or union always means to descend into the type. Both GCC 10 and
* Clang 8 already warn about these extra braces, nevertheless there is
* real-life code (the Postfix MTA) that exploits this corner case of the
* standard.
*/
struct point scalar_with_several_braces = {
{{{3}}},
{{{{4}}}},
};
struct rectangle {
struct point top_left;
struct point bottom_right;
};
/*
* C99 6.7.8p22 says: At the _end_ of its initializer list, the array no
* longer has incomplete type.
*/
struct point points[] = {
{
/*
* At this point, the size of the object 'points' is not known
* yet since its type is still incomplete. Lint could warn
* about this, but GCC and Clang already do.
*
* Before init.c 1.179 from 2021.03.30, the type information
* of 'points' was set too early, resulting in a negative
* array size below.
*/
sizeof(int[-(int)sizeof(points)]),
4
}
};
union {
int first_member;
void *second_member;
unsigned char any_member;
} c99_6_7_8_p38_example13 = { .any_member = 42 };
/*
* During initialization of an object of type array of unknown size, the type
* information on the symbol is updated in-place. Ensure that this happens on
* a copy of the type.
*
* C99 6.7.8p31 example 7
*/
void
ensure_array_type_is_not_modified_during_initialization(void)
{
typedef int array_of_unknown_size[];
array_of_unknown_size a1 = { 1, 2, 3};
switch (4) {
case sizeof(array_of_unknown_size):
/* expect+1: error: duplicate case '0' in switch [199] */
case 0:
case 3:
case 4:
case 12:
break;
}
struct point unknown_member_name_beginning = {
/* expect+1: error: type 'struct point' does not have member 'r' [101] */
.r = 5,
.x = 4,
.y = 3,
};
struct point unknown_member_name_middle = {
.x = 4,
/* expect+1: error: type 'struct point' does not have member 'r' [101] */
.r = 5,
.y = 3,
};
struct point unknown_member_name_end = {
.x = 4,
.y = 3,
/* expect+1: error: type 'struct point' does not have member 'r' [101] */
.r = 5,
};
union value {
int int_value;
void *pointer_value;
};
union value unknown_union_member_name_first = {
/* expect+1: error: type 'union value' does not have member 'unknown_value' [101] */
.unknown_value = 4,
.int_value = 3,
};
union value unknown_union_member_name_second = {
.int_value = 3,
/* expect+1: error: type 'union value' does not have member 'unknown_value' [101] */
.unknown_value = 4,
};
struct point subscript_designator_on_struct = {
/* expect+1: error: syntax error 'designator '[...]' is only for arrays' [249] */
[0] = 3,
};
struct point unknown_member_on_struct = {
/* expect+1: error: type 'struct point' does not have member 'member' [101] */
.member[0][0].member = 4,
};
struct point unknown_member_on_scalar = {
/* expect+1: error: syntax error 'scalar type cannot use designator' [249] */
.x.y.z = 5,
};
struct {
int:16;
/* expect+2: warning: 'struct <unnamed>' has no named members [65] */
/* expect+1: error: cannot initialize struct/union with no named member [179] */
} struct_with_only_unnamed_members = {
123,
};
union {
int:16;
/* expect+2: warning: 'union <unnamed>' has no named members [65] */
/* expect+1: error: cannot initialize struct/union with no named member [179] */
} union_with_only_unnamed_members = {
123,
};
int designator_for_scalar = {
/* expect+1: error: syntax error 'scalar type cannot use designator' [249] */
.value = 3,
};
struct point member_designator_for_scalar_in_struct = {
/* expect+1: error: syntax error 'scalar type cannot use designator' [249] */
{ .x = 3 },
};
struct point subscript_designator_for_scalar_in_struct = {
/* expect+1: error: syntax error 'designator '[...]' is only for arrays' [249] */
{ [1] = 4 },
};
/* Seen in pcidevs_data.h, variable 'pci_words'. */
const char string_initialized_with_braced_literal[] = {
"initializer",
};
// An array of unknown size containing strings.
char weekday_names[][4] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
/*
* The expansion of the offsetof macro may dereference a null pointer.
* Such expressions are allowed in initializers for objects with
* static duration.
*/
struct offset_and_data {
unsigned long offset;
unsigned long data;
};
// The size of the array is determined by the maximum index, not by the last
// one mentioned.
int arr_11[] = { [10] = 10, [0] = 0 };
/* expect+1: error: negative array dimension (-11) [20] */
typedef int ctassert_11[-(int)(sizeof(arr_11) / sizeof(arr_11[0]))];
// Without an explicit subscript designator, the subscript counts up.
int arr_3[] = { [1] = 1, [0] = 0, 1, 2 };
/* expect+1: error: negative array dimension (-3) [20] */
typedef int ctassert_3[-(int)(sizeof(arr_3) / sizeof(arr_3[0]))];
// Ensure that deeply nested structs can be designated in an initializer.
int
init_deeply_nested_struct(void)
{
struct rgb {
unsigned red;
unsigned green;
unsigned blue;
};
struct {
int type;
union {
char b[20];
short s[10];
long l[5];
} data;
} array_in_union_in_struct = {
.type = 3,
.data.l[0] = 4
};
// Somewhere between 2005.12.24.20.47.56 and 2006.12.19.19.06.44, lint could
// not initialize named members, see PR bin/20264.
union {
char *p;
int a[1];
} array_in_union = {
.a = { 7 }
};
/*
* Initialization of a nested struct, in which some parts are initialized
* from non-constant expressions of the inner struct type.
*
* In C99, 6.7.8p13 describes exactly this case.
*/
void
init_nested_struct(void)
{