#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_VALUE_H
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_VALUE_H
#include "clang/AST/Decl.h"
#include "clang/Analysis/FlowSensitive/StorageLocation.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include <cassert>
#include <utility>
namespace clang {
namespace dataflow {
class Value {
public:
enum class Kind {
Integer,
Reference,
Pointer,
Struct,
AtomicBool,
Conjunction,
Disjunction,
Negation,
Implication,
Biconditional,
};
explicit Value(Kind ValKind) : ValKind(ValKind) {}
Value(const Value &) = delete;
Value &operator=(const Value &) = delete;
virtual ~Value() = default;
Kind getKind() const { return ValKind; }
Value *getProperty(llvm::StringRef Name) const {
auto It = Properties.find(Name);
return It == Properties.end() ? nullptr : It->second;
}
void setProperty(llvm::StringRef Name, Value &Val) {
Properties.insert_or_assign(Name, &Val);
}
private:
Kind ValKind;
llvm::StringMap<Value *> Properties;
};
class BoolValue : public Value {
public:
explicit BoolValue(Kind ValueKind) : Value(ValueKind) {}
static bool classof(const Value *Val) {
return Val->getKind() == Kind::AtomicBool ||
Val->getKind() == Kind::Conjunction ||
Val->getKind() == Kind::Disjunction ||
Val->getKind() == Kind::Negation ||
Val->getKind() == Kind::Implication ||
Val->getKind() == Kind::Biconditional;
}
};
class AtomicBoolValue : public BoolValue {
public:
explicit AtomicBoolValue() : BoolValue(Kind::AtomicBool) {}
static bool classof(const Value *Val) {
return Val->getKind() == Kind::AtomicBool;
}
};
class ConjunctionValue : public BoolValue {
public:
explicit ConjunctionValue(BoolValue &LeftSubVal, BoolValue &RightSubVal)
: BoolValue(Kind::Conjunction), LeftSubVal(LeftSubVal),
RightSubVal(RightSubVal) {}
static bool classof(const Value *Val) {
return Val->getKind() == Kind::Conjunction;
}
BoolValue &getLeftSubValue() const { return LeftSubVal; }
BoolValue &getRightSubValue() const { return RightSubVal; }
private:
BoolValue &LeftSubVal;
BoolValue &RightSubVal;
};
class DisjunctionValue : public BoolValue {
public:
explicit DisjunctionValue(BoolValue &LeftSubVal, BoolValue &RightSubVal)
: BoolValue(Kind::Disjunction), LeftSubVal(LeftSubVal),
RightSubVal(RightSubVal) {}
static bool classof(const Value *Val) {
return Val->getKind() == Kind::Disjunction;
}
BoolValue &getLeftSubValue() const { return LeftSubVal; }
BoolValue &getRightSubValue() const { return RightSubVal; }
private:
BoolValue &LeftSubVal;
BoolValue &RightSubVal;
};
class NegationValue : public BoolValue {
public:
explicit NegationValue(BoolValue &SubVal)
: BoolValue(Kind::Negation), SubVal(SubVal) {}
static bool classof(const Value *Val) {
return Val->getKind() == Kind::Negation;
}
BoolValue &getSubVal() const { return SubVal; }
private:
BoolValue &SubVal;
};
class ImplicationValue : public BoolValue {
public:
explicit ImplicationValue(BoolValue &LeftSubVal, BoolValue &RightSubVal)
: BoolValue(Kind::Implication), LeftSubVal(LeftSubVal),
RightSubVal(RightSubVal) {}
static bool classof(const Value *Val) {
return Val->getKind() == Kind::Implication;
}
BoolValue &getLeftSubValue() const { return LeftSubVal; }
BoolValue &getRightSubValue() const { return RightSubVal; }
private:
BoolValue &LeftSubVal;
BoolValue &RightSubVal;
};
class BiconditionalValue : public BoolValue {
public:
explicit BiconditionalValue(BoolValue &LeftSubVal, BoolValue &RightSubVal)
: BoolValue(Kind::Biconditional), LeftSubVal(LeftSubVal),
RightSubVal(RightSubVal) {}
static bool classof(const Value *Val) {
return Val->getKind() == Kind::Biconditional;
}
BoolValue &getLeftSubValue() const { return LeftSubVal; }
BoolValue &getRightSubValue() const { return RightSubVal; }
private:
BoolValue &LeftSubVal;
BoolValue &RightSubVal;
};
class IntegerValue : public Value {
public:
explicit IntegerValue() : Value(Kind::Integer) {}
static bool classof(const Value *Val) {
return Val->getKind() == Kind::Integer;
}
};
class ReferenceValue final : public Value {
public:
explicit ReferenceValue(StorageLocation &ReferentLoc)
: Value(Kind::Reference), ReferentLoc(ReferentLoc) {}
static bool classof(const Value *Val) {
return Val->getKind() == Kind::Reference;
}
StorageLocation &getReferentLoc() const { return ReferentLoc; }
private:
StorageLocation &ReferentLoc;
};
class PointerValue final : public Value {
public:
explicit PointerValue(StorageLocation &PointeeLoc)
: Value(Kind::Pointer), PointeeLoc(PointeeLoc) {}
static bool classof(const Value *Val) {
return Val->getKind() == Kind::Pointer;
}
StorageLocation &getPointeeLoc() const { return PointeeLoc; }
private:
StorageLocation &PointeeLoc;
};
class StructValue final : public Value {
public:
StructValue() : StructValue(llvm::DenseMap<const ValueDecl *, Value *>()) {}
explicit StructValue(llvm::DenseMap<const ValueDecl *, Value *> Children)
: Value(Kind::Struct), Children(std::move(Children)) {}
static bool classof(const Value *Val) {
return Val->getKind() == Kind::Struct;
}
Value *getChild(const ValueDecl &D) const {
auto It = Children.find(&D);
if (It == Children.end())
return nullptr;
return It->second;
}
void setChild(const ValueDecl &D, Value &Val) { Children[&D] = &Val; }
private:
llvm::DenseMap<const ValueDecl *, Value *> Children;
};
} }
#endif