1 // RUN: %clang_cc1 -no-opaque-pointers -triple x86_64-apple-darwin -O1 -disable-llvm-passes %s -emit-llvm -o - | FileCheck %s
2
p2unsigned(unsigned ** ptr)3 void p2unsigned(unsigned **ptr) {
4 // CHECK-LABEL: define void @p2unsigned(i32** noundef %ptr)
5 // CHECK-NEXT: entry:
6 // CHECK-NEXT: %ptr.addr = alloca i32**, align 8
7 // CHECK-NEXT: store i32** %ptr, i32*** %ptr.addr, align 8, !tbaa [[ANY_POINTER_0:!.+]]
8 // CHECK-NEXT: [[BASE:%.+]] = load i32**, i32*** %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
9 // CHECK-NEXT: store i32* null, i32** [[BASE]], align 8, !tbaa [[ANY_POINTER_0]]
10 // CHECK-NEXT: ret void
11 //
12 *ptr = 0;
13 }
14
p2unsigned_volatile(unsigned * volatile * ptr)15 void p2unsigned_volatile(unsigned *volatile *ptr) {
16 // CHECK-LABEL: define void @p2unsigned_volatile(i32** noundef %ptr)
17 // CHECK-NEXT: entry:
18 // CHECK-NEXT: %ptr.addr = alloca i32**, align 8
19 // CHECK-NEXT: store i32** %ptr, i32*** %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
20 // CHECK-NEXT: [[BASE:%.+]] = load i32**, i32*** %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
21 // CHECK-NEXT: store volatile i32* null, i32** [[BASE]], align 8, !tbaa [[ANY_POINTER_0]]
22 // CHECK-NEXT: ret void
23 //
24 *ptr = 0;
25 }
26
p3int(int *** ptr)27 void p3int(int ***ptr) {
28 // CHECK-LABEL: define void @p3int(i32*** noundef %ptr)
29 // CHECK-NEXT: entry:
30 // CHECK-NEXT: %ptr.addr = alloca i32***, align 8
31 // CHECK-NEXT: store i32*** %ptr, i32**** %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
32 // CHECK-NEXT: [[BASE_0:%.+]] = load i32***, i32**** %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
33 // CHECK-NEXT: [[BASE_1:%.+]] = load i32**, i32*** [[BASE_0]], align 8, !tbaa [[ANY_POINTER_0]]
34 // CHECK-NEXT: store i32* null, i32** [[BASE_1]], align 8, !tbaa [[ANY_POINTER_0]]
35 // CHECK-NEXT: ret void
36 //
37 **ptr = 0;
38 }
39
p4char(char **** ptr)40 void p4char(char ****ptr) {
41 // CHECK-LABEL: define void @p4char(i8**** noundef %ptr)
42 // CHECK-NEXT: entry:
43 // CHECK-NEXT: %ptr.addr = alloca i8****, align 8
44 // CHECK-NEXT: store i8**** %ptr, i8***** %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
45 // CHECK-NEXT: [[BASE_0:%.+]] = load i8****, i8***** %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
46 // CHECK-NEXT: [[BASE_1:%.+]] = load i8***, i8**** [[BASE_0]], align 8, !tbaa [[ANY_POINTER_0]]
47 // CHECK-NEXT: [[BASE_2:%.+]] = load i8**, i8*** [[BASE_1]], align 8, !tbaa [[ANY_POINTER_0]]
48 // CHECK-NEXT: store i8* null, i8** [[BASE_2]], align 8, !tbaa [[ANY_POINTER_0]]
49 // CHECK-NEXT: ret void
50 //
51 ***ptr = 0;
52 }
53
p4char_const1(const char **** ptr)54 void p4char_const1(const char ****ptr) {
55 // CHECK-LABEL: define void @p4char_const1(i8**** noundef %ptr)
56 // CHECK-NEXT: entry:
57 // CHECK-NEXT: %ptr.addr = alloca i8****, align 8
58 // CHECK-NEXT: store i8**** %ptr, i8***** %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
59 // CHECK-NEXT: [[BASE_0:%.+]] = load i8****, i8***** %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
60 // CHECK-NEXT: [[BASE_1:%.+]] = load i8***, i8**** [[BASE_0]], align 8, !tbaa [[ANY_POINTER_0]]
61 // CHECK-NEXT: [[BASE_2:%.+]] = load i8**, i8*** [[BASE_1]], align 8, !tbaa [[ANY_POINTER_0]]
62 // CHECK-NEXT: store i8* null, i8** [[BASE_2]], align 8, !tbaa [[ANY_POINTER_0]]
63 // CHECK-NEXT: ret void
64 //
65 ***ptr = 0;
66 }
67
p4char_const2(const char ** const ** ptr)68 void p4char_const2(const char **const **ptr) {
69 // CHECK-LABEL: define void @p4char_const2(i8**** noundef %ptr)
70 // CHECK-NEXT: entry:
71 // CHECK-NEXT: %ptr.addr = alloca i8****, align 8
72 // CHECK-NEXT: store i8**** %ptr, i8***** %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
73 // CHECK-NEXT: [[BASE_0:%.+]] = load i8****, i8***** %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
74 // CHECK-NEXT: [[BASE_1:%.+]] = load i8***, i8**** [[BASE_0]], align 8, !tbaa [[ANY_POINTER_0]]
75 // CHECK-NEXT: [[BASE_2:%.+]] = load i8**, i8*** [[BASE_1]], align 8, !tbaa [[ANY_POINTER_0]]
76 // CHECK-NEXT: store i8* null, i8** [[BASE_2]], align 8, !tbaa [[ANY_POINTER_0]]
77 // CHECK-NEXT: ret void
78 //
79 ***ptr = 0;
80 }
81
82 struct S1 {
83 int x;
84 int y;
85 };
86
p2struct(struct S1 ** ptr)87 void p2struct(struct S1 **ptr) {
88 // CHECK-LABEL: define void @p2struct(%struct.S1** noundef %ptr)
89 // CHECK-NEXT: entry:
90 // CHECK-NEXT: %ptr.addr = alloca %struct.S1**, align 8
91 // CHECK-NEXT: store %struct.S1** %ptr, %struct.S1*** %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
92 // CHECK-NEXT: [[BASE:%.+]] = load %struct.S1**, %struct.S1*** %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
93 // CHECK-NEXT: store %struct.S1* null, %struct.S1** [[BASE]], align 8, !tbaa [[ANY_POINTER_0]]
94 // CHECK-NEXT: ret void
95 //
96 *ptr = 0;
97 }
98
99 // CHECK: [[ANY_POINTER_0]] = !{[[ANY_POINTER:!.+]], [[ANY_POINTER]], i64 0}
100 // CHECK: [[ANY_POINTER]] = !{!"any pointer", [[CHAR:!.+]], i64 0}
101 // CHECK: [[CHAR]] = !{!"omnipotent char", [[TBAA_ROOT:!.+]], i64 0}
102 // CHECK: [[TBAA_ROOT]] = !{!"Simple C/C++ TBAA"}
103 //
104