Clang Project

clang_source_code/test/Analysis/max-nodes-suppress-on-sink.c
1// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config max-nodes=12 -verify %s
2
3// Here we test how "suppress on sink" feature of certain bugtypes interacts
4// with reaching analysis limits.
5
6// If we report a warning of a bug-type with "suppress on sink" attribute set
7// (such as MallocChecker's memory leak warning), then failing to reach the
8// reason for the sink (eg. no-return function such as "exit()") due to analysis
9// limits (eg. max-nodes option), we may produce a false positive.
10
11typedef __typeof(sizeof(int)) size_t;
12void *malloc(size_t);
13
14extern void exit(int) __attribute__ ((__noreturn__));
15
16void clang_analyzer_warnIfReached(void);
17
18int coin();
19
20void test_single_cfg_block_sink() {
21  void *p = malloc(1); // no-warning (wherever the leak warning may occur here)
22
23  // Due to max-nodes option in the run line, we should reach the first call
24  // but bail out before the second call.
25  // If the test on these two lines starts failing, see if modifying
26  // the max-nodes run-line helps.
27  clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
28  clang_analyzer_warnIfReached(); // no-warning
29
30  // Even though we do not reach this line, we should still suppress
31  // the leak report.
32  exit(0);
33}
34
35// A similar test with more complicated control flow before the no-return thing,
36// so that the no-return thing wasn't in the same CFG block.
37void test_more_complex_control_flow_before_sink() {
38  void *p = malloc(1); // no-warning
39
40  clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
41  clang_analyzer_warnIfReached(); // no-warning
42
43  if (coin())
44    exit(0);
45  else
46    exit(1);
47}
48
49// A loop before the no-return function, to make sure that
50// the dominated-by-sink analysis doesn't hang.
51void test_loop_before_sink(int n) {
52  void *p = malloc(1); // no-warning
53
54  clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
55  clang_analyzer_warnIfReached(); // no-warning
56
57  for (int i = 0; i < n; ++i) {
58  }
59  exit(1);
60}
61
62// We're not sure if this is no-return.
63void test_loop_with_sink(int n) {
64  void *p = malloc(1); // expected-warning@+2{{Potential leak of memory}}
65
66  clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
67  clang_analyzer_warnIfReached(); // no-warning
68
69  for (int i = 0; i < n; ++i)
70    if (i == 0)
71      exit(1);
72}
73
74// Handle unreachable blocks correctly.
75void test_unreachable_successor_blocks() {
76  void *p = malloc(1); // no-warning
77
78  clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
79  clang_analyzer_warnIfReached(); // no-warning
80
81  if (1) // no-crash
82    exit(1);
83}
84