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