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