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