1 | // RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s |
2 | |
3 | void clang_analyzer_eval(int); |
4 | void clang_analyzer_checkInlined(int); |
5 | |
6 | int test1_f1() { |
7 | int y = 1; |
8 | y++; |
9 | clang_analyzer_checkInlined(1); // expected-warning{{TRUE}} |
10 | return y; |
11 | } |
12 | |
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. |
28 | void test2_f1() {} |
29 | int test2_f2(); |
30 | |
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 | |
37 | unsigned factorial(unsigned x) { |
38 | if (x <= 1) |
39 | return 1; |
40 | return x * factorial(x - 1); |
41 | } |
42 | |
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 | |
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. |
68 | static char *return_buf(char *buf) { |
69 | return buf + 10; |
70 | } |
71 | |
72 | void test_return_stack_memory_ok() { |
73 | char stack_buf[100]; |
74 | char *pos = return_buf(stack_buf); |
75 | (void) pos; |
76 | } |
77 | |
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; }; |
87 | int test_rdar10977037_aux(struct rdar10977037 v) { return v.y; } |
88 | int test_rdar10977037_aux_2(struct rdar10977037 v); |
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); |
100 | void test() { |
101 | clang_analyzer_eval(plus1(2) == 3); // expected-warning{{TRUE}} |
102 | } |
103 | |
104 | int plus1(int x) { |
105 | return x + 1; |
106 | } |
107 | |
108 | |
109 | void never_called_by_anyone() { |
110 | clang_analyzer_checkInlined(0); // no-warning |
111 | } |
112 | |
113 | |
114 | void knr_one_argument(a) int a; { } |
115 | |
116 | void call_with_less_arguments() { |
117 | knr_one_argument(); // expected-warning{{too few arguments}} expected-warning{{Function taking 1 argument is called with fewer (0)}} |
118 | } |
119 | |