21#include "llvm/ADT/DenseMap.h"
22#include "llvm/ADT/DenseSet.h"
23#include "llvm/ADT/MapVector.h"
24#include "llvm/ADT/STLExtras.h"
25#include "llvm/Support/ErrorHandling.h"
41 const llvm::DenseMap<const ValueDecl *, StorageLocation *> &DeclToLoc1,
42 const llvm::DenseMap<const ValueDecl *, StorageLocation *> &DeclToLoc2) {
43 for (
auto &Entry : DeclToLoc1) {
44 auto It = DeclToLoc2.find(Entry.first);
45 if (It != DeclToLoc2.end() && Entry.second != It->second)
53template <
typename K,
typename V>
55 const llvm::DenseMap<K, V> &Map2) {
56 llvm::DenseMap<K, V>
Result;
57 for (
auto &Entry : Map1) {
58 auto It = Map2.find(Entry.first);
59 if (It != Map2.end() && Entry.second == It->second)
60 Result.insert({Entry.first, Entry.second});
92 switch (Model.
compare(
Type, Val1, Env1, Val2, Env2)) {
100 llvm_unreachable(
"All cases covered in switch");
114 if (isa<BoolValue>(&Val1) && isa<BoolValue>(&Val2)) {
128 auto &Expr1 = cast<BoolValue>(Val1).formula();
129 auto &Expr2 = cast<BoolValue>(Val2).formula();
130 auto &A = MergedEnv.
arena();
134 A.makeEquals(MergedVal, Expr1)),
136 A.makeEquals(MergedVal, Expr2))));
137 return &A.makeBoolValue(MergedVal);
140 Value *MergedVal =
nullptr;
141 if (
auto *RecordVal1 = dyn_cast<RecordValue>(&Val1)) {
142 auto *RecordVal2 = cast<RecordValue>(&Val2);
144 if (&RecordVal1->getLoc() == &RecordVal2->getLoc())
162 if (Model.
merge(
Type, Val1, Env1, Val2, Env2, *MergedVal, MergedEnv))
174 if (isa<BoolValue>(&Prev)) {
175 assert(isa<BoolValue>(Current));
178 if (isa<TopBoolValue>(Prev))
186 if (
auto *W = Model.
widen(
Type, Prev, PrevEnv, Current, CurrentEnv))
194template <
typename Key>
196 const llvm::MapVector<Key, Value *> &Map2,
199 for (
auto &Entry : Map1) {
201 assert(K !=
nullptr);
203 Value *Val = Entry.second;
204 assert(Val !=
nullptr);
206 auto It = Map2.find(K);
207 if (It == Map2.end())
209 assert(It->second !=
nullptr);
222template <
typename Key>
223llvm::MapVector<Key, Value *>
225 const llvm::MapVector<Key, Value *> &Map2,
228 llvm::MapVector<Key, Value *> MergedMap;
229 for (
auto &Entry : Map1) {
231 assert(K !=
nullptr);
233 Value *Val = Entry.second;
234 assert(Val !=
nullptr);
236 auto It = Map2.find(K);
237 if (It == Map2.end())
239 assert(It->second !=
nullptr);
242 MergedMap.insert({K, Val});
247 K->getType(), *Val, Env1, *It->second, Env2, JoinedEnv, Model)) {
248 MergedMap.insert({K, MergedVal});
257template <
typename Key>
258llvm::MapVector<Key, Value *>
260 const llvm::MapVector<Key, Value *> &PrevMap,
263 llvm::MapVector<Key, Value *> WidenedMap;
264 for (
auto &Entry : CurMap) {
266 assert(K !=
nullptr);
268 Value *Val = Entry.second;
269 assert(Val !=
nullptr);
271 auto PrevIt = PrevMap.find(K);
272 if (PrevIt == PrevMap.end())
274 assert(PrevIt->second !=
nullptr);
277 WidenedMap.insert({K, Val});
282 PrevEnv, *Val, CurEnv, Model);
283 WidenedMap.insert({K, &WidenedVal});
284 if (&WidenedVal != PrevIt->second)
294 if (
auto *
V = dyn_cast<VarDecl>(&D))
295 if (
V->hasGlobalStorage())
301 if (
auto *FD = dyn_cast<FunctionDecl>(&D))
306 if (!
C.getMethodDecl())
308 auto *Body = dyn_cast_or_null<CompoundStmt>(
C.getMethodDecl()->getBody());
309 if (!Body || Body->size() != 1)
311 if (
auto *RS = dyn_cast<ReturnStmt>(*Body->body_begin()))
312 if (
auto *Return = RS->getRetValue())
313 return dyn_cast<MemberExpr>(Return->IgnoreParenImpCasts());
323 if (
const auto *Decomp = dyn_cast<DecompositionDecl>(&D))
324 for (
const auto *B : Decomp->bindings())
325 if (
auto *ME = dyn_cast_or_null<MemberExpr>(B->getBinding()))
327 if (
const auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl()))
338 for (
auto *Child : S.children())
339 if (Child !=
nullptr)
341 if (
const auto *DefaultInit = dyn_cast<CXXDefaultInitExpr>(&S))
344 if (
auto *DS = dyn_cast<DeclStmt>(&S)) {
345 if (DS->isSingleDecl())
348 for (
auto *D : DS->getDeclGroup())
350 }
else if (
auto *E = dyn_cast<DeclRefExpr>(&S)) {
353 }
else if (
const auto *
C = dyn_cast<CXXMemberCallExpr>(&S)) {
357 if (
const auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl()))
359 }
else if (
auto *E = dyn_cast<MemberExpr>(&S)) {
361 const ValueDecl *VD = E->getMemberDecl();
364 if (
const auto *FD = dyn_cast<FieldDecl>(VD))
366 }
else if (
auto *InitList = dyn_cast<InitListExpr>(&S)) {
367 if (
RecordDecl *RD = InitList->getType()->getAsRecordDecl())
375void Environment::initFieldsGlobalsAndFuncs(
const FunctionDecl *FuncDecl) {
376 assert(FuncDecl->
getBody() !=
nullptr);
384 if (
const auto *CtorDecl = dyn_cast<CXXConstructorDecl>(FuncDecl)) {
385 for (
const auto *Init : CtorDecl->inits()) {
386 if (Init->isMemberInitializer()) {
387 Fields.insert(Init->getMember());
388 }
else if (Init->isIndirectMemberInitializer()) {
389 for (
const auto *I : Init->getIndirectMember()->chain())
390 Fields.insert(cast<FieldDecl>(I));
392 const Expr *E = Init->getInit();
393 assert(E !=
nullptr);
397 for (
const FieldDecl *F : CtorDecl->getParent()->fields())
398 if (
const auto *I = F->getInClassInitializer())
405 DACtx->addModeledFields(Fields);
407 for (
const VarDecl *D : Vars) {
414 for (
const FunctionDecl *FD : Funcs) {
424 FlowConditionToken(DACtx.arena().makeFlowConditionToken()) {}
435 CallStack.push_back(&DeclCtx);
437 if (
const auto *FuncDecl = dyn_cast<FunctionDecl>(&DeclCtx)) {
438 assert(FuncDecl->
getBody() !=
nullptr);
440 initFieldsGlobalsAndFuncs(FuncDecl);
442 for (
const auto *ParamDecl : FuncDecl->
parameters()) {
443 assert(ParamDecl !=
nullptr);
448 if (
const auto *MethodDecl = dyn_cast<CXXMethodDecl>(&DeclCtx)) {
449 auto *
Parent = MethodDecl->getParent();
450 assert(
Parent !=
nullptr);
452 MethodDecl = dyn_cast<CXXMethodDecl>(
Parent->getDeclContext());
455 if (MethodDecl && !MethodDecl->isStatic()) {
456 QualType ThisPointeeType = MethodDecl->getThisObjectType();
458 &cast<RecordValue>(
createValue(ThisPointeeType))->getLoc();
465 return CallStack.size() <= MaxDepth && !llvm::is_contained(CallStack, Callee);
471 if (
const auto *MethodCall = dyn_cast<CXXMemberCallExpr>(Call)) {
472 if (
const Expr *Arg = MethodCall->getImplicitObjectArgument()) {
473 if (!isa<CXXThisExpr>(Arg))
481 Env.pushCallInternal(Call->getDirectCallee(),
490 Env.ThisPointeeLoc = &
Env.getResultObjectLocation(*Call);
492 Env.pushCallInternal(Call->getConstructor(),
498void Environment::pushCallInternal(
const FunctionDecl *FuncDecl,
506 CallStack.push_back(FuncDecl);
508 initFieldsGlobalsAndFuncs(FuncDecl);
514 for (
unsigned ArgIndex = 0; ArgIndex < Args.size(); ++ParamIt, ++ArgIndex) {
515 assert(ParamIt != FuncDecl->
param_end());
516 const VarDecl *Param = *ParamIt;
529 this->LocToVal = std::move(CalleeEnv.LocToVal);
530 this->FlowConditionToken = std::move(CalleeEnv.FlowConditionToken);
532 if (Call->isGLValue()) {
533 if (CalleeEnv.ReturnLoc !=
nullptr)
535 }
else if (!Call->getType()->isVoidType()) {
536 if (CalleeEnv.ReturnVal !=
nullptr)
537 setValue(*Call, *CalleeEnv.ReturnVal);
544 this->LocToVal = std::move(CalleeEnv.LocToVal);
545 this->FlowConditionToken = std::move(CalleeEnv.FlowConditionToken);
547 if (
Value *Val = CalleeEnv.
getValue(*CalleeEnv.ThisPointeeLoc)) {
554 assert(DACtx == Other.DACtx);
556 if (ReturnVal != Other.ReturnVal)
559 if (ReturnLoc != Other.ReturnLoc)
562 if (ThisPointeeLoc != Other.ThisPointeeLoc)
565 if (DeclToLoc != Other.DeclToLoc)
568 if (ExprToLoc != Other.ExprToLoc)
582 assert(DACtx == PrevEnv.DACtx);
583 assert(ReturnVal == PrevEnv.ReturnVal);
584 assert(ReturnLoc == PrevEnv.ReturnLoc);
585 assert(ThisPointeeLoc == PrevEnv.ThisPointeeLoc);
586 assert(CallStack == PrevEnv.CallStack);
596 assert(DeclToLoc.size() <= PrevEnv.DeclToLoc.size());
597 assert(ExprToVal.size() <= PrevEnv.ExprToVal.size());
598 assert(ExprToLoc.size() <= PrevEnv.ExprToLoc.size());
605 if (DeclToLoc.size() != PrevEnv.DeclToLoc.size() ||
606 ExprToLoc.size() != PrevEnv.ExprToLoc.size() ||
607 ExprToVal.size() != PrevEnv.ExprToVal.size() ||
608 LocToVal.size() != PrevEnv.LocToVal.size())
616 assert(EnvA.DACtx == EnvB.DACtx);
617 assert(EnvA.ThisPointeeLoc == EnvB.ThisPointeeLoc);
618 assert(EnvA.CallStack == EnvB.CallStack);
622 JoinedEnv.CallStack = EnvA.CallStack;
623 JoinedEnv.ThisPointeeLoc = EnvA.ThisPointeeLoc;
625 if (EnvA.ReturnVal ==
nullptr || EnvB.ReturnVal ==
nullptr) {
633 JoinedEnv.ReturnVal =
nullptr;
635 JoinedEnv.ReturnVal = EnvA.ReturnVal;
637 assert(!EnvA.CallStack.empty());
640 auto *Func = dyn_cast<FunctionDecl>(EnvA.CallStack.back());
641 assert(Func !=
nullptr);
642 if (
Value *MergedVal =
644 *EnvB.ReturnVal, EnvB, JoinedEnv, Model))
645 JoinedEnv.ReturnVal = MergedVal;
648 if (EnvA.ReturnLoc == EnvB.ReturnLoc)
649 JoinedEnv.ReturnLoc = EnvA.ReturnLoc;
651 JoinedEnv.ReturnLoc =
nullptr;
661 EnvA.FlowConditionToken, EnvB.FlowConditionToken);
664 EnvB, JoinedEnv, Model);
667 EnvB, JoinedEnv, Model);
691 assert(!DeclToLoc.contains(&D));
692 DeclToLoc[&D] = &Loc;
696 auto It = DeclToLoc.find(&D);
697 if (It == DeclToLoc.end())
706 assert(DeclToLoc.contains(&D));
716 setStorageLocationInternal(E, Loc);
723 return getStorageLocationInternal(E);
727 return ThisPointeeLoc;
735 if (
StorageLocation *ExistingLoc = getStorageLocationInternal(RecordPRValue))
736 return *cast<RecordStorageLocation>(ExistingLoc);
737 auto &Loc = cast<RecordStorageLocation>(
739 setStorageLocationInternal(RecordPRValue, Loc);
748 assert(!isa<RecordValue>(&Val) || &cast<RecordValue>(&Val)->getLoc() == &Loc);
750 LocToVal[&Loc] = &Val;
755 ExprToVal[&E] = &Val;
759 return LocToVal.lookup(&Loc);
772 return It == ExprToVal.end() ? nullptr : It->second;
776 if (It == ExprToLoc.end())
783 int CreatedValuesCount = 0;
787 llvm::errs() <<
"Attempting to initialize a huge value of type: " <<
Type
793void Environment::setStorageLocationInternal(
const Expr &E,
796 assert(!ExprToLoc.contains(&CanonE));
797 ExprToLoc[&CanonE] = &Loc;
800StorageLocation *Environment::getStorageLocationInternal(
const Expr &E)
const {
802 return It == ExprToLoc.end() ? nullptr : &*It->second;
805Value *Environment::createValueUnlessSelfReferential(
807 int &CreatedValuesCount) {
808 assert(!
Type.isNull());
809 assert(!
Type->isReferenceType());
816 if (
Type->isBooleanType()) {
817 CreatedValuesCount++;
821 if (
Type->isIntegerType()) {
825 CreatedValuesCount++;
829 if (
Type->isPointerType()) {
830 CreatedValuesCount++;
831 QualType PointeeType =
Type->getPointeeType();
832 StorageLocation &PointeeLoc =
833 createLocAndMaybeValue(PointeeType,
Visited, Depth, CreatedValuesCount);
838 if (
Type->isRecordType()) {
839 CreatedValuesCount++;
840 llvm::DenseMap<const ValueDecl *, StorageLocation *> FieldLocs;
842 assert(Field !=
nullptr);
844 QualType FieldType =
Field->getType();
847 {
Field, &createLocAndMaybeValue(FieldType,
Visited, Depth + 1,
848 CreatedValuesCount)});
851 RecordStorageLocation &Loc =
853 RecordValue &RecordVal = create<RecordValue>(Loc);
866Environment::createLocAndMaybeValue(QualType Ty,
868 int Depth,
int &CreatedValuesCount) {
869 if (!
Visited.insert(Ty.getCanonicalType()).second)
871 Value *Val = createValueUnlessSelfReferential(
872 Ty.getNonReferenceType(),
Visited, Depth, CreatedValuesCount);
873 Visited.erase(Ty.getCanonicalType());
875 Ty = Ty.getNonReferenceType();
880 if (Ty->isRecordType())
881 return cast<RecordValue>(Val)->getLoc();
888StorageLocation &Environment::createObjectInternal(
const VarDecl *D,
890 const Expr *InitExpr) {
891 if (Ty->isReferenceType()) {
904 return createObjectInternal(D, Ty.getNonReferenceType(),
nullptr);
907 Value *Val =
nullptr;
926 if (Ty->isRecordType())
927 return cast<RecordValue>(Val)->getLoc();
929 StorageLocation &Loc =
949 OS <<
"DeclToLoc:\n";
950 for (
auto [D, L] : DeclToLoc)
951 OS <<
" [" << D->getNameAsString() <<
", " << L <<
"]\n";
953 OS <<
"ExprToLoc:\n";
954 for (
auto [E, L] : ExprToLoc)
955 OS <<
" [" << E <<
", " << L <<
"]\n";
957 OS <<
"ExprToVal:\n";
958 for (
auto [E,
V] : ExprToVal)
959 OS <<
" [" << E <<
", " <<
V <<
": " << *
V <<
"]\n";
962 for (
auto [L,
V] : LocToVal) {
963 OS <<
" [" << L <<
", " <<
V <<
": " << *
V <<
"]\n";
966 OS <<
"FlowConditionToken:\n";
977 if (ImplicitObject ==
nullptr)
980 if (
auto *Val = cast_or_null<PointerValue>(
Env.
getValue(*ImplicitObject)))
981 return &cast<RecordStorageLocation>(Val->getPointeeLoc());
984 return cast_or_null<RecordStorageLocation>(
995 return &cast<RecordStorageLocation>(Val->getPointeeLoc());
1006 std::vector<FieldDecl *> Fields;
1008 RD->
fields(), std::back_inserter(Fields),
1009 [](
const FieldDecl *Field) { return !Field->isUnnamedBitfield(); });
1023 if (
auto *ExistingVal = cast_or_null<RecordValue>(
Env.
getValue(
Expr))) {
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
llvm::DenseSet< const void * > Visited
C Language Family Type Representation.
Represents a call to a C++ constructor.
Represents a call to a member function that may be written either with member call syntax (e....
Expr * getImplicitObjectArgument() const
Retrieve the implicit object argument for the member call.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Decl - This represents one declaration (or definition), e.g.
This represents one expression.
Represents a member of a struct/union/class.
Represents a function declaration or definition.
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
param_iterator param_end()
ArrayRef< ParmVarDecl * > parameters() const
param_iterator param_begin()
FunctionDecl * getDefinition()
Get the definition for this declaration.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
A (possibly-)qualified type.
Represents a struct/union/class.
field_range fields() const
Stmt - This represents one statement.
The base class of the type hierarchy.
bool isPointerType() const
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
bool isRecordType() const
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
const Formula & makeAtomRef(Atom A)
Returns a formula for the variable A.
std::enable_if_t< std::is_base_of< StorageLocation, T >::value, T & > create(Args &&...args)
Creates a T (some subclass of StorageLocation), forwarding args to the constructor,...
Owns objects that encompass the state of a program and stores context that is used during dataflow an...
StorageLocation & getStableStorageLocation(const VarDecl &D)
Returns a stable storage location for D.
Atom joinFlowConditions(Atom FirstToken, Atom SecondToken)
Creates a new flow condition that represents the disjunction of the flow conditions identified by Fir...
void addFlowConditionConstraint(Atom Token, const Formula &Constraint)
Adds Constraint to the flow condition identified by Token.
Atom forkFlowCondition(Atom Token)
Creates a new flow condition with the same constraints as the flow condition identified by Token and ...
PointerValue & getOrCreateNullPointerValue(QualType PointeeType)
Returns a pointer value that represents a null pointer.
bool flowConditionImplies(Atom Token, const Formula &)
Returns true if and only if the constraints of the flow condition identified by Token imply that Val ...
StorageLocation & createStorageLocation(QualType Type)
Returns a new storage location appropriate for Type.
FieldSet getModeledFields(QualType Type)
Returns the fields of Type, limited to the set of fields modeled by this context.
LLVM_DUMP_METHOD void dumpFlowCondition(Atom Token, llvm::raw_ostream &OS=llvm::dbgs())
Supplements Environment with non-standard comparison and join operations.
virtual ComparisonResult compare(QualType Type, const Value &Val1, const Environment &Env1, const Value &Val2, const Environment &Env2)
Returns: Same: Val1 is equivalent to Val2, according to the model.
virtual Value * widen(QualType Type, Value &Prev, const Environment &PrevEnv, Value &Current, Environment &CurrentEnv)
This function may widen the current value – replace it with an approximation that can reach a fixed p...
virtual bool merge(QualType Type, const Value &Val1, const Environment &Env1, const Value &Val2, const Environment &Env2, Value &MergedVal, Environment &MergedEnv)
Modifies MergedVal to approximate both Val1 and Val2.
Holds the state of the program (store and heap) at a given program point.
static Environment join(const Environment &EnvA, const Environment &EnvB, Environment::ValueModel &Model)
Joins two environments by taking the intersection of storage locations and values that are stored in ...
void addToFlowCondition(const Formula &)
Record a fact that must be true if this point in the program is reached.
PointerValue & getOrCreateNullPointerValue(QualType PointeeType)
Returns a pointer value that represents a null pointer.
LatticeJoinEffect widen(const Environment &PrevEnv, Environment::ValueModel &Model)
Widens the environment point-wise, using PrevEnv as needed to inform the approximation.
RecordStorageLocation * getThisPointeeStorageLocation() const
Returns the storage location assigned to the this pointee in the environment or null if the this poin...
Environment pushCall(const CallExpr *Call) const
Creates and returns an environment to use for an inline analysis of the callee.
StorageLocation * getStorageLocation(const ValueDecl &D) const
Returns the storage location assigned to D in the environment, or null if D isn't assigned a storage ...
LLVM_DUMP_METHOD void dump() const
BoolValue & makeTopBoolValue() const
Returns a unique instance of boolean Top.
StorageLocation & createStorageLocation(QualType Type)
Creates a storage location appropriate for Type.
Environment fork() const
Returns a new environment that is a copy of this one.
void popCall(const CallExpr *Call, const Environment &CalleeEnv)
Moves gathered information back into this from a CalleeEnv created via pushCall.
Environment(DataflowAnalysisContext &DACtx)
Creates an environment that uses DACtx to store objects that encompass the state of a program.
bool equivalentTo(const Environment &Other, Environment::ValueModel &Model) const
Returns true if and only if the environment is equivalent to Other, i.e the two environments:
BoolValue & makeAtomicBoolValue() const
Returns an atomic boolean value.
Value * getValue(const StorageLocation &Loc) const
Returns the value assigned to Loc in the environment or null if Loc isn't assigned a value in the env...
bool canDescend(unsigned MaxDepth, const DeclContext *Callee) const
Returns whether this Environment can be extended to analyze the given Callee (i.e.
StorageLocation & createObject(QualType Ty, const Expr *InitExpr=nullptr)
Creates an object (i.e.
RecordStorageLocation & getResultObjectLocation(const Expr &RecordPRValue)
Returns the location of the result object for a record-type prvalue.
void setStorageLocation(const ValueDecl &D, StorageLocation &Loc)
Assigns Loc as the storage location of D in the environment.
void removeDecl(const ValueDecl &D)
Removes the location assigned to D in the environment.
Value * createValue(QualType Type)
Creates a value appropriate for Type, if Type is supported, otherwise returns null.
void setValue(const StorageLocation &Loc, Value &Val)
Assigns Val as the value of Loc in the environment.
Atom getFlowConditionToken() const
Returns a boolean variable that identifies the flow condition (FC).
bool flowConditionImplies(const Formula &) const
Returns true if the formula is always true when this point is reached.
std::enable_if_t< std::is_base_of< Value, T >::value, T & > create(Args &&...args)
Creates a T (some subclass of Value), forwarding args to the constructor, and returns a reference to ...
Models a symbolic pointer. Specifically, any value of type T*.
A storage location for a record (struct, class, or union).
Models a value of struct or class type.
Base class for elements of the local variable store and of the heap.
Base class for all values computed by abstract interpretation.
llvm::MapVector< Key, Value * > joinKeyToValueMap(const llvm::MapVector< Key, Value * > &Map1, const llvm::MapVector< Key, Value * > &Map2, const Environment &Env1, const Environment &Env2, Environment &JoinedEnv, Environment::ValueModel &Model)
static Value & widenDistinctValues(QualType Type, Value &Prev, const Environment &PrevEnv, Value &Current, Environment &CurrentEnv, Environment::ValueModel &Model)
llvm::DenseMap< K, V > intersectDenseMaps(const llvm::DenseMap< K, V > &Map1, const llvm::DenseMap< K, V > &Map2)
Returns a map consisting of key-value entries that are present in both maps.
bool declToLocConsistent(const llvm::DenseMap< const ValueDecl *, StorageLocation * > &DeclToLoc1, const llvm::DenseMap< const ValueDecl *, StorageLocation * > &DeclToLoc2)
Returns whether all declarations that DeclToLoc1 and DeclToLoc2 have in common map to the same storag...
static void getFieldsGlobalsAndFuncs(const Decl &D, FieldSet &Fields, llvm::DenseSet< const VarDecl * > &Vars, llvm::DenseSet< const FunctionDecl * > &Funcs)
bool compareKeyToValueMaps(const llvm::MapVector< Key, Value * > &Map1, const llvm::MapVector< Key, Value * > &Map2, const Environment &Env1, const Environment &Env2, Environment::ValueModel &Model)
static bool equateUnknownValues(Value::Kind K)
bool areEquivalentValues(const Value &Val1, const Value &Val2)
An equivalence relation for values.
static constexpr int MaxCompositeValueDepth
LatticeJoinEffect
Effect indicating whether a lattice join operation resulted in a new value.
static Value * mergeDistinctValues(QualType Type, Value &Val1, const Environment &Env1, Value &Val2, const Environment &Env2, Environment &MergedEnv, Environment::ValueModel &Model)
Attempts to merge distinct values Val1 and Val2 in Env1 and Env2, respectively, of the same type Type...
llvm::SmallSetVector< const FieldDecl *, 4 > FieldSet
A set of FieldDecl *.
static constexpr int MaxCompositeValueSize
static void insertIfFunction(const Decl &D, llvm::DenseSet< const FunctionDecl * > &Funcs)
static MemberExpr * getMemberForAccessor(const CXXMemberCallExpr &C)
llvm::MapVector< Key, Value * > widenKeyToValueMap(const llvm::MapVector< Key, Value * > &CurMap, const llvm::MapVector< Key, Value * > &PrevMap, Environment &CurEnv, const Environment &PrevEnv, Environment::ValueModel &Model, LatticeJoinEffect &Effect)
RecordStorageLocation * getImplicitObjectLocation(const CXXMemberCallExpr &MCE, const Environment &Env)
Returns the storage location for the implicit object of a CXXMemberCallExpr, or null if none is defin...
const Expr & ignoreCFGOmittedNodes(const Expr &E)
Skip past nodes that the CFG does not emit.
std::vector< FieldDecl * > getFieldsForInitListExpr(const RecordDecl *RD)
Returns the fields of RD that are initialized by an InitListExpr, in the order in which they appear i...
static bool compareDistinctValues(QualType Type, Value &Val1, const Environment &Env1, Value &Val2, const Environment &Env2, Environment::ValueModel &Model)
RecordStorageLocation * getBaseObjectLocation(const MemberExpr &ME, const Environment &Env)
Returns the storage location for the base object of a MemberExpr, or null if none is defined in the e...
static void insertIfGlobal(const Decl &D, llvm::DenseSet< const VarDecl * > &Vars)
Initializes a global storage value.
RecordValue & refreshRecordValue(RecordStorageLocation &Loc, Environment &Env)
Associates a new RecordValue with Loc and returns the new value.
@ C
Languages that the frontend can parse and compile.
@ Result
The result type of a method or function.