Skip to content

Commit c3c2f46

Browse files
authored
[C2y] Claim conformance and add test coverage for WG14 N3346 (#115516)
This converts some undefined behaviors during initialization to instead be constraint violations. Clang has always implemented these as constraints, so no compiler changes were needed.
1 parent 39358f8 commit c3c2f46

File tree

3 files changed

+74
-1
lines changed

3 files changed

+74
-1
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,11 @@ C2y Feature Support
303303
undefined. Clang has always accepted ``const`` and ``volatile`` qualified
304304
function types by ignoring the qualifiers.
305305

306+
- Updated conformance for `N3346 <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3346.pdf>`_
307+
which changes some undefined behavior around initialization to instead be
308+
constraint violations. This paper adopts Clang's existing practice, so there
309+
were no changes to compiler behavior.
310+
306311
C23 Feature Support
307312
^^^^^^^^^^^^^^^^^^^
308313

clang/test/C/C2y/n3346.c

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// RUN: %clang_cc1 -verify -std=c2y -Wall -pedantic -ffreestanding %s
2+
// RUN: %clang_cc1 -verify=expected,ped -Wall -pedantic -ffreestanding %s
3+
4+
/* WG14 N3346: Yes
5+
* Slay Some Earthly Demons VIII
6+
*
7+
* Updates some undefined behavior during initialization to instead be a
8+
* constraint violation.
9+
*/
10+
11+
// The initializer for a scalar shall be a single expression, optionally
12+
// enclosed in braces, or it shall be an empty initializer.
13+
int i = 12, j = {12}, k = {}; // ped-warning {{use of an empty initializer is a C23 extension}}
14+
15+
struct S {
16+
int i;
17+
float f;
18+
int : 0;
19+
char c;
20+
};
21+
22+
void test1(void) {
23+
// The initializer for an object that has structure or union type shall be
24+
// either a single expression that has compatible type or a brace-enclosed
25+
// list of initializers for the elements or named members.
26+
struct S s1 = { 1, 1.2f, 'a' };
27+
struct S s2 = s1;
28+
29+
// Despite being structurally identical to S, T is not compatible with S.
30+
struct T { int i; float f; int : 0; char c; } t;
31+
struct S s3 = t; // expected-error {{initializing 'struct S' with an expression of incompatible type 'struct T'}}
32+
}
33+
34+
void test2(void) {
35+
typedef __WCHAR_TYPE__ wchar_t;
36+
typedef __CHAR16_TYPE__ char16_t;
37+
typedef __CHAR32_TYPE__ char32_t;
38+
39+
// The initializer for an array shall be either a string literal, optionally
40+
// enclosed in braces, or a brace-enclosed list of initializers for the
41+
// elements. An array initialized by character string literal or UTF-8 string
42+
// literal shall have a character type as element type. An array initialized
43+
// with a wide string literal shall have element type compatible with a
44+
// qualified or unqualified wchar_t, char16_t, or char32_t, and the string
45+
// literal shall have the corresponding encoding prefix (L, u, or U,
46+
// respectively).
47+
char str1[] = "string literal";
48+
char str2[] = { "string literal" };
49+
char str3[] = u8"string literal";
50+
char str4[] = { u8"string literal" };
51+
52+
int str5[] = "this doesn't work"; // expected-error {{array initializer must be an initializer list}}
53+
int str6[] = { "this also doesn't work" }; // expected-error {{incompatible pointer to integer conversion initializing 'int' with an expression of type 'char[23]'}}
54+
55+
wchar_t str7[] = L"string literal";
56+
wchar_t str8[] = { L"string literal" };
57+
char16_t str9[] = u"string literal";
58+
char16_t str10[] = { u"string literal" };
59+
char32_t str11[] = U"string literal";
60+
char32_t str12[] = { U"string literal" };
61+
62+
wchar_t str13[] = "nope"; // expected-error {{initializing wide char array with non-wide string literal}}
63+
wchar_t str14[] = { "nope" }; // expected-error-re {{incompatible pointer to integer conversion initializing 'wchar_t' (aka '{{.*}}') with an expression of type 'char[5]'}}
64+
char16_t str15[] = "nope"; // expected-error {{initializing wide char array with non-wide string literal}}
65+
char16_t str16[] = { "nope" }; // expected-error-re {{incompatible pointer to integer conversion initializing 'char16_t' (aka '{{.*}}') with an expression of type 'char[5]'}}
66+
char32_t str17[] = "nope"; // expected-error {{initializing wide char array with non-wide string literal}}
67+
char32_t str18[] = { "nope" }; // expected-error-re {{incompatible pointer to integer conversion initializing 'char32_t' (aka '{{.*}}') with an expression of type 'char[5]'}}
68+
}

clang/www/c_status.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ <h2 id="c2y">C2y implementation status</h2>
211211
<tr>
212212
<td>Slay Some Earthly Demons VIII</td>
213213
<td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3346.pdf">N3346</a></td>
214-
<td class="unknown" align="center">Unknown</td>
214+
<td class="full" align="center">Yes</td>
215215
</tr>
216216
<tr>
217217
<td>Introduce complex literals v. 2</td>

0 commit comments

Comments
 (0)