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