llvm/clang/unittests/Analysis/FlowSensitive/SignAnalysisTest.cpp

//===- unittests/Analysis/FlowSensitive/SignAnalysisTest.cpp --===//
//
// 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 file defines a simplistic version of Sign Analysis as a demo of a
//  forward, monotonic dataflow analysis. The implementation uses 3 boolean
//  values to represent the sign lattice (negative, zero, positive). In
//  practice, 2 booleans would be enough, however, this approach has the
//  advantage of clarity over the optimized solution.
//
//===----------------------------------------------------------------------===//

#include "TestingSupport.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Analysis/FlowSensitive/CFGMatchSwitch.h"
#include "clang/Analysis/FlowSensitive/DataflowAnalysis.h"
#include "clang/Analysis/FlowSensitive/NoopLattice.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Testing/Annotations/Annotations.h"
#include "llvm/Testing/Support/Error.h"
#include "gtest/gtest.h"
#include <memory>

namespace {

usingnamespaceclang;
usingnamespacedataflow;
usingnamespaceast_matchers;
usingnamespacetest;
UnorderedElementsAre;

enum class Sign : int {};

Sign getSign(int64_t V) {}

LatticeTransferState;

constexpr char kVar[] =;

void initNegative(Value &Val, Environment &Env) {}
void initPositive(Value &Val, Environment &Env) {}
void initZero(Value &Val, Environment &Env) {}

// The boolean properties that are associated to a Value. If a property is not
// set then these are null pointers, otherwise, the pointed BoolValues are
// owned by the Environment.
struct SignProperties {};
void setSignProperties(Value &Val, const SignProperties &Ps) {}
SignProperties initUnknown(Value &Val, Environment &Env) {}
SignProperties getSignProperties(const Value &Val, const Environment &Env) {}

void transferUninitializedInt(const DeclStmt *D,
                              const MatchFinder::MatchResult &M,
                              LatticeTransferState &State) {}

// Get the Value (1), the properties for the operand (2), and the properties
// for the unary operator (3). The return value is a tuple of (1,2,3).
//
// The returned Value (1) is a nullptr, if there is no Value associated to the
// operand of the unary operator, or if the properties are not set for that
// operand.
// Other than that, new sign properties are created for the Value of the
// unary operator and a new Value is created for the unary operator itself if
// it hadn't have any previously.
std::tuple<Value *, SignProperties, SignProperties>
getValueAndSignProperties(const UnaryOperator *UO,
                          const MatchFinder::MatchResult &M,
                          LatticeTransferState &State) {}

void transferBinary(const BinaryOperator *BO, const MatchFinder::MatchResult &M,
                    LatticeTransferState &State) {}

void transferUnaryMinus(const UnaryOperator *UO,
                        const MatchFinder::MatchResult &M,
                        LatticeTransferState &State) {}

void transferUnaryNot(const UnaryOperator *UO,
                      const MatchFinder::MatchResult &M,
                      LatticeTransferState &State) {}

// Returns the `Value` associated with `E` (which may be either a prvalue or
// glvalue). Creates a `Value` or `StorageLocation` as needed if `E` does not
// have either of these associated with it yet.
//
// If this functionality turns out to be needed in more cases, this function
// should be moved to a more central location.
Value *getOrCreateValue(const Expr *E, Environment &Env) {}

void transferExpr(const Expr *E, const MatchFinder::MatchResult &M,
                  LatticeTransferState &State) {}

auto refToVar() {}

auto buildTransferMatchSwitch() {}

class SignPropagationAnalysis
    : public DataflowAnalysis<SignPropagationAnalysis, NoopLattice> {};

BoolValue &joinBoolValues(BoolValue &Bool1, const Environment &Env1,
                          BoolValue &Bool2, const Environment &Env2,
                          Environment &JoinedEnv) {}

void SignPropagationAnalysis::join(QualType Type, const Value &Val1,
                                   const Environment &Env1, const Value &Val2,
                                   const Environment &Env2, Value &JoinedVal,
                                   Environment &JoinedEnv) {}

template <typename Matcher>
void runDataflow(llvm::StringRef Code, Matcher Match,
                 LangStandard::Kind Std = LangStandard::lang_cxx17,
                 llvm::StringRef TargetFun = "fun") {}

// FIXME add this to testing support.
template <typename NodeType, typename MatcherType>
const NodeType *findFirst(ASTContext &ASTCtx, const MatcherType &M) {}

template <typename Node>
std::pair<testing::AssertionResult, Value *>
getProperty(const Environment &Env, ASTContext &ASTCtx, const Node *N,
            StringRef Property) {}

// Test if the given property of the given node is implied by the flow
// condition. If 'Implies' is false then check if it is not implied.
template <typename Node>
testing::AssertionResult isPropertyImplied(const Environment &Env,
                                           ASTContext &ASTCtx, const Node *N,
                                           StringRef Property, bool Implies) {}

template <typename Node>
testing::AssertionResult isNegative(const Node *N, ASTContext &ASTCtx,
                                    const Environment &Env) {}
template <typename Node>
testing::AssertionResult isPositive(const Node *N, ASTContext &ASTCtx,
                                    const Environment &Env) {}
template <typename Node>
testing::AssertionResult isZero(const Node *N, ASTContext &ASTCtx,
                                const Environment &Env) {}
template <typename Node>
testing::AssertionResult isTop(const Node *N, ASTContext &ASTCtx,
                               const Environment &Env) {}

TEST(SignAnalysisTest, Init) {}

TEST(SignAnalysisTest, UnaryMinus) {}

TEST(SignAnalysisTest, UnaryNot) {}

TEST(SignAnalysisTest, UnaryNotInIf) {}

TEST(SignAnalysisTest, BinaryGT) {}

TEST(SignAnalysisTest, BinaryLT) {}

TEST(SignAnalysisTest, BinaryGE) {}

TEST(SignAnalysisTest, BinaryLE) {}

TEST(SignAnalysisTest, BinaryEQ) {}

TEST(SignAnalysisTest, ComplexLoopCondition) {}

TEST(SignAnalysisTest, JoinToTop) {}

TEST(SignAnalysisTest, JoinToNeg) {}

TEST(SignAnalysisTest, NestedIfs) {}

} // namespace