//==- GTestChecker.cpp - Model gtest API --*- C++ -*-==//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This checker models the behavior of un-inlined APIs from the gtest
// unit-testing library to avoid false positives when using assertions from
// that library.
//
//===----------------------------------------------------------------------===//

#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/LangOptions.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "llvm/Support/raw_ostream.h"

using namespace clang;
using namespace ento;

// Modeling of un-inlined AssertionResult constructors
//
// The gtest unit testing API provides macros for assertions that expand
// into an if statement that calls a series of constructors and returns
// when the "assertion" is false.
//
// For example,
//
//   ASSERT_TRUE(a == b)
//
// expands into:
//
//   switch (0)
//   case 0:
//   default:
//     if (const ::testing::AssertionResult gtest_ar_ =
//             ::testing::AssertionResult((a == b)))
//       ;
//     else
//       return ::testing::internal::AssertHelper(
//                  ::testing::TestPartResult::kFatalFailure,
//                  "<path to project>",
//                  <line number>,
//                  ::testing::internal::GetBoolAssertionFailureMessage(
//                      gtest_ar_, "a == b", "false", "true")
//                      .c_str()) = ::testing::Message();
//
// where AssertionResult is defined similarly to
//
//   class AssertionResult {
//   public:
//     AssertionResult(const AssertionResult& other);
//     explicit AssertionResult(bool success) : success_(success) {}
//     operator bool() const { return success_; }
//     ...
//     private:
//     bool success_;
//   };
//
// In order for the analyzer to correctly handle this assertion, it needs to
// know that the boolean value of the expression "a == b" is stored the
// 'success_' field of the original AssertionResult temporary and propagated
// (via the copy constructor) into the 'success_' field of the object stored
// in 'gtest_ar_'.  That boolean value will then be returned from the bool
// conversion method in the if statement. This guarantees that the assertion
// holds when the return path is not taken.
//
// If the success value is not properly propagated, then the eager case split
// on evaluating the expression can cause pernicious false positives
// on the non-return path:
//
//   ASSERT(ptr != NULL)
//   *ptr = 7; // False positive null pointer dereference here
//
// Unfortunately, the bool constructor cannot be inlined (because its
// implementation is not present in the headers) and the copy constructor is
// not inlined (because it is constructed into a temporary and the analyzer
// does not inline these since it does not yet reliably call temporary
// destructors).
//
// This checker compensates for the missing inlining by propagating the
// _success value across the bool and copy constructors so the assertion behaves
// as expected.

namespace {
class GTestChecker : public Checker<check::PostCall> {

  mutable IdentifierInfo *AssertionResultII;
  mutable IdentifierInfo *SuccessII;

public:
  GTestChecker();

  void checkPostCall(const CallEvent &Call, CheckerContext &C) const;

private:
  void modelAssertionResultBoolConstructor(const CXXConstructorCall *Call,
                                           bool IsRef, CheckerContext &C) const;

  void modelAssertionResultCopyConstructor(const CXXConstructorCall *Call,
                                           CheckerContext &C) const;

  void initIdentifierInfo(ASTContext &Ctx) const;

  SVal
  getAssertionResultSuccessFieldValue(const CXXRecordDecl *AssertionResultDecl,
                                      SVal Instance,
                                      ProgramStateRef State) const;

  static ProgramStateRef assumeValuesEqual(SVal Val1, SVal Val2,
                                           ProgramStateRef State,
                                           CheckerContext &C);
};
} // End anonymous namespace.

GTestChecker::GTestChecker() : AssertionResultII(nullptr), SuccessII(nullptr) {}

/// Model a call to an un-inlined AssertionResult(bool) or
/// AssertionResult(bool &, ...).
/// To do so, constrain the value of the newly-constructed instance's 'success_'
/// field to be equal to the passed-in boolean value.
///
/// \param IsRef Whether the boolean parameter is a reference or not.
void GTestChecker::modelAssertionResultBoolConstructor(
    const CXXConstructorCall *Call, bool IsRef, CheckerContext &C) const {
  assert(Call->getNumArgs() >= 1 && Call->getNumArgs() <= 2);

  ProgramStateRef State = C.getState();
  SVal BooleanArgVal = Call->getArgSVal(0);
  if (IsRef) {
    // The argument is a reference, so load from it to get the boolean value.
    if (!BooleanArgVal.getAs<Loc>())
      return;
    BooleanArgVal = C.getState()->getSVal(BooleanArgVal.castAs<Loc>());
  }

  SVal ThisVal = Call->getCXXThisVal();

  SVal ThisSuccess = getAssertionResultSuccessFieldValue(
      Call->getDecl()->getParent(), ThisVal, State);

  State = assumeValuesEqual(ThisSuccess, BooleanArgVal, State, C);
  C.addTransition(State);
}

/// Model a call to an un-inlined AssertionResult copy constructor:
///
///   AssertionResult(const &AssertionResult other)
///
/// To do so, constrain the value of the newly-constructed instance's
/// 'success_' field to be equal to the value of the pass-in instance's
/// 'success_' field.
void GTestChecker::modelAssertionResultCopyConstructor(
    const CXXConstructorCall *Call, CheckerContext &C) const {
  assert(Call->getNumArgs() == 1);

  // The first parameter of the copy constructor must be the other
  // instance to initialize this instances fields from.
  SVal OtherVal = Call->getArgSVal(0);
  SVal ThisVal = Call->getCXXThisVal();

  const CXXRecordDecl *AssertResultClassDecl = Call->getDecl()->getParent();
  ProgramStateRef State = C.getState();

  SVal ThisSuccess = getAssertionResultSuccessFieldValue(AssertResultClassDecl,
                                                         ThisVal, State);
  SVal OtherSuccess = getAssertionResultSuccessFieldValue(AssertResultClassDecl,
                                                          OtherVal, State);

  State = assumeValuesEqual(ThisSuccess, OtherSuccess, State, C);
  C.addTransition(State);
}

/// Model calls to AssertionResult constructors that are not inlined.
void GTestChecker::checkPostCall(const CallEvent &Call,
                                 CheckerContext &C) const {
  /// If the constructor was inlined, there is no need model it.
  if (C.wasInlined)
    return;

  initIdentifierInfo(C.getASTContext());

  auto *CtorCall = dyn_cast<CXXConstructorCall>(&Call);
  if (!CtorCall)
    return;

  const CXXConstructorDecl *CtorDecl = CtorCall->getDecl();
  const CXXRecordDecl *CtorParent = CtorDecl->getParent();
  if (CtorParent->getIdentifier() != AssertionResultII)
    return;

  unsigned ParamCount = CtorDecl->getNumParams();

  // Call the appropriate modeling method based the parameters and their
  // types.

  // We have AssertionResult(const &AssertionResult)
  if (CtorDecl->isCopyConstructor() && ParamCount == 1) {
    modelAssertionResultCopyConstructor(CtorCall, C);
    return;
  }

  // There are two possible boolean constructors, depending on which
  // version of gtest is being used:
  //
  // v1.7 and earlier:
  //      AssertionResult(bool success)
  //
  // v1.8 and greater:
  //      template <typename T>
  //      AssertionResult(const T& success,
  //                      typename internal::EnableIf<
  //                          !internal::ImplicitlyConvertible<T,
  //                              AssertionResult>::value>::type*)
  //
  CanQualType BoolTy = C.getASTContext().BoolTy;
  if (ParamCount == 1 && CtorDecl->getParamDecl(0)->getType() == BoolTy) {
    // We have AssertionResult(bool)
    modelAssertionResultBoolConstructor(CtorCall, /*IsRef=*/false, C);
    return;
  }
  if (ParamCount == 2){
    auto *RefTy = CtorDecl->getParamDecl(0)->getType()->getAs<ReferenceType>();
    if (RefTy &&
        RefTy->getPointeeType()->getCanonicalTypeUnqualified() == BoolTy) {
      // We have AssertionResult(bool &, ...)
      modelAssertionResultBoolConstructor(CtorCall, /*IsRef=*/true, C);
      return;
    }
  }
}

void GTestChecker::initIdentifierInfo(ASTContext &Ctx) const {
  if (AssertionResultII)
    return;

  AssertionResultII = &Ctx.Idents.get("AssertionResult");
  SuccessII = &Ctx.Idents.get("success_");
}

/// Returns the value stored in the 'success_' field of the passed-in
/// AssertionResult instance.
SVal GTestChecker::getAssertionResultSuccessFieldValue(
    const CXXRecordDecl *AssertionResultDecl, SVal Instance,
    ProgramStateRef State) const {

  DeclContext::lookup_result Result = AssertionResultDecl->lookup(SuccessII);
  if (Result.empty())
    return UnknownVal();

  auto *SuccessField = dyn_cast<FieldDecl>(Result.front());
  if (!SuccessField)
    return UnknownVal();

  Optional<Loc> FieldLoc =
      State->getLValue(SuccessField, Instance).getAs<Loc>();
  if (!FieldLoc.hasValue())
    return UnknownVal();

  return State->getSVal(*FieldLoc);
}

/// Constrain the passed-in state to assume two values are equal.
ProgramStateRef GTestChecker::assumeValuesEqual(SVal Val1, SVal Val2,
                                                ProgramStateRef State,
                                                CheckerContext &C) {
  if (!Val1.getAs<DefinedOrUnknownSVal>() ||
      !Val2.getAs<DefinedOrUnknownSVal>())
    return State;

  auto ValuesEqual =
      C.getSValBuilder().evalEQ(State, Val1.castAs<DefinedOrUnknownSVal>(),
                                Val2.castAs<DefinedOrUnknownSVal>());

  if (!ValuesEqual.getAs<DefinedSVal>())
    return State;

  State = C.getConstraintManager().assume(
      State, ValuesEqual.castAs<DefinedSVal>(), true);

  return State;
}

void ento::registerGTestChecker(CheckerManager &Mgr) {
  Mgr.registerChecker<GTestChecker>();
}

bool ento::shouldRegisterGTestChecker(const LangOptions &LO) {
  // gtest is a C++ API so there is no sense running the checker
  // if not compiling for C++.
  return LO.CPlusPlus;
}
