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