1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | // RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s void clang_analyzer_eval(int); void clang_analyzer_checkInlined(int); int test1_f1() { int y = 1; y++; clang_analyzer_checkInlined(1); // expected-warning{{TRUE}} return y; } void test1_f2() { int x = 1; x = test1_f1(); if (x == 1) { int *p = 0; *p = 3; // no-warning } if (x == 2) { int *p = 0; *p = 3; // expected-warning{{Dereference of null pointer (loaded from variable 'p')}} } } // Test that inlining works when the declared function has less arguments // than the actual number in the declaration. void test2_f1() {} int test2_f2(); void test2_f3() { test2_f1(test2_f2()); // expected-warning{{too many arguments in call to 'test2_f1'}} } // Test that inlining works with recursive functions. unsigned factorial(unsigned x) { if (x <= 1) return 1; return x * factorial(x - 1); } void test_factorial() { if (factorial(3) == 6) { int *p = 0; *p = 0xDEADBEEF; // expected-warning {{null}} } else { int *p = 0; *p = 0xDEADBEEF; // no-warning } } void test_factorial_2() { unsigned x = factorial(3); if (x == factorial(3)) { int *p = 0; *p = 0xDEADBEEF; // expected-warning {{null}} } else { int *p = 0; *p = 0xDEADBEEF; // no-warning } } // Test that returning stack memory from a parent stack frame does // not trigger a warning. static char *return_buf(char *buf) { return buf + 10; } void test_return_stack_memory_ok() { char stack_buf[100]; char *pos = return_buf(stack_buf); (void) pos; } char *test_return_stack_memory_bad() { char stack_buf[100]; char *x = stack_buf; return x; // expected-warning {{stack memory associated}} } // Test that passing a struct value with an uninitialized field does // not trigger a warning if we are inlining and the body is available. struct rdar10977037 { int x, y; }; int test_rdar10977037_aux(struct rdar10977037 v) { return v.y; } int test_rdar10977037_aux_2(struct rdar10977037 v); int test_rdar10977037() { struct rdar10977037 v; v.y = 1; v. y += test_rdar10977037_aux(v); // no-warning return test_rdar10977037_aux_2(v); // expected-warning {{Passed-by-value struct argument contains uninitialized data}} } // Test inlining a forward-declared function. // This regressed when CallEvent was first introduced. int plus1(int x); void test() { clang_analyzer_eval(plus1(2) == 3); // expected-warning{{TRUE}} } int plus1(int x) { return x + 1; } void never_called_by_anyone() { clang_analyzer_checkInlined(0); // no-warning } void knr_one_argument(a) int a; { } void call_with_less_arguments() { knr_one_argument(); // expected-warning{{too few arguments}} expected-warning{{Function taking 1 argument is called with fewer (0)}} } |