xref: /freebsd-src/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp (revision 972a253a57b6f144b0e4a3e2080a2a0076ec55a0)
181ad6265SDimitry Andric //===-- DataflowAnalysisContext.cpp -----------------------------*- C++ -*-===//
281ad6265SDimitry Andric //
381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
681ad6265SDimitry Andric //
781ad6265SDimitry Andric //===----------------------------------------------------------------------===//
881ad6265SDimitry Andric //
981ad6265SDimitry Andric //  This file defines a DataflowAnalysisContext class that owns objects that
1081ad6265SDimitry Andric //  encompass the state of a program and stores context that is used during
1181ad6265SDimitry Andric //  dataflow analysis.
1281ad6265SDimitry Andric //
1381ad6265SDimitry Andric //===----------------------------------------------------------------------===//
1481ad6265SDimitry Andric 
1581ad6265SDimitry Andric #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
1681ad6265SDimitry Andric #include "clang/AST/ExprCXX.h"
17fcaf7f86SDimitry Andric #include "clang/Analysis/FlowSensitive/DebugSupport.h"
1881ad6265SDimitry Andric #include "clang/Analysis/FlowSensitive/Value.h"
19fcaf7f86SDimitry Andric #include "llvm/Support/Debug.h"
2081ad6265SDimitry Andric #include <cassert>
2181ad6265SDimitry Andric #include <memory>
2281ad6265SDimitry Andric #include <utility>
2381ad6265SDimitry Andric 
2481ad6265SDimitry Andric namespace clang {
2581ad6265SDimitry Andric namespace dataflow {
2681ad6265SDimitry Andric 
2781ad6265SDimitry Andric StorageLocation &
2881ad6265SDimitry Andric DataflowAnalysisContext::getStableStorageLocation(QualType Type) {
29753f127fSDimitry Andric   if (!Type.isNull() &&
30753f127fSDimitry Andric       (Type->isStructureOrClassType() || Type->isUnionType())) {
3181ad6265SDimitry Andric     // FIXME: Explore options to avoid eager initialization of fields as some of
3281ad6265SDimitry Andric     // them might not be needed for a particular analysis.
3381ad6265SDimitry Andric     llvm::DenseMap<const ValueDecl *, StorageLocation *> FieldLocs;
3481ad6265SDimitry Andric     for (const FieldDecl *Field : getObjectFields(Type))
3581ad6265SDimitry Andric       FieldLocs.insert({Field, &getStableStorageLocation(Field->getType())});
3681ad6265SDimitry Andric     return takeOwnership(
3781ad6265SDimitry Andric         std::make_unique<AggregateStorageLocation>(Type, std::move(FieldLocs)));
3881ad6265SDimitry Andric   }
3981ad6265SDimitry Andric   return takeOwnership(std::make_unique<ScalarStorageLocation>(Type));
4081ad6265SDimitry Andric }
4181ad6265SDimitry Andric 
4281ad6265SDimitry Andric StorageLocation &
4381ad6265SDimitry Andric DataflowAnalysisContext::getStableStorageLocation(const VarDecl &D) {
4481ad6265SDimitry Andric   if (auto *Loc = getStorageLocation(D))
4581ad6265SDimitry Andric     return *Loc;
4681ad6265SDimitry Andric   auto &Loc = getStableStorageLocation(D.getType());
4781ad6265SDimitry Andric   setStorageLocation(D, Loc);
4881ad6265SDimitry Andric   return Loc;
4981ad6265SDimitry Andric }
5081ad6265SDimitry Andric 
5181ad6265SDimitry Andric StorageLocation &
5281ad6265SDimitry Andric DataflowAnalysisContext::getStableStorageLocation(const Expr &E) {
5381ad6265SDimitry Andric   if (auto *Loc = getStorageLocation(E))
5481ad6265SDimitry Andric     return *Loc;
5581ad6265SDimitry Andric   auto &Loc = getStableStorageLocation(E.getType());
5681ad6265SDimitry Andric   setStorageLocation(E, Loc);
5781ad6265SDimitry Andric   return Loc;
5881ad6265SDimitry Andric }
5981ad6265SDimitry Andric 
6081ad6265SDimitry Andric PointerValue &
6181ad6265SDimitry Andric DataflowAnalysisContext::getOrCreateNullPointerValue(QualType PointeeType) {
62753f127fSDimitry Andric   auto CanonicalPointeeType =
63753f127fSDimitry Andric       PointeeType.isNull() ? PointeeType : PointeeType.getCanonicalType();
6481ad6265SDimitry Andric   auto Res = NullPointerVals.try_emplace(CanonicalPointeeType, nullptr);
6581ad6265SDimitry Andric   if (Res.second) {
6681ad6265SDimitry Andric     auto &PointeeLoc = getStableStorageLocation(CanonicalPointeeType);
6781ad6265SDimitry Andric     Res.first->second =
6881ad6265SDimitry Andric         &takeOwnership(std::make_unique<PointerValue>(PointeeLoc));
6981ad6265SDimitry Andric   }
7081ad6265SDimitry Andric   return *Res.first->second;
7181ad6265SDimitry Andric }
7281ad6265SDimitry Andric 
7381ad6265SDimitry Andric static std::pair<BoolValue *, BoolValue *>
7481ad6265SDimitry Andric makeCanonicalBoolValuePair(BoolValue &LHS, BoolValue &RHS) {
7581ad6265SDimitry Andric   auto Res = std::make_pair(&LHS, &RHS);
7681ad6265SDimitry Andric   if (&RHS < &LHS)
7781ad6265SDimitry Andric     std::swap(Res.first, Res.second);
7881ad6265SDimitry Andric   return Res;
7981ad6265SDimitry Andric }
8081ad6265SDimitry Andric 
8181ad6265SDimitry Andric BoolValue &DataflowAnalysisContext::getOrCreateConjunction(BoolValue &LHS,
8281ad6265SDimitry Andric                                                            BoolValue &RHS) {
8381ad6265SDimitry Andric   if (&LHS == &RHS)
8481ad6265SDimitry Andric     return LHS;
8581ad6265SDimitry Andric 
8681ad6265SDimitry Andric   auto Res = ConjunctionVals.try_emplace(makeCanonicalBoolValuePair(LHS, RHS),
8781ad6265SDimitry Andric                                          nullptr);
8881ad6265SDimitry Andric   if (Res.second)
8981ad6265SDimitry Andric     Res.first->second =
9081ad6265SDimitry Andric         &takeOwnership(std::make_unique<ConjunctionValue>(LHS, RHS));
9181ad6265SDimitry Andric   return *Res.first->second;
9281ad6265SDimitry Andric }
9381ad6265SDimitry Andric 
9481ad6265SDimitry Andric BoolValue &DataflowAnalysisContext::getOrCreateDisjunction(BoolValue &LHS,
9581ad6265SDimitry Andric                                                            BoolValue &RHS) {
9681ad6265SDimitry Andric   if (&LHS == &RHS)
9781ad6265SDimitry Andric     return LHS;
9881ad6265SDimitry Andric 
9981ad6265SDimitry Andric   auto Res = DisjunctionVals.try_emplace(makeCanonicalBoolValuePair(LHS, RHS),
10081ad6265SDimitry Andric                                          nullptr);
10181ad6265SDimitry Andric   if (Res.second)
10281ad6265SDimitry Andric     Res.first->second =
10381ad6265SDimitry Andric         &takeOwnership(std::make_unique<DisjunctionValue>(LHS, RHS));
10481ad6265SDimitry Andric   return *Res.first->second;
10581ad6265SDimitry Andric }
10681ad6265SDimitry Andric 
10781ad6265SDimitry Andric BoolValue &DataflowAnalysisContext::getOrCreateNegation(BoolValue &Val) {
10881ad6265SDimitry Andric   auto Res = NegationVals.try_emplace(&Val, nullptr);
10981ad6265SDimitry Andric   if (Res.second)
11081ad6265SDimitry Andric     Res.first->second = &takeOwnership(std::make_unique<NegationValue>(Val));
11181ad6265SDimitry Andric   return *Res.first->second;
11281ad6265SDimitry Andric }
11381ad6265SDimitry Andric 
11481ad6265SDimitry Andric BoolValue &DataflowAnalysisContext::getOrCreateImplication(BoolValue &LHS,
11581ad6265SDimitry Andric                                                            BoolValue &RHS) {
116*972a253aSDimitry Andric   if (&LHS == &RHS)
117*972a253aSDimitry Andric     return getBoolLiteralValue(true);
118*972a253aSDimitry Andric 
119*972a253aSDimitry Andric   auto Res = ImplicationVals.try_emplace(std::make_pair(&LHS, &RHS), nullptr);
120*972a253aSDimitry Andric   if (Res.second)
121*972a253aSDimitry Andric     Res.first->second =
122*972a253aSDimitry Andric         &takeOwnership(std::make_unique<ImplicationValue>(LHS, RHS));
123*972a253aSDimitry Andric   return *Res.first->second;
12481ad6265SDimitry Andric }
12581ad6265SDimitry Andric 
12681ad6265SDimitry Andric BoolValue &DataflowAnalysisContext::getOrCreateIff(BoolValue &LHS,
12781ad6265SDimitry Andric                                                    BoolValue &RHS) {
128*972a253aSDimitry Andric   if (&LHS == &RHS)
129*972a253aSDimitry Andric     return getBoolLiteralValue(true);
130*972a253aSDimitry Andric 
131*972a253aSDimitry Andric   auto Res = BiconditionalVals.try_emplace(makeCanonicalBoolValuePair(LHS, RHS),
132*972a253aSDimitry Andric                                            nullptr);
133*972a253aSDimitry Andric   if (Res.second)
134*972a253aSDimitry Andric     Res.first->second =
135*972a253aSDimitry Andric         &takeOwnership(std::make_unique<BiconditionalValue>(LHS, RHS));
136*972a253aSDimitry Andric   return *Res.first->second;
13781ad6265SDimitry Andric }
13881ad6265SDimitry Andric 
13981ad6265SDimitry Andric AtomicBoolValue &DataflowAnalysisContext::makeFlowConditionToken() {
14081ad6265SDimitry Andric   return createAtomicBoolValue();
14181ad6265SDimitry Andric }
14281ad6265SDimitry Andric 
14381ad6265SDimitry Andric void DataflowAnalysisContext::addFlowConditionConstraint(
14481ad6265SDimitry Andric     AtomicBoolValue &Token, BoolValue &Constraint) {
14581ad6265SDimitry Andric   auto Res = FlowConditionConstraints.try_emplace(&Token, &Constraint);
14681ad6265SDimitry Andric   if (!Res.second) {
14781ad6265SDimitry Andric     Res.first->second = &getOrCreateConjunction(*Res.first->second, Constraint);
14881ad6265SDimitry Andric   }
14981ad6265SDimitry Andric }
15081ad6265SDimitry Andric 
15181ad6265SDimitry Andric AtomicBoolValue &
15281ad6265SDimitry Andric DataflowAnalysisContext::forkFlowCondition(AtomicBoolValue &Token) {
15381ad6265SDimitry Andric   auto &ForkToken = makeFlowConditionToken();
15481ad6265SDimitry Andric   FlowConditionDeps[&ForkToken].insert(&Token);
15581ad6265SDimitry Andric   addFlowConditionConstraint(ForkToken, Token);
15681ad6265SDimitry Andric   return ForkToken;
15781ad6265SDimitry Andric }
15881ad6265SDimitry Andric 
15981ad6265SDimitry Andric AtomicBoolValue &
16081ad6265SDimitry Andric DataflowAnalysisContext::joinFlowConditions(AtomicBoolValue &FirstToken,
16181ad6265SDimitry Andric                                             AtomicBoolValue &SecondToken) {
16281ad6265SDimitry Andric   auto &Token = makeFlowConditionToken();
16381ad6265SDimitry Andric   FlowConditionDeps[&Token].insert(&FirstToken);
16481ad6265SDimitry Andric   FlowConditionDeps[&Token].insert(&SecondToken);
16581ad6265SDimitry Andric   addFlowConditionConstraint(Token,
16681ad6265SDimitry Andric                              getOrCreateDisjunction(FirstToken, SecondToken));
16781ad6265SDimitry Andric   return Token;
16881ad6265SDimitry Andric }
16981ad6265SDimitry Andric 
17081ad6265SDimitry Andric Solver::Result
17181ad6265SDimitry Andric DataflowAnalysisContext::querySolver(llvm::DenseSet<BoolValue *> Constraints) {
17281ad6265SDimitry Andric   Constraints.insert(&getBoolLiteralValue(true));
17381ad6265SDimitry Andric   Constraints.insert(&getOrCreateNegation(getBoolLiteralValue(false)));
17481ad6265SDimitry Andric   return S->solve(std::move(Constraints));
17581ad6265SDimitry Andric }
17681ad6265SDimitry Andric 
17781ad6265SDimitry Andric bool DataflowAnalysisContext::flowConditionImplies(AtomicBoolValue &Token,
17881ad6265SDimitry Andric                                                    BoolValue &Val) {
17981ad6265SDimitry Andric   // Returns true if and only if truth assignment of the flow condition implies
18081ad6265SDimitry Andric   // that `Val` is also true. We prove whether or not this property holds by
18181ad6265SDimitry Andric   // reducing the problem to satisfiability checking. In other words, we attempt
18281ad6265SDimitry Andric   // to show that assuming `Val` is false makes the constraints induced by the
18381ad6265SDimitry Andric   // flow condition unsatisfiable.
18481ad6265SDimitry Andric   llvm::DenseSet<BoolValue *> Constraints = {&Token, &getOrCreateNegation(Val)};
18581ad6265SDimitry Andric   llvm::DenseSet<AtomicBoolValue *> VisitedTokens;
18681ad6265SDimitry Andric   addTransitiveFlowConditionConstraints(Token, Constraints, VisitedTokens);
18781ad6265SDimitry Andric   return isUnsatisfiable(std::move(Constraints));
18881ad6265SDimitry Andric }
18981ad6265SDimitry Andric 
19081ad6265SDimitry Andric bool DataflowAnalysisContext::flowConditionIsTautology(AtomicBoolValue &Token) {
19181ad6265SDimitry Andric   // Returns true if and only if we cannot prove that the flow condition can
19281ad6265SDimitry Andric   // ever be false.
19381ad6265SDimitry Andric   llvm::DenseSet<BoolValue *> Constraints = {&getOrCreateNegation(Token)};
19481ad6265SDimitry Andric   llvm::DenseSet<AtomicBoolValue *> VisitedTokens;
19581ad6265SDimitry Andric   addTransitiveFlowConditionConstraints(Token, Constraints, VisitedTokens);
19681ad6265SDimitry Andric   return isUnsatisfiable(std::move(Constraints));
19781ad6265SDimitry Andric }
19881ad6265SDimitry Andric 
19981ad6265SDimitry Andric bool DataflowAnalysisContext::equivalentBoolValues(BoolValue &Val1,
20081ad6265SDimitry Andric                                                    BoolValue &Val2) {
20181ad6265SDimitry Andric   llvm::DenseSet<BoolValue *> Constraints = {
20281ad6265SDimitry Andric       &getOrCreateNegation(getOrCreateIff(Val1, Val2))};
20381ad6265SDimitry Andric   return isUnsatisfiable(Constraints);
20481ad6265SDimitry Andric }
20581ad6265SDimitry Andric 
20681ad6265SDimitry Andric void DataflowAnalysisContext::addTransitiveFlowConditionConstraints(
20781ad6265SDimitry Andric     AtomicBoolValue &Token, llvm::DenseSet<BoolValue *> &Constraints,
20881ad6265SDimitry Andric     llvm::DenseSet<AtomicBoolValue *> &VisitedTokens) {
20981ad6265SDimitry Andric   auto Res = VisitedTokens.insert(&Token);
21081ad6265SDimitry Andric   if (!Res.second)
21181ad6265SDimitry Andric     return;
21281ad6265SDimitry Andric 
213*972a253aSDimitry Andric   auto ConstraintsIt = FlowConditionConstraints.find(&Token);
214*972a253aSDimitry Andric   if (ConstraintsIt == FlowConditionConstraints.end()) {
21581ad6265SDimitry Andric     Constraints.insert(&Token);
21681ad6265SDimitry Andric   } else {
21781ad6265SDimitry Andric     // Bind flow condition token via `iff` to its set of constraints:
21881ad6265SDimitry Andric     // FC <=> (C1 ^ C2 ^ ...), where Ci are constraints
219*972a253aSDimitry Andric     Constraints.insert(&getOrCreateIff(Token, *ConstraintsIt->second));
22081ad6265SDimitry Andric   }
22181ad6265SDimitry Andric 
222*972a253aSDimitry Andric   auto DepsIt = FlowConditionDeps.find(&Token);
223*972a253aSDimitry Andric   if (DepsIt != FlowConditionDeps.end()) {
224*972a253aSDimitry Andric     for (AtomicBoolValue *DepToken : DepsIt->second) {
22581ad6265SDimitry Andric       addTransitiveFlowConditionConstraints(*DepToken, Constraints,
22681ad6265SDimitry Andric                                             VisitedTokens);
22781ad6265SDimitry Andric     }
22881ad6265SDimitry Andric   }
22981ad6265SDimitry Andric }
23081ad6265SDimitry Andric 
23181ad6265SDimitry Andric BoolValue &DataflowAnalysisContext::substituteBoolValue(
23281ad6265SDimitry Andric     BoolValue &Val,
23381ad6265SDimitry Andric     llvm::DenseMap<BoolValue *, BoolValue *> &SubstitutionsCache) {
234*972a253aSDimitry Andric   auto It = SubstitutionsCache.find(&Val);
235*972a253aSDimitry Andric   if (It != SubstitutionsCache.end()) {
23681ad6265SDimitry Andric     // Return memoized result of substituting this boolean value.
237*972a253aSDimitry Andric     return *It->second;
23881ad6265SDimitry Andric   }
23981ad6265SDimitry Andric 
24081ad6265SDimitry Andric   // Handle substitution on the boolean value (and its subvalues), saving the
24181ad6265SDimitry Andric   // result into `SubstitutionsCache`.
24281ad6265SDimitry Andric   BoolValue *Result;
24381ad6265SDimitry Andric   switch (Val.getKind()) {
24481ad6265SDimitry Andric   case Value::Kind::AtomicBool: {
24581ad6265SDimitry Andric     Result = &Val;
24681ad6265SDimitry Andric     break;
24781ad6265SDimitry Andric   }
24881ad6265SDimitry Andric   case Value::Kind::Negation: {
24981ad6265SDimitry Andric     auto &Negation = *cast<NegationValue>(&Val);
25081ad6265SDimitry Andric     auto &Sub = substituteBoolValue(Negation.getSubVal(), SubstitutionsCache);
25181ad6265SDimitry Andric     Result = &getOrCreateNegation(Sub);
25281ad6265SDimitry Andric     break;
25381ad6265SDimitry Andric   }
25481ad6265SDimitry Andric   case Value::Kind::Disjunction: {
25581ad6265SDimitry Andric     auto &Disjunct = *cast<DisjunctionValue>(&Val);
25681ad6265SDimitry Andric     auto &LeftSub =
25781ad6265SDimitry Andric         substituteBoolValue(Disjunct.getLeftSubValue(), SubstitutionsCache);
25881ad6265SDimitry Andric     auto &RightSub =
25981ad6265SDimitry Andric         substituteBoolValue(Disjunct.getRightSubValue(), SubstitutionsCache);
26081ad6265SDimitry Andric     Result = &getOrCreateDisjunction(LeftSub, RightSub);
26181ad6265SDimitry Andric     break;
26281ad6265SDimitry Andric   }
26381ad6265SDimitry Andric   case Value::Kind::Conjunction: {
26481ad6265SDimitry Andric     auto &Conjunct = *cast<ConjunctionValue>(&Val);
26581ad6265SDimitry Andric     auto &LeftSub =
26681ad6265SDimitry Andric         substituteBoolValue(Conjunct.getLeftSubValue(), SubstitutionsCache);
26781ad6265SDimitry Andric     auto &RightSub =
26881ad6265SDimitry Andric         substituteBoolValue(Conjunct.getRightSubValue(), SubstitutionsCache);
26981ad6265SDimitry Andric     Result = &getOrCreateConjunction(LeftSub, RightSub);
27081ad6265SDimitry Andric     break;
27181ad6265SDimitry Andric   }
272*972a253aSDimitry Andric   case Value::Kind::Implication: {
273*972a253aSDimitry Andric     auto &IV = *cast<ImplicationValue>(&Val);
274*972a253aSDimitry Andric     auto &LeftSub =
275*972a253aSDimitry Andric         substituteBoolValue(IV.getLeftSubValue(), SubstitutionsCache);
276*972a253aSDimitry Andric     auto &RightSub =
277*972a253aSDimitry Andric         substituteBoolValue(IV.getRightSubValue(), SubstitutionsCache);
278*972a253aSDimitry Andric     Result = &getOrCreateImplication(LeftSub, RightSub);
279*972a253aSDimitry Andric     break;
280*972a253aSDimitry Andric   }
281*972a253aSDimitry Andric   case Value::Kind::Biconditional: {
282*972a253aSDimitry Andric     auto &BV = *cast<BiconditionalValue>(&Val);
283*972a253aSDimitry Andric     auto &LeftSub =
284*972a253aSDimitry Andric         substituteBoolValue(BV.getLeftSubValue(), SubstitutionsCache);
285*972a253aSDimitry Andric     auto &RightSub =
286*972a253aSDimitry Andric         substituteBoolValue(BV.getRightSubValue(), SubstitutionsCache);
287*972a253aSDimitry Andric     Result = &getOrCreateIff(LeftSub, RightSub);
288*972a253aSDimitry Andric     break;
289*972a253aSDimitry Andric   }
29081ad6265SDimitry Andric   default:
29181ad6265SDimitry Andric     llvm_unreachable("Unhandled Value Kind");
29281ad6265SDimitry Andric   }
29381ad6265SDimitry Andric   SubstitutionsCache[&Val] = Result;
29481ad6265SDimitry Andric   return *Result;
29581ad6265SDimitry Andric }
29681ad6265SDimitry Andric 
29781ad6265SDimitry Andric BoolValue &DataflowAnalysisContext::buildAndSubstituteFlowCondition(
29881ad6265SDimitry Andric     AtomicBoolValue &Token,
29981ad6265SDimitry Andric     llvm::DenseMap<AtomicBoolValue *, BoolValue *> Substitutions) {
30081ad6265SDimitry Andric   assert(
30181ad6265SDimitry Andric       Substitutions.find(&getBoolLiteralValue(true)) == Substitutions.end() &&
30281ad6265SDimitry Andric       Substitutions.find(&getBoolLiteralValue(false)) == Substitutions.end() &&
30381ad6265SDimitry Andric       "Do not substitute true/false boolean literals");
30481ad6265SDimitry Andric   llvm::DenseMap<BoolValue *, BoolValue *> SubstitutionsCache(
30581ad6265SDimitry Andric       Substitutions.begin(), Substitutions.end());
30681ad6265SDimitry Andric   return buildAndSubstituteFlowConditionWithCache(Token, SubstitutionsCache);
30781ad6265SDimitry Andric }
30881ad6265SDimitry Andric 
30981ad6265SDimitry Andric BoolValue &DataflowAnalysisContext::buildAndSubstituteFlowConditionWithCache(
31081ad6265SDimitry Andric     AtomicBoolValue &Token,
31181ad6265SDimitry Andric     llvm::DenseMap<BoolValue *, BoolValue *> &SubstitutionsCache) {
312*972a253aSDimitry Andric   auto ConstraintsIt = FlowConditionConstraints.find(&Token);
313*972a253aSDimitry Andric   if (ConstraintsIt == FlowConditionConstraints.end()) {
31481ad6265SDimitry Andric     return getBoolLiteralValue(true);
31581ad6265SDimitry Andric   }
316*972a253aSDimitry Andric   auto DepsIt = FlowConditionDeps.find(&Token);
317*972a253aSDimitry Andric   if (DepsIt != FlowConditionDeps.end()) {
318*972a253aSDimitry Andric     for (AtomicBoolValue *DepToken : DepsIt->second) {
31981ad6265SDimitry Andric       auto &NewDep = buildAndSubstituteFlowConditionWithCache(
32081ad6265SDimitry Andric           *DepToken, SubstitutionsCache);
32181ad6265SDimitry Andric       SubstitutionsCache[DepToken] = &NewDep;
32281ad6265SDimitry Andric     }
32381ad6265SDimitry Andric   }
324*972a253aSDimitry Andric   return substituteBoolValue(*ConstraintsIt->second, SubstitutionsCache);
32581ad6265SDimitry Andric }
32681ad6265SDimitry Andric 
327fcaf7f86SDimitry Andric void DataflowAnalysisContext::dumpFlowCondition(AtomicBoolValue &Token) {
328fcaf7f86SDimitry Andric   llvm::DenseSet<BoolValue *> Constraints = {&Token};
329fcaf7f86SDimitry Andric   llvm::DenseSet<AtomicBoolValue *> VisitedTokens;
330fcaf7f86SDimitry Andric   addTransitiveFlowConditionConstraints(Token, Constraints, VisitedTokens);
331fcaf7f86SDimitry Andric 
332fcaf7f86SDimitry Andric   llvm::DenseMap<const AtomicBoolValue *, std::string> AtomNames = {
333fcaf7f86SDimitry Andric       {&getBoolLiteralValue(false), "False"},
334fcaf7f86SDimitry Andric       {&getBoolLiteralValue(true), "True"}};
335fcaf7f86SDimitry Andric   llvm::dbgs() << debugString(Constraints, AtomNames);
336fcaf7f86SDimitry Andric }
337fcaf7f86SDimitry Andric 
33881ad6265SDimitry Andric } // namespace dataflow
33981ad6265SDimitry Andric } // namespace clang
34081ad6265SDimitry Andric 
34181ad6265SDimitry Andric using namespace clang;
34281ad6265SDimitry Andric 
34381ad6265SDimitry Andric const Expr &clang::dataflow::ignoreCFGOmittedNodes(const Expr &E) {
34481ad6265SDimitry Andric   const Expr *Current = &E;
34581ad6265SDimitry Andric   if (auto *EWC = dyn_cast<ExprWithCleanups>(Current)) {
34681ad6265SDimitry Andric     Current = EWC->getSubExpr();
34781ad6265SDimitry Andric     assert(Current != nullptr);
34881ad6265SDimitry Andric   }
34981ad6265SDimitry Andric   Current = Current->IgnoreParens();
35081ad6265SDimitry Andric   assert(Current != nullptr);
35181ad6265SDimitry Andric   return *Current;
35281ad6265SDimitry Andric }
35381ad6265SDimitry Andric 
35481ad6265SDimitry Andric const Stmt &clang::dataflow::ignoreCFGOmittedNodes(const Stmt &S) {
35581ad6265SDimitry Andric   if (auto *E = dyn_cast<Expr>(&S))
35681ad6265SDimitry Andric     return ignoreCFGOmittedNodes(*E);
35781ad6265SDimitry Andric   return S;
35881ad6265SDimitry Andric }
35981ad6265SDimitry Andric 
36081ad6265SDimitry Andric // FIXME: Does not precisely handle non-virtual diamond inheritance. A single
36181ad6265SDimitry Andric // field decl will be modeled for all instances of the inherited field.
36281ad6265SDimitry Andric static void
36381ad6265SDimitry Andric getFieldsFromClassHierarchy(QualType Type,
36481ad6265SDimitry Andric                             llvm::DenseSet<const FieldDecl *> &Fields) {
36581ad6265SDimitry Andric   if (Type->isIncompleteType() || Type->isDependentType() ||
36681ad6265SDimitry Andric       !Type->isRecordType())
36781ad6265SDimitry Andric     return;
36881ad6265SDimitry Andric 
36981ad6265SDimitry Andric   for (const FieldDecl *Field : Type->getAsRecordDecl()->fields())
37081ad6265SDimitry Andric     Fields.insert(Field);
37181ad6265SDimitry Andric   if (auto *CXXRecord = Type->getAsCXXRecordDecl())
37281ad6265SDimitry Andric     for (const CXXBaseSpecifier &Base : CXXRecord->bases())
37381ad6265SDimitry Andric       getFieldsFromClassHierarchy(Base.getType(), Fields);
37481ad6265SDimitry Andric }
37581ad6265SDimitry Andric 
37681ad6265SDimitry Andric /// Gets the set of all fields in the type.
37781ad6265SDimitry Andric llvm::DenseSet<const FieldDecl *>
37881ad6265SDimitry Andric clang::dataflow::getObjectFields(QualType Type) {
37981ad6265SDimitry Andric   llvm::DenseSet<const FieldDecl *> Fields;
38081ad6265SDimitry Andric   getFieldsFromClassHierarchy(Type, Fields);
38181ad6265SDimitry Andric   return Fields;
38281ad6265SDimitry Andric }
383