xref: /freebsd-src/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
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"
19*bdd1243dSDimitry Andric #include "llvm/ADT/SetOperations.h"
20fcaf7f86SDimitry Andric #include "llvm/Support/Debug.h"
2181ad6265SDimitry Andric #include <cassert>
2281ad6265SDimitry Andric #include <memory>
2381ad6265SDimitry Andric #include <utility>
2481ad6265SDimitry Andric 
2581ad6265SDimitry Andric namespace clang {
2681ad6265SDimitry Andric namespace dataflow {
2781ad6265SDimitry Andric 
28*bdd1243dSDimitry Andric void DataflowAnalysisContext::addModeledFields(
29*bdd1243dSDimitry Andric     const llvm::DenseSet<const FieldDecl *> &Fields) {
30*bdd1243dSDimitry Andric   llvm::set_union(ModeledFields, Fields);
31*bdd1243dSDimitry Andric }
32*bdd1243dSDimitry Andric 
33*bdd1243dSDimitry Andric llvm::DenseSet<const FieldDecl *>
34*bdd1243dSDimitry Andric DataflowAnalysisContext::getReferencedFields(QualType Type) {
35*bdd1243dSDimitry Andric   llvm::DenseSet<const FieldDecl *> Fields = getObjectFields(Type);
36*bdd1243dSDimitry Andric   llvm::set_intersect(Fields, ModeledFields);
37*bdd1243dSDimitry Andric   return Fields;
38*bdd1243dSDimitry Andric }
39*bdd1243dSDimitry Andric 
40*bdd1243dSDimitry Andric StorageLocation &DataflowAnalysisContext::createStorageLocation(QualType Type) {
41753f127fSDimitry Andric   if (!Type.isNull() &&
42753f127fSDimitry Andric       (Type->isStructureOrClassType() || Type->isUnionType())) {
4381ad6265SDimitry Andric     llvm::DenseMap<const ValueDecl *, StorageLocation *> FieldLocs;
44*bdd1243dSDimitry Andric     // During context-sensitive analysis, a struct may be allocated in one
45*bdd1243dSDimitry Andric     // function, but its field accessed in a function lower in the stack than
46*bdd1243dSDimitry Andric     // the allocation. Since we only collect fields used in the function where
47*bdd1243dSDimitry Andric     // the allocation occurs, we can't apply that filter when performing
48*bdd1243dSDimitry Andric     // context-sensitive analysis. But, this only applies to storage locations,
49*bdd1243dSDimitry Andric     // since field access it not allowed to fail. In contrast, field *values*
50*bdd1243dSDimitry Andric     // don't need this allowance, since the API allows for uninitialized fields.
51*bdd1243dSDimitry Andric     auto Fields = Opts.ContextSensitiveOpts ? getObjectFields(Type)
52*bdd1243dSDimitry Andric                                             : getReferencedFields(Type);
53*bdd1243dSDimitry Andric     for (const FieldDecl *Field : Fields)
54*bdd1243dSDimitry Andric       FieldLocs.insert({Field, &createStorageLocation(Field->getType())});
5581ad6265SDimitry Andric     return takeOwnership(
5681ad6265SDimitry Andric         std::make_unique<AggregateStorageLocation>(Type, std::move(FieldLocs)));
5781ad6265SDimitry Andric   }
5881ad6265SDimitry Andric   return takeOwnership(std::make_unique<ScalarStorageLocation>(Type));
5981ad6265SDimitry Andric }
6081ad6265SDimitry Andric 
6181ad6265SDimitry Andric StorageLocation &
6281ad6265SDimitry Andric DataflowAnalysisContext::getStableStorageLocation(const VarDecl &D) {
6381ad6265SDimitry Andric   if (auto *Loc = getStorageLocation(D))
6481ad6265SDimitry Andric     return *Loc;
65*bdd1243dSDimitry Andric   auto &Loc = createStorageLocation(D.getType());
6681ad6265SDimitry Andric   setStorageLocation(D, Loc);
6781ad6265SDimitry Andric   return Loc;
6881ad6265SDimitry Andric }
6981ad6265SDimitry Andric 
7081ad6265SDimitry Andric StorageLocation &
7181ad6265SDimitry Andric DataflowAnalysisContext::getStableStorageLocation(const Expr &E) {
7281ad6265SDimitry Andric   if (auto *Loc = getStorageLocation(E))
7381ad6265SDimitry Andric     return *Loc;
74*bdd1243dSDimitry Andric   auto &Loc = createStorageLocation(E.getType());
7581ad6265SDimitry Andric   setStorageLocation(E, Loc);
7681ad6265SDimitry Andric   return Loc;
7781ad6265SDimitry Andric }
7881ad6265SDimitry Andric 
7981ad6265SDimitry Andric PointerValue &
8081ad6265SDimitry Andric DataflowAnalysisContext::getOrCreateNullPointerValue(QualType PointeeType) {
81753f127fSDimitry Andric   auto CanonicalPointeeType =
82753f127fSDimitry Andric       PointeeType.isNull() ? PointeeType : PointeeType.getCanonicalType();
8381ad6265SDimitry Andric   auto Res = NullPointerVals.try_emplace(CanonicalPointeeType, nullptr);
8481ad6265SDimitry Andric   if (Res.second) {
85*bdd1243dSDimitry Andric     auto &PointeeLoc = createStorageLocation(CanonicalPointeeType);
8681ad6265SDimitry Andric     Res.first->second =
8781ad6265SDimitry Andric         &takeOwnership(std::make_unique<PointerValue>(PointeeLoc));
8881ad6265SDimitry Andric   }
8981ad6265SDimitry Andric   return *Res.first->second;
9081ad6265SDimitry Andric }
9181ad6265SDimitry Andric 
9281ad6265SDimitry Andric static std::pair<BoolValue *, BoolValue *>
9381ad6265SDimitry Andric makeCanonicalBoolValuePair(BoolValue &LHS, BoolValue &RHS) {
9481ad6265SDimitry Andric   auto Res = std::make_pair(&LHS, &RHS);
9581ad6265SDimitry Andric   if (&RHS < &LHS)
9681ad6265SDimitry Andric     std::swap(Res.first, Res.second);
9781ad6265SDimitry Andric   return Res;
9881ad6265SDimitry Andric }
9981ad6265SDimitry Andric 
10081ad6265SDimitry Andric BoolValue &DataflowAnalysisContext::getOrCreateConjunction(BoolValue &LHS,
10181ad6265SDimitry Andric                                                            BoolValue &RHS) {
10281ad6265SDimitry Andric   if (&LHS == &RHS)
10381ad6265SDimitry Andric     return LHS;
10481ad6265SDimitry Andric 
10581ad6265SDimitry Andric   auto Res = ConjunctionVals.try_emplace(makeCanonicalBoolValuePair(LHS, RHS),
10681ad6265SDimitry Andric                                          nullptr);
10781ad6265SDimitry Andric   if (Res.second)
10881ad6265SDimitry Andric     Res.first->second =
10981ad6265SDimitry Andric         &takeOwnership(std::make_unique<ConjunctionValue>(LHS, RHS));
11081ad6265SDimitry Andric   return *Res.first->second;
11181ad6265SDimitry Andric }
11281ad6265SDimitry Andric 
11381ad6265SDimitry Andric BoolValue &DataflowAnalysisContext::getOrCreateDisjunction(BoolValue &LHS,
11481ad6265SDimitry Andric                                                            BoolValue &RHS) {
11581ad6265SDimitry Andric   if (&LHS == &RHS)
11681ad6265SDimitry Andric     return LHS;
11781ad6265SDimitry Andric 
11881ad6265SDimitry Andric   auto Res = DisjunctionVals.try_emplace(makeCanonicalBoolValuePair(LHS, RHS),
11981ad6265SDimitry Andric                                          nullptr);
12081ad6265SDimitry Andric   if (Res.second)
12181ad6265SDimitry Andric     Res.first->second =
12281ad6265SDimitry Andric         &takeOwnership(std::make_unique<DisjunctionValue>(LHS, RHS));
12381ad6265SDimitry Andric   return *Res.first->second;
12481ad6265SDimitry Andric }
12581ad6265SDimitry Andric 
12681ad6265SDimitry Andric BoolValue &DataflowAnalysisContext::getOrCreateNegation(BoolValue &Val) {
12781ad6265SDimitry Andric   auto Res = NegationVals.try_emplace(&Val, nullptr);
12881ad6265SDimitry Andric   if (Res.second)
12981ad6265SDimitry Andric     Res.first->second = &takeOwnership(std::make_unique<NegationValue>(Val));
13081ad6265SDimitry Andric   return *Res.first->second;
13181ad6265SDimitry Andric }
13281ad6265SDimitry Andric 
13381ad6265SDimitry Andric BoolValue &DataflowAnalysisContext::getOrCreateImplication(BoolValue &LHS,
13481ad6265SDimitry Andric                                                            BoolValue &RHS) {
135972a253aSDimitry Andric   if (&LHS == &RHS)
136972a253aSDimitry Andric     return getBoolLiteralValue(true);
137972a253aSDimitry Andric 
138972a253aSDimitry Andric   auto Res = ImplicationVals.try_emplace(std::make_pair(&LHS, &RHS), nullptr);
139972a253aSDimitry Andric   if (Res.second)
140972a253aSDimitry Andric     Res.first->second =
141972a253aSDimitry Andric         &takeOwnership(std::make_unique<ImplicationValue>(LHS, RHS));
142972a253aSDimitry Andric   return *Res.first->second;
14381ad6265SDimitry Andric }
14481ad6265SDimitry Andric 
14581ad6265SDimitry Andric BoolValue &DataflowAnalysisContext::getOrCreateIff(BoolValue &LHS,
14681ad6265SDimitry Andric                                                    BoolValue &RHS) {
147972a253aSDimitry Andric   if (&LHS == &RHS)
148972a253aSDimitry Andric     return getBoolLiteralValue(true);
149972a253aSDimitry Andric 
150972a253aSDimitry Andric   auto Res = BiconditionalVals.try_emplace(makeCanonicalBoolValuePair(LHS, RHS),
151972a253aSDimitry Andric                                            nullptr);
152972a253aSDimitry Andric   if (Res.second)
153972a253aSDimitry Andric     Res.first->second =
154972a253aSDimitry Andric         &takeOwnership(std::make_unique<BiconditionalValue>(LHS, RHS));
155972a253aSDimitry Andric   return *Res.first->second;
15681ad6265SDimitry Andric }
15781ad6265SDimitry Andric 
15881ad6265SDimitry Andric AtomicBoolValue &DataflowAnalysisContext::makeFlowConditionToken() {
15981ad6265SDimitry Andric   return createAtomicBoolValue();
16081ad6265SDimitry Andric }
16181ad6265SDimitry Andric 
16281ad6265SDimitry Andric void DataflowAnalysisContext::addFlowConditionConstraint(
16381ad6265SDimitry Andric     AtomicBoolValue &Token, BoolValue &Constraint) {
16481ad6265SDimitry Andric   auto Res = FlowConditionConstraints.try_emplace(&Token, &Constraint);
16581ad6265SDimitry Andric   if (!Res.second) {
16681ad6265SDimitry Andric     Res.first->second = &getOrCreateConjunction(*Res.first->second, Constraint);
16781ad6265SDimitry Andric   }
16881ad6265SDimitry Andric }
16981ad6265SDimitry Andric 
17081ad6265SDimitry Andric AtomicBoolValue &
17181ad6265SDimitry Andric DataflowAnalysisContext::forkFlowCondition(AtomicBoolValue &Token) {
17281ad6265SDimitry Andric   auto &ForkToken = makeFlowConditionToken();
17381ad6265SDimitry Andric   FlowConditionDeps[&ForkToken].insert(&Token);
17481ad6265SDimitry Andric   addFlowConditionConstraint(ForkToken, Token);
17581ad6265SDimitry Andric   return ForkToken;
17681ad6265SDimitry Andric }
17781ad6265SDimitry Andric 
17881ad6265SDimitry Andric AtomicBoolValue &
17981ad6265SDimitry Andric DataflowAnalysisContext::joinFlowConditions(AtomicBoolValue &FirstToken,
18081ad6265SDimitry Andric                                             AtomicBoolValue &SecondToken) {
18181ad6265SDimitry Andric   auto &Token = makeFlowConditionToken();
18281ad6265SDimitry Andric   FlowConditionDeps[&Token].insert(&FirstToken);
18381ad6265SDimitry Andric   FlowConditionDeps[&Token].insert(&SecondToken);
18481ad6265SDimitry Andric   addFlowConditionConstraint(Token,
18581ad6265SDimitry Andric                              getOrCreateDisjunction(FirstToken, SecondToken));
18681ad6265SDimitry Andric   return Token;
18781ad6265SDimitry Andric }
18881ad6265SDimitry Andric 
18981ad6265SDimitry Andric Solver::Result
19081ad6265SDimitry Andric DataflowAnalysisContext::querySolver(llvm::DenseSet<BoolValue *> Constraints) {
19181ad6265SDimitry Andric   Constraints.insert(&getBoolLiteralValue(true));
19281ad6265SDimitry Andric   Constraints.insert(&getOrCreateNegation(getBoolLiteralValue(false)));
19381ad6265SDimitry Andric   return S->solve(std::move(Constraints));
19481ad6265SDimitry Andric }
19581ad6265SDimitry Andric 
19681ad6265SDimitry Andric bool DataflowAnalysisContext::flowConditionImplies(AtomicBoolValue &Token,
19781ad6265SDimitry Andric                                                    BoolValue &Val) {
19881ad6265SDimitry Andric   // Returns true if and only if truth assignment of the flow condition implies
19981ad6265SDimitry Andric   // that `Val` is also true. We prove whether or not this property holds by
20081ad6265SDimitry Andric   // reducing the problem to satisfiability checking. In other words, we attempt
20181ad6265SDimitry Andric   // to show that assuming `Val` is false makes the constraints induced by the
20281ad6265SDimitry Andric   // flow condition unsatisfiable.
20381ad6265SDimitry Andric   llvm::DenseSet<BoolValue *> Constraints = {&Token, &getOrCreateNegation(Val)};
20481ad6265SDimitry Andric   llvm::DenseSet<AtomicBoolValue *> VisitedTokens;
20581ad6265SDimitry Andric   addTransitiveFlowConditionConstraints(Token, Constraints, VisitedTokens);
20681ad6265SDimitry Andric   return isUnsatisfiable(std::move(Constraints));
20781ad6265SDimitry Andric }
20881ad6265SDimitry Andric 
20981ad6265SDimitry Andric bool DataflowAnalysisContext::flowConditionIsTautology(AtomicBoolValue &Token) {
21081ad6265SDimitry Andric   // Returns true if and only if we cannot prove that the flow condition can
21181ad6265SDimitry Andric   // ever be false.
21281ad6265SDimitry Andric   llvm::DenseSet<BoolValue *> Constraints = {&getOrCreateNegation(Token)};
21381ad6265SDimitry Andric   llvm::DenseSet<AtomicBoolValue *> VisitedTokens;
21481ad6265SDimitry Andric   addTransitiveFlowConditionConstraints(Token, Constraints, VisitedTokens);
21581ad6265SDimitry Andric   return isUnsatisfiable(std::move(Constraints));
21681ad6265SDimitry Andric }
21781ad6265SDimitry Andric 
21881ad6265SDimitry Andric bool DataflowAnalysisContext::equivalentBoolValues(BoolValue &Val1,
21981ad6265SDimitry Andric                                                    BoolValue &Val2) {
22081ad6265SDimitry Andric   llvm::DenseSet<BoolValue *> Constraints = {
22181ad6265SDimitry Andric       &getOrCreateNegation(getOrCreateIff(Val1, Val2))};
22281ad6265SDimitry Andric   return isUnsatisfiable(Constraints);
22381ad6265SDimitry Andric }
22481ad6265SDimitry Andric 
22581ad6265SDimitry Andric void DataflowAnalysisContext::addTransitiveFlowConditionConstraints(
22681ad6265SDimitry Andric     AtomicBoolValue &Token, llvm::DenseSet<BoolValue *> &Constraints,
22781ad6265SDimitry Andric     llvm::DenseSet<AtomicBoolValue *> &VisitedTokens) {
22881ad6265SDimitry Andric   auto Res = VisitedTokens.insert(&Token);
22981ad6265SDimitry Andric   if (!Res.second)
23081ad6265SDimitry Andric     return;
23181ad6265SDimitry Andric 
232972a253aSDimitry Andric   auto ConstraintsIt = FlowConditionConstraints.find(&Token);
233972a253aSDimitry Andric   if (ConstraintsIt == FlowConditionConstraints.end()) {
23481ad6265SDimitry Andric     Constraints.insert(&Token);
23581ad6265SDimitry Andric   } else {
23681ad6265SDimitry Andric     // Bind flow condition token via `iff` to its set of constraints:
23781ad6265SDimitry Andric     // FC <=> (C1 ^ C2 ^ ...), where Ci are constraints
238972a253aSDimitry Andric     Constraints.insert(&getOrCreateIff(Token, *ConstraintsIt->second));
23981ad6265SDimitry Andric   }
24081ad6265SDimitry Andric 
241972a253aSDimitry Andric   auto DepsIt = FlowConditionDeps.find(&Token);
242972a253aSDimitry Andric   if (DepsIt != FlowConditionDeps.end()) {
243972a253aSDimitry Andric     for (AtomicBoolValue *DepToken : DepsIt->second) {
24481ad6265SDimitry Andric       addTransitiveFlowConditionConstraints(*DepToken, Constraints,
24581ad6265SDimitry Andric                                             VisitedTokens);
24681ad6265SDimitry Andric     }
24781ad6265SDimitry Andric   }
24881ad6265SDimitry Andric }
24981ad6265SDimitry Andric 
25081ad6265SDimitry Andric BoolValue &DataflowAnalysisContext::substituteBoolValue(
25181ad6265SDimitry Andric     BoolValue &Val,
25281ad6265SDimitry Andric     llvm::DenseMap<BoolValue *, BoolValue *> &SubstitutionsCache) {
253972a253aSDimitry Andric   auto It = SubstitutionsCache.find(&Val);
254972a253aSDimitry Andric   if (It != SubstitutionsCache.end()) {
25581ad6265SDimitry Andric     // Return memoized result of substituting this boolean value.
256972a253aSDimitry Andric     return *It->second;
25781ad6265SDimitry Andric   }
25881ad6265SDimitry Andric 
25981ad6265SDimitry Andric   // Handle substitution on the boolean value (and its subvalues), saving the
26081ad6265SDimitry Andric   // result into `SubstitutionsCache`.
26181ad6265SDimitry Andric   BoolValue *Result;
26281ad6265SDimitry Andric   switch (Val.getKind()) {
26381ad6265SDimitry Andric   case Value::Kind::AtomicBool: {
26481ad6265SDimitry Andric     Result = &Val;
26581ad6265SDimitry Andric     break;
26681ad6265SDimitry Andric   }
26781ad6265SDimitry Andric   case Value::Kind::Negation: {
26881ad6265SDimitry Andric     auto &Negation = *cast<NegationValue>(&Val);
26981ad6265SDimitry Andric     auto &Sub = substituteBoolValue(Negation.getSubVal(), SubstitutionsCache);
27081ad6265SDimitry Andric     Result = &getOrCreateNegation(Sub);
27181ad6265SDimitry Andric     break;
27281ad6265SDimitry Andric   }
27381ad6265SDimitry Andric   case Value::Kind::Disjunction: {
27481ad6265SDimitry Andric     auto &Disjunct = *cast<DisjunctionValue>(&Val);
27581ad6265SDimitry Andric     auto &LeftSub =
27681ad6265SDimitry Andric         substituteBoolValue(Disjunct.getLeftSubValue(), SubstitutionsCache);
27781ad6265SDimitry Andric     auto &RightSub =
27881ad6265SDimitry Andric         substituteBoolValue(Disjunct.getRightSubValue(), SubstitutionsCache);
27981ad6265SDimitry Andric     Result = &getOrCreateDisjunction(LeftSub, RightSub);
28081ad6265SDimitry Andric     break;
28181ad6265SDimitry Andric   }
28281ad6265SDimitry Andric   case Value::Kind::Conjunction: {
28381ad6265SDimitry Andric     auto &Conjunct = *cast<ConjunctionValue>(&Val);
28481ad6265SDimitry Andric     auto &LeftSub =
28581ad6265SDimitry Andric         substituteBoolValue(Conjunct.getLeftSubValue(), SubstitutionsCache);
28681ad6265SDimitry Andric     auto &RightSub =
28781ad6265SDimitry Andric         substituteBoolValue(Conjunct.getRightSubValue(), SubstitutionsCache);
28881ad6265SDimitry Andric     Result = &getOrCreateConjunction(LeftSub, RightSub);
28981ad6265SDimitry Andric     break;
29081ad6265SDimitry Andric   }
291972a253aSDimitry Andric   case Value::Kind::Implication: {
292972a253aSDimitry Andric     auto &IV = *cast<ImplicationValue>(&Val);
293972a253aSDimitry Andric     auto &LeftSub =
294972a253aSDimitry Andric         substituteBoolValue(IV.getLeftSubValue(), SubstitutionsCache);
295972a253aSDimitry Andric     auto &RightSub =
296972a253aSDimitry Andric         substituteBoolValue(IV.getRightSubValue(), SubstitutionsCache);
297972a253aSDimitry Andric     Result = &getOrCreateImplication(LeftSub, RightSub);
298972a253aSDimitry Andric     break;
299972a253aSDimitry Andric   }
300972a253aSDimitry Andric   case Value::Kind::Biconditional: {
301972a253aSDimitry Andric     auto &BV = *cast<BiconditionalValue>(&Val);
302972a253aSDimitry Andric     auto &LeftSub =
303972a253aSDimitry Andric         substituteBoolValue(BV.getLeftSubValue(), SubstitutionsCache);
304972a253aSDimitry Andric     auto &RightSub =
305972a253aSDimitry Andric         substituteBoolValue(BV.getRightSubValue(), SubstitutionsCache);
306972a253aSDimitry Andric     Result = &getOrCreateIff(LeftSub, RightSub);
307972a253aSDimitry Andric     break;
308972a253aSDimitry Andric   }
30981ad6265SDimitry Andric   default:
31081ad6265SDimitry Andric     llvm_unreachable("Unhandled Value Kind");
31181ad6265SDimitry Andric   }
31281ad6265SDimitry Andric   SubstitutionsCache[&Val] = Result;
31381ad6265SDimitry Andric   return *Result;
31481ad6265SDimitry Andric }
31581ad6265SDimitry Andric 
31681ad6265SDimitry Andric BoolValue &DataflowAnalysisContext::buildAndSubstituteFlowCondition(
31781ad6265SDimitry Andric     AtomicBoolValue &Token,
31881ad6265SDimitry Andric     llvm::DenseMap<AtomicBoolValue *, BoolValue *> Substitutions) {
31981ad6265SDimitry Andric   assert(
32081ad6265SDimitry Andric       Substitutions.find(&getBoolLiteralValue(true)) == Substitutions.end() &&
32181ad6265SDimitry Andric       Substitutions.find(&getBoolLiteralValue(false)) == Substitutions.end() &&
32281ad6265SDimitry Andric       "Do not substitute true/false boolean literals");
32381ad6265SDimitry Andric   llvm::DenseMap<BoolValue *, BoolValue *> SubstitutionsCache(
32481ad6265SDimitry Andric       Substitutions.begin(), Substitutions.end());
32581ad6265SDimitry Andric   return buildAndSubstituteFlowConditionWithCache(Token, SubstitutionsCache);
32681ad6265SDimitry Andric }
32781ad6265SDimitry Andric 
32881ad6265SDimitry Andric BoolValue &DataflowAnalysisContext::buildAndSubstituteFlowConditionWithCache(
32981ad6265SDimitry Andric     AtomicBoolValue &Token,
33081ad6265SDimitry Andric     llvm::DenseMap<BoolValue *, BoolValue *> &SubstitutionsCache) {
331972a253aSDimitry Andric   auto ConstraintsIt = FlowConditionConstraints.find(&Token);
332972a253aSDimitry Andric   if (ConstraintsIt == FlowConditionConstraints.end()) {
33381ad6265SDimitry Andric     return getBoolLiteralValue(true);
33481ad6265SDimitry Andric   }
335972a253aSDimitry Andric   auto DepsIt = FlowConditionDeps.find(&Token);
336972a253aSDimitry Andric   if (DepsIt != FlowConditionDeps.end()) {
337972a253aSDimitry Andric     for (AtomicBoolValue *DepToken : DepsIt->second) {
33881ad6265SDimitry Andric       auto &NewDep = buildAndSubstituteFlowConditionWithCache(
33981ad6265SDimitry Andric           *DepToken, SubstitutionsCache);
34081ad6265SDimitry Andric       SubstitutionsCache[DepToken] = &NewDep;
34181ad6265SDimitry Andric     }
34281ad6265SDimitry Andric   }
343972a253aSDimitry Andric   return substituteBoolValue(*ConstraintsIt->second, SubstitutionsCache);
34481ad6265SDimitry Andric }
34581ad6265SDimitry Andric 
346fcaf7f86SDimitry Andric void DataflowAnalysisContext::dumpFlowCondition(AtomicBoolValue &Token) {
347fcaf7f86SDimitry Andric   llvm::DenseSet<BoolValue *> Constraints = {&Token};
348fcaf7f86SDimitry Andric   llvm::DenseSet<AtomicBoolValue *> VisitedTokens;
349fcaf7f86SDimitry Andric   addTransitiveFlowConditionConstraints(Token, Constraints, VisitedTokens);
350fcaf7f86SDimitry Andric 
351fcaf7f86SDimitry Andric   llvm::DenseMap<const AtomicBoolValue *, std::string> AtomNames = {
352fcaf7f86SDimitry Andric       {&getBoolLiteralValue(false), "False"},
353fcaf7f86SDimitry Andric       {&getBoolLiteralValue(true), "True"}};
354fcaf7f86SDimitry Andric   llvm::dbgs() << debugString(Constraints, AtomNames);
355fcaf7f86SDimitry Andric }
356fcaf7f86SDimitry Andric 
357*bdd1243dSDimitry Andric const ControlFlowContext *
358*bdd1243dSDimitry Andric DataflowAnalysisContext::getControlFlowContext(const FunctionDecl *F) {
359*bdd1243dSDimitry Andric   // Canonicalize the key:
360*bdd1243dSDimitry Andric   F = F->getDefinition();
361*bdd1243dSDimitry Andric   if (F == nullptr)
362*bdd1243dSDimitry Andric     return nullptr;
363*bdd1243dSDimitry Andric   auto It = FunctionContexts.find(F);
364*bdd1243dSDimitry Andric   if (It != FunctionContexts.end())
365*bdd1243dSDimitry Andric     return &It->second;
366*bdd1243dSDimitry Andric 
367*bdd1243dSDimitry Andric   if (Stmt *Body = F->getBody()) {
368*bdd1243dSDimitry Andric     auto CFCtx = ControlFlowContext::build(F, *Body, F->getASTContext());
369*bdd1243dSDimitry Andric     // FIXME: Handle errors.
370*bdd1243dSDimitry Andric     assert(CFCtx);
371*bdd1243dSDimitry Andric     auto Result = FunctionContexts.insert({F, std::move(*CFCtx)});
372*bdd1243dSDimitry Andric     return &Result.first->second;
373*bdd1243dSDimitry Andric   }
374*bdd1243dSDimitry Andric 
375*bdd1243dSDimitry Andric   return nullptr;
376*bdd1243dSDimitry Andric }
377*bdd1243dSDimitry Andric 
37881ad6265SDimitry Andric } // namespace dataflow
37981ad6265SDimitry Andric } // namespace clang
38081ad6265SDimitry Andric 
38181ad6265SDimitry Andric using namespace clang;
38281ad6265SDimitry Andric 
38381ad6265SDimitry Andric const Expr &clang::dataflow::ignoreCFGOmittedNodes(const Expr &E) {
38481ad6265SDimitry Andric   const Expr *Current = &E;
38581ad6265SDimitry Andric   if (auto *EWC = dyn_cast<ExprWithCleanups>(Current)) {
38681ad6265SDimitry Andric     Current = EWC->getSubExpr();
38781ad6265SDimitry Andric     assert(Current != nullptr);
38881ad6265SDimitry Andric   }
38981ad6265SDimitry Andric   Current = Current->IgnoreParens();
39081ad6265SDimitry Andric   assert(Current != nullptr);
39181ad6265SDimitry Andric   return *Current;
39281ad6265SDimitry Andric }
39381ad6265SDimitry Andric 
39481ad6265SDimitry Andric const Stmt &clang::dataflow::ignoreCFGOmittedNodes(const Stmt &S) {
39581ad6265SDimitry Andric   if (auto *E = dyn_cast<Expr>(&S))
39681ad6265SDimitry Andric     return ignoreCFGOmittedNodes(*E);
39781ad6265SDimitry Andric   return S;
39881ad6265SDimitry Andric }
39981ad6265SDimitry Andric 
40081ad6265SDimitry Andric // FIXME: Does not precisely handle non-virtual diamond inheritance. A single
40181ad6265SDimitry Andric // field decl will be modeled for all instances of the inherited field.
40281ad6265SDimitry Andric static void
40381ad6265SDimitry Andric getFieldsFromClassHierarchy(QualType Type,
40481ad6265SDimitry Andric                             llvm::DenseSet<const FieldDecl *> &Fields) {
40581ad6265SDimitry Andric   if (Type->isIncompleteType() || Type->isDependentType() ||
40681ad6265SDimitry Andric       !Type->isRecordType())
40781ad6265SDimitry Andric     return;
40881ad6265SDimitry Andric 
40981ad6265SDimitry Andric   for (const FieldDecl *Field : Type->getAsRecordDecl()->fields())
41081ad6265SDimitry Andric     Fields.insert(Field);
41181ad6265SDimitry Andric   if (auto *CXXRecord = Type->getAsCXXRecordDecl())
41281ad6265SDimitry Andric     for (const CXXBaseSpecifier &Base : CXXRecord->bases())
41381ad6265SDimitry Andric       getFieldsFromClassHierarchy(Base.getType(), Fields);
41481ad6265SDimitry Andric }
41581ad6265SDimitry Andric 
41681ad6265SDimitry Andric /// Gets the set of all fields in the type.
41781ad6265SDimitry Andric llvm::DenseSet<const FieldDecl *>
41881ad6265SDimitry Andric clang::dataflow::getObjectFields(QualType Type) {
41981ad6265SDimitry Andric   llvm::DenseSet<const FieldDecl *> Fields;
42081ad6265SDimitry Andric   getFieldsFromClassHierarchy(Type, Fields);
42181ad6265SDimitry Andric   return Fields;
42281ad6265SDimitry Andric }
423