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 
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   // class-note@-2 {{Returning zero, which participates in a condition later}}
28 }
29 
30 bool parseFile() {
31   Foo F;
32   if (parseFoo(F)) {
33     // class-note@-1 {{Calling 'parseFoo'}}
34     // class-note@-2 {{Returning from 'parseFoo'}}
35     // class-note@-3 {{Taking false branch}}
36     return true;
37   }
38 
39   if (F.Field == 0) {
40     // class-note@-1 {{Field 'Field' is equal to 0}}
41     // class-note@-2 {{Taking true branch}}
42 
43     // no-warning: "The left operand of '==' is a garbage value" was here.
44     doSomething();
45   }
46 
47   (void)(1 / F.Field);
48   // class-warning@-1 {{Division by zero}}
49   // class-note@-2 {{Division by zero}}
50   return false;
51 }
52 } // namespace test_classes
53 
54 
55 // We predefined 'MCAsmParser::Error' as returning true, but now it returns
56 // false, which breaks our invariant. Test the notes.
57 namespace test_break {
58 struct MCAsmParser {
59   static bool Error() {
60     return false; // class-note {{'MCAsmParser::Error' returns false}}
61     // class-note@-1 {{Returning zero, which participates in a condition later}}
62   }
63 };
64 
65 bool parseFoo(Foo &F) {
66   if (problem()) {
67     // class-note@-1 {{Assuming the condition is false}}
68     // class-note@-2 {{Taking false branch}}
69     return !MCAsmParser::Error();
70   }
71 
72   F.Field = 0;
73   // class-note@-1 {{The value 0 is assigned to 'F.Field'}}
74   return MCAsmParser::Error();
75   // class-note@-1 {{Calling 'MCAsmParser::Error'}}
76   // class-note@-2 {{Returning from 'MCAsmParser::Error'}}
77   // class-note@-3 {{Returning zero, which participates in a condition later}}
78 }
79 
80 bool parseFile() {
81   Foo F;
82   if (parseFoo(F)) {
83     // class-note@-1 {{Calling 'parseFoo'}}
84     // class-note@-2 {{Returning from 'parseFoo'}}
85     // class-note@-3 {{Taking false branch}}
86     return true;
87   }
88 
89   (void)(1 / F.Field);
90   // class-warning@-1 {{Division by zero}}
91   // class-note@-2 {{Division by zero}}
92   return false;
93 }
94 } // namespace test_classes
95