|  | // RUN: %clang_analyze_cc1 \ | 
|  | // RUN:  -analyzer-checker=core,apiModeling.llvm.ReturnValue \ | 
|  | // RUN:  -analyzer-output=text -verify %s | 
|  |  | 
|  | struct Foo { int Field; }; | 
|  | bool problem(); | 
|  | void doSomething(); | 
|  |  | 
|  | // Test the normal case when the implementation of MCAsmParser::Error() (one of | 
|  | // the methods modeled by this checker) is opaque. | 
|  | namespace test_normal { | 
|  | struct MCAsmParser { | 
|  | static bool Error(); | 
|  | }; | 
|  |  | 
|  | bool parseFoo(Foo &F) { | 
|  | if (problem()) { | 
|  | // expected-note@-1 {{Assuming the condition is false}} | 
|  | // expected-note@-2 {{Taking false branch}} | 
|  | return MCAsmParser::Error(); | 
|  | } | 
|  |  | 
|  | F.Field = 0; | 
|  | // expected-note@-1 {{The value 0 is assigned to 'F.Field'}} | 
|  | return false; | 
|  | } | 
|  |  | 
|  | bool parseFile() { | 
|  | Foo F; | 
|  | if (parseFoo(F)) { | 
|  | // expected-note@-1 {{Calling 'parseFoo'}} | 
|  | // expected-note@-2 {{Returning from 'parseFoo'}} | 
|  | // expected-note@-3 {{Taking false branch}} | 
|  | return true; | 
|  | } | 
|  |  | 
|  | // The following expression would produce the false positive report | 
|  | //    "The left operand of '==' is a garbage value" | 
|  | // without the modeling done by apiModeling.llvm.ReturnValue: | 
|  | if (F.Field == 0) { | 
|  | // expected-note@-1 {{Field 'Field' is equal to 0}} | 
|  | // expected-note@-2 {{Taking true branch}} | 
|  | doSomething(); | 
|  | } | 
|  |  | 
|  | // Trigger a zero division to get path notes: | 
|  | (void)(1 / F.Field); | 
|  | // expected-warning@-1 {{Division by zero}} | 
|  | // expected-note@-2 {{Division by zero}} | 
|  | return false; | 
|  | } | 
|  | } // namespace test_normal | 
|  |  | 
|  |  | 
|  | // Sanity check for the highly unlikely case where the implementation of the | 
|  | // method breaks the convention. | 
|  | namespace test_break { | 
|  | struct MCAsmParser { | 
|  | static bool Error() { | 
|  | return false; | 
|  | } | 
|  | }; | 
|  |  | 
|  | bool parseFoo(Foo &F) { | 
|  | if (problem()) { | 
|  | // expected-note@-1 {{Assuming the condition is false}} | 
|  | // expected-note@-2 {{Taking false branch}} | 
|  | return !MCAsmParser::Error(); | 
|  | } | 
|  |  | 
|  | F.Field = 0; | 
|  | // expected-note@-1 {{The value 0 is assigned to 'F.Field'}} | 
|  | return MCAsmParser::Error(); | 
|  | // expected-note@-1 {{'MCAsmParser::Error' returned false, breaking the convention that it always returns true}} | 
|  | } | 
|  |  | 
|  | bool parseFile() { | 
|  | Foo F; | 
|  | if (parseFoo(F)) { | 
|  | // expected-note@-1 {{Calling 'parseFoo'}} | 
|  | // expected-note@-2 {{Returning from 'parseFoo'}} | 
|  | // expected-note@-3 {{Taking false branch}} | 
|  | return true; | 
|  | } | 
|  |  | 
|  | (void)(1 / F.Field); | 
|  | // expected-warning@-1 {{Division by zero}} | 
|  | // expected-note@-2 {{Division by zero}} | 
|  | return false; | 
|  | } | 
|  | } // namespace test_break |