1 // -*- C++ -*- 2 //===----------------------------------------------------------------------===// 3 // 4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5 // See https://llvm.org/LICENSE.txt for license information. 6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7 // 8 //===----------------------------------------------------------------------===// 9 10 // TODO: Figure out why this fails with Memory Sanitizer. 11 // XFAIL: msan 12 13 // This test fails on older llvm, when built with picolibc. 14 // XFAIL: clang-16 && LIBCXX-PICOLIBC-FIXME 15 16 #undef NDEBUG 17 #include <assert.h> 18 #include <stdlib.h> 19 #include <unwind.h> 20 21 #define EXPECTED_NUM_FRAMES 50 22 #define NUM_FRAMES_UPPER_BOUND 100 23 callback(_Unwind_Context * context,void * cnt)24__attribute__((noinline)) _Unwind_Reason_Code callback(_Unwind_Context *context, 25 void *cnt) { 26 (void)context; 27 int *i = (int *)cnt; 28 ++*i; 29 if (*i > NUM_FRAMES_UPPER_BOUND) { 30 abort(); 31 } 32 return _URC_NO_REASON; 33 } 34 test_backtrace()35__attribute__((noinline)) void test_backtrace() { 36 int n = 0; 37 _Unwind_Backtrace(&callback, &n); 38 if (n < EXPECTED_NUM_FRAMES) { 39 abort(); 40 } 41 } 42 43 // These functions are effectively the same, but we have to be careful to avoid 44 // unwanted optimizations that would mess with the number of frames we expect. 45 // Surprisingly, slapping `noinline` is not sufficient -- we also have to avoid 46 // writing the function in a way that the compiler can easily spot tail 47 // recursion. 48 __attribute__((noinline)) int test1(int i); 49 __attribute__((noinline)) int test2(int i); 50 test1(int i)51__attribute__((noinline)) int test1(int i) { 52 if (i == 0) { 53 test_backtrace(); 54 return 0; 55 } else { 56 return i + test2(i - 1); 57 } 58 } 59 test2(int i)60__attribute__((noinline)) int test2(int i) { 61 if (i == 0) { 62 test_backtrace(); 63 return 0; 64 } else { 65 return i + test1(i - 1); 66 } 67 } 68 main(int,char **)69int main(int, char**) { 70 int total = test1(50); 71 assert(total == 1275); 72 return 0; 73 } 74