1//===-- GtestModelHelpers.cpp -----------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines helpers for handling gtest constructs in dataflow models.
10//
11//===----------------------------------------------------------------------===//
12
13#include "GtestModelHelpers.h"
14#include "clang/ASTMatchers/ASTMatchers.h"
15#include "clang/Analysis/FlowSensitive/StorageLocation.h"
16#include "llvm/ADT/STLFunctionalExtras.h"
17
18using namespace clang::dataflow::gtest;
19using namespace clang::dataflow;
20using namespace clang;
21
22void clang::dataflow::gtest::transferAssertionResultExpectationOperatorBoolCall(
23 const CXXMemberCallExpr *Expr, Environment &Env,
24 llvm::function_ref<StorageLocation &(RecordStorageLocation &)> GetOk) {
25 auto *RecordLoc = getImplicitObjectLocation(MCE: *Expr, Env);
26 if (RecordLoc == nullptr)
27 return;
28 RecordStorageLocation *AssertionResultLoc = nullptr;
29 StorageLocation *ExpectedResultLoc = nullptr;
30 for (auto [Field, ChildLoc] : RecordLoc->children()) {
31 if (Field->getName() == "assertion_result")
32 AssertionResultLoc = dyn_cast_or_null<RecordStorageLocation>(Val: ChildLoc);
33 else if (Field->getName() == "expected_result")
34 ExpectedResultLoc = ChildLoc;
35 }
36 if (AssertionResultLoc == nullptr || ExpectedResultLoc == nullptr)
37 return;
38 BoolValue *SuccessVal = Env.get<BoolValue>(Loc: GetOk(*AssertionResultLoc));
39 BoolValue *ExpectedVal = Env.get<BoolValue>(Loc: *ExpectedResultLoc);
40 if (SuccessVal == nullptr || ExpectedVal == nullptr)
41 return;
42 auto &A = Env.arena();
43 auto &Res = Env.makeAtomicBoolValue();
44 Env.assume(A.makeEquals(LHS: Res.formula(), RHS: A.makeEquals(LHS: SuccessVal->formula(),
45 RHS: ExpectedVal->formula())));
46 Env.setValue(E: *Expr, Val&: Res);
47}
48
49clang::ast_matchers::StatementMatcher
50clang::dataflow::gtest::isAssertionResultExpectationOperatorBoolCall() {
51 using namespace clang::ast_matchers;
52 return cxxMemberCallExpr(
53 on(InnerMatcher: expr(unless(cxxThisExpr()))),
54 callee(InnerMatcher: cxxMethodDecl(
55 hasName(Name: "operator bool"),
56 ofClass(InnerMatcher: hasName(Name: "testing::internal::AssertionResultExpectation")))));
57}
58