Skip to content

Commit a103ecc

Browse files
AaronBallmanAlexisPerry
authored andcommitted
[C23] Claim we do not conform to N2819
This paper clarified the lifetime of compound literal objects in odd scopes, such as use at function prototype scope. We do not currently implement this paper, as the new test demonstrates.
1 parent 3231b80 commit a103ecc

File tree

2 files changed

+58
-1
lines changed

2 files changed

+58
-1
lines changed

clang/test/C/C2x/n2819.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 3
2+
// RUN: %clang_cc1 -triple=x86_64 -emit-llvm -o - -std=c23 %s | FileCheck %s
3+
4+
/* WG14 N2819: No
5+
* Disambiguate the storage class of some compound literals
6+
*/
7+
8+
int *escaped;
9+
// CHECK-LABEL: define dso_local i32 @f(
10+
// CHECK-SAME: ptr noundef [[PTR:%.*]]) #[[ATTR0:[0-9]+]] {
11+
// CHECK-NEXT: entry:
12+
// CHECK-NEXT: [[PTR_ADDR:%.*]] = alloca ptr, align 8
13+
// CHECK-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8
14+
// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8
15+
// CHECK-NEXT: store ptr [[TMP0]], ptr @escaped, align 8
16+
// CHECK-NEXT: ret i32 1
17+
//
18+
int f(int *ptr) { escaped = ptr; return 1; }
19+
20+
// CHECK-LABEL: define dso_local i32 @g(
21+
// CHECK-SAME: ptr noundef [[PARA:%.*]]) #[[ATTR0]] {
22+
// CHECK-NEXT: entry:
23+
// CHECK-NEXT: [[PARA_ADDR:%.*]] = alloca ptr, align 8
24+
// CHECK-NEXT: store ptr [[PARA]], ptr [[PARA_ADDR]], align 8
25+
// CHECK-NEXT: [[CALL:%.*]] = call i32 @f(ptr noundef @.compoundliteral)
26+
// CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[CALL]] to i64
27+
// CHECK-NEXT: ret i32 0
28+
//
29+
// FIXME: notice the we are using the global .compoundliteral object, not
30+
// allocating a new object on each call to g(). That's what was clarified by
31+
// N2819.
32+
int g(char *para [f(( int [27]) { 0 })]) {
33+
return 0;
34+
}
35+
36+
// CHECK-LABEL: define dso_local i32 @main(
37+
// CHECK-SAME: ) #[[ATTR0]] {
38+
// CHECK-NEXT: entry:
39+
// CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4
40+
// CHECK-NEXT: store i32 0, ptr [[RETVAL]], align 4
41+
// CHECK-NEXT: [[CALL:%.*]] = call i32 @g(ptr noundef null)
42+
// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr @escaped, align 8
43+
// CHECK-NEXT: store i32 12, ptr [[TMP0]], align 4
44+
// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr @escaped, align 8
45+
// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[TMP1]], align 4
46+
// CHECK-NEXT: ret i32 [[TMP2]]
47+
//
48+
int main() {
49+
// Sets 'escaped' to the address of the array created by the compound literal.
50+
g(nullptr);
51+
52+
// The lifetime of that object should have ended when g() returned, so this
53+
// should be a use-after-free.
54+
*escaped = 12;
55+
return *escaped;
56+
}
57+

clang/www/c_status.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1025,7 +1025,7 @@ <h2 id="c2x">C23 implementation status</h2>
10251025
<tr>
10261026
<td>Disambiguate the storage class of some compound literals</td>
10271027
<td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2819.pdf">N2819</a></td>
1028-
<td class="unknown" align="center">Unknown</td>
1028+
<td class="none" align="center">No</td>
10291029
</tr>
10301030
<tr>
10311031
<td>Add annotations for unreachable control flow v2</td>

0 commit comments

Comments
 (0)