xref: /llvm-project/clang/test/Analysis/return-value-guaranteed.cpp (revision 97dd8e3c4f38ef345b01fbbf0a2052c7875ff7e0)
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