xref: /aosp_15_r20/external/clang/test/Analysis/inline.c (revision 67e74705e28f6214e480b399dd47ea732279e315)
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 Li int 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 Li void 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 Li void test2_f1() {}
29*67e74705SXin Li int test2_f2();
30*67e74705SXin Li 
test2_f3()31*67e74705SXin Li void 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 Li unsigned 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 Li void 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 Li void 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 Li static char *return_buf(char *buf) {
69*67e74705SXin Li   return buf + 10;
70*67e74705SXin Li }
71*67e74705SXin Li 
test_return_stack_memory_ok()72*67e74705SXin Li void 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 Li char *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 Li int test_rdar10977037_aux(struct rdar10977037 v) { return v.y; }
88*67e74705SXin Li int test_rdar10977037_aux_2(struct rdar10977037 v);
test_rdar10977037()89*67e74705SXin Li int 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 Li void test() {
101*67e74705SXin Li   clang_analyzer_eval(plus1(2) == 3); // expected-warning{{TRUE}}
102*67e74705SXin Li }
103*67e74705SXin Li 
plus1(int x)104*67e74705SXin Li int plus1(int x) {
105*67e74705SXin Li   return x + 1;
106*67e74705SXin Li }
107*67e74705SXin Li 
108*67e74705SXin Li 
never_called_by_anyone()109*67e74705SXin Li void 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 Li void knr_one_argument(a) int a; { }
115*67e74705SXin Li 
call_with_less_arguments()116*67e74705SXin Li void 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