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