1 | // RUN: %clangxx %s -O1 -o %t -fexperimental-sanitize-metadata=covered,uar && %t | FileCheck %s |
2 | // RUN: %clangxx %s -O1 -o %t -fexperimental-sanitize-metadata=covered,uar -fsanitize=address,signed-integer-overflow,alignment && %t | FileCheck %s |
3 | // RUN: %clangxx %s -O1 -o %t -mcmodel=large -fexperimental-sanitize-metadata=covered,uar -fsanitize=address,signed-integer-overflow,alignment && %t | FileCheck %s |
4 | |
5 | // CHECK: metadata add version 2 |
6 | |
7 | __attribute__((noinline, not_tail_called)) void escape(const volatile void *p) { |
8 | [[maybe_unused]] static const volatile void *sink; |
9 | sink = p; |
10 | } |
11 | |
12 | __attribute__((noinline, not_tail_called)) void use(int x) { |
13 | static volatile int sink; |
14 | sink += x; |
15 | } |
16 | |
17 | // CHECK: empty: features=0 stack_args=0 |
18 | void empty() {} |
19 | |
20 | // CHECK: simple: features=0 stack_args=0 |
21 | int simple(int *data, int index) { return data[index + 1]; } |
22 | |
23 | // CHECK: builtins: features=0 stack_args=0 |
24 | int builtins() { |
25 | int x = 0; |
26 | __builtin_prefetch(&x); |
27 | return x; |
28 | } |
29 | |
30 | // CHECK: ellipsis: features=0 stack_args=0 |
31 | void ellipsis(const char *fmt, ...) { |
32 | int x; |
33 | escape(p: &x); |
34 | } |
35 | |
36 | // CHECK: non_empty_function: features=2 stack_args=0 |
37 | void non_empty_function() { |
38 | int x; |
39 | escape(p: &x); |
40 | } |
41 | |
42 | // CHECK: no_stack_args: features=2 stack_args=0 |
43 | void no_stack_args(long a0, long a1, long a2, long a3, long a4, long a5) { |
44 | int x; |
45 | escape(p: &x); |
46 | } |
47 | |
48 | // CHECK: stack_args: features=6 stack_args=16 |
49 | void stack_args(long a0, long a1, long a2, long a3, long a4, long a5, long a6) { |
50 | int x; |
51 | escape(p: &x); |
52 | } |
53 | |
54 | // CHECK: more_stack_args: features=6 stack_args=32 |
55 | void more_stack_args(long a0, long a1, long a2, long a3, long a4, long a5, |
56 | long a6, long a7, long a8) { |
57 | int x; |
58 | escape(p: &x); |
59 | } |
60 | |
61 | // CHECK: struct_stack_args: features=6 stack_args=144 |
62 | struct large { |
63 | char x[131]; |
64 | }; |
65 | void struct_stack_args(large a) { |
66 | int x; |
67 | escape(p: &x); |
68 | } |
69 | |
70 | __attribute__((noinline)) int tail_called(int x) { return x; } |
71 | |
72 | // CHECK: with_tail_call: features=2 |
73 | int with_tail_call(int x) { [[clang::musttail]] return tail_called(x); } |
74 | |
75 | __attribute__((noinline, noreturn)) int noreturn(int x) { __builtin_trap(); } |
76 | |
77 | // CHECK: with_noreturn_tail_call: features=0 |
78 | int with_noreturn_tail_call(int x) { return noreturn(x); } |
79 | |
80 | // CHECK: local_array: features=0 |
81 | void local_array(int x) { |
82 | int data[10]; |
83 | use(x: data[x]); |
84 | } |
85 | |
86 | // CHECK: local_alloca: features=0 |
87 | void local_alloca(int size, int i, int j) { |
88 | volatile int *p = static_cast<int *>(__builtin_alloca(size)); |
89 | p[i] = 0; |
90 | use(x: p[j]); |
91 | } |
92 | |
93 | // CHECK: escaping_alloca: features=2 |
94 | void escaping_alloca(int size, int i) { |
95 | volatile int *p = static_cast<int *>(__builtin_alloca(size)); |
96 | escape(p: &p[i]); |
97 | } |
98 | |
99 | #define FUNCTIONS \ |
100 | FN(empty); \ |
101 | FN(simple); \ |
102 | FN(builtins); \ |
103 | FN(ellipsis); \ |
104 | FN(non_empty_function); \ |
105 | FN(no_stack_args); \ |
106 | FN(stack_args); \ |
107 | FN(more_stack_args); \ |
108 | FN(struct_stack_args); \ |
109 | FN(with_tail_call); \ |
110 | FN(with_noreturn_tail_call); \ |
111 | FN(local_array); \ |
112 | FN(local_alloca); \ |
113 | FN(escaping_alloca); \ |
114 | /**/ |
115 | |
116 | #include "common.h" |
117 | |