Skip to content

Commit 6bc71cd

Browse files
committed
[C99] Claim partial conformance to n448
This is the paper that added the 'restrict' keyword. Clang is conforming to the letter of the standard's requirements, so it would be defensible for us to claim full support instead. However, LLVM does not currently support the optimization semantics with restricted local variables or data members, only with restricted pointers declared in function parameters. So we're only claiming partial support because we don't yet take full advantage of what the feature allows.
1 parent 0ec567c commit 6bc71cd

File tree

2 files changed

+54
-1
lines changed

2 files changed

+54
-1
lines changed

clang/test/C/C99/n448.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// RUN: %clang_cc1 -verify -std=c99 %s
2+
// RUN: %clang_cc1 -verify -std=c23 %s
3+
4+
/* WG14 N448: Partial
5+
* Restricted pointers
6+
*
7+
* NB: we claim partial conformance only because LLVM does not attempt to apply
8+
* the semantics on local variables or structure data members; it only
9+
* considers function parameters. However, Clang itself is fully conforming for
10+
* this feature.
11+
*/
12+
13+
// Restrict is only allowed on pointers.
14+
int * restrict ipr;
15+
int restrict ir; // expected-error {{restrict requires a pointer or reference ('int' is invalid)}}
16+
17+
// Restrict only applies to object pointers.
18+
void (* restrict fp)(void); // expected-error {{pointer to function type 'void (void)' may not be 'restrict' qualified}}
19+
20+
typedef int *int_ptr;
21+
int_ptr restrict ipr2; // okay, still applied to the pointer.
22+
23+
// Show that the qualifer is dropped on lvalue conversion
24+
_Static_assert(
25+
_Generic(ipr,
26+
int * : 1,
27+
int * restrict : 0, // expected-warning {{due to lvalue conversion of the controlling expression, association of type 'int *restrict' will never be selected because it is qualified}}
28+
default : 0),
29+
"");
30+
31+
// Show that it's allowed as a qualifier for array parameters.
32+
void f(int array[restrict]) {
33+
int *ipnr = ipr; // okay to drop the top-level qualifier
34+
35+
// Show that it's not okay to drop the qualifier when it's not at the top level.
36+
int * restrict * restrict iprpr;
37+
int **ipp = iprpr; // expected-warning {{initializing 'int **' with an expression of type 'int *restrict *restrict' discards qualifiers}}
38+
int ** restrict ippr = iprpr; // expected-warning {{initializing 'int **restrict' with an expression of type 'int *restrict *restrict' discards qualifiers}}
39+
}
40+
41+
#if __STDC_VERSION__ >= 202311L
42+
// C23 doesn't allow constexpr to mix with restrict. See C23 6.7.2p5.
43+
constexpr int * restrict ip; // expected-error {{constexpr variable cannot have type 'int *const restrict'}}
44+
#endif // __STDC_VERSION__ >= 202311L

clang/www/c_status.html

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,16 @@ <h2 id="c99">C99 implementation status</h2>
115115
<tr>
116116
<td>restricted pointers</td>
117117
<td>N448</td>
118-
<td class="unknown" align="center">Unknown</td>
118+
<td class="partial" align="center">
119+
<details><summary>Partial</summary>
120+
Clang's support for <code>restrict</code> is fully conforming but
121+
considered only partially implemented. Clang implements all of the
122+
constraints required for <code>restrict</code> support, but LLVM only
123+
supports <code>restrict</code> optimization semantics for restricted
124+
pointers used as function parameters; it does not fully support the
125+
semantics for restrict on local variables or data members.
126+
</details>
127+
</td>
119128
</tr>
120129
<tr>
121130
<td>variable length arrays</td>

0 commit comments

Comments
 (0)