1ae60884dSStanislav Gatev //===-- DataflowAnalysisContext.cpp -----------------------------*- C++ -*-===//
2ae60884dSStanislav Gatev //
3ae60884dSStanislav Gatev // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4ae60884dSStanislav Gatev // See https://llvm.org/LICENSE.txt for license information.
5ae60884dSStanislav Gatev // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ae60884dSStanislav Gatev //
7ae60884dSStanislav Gatev //===----------------------------------------------------------------------===//
8ae60884dSStanislav Gatev //
9ae60884dSStanislav Gatev //  This file defines a DataflowAnalysisContext class that owns objects that
10ae60884dSStanislav Gatev //  encompass the state of a program and stores context that is used during
11ae60884dSStanislav Gatev //  dataflow analysis.
12ae60884dSStanislav Gatev //
13ae60884dSStanislav Gatev //===----------------------------------------------------------------------===//
14ae60884dSStanislav Gatev 
15ae60884dSStanislav Gatev #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
1645643cfcSEric Li #include "clang/AST/ExprCXX.h"
17b5414b56SDmitri Gribenko #include "clang/Analysis/FlowSensitive/DebugSupport.h"
18ae60884dSStanislav Gatev #include "clang/Analysis/FlowSensitive/Value.h"
19b5414b56SDmitri Gribenko #include "llvm/Support/Debug.h"
20ae60884dSStanislav Gatev #include <cassert>
21ae60884dSStanislav Gatev #include <memory>
22ae60884dSStanislav Gatev #include <utility>
23ae60884dSStanislav Gatev 
24ae60884dSStanislav Gatev namespace clang {
25ae60884dSStanislav Gatev namespace dataflow {
26ae60884dSStanislav Gatev 
2712c7352fSWei Yi Tee StorageLocation &
getStableStorageLocation(QualType Type)2812c7352fSWei Yi Tee DataflowAnalysisContext::getStableStorageLocation(QualType Type) {
29f10d271aSEric Li   if (!Type.isNull() &&
30f10d271aSEric Li       (Type->isStructureOrClassType() || Type->isUnionType())) {
3112c7352fSWei Yi Tee     // FIXME: Explore options to avoid eager initialization of fields as some of
3212c7352fSWei Yi Tee     // them might not be needed for a particular analysis.
3312c7352fSWei Yi Tee     llvm::DenseMap<const ValueDecl *, StorageLocation *> FieldLocs;
3412c7352fSWei Yi Tee     for (const FieldDecl *Field : getObjectFields(Type))
3512c7352fSWei Yi Tee       FieldLocs.insert({Field, &getStableStorageLocation(Field->getType())});
3612c7352fSWei Yi Tee     return takeOwnership(
3712c7352fSWei Yi Tee         std::make_unique<AggregateStorageLocation>(Type, std::move(FieldLocs)));
3812c7352fSWei Yi Tee   }
3912c7352fSWei Yi Tee   return takeOwnership(std::make_unique<ScalarStorageLocation>(Type));
4012c7352fSWei Yi Tee }
4112c7352fSWei Yi Tee 
4212c7352fSWei Yi Tee StorageLocation &
getStableStorageLocation(const VarDecl & D)4312c7352fSWei Yi Tee DataflowAnalysisContext::getStableStorageLocation(const VarDecl &D) {
4412c7352fSWei Yi Tee   if (auto *Loc = getStorageLocation(D))
4512c7352fSWei Yi Tee     return *Loc;
4612c7352fSWei Yi Tee   auto &Loc = getStableStorageLocation(D.getType());
4712c7352fSWei Yi Tee   setStorageLocation(D, Loc);
4812c7352fSWei Yi Tee   return Loc;
4912c7352fSWei Yi Tee }
5012c7352fSWei Yi Tee 
5112c7352fSWei Yi Tee StorageLocation &
getStableStorageLocation(const Expr & E)5212c7352fSWei Yi Tee DataflowAnalysisContext::getStableStorageLocation(const Expr &E) {
5312c7352fSWei Yi Tee   if (auto *Loc = getStorageLocation(E))
5412c7352fSWei Yi Tee     return *Loc;
5512c7352fSWei Yi Tee   auto &Loc = getStableStorageLocation(E.getType());
5612c7352fSWei Yi Tee   setStorageLocation(E, Loc);
5712c7352fSWei Yi Tee   return Loc;
5812c7352fSWei Yi Tee }
5912c7352fSWei Yi Tee 
60b611376eSWei Yi Tee PointerValue &
getOrCreateNullPointerValue(QualType PointeeType)61b611376eSWei Yi Tee DataflowAnalysisContext::getOrCreateNullPointerValue(QualType PointeeType) {
62f10d271aSEric Li   auto CanonicalPointeeType =
63f10d271aSEric Li       PointeeType.isNull() ? PointeeType : PointeeType.getCanonicalType();
64b611376eSWei Yi Tee   auto Res = NullPointerVals.try_emplace(CanonicalPointeeType, nullptr);
65b611376eSWei Yi Tee   if (Res.second) {
66b611376eSWei Yi Tee     auto &PointeeLoc = getStableStorageLocation(CanonicalPointeeType);
67b611376eSWei Yi Tee     Res.first->second =
68b611376eSWei Yi Tee         &takeOwnership(std::make_unique<PointerValue>(PointeeLoc));
69b611376eSWei Yi Tee   }
70b611376eSWei Yi Tee   return *Res.first->second;
71b611376eSWei Yi Tee }
72b611376eSWei Yi Tee 
73ae60884dSStanislav Gatev static std::pair<BoolValue *, BoolValue *>
makeCanonicalBoolValuePair(BoolValue & LHS,BoolValue & RHS)74ae60884dSStanislav Gatev makeCanonicalBoolValuePair(BoolValue &LHS, BoolValue &RHS) {
75ae60884dSStanislav Gatev   auto Res = std::make_pair(&LHS, &RHS);
76ae60884dSStanislav Gatev   if (&RHS < &LHS)
77ae60884dSStanislav Gatev     std::swap(Res.first, Res.second);
78ae60884dSStanislav Gatev   return Res;
79ae60884dSStanislav Gatev }
80ae60884dSStanislav Gatev 
getOrCreateConjunction(BoolValue & LHS,BoolValue & RHS)8100e9d534SWei Yi Tee BoolValue &DataflowAnalysisContext::getOrCreateConjunction(BoolValue &LHS,
82ae60884dSStanislav Gatev                                                            BoolValue &RHS) {
83ae60884dSStanislav Gatev   if (&LHS == &RHS)
84ae60884dSStanislav Gatev     return LHS;
85ae60884dSStanislav Gatev 
86ae60884dSStanislav Gatev   auto Res = ConjunctionVals.try_emplace(makeCanonicalBoolValuePair(LHS, RHS),
87ae60884dSStanislav Gatev                                          nullptr);
88ae60884dSStanislav Gatev   if (Res.second)
89ae60884dSStanislav Gatev     Res.first->second =
90ae60884dSStanislav Gatev         &takeOwnership(std::make_unique<ConjunctionValue>(LHS, RHS));
91ae60884dSStanislav Gatev   return *Res.first->second;
92ae60884dSStanislav Gatev }
93ae60884dSStanislav Gatev 
getOrCreateDisjunction(BoolValue & LHS,BoolValue & RHS)9400e9d534SWei Yi Tee BoolValue &DataflowAnalysisContext::getOrCreateDisjunction(BoolValue &LHS,
95ae60884dSStanislav Gatev                                                            BoolValue &RHS) {
96ae60884dSStanislav Gatev   if (&LHS == &RHS)
97ae60884dSStanislav Gatev     return LHS;
98ae60884dSStanislav Gatev 
99ae60884dSStanislav Gatev   auto Res = DisjunctionVals.try_emplace(makeCanonicalBoolValuePair(LHS, RHS),
100ae60884dSStanislav Gatev                                          nullptr);
101ae60884dSStanislav Gatev   if (Res.second)
102ae60884dSStanislav Gatev     Res.first->second =
103ae60884dSStanislav Gatev         &takeOwnership(std::make_unique<DisjunctionValue>(LHS, RHS));
104ae60884dSStanislav Gatev   return *Res.first->second;
105ae60884dSStanislav Gatev }
106ae60884dSStanislav Gatev 
getOrCreateNegation(BoolValue & Val)10700e9d534SWei Yi Tee BoolValue &DataflowAnalysisContext::getOrCreateNegation(BoolValue &Val) {
108ae60884dSStanislav Gatev   auto Res = NegationVals.try_emplace(&Val, nullptr);
109ae60884dSStanislav Gatev   if (Res.second)
110ae60884dSStanislav Gatev     Res.first->second = &takeOwnership(std::make_unique<NegationValue>(Val));
111ae60884dSStanislav Gatev   return *Res.first->second;
112ae60884dSStanislav Gatev }
113ae60884dSStanislav Gatev 
getOrCreateImplication(BoolValue & LHS,BoolValue & RHS)11400e9d534SWei Yi Tee BoolValue &DataflowAnalysisContext::getOrCreateImplication(BoolValue &LHS,
11500e9d534SWei Yi Tee                                                            BoolValue &RHS) {
116*b5e3dac3SDmitri Gribenko   if (&LHS == &RHS)
117*b5e3dac3SDmitri Gribenko     return getBoolLiteralValue(true);
118*b5e3dac3SDmitri Gribenko 
119*b5e3dac3SDmitri Gribenko   auto Res = ImplicationVals.try_emplace(std::make_pair(&LHS, &RHS), nullptr);
120*b5e3dac3SDmitri Gribenko   if (Res.second)
121*b5e3dac3SDmitri Gribenko     Res.first->second =
122*b5e3dac3SDmitri Gribenko         &takeOwnership(std::make_unique<ImplicationValue>(LHS, RHS));
123*b5e3dac3SDmitri Gribenko   return *Res.first->second;
12400e9d534SWei Yi Tee }
12500e9d534SWei Yi Tee 
getOrCreateIff(BoolValue & LHS,BoolValue & RHS)12600e9d534SWei Yi Tee BoolValue &DataflowAnalysisContext::getOrCreateIff(BoolValue &LHS,
12700e9d534SWei Yi Tee                                                    BoolValue &RHS) {
128*b5e3dac3SDmitri Gribenko   if (&LHS == &RHS)
129*b5e3dac3SDmitri Gribenko     return getBoolLiteralValue(true);
130*b5e3dac3SDmitri Gribenko 
131*b5e3dac3SDmitri Gribenko   auto Res = BiconditionalVals.try_emplace(makeCanonicalBoolValuePair(LHS, RHS),
132*b5e3dac3SDmitri Gribenko                                            nullptr);
133*b5e3dac3SDmitri Gribenko   if (Res.second)
134*b5e3dac3SDmitri Gribenko     Res.first->second =
135*b5e3dac3SDmitri Gribenko         &takeOwnership(std::make_unique<BiconditionalValue>(LHS, RHS));
136*b5e3dac3SDmitri Gribenko   return *Res.first->second;
13700e9d534SWei Yi Tee }
13800e9d534SWei Yi Tee 
makeFlowConditionToken()139955a05a2SStanislav Gatev AtomicBoolValue &DataflowAnalysisContext::makeFlowConditionToken() {
140fb88ea62SWei Yi Tee   return createAtomicBoolValue();
141955a05a2SStanislav Gatev }
142955a05a2SStanislav Gatev 
addFlowConditionConstraint(AtomicBoolValue & Token,BoolValue & Constraint)143955a05a2SStanislav Gatev void DataflowAnalysisContext::addFlowConditionConstraint(
144955a05a2SStanislav Gatev     AtomicBoolValue &Token, BoolValue &Constraint) {
145fb88ea62SWei Yi Tee   auto Res = FlowConditionConstraints.try_emplace(&Token, &Constraint);
146fb88ea62SWei Yi Tee   if (!Res.second) {
14700e9d534SWei Yi Tee     Res.first->second = &getOrCreateConjunction(*Res.first->second, Constraint);
148fb88ea62SWei Yi Tee   }
149955a05a2SStanislav Gatev }
150955a05a2SStanislav Gatev 
151955a05a2SStanislav Gatev AtomicBoolValue &
forkFlowCondition(AtomicBoolValue & Token)152955a05a2SStanislav Gatev DataflowAnalysisContext::forkFlowCondition(AtomicBoolValue &Token) {
153955a05a2SStanislav Gatev   auto &ForkToken = makeFlowConditionToken();
154955a05a2SStanislav Gatev   FlowConditionDeps[&ForkToken].insert(&Token);
155955a05a2SStanislav Gatev   addFlowConditionConstraint(ForkToken, Token);
156955a05a2SStanislav Gatev   return ForkToken;
157955a05a2SStanislav Gatev }
158955a05a2SStanislav Gatev 
159955a05a2SStanislav Gatev AtomicBoolValue &
joinFlowConditions(AtomicBoolValue & FirstToken,AtomicBoolValue & SecondToken)160955a05a2SStanislav Gatev DataflowAnalysisContext::joinFlowConditions(AtomicBoolValue &FirstToken,
161955a05a2SStanislav Gatev                                             AtomicBoolValue &SecondToken) {
162955a05a2SStanislav Gatev   auto &Token = makeFlowConditionToken();
163955a05a2SStanislav Gatev   FlowConditionDeps[&Token].insert(&FirstToken);
164955a05a2SStanislav Gatev   FlowConditionDeps[&Token].insert(&SecondToken);
16500e9d534SWei Yi Tee   addFlowConditionConstraint(Token,
16600e9d534SWei Yi Tee                              getOrCreateDisjunction(FirstToken, SecondToken));
167955a05a2SStanislav Gatev   return Token;
168955a05a2SStanislav Gatev }
169955a05a2SStanislav Gatev 
17042a7ddb4SWei Yi Tee Solver::Result
querySolver(llvm::DenseSet<BoolValue * > Constraints)17142a7ddb4SWei Yi Tee DataflowAnalysisContext::querySolver(llvm::DenseSet<BoolValue *> Constraints) {
17242a7ddb4SWei Yi Tee   Constraints.insert(&getBoolLiteralValue(true));
17342a7ddb4SWei Yi Tee   Constraints.insert(&getOrCreateNegation(getBoolLiteralValue(false)));
17442a7ddb4SWei Yi Tee   return S->solve(std::move(Constraints));
17542a7ddb4SWei Yi Tee }
17642a7ddb4SWei Yi Tee 
flowConditionImplies(AtomicBoolValue & Token,BoolValue & Val)177955a05a2SStanislav Gatev bool DataflowAnalysisContext::flowConditionImplies(AtomicBoolValue &Token,
178955a05a2SStanislav Gatev                                                    BoolValue &Val) {
179955a05a2SStanislav Gatev   // Returns true if and only if truth assignment of the flow condition implies
180955a05a2SStanislav Gatev   // that `Val` is also true. We prove whether or not this property holds by
181955a05a2SStanislav Gatev   // reducing the problem to satisfiability checking. In other words, we attempt
182955a05a2SStanislav Gatev   // to show that assuming `Val` is false makes the constraints induced by the
183955a05a2SStanislav Gatev   // flow condition unsatisfiable.
18442a7ddb4SWei Yi Tee   llvm::DenseSet<BoolValue *> Constraints = {&Token, &getOrCreateNegation(Val)};
185955a05a2SStanislav Gatev   llvm::DenseSet<AtomicBoolValue *> VisitedTokens;
186955a05a2SStanislav Gatev   addTransitiveFlowConditionConstraints(Token, Constraints, VisitedTokens);
18742a7ddb4SWei Yi Tee   return isUnsatisfiable(std::move(Constraints));
188955a05a2SStanislav Gatev }
189955a05a2SStanislav Gatev 
flowConditionIsTautology(AtomicBoolValue & Token)19058abe36aSEric Li bool DataflowAnalysisContext::flowConditionIsTautology(AtomicBoolValue &Token) {
19158abe36aSEric Li   // Returns true if and only if we cannot prove that the flow condition can
19258abe36aSEric Li   // ever be false.
19342a7ddb4SWei Yi Tee   llvm::DenseSet<BoolValue *> Constraints = {&getOrCreateNegation(Token)};
19458abe36aSEric Li   llvm::DenseSet<AtomicBoolValue *> VisitedTokens;
19558abe36aSEric Li   addTransitiveFlowConditionConstraints(Token, Constraints, VisitedTokens);
19642a7ddb4SWei Yi Tee   return isUnsatisfiable(std::move(Constraints));
19758abe36aSEric Li }
19858abe36aSEric Li 
equivalentBoolValues(BoolValue & Val1,BoolValue & Val2)1990f65a3e6SWei Yi Tee bool DataflowAnalysisContext::equivalentBoolValues(BoolValue &Val1,
2000f65a3e6SWei Yi Tee                                                    BoolValue &Val2) {
2010f65a3e6SWei Yi Tee   llvm::DenseSet<BoolValue *> Constraints = {
2020f65a3e6SWei Yi Tee       &getOrCreateNegation(getOrCreateIff(Val1, Val2))};
2030f65a3e6SWei Yi Tee   return isUnsatisfiable(Constraints);
2040f65a3e6SWei Yi Tee }
2050f65a3e6SWei Yi Tee 
addTransitiveFlowConditionConstraints(AtomicBoolValue & Token,llvm::DenseSet<BoolValue * > & Constraints,llvm::DenseSet<AtomicBoolValue * > & VisitedTokens)206955a05a2SStanislav Gatev void DataflowAnalysisContext::addTransitiveFlowConditionConstraints(
207955a05a2SStanislav Gatev     AtomicBoolValue &Token, llvm::DenseSet<BoolValue *> &Constraints,
208fb88ea62SWei Yi Tee     llvm::DenseSet<AtomicBoolValue *> &VisitedTokens) {
209955a05a2SStanislav Gatev   auto Res = VisitedTokens.insert(&Token);
210955a05a2SStanislav Gatev   if (!Res.second)
211955a05a2SStanislav Gatev     return;
212955a05a2SStanislav Gatev 
213c0c9d717SDmitri Gribenko   auto ConstraintsIt = FlowConditionConstraints.find(&Token);
214c0c9d717SDmitri Gribenko   if (ConstraintsIt == FlowConditionConstraints.end()) {
215fb88ea62SWei Yi Tee     Constraints.insert(&Token);
216fb88ea62SWei Yi Tee   } else {
217fb88ea62SWei Yi Tee     // Bind flow condition token via `iff` to its set of constraints:
218fb88ea62SWei Yi Tee     // FC <=> (C1 ^ C2 ^ ...), where Ci are constraints
219c0c9d717SDmitri Gribenko     Constraints.insert(&getOrCreateIff(Token, *ConstraintsIt->second));
220fb88ea62SWei Yi Tee   }
221955a05a2SStanislav Gatev 
222c0c9d717SDmitri Gribenko   auto DepsIt = FlowConditionDeps.find(&Token);
223c0c9d717SDmitri Gribenko   if (DepsIt != FlowConditionDeps.end()) {
224c0c9d717SDmitri Gribenko     for (AtomicBoolValue *DepToken : DepsIt->second) {
225955a05a2SStanislav Gatev       addTransitiveFlowConditionConstraints(*DepToken, Constraints,
226955a05a2SStanislav Gatev                                             VisitedTokens);
227955a05a2SStanislav Gatev     }
228955a05a2SStanislav Gatev   }
229fb88ea62SWei Yi Tee }
230955a05a2SStanislav Gatev 
substituteBoolValue(BoolValue & Val,llvm::DenseMap<BoolValue *,BoolValue * > & SubstitutionsCache)231bdfe556dSWei Yi Tee BoolValue &DataflowAnalysisContext::substituteBoolValue(
232bdfe556dSWei Yi Tee     BoolValue &Val,
233bdfe556dSWei Yi Tee     llvm::DenseMap<BoolValue *, BoolValue *> &SubstitutionsCache) {
234c0c9d717SDmitri Gribenko   auto It = SubstitutionsCache.find(&Val);
235c0c9d717SDmitri Gribenko   if (It != SubstitutionsCache.end()) {
236fa34210fSWei Yi Tee     // Return memoized result of substituting this boolean value.
237c0c9d717SDmitri Gribenko     return *It->second;
238bdfe556dSWei Yi Tee   }
239fa34210fSWei Yi Tee 
240fa34210fSWei Yi Tee   // Handle substitution on the boolean value (and its subvalues), saving the
241fa34210fSWei Yi Tee   // result into `SubstitutionsCache`.
242bdfe556dSWei Yi Tee   BoolValue *Result;
243bdfe556dSWei Yi Tee   switch (Val.getKind()) {
244bdfe556dSWei Yi Tee   case Value::Kind::AtomicBool: {
245bdfe556dSWei Yi Tee     Result = &Val;
246bdfe556dSWei Yi Tee     break;
247bdfe556dSWei Yi Tee   }
248bdfe556dSWei Yi Tee   case Value::Kind::Negation: {
249bdfe556dSWei Yi Tee     auto &Negation = *cast<NegationValue>(&Val);
250bdfe556dSWei Yi Tee     auto &Sub = substituteBoolValue(Negation.getSubVal(), SubstitutionsCache);
251bdfe556dSWei Yi Tee     Result = &getOrCreateNegation(Sub);
252bdfe556dSWei Yi Tee     break;
253bdfe556dSWei Yi Tee   }
254bdfe556dSWei Yi Tee   case Value::Kind::Disjunction: {
255bdfe556dSWei Yi Tee     auto &Disjunct = *cast<DisjunctionValue>(&Val);
256bdfe556dSWei Yi Tee     auto &LeftSub =
257bdfe556dSWei Yi Tee         substituteBoolValue(Disjunct.getLeftSubValue(), SubstitutionsCache);
258bdfe556dSWei Yi Tee     auto &RightSub =
259bdfe556dSWei Yi Tee         substituteBoolValue(Disjunct.getRightSubValue(), SubstitutionsCache);
260bdfe556dSWei Yi Tee     Result = &getOrCreateDisjunction(LeftSub, RightSub);
261bdfe556dSWei Yi Tee     break;
262bdfe556dSWei Yi Tee   }
263bdfe556dSWei Yi Tee   case Value::Kind::Conjunction: {
264bdfe556dSWei Yi Tee     auto &Conjunct = *cast<ConjunctionValue>(&Val);
265bdfe556dSWei Yi Tee     auto &LeftSub =
266bdfe556dSWei Yi Tee         substituteBoolValue(Conjunct.getLeftSubValue(), SubstitutionsCache);
267bdfe556dSWei Yi Tee     auto &RightSub =
268bdfe556dSWei Yi Tee         substituteBoolValue(Conjunct.getRightSubValue(), SubstitutionsCache);
269bdfe556dSWei Yi Tee     Result = &getOrCreateConjunction(LeftSub, RightSub);
270bdfe556dSWei Yi Tee     break;
271bdfe556dSWei Yi Tee   }
272*b5e3dac3SDmitri Gribenko   case Value::Kind::Implication: {
273*b5e3dac3SDmitri Gribenko     auto &IV = *cast<ImplicationValue>(&Val);
274*b5e3dac3SDmitri Gribenko     auto &LeftSub =
275*b5e3dac3SDmitri Gribenko         substituteBoolValue(IV.getLeftSubValue(), SubstitutionsCache);
276*b5e3dac3SDmitri Gribenko     auto &RightSub =
277*b5e3dac3SDmitri Gribenko         substituteBoolValue(IV.getRightSubValue(), SubstitutionsCache);
278*b5e3dac3SDmitri Gribenko     Result = &getOrCreateImplication(LeftSub, RightSub);
279*b5e3dac3SDmitri Gribenko     break;
280*b5e3dac3SDmitri Gribenko   }
281*b5e3dac3SDmitri Gribenko   case Value::Kind::Biconditional: {
282*b5e3dac3SDmitri Gribenko     auto &BV = *cast<BiconditionalValue>(&Val);
283*b5e3dac3SDmitri Gribenko     auto &LeftSub =
284*b5e3dac3SDmitri Gribenko         substituteBoolValue(BV.getLeftSubValue(), SubstitutionsCache);
285*b5e3dac3SDmitri Gribenko     auto &RightSub =
286*b5e3dac3SDmitri Gribenko         substituteBoolValue(BV.getRightSubValue(), SubstitutionsCache);
287*b5e3dac3SDmitri Gribenko     Result = &getOrCreateIff(LeftSub, RightSub);
288*b5e3dac3SDmitri Gribenko     break;
289*b5e3dac3SDmitri Gribenko   }
290bdfe556dSWei Yi Tee   default:
291bdfe556dSWei Yi Tee     llvm_unreachable("Unhandled Value Kind");
292bdfe556dSWei Yi Tee   }
293bdfe556dSWei Yi Tee   SubstitutionsCache[&Val] = Result;
294bdfe556dSWei Yi Tee   return *Result;
295bdfe556dSWei Yi Tee }
296bdfe556dSWei Yi Tee 
buildAndSubstituteFlowCondition(AtomicBoolValue & Token,llvm::DenseMap<AtomicBoolValue *,BoolValue * > Substitutions)297bdfe556dSWei Yi Tee BoolValue &DataflowAnalysisContext::buildAndSubstituteFlowCondition(
298bdfe556dSWei Yi Tee     AtomicBoolValue &Token,
299bdfe556dSWei Yi Tee     llvm::DenseMap<AtomicBoolValue *, BoolValue *> Substitutions) {
300fa34210fSWei Yi Tee   assert(
301fa34210fSWei Yi Tee       Substitutions.find(&getBoolLiteralValue(true)) == Substitutions.end() &&
302fa34210fSWei Yi Tee       Substitutions.find(&getBoolLiteralValue(false)) == Substitutions.end() &&
303fa34210fSWei Yi Tee       "Do not substitute true/false boolean literals");
304bdfe556dSWei Yi Tee   llvm::DenseMap<BoolValue *, BoolValue *> SubstitutionsCache(
305bdfe556dSWei Yi Tee       Substitutions.begin(), Substitutions.end());
306bdfe556dSWei Yi Tee   return buildAndSubstituteFlowConditionWithCache(Token, SubstitutionsCache);
307bdfe556dSWei Yi Tee }
308bdfe556dSWei Yi Tee 
buildAndSubstituteFlowConditionWithCache(AtomicBoolValue & Token,llvm::DenseMap<BoolValue *,BoolValue * > & SubstitutionsCache)309bdfe556dSWei Yi Tee BoolValue &DataflowAnalysisContext::buildAndSubstituteFlowConditionWithCache(
310bdfe556dSWei Yi Tee     AtomicBoolValue &Token,
311bdfe556dSWei Yi Tee     llvm::DenseMap<BoolValue *, BoolValue *> &SubstitutionsCache) {
312c0c9d717SDmitri Gribenko   auto ConstraintsIt = FlowConditionConstraints.find(&Token);
313c0c9d717SDmitri Gribenko   if (ConstraintsIt == FlowConditionConstraints.end()) {
314bdfe556dSWei Yi Tee     return getBoolLiteralValue(true);
315bdfe556dSWei Yi Tee   }
316c0c9d717SDmitri Gribenko   auto DepsIt = FlowConditionDeps.find(&Token);
317c0c9d717SDmitri Gribenko   if (DepsIt != FlowConditionDeps.end()) {
318c0c9d717SDmitri Gribenko     for (AtomicBoolValue *DepToken : DepsIt->second) {
319bdfe556dSWei Yi Tee       auto &NewDep = buildAndSubstituteFlowConditionWithCache(
320bdfe556dSWei Yi Tee           *DepToken, SubstitutionsCache);
321bdfe556dSWei Yi Tee       SubstitutionsCache[DepToken] = &NewDep;
322bdfe556dSWei Yi Tee     }
323bdfe556dSWei Yi Tee   }
324c0c9d717SDmitri Gribenko   return substituteBoolValue(*ConstraintsIt->second, SubstitutionsCache);
325bdfe556dSWei Yi Tee }
326bdfe556dSWei Yi Tee 
dumpFlowCondition(AtomicBoolValue & Token)327b5414b56SDmitri Gribenko void DataflowAnalysisContext::dumpFlowCondition(AtomicBoolValue &Token) {
328b5414b56SDmitri Gribenko   llvm::DenseSet<BoolValue *> Constraints = {&Token};
329b5414b56SDmitri Gribenko   llvm::DenseSet<AtomicBoolValue *> VisitedTokens;
330b5414b56SDmitri Gribenko   addTransitiveFlowConditionConstraints(Token, Constraints, VisitedTokens);
331b5414b56SDmitri Gribenko 
332b5414b56SDmitri Gribenko   llvm::DenseMap<const AtomicBoolValue *, std::string> AtomNames = {
333b5414b56SDmitri Gribenko       {&getBoolLiteralValue(false), "False"},
334b5414b56SDmitri Gribenko       {&getBoolLiteralValue(true), "True"}};
335b5414b56SDmitri Gribenko   llvm::dbgs() << debugString(Constraints, AtomNames);
336b5414b56SDmitri Gribenko }
337b5414b56SDmitri Gribenko 
338ae60884dSStanislav Gatev } // namespace dataflow
339ae60884dSStanislav Gatev } // namespace clang
34045643cfcSEric Li 
34145643cfcSEric Li using namespace clang;
34245643cfcSEric Li 
ignoreCFGOmittedNodes(const Expr & E)34345643cfcSEric Li const Expr &clang::dataflow::ignoreCFGOmittedNodes(const Expr &E) {
34445643cfcSEric Li   const Expr *Current = &E;
34545643cfcSEric Li   if (auto *EWC = dyn_cast<ExprWithCleanups>(Current)) {
34645643cfcSEric Li     Current = EWC->getSubExpr();
34745643cfcSEric Li     assert(Current != nullptr);
34845643cfcSEric Li   }
34945643cfcSEric Li   Current = Current->IgnoreParens();
35045643cfcSEric Li   assert(Current != nullptr);
35145643cfcSEric Li   return *Current;
35245643cfcSEric Li }
35345643cfcSEric Li 
ignoreCFGOmittedNodes(const Stmt & S)35445643cfcSEric Li const Stmt &clang::dataflow::ignoreCFGOmittedNodes(const Stmt &S) {
35545643cfcSEric Li   if (auto *E = dyn_cast<Expr>(&S))
35645643cfcSEric Li     return ignoreCFGOmittedNodes(*E);
35745643cfcSEric Li   return S;
35845643cfcSEric Li }
35912c7352fSWei Yi Tee 
36012c7352fSWei Yi Tee // FIXME: Does not precisely handle non-virtual diamond inheritance. A single
36112c7352fSWei Yi Tee // field decl will be modeled for all instances of the inherited field.
36212c7352fSWei Yi Tee static void
getFieldsFromClassHierarchy(QualType Type,llvm::DenseSet<const FieldDecl * > & Fields)36312c7352fSWei Yi Tee getFieldsFromClassHierarchy(QualType Type,
36412c7352fSWei Yi Tee                             llvm::DenseSet<const FieldDecl *> &Fields) {
36512c7352fSWei Yi Tee   if (Type->isIncompleteType() || Type->isDependentType() ||
36612c7352fSWei Yi Tee       !Type->isRecordType())
36712c7352fSWei Yi Tee     return;
36812c7352fSWei Yi Tee 
36912c7352fSWei Yi Tee   for (const FieldDecl *Field : Type->getAsRecordDecl()->fields())
37012c7352fSWei Yi Tee     Fields.insert(Field);
37112c7352fSWei Yi Tee   if (auto *CXXRecord = Type->getAsCXXRecordDecl())
37212c7352fSWei Yi Tee     for (const CXXBaseSpecifier &Base : CXXRecord->bases())
37312c7352fSWei Yi Tee       getFieldsFromClassHierarchy(Base.getType(), Fields);
37412c7352fSWei Yi Tee }
37512c7352fSWei Yi Tee 
37612c7352fSWei Yi Tee /// Gets the set of all fields in the type.
37712c7352fSWei Yi Tee llvm::DenseSet<const FieldDecl *>
getObjectFields(QualType Type)37812c7352fSWei Yi Tee clang::dataflow::getObjectFields(QualType Type) {
37912c7352fSWei Yi Tee   llvm::DenseSet<const FieldDecl *> Fields;
38012c7352fSWei Yi Tee   getFieldsFromClassHierarchy(Type, Fields);
38112c7352fSWei Yi Tee   return Fields;
38212c7352fSWei Yi Tee }
383