xref: /freebsd-src/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
104eeddc0SDimitry Andric //===-- DataflowEnvironment.cpp ---------------------------------*- C++ -*-===//
204eeddc0SDimitry Andric //
304eeddc0SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
404eeddc0SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
504eeddc0SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
604eeddc0SDimitry Andric //
704eeddc0SDimitry Andric //===----------------------------------------------------------------------===//
804eeddc0SDimitry Andric //
904eeddc0SDimitry Andric //  This file defines an Environment class that is used by dataflow analyses
1004eeddc0SDimitry Andric //  that run over Control-Flow Graphs (CFGs) to keep track of the state of the
1104eeddc0SDimitry Andric //  program at given program points.
1204eeddc0SDimitry Andric //
1304eeddc0SDimitry Andric //===----------------------------------------------------------------------===//
1404eeddc0SDimitry Andric 
1504eeddc0SDimitry Andric #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
1604eeddc0SDimitry Andric #include "clang/AST/Decl.h"
1704eeddc0SDimitry Andric #include "clang/AST/DeclCXX.h"
18*81ad6265SDimitry Andric #include "clang/AST/ExprCXX.h"
1904eeddc0SDimitry Andric #include "clang/AST/Type.h"
2004eeddc0SDimitry Andric #include "clang/Analysis/FlowSensitive/DataflowLattice.h"
2104eeddc0SDimitry Andric #include "clang/Analysis/FlowSensitive/StorageLocation.h"
2204eeddc0SDimitry Andric #include "clang/Analysis/FlowSensitive/Value.h"
2304eeddc0SDimitry Andric #include "llvm/ADT/DenseMap.h"
2404eeddc0SDimitry Andric #include "llvm/ADT/DenseSet.h"
25*81ad6265SDimitry Andric #include "llvm/Support/Casting.h"
2604eeddc0SDimitry Andric #include "llvm/Support/ErrorHandling.h"
27*81ad6265SDimitry Andric #include <cassert>
2804eeddc0SDimitry Andric #include <memory>
2904eeddc0SDimitry Andric #include <utility>
3004eeddc0SDimitry Andric 
3104eeddc0SDimitry Andric namespace clang {
3204eeddc0SDimitry Andric namespace dataflow {
3304eeddc0SDimitry Andric 
34*81ad6265SDimitry Andric // FIXME: convert these to parameters of the analysis or environment. Current
35*81ad6265SDimitry Andric // settings have been experimentaly validated, but only for a particular
36*81ad6265SDimitry Andric // analysis.
37*81ad6265SDimitry Andric static constexpr int MaxCompositeValueDepth = 3;
38*81ad6265SDimitry Andric static constexpr int MaxCompositeValueSize = 1000;
39*81ad6265SDimitry Andric 
4004eeddc0SDimitry Andric /// Returns a map consisting of key-value entries that are present in both maps.
4104eeddc0SDimitry Andric template <typename K, typename V>
4204eeddc0SDimitry Andric llvm::DenseMap<K, V> intersectDenseMaps(const llvm::DenseMap<K, V> &Map1,
4304eeddc0SDimitry Andric                                         const llvm::DenseMap<K, V> &Map2) {
4404eeddc0SDimitry Andric   llvm::DenseMap<K, V> Result;
4504eeddc0SDimitry Andric   for (auto &Entry : Map1) {
4604eeddc0SDimitry Andric     auto It = Map2.find(Entry.first);
4704eeddc0SDimitry Andric     if (It != Map2.end() && Entry.second == It->second)
4804eeddc0SDimitry Andric       Result.insert({Entry.first, Entry.second});
4904eeddc0SDimitry Andric   }
5004eeddc0SDimitry Andric   return Result;
5104eeddc0SDimitry Andric }
5204eeddc0SDimitry Andric 
53*81ad6265SDimitry Andric static bool areEquivalentIndirectionValues(Value *Val1, Value *Val2) {
54*81ad6265SDimitry Andric   if (auto *IndVal1 = dyn_cast<ReferenceValue>(Val1)) {
55*81ad6265SDimitry Andric     auto *IndVal2 = cast<ReferenceValue>(Val2);
56*81ad6265SDimitry Andric     return &IndVal1->getReferentLoc() == &IndVal2->getReferentLoc();
57*81ad6265SDimitry Andric   }
58*81ad6265SDimitry Andric   if (auto *IndVal1 = dyn_cast<PointerValue>(Val1)) {
59*81ad6265SDimitry Andric     auto *IndVal2 = cast<PointerValue>(Val2);
601fd87a68SDimitry Andric     return &IndVal1->getPointeeLoc() == &IndVal2->getPointeeLoc();
611fd87a68SDimitry Andric   }
62*81ad6265SDimitry Andric   return false;
63*81ad6265SDimitry Andric }
641fd87a68SDimitry Andric 
65*81ad6265SDimitry Andric /// Returns true if and only if `Val1` is equivalent to `Val2`.
66*81ad6265SDimitry Andric static bool equivalentValues(QualType Type, Value *Val1,
67*81ad6265SDimitry Andric                              const Environment &Env1, Value *Val2,
68*81ad6265SDimitry Andric                              const Environment &Env2,
69*81ad6265SDimitry Andric                              Environment::ValueModel &Model) {
70*81ad6265SDimitry Andric   return Val1 == Val2 || areEquivalentIndirectionValues(Val1, Val2) ||
71*81ad6265SDimitry Andric          Model.compareEquivalent(Type, *Val1, Env1, *Val2, Env2);
72*81ad6265SDimitry Andric }
73*81ad6265SDimitry Andric 
74*81ad6265SDimitry Andric /// Attempts to merge distinct values `Val1` and `Val2` in `Env1` and `Env2`,
75*81ad6265SDimitry Andric /// respectively, of the same type `Type`. Merging generally produces a single
76*81ad6265SDimitry Andric /// value that (soundly) approximates the two inputs, although the actual
77*81ad6265SDimitry Andric /// meaning depends on `Model`.
78*81ad6265SDimitry Andric static Value *mergeDistinctValues(QualType Type, Value *Val1,
79*81ad6265SDimitry Andric                                   const Environment &Env1, Value *Val2,
80*81ad6265SDimitry Andric                                   const Environment &Env2,
81*81ad6265SDimitry Andric                                   Environment &MergedEnv,
82*81ad6265SDimitry Andric                                   Environment::ValueModel &Model) {
83*81ad6265SDimitry Andric   // Join distinct boolean values preserving information about the constraints
84*81ad6265SDimitry Andric   // in the respective path conditions.
85*81ad6265SDimitry Andric   //
86*81ad6265SDimitry Andric   // FIXME: Does not work for backedges, since the two (or more) paths will not
87*81ad6265SDimitry Andric   // have mutually exclusive conditions.
88*81ad6265SDimitry Andric   if (auto *Expr1 = dyn_cast<BoolValue>(Val1)) {
89*81ad6265SDimitry Andric     auto *Expr2 = cast<BoolValue>(Val2);
90*81ad6265SDimitry Andric     auto &MergedVal = MergedEnv.makeAtomicBoolValue();
91*81ad6265SDimitry Andric     MergedEnv.addToFlowCondition(MergedEnv.makeOr(
92*81ad6265SDimitry Andric         MergedEnv.makeAnd(Env1.getFlowConditionToken(),
93*81ad6265SDimitry Andric                           MergedEnv.makeIff(MergedVal, *Expr1)),
94*81ad6265SDimitry Andric         MergedEnv.makeAnd(Env2.getFlowConditionToken(),
95*81ad6265SDimitry Andric                           MergedEnv.makeIff(MergedVal, *Expr2))));
96*81ad6265SDimitry Andric     return &MergedVal;
97*81ad6265SDimitry Andric   }
98*81ad6265SDimitry Andric 
99*81ad6265SDimitry Andric   // FIXME: add unit tests that cover this statement.
100*81ad6265SDimitry Andric   if (areEquivalentIndirectionValues(Val1, Val2)) {
101*81ad6265SDimitry Andric     return Val1;
102*81ad6265SDimitry Andric   }
103*81ad6265SDimitry Andric 
104*81ad6265SDimitry Andric   // FIXME: Consider destroying `MergedValue` immediately if `ValueModel::merge`
105*81ad6265SDimitry Andric   // returns false to avoid storing unneeded values in `DACtx`.
106*81ad6265SDimitry Andric   if (Value *MergedVal = MergedEnv.createValue(Type))
107*81ad6265SDimitry Andric     if (Model.merge(Type, *Val1, Env1, *Val2, Env2, *MergedVal, MergedEnv))
108*81ad6265SDimitry Andric       return MergedVal;
109*81ad6265SDimitry Andric 
110*81ad6265SDimitry Andric   return nullptr;
111*81ad6265SDimitry Andric }
112*81ad6265SDimitry Andric 
113*81ad6265SDimitry Andric /// Initializes a global storage value.
114*81ad6265SDimitry Andric static void initGlobalVar(const VarDecl &D, Environment &Env) {
115*81ad6265SDimitry Andric   if (!D.hasGlobalStorage() ||
116*81ad6265SDimitry Andric       Env.getStorageLocation(D, SkipPast::None) != nullptr)
117*81ad6265SDimitry Andric     return;
118*81ad6265SDimitry Andric 
119*81ad6265SDimitry Andric   auto &Loc = Env.createStorageLocation(D);
120*81ad6265SDimitry Andric   Env.setStorageLocation(D, Loc);
121*81ad6265SDimitry Andric   if (auto *Val = Env.createValue(D.getType()))
122*81ad6265SDimitry Andric     Env.setValue(Loc, *Val);
123*81ad6265SDimitry Andric }
124*81ad6265SDimitry Andric 
125*81ad6265SDimitry Andric /// Initializes a global storage value.
126*81ad6265SDimitry Andric static void initGlobalVar(const Decl &D, Environment &Env) {
127*81ad6265SDimitry Andric   if (auto *V = dyn_cast<VarDecl>(&D))
128*81ad6265SDimitry Andric     initGlobalVar(*V, Env);
129*81ad6265SDimitry Andric }
130*81ad6265SDimitry Andric 
131*81ad6265SDimitry Andric /// Initializes global storage values that are declared or referenced from
132*81ad6265SDimitry Andric /// sub-statements of `S`.
133*81ad6265SDimitry Andric // FIXME: Add support for resetting globals after function calls to enable
134*81ad6265SDimitry Andric // the implementation of sound analyses.
135*81ad6265SDimitry Andric static void initGlobalVars(const Stmt &S, Environment &Env) {
136*81ad6265SDimitry Andric   for (auto *Child : S.children()) {
137*81ad6265SDimitry Andric     if (Child != nullptr)
138*81ad6265SDimitry Andric       initGlobalVars(*Child, Env);
139*81ad6265SDimitry Andric   }
140*81ad6265SDimitry Andric 
141*81ad6265SDimitry Andric   if (auto *DS = dyn_cast<DeclStmt>(&S)) {
142*81ad6265SDimitry Andric     if (DS->isSingleDecl()) {
143*81ad6265SDimitry Andric       initGlobalVar(*DS->getSingleDecl(), Env);
144*81ad6265SDimitry Andric     } else {
145*81ad6265SDimitry Andric       for (auto *D : DS->getDeclGroup())
146*81ad6265SDimitry Andric         initGlobalVar(*D, Env);
147*81ad6265SDimitry Andric     }
148*81ad6265SDimitry Andric   } else if (auto *E = dyn_cast<DeclRefExpr>(&S)) {
149*81ad6265SDimitry Andric     initGlobalVar(*E->getDecl(), Env);
150*81ad6265SDimitry Andric   } else if (auto *E = dyn_cast<MemberExpr>(&S)) {
151*81ad6265SDimitry Andric     initGlobalVar(*E->getMemberDecl(), Env);
152*81ad6265SDimitry Andric   }
153*81ad6265SDimitry Andric }
154*81ad6265SDimitry Andric 
155*81ad6265SDimitry Andric Environment::Environment(DataflowAnalysisContext &DACtx)
156*81ad6265SDimitry Andric     : DACtx(&DACtx), FlowConditionToken(&DACtx.makeFlowConditionToken()) {}
157*81ad6265SDimitry Andric 
158*81ad6265SDimitry Andric Environment::Environment(const Environment &Other)
159*81ad6265SDimitry Andric     : DACtx(Other.DACtx), DeclToLoc(Other.DeclToLoc),
160*81ad6265SDimitry Andric       ExprToLoc(Other.ExprToLoc), LocToVal(Other.LocToVal),
161*81ad6265SDimitry Andric       MemberLocToStruct(Other.MemberLocToStruct),
162*81ad6265SDimitry Andric       FlowConditionToken(&DACtx->forkFlowCondition(*Other.FlowConditionToken)) {
163*81ad6265SDimitry Andric }
164*81ad6265SDimitry Andric 
165*81ad6265SDimitry Andric Environment &Environment::operator=(const Environment &Other) {
166*81ad6265SDimitry Andric   Environment Copy(Other);
167*81ad6265SDimitry Andric   *this = std::move(Copy);
168*81ad6265SDimitry Andric   return *this;
1691fd87a68SDimitry Andric }
1701fd87a68SDimitry Andric 
17104eeddc0SDimitry Andric Environment::Environment(DataflowAnalysisContext &DACtx,
17204eeddc0SDimitry Andric                          const DeclContext &DeclCtx)
17304eeddc0SDimitry Andric     : Environment(DACtx) {
17404eeddc0SDimitry Andric   if (const auto *FuncDecl = dyn_cast<FunctionDecl>(&DeclCtx)) {
175*81ad6265SDimitry Andric     assert(FuncDecl->getBody() != nullptr);
176*81ad6265SDimitry Andric     initGlobalVars(*FuncDecl->getBody(), *this);
17704eeddc0SDimitry Andric     for (const auto *ParamDecl : FuncDecl->parameters()) {
17804eeddc0SDimitry Andric       assert(ParamDecl != nullptr);
17904eeddc0SDimitry Andric       auto &ParamLoc = createStorageLocation(*ParamDecl);
18004eeddc0SDimitry Andric       setStorageLocation(*ParamDecl, ParamLoc);
18104eeddc0SDimitry Andric       if (Value *ParamVal = createValue(ParamDecl->getType()))
18204eeddc0SDimitry Andric         setValue(ParamLoc, *ParamVal);
18304eeddc0SDimitry Andric     }
18404eeddc0SDimitry Andric   }
18504eeddc0SDimitry Andric 
18604eeddc0SDimitry Andric   if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(&DeclCtx)) {
187*81ad6265SDimitry Andric     auto *Parent = MethodDecl->getParent();
188*81ad6265SDimitry Andric     assert(Parent != nullptr);
189*81ad6265SDimitry Andric     if (Parent->isLambda())
190*81ad6265SDimitry Andric       MethodDecl = dyn_cast<CXXMethodDecl>(Parent->getDeclContext());
191*81ad6265SDimitry Andric 
192*81ad6265SDimitry Andric     if (MethodDecl && !MethodDecl->isStatic()) {
19304eeddc0SDimitry Andric       QualType ThisPointeeType = MethodDecl->getThisObjectType();
19404eeddc0SDimitry Andric       // FIXME: Add support for union types.
19504eeddc0SDimitry Andric       if (!ThisPointeeType->isUnionType()) {
19604eeddc0SDimitry Andric         auto &ThisPointeeLoc = createStorageLocation(ThisPointeeType);
19704eeddc0SDimitry Andric         DACtx.setThisPointeeStorageLocation(ThisPointeeLoc);
19804eeddc0SDimitry Andric         if (Value *ThisPointeeVal = createValue(ThisPointeeType))
19904eeddc0SDimitry Andric           setValue(ThisPointeeLoc, *ThisPointeeVal);
20004eeddc0SDimitry Andric       }
20104eeddc0SDimitry Andric     }
20204eeddc0SDimitry Andric   }
20304eeddc0SDimitry Andric }
20404eeddc0SDimitry Andric 
2051fd87a68SDimitry Andric bool Environment::equivalentTo(const Environment &Other,
2061fd87a68SDimitry Andric                                Environment::ValueModel &Model) const {
20704eeddc0SDimitry Andric   assert(DACtx == Other.DACtx);
2081fd87a68SDimitry Andric 
2091fd87a68SDimitry Andric   if (DeclToLoc != Other.DeclToLoc)
2101fd87a68SDimitry Andric     return false;
2111fd87a68SDimitry Andric 
2121fd87a68SDimitry Andric   if (ExprToLoc != Other.ExprToLoc)
2131fd87a68SDimitry Andric     return false;
2141fd87a68SDimitry Andric 
215*81ad6265SDimitry Andric   // Compare the contents for the intersection of their domains.
2161fd87a68SDimitry Andric   for (auto &Entry : LocToVal) {
2171fd87a68SDimitry Andric     const StorageLocation *Loc = Entry.first;
2181fd87a68SDimitry Andric     assert(Loc != nullptr);
2191fd87a68SDimitry Andric 
2201fd87a68SDimitry Andric     Value *Val = Entry.second;
2211fd87a68SDimitry Andric     assert(Val != nullptr);
2221fd87a68SDimitry Andric 
2231fd87a68SDimitry Andric     auto It = Other.LocToVal.find(Loc);
2241fd87a68SDimitry Andric     if (It == Other.LocToVal.end())
225*81ad6265SDimitry Andric       continue;
2261fd87a68SDimitry Andric     assert(It->second != nullptr);
2271fd87a68SDimitry Andric 
228*81ad6265SDimitry Andric     if (!equivalentValues(Loc->getType(), Val, *this, It->second, Other, Model))
2291fd87a68SDimitry Andric       return false;
2301fd87a68SDimitry Andric   }
2311fd87a68SDimitry Andric 
2321fd87a68SDimitry Andric   return true;
23304eeddc0SDimitry Andric }
23404eeddc0SDimitry Andric 
23504eeddc0SDimitry Andric LatticeJoinEffect Environment::join(const Environment &Other,
2361fd87a68SDimitry Andric                                     Environment::ValueModel &Model) {
23704eeddc0SDimitry Andric   assert(DACtx == Other.DACtx);
23804eeddc0SDimitry Andric 
23904eeddc0SDimitry Andric   auto Effect = LatticeJoinEffect::Unchanged;
24004eeddc0SDimitry Andric 
241*81ad6265SDimitry Andric   Environment JoinedEnv(*DACtx);
242*81ad6265SDimitry Andric 
243*81ad6265SDimitry Andric   JoinedEnv.DeclToLoc = intersectDenseMaps(DeclToLoc, Other.DeclToLoc);
244*81ad6265SDimitry Andric   if (DeclToLoc.size() != JoinedEnv.DeclToLoc.size())
24504eeddc0SDimitry Andric     Effect = LatticeJoinEffect::Changed;
24604eeddc0SDimitry Andric 
247*81ad6265SDimitry Andric   JoinedEnv.ExprToLoc = intersectDenseMaps(ExprToLoc, Other.ExprToLoc);
248*81ad6265SDimitry Andric   if (ExprToLoc.size() != JoinedEnv.ExprToLoc.size())
24904eeddc0SDimitry Andric     Effect = LatticeJoinEffect::Changed;
25004eeddc0SDimitry Andric 
251*81ad6265SDimitry Andric   JoinedEnv.MemberLocToStruct =
252*81ad6265SDimitry Andric       intersectDenseMaps(MemberLocToStruct, Other.MemberLocToStruct);
253*81ad6265SDimitry Andric   if (MemberLocToStruct.size() != JoinedEnv.MemberLocToStruct.size())
254*81ad6265SDimitry Andric     Effect = LatticeJoinEffect::Changed;
255*81ad6265SDimitry Andric 
256*81ad6265SDimitry Andric   // FIXME: set `Effect` as needed.
257*81ad6265SDimitry Andric   JoinedEnv.FlowConditionToken = &DACtx->joinFlowConditions(
258*81ad6265SDimitry Andric       *FlowConditionToken, *Other.FlowConditionToken);
259*81ad6265SDimitry Andric 
260*81ad6265SDimitry Andric   for (auto &Entry : LocToVal) {
26104eeddc0SDimitry Andric     const StorageLocation *Loc = Entry.first;
26204eeddc0SDimitry Andric     assert(Loc != nullptr);
26304eeddc0SDimitry Andric 
26404eeddc0SDimitry Andric     Value *Val = Entry.second;
26504eeddc0SDimitry Andric     assert(Val != nullptr);
26604eeddc0SDimitry Andric 
26704eeddc0SDimitry Andric     auto It = Other.LocToVal.find(Loc);
26804eeddc0SDimitry Andric     if (It == Other.LocToVal.end())
26904eeddc0SDimitry Andric       continue;
27004eeddc0SDimitry Andric     assert(It->second != nullptr);
27104eeddc0SDimitry Andric 
272*81ad6265SDimitry Andric     if (Val == It->second) {
273*81ad6265SDimitry Andric       JoinedEnv.LocToVal.insert({Loc, Val});
27404eeddc0SDimitry Andric       continue;
27504eeddc0SDimitry Andric     }
27604eeddc0SDimitry Andric 
277*81ad6265SDimitry Andric     if (Value *MergedVal = mergeDistinctValues(
278*81ad6265SDimitry Andric             Loc->getType(), Val, *this, It->second, Other, JoinedEnv, Model))
279*81ad6265SDimitry Andric       JoinedEnv.LocToVal.insert({Loc, MergedVal});
28004eeddc0SDimitry Andric   }
281*81ad6265SDimitry Andric   if (LocToVal.size() != JoinedEnv.LocToVal.size())
28204eeddc0SDimitry Andric     Effect = LatticeJoinEffect::Changed;
28304eeddc0SDimitry Andric 
284*81ad6265SDimitry Andric   *this = std::move(JoinedEnv);
285*81ad6265SDimitry Andric 
28604eeddc0SDimitry Andric   return Effect;
28704eeddc0SDimitry Andric }
28804eeddc0SDimitry Andric 
28904eeddc0SDimitry Andric StorageLocation &Environment::createStorageLocation(QualType Type) {
290*81ad6265SDimitry Andric   return DACtx->getStableStorageLocation(Type);
29104eeddc0SDimitry Andric }
29204eeddc0SDimitry Andric 
29304eeddc0SDimitry Andric StorageLocation &Environment::createStorageLocation(const VarDecl &D) {
29404eeddc0SDimitry Andric   // Evaluated declarations are always assigned the same storage locations to
29504eeddc0SDimitry Andric   // ensure that the environment stabilizes across loop iterations. Storage
29604eeddc0SDimitry Andric   // locations for evaluated declarations are stored in the analysis context.
297*81ad6265SDimitry Andric   return DACtx->getStableStorageLocation(D);
29804eeddc0SDimitry Andric }
29904eeddc0SDimitry Andric 
30004eeddc0SDimitry Andric StorageLocation &Environment::createStorageLocation(const Expr &E) {
30104eeddc0SDimitry Andric   // Evaluated expressions are always assigned the same storage locations to
30204eeddc0SDimitry Andric   // ensure that the environment stabilizes across loop iterations. Storage
30304eeddc0SDimitry Andric   // locations for evaluated expressions are stored in the analysis context.
304*81ad6265SDimitry Andric   return DACtx->getStableStorageLocation(E);
30504eeddc0SDimitry Andric }
30604eeddc0SDimitry Andric 
30704eeddc0SDimitry Andric void Environment::setStorageLocation(const ValueDecl &D, StorageLocation &Loc) {
30804eeddc0SDimitry Andric   assert(DeclToLoc.find(&D) == DeclToLoc.end());
30904eeddc0SDimitry Andric   DeclToLoc[&D] = &Loc;
31004eeddc0SDimitry Andric }
31104eeddc0SDimitry Andric 
31204eeddc0SDimitry Andric StorageLocation *Environment::getStorageLocation(const ValueDecl &D,
31304eeddc0SDimitry Andric                                                  SkipPast SP) const {
31404eeddc0SDimitry Andric   auto It = DeclToLoc.find(&D);
31504eeddc0SDimitry Andric   return It == DeclToLoc.end() ? nullptr : &skip(*It->second, SP);
31604eeddc0SDimitry Andric }
31704eeddc0SDimitry Andric 
31804eeddc0SDimitry Andric void Environment::setStorageLocation(const Expr &E, StorageLocation &Loc) {
319*81ad6265SDimitry Andric   const Expr &CanonE = ignoreCFGOmittedNodes(E);
320*81ad6265SDimitry Andric   assert(ExprToLoc.find(&CanonE) == ExprToLoc.end());
321*81ad6265SDimitry Andric   ExprToLoc[&CanonE] = &Loc;
32204eeddc0SDimitry Andric }
32304eeddc0SDimitry Andric 
32404eeddc0SDimitry Andric StorageLocation *Environment::getStorageLocation(const Expr &E,
32504eeddc0SDimitry Andric                                                  SkipPast SP) const {
326*81ad6265SDimitry Andric   // FIXME: Add a test with parens.
327*81ad6265SDimitry Andric   auto It = ExprToLoc.find(&ignoreCFGOmittedNodes(E));
32804eeddc0SDimitry Andric   return It == ExprToLoc.end() ? nullptr : &skip(*It->second, SP);
32904eeddc0SDimitry Andric }
33004eeddc0SDimitry Andric 
33104eeddc0SDimitry Andric StorageLocation *Environment::getThisPointeeStorageLocation() const {
33204eeddc0SDimitry Andric   return DACtx->getThisPointeeStorageLocation();
33304eeddc0SDimitry Andric }
33404eeddc0SDimitry Andric 
335*81ad6265SDimitry Andric PointerValue &Environment::getOrCreateNullPointerValue(QualType PointeeType) {
336*81ad6265SDimitry Andric   return DACtx->getOrCreateNullPointerValue(PointeeType);
337*81ad6265SDimitry Andric }
338*81ad6265SDimitry Andric 
33904eeddc0SDimitry Andric void Environment::setValue(const StorageLocation &Loc, Value &Val) {
34004eeddc0SDimitry Andric   LocToVal[&Loc] = &Val;
34104eeddc0SDimitry Andric 
34204eeddc0SDimitry Andric   if (auto *StructVal = dyn_cast<StructValue>(&Val)) {
34304eeddc0SDimitry Andric     auto &AggregateLoc = *cast<AggregateStorageLocation>(&Loc);
34404eeddc0SDimitry Andric 
34504eeddc0SDimitry Andric     const QualType Type = AggregateLoc.getType();
34604eeddc0SDimitry Andric     assert(Type->isStructureOrClassType());
34704eeddc0SDimitry Andric 
348*81ad6265SDimitry Andric     for (const FieldDecl *Field : getObjectFields(Type)) {
34904eeddc0SDimitry Andric       assert(Field != nullptr);
350*81ad6265SDimitry Andric       StorageLocation &FieldLoc = AggregateLoc.getChild(*Field);
351*81ad6265SDimitry Andric       MemberLocToStruct[&FieldLoc] = std::make_pair(StructVal, Field);
352*81ad6265SDimitry Andric       if (auto *FieldVal = StructVal->getChild(*Field))
353*81ad6265SDimitry Andric         setValue(FieldLoc, *FieldVal);
35404eeddc0SDimitry Andric     }
35504eeddc0SDimitry Andric   }
356*81ad6265SDimitry Andric 
357*81ad6265SDimitry Andric   auto IT = MemberLocToStruct.find(&Loc);
358*81ad6265SDimitry Andric   if (IT != MemberLocToStruct.end()) {
359*81ad6265SDimitry Andric     // `Loc` is the location of a struct member so we need to also update the
360*81ad6265SDimitry Andric     // value of the member in the corresponding `StructValue`.
361*81ad6265SDimitry Andric 
362*81ad6265SDimitry Andric     assert(IT->second.first != nullptr);
363*81ad6265SDimitry Andric     StructValue &StructVal = *IT->second.first;
364*81ad6265SDimitry Andric 
365*81ad6265SDimitry Andric     assert(IT->second.second != nullptr);
366*81ad6265SDimitry Andric     const ValueDecl &Member = *IT->second.second;
367*81ad6265SDimitry Andric 
368*81ad6265SDimitry Andric     StructVal.setChild(Member, Val);
369*81ad6265SDimitry Andric   }
37004eeddc0SDimitry Andric }
37104eeddc0SDimitry Andric 
37204eeddc0SDimitry Andric Value *Environment::getValue(const StorageLocation &Loc) const {
37304eeddc0SDimitry Andric   auto It = LocToVal.find(&Loc);
37404eeddc0SDimitry Andric   return It == LocToVal.end() ? nullptr : It->second;
37504eeddc0SDimitry Andric }
37604eeddc0SDimitry Andric 
37704eeddc0SDimitry Andric Value *Environment::getValue(const ValueDecl &D, SkipPast SP) const {
37804eeddc0SDimitry Andric   auto *Loc = getStorageLocation(D, SP);
37904eeddc0SDimitry Andric   if (Loc == nullptr)
38004eeddc0SDimitry Andric     return nullptr;
38104eeddc0SDimitry Andric   return getValue(*Loc);
38204eeddc0SDimitry Andric }
38304eeddc0SDimitry Andric 
38404eeddc0SDimitry Andric Value *Environment::getValue(const Expr &E, SkipPast SP) const {
38504eeddc0SDimitry Andric   auto *Loc = getStorageLocation(E, SP);
38604eeddc0SDimitry Andric   if (Loc == nullptr)
38704eeddc0SDimitry Andric     return nullptr;
38804eeddc0SDimitry Andric   return getValue(*Loc);
38904eeddc0SDimitry Andric }
39004eeddc0SDimitry Andric 
39104eeddc0SDimitry Andric Value *Environment::createValue(QualType Type) {
39204eeddc0SDimitry Andric   llvm::DenseSet<QualType> Visited;
393*81ad6265SDimitry Andric   int CreatedValuesCount = 0;
394*81ad6265SDimitry Andric   Value *Val = createValueUnlessSelfReferential(Type, Visited, /*Depth=*/0,
395*81ad6265SDimitry Andric                                                 CreatedValuesCount);
396*81ad6265SDimitry Andric   if (CreatedValuesCount > MaxCompositeValueSize) {
397*81ad6265SDimitry Andric     llvm::errs() << "Attempting to initialize a huge value of type: " << Type
398*81ad6265SDimitry Andric                  << '\n';
399*81ad6265SDimitry Andric   }
400*81ad6265SDimitry Andric   return Val;
40104eeddc0SDimitry Andric }
40204eeddc0SDimitry Andric 
40304eeddc0SDimitry Andric Value *Environment::createValueUnlessSelfReferential(
404*81ad6265SDimitry Andric     QualType Type, llvm::DenseSet<QualType> &Visited, int Depth,
405*81ad6265SDimitry Andric     int &CreatedValuesCount) {
40604eeddc0SDimitry Andric   assert(!Type.isNull());
40704eeddc0SDimitry Andric 
408*81ad6265SDimitry Andric   // Allow unlimited fields at depth 1; only cap at deeper nesting levels.
409*81ad6265SDimitry Andric   if ((Depth > 1 && CreatedValuesCount > MaxCompositeValueSize) ||
410*81ad6265SDimitry Andric       Depth > MaxCompositeValueDepth)
411*81ad6265SDimitry Andric     return nullptr;
412*81ad6265SDimitry Andric 
413*81ad6265SDimitry Andric   if (Type->isBooleanType()) {
414*81ad6265SDimitry Andric     CreatedValuesCount++;
415*81ad6265SDimitry Andric     return &makeAtomicBoolValue();
416*81ad6265SDimitry Andric   }
417*81ad6265SDimitry Andric 
41804eeddc0SDimitry Andric   if (Type->isIntegerType()) {
419*81ad6265SDimitry Andric     CreatedValuesCount++;
42004eeddc0SDimitry Andric     return &takeOwnership(std::make_unique<IntegerValue>());
42104eeddc0SDimitry Andric   }
42204eeddc0SDimitry Andric 
42304eeddc0SDimitry Andric   if (Type->isReferenceType()) {
424*81ad6265SDimitry Andric     CreatedValuesCount++;
425*81ad6265SDimitry Andric     QualType PointeeType = Type->castAs<ReferenceType>()->getPointeeType();
42604eeddc0SDimitry Andric     auto &PointeeLoc = createStorageLocation(PointeeType);
42704eeddc0SDimitry Andric 
428*81ad6265SDimitry Andric     if (Visited.insert(PointeeType.getCanonicalType()).second) {
429*81ad6265SDimitry Andric       Value *PointeeVal = createValueUnlessSelfReferential(
430*81ad6265SDimitry Andric           PointeeType, Visited, Depth, CreatedValuesCount);
43104eeddc0SDimitry Andric       Visited.erase(PointeeType.getCanonicalType());
43204eeddc0SDimitry Andric 
43304eeddc0SDimitry Andric       if (PointeeVal != nullptr)
43404eeddc0SDimitry Andric         setValue(PointeeLoc, *PointeeVal);
43504eeddc0SDimitry Andric     }
43604eeddc0SDimitry Andric 
43704eeddc0SDimitry Andric     return &takeOwnership(std::make_unique<ReferenceValue>(PointeeLoc));
43804eeddc0SDimitry Andric   }
43904eeddc0SDimitry Andric 
44004eeddc0SDimitry Andric   if (Type->isPointerType()) {
441*81ad6265SDimitry Andric     CreatedValuesCount++;
442*81ad6265SDimitry Andric     QualType PointeeType = Type->castAs<PointerType>()->getPointeeType();
44304eeddc0SDimitry Andric     auto &PointeeLoc = createStorageLocation(PointeeType);
44404eeddc0SDimitry Andric 
445*81ad6265SDimitry Andric     if (Visited.insert(PointeeType.getCanonicalType()).second) {
446*81ad6265SDimitry Andric       Value *PointeeVal = createValueUnlessSelfReferential(
447*81ad6265SDimitry Andric           PointeeType, Visited, Depth, CreatedValuesCount);
44804eeddc0SDimitry Andric       Visited.erase(PointeeType.getCanonicalType());
44904eeddc0SDimitry Andric 
45004eeddc0SDimitry Andric       if (PointeeVal != nullptr)
45104eeddc0SDimitry Andric         setValue(PointeeLoc, *PointeeVal);
45204eeddc0SDimitry Andric     }
45304eeddc0SDimitry Andric 
45404eeddc0SDimitry Andric     return &takeOwnership(std::make_unique<PointerValue>(PointeeLoc));
45504eeddc0SDimitry Andric   }
45604eeddc0SDimitry Andric 
45704eeddc0SDimitry Andric   if (Type->isStructureOrClassType()) {
458*81ad6265SDimitry Andric     CreatedValuesCount++;
45904eeddc0SDimitry Andric     // FIXME: Initialize only fields that are accessed in the context that is
46004eeddc0SDimitry Andric     // being analyzed.
46104eeddc0SDimitry Andric     llvm::DenseMap<const ValueDecl *, Value *> FieldValues;
462*81ad6265SDimitry Andric     for (const FieldDecl *Field : getObjectFields(Type)) {
46304eeddc0SDimitry Andric       assert(Field != nullptr);
46404eeddc0SDimitry Andric 
46504eeddc0SDimitry Andric       QualType FieldType = Field->getType();
46604eeddc0SDimitry Andric       if (Visited.contains(FieldType.getCanonicalType()))
46704eeddc0SDimitry Andric         continue;
46804eeddc0SDimitry Andric 
46904eeddc0SDimitry Andric       Visited.insert(FieldType.getCanonicalType());
470*81ad6265SDimitry Andric       if (auto *FieldValue = createValueUnlessSelfReferential(
471*81ad6265SDimitry Andric               FieldType, Visited, Depth + 1, CreatedValuesCount))
472*81ad6265SDimitry Andric         FieldValues.insert({Field, FieldValue});
47304eeddc0SDimitry Andric       Visited.erase(FieldType.getCanonicalType());
47404eeddc0SDimitry Andric     }
47504eeddc0SDimitry Andric 
47604eeddc0SDimitry Andric     return &takeOwnership(
47704eeddc0SDimitry Andric         std::make_unique<StructValue>(std::move(FieldValues)));
47804eeddc0SDimitry Andric   }
47904eeddc0SDimitry Andric 
48004eeddc0SDimitry Andric   return nullptr;
48104eeddc0SDimitry Andric }
48204eeddc0SDimitry Andric 
48304eeddc0SDimitry Andric StorageLocation &Environment::skip(StorageLocation &Loc, SkipPast SP) const {
48404eeddc0SDimitry Andric   switch (SP) {
48504eeddc0SDimitry Andric   case SkipPast::None:
48604eeddc0SDimitry Andric     return Loc;
48704eeddc0SDimitry Andric   case SkipPast::Reference:
48804eeddc0SDimitry Andric     // References cannot be chained so we only need to skip past one level of
48904eeddc0SDimitry Andric     // indirection.
49004eeddc0SDimitry Andric     if (auto *Val = dyn_cast_or_null<ReferenceValue>(getValue(Loc)))
491*81ad6265SDimitry Andric       return Val->getReferentLoc();
49204eeddc0SDimitry Andric     return Loc;
49304eeddc0SDimitry Andric   case SkipPast::ReferenceThenPointer:
49404eeddc0SDimitry Andric     StorageLocation &LocPastRef = skip(Loc, SkipPast::Reference);
49504eeddc0SDimitry Andric     if (auto *Val = dyn_cast_or_null<PointerValue>(getValue(LocPastRef)))
49604eeddc0SDimitry Andric       return Val->getPointeeLoc();
49704eeddc0SDimitry Andric     return LocPastRef;
49804eeddc0SDimitry Andric   }
49904eeddc0SDimitry Andric   llvm_unreachable("bad SkipPast kind");
50004eeddc0SDimitry Andric }
50104eeddc0SDimitry Andric 
50204eeddc0SDimitry Andric const StorageLocation &Environment::skip(const StorageLocation &Loc,
50304eeddc0SDimitry Andric                                          SkipPast SP) const {
50404eeddc0SDimitry Andric   return skip(*const_cast<StorageLocation *>(&Loc), SP);
50504eeddc0SDimitry Andric }
50604eeddc0SDimitry Andric 
507*81ad6265SDimitry Andric void Environment::addToFlowCondition(BoolValue &Val) {
508*81ad6265SDimitry Andric   DACtx->addFlowConditionConstraint(*FlowConditionToken, Val);
509*81ad6265SDimitry Andric }
510*81ad6265SDimitry Andric 
511*81ad6265SDimitry Andric bool Environment::flowConditionImplies(BoolValue &Val) const {
512*81ad6265SDimitry Andric   return DACtx->flowConditionImplies(*FlowConditionToken, Val);
513*81ad6265SDimitry Andric }
514*81ad6265SDimitry Andric 
51504eeddc0SDimitry Andric } // namespace dataflow
51604eeddc0SDimitry Andric } // namespace clang
517