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-DAG: 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-DAG: empty: features=0 stack_args=0 18 void empty() {} 19 20 // CHECK-DAG: simple: features=0 stack_args=0 21 int simple(int *data, int index) { return data[index + 1]; } 22 23 // CHECK-DAG: builtins: features=0 stack_args=0 24 int builtins() { 25 int x = 0; 26 __builtin_prefetch(&x); 27 return x; 28 } 29 30 // CHECK-DAG: ellipsis: features=0 stack_args=0 31 void ellipsis(const char *fmt, ...) { 32 int x; 33 escape(&x); 34 } 35 36 // CHECK-DAG: non_empty_function: features=2 stack_args=0 37 void non_empty_function() { 38 int x; 39 escape(&x); 40 } 41 42 // CHECK-DAG: 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(&x); 46 } 47 48 // CHECK-DAG: 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(&x); 52 } 53 54 // CHECK-DAG: 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(&x); 59 } 60 61 // CHECK-DAG: 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(&x); 68 } 69 70 __attribute__((noinline)) int tail_called(int x) { return x; } 71 72 // CHECK-DAG: 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-DAG: with_noreturn_tail_call: features=0 78 int with_noreturn_tail_call(int x) { return noreturn(x); } 79 80 // CHECK-DAG: local_array: features=0 81 void local_array(int x) { 82 int data[10]; 83 use(data[x]); 84 } 85 86 // CHECK-DAG: 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(p[j]); 91 } 92 93 // CHECK-DAG: 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[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