1 // RUN: %clang_analyze_cc1 \
2 // RUN: -analyzer-checker=core,apiModeling.llvm.ReturnValue \
3 // RUN: -analyzer-output=text -verify=class %s
4
5 struct Foo { int Field; };
6 bool problem();
7 void doSomething();
8
9 // We predefined the return value of 'MCAsmParser::Error' as true and we cannot
10 // take the false-branches which leads to a "garbage value" false positive.
11 namespace test_classes {
12 struct MCAsmParser {
13 static bool Error();
14 };
15
parseFoo(Foo & F)16 bool parseFoo(Foo &F) {
17 if (problem()) {
18 // class-note@-1 {{Assuming the condition is false}}
19 // class-note@-2 {{Taking false branch}}
20 return MCAsmParser::Error();
21 }
22
23 F.Field = 0;
24 // class-note@-1 {{The value 0 is assigned to 'F.Field'}}
25 return !MCAsmParser::Error();
26 // class-note@-1 {{'MCAsmParser::Error' returns true}}
27 }
28
parseFile()29 bool parseFile() {
30 Foo F;
31 if (parseFoo(F)) {
32 // class-note@-1 {{Calling 'parseFoo'}}
33 // class-note@-2 {{Returning from 'parseFoo'}}
34 // class-note@-3 {{Taking false branch}}
35 return true;
36 }
37
38 if (F.Field == 0) {
39 // class-note@-1 {{Field 'Field' is equal to 0}}
40 // class-note@-2 {{Taking true branch}}
41
42 // no-warning: "The left operand of '==' is a garbage value" was here.
43 doSomething();
44 }
45
46 (void)(1 / F.Field);
47 // class-warning@-1 {{Division by zero}}
48 // class-note@-2 {{Division by zero}}
49 return false;
50 }
51 } // namespace test_classes
52
53
54 // We predefined 'MCAsmParser::Error' as returning true, but now it returns
55 // false, which breaks our invariant. Test the notes.
56 namespace test_break {
57 struct MCAsmParser {
Errortest_break::MCAsmParser58 static bool Error() {
59 return false; // class-note {{'MCAsmParser::Error' returns false}}
60 }
61 };
62
parseFoo(Foo & F)63 bool parseFoo(Foo &F) {
64 if (problem()) {
65 // class-note@-1 {{Assuming the condition is false}}
66 // class-note@-2 {{Taking false branch}}
67 return !MCAsmParser::Error();
68 }
69
70 F.Field = 0;
71 // class-note@-1 {{The value 0 is assigned to 'F.Field'}}
72 return MCAsmParser::Error();
73 // class-note@-1 {{Calling 'MCAsmParser::Error'}}
74 // class-note@-2 {{Returning from 'MCAsmParser::Error'}}
75 }
76
parseFile()77 bool parseFile() {
78 Foo F;
79 if (parseFoo(F)) {
80 // class-note@-1 {{Calling 'parseFoo'}}
81 // class-note@-2 {{Returning from 'parseFoo'}}
82 // class-note@-3 {{Taking false branch}}
83 return true;
84 }
85
86 (void)(1 / F.Field);
87 // class-warning@-1 {{Division by zero}}
88 // class-note@-2 {{Division by zero}}
89 return false;
90 }
91 } // namespace test_classes
92