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