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