1 // RUN: %clang_analyze_cc1 \
2 // RUN: -analyzer-checker=core,apiModeling.llvm.ReturnValue \
3 // RUN: -analyzer-output=text -verify %s
4
5 struct Foo { int Field; };
6 bool problem();
7 void doSomething();
8
9 // Test the normal case when the implementation of MCAsmParser::Error() (one of
10 // the methods modeled by this checker) is opaque.
11 namespace test_normal {
12 struct MCAsmParser {
13 static bool Error();
14 };
15
parseFoo(Foo & F)16 bool parseFoo(Foo &F) {
17 if (problem()) {
18 // expected-note@-1 {{Assuming the condition is false}}
19 // expected-note@-2 {{Taking false branch}}
20 return MCAsmParser::Error();
21 }
22
23 F.Field = 0;
24 // expected-note@-1 {{The value 0 is assigned to 'F.Field'}}
25 return false;
26 }
27
parseFile()28 bool parseFile() {
29 Foo F;
30 if (parseFoo(F)) {
31 // expected-note@-1 {{Calling 'parseFoo'}}
32 // expected-note@-2 {{Returning from 'parseFoo'}}
33 // expected-note@-3 {{Taking false branch}}
34 return true;
35 }
36
37 // The following expression would produce the false positive report
38 // "The left operand of '==' is a garbage value"
39 // without the modeling done by apiModeling.llvm.ReturnValue:
40 if (F.Field == 0) {
41 // expected-note@-1 {{Field 'Field' is equal to 0}}
42 // expected-note@-2 {{Taking true branch}}
43 doSomething();
44 }
45
46 // Trigger a zero division to get path notes:
47 (void)(1 / F.Field);
48 // expected-warning@-1 {{Division by zero}}
49 // expected-note@-2 {{Division by zero}}
50 return false;
51 }
52 } // namespace test_normal
53
54
55 // Sanity check for the highly unlikely case where the implementation of the
56 // method breaks the convention.
57 namespace test_break {
58 struct MCAsmParser {
Errortest_break::MCAsmParser59 static bool Error() {
60 return false;
61 }
62 };
63
parseFoo(Foo & F)64 bool parseFoo(Foo &F) {
65 if (problem()) {
66 // expected-note@-1 {{Assuming the condition is false}}
67 // expected-note@-2 {{Taking false branch}}
68 return !MCAsmParser::Error();
69 }
70
71 F.Field = 0;
72 // expected-note@-1 {{The value 0 is assigned to 'F.Field'}}
73 return MCAsmParser::Error();
74 // expected-note@-1 {{'MCAsmParser::Error' returned false, breaking the convention that it always returns true}}
75 }
76
parseFile()77 bool parseFile() {
78 Foo F;
79 if (parseFoo(F)) {
80 // expected-note@-1 {{Calling 'parseFoo'}}
81 // expected-note@-2 {{Returning from 'parseFoo'}}
82 // expected-note@-3 {{Taking false branch}}
83 return true;
84 }
85
86 (void)(1 / F.Field);
87 // expected-warning@-1 {{Division by zero}}
88 // expected-note@-2 {{Division by zero}}
89 return false;
90 }
91 } // namespace test_break
92