xref: /openbsd-src/gnu/llvm/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp (revision 12c855180aad702bbcca06e0398d774beeafb155)
1*12c85518Srobert //===-- DataflowAnalysisContext.cpp -----------------------------*- C++ -*-===//
2*12c85518Srobert //
3*12c85518Srobert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*12c85518Srobert // See https://llvm.org/LICENSE.txt for license information.
5*12c85518Srobert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*12c85518Srobert //
7*12c85518Srobert //===----------------------------------------------------------------------===//
8*12c85518Srobert //
9*12c85518Srobert //  This file defines a DataflowAnalysisContext class that owns objects that
10*12c85518Srobert //  encompass the state of a program and stores context that is used during
11*12c85518Srobert //  dataflow analysis.
12*12c85518Srobert //
13*12c85518Srobert //===----------------------------------------------------------------------===//
14*12c85518Srobert 
15*12c85518Srobert #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
16*12c85518Srobert #include "clang/AST/ExprCXX.h"
17*12c85518Srobert #include "clang/Analysis/FlowSensitive/DebugSupport.h"
18*12c85518Srobert #include "clang/Analysis/FlowSensitive/Value.h"
19*12c85518Srobert #include "llvm/ADT/SetOperations.h"
20*12c85518Srobert #include "llvm/Support/Debug.h"
21*12c85518Srobert #include <cassert>
22*12c85518Srobert #include <memory>
23*12c85518Srobert #include <utility>
24*12c85518Srobert 
25*12c85518Srobert namespace clang {
26*12c85518Srobert namespace dataflow {
27*12c85518Srobert 
addModeledFields(const llvm::DenseSet<const FieldDecl * > & Fields)28*12c85518Srobert void DataflowAnalysisContext::addModeledFields(
29*12c85518Srobert     const llvm::DenseSet<const FieldDecl *> &Fields) {
30*12c85518Srobert   llvm::set_union(ModeledFields, Fields);
31*12c85518Srobert }
32*12c85518Srobert 
33*12c85518Srobert llvm::DenseSet<const FieldDecl *>
getReferencedFields(QualType Type)34*12c85518Srobert DataflowAnalysisContext::getReferencedFields(QualType Type) {
35*12c85518Srobert   llvm::DenseSet<const FieldDecl *> Fields = getObjectFields(Type);
36*12c85518Srobert   llvm::set_intersect(Fields, ModeledFields);
37*12c85518Srobert   return Fields;
38*12c85518Srobert }
39*12c85518Srobert 
createStorageLocation(QualType Type)40*12c85518Srobert StorageLocation &DataflowAnalysisContext::createStorageLocation(QualType Type) {
41*12c85518Srobert   if (!Type.isNull() &&
42*12c85518Srobert       (Type->isStructureOrClassType() || Type->isUnionType())) {
43*12c85518Srobert     llvm::DenseMap<const ValueDecl *, StorageLocation *> FieldLocs;
44*12c85518Srobert     // During context-sensitive analysis, a struct may be allocated in one
45*12c85518Srobert     // function, but its field accessed in a function lower in the stack than
46*12c85518Srobert     // the allocation. Since we only collect fields used in the function where
47*12c85518Srobert     // the allocation occurs, we can't apply that filter when performing
48*12c85518Srobert     // context-sensitive analysis. But, this only applies to storage locations,
49*12c85518Srobert     // since field access it not allowed to fail. In contrast, field *values*
50*12c85518Srobert     // don't need this allowance, since the API allows for uninitialized fields.
51*12c85518Srobert     auto Fields = Opts.ContextSensitiveOpts ? getObjectFields(Type)
52*12c85518Srobert                                             : getReferencedFields(Type);
53*12c85518Srobert     for (const FieldDecl *Field : Fields)
54*12c85518Srobert       FieldLocs.insert({Field, &createStorageLocation(Field->getType())});
55*12c85518Srobert     return takeOwnership(
56*12c85518Srobert         std::make_unique<AggregateStorageLocation>(Type, std::move(FieldLocs)));
57*12c85518Srobert   }
58*12c85518Srobert   return takeOwnership(std::make_unique<ScalarStorageLocation>(Type));
59*12c85518Srobert }
60*12c85518Srobert 
61*12c85518Srobert StorageLocation &
getStableStorageLocation(const VarDecl & D)62*12c85518Srobert DataflowAnalysisContext::getStableStorageLocation(const VarDecl &D) {
63*12c85518Srobert   if (auto *Loc = getStorageLocation(D))
64*12c85518Srobert     return *Loc;
65*12c85518Srobert   auto &Loc = createStorageLocation(D.getType());
66*12c85518Srobert   setStorageLocation(D, Loc);
67*12c85518Srobert   return Loc;
68*12c85518Srobert }
69*12c85518Srobert 
70*12c85518Srobert StorageLocation &
getStableStorageLocation(const Expr & E)71*12c85518Srobert DataflowAnalysisContext::getStableStorageLocation(const Expr &E) {
72*12c85518Srobert   if (auto *Loc = getStorageLocation(E))
73*12c85518Srobert     return *Loc;
74*12c85518Srobert   auto &Loc = createStorageLocation(E.getType());
75*12c85518Srobert   setStorageLocation(E, Loc);
76*12c85518Srobert   return Loc;
77*12c85518Srobert }
78*12c85518Srobert 
79*12c85518Srobert PointerValue &
getOrCreateNullPointerValue(QualType PointeeType)80*12c85518Srobert DataflowAnalysisContext::getOrCreateNullPointerValue(QualType PointeeType) {
81*12c85518Srobert   auto CanonicalPointeeType =
82*12c85518Srobert       PointeeType.isNull() ? PointeeType : PointeeType.getCanonicalType();
83*12c85518Srobert   auto Res = NullPointerVals.try_emplace(CanonicalPointeeType, nullptr);
84*12c85518Srobert   if (Res.second) {
85*12c85518Srobert     auto &PointeeLoc = createStorageLocation(CanonicalPointeeType);
86*12c85518Srobert     Res.first->second =
87*12c85518Srobert         &takeOwnership(std::make_unique<PointerValue>(PointeeLoc));
88*12c85518Srobert   }
89*12c85518Srobert   return *Res.first->second;
90*12c85518Srobert }
91*12c85518Srobert 
92*12c85518Srobert static std::pair<BoolValue *, BoolValue *>
makeCanonicalBoolValuePair(BoolValue & LHS,BoolValue & RHS)93*12c85518Srobert makeCanonicalBoolValuePair(BoolValue &LHS, BoolValue &RHS) {
94*12c85518Srobert   auto Res = std::make_pair(&LHS, &RHS);
95*12c85518Srobert   if (&RHS < &LHS)
96*12c85518Srobert     std::swap(Res.first, Res.second);
97*12c85518Srobert   return Res;
98*12c85518Srobert }
99*12c85518Srobert 
getOrCreateConjunction(BoolValue & LHS,BoolValue & RHS)100*12c85518Srobert BoolValue &DataflowAnalysisContext::getOrCreateConjunction(BoolValue &LHS,
101*12c85518Srobert                                                            BoolValue &RHS) {
102*12c85518Srobert   if (&LHS == &RHS)
103*12c85518Srobert     return LHS;
104*12c85518Srobert 
105*12c85518Srobert   auto Res = ConjunctionVals.try_emplace(makeCanonicalBoolValuePair(LHS, RHS),
106*12c85518Srobert                                          nullptr);
107*12c85518Srobert   if (Res.second)
108*12c85518Srobert     Res.first->second =
109*12c85518Srobert         &takeOwnership(std::make_unique<ConjunctionValue>(LHS, RHS));
110*12c85518Srobert   return *Res.first->second;
111*12c85518Srobert }
112*12c85518Srobert 
getOrCreateDisjunction(BoolValue & LHS,BoolValue & RHS)113*12c85518Srobert BoolValue &DataflowAnalysisContext::getOrCreateDisjunction(BoolValue &LHS,
114*12c85518Srobert                                                            BoolValue &RHS) {
115*12c85518Srobert   if (&LHS == &RHS)
116*12c85518Srobert     return LHS;
117*12c85518Srobert 
118*12c85518Srobert   auto Res = DisjunctionVals.try_emplace(makeCanonicalBoolValuePair(LHS, RHS),
119*12c85518Srobert                                          nullptr);
120*12c85518Srobert   if (Res.second)
121*12c85518Srobert     Res.first->second =
122*12c85518Srobert         &takeOwnership(std::make_unique<DisjunctionValue>(LHS, RHS));
123*12c85518Srobert   return *Res.first->second;
124*12c85518Srobert }
125*12c85518Srobert 
getOrCreateNegation(BoolValue & Val)126*12c85518Srobert BoolValue &DataflowAnalysisContext::getOrCreateNegation(BoolValue &Val) {
127*12c85518Srobert   auto Res = NegationVals.try_emplace(&Val, nullptr);
128*12c85518Srobert   if (Res.second)
129*12c85518Srobert     Res.first->second = &takeOwnership(std::make_unique<NegationValue>(Val));
130*12c85518Srobert   return *Res.first->second;
131*12c85518Srobert }
132*12c85518Srobert 
getOrCreateImplication(BoolValue & LHS,BoolValue & RHS)133*12c85518Srobert BoolValue &DataflowAnalysisContext::getOrCreateImplication(BoolValue &LHS,
134*12c85518Srobert                                                            BoolValue &RHS) {
135*12c85518Srobert   if (&LHS == &RHS)
136*12c85518Srobert     return getBoolLiteralValue(true);
137*12c85518Srobert 
138*12c85518Srobert   auto Res = ImplicationVals.try_emplace(std::make_pair(&LHS, &RHS), nullptr);
139*12c85518Srobert   if (Res.second)
140*12c85518Srobert     Res.first->second =
141*12c85518Srobert         &takeOwnership(std::make_unique<ImplicationValue>(LHS, RHS));
142*12c85518Srobert   return *Res.first->second;
143*12c85518Srobert }
144*12c85518Srobert 
getOrCreateIff(BoolValue & LHS,BoolValue & RHS)145*12c85518Srobert BoolValue &DataflowAnalysisContext::getOrCreateIff(BoolValue &LHS,
146*12c85518Srobert                                                    BoolValue &RHS) {
147*12c85518Srobert   if (&LHS == &RHS)
148*12c85518Srobert     return getBoolLiteralValue(true);
149*12c85518Srobert 
150*12c85518Srobert   auto Res = BiconditionalVals.try_emplace(makeCanonicalBoolValuePair(LHS, RHS),
151*12c85518Srobert                                            nullptr);
152*12c85518Srobert   if (Res.second)
153*12c85518Srobert     Res.first->second =
154*12c85518Srobert         &takeOwnership(std::make_unique<BiconditionalValue>(LHS, RHS));
155*12c85518Srobert   return *Res.first->second;
156*12c85518Srobert }
157*12c85518Srobert 
makeFlowConditionToken()158*12c85518Srobert AtomicBoolValue &DataflowAnalysisContext::makeFlowConditionToken() {
159*12c85518Srobert   return createAtomicBoolValue();
160*12c85518Srobert }
161*12c85518Srobert 
addFlowConditionConstraint(AtomicBoolValue & Token,BoolValue & Constraint)162*12c85518Srobert void DataflowAnalysisContext::addFlowConditionConstraint(
163*12c85518Srobert     AtomicBoolValue &Token, BoolValue &Constraint) {
164*12c85518Srobert   auto Res = FlowConditionConstraints.try_emplace(&Token, &Constraint);
165*12c85518Srobert   if (!Res.second) {
166*12c85518Srobert     Res.first->second = &getOrCreateConjunction(*Res.first->second, Constraint);
167*12c85518Srobert   }
168*12c85518Srobert }
169*12c85518Srobert 
170*12c85518Srobert AtomicBoolValue &
forkFlowCondition(AtomicBoolValue & Token)171*12c85518Srobert DataflowAnalysisContext::forkFlowCondition(AtomicBoolValue &Token) {
172*12c85518Srobert   auto &ForkToken = makeFlowConditionToken();
173*12c85518Srobert   FlowConditionDeps[&ForkToken].insert(&Token);
174*12c85518Srobert   addFlowConditionConstraint(ForkToken, Token);
175*12c85518Srobert   return ForkToken;
176*12c85518Srobert }
177*12c85518Srobert 
178*12c85518Srobert AtomicBoolValue &
joinFlowConditions(AtomicBoolValue & FirstToken,AtomicBoolValue & SecondToken)179*12c85518Srobert DataflowAnalysisContext::joinFlowConditions(AtomicBoolValue &FirstToken,
180*12c85518Srobert                                             AtomicBoolValue &SecondToken) {
181*12c85518Srobert   auto &Token = makeFlowConditionToken();
182*12c85518Srobert   FlowConditionDeps[&Token].insert(&FirstToken);
183*12c85518Srobert   FlowConditionDeps[&Token].insert(&SecondToken);
184*12c85518Srobert   addFlowConditionConstraint(Token,
185*12c85518Srobert                              getOrCreateDisjunction(FirstToken, SecondToken));
186*12c85518Srobert   return Token;
187*12c85518Srobert }
188*12c85518Srobert 
189*12c85518Srobert Solver::Result
querySolver(llvm::DenseSet<BoolValue * > Constraints)190*12c85518Srobert DataflowAnalysisContext::querySolver(llvm::DenseSet<BoolValue *> Constraints) {
191*12c85518Srobert   Constraints.insert(&getBoolLiteralValue(true));
192*12c85518Srobert   Constraints.insert(&getOrCreateNegation(getBoolLiteralValue(false)));
193*12c85518Srobert   return S->solve(std::move(Constraints));
194*12c85518Srobert }
195*12c85518Srobert 
flowConditionImplies(AtomicBoolValue & Token,BoolValue & Val)196*12c85518Srobert bool DataflowAnalysisContext::flowConditionImplies(AtomicBoolValue &Token,
197*12c85518Srobert                                                    BoolValue &Val) {
198*12c85518Srobert   // Returns true if and only if truth assignment of the flow condition implies
199*12c85518Srobert   // that `Val` is also true. We prove whether or not this property holds by
200*12c85518Srobert   // reducing the problem to satisfiability checking. In other words, we attempt
201*12c85518Srobert   // to show that assuming `Val` is false makes the constraints induced by the
202*12c85518Srobert   // flow condition unsatisfiable.
203*12c85518Srobert   llvm::DenseSet<BoolValue *> Constraints = {&Token, &getOrCreateNegation(Val)};
204*12c85518Srobert   llvm::DenseSet<AtomicBoolValue *> VisitedTokens;
205*12c85518Srobert   addTransitiveFlowConditionConstraints(Token, Constraints, VisitedTokens);
206*12c85518Srobert   return isUnsatisfiable(std::move(Constraints));
207*12c85518Srobert }
208*12c85518Srobert 
flowConditionIsTautology(AtomicBoolValue & Token)209*12c85518Srobert bool DataflowAnalysisContext::flowConditionIsTautology(AtomicBoolValue &Token) {
210*12c85518Srobert   // Returns true if and only if we cannot prove that the flow condition can
211*12c85518Srobert   // ever be false.
212*12c85518Srobert   llvm::DenseSet<BoolValue *> Constraints = {&getOrCreateNegation(Token)};
213*12c85518Srobert   llvm::DenseSet<AtomicBoolValue *> VisitedTokens;
214*12c85518Srobert   addTransitiveFlowConditionConstraints(Token, Constraints, VisitedTokens);
215*12c85518Srobert   return isUnsatisfiable(std::move(Constraints));
216*12c85518Srobert }
217*12c85518Srobert 
equivalentBoolValues(BoolValue & Val1,BoolValue & Val2)218*12c85518Srobert bool DataflowAnalysisContext::equivalentBoolValues(BoolValue &Val1,
219*12c85518Srobert                                                    BoolValue &Val2) {
220*12c85518Srobert   llvm::DenseSet<BoolValue *> Constraints = {
221*12c85518Srobert       &getOrCreateNegation(getOrCreateIff(Val1, Val2))};
222*12c85518Srobert   return isUnsatisfiable(Constraints);
223*12c85518Srobert }
224*12c85518Srobert 
addTransitiveFlowConditionConstraints(AtomicBoolValue & Token,llvm::DenseSet<BoolValue * > & Constraints,llvm::DenseSet<AtomicBoolValue * > & VisitedTokens)225*12c85518Srobert void DataflowAnalysisContext::addTransitiveFlowConditionConstraints(
226*12c85518Srobert     AtomicBoolValue &Token, llvm::DenseSet<BoolValue *> &Constraints,
227*12c85518Srobert     llvm::DenseSet<AtomicBoolValue *> &VisitedTokens) {
228*12c85518Srobert   auto Res = VisitedTokens.insert(&Token);
229*12c85518Srobert   if (!Res.second)
230*12c85518Srobert     return;
231*12c85518Srobert 
232*12c85518Srobert   auto ConstraintsIt = FlowConditionConstraints.find(&Token);
233*12c85518Srobert   if (ConstraintsIt == FlowConditionConstraints.end()) {
234*12c85518Srobert     Constraints.insert(&Token);
235*12c85518Srobert   } else {
236*12c85518Srobert     // Bind flow condition token via `iff` to its set of constraints:
237*12c85518Srobert     // FC <=> (C1 ^ C2 ^ ...), where Ci are constraints
238*12c85518Srobert     Constraints.insert(&getOrCreateIff(Token, *ConstraintsIt->second));
239*12c85518Srobert   }
240*12c85518Srobert 
241*12c85518Srobert   auto DepsIt = FlowConditionDeps.find(&Token);
242*12c85518Srobert   if (DepsIt != FlowConditionDeps.end()) {
243*12c85518Srobert     for (AtomicBoolValue *DepToken : DepsIt->second) {
244*12c85518Srobert       addTransitiveFlowConditionConstraints(*DepToken, Constraints,
245*12c85518Srobert                                             VisitedTokens);
246*12c85518Srobert     }
247*12c85518Srobert   }
248*12c85518Srobert }
249*12c85518Srobert 
substituteBoolValue(BoolValue & Val,llvm::DenseMap<BoolValue *,BoolValue * > & SubstitutionsCache)250*12c85518Srobert BoolValue &DataflowAnalysisContext::substituteBoolValue(
251*12c85518Srobert     BoolValue &Val,
252*12c85518Srobert     llvm::DenseMap<BoolValue *, BoolValue *> &SubstitutionsCache) {
253*12c85518Srobert   auto It = SubstitutionsCache.find(&Val);
254*12c85518Srobert   if (It != SubstitutionsCache.end()) {
255*12c85518Srobert     // Return memoized result of substituting this boolean value.
256*12c85518Srobert     return *It->second;
257*12c85518Srobert   }
258*12c85518Srobert 
259*12c85518Srobert   // Handle substitution on the boolean value (and its subvalues), saving the
260*12c85518Srobert   // result into `SubstitutionsCache`.
261*12c85518Srobert   BoolValue *Result;
262*12c85518Srobert   switch (Val.getKind()) {
263*12c85518Srobert   case Value::Kind::AtomicBool: {
264*12c85518Srobert     Result = &Val;
265*12c85518Srobert     break;
266*12c85518Srobert   }
267*12c85518Srobert   case Value::Kind::Negation: {
268*12c85518Srobert     auto &Negation = *cast<NegationValue>(&Val);
269*12c85518Srobert     auto &Sub = substituteBoolValue(Negation.getSubVal(), SubstitutionsCache);
270*12c85518Srobert     Result = &getOrCreateNegation(Sub);
271*12c85518Srobert     break;
272*12c85518Srobert   }
273*12c85518Srobert   case Value::Kind::Disjunction: {
274*12c85518Srobert     auto &Disjunct = *cast<DisjunctionValue>(&Val);
275*12c85518Srobert     auto &LeftSub =
276*12c85518Srobert         substituteBoolValue(Disjunct.getLeftSubValue(), SubstitutionsCache);
277*12c85518Srobert     auto &RightSub =
278*12c85518Srobert         substituteBoolValue(Disjunct.getRightSubValue(), SubstitutionsCache);
279*12c85518Srobert     Result = &getOrCreateDisjunction(LeftSub, RightSub);
280*12c85518Srobert     break;
281*12c85518Srobert   }
282*12c85518Srobert   case Value::Kind::Conjunction: {
283*12c85518Srobert     auto &Conjunct = *cast<ConjunctionValue>(&Val);
284*12c85518Srobert     auto &LeftSub =
285*12c85518Srobert         substituteBoolValue(Conjunct.getLeftSubValue(), SubstitutionsCache);
286*12c85518Srobert     auto &RightSub =
287*12c85518Srobert         substituteBoolValue(Conjunct.getRightSubValue(), SubstitutionsCache);
288*12c85518Srobert     Result = &getOrCreateConjunction(LeftSub, RightSub);
289*12c85518Srobert     break;
290*12c85518Srobert   }
291*12c85518Srobert   case Value::Kind::Implication: {
292*12c85518Srobert     auto &IV = *cast<ImplicationValue>(&Val);
293*12c85518Srobert     auto &LeftSub =
294*12c85518Srobert         substituteBoolValue(IV.getLeftSubValue(), SubstitutionsCache);
295*12c85518Srobert     auto &RightSub =
296*12c85518Srobert         substituteBoolValue(IV.getRightSubValue(), SubstitutionsCache);
297*12c85518Srobert     Result = &getOrCreateImplication(LeftSub, RightSub);
298*12c85518Srobert     break;
299*12c85518Srobert   }
300*12c85518Srobert   case Value::Kind::Biconditional: {
301*12c85518Srobert     auto &BV = *cast<BiconditionalValue>(&Val);
302*12c85518Srobert     auto &LeftSub =
303*12c85518Srobert         substituteBoolValue(BV.getLeftSubValue(), SubstitutionsCache);
304*12c85518Srobert     auto &RightSub =
305*12c85518Srobert         substituteBoolValue(BV.getRightSubValue(), SubstitutionsCache);
306*12c85518Srobert     Result = &getOrCreateIff(LeftSub, RightSub);
307*12c85518Srobert     break;
308*12c85518Srobert   }
309*12c85518Srobert   default:
310*12c85518Srobert     llvm_unreachable("Unhandled Value Kind");
311*12c85518Srobert   }
312*12c85518Srobert   SubstitutionsCache[&Val] = Result;
313*12c85518Srobert   return *Result;
314*12c85518Srobert }
315*12c85518Srobert 
buildAndSubstituteFlowCondition(AtomicBoolValue & Token,llvm::DenseMap<AtomicBoolValue *,BoolValue * > Substitutions)316*12c85518Srobert BoolValue &DataflowAnalysisContext::buildAndSubstituteFlowCondition(
317*12c85518Srobert     AtomicBoolValue &Token,
318*12c85518Srobert     llvm::DenseMap<AtomicBoolValue *, BoolValue *> Substitutions) {
319*12c85518Srobert   assert(
320*12c85518Srobert       Substitutions.find(&getBoolLiteralValue(true)) == Substitutions.end() &&
321*12c85518Srobert       Substitutions.find(&getBoolLiteralValue(false)) == Substitutions.end() &&
322*12c85518Srobert       "Do not substitute true/false boolean literals");
323*12c85518Srobert   llvm::DenseMap<BoolValue *, BoolValue *> SubstitutionsCache(
324*12c85518Srobert       Substitutions.begin(), Substitutions.end());
325*12c85518Srobert   return buildAndSubstituteFlowConditionWithCache(Token, SubstitutionsCache);
326*12c85518Srobert }
327*12c85518Srobert 
buildAndSubstituteFlowConditionWithCache(AtomicBoolValue & Token,llvm::DenseMap<BoolValue *,BoolValue * > & SubstitutionsCache)328*12c85518Srobert BoolValue &DataflowAnalysisContext::buildAndSubstituteFlowConditionWithCache(
329*12c85518Srobert     AtomicBoolValue &Token,
330*12c85518Srobert     llvm::DenseMap<BoolValue *, BoolValue *> &SubstitutionsCache) {
331*12c85518Srobert   auto ConstraintsIt = FlowConditionConstraints.find(&Token);
332*12c85518Srobert   if (ConstraintsIt == FlowConditionConstraints.end()) {
333*12c85518Srobert     return getBoolLiteralValue(true);
334*12c85518Srobert   }
335*12c85518Srobert   auto DepsIt = FlowConditionDeps.find(&Token);
336*12c85518Srobert   if (DepsIt != FlowConditionDeps.end()) {
337*12c85518Srobert     for (AtomicBoolValue *DepToken : DepsIt->second) {
338*12c85518Srobert       auto &NewDep = buildAndSubstituteFlowConditionWithCache(
339*12c85518Srobert           *DepToken, SubstitutionsCache);
340*12c85518Srobert       SubstitutionsCache[DepToken] = &NewDep;
341*12c85518Srobert     }
342*12c85518Srobert   }
343*12c85518Srobert   return substituteBoolValue(*ConstraintsIt->second, SubstitutionsCache);
344*12c85518Srobert }
345*12c85518Srobert 
dumpFlowCondition(AtomicBoolValue & Token)346*12c85518Srobert void DataflowAnalysisContext::dumpFlowCondition(AtomicBoolValue &Token) {
347*12c85518Srobert   llvm::DenseSet<BoolValue *> Constraints = {&Token};
348*12c85518Srobert   llvm::DenseSet<AtomicBoolValue *> VisitedTokens;
349*12c85518Srobert   addTransitiveFlowConditionConstraints(Token, Constraints, VisitedTokens);
350*12c85518Srobert 
351*12c85518Srobert   llvm::DenseMap<const AtomicBoolValue *, std::string> AtomNames = {
352*12c85518Srobert       {&getBoolLiteralValue(false), "False"},
353*12c85518Srobert       {&getBoolLiteralValue(true), "True"}};
354*12c85518Srobert   llvm::dbgs() << debugString(Constraints, AtomNames);
355*12c85518Srobert }
356*12c85518Srobert 
357*12c85518Srobert const ControlFlowContext *
getControlFlowContext(const FunctionDecl * F)358*12c85518Srobert DataflowAnalysisContext::getControlFlowContext(const FunctionDecl *F) {
359*12c85518Srobert   // Canonicalize the key:
360*12c85518Srobert   F = F->getDefinition();
361*12c85518Srobert   if (F == nullptr)
362*12c85518Srobert     return nullptr;
363*12c85518Srobert   auto It = FunctionContexts.find(F);
364*12c85518Srobert   if (It != FunctionContexts.end())
365*12c85518Srobert     return &It->second;
366*12c85518Srobert 
367*12c85518Srobert   if (Stmt *Body = F->getBody()) {
368*12c85518Srobert     auto CFCtx = ControlFlowContext::build(F, *Body, F->getASTContext());
369*12c85518Srobert     // FIXME: Handle errors.
370*12c85518Srobert     assert(CFCtx);
371*12c85518Srobert     auto Result = FunctionContexts.insert({F, std::move(*CFCtx)});
372*12c85518Srobert     return &Result.first->second;
373*12c85518Srobert   }
374*12c85518Srobert 
375*12c85518Srobert   return nullptr;
376*12c85518Srobert }
377*12c85518Srobert 
378*12c85518Srobert } // namespace dataflow
379*12c85518Srobert } // namespace clang
380*12c85518Srobert 
381*12c85518Srobert using namespace clang;
382*12c85518Srobert 
ignoreCFGOmittedNodes(const Expr & E)383*12c85518Srobert const Expr &clang::dataflow::ignoreCFGOmittedNodes(const Expr &E) {
384*12c85518Srobert   const Expr *Current = &E;
385*12c85518Srobert   if (auto *EWC = dyn_cast<ExprWithCleanups>(Current)) {
386*12c85518Srobert     Current = EWC->getSubExpr();
387*12c85518Srobert     assert(Current != nullptr);
388*12c85518Srobert   }
389*12c85518Srobert   Current = Current->IgnoreParens();
390*12c85518Srobert   assert(Current != nullptr);
391*12c85518Srobert   return *Current;
392*12c85518Srobert }
393*12c85518Srobert 
ignoreCFGOmittedNodes(const Stmt & S)394*12c85518Srobert const Stmt &clang::dataflow::ignoreCFGOmittedNodes(const Stmt &S) {
395*12c85518Srobert   if (auto *E = dyn_cast<Expr>(&S))
396*12c85518Srobert     return ignoreCFGOmittedNodes(*E);
397*12c85518Srobert   return S;
398*12c85518Srobert }
399*12c85518Srobert 
400*12c85518Srobert // FIXME: Does not precisely handle non-virtual diamond inheritance. A single
401*12c85518Srobert // field decl will be modeled for all instances of the inherited field.
402*12c85518Srobert static void
getFieldsFromClassHierarchy(QualType Type,llvm::DenseSet<const FieldDecl * > & Fields)403*12c85518Srobert getFieldsFromClassHierarchy(QualType Type,
404*12c85518Srobert                             llvm::DenseSet<const FieldDecl *> &Fields) {
405*12c85518Srobert   if (Type->isIncompleteType() || Type->isDependentType() ||
406*12c85518Srobert       !Type->isRecordType())
407*12c85518Srobert     return;
408*12c85518Srobert 
409*12c85518Srobert   for (const FieldDecl *Field : Type->getAsRecordDecl()->fields())
410*12c85518Srobert     Fields.insert(Field);
411*12c85518Srobert   if (auto *CXXRecord = Type->getAsCXXRecordDecl())
412*12c85518Srobert     for (const CXXBaseSpecifier &Base : CXXRecord->bases())
413*12c85518Srobert       getFieldsFromClassHierarchy(Base.getType(), Fields);
414*12c85518Srobert }
415*12c85518Srobert 
416*12c85518Srobert /// Gets the set of all fields in the type.
417*12c85518Srobert llvm::DenseSet<const FieldDecl *>
getObjectFields(QualType Type)418*12c85518Srobert clang::dataflow::getObjectFields(QualType Type) {
419*12c85518Srobert   llvm::DenseSet<const FieldDecl *> Fields;
420*12c85518Srobert   getFieldsFromClassHierarchy(Type, Fields);
421*12c85518Srobert   return Fields;
422*12c85518Srobert }
423