/* $NetBSD: init_c99.c,v 1.2 2024/06/09 10:27:39 rillig Exp $ */ # 3 "init_c99.c" // 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, }; int array_flat[2][2] = { 11, 12, 21, 22 }; int array_nested[2][2] = { { 11, 12 }, { 21, 22 } }; int array_with_designators[] = { ['1'] = 111, ['5'] = 555, ['9'] = 999 }; int array_with_some_designators[] = { ['1'] = 111, 222, ['9'] = 999 }; struct point { int x; int y; }; struct point point = { 3, 4 }; struct point point_with_designators = { .y = 4, .x = 3, }; 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.8p18 */ struct rectangle screen = { .bottom_right = { 1920, 1080, } }; /* * 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 } }; struct triangle { struct point points[3]; }; struct pentagon { struct point points[5]; }; struct geometry { struct pentagon pentagons[6]; struct triangle triangles[10]; struct point points[3][5][2]; }; /* * Initialization of a complex struct containing nested arrays and nested * structs. */ struct geometry geometry = { .pentagons[0].points[4].x = 1, .points[0][0][0] = { 0, 0 }, .points[2][4][1] = {301, 302 }, /* expect+1: error: array subscript 3 cannot be > 2 [168] */ .points[3][0][0] = {3001, 3002 }, /* expect+1: error: array subscript 5 cannot be > 4 [168] */ .points[0][5][0] = {501, 502 }, /* expect+1: error: array subscript 2 cannot be > 1 [168] */ .points[0][0][2] = {21, 22 }, }; struct ends_with_unnamed_bit_field { int member; int:0; } ends_with_unnamed_bit_field = { 12345, /* expect+1: error: too many struct/union initializers [172] */ 23456, }; char prefixed_message[] = { 'E', ':', ' ', /* expect+1: warning: illegal combination of integer 'char' and pointer 'pointer to char' [183] */ "message\n", }; char message_with_suffix[] = { "message", /* The excess character is not detected by lint but by compilers. */ '\n', }; struct ten { int i0; int i1; int i2; int i3; int i4; int i5; int i6; int i7; int i8; int i9; }; struct ten ten = { .i3 = 3, 4, 5, 6, }; /* * ISO C99 6.7.8 provides a large list of examples for initialization, * covering all tricky edge cases. */ /* expect+1: warning: lossy conversion of 3.5 to 'int' [381] */ int c99_6_7_8_p24_example1_i = 3.5; double _Complex c99_6_7_8_p24_example1_c = 5 + 3 * 1.0fi; int c99_6_7_8_p25_example2[] = { 1, 3, 5 }; int c99_6_7_8_p26_example3a[4][3] = { { 1, 3, 5 }, { 2, 4, 6 }, { 3, 5, 7 }, }; int c99_6_7_8_p26_example3b[4][3] = { 1, 3, 5, 2, 4, 6, 3, 5, 7 }; int c99_6_7_8_p27_example4[4][3] = { { 1 }, { 2 }, { 3 }, { 4 } }; struct { int a[3], b; } c99_6_7_8_p28_example5[] = { { 1 }, 2, }; short c99_6_7_8_p29_example6a[4][3][2] = { { 1 }, { 2, 3 }, { 4, 5, 6 }, }; short c99_6_7_8_p29_example6b[4][3][2] = { 1, 0, 0, 0, 0, 0, 2, 3, 0, 0, 0, 0, 4, 5, 6, 0, 0, 0, }; short c99_6_7_8_p29_example6c[4][3][2] = { { { 1 }, }, { { 2, 3 }, }, { { 4, 5 }, { 6 }, } }; void c99_6_7_8_p31_example7(void) { typedef int A[]; A a = { 1, 2 }, b = { 3, 4, 5 }; /* expect+1: error: negative array dimension (-8) [20] */ typedef int reveal_sizeof_a[-(int)(sizeof(a))]; /* expect+1: error: negative array dimension (-12) [20] */ typedef int reveal_sizeof_b[-(int)(sizeof(b))]; } char c99_6_7_8_p32_example8_s1[] = "abc", c99_6_7_8_p32_example8_t1[3] = "abc"; char c99_6_7_8_p32_example8_s2[] = { 'a', 'b', 'c', '\0' }, c99_6_7_8_p32_example8_t2[3] = { 'a', 'b', 'c' }; char *c99_6_7_8_p32_example8_p = "abc"; enum { member_one, member_two }; const char *c99_6_7_8_p33_example9[] = { [member_two] = "member two", [member_one] = "member one", }; struct { int quot, rem; } c99_6_7_8_p34_example10 = { .quot = 2, .rem = -1 }; struct { int a[3], b; } c99_6_7_8_p35_example11[] = { [0].a = {1}, [1].a[0] = 2 }; int c99_6_7_8_p36_example12a[16] = { 1, 3, 5, 7, 9, [16-5] = 8, 6, 4, 2, 0 }; int c99_6_7_8_p36_example12b[8] = { 1, 3, 5, 7, 9, [8-5] = 8, 6, 4, 2, 0 }; 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; } /* expect+1: error: negative array dimension (-12) [20] */ typedef int reveal_sizeof_a1[-(int)(sizeof(a1))]; } 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 ' 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 ' 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" }; /* nested struct/union initialization */ struct outer { int i; char c; union inner { short us; char uc; } u; char *s; } struct_containing_union[] = { { .s = "foo", .c = 'b', .u = { .uc = 'c' } }, { .i = 1, .c = 'a', .u = { .us = 2 } }, }; /* * 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; }; struct offset_and_data offset_and_data = { (unsigned long)&(((struct offset_and_data *)0)->data), 0, }; // 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]))]; // C99 struct initialization using designators. struct { int i; char *s; } struct_array[] = { { .i = 2, }, { .s = "foo" }, { .i = 1, .s = "bar" }, { .s = "foo", .i = -1 }, }; // 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 hobbies { unsigned dancing: 1; unsigned running: 1; unsigned swimming: 1; }; struct person { struct hobbies hobbies; struct rgb favorite_color; }; struct city { struct person mayor; }; struct state { struct city capital; }; struct state st = { .capital.mayor.hobbies.dancing = 1, .capital.mayor.favorite_color.green = 0xFF, .capital.mayor.favorite_color.red = 0xFF, }; return st.capital.mayor.favorite_color.red; } struct { int i[10]; char *s; } struct_array_with_inner_array[] = { { { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, "foo" }, }; 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) { typedef enum O1 { O1C = 101 } O1; typedef enum O2 { O2C = 102 } O2; typedef enum O3 { O3C = 103 } O3; typedef enum I1 { I1C = 201 } I1; typedef enum I2 { I2C = 202 } I2; struct Inner1 { I1 i1; }; struct Outer3Inner1 { O1 o1; struct Inner1 inner; O3 o3; }; struct Inner1 inner1 = { I1C }; struct Outer3Inner1 o3i1 = { O1C, inner1, O3C }; O1 o1 = o3i1.o1; struct Inner2 { I1 i1; I2 i2; }; struct Outer3Inner2 { O1 o1; struct Inner2 inner; O3 o3; }; struct Inner2 inner2 = { I1C, I2C }; struct Outer3Inner2 o3i2 = { O1C, inner2, O3C }; o1 = o3i2.o1; /* * For static storage duration, each initializer expression must be a * constant expression. */ static struct Inner2 inner3_static = { I1C, I2C }; static struct Outer3Inner2 o3i2_static = { O1C, /* expect+1: error: non-constant initializer [177] */ inner3_static, O3C }; }