| // 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 |