From 3faf50952d639f79207de595719f79f22a993eb9 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Tue, 28 Apr 2020 04:44:26 -0400 Subject: [PATCH 084/179] FIXME: handle pure fns, known fns, and fn ptrs with handle_unrecognized_call --- gcc/analyzer/region-model2.cc | 11 +- gcc/testsuite/gcc.dg/analyzer/unknown-fns-2.c | 120 ++++++++++++++++++ 2 files changed, 130 insertions(+), 1 deletion(-) diff --git a/gcc/analyzer/region-model2.cc b/gcc/analyzer/region-model2.cc index ac35ad8750a..23fe704e34e 100644 --- a/gcc/analyzer/region-model2.cc +++ b/gcc/analyzer/region-model2.cc @@ -4080,6 +4080,8 @@ region_model2::on_gcall (const supernode *snode, { region_model2_context *ctxt = NULL; // FIXME + bool unknown_effects = false; + /* Debugging/test support. */ if (is_special_named_call_p (call, "__analyzer_dump", 0)) { @@ -4163,9 +4165,16 @@ region_model2::on_gcall (const supernode *snode, /* Otherwise an unknown value. */ return true; } + + if (!fndecl_has_gimple_body_p (callee_fndecl) + && !DECL_PURE_P (callee_fndecl)) + unknown_effects = true; } + else + unknown_effects = true; - handle_unrecognized_call (call, ctxt); + if (unknown_effects) + handle_unrecognized_call (call, ctxt); return true; } diff --git a/gcc/testsuite/gcc.dg/analyzer/unknown-fns-2.c b/gcc/testsuite/gcc.dg/analyzer/unknown-fns-2.c index fd99127e3ec..be722c2215b 100644 --- a/gcc/testsuite/gcc.dg/analyzer/unknown-fns-2.c +++ b/gcc/testsuite/gcc.dg/analyzer/unknown-fns-2.c @@ -30,6 +30,30 @@ void test_1 (void) __analyzer_eval (i == 17); /* { dg-warning "UNKNOWN" } */ } +/* As test_1, but with an unknown fn_ptr. */ + +void test_1a (void (*fn_ptr) (void *)) +{ + int i; + + i = 42; + __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */ + + fn_ptr (NULL); + __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */ + + fn_ptr (&i); + __analyzer_eval (i == 42); /* { dg-warning "UNKNOWN" } */ + + i = 17; + __analyzer_eval (i == 17); /* { dg-warning "TRUE" } */ + + /* Even though we're not passing &i to unknown_fn, it escaped + above, so fn_ptr (NULL) could write to it. */ + fn_ptr (NULL); + __analyzer_eval (i == 17); /* { dg-warning "UNKNOWN" } */ +} + int *global_for_test_2; void test_2 (void) @@ -119,3 +143,99 @@ void test_4 (struct used_by_test_4 *st4_ptr) unknown_fn (NULL); __analyzer_eval (i == 17); /* { dg-warning "UNKNOWN" } */ } + +static void __attribute__((noinline)) +known_fn (void *ptr) +{ + /* Empty. */ +} + +void test_5 (void) +{ + int i; + + i = 42; + __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */ + + known_fn (&i); + __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */ + + i = 17; + __analyzer_eval (i == 17); /* { dg-warning "TRUE" } */ + + /* Ensure that we don't consider &i to have escaped. */ + unknown_fn (NULL); + __analyzer_eval (i == 17); /* { dg-warning "TRUE" } */ +} + +extern int __attribute__ ((__pure__)) +unknown_pure_fn (void *); + +void test_6 (void) +{ + int i; + + i = 42; + __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */ + + unknown_pure_fn (&i); + __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */ + + i = 17; + __analyzer_eval (i == 17); /* { dg-warning "TRUE" } */ + + /* Ensure that we don't consider &i to have escaped. */ + unknown_fn (NULL); + __analyzer_eval (i == 17); /* { dg-warning "TRUE" } */ +} + +extern void unknown_const_fn (const void *); + +void test_7 (void) +{ + int i; + + i = 42; + __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */ + + /* &i is passed as a const void *, so i shouldn't be clobbered by + the call. */ + unknown_const_fn (&i); + __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */ + + i = 17; + __analyzer_eval (i == 17); /* { dg-warning "TRUE" } */ + + /* Ensure that we don't consider &i to have escaped. */ + unknown_fn (NULL); + __analyzer_eval (i == 17); /* { dg-warning "TRUE" } */ +} + +struct used_by_test_8 +{ + int *int_ptr; +}; + +void test_8 (void) +{ + int i; + + i = 42; + __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */ + + struct used_by_test_8 st8; + st8.int_ptr = &i; + + /* Although unknown_const_fn takes a const void *, the + int_ptr is a non-const int *, and so &i should be considered + writable. */ + unknown_const_fn (&st8); + __analyzer_eval (i == 42); /* { dg-warning "UNKNOWN" } */ + + i = 17; + __analyzer_eval (i == 17); /* { dg-warning "TRUE" } */ + + /* &i should be considered to have escaped. */ + unknown_fn (NULL); + __analyzer_eval (i == 17); /* { dg-warning "UNKNOWN" } */ +} -- 2.21.0