Home | History | Annotate | Download | only in Analysis
      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 
      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}}
    118 }
    119