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