// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-ipa=inlining -analyzer-store region -verify %s int test1_f1() { int y = 1; y++; return y; } void test1_f2() { int x = 1; x = test1_f1(); if (x == 1) { int *p = 0; *p = 3; // no-warning } if (x == 2) { int *p = 0; *p = 3; // expected-warning{{Dereference of null pointer (loaded from variable 'p')}} } } // Test that inlining works when the declared function has less arguments // than the actual number in the declaration. void test2_f1() {} int test2_f2(); void test2_f3() { test2_f1(test2_f2()); // expected-warning{{too many arguments in call to 'test2_f1'}} } // Test that inlining works with recursive functions. unsigned factorial(unsigned x) { if (x <= 1) return 1; return x * factorial(x - 1); } void test_factorial() { if (factorial(3) == 6) { int *p = 0; *p = 0xDEADBEEF; // expected-warning {{null}} } else { int *p = 0; *p = 0xDEADBEEF; // no-warning } } void test_factorial_2() { unsigned x = factorial(3); if (x == factorial(3)) { int *p = 0; *p = 0xDEADBEEF; // expected-warning {{null}} } else { int *p = 0; *p = 0xDEADBEEF; // no-warning } } // Test that returning stack memory from a parent stack frame does // not trigger a warning. static char *return_buf(char *buf) { return buf + 10; } void test_return_stack_memory_ok() { char stack_buf[100]; char *pos = return_buf(stack_buf); (void) pos; } char *test_return_stack_memory_bad() { char stack_buf[100]; char *x = stack_buf; return x; // expected-warning {{stack memory associated}} } // Test that passing a struct value with an uninitialized field does // not trigger a warning if we are inlining and the body is available. struct rdar10977037 { int x, y; }; int test_rdar10977037_aux(struct rdar10977037 v) { return v.y; } int test_rdar10977037_aux_2(struct rdar10977037 v); int test_rdar10977037() { struct rdar10977037 v; v.y = 1; v. y += test_rdar10977037_aux(v); // no-warning return test_rdar10977037_aux_2(v); // expected-warning {{Passed-by-value struct argument contains uninitialized data}} }