llvm/clang/test/Analysis/return-value-guaranteed.cpp

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