xref: /freebsd-src/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp (revision cb14a3fe5122c879eae1fb480ed7ce82a699ddb6)
104eeddc0SDimitry Andric //===-- DataflowEnvironment.cpp ---------------------------------*- C++ -*-===//
204eeddc0SDimitry Andric //
304eeddc0SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
404eeddc0SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
504eeddc0SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
604eeddc0SDimitry Andric //
704eeddc0SDimitry Andric //===----------------------------------------------------------------------===//
804eeddc0SDimitry Andric //
904eeddc0SDimitry Andric //  This file defines an Environment class that is used by dataflow analyses
1004eeddc0SDimitry Andric //  that run over Control-Flow Graphs (CFGs) to keep track of the state of the
1104eeddc0SDimitry Andric //  program at given program points.
1204eeddc0SDimitry Andric //
1304eeddc0SDimitry Andric //===----------------------------------------------------------------------===//
1404eeddc0SDimitry Andric 
1504eeddc0SDimitry Andric #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
1604eeddc0SDimitry Andric #include "clang/AST/Decl.h"
1704eeddc0SDimitry Andric #include "clang/AST/DeclCXX.h"
1804eeddc0SDimitry Andric #include "clang/AST/Type.h"
1904eeddc0SDimitry Andric #include "clang/Analysis/FlowSensitive/DataflowLattice.h"
2004eeddc0SDimitry Andric #include "clang/Analysis/FlowSensitive/Value.h"
2104eeddc0SDimitry Andric #include "llvm/ADT/DenseMap.h"
2204eeddc0SDimitry Andric #include "llvm/ADT/DenseSet.h"
2306c3fb27SDimitry Andric #include "llvm/ADT/MapVector.h"
24bdd1243dSDimitry Andric #include "llvm/ADT/STLExtras.h"
2504eeddc0SDimitry Andric #include "llvm/Support/ErrorHandling.h"
2681ad6265SDimitry Andric #include <cassert>
2704eeddc0SDimitry Andric #include <utility>
2804eeddc0SDimitry Andric 
2904eeddc0SDimitry Andric namespace clang {
3004eeddc0SDimitry Andric namespace dataflow {
3104eeddc0SDimitry Andric 
3281ad6265SDimitry Andric // FIXME: convert these to parameters of the analysis or environment. Current
3381ad6265SDimitry Andric // settings have been experimentaly validated, but only for a particular
3481ad6265SDimitry Andric // analysis.
3581ad6265SDimitry Andric static constexpr int MaxCompositeValueDepth = 3;
3681ad6265SDimitry Andric static constexpr int MaxCompositeValueSize = 1000;
3781ad6265SDimitry Andric 
3804eeddc0SDimitry Andric /// Returns a map consisting of key-value entries that are present in both maps.
395f757f3fSDimitry Andric static llvm::DenseMap<const ValueDecl *, StorageLocation *> intersectDeclToLoc(
405f757f3fSDimitry Andric     const llvm::DenseMap<const ValueDecl *, StorageLocation *> &DeclToLoc1,
415f757f3fSDimitry Andric     const llvm::DenseMap<const ValueDecl *, StorageLocation *> &DeclToLoc2) {
425f757f3fSDimitry Andric   llvm::DenseMap<const ValueDecl *, StorageLocation *> Result;
435f757f3fSDimitry Andric   for (auto &Entry : DeclToLoc1) {
445f757f3fSDimitry Andric     auto It = DeclToLoc2.find(Entry.first);
455f757f3fSDimitry Andric     if (It != DeclToLoc2.end() && Entry.second == It->second)
4604eeddc0SDimitry Andric       Result.insert({Entry.first, Entry.second});
4704eeddc0SDimitry Andric   }
4804eeddc0SDimitry Andric   return Result;
4904eeddc0SDimitry Andric }
5004eeddc0SDimitry Andric 
515f757f3fSDimitry Andric // Whether to consider equivalent two values with an unknown relation.
525f757f3fSDimitry Andric //
535f757f3fSDimitry Andric // FIXME: this function is a hack enabling unsoundness to support
545f757f3fSDimitry Andric // convergence. Once we have widening support for the reference/pointer and
555f757f3fSDimitry Andric // struct built-in models, this should be unconditionally `false` (and inlined
565f757f3fSDimitry Andric // as such at its call sites).
575f757f3fSDimitry Andric static bool equateUnknownValues(Value::Kind K) {
585f757f3fSDimitry Andric   switch (K) {
595f757f3fSDimitry Andric   case Value::Kind::Integer:
605f757f3fSDimitry Andric   case Value::Kind::Pointer:
615f757f3fSDimitry Andric   case Value::Kind::Record:
625f757f3fSDimitry Andric     return true;
635f757f3fSDimitry Andric   default:
645f757f3fSDimitry Andric     return false;
655f757f3fSDimitry Andric   }
665f757f3fSDimitry Andric }
675f757f3fSDimitry Andric 
68bdd1243dSDimitry Andric static bool compareDistinctValues(QualType Type, Value &Val1,
69bdd1243dSDimitry Andric                                   const Environment &Env1, Value &Val2,
7081ad6265SDimitry Andric                                   const Environment &Env2,
7181ad6265SDimitry Andric                                   Environment::ValueModel &Model) {
72bdd1243dSDimitry Andric   // Note: Potentially costly, but, for booleans, we could check whether both
73bdd1243dSDimitry Andric   // can be proven equivalent in their respective environments.
74bdd1243dSDimitry Andric 
75bdd1243dSDimitry Andric   // FIXME: move the reference/pointers logic from `areEquivalentValues` to here
76bdd1243dSDimitry Andric   // and implement separate, join/widen specific handling for
77bdd1243dSDimitry Andric   // reference/pointers.
78bdd1243dSDimitry Andric   switch (Model.compare(Type, Val1, Env1, Val2, Env2)) {
79bdd1243dSDimitry Andric   case ComparisonResult::Same:
80bdd1243dSDimitry Andric     return true;
81bdd1243dSDimitry Andric   case ComparisonResult::Different:
82bdd1243dSDimitry Andric     return false;
83bdd1243dSDimitry Andric   case ComparisonResult::Unknown:
845f757f3fSDimitry Andric     return equateUnknownValues(Val1.getKind());
85bdd1243dSDimitry Andric   }
86bdd1243dSDimitry Andric   llvm_unreachable("All cases covered in switch");
8781ad6265SDimitry Andric }
8881ad6265SDimitry Andric 
8981ad6265SDimitry Andric /// Attempts to merge distinct values `Val1` and `Val2` in `Env1` and `Env2`,
9081ad6265SDimitry Andric /// respectively, of the same type `Type`. Merging generally produces a single
9181ad6265SDimitry Andric /// value that (soundly) approximates the two inputs, although the actual
9281ad6265SDimitry Andric /// meaning depends on `Model`.
93bdd1243dSDimitry Andric static Value *mergeDistinctValues(QualType Type, Value &Val1,
94bdd1243dSDimitry Andric                                   const Environment &Env1, Value &Val2,
9581ad6265SDimitry Andric                                   const Environment &Env2,
9681ad6265SDimitry Andric                                   Environment &MergedEnv,
9781ad6265SDimitry Andric                                   Environment::ValueModel &Model) {
9881ad6265SDimitry Andric   // Join distinct boolean values preserving information about the constraints
9981ad6265SDimitry Andric   // in the respective path conditions.
100bdd1243dSDimitry Andric   if (isa<BoolValue>(&Val1) && isa<BoolValue>(&Val2)) {
101bdd1243dSDimitry Andric     // FIXME: Checking both values should be unnecessary, since they should have
102bdd1243dSDimitry Andric     // a consistent shape.  However, right now we can end up with BoolValue's in
103bdd1243dSDimitry Andric     // integer-typed variables due to our incorrect handling of
104bdd1243dSDimitry Andric     // boolean-to-integer casts (we just propagate the BoolValue to the result
105bdd1243dSDimitry Andric     // of the cast). So, a join can encounter an integer in one branch but a
106bdd1243dSDimitry Andric     // bool in the other.
107bdd1243dSDimitry Andric     // For example:
108bdd1243dSDimitry Andric     // ```
109bdd1243dSDimitry Andric     // std::optional<bool> o;
110bdd1243dSDimitry Andric     // int x;
111bdd1243dSDimitry Andric     // if (o.has_value())
112bdd1243dSDimitry Andric     //   x = o.value();
113bdd1243dSDimitry Andric     // ```
11406c3fb27SDimitry Andric     auto &Expr1 = cast<BoolValue>(Val1).formula();
11506c3fb27SDimitry Andric     auto &Expr2 = cast<BoolValue>(Val2).formula();
11606c3fb27SDimitry Andric     auto &A = MergedEnv.arena();
11706c3fb27SDimitry Andric     auto &MergedVal = A.makeAtomRef(A.makeAtom());
1185f757f3fSDimitry Andric     MergedEnv.assume(
11906c3fb27SDimitry Andric         A.makeOr(A.makeAnd(A.makeAtomRef(Env1.getFlowConditionToken()),
12006c3fb27SDimitry Andric                            A.makeEquals(MergedVal, Expr1)),
12106c3fb27SDimitry Andric                  A.makeAnd(A.makeAtomRef(Env2.getFlowConditionToken()),
12206c3fb27SDimitry Andric                            A.makeEquals(MergedVal, Expr2))));
12306c3fb27SDimitry Andric     return &A.makeBoolValue(MergedVal);
12406c3fb27SDimitry Andric   }
12506c3fb27SDimitry Andric 
12606c3fb27SDimitry Andric   Value *MergedVal = nullptr;
1275f757f3fSDimitry Andric   if (auto *RecordVal1 = dyn_cast<RecordValue>(&Val1)) {
1285f757f3fSDimitry Andric     auto *RecordVal2 = cast<RecordValue>(&Val2);
12906c3fb27SDimitry Andric 
1305f757f3fSDimitry Andric     if (&RecordVal1->getLoc() == &RecordVal2->getLoc())
1315f757f3fSDimitry Andric       // `RecordVal1` and `RecordVal2` may have different properties associated
1325f757f3fSDimitry Andric       // with them. Create a new `RecordValue` with the same location but
1335f757f3fSDimitry Andric       // without any properties so that we soundly approximate both values. If a
1345f757f3fSDimitry Andric       // particular analysis needs to merge properties, it should do so in
1355f757f3fSDimitry Andric       // `DataflowAnalysis::merge()`.
1365f757f3fSDimitry Andric       MergedVal = &MergedEnv.create<RecordValue>(RecordVal1->getLoc());
1375f757f3fSDimitry Andric     else
1385f757f3fSDimitry Andric       // If the locations for the two records are different, need to create a
1395f757f3fSDimitry Andric       // completely new value.
1405f757f3fSDimitry Andric       MergedVal = MergedEnv.createValue(Type);
14106c3fb27SDimitry Andric   } else {
14206c3fb27SDimitry Andric     MergedVal = MergedEnv.createValue(Type);
14381ad6265SDimitry Andric   }
14481ad6265SDimitry Andric 
14581ad6265SDimitry Andric   // FIXME: Consider destroying `MergedValue` immediately if `ValueModel::merge`
14681ad6265SDimitry Andric   // returns false to avoid storing unneeded values in `DACtx`.
14706c3fb27SDimitry Andric   if (MergedVal)
148bdd1243dSDimitry Andric     if (Model.merge(Type, Val1, Env1, Val2, Env2, *MergedVal, MergedEnv))
14981ad6265SDimitry Andric       return MergedVal;
15081ad6265SDimitry Andric 
15181ad6265SDimitry Andric   return nullptr;
15281ad6265SDimitry Andric }
15381ad6265SDimitry Andric 
154bdd1243dSDimitry Andric // When widening does not change `Current`, return value will equal `&Prev`.
155bdd1243dSDimitry Andric static Value &widenDistinctValues(QualType Type, Value &Prev,
156bdd1243dSDimitry Andric                                   const Environment &PrevEnv, Value &Current,
157bdd1243dSDimitry Andric                                   Environment &CurrentEnv,
158bdd1243dSDimitry Andric                                   Environment::ValueModel &Model) {
159bdd1243dSDimitry Andric   // Boolean-model widening.
1605f757f3fSDimitry Andric   if (auto *PrevBool = dyn_cast<BoolValue>(&Prev)) {
1615f757f3fSDimitry Andric     // If previous value was already Top, re-use that to (implicitly) indicate
1625f757f3fSDimitry Andric     // that no change occurred.
163bdd1243dSDimitry Andric     if (isa<TopBoolValue>(Prev))
164bdd1243dSDimitry Andric       return Prev;
1655f757f3fSDimitry Andric 
1665f757f3fSDimitry Andric     // We may need to widen to Top, but before we do so, check whether both
1675f757f3fSDimitry Andric     // values are implied to be either true or false in the current environment.
1685f757f3fSDimitry Andric     // In that case, we can simply return a literal instead.
1695f757f3fSDimitry Andric     auto &CurBool = cast<BoolValue>(Current);
1705f757f3fSDimitry Andric     bool TruePrev = PrevEnv.proves(PrevBool->formula());
1715f757f3fSDimitry Andric     bool TrueCur = CurrentEnv.proves(CurBool.formula());
1725f757f3fSDimitry Andric     if (TruePrev && TrueCur)
1735f757f3fSDimitry Andric       return CurrentEnv.getBoolLiteralValue(true);
1745f757f3fSDimitry Andric     if (!TruePrev && !TrueCur &&
1755f757f3fSDimitry Andric         PrevEnv.proves(PrevEnv.arena().makeNot(PrevBool->formula())) &&
1765f757f3fSDimitry Andric         CurrentEnv.proves(CurrentEnv.arena().makeNot(CurBool.formula())))
1775f757f3fSDimitry Andric       return CurrentEnv.getBoolLiteralValue(false);
1785f757f3fSDimitry Andric 
179bdd1243dSDimitry Andric     return CurrentEnv.makeTopBoolValue();
180bdd1243dSDimitry Andric   }
18181ad6265SDimitry Andric 
182bdd1243dSDimitry Andric   // FIXME: Add other built-in model widening.
183bdd1243dSDimitry Andric 
184bdd1243dSDimitry Andric   // Custom-model widening.
185bdd1243dSDimitry Andric   if (auto *W = Model.widen(Type, Prev, PrevEnv, Current, CurrentEnv))
186bdd1243dSDimitry Andric     return *W;
187bdd1243dSDimitry Andric 
1885f757f3fSDimitry Andric   return equateUnknownValues(Prev.getKind()) ? Prev : Current;
1895f757f3fSDimitry Andric }
1905f757f3fSDimitry Andric 
1915f757f3fSDimitry Andric // Returns whether the values in `Map1` and `Map2` compare equal for those
1925f757f3fSDimitry Andric // keys that `Map1` and `Map2` have in common.
1935f757f3fSDimitry Andric template <typename Key>
1945f757f3fSDimitry Andric bool compareKeyToValueMaps(const llvm::MapVector<Key, Value *> &Map1,
1955f757f3fSDimitry Andric                            const llvm::MapVector<Key, Value *> &Map2,
1965f757f3fSDimitry Andric                            const Environment &Env1, const Environment &Env2,
1975f757f3fSDimitry Andric                            Environment::ValueModel &Model) {
1985f757f3fSDimitry Andric   for (auto &Entry : Map1) {
1995f757f3fSDimitry Andric     Key K = Entry.first;
2005f757f3fSDimitry Andric     assert(K != nullptr);
2015f757f3fSDimitry Andric 
2025f757f3fSDimitry Andric     Value *Val = Entry.second;
2035f757f3fSDimitry Andric     assert(Val != nullptr);
2045f757f3fSDimitry Andric 
2055f757f3fSDimitry Andric     auto It = Map2.find(K);
2065f757f3fSDimitry Andric     if (It == Map2.end())
2075f757f3fSDimitry Andric       continue;
2085f757f3fSDimitry Andric     assert(It->second != nullptr);
2095f757f3fSDimitry Andric 
2105f757f3fSDimitry Andric     if (!areEquivalentValues(*Val, *It->second) &&
2115f757f3fSDimitry Andric         !compareDistinctValues(K->getType(), *Val, Env1, *It->second, Env2,
2125f757f3fSDimitry Andric                                Model))
2135f757f3fSDimitry Andric       return false;
2145f757f3fSDimitry Andric   }
2155f757f3fSDimitry Andric 
2165f757f3fSDimitry Andric   return true;
2175f757f3fSDimitry Andric }
2185f757f3fSDimitry Andric 
2195f757f3fSDimitry Andric // Perform a join on two `LocToVal` maps.
2205f757f3fSDimitry Andric static llvm::MapVector<const StorageLocation *, Value *>
2215f757f3fSDimitry Andric joinLocToVal(const llvm::MapVector<const StorageLocation *, Value *> &LocToVal,
2225f757f3fSDimitry Andric              const llvm::MapVector<const StorageLocation *, Value *> &LocToVal2,
2235f757f3fSDimitry Andric              const Environment &Env1, const Environment &Env2,
2245f757f3fSDimitry Andric              Environment &JoinedEnv, Environment::ValueModel &Model) {
2255f757f3fSDimitry Andric   llvm::MapVector<const StorageLocation *, Value *> Result;
2265f757f3fSDimitry Andric   for (auto &Entry : LocToVal) {
2275f757f3fSDimitry Andric     const StorageLocation *Loc = Entry.first;
2285f757f3fSDimitry Andric     assert(Loc != nullptr);
2295f757f3fSDimitry Andric 
2305f757f3fSDimitry Andric     Value *Val = Entry.second;
2315f757f3fSDimitry Andric     assert(Val != nullptr);
2325f757f3fSDimitry Andric 
2335f757f3fSDimitry Andric     auto It = LocToVal2.find(Loc);
2345f757f3fSDimitry Andric     if (It == LocToVal2.end())
2355f757f3fSDimitry Andric       continue;
2365f757f3fSDimitry Andric     assert(It->second != nullptr);
2375f757f3fSDimitry Andric 
2385f757f3fSDimitry Andric     if (areEquivalentValues(*Val, *It->second)) {
2395f757f3fSDimitry Andric       Result.insert({Loc, Val});
2405f757f3fSDimitry Andric       continue;
2415f757f3fSDimitry Andric     }
2425f757f3fSDimitry Andric 
2435f757f3fSDimitry Andric     if (Value *MergedVal = mergeDistinctValues(
2445f757f3fSDimitry Andric             Loc->getType(), *Val, Env1, *It->second, Env2, JoinedEnv, Model)) {
2455f757f3fSDimitry Andric       Result.insert({Loc, MergedVal});
2465f757f3fSDimitry Andric     }
2475f757f3fSDimitry Andric   }
2485f757f3fSDimitry Andric 
2495f757f3fSDimitry Andric   return Result;
2505f757f3fSDimitry Andric }
2515f757f3fSDimitry Andric 
2525f757f3fSDimitry Andric // Perform widening on either `LocToVal` or `ExprToVal`. `Key` must be either
2535f757f3fSDimitry Andric // `const StorageLocation *` or `const Expr *`.
2545f757f3fSDimitry Andric template <typename Key>
2555f757f3fSDimitry Andric llvm::MapVector<Key, Value *>
2565f757f3fSDimitry Andric widenKeyToValueMap(const llvm::MapVector<Key, Value *> &CurMap,
2575f757f3fSDimitry Andric                    const llvm::MapVector<Key, Value *> &PrevMap,
2585f757f3fSDimitry Andric                    Environment &CurEnv, const Environment &PrevEnv,
2595f757f3fSDimitry Andric                    Environment::ValueModel &Model, LatticeJoinEffect &Effect) {
2605f757f3fSDimitry Andric   llvm::MapVector<Key, Value *> WidenedMap;
2615f757f3fSDimitry Andric   for (auto &Entry : CurMap) {
2625f757f3fSDimitry Andric     Key K = Entry.first;
2635f757f3fSDimitry Andric     assert(K != nullptr);
2645f757f3fSDimitry Andric 
2655f757f3fSDimitry Andric     Value *Val = Entry.second;
2665f757f3fSDimitry Andric     assert(Val != nullptr);
2675f757f3fSDimitry Andric 
2685f757f3fSDimitry Andric     auto PrevIt = PrevMap.find(K);
2695f757f3fSDimitry Andric     if (PrevIt == PrevMap.end())
2705f757f3fSDimitry Andric       continue;
2715f757f3fSDimitry Andric     assert(PrevIt->second != nullptr);
2725f757f3fSDimitry Andric 
2735f757f3fSDimitry Andric     if (areEquivalentValues(*Val, *PrevIt->second)) {
2745f757f3fSDimitry Andric       WidenedMap.insert({K, Val});
2755f757f3fSDimitry Andric       continue;
2765f757f3fSDimitry Andric     }
2775f757f3fSDimitry Andric 
2785f757f3fSDimitry Andric     Value &WidenedVal = widenDistinctValues(K->getType(), *PrevIt->second,
2795f757f3fSDimitry Andric                                             PrevEnv, *Val, CurEnv, Model);
2805f757f3fSDimitry Andric     WidenedMap.insert({K, &WidenedVal});
2815f757f3fSDimitry Andric     if (&WidenedVal != PrevIt->second)
2825f757f3fSDimitry Andric       Effect = LatticeJoinEffect::Changed;
2835f757f3fSDimitry Andric   }
2845f757f3fSDimitry Andric 
2855f757f3fSDimitry Andric   return WidenedMap;
28681ad6265SDimitry Andric }
28781ad6265SDimitry Andric 
28881ad6265SDimitry Andric /// Initializes a global storage value.
289bdd1243dSDimitry Andric static void insertIfGlobal(const Decl &D,
290bdd1243dSDimitry Andric                            llvm::DenseSet<const VarDecl *> &Vars) {
29181ad6265SDimitry Andric   if (auto *V = dyn_cast<VarDecl>(&D))
292bdd1243dSDimitry Andric     if (V->hasGlobalStorage())
293bdd1243dSDimitry Andric       Vars.insert(V);
29481ad6265SDimitry Andric }
29581ad6265SDimitry Andric 
29606c3fb27SDimitry Andric static void insertIfFunction(const Decl &D,
29706c3fb27SDimitry Andric                              llvm::DenseSet<const FunctionDecl *> &Funcs) {
29806c3fb27SDimitry Andric   if (auto *FD = dyn_cast<FunctionDecl>(&D))
29906c3fb27SDimitry Andric     Funcs.insert(FD);
30006c3fb27SDimitry Andric }
30106c3fb27SDimitry Andric 
3025f757f3fSDimitry Andric static MemberExpr *getMemberForAccessor(const CXXMemberCallExpr &C) {
3035f757f3fSDimitry Andric   // Use getCalleeDecl instead of getMethodDecl in order to handle
3045f757f3fSDimitry Andric   // pointer-to-member calls.
3055f757f3fSDimitry Andric   const auto *MethodDecl = dyn_cast_or_null<CXXMethodDecl>(C.getCalleeDecl());
3065f757f3fSDimitry Andric   if (!MethodDecl)
3075f757f3fSDimitry Andric     return nullptr;
3085f757f3fSDimitry Andric   auto *Body = dyn_cast_or_null<CompoundStmt>(MethodDecl->getBody());
3095f757f3fSDimitry Andric   if (!Body || Body->size() != 1)
3105f757f3fSDimitry Andric     return nullptr;
3115f757f3fSDimitry Andric   if (auto *RS = dyn_cast<ReturnStmt>(*Body->body_begin()))
3125f757f3fSDimitry Andric     if (auto *Return = RS->getRetValue())
3135f757f3fSDimitry Andric       return dyn_cast<MemberExpr>(Return->IgnoreParenImpCasts());
3145f757f3fSDimitry Andric   return nullptr;
3155f757f3fSDimitry Andric }
3165f757f3fSDimitry Andric 
31706c3fb27SDimitry Andric static void
31806c3fb27SDimitry Andric getFieldsGlobalsAndFuncs(const Decl &D, FieldSet &Fields,
31906c3fb27SDimitry Andric                          llvm::DenseSet<const VarDecl *> &Vars,
32006c3fb27SDimitry Andric                          llvm::DenseSet<const FunctionDecl *> &Funcs) {
32106c3fb27SDimitry Andric   insertIfGlobal(D, Vars);
32206c3fb27SDimitry Andric   insertIfFunction(D, Funcs);
323bdd1243dSDimitry Andric   if (const auto *Decomp = dyn_cast<DecompositionDecl>(&D))
324bdd1243dSDimitry Andric     for (const auto *B : Decomp->bindings())
325bdd1243dSDimitry Andric       if (auto *ME = dyn_cast_or_null<MemberExpr>(B->getBinding()))
326bdd1243dSDimitry Andric         // FIXME: should we be using `E->getFoundDecl()`?
327bdd1243dSDimitry Andric         if (const auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl()))
328bdd1243dSDimitry Andric           Fields.insert(FD);
32981ad6265SDimitry Andric }
33081ad6265SDimitry Andric 
33106c3fb27SDimitry Andric /// Traverses `S` and inserts into `Fields`, `Vars` and `Funcs` any fields,
33206c3fb27SDimitry Andric /// global variables and functions that are declared in or referenced from
33306c3fb27SDimitry Andric /// sub-statements.
33406c3fb27SDimitry Andric static void
33506c3fb27SDimitry Andric getFieldsGlobalsAndFuncs(const Stmt &S, FieldSet &Fields,
33606c3fb27SDimitry Andric                          llvm::DenseSet<const VarDecl *> &Vars,
33706c3fb27SDimitry Andric                          llvm::DenseSet<const FunctionDecl *> &Funcs) {
338bdd1243dSDimitry Andric   for (auto *Child : S.children())
339bdd1243dSDimitry Andric     if (Child != nullptr)
34006c3fb27SDimitry Andric       getFieldsGlobalsAndFuncs(*Child, Fields, Vars, Funcs);
34106c3fb27SDimitry Andric   if (const auto *DefaultInit = dyn_cast<CXXDefaultInitExpr>(&S))
34206c3fb27SDimitry Andric     getFieldsGlobalsAndFuncs(*DefaultInit->getExpr(), Fields, Vars, Funcs);
343bdd1243dSDimitry Andric 
34481ad6265SDimitry Andric   if (auto *DS = dyn_cast<DeclStmt>(&S)) {
345bdd1243dSDimitry Andric     if (DS->isSingleDecl())
34606c3fb27SDimitry Andric       getFieldsGlobalsAndFuncs(*DS->getSingleDecl(), Fields, Vars, Funcs);
347bdd1243dSDimitry Andric     else
34881ad6265SDimitry Andric       for (auto *D : DS->getDeclGroup())
34906c3fb27SDimitry Andric         getFieldsGlobalsAndFuncs(*D, Fields, Vars, Funcs);
35081ad6265SDimitry Andric   } else if (auto *E = dyn_cast<DeclRefExpr>(&S)) {
35106c3fb27SDimitry Andric     insertIfGlobal(*E->getDecl(), Vars);
35206c3fb27SDimitry Andric     insertIfFunction(*E->getDecl(), Funcs);
3535f757f3fSDimitry Andric   } else if (const auto *C = dyn_cast<CXXMemberCallExpr>(&S)) {
3545f757f3fSDimitry Andric     // If this is a method that returns a member variable but does nothing else,
3555f757f3fSDimitry Andric     // model the field of the return value.
3565f757f3fSDimitry Andric     if (MemberExpr *E = getMemberForAccessor(*C))
3575f757f3fSDimitry Andric       if (const auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl()))
3585f757f3fSDimitry Andric         Fields.insert(FD);
35981ad6265SDimitry Andric   } else if (auto *E = dyn_cast<MemberExpr>(&S)) {
360bdd1243dSDimitry Andric     // FIXME: should we be using `E->getFoundDecl()`?
361bdd1243dSDimitry Andric     const ValueDecl *VD = E->getMemberDecl();
36206c3fb27SDimitry Andric     insertIfGlobal(*VD, Vars);
36306c3fb27SDimitry Andric     insertIfFunction(*VD, Funcs);
364bdd1243dSDimitry Andric     if (const auto *FD = dyn_cast<FieldDecl>(VD))
365bdd1243dSDimitry Andric       Fields.insert(FD);
36606c3fb27SDimitry Andric   } else if (auto *InitList = dyn_cast<InitListExpr>(&S)) {
36706c3fb27SDimitry Andric     if (RecordDecl *RD = InitList->getType()->getAsRecordDecl())
36806c3fb27SDimitry Andric       for (const auto *FD : getFieldsForInitListExpr(RD))
36906c3fb27SDimitry Andric         Fields.insert(FD);
370bdd1243dSDimitry Andric   }
371bdd1243dSDimitry Andric }
372bdd1243dSDimitry Andric 
3735f757f3fSDimitry Andric Environment::Environment(DataflowAnalysisContext &DACtx)
3745f757f3fSDimitry Andric     : DACtx(&DACtx),
3755f757f3fSDimitry Andric       FlowConditionToken(DACtx.arena().makeFlowConditionToken()) {}
3765f757f3fSDimitry Andric 
3775f757f3fSDimitry Andric Environment::Environment(DataflowAnalysisContext &DACtx,
3785f757f3fSDimitry Andric                          const DeclContext &DeclCtx)
3795f757f3fSDimitry Andric     : Environment(DACtx) {
3805f757f3fSDimitry Andric   CallStack.push_back(&DeclCtx);
3815f757f3fSDimitry Andric }
3825f757f3fSDimitry Andric 
3835f757f3fSDimitry Andric void Environment::initialize() {
3845f757f3fSDimitry Andric   const DeclContext *DeclCtx = getDeclCtx();
3855f757f3fSDimitry Andric   if (DeclCtx == nullptr)
3865f757f3fSDimitry Andric     return;
3875f757f3fSDimitry Andric 
3885f757f3fSDimitry Andric   if (const auto *FuncDecl = dyn_cast<FunctionDecl>(DeclCtx)) {
3895f757f3fSDimitry Andric     assert(FuncDecl->getBody() != nullptr);
3905f757f3fSDimitry Andric 
3915f757f3fSDimitry Andric     initFieldsGlobalsAndFuncs(FuncDecl);
3925f757f3fSDimitry Andric 
3935f757f3fSDimitry Andric     for (const auto *ParamDecl : FuncDecl->parameters()) {
3945f757f3fSDimitry Andric       assert(ParamDecl != nullptr);
3955f757f3fSDimitry Andric       setStorageLocation(*ParamDecl, createObject(*ParamDecl, nullptr));
3965f757f3fSDimitry Andric     }
3975f757f3fSDimitry Andric   }
3985f757f3fSDimitry Andric 
3995f757f3fSDimitry Andric   if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(DeclCtx)) {
4005f757f3fSDimitry Andric     auto *Parent = MethodDecl->getParent();
4015f757f3fSDimitry Andric     assert(Parent != nullptr);
4025f757f3fSDimitry Andric 
4035f757f3fSDimitry Andric     if (Parent->isLambda()) {
4045f757f3fSDimitry Andric       for (auto Capture : Parent->captures()) {
4055f757f3fSDimitry Andric         if (Capture.capturesVariable()) {
4065f757f3fSDimitry Andric           const auto *VarDecl = Capture.getCapturedVar();
4075f757f3fSDimitry Andric           assert(VarDecl != nullptr);
4085f757f3fSDimitry Andric           setStorageLocation(*VarDecl, createObject(*VarDecl, nullptr));
4095f757f3fSDimitry Andric         } else if (Capture.capturesThis()) {
4105f757f3fSDimitry Andric           const auto *SurroundingMethodDecl =
4115f757f3fSDimitry Andric               cast<CXXMethodDecl>(DeclCtx->getNonClosureAncestor());
4125f757f3fSDimitry Andric           QualType ThisPointeeType =
4135f757f3fSDimitry Andric               SurroundingMethodDecl->getFunctionObjectParameterType();
4145f757f3fSDimitry Andric           setThisPointeeStorageLocation(
4155f757f3fSDimitry Andric               cast<RecordValue>(createValue(ThisPointeeType))->getLoc());
4165f757f3fSDimitry Andric         }
4175f757f3fSDimitry Andric       }
4185f757f3fSDimitry Andric     } else if (MethodDecl->isImplicitObjectMemberFunction()) {
4195f757f3fSDimitry Andric       QualType ThisPointeeType = MethodDecl->getFunctionObjectParameterType();
4205f757f3fSDimitry Andric       setThisPointeeStorageLocation(
4215f757f3fSDimitry Andric           cast<RecordValue>(createValue(ThisPointeeType))->getLoc());
4225f757f3fSDimitry Andric     }
4235f757f3fSDimitry Andric   }
4245f757f3fSDimitry Andric }
4255f757f3fSDimitry Andric 
426bdd1243dSDimitry Andric // FIXME: Add support for resetting globals after function calls to enable
427bdd1243dSDimitry Andric // the implementation of sound analyses.
42806c3fb27SDimitry Andric void Environment::initFieldsGlobalsAndFuncs(const FunctionDecl *FuncDecl) {
42906c3fb27SDimitry Andric   assert(FuncDecl->getBody() != nullptr);
43006c3fb27SDimitry Andric 
43106c3fb27SDimitry Andric   FieldSet Fields;
43206c3fb27SDimitry Andric   llvm::DenseSet<const VarDecl *> Vars;
43306c3fb27SDimitry Andric   llvm::DenseSet<const FunctionDecl *> Funcs;
43406c3fb27SDimitry Andric 
43506c3fb27SDimitry Andric   // Look for global variable and field references in the
43606c3fb27SDimitry Andric   // constructor-initializers.
43706c3fb27SDimitry Andric   if (const auto *CtorDecl = dyn_cast<CXXConstructorDecl>(FuncDecl)) {
43806c3fb27SDimitry Andric     for (const auto *Init : CtorDecl->inits()) {
43906c3fb27SDimitry Andric       if (Init->isMemberInitializer()) {
44006c3fb27SDimitry Andric         Fields.insert(Init->getMember());
44106c3fb27SDimitry Andric       } else if (Init->isIndirectMemberInitializer()) {
44206c3fb27SDimitry Andric         for (const auto *I : Init->getIndirectMember()->chain())
44306c3fb27SDimitry Andric           Fields.insert(cast<FieldDecl>(I));
44406c3fb27SDimitry Andric       }
44506c3fb27SDimitry Andric       const Expr *E = Init->getInit();
44606c3fb27SDimitry Andric       assert(E != nullptr);
44706c3fb27SDimitry Andric       getFieldsGlobalsAndFuncs(*E, Fields, Vars, Funcs);
44806c3fb27SDimitry Andric     }
44906c3fb27SDimitry Andric     // Add all fields mentioned in default member initializers.
45006c3fb27SDimitry Andric     for (const FieldDecl *F : CtorDecl->getParent()->fields())
45106c3fb27SDimitry Andric       if (const auto *I = F->getInClassInitializer())
45206c3fb27SDimitry Andric           getFieldsGlobalsAndFuncs(*I, Fields, Vars, Funcs);
45306c3fb27SDimitry Andric   }
45406c3fb27SDimitry Andric   getFieldsGlobalsAndFuncs(*FuncDecl->getBody(), Fields, Vars, Funcs);
45506c3fb27SDimitry Andric 
45606c3fb27SDimitry Andric   // These have to be added before the lines that follow to ensure that
45706c3fb27SDimitry Andric   // `create*` work correctly for structs.
45806c3fb27SDimitry Andric   DACtx->addModeledFields(Fields);
45906c3fb27SDimitry Andric 
460bdd1243dSDimitry Andric   for (const VarDecl *D : Vars) {
46106c3fb27SDimitry Andric     if (getStorageLocation(*D) != nullptr)
462bdd1243dSDimitry Andric       continue;
46306c3fb27SDimitry Andric 
46406c3fb27SDimitry Andric     setStorageLocation(*D, createObject(*D));
46506c3fb27SDimitry Andric   }
46606c3fb27SDimitry Andric 
46706c3fb27SDimitry Andric   for (const FunctionDecl *FD : Funcs) {
46806c3fb27SDimitry Andric     if (getStorageLocation(*FD) != nullptr)
46906c3fb27SDimitry Andric       continue;
47006c3fb27SDimitry Andric     auto &Loc = createStorageLocation(FD->getType());
47106c3fb27SDimitry Andric     setStorageLocation(*FD, Loc);
47281ad6265SDimitry Andric   }
47381ad6265SDimitry Andric }
47481ad6265SDimitry Andric 
47506c3fb27SDimitry Andric Environment Environment::fork() const {
47606c3fb27SDimitry Andric   Environment Copy(*this);
47706c3fb27SDimitry Andric   Copy.FlowConditionToken = DACtx->forkFlowCondition(FlowConditionToken);
47806c3fb27SDimitry Andric   return Copy;
4791fd87a68SDimitry Andric }
4801fd87a68SDimitry Andric 
481bdd1243dSDimitry Andric bool Environment::canDescend(unsigned MaxDepth,
482bdd1243dSDimitry Andric                              const DeclContext *Callee) const {
483bdd1243dSDimitry Andric   return CallStack.size() <= MaxDepth && !llvm::is_contained(CallStack, Callee);
48404eeddc0SDimitry Andric }
48504eeddc0SDimitry Andric 
486972a253aSDimitry Andric Environment Environment::pushCall(const CallExpr *Call) const {
487972a253aSDimitry Andric   Environment Env(*this);
488972a253aSDimitry Andric 
489bdd1243dSDimitry Andric   if (const auto *MethodCall = dyn_cast<CXXMemberCallExpr>(Call)) {
490bdd1243dSDimitry Andric     if (const Expr *Arg = MethodCall->getImplicitObjectArgument()) {
491bdd1243dSDimitry Andric       if (!isa<CXXThisExpr>(Arg))
4925f757f3fSDimitry Andric           Env.ThisPointeeLoc =
4935f757f3fSDimitry Andric               cast<RecordStorageLocation>(getStorageLocation(*Arg));
494bdd1243dSDimitry Andric       // Otherwise (when the argument is `this`), retain the current
495bdd1243dSDimitry Andric       // environment's `ThisPointeeLoc`.
496bdd1243dSDimitry Andric     }
497bdd1243dSDimitry Andric   }
498972a253aSDimitry Andric 
499bdd1243dSDimitry Andric   Env.pushCallInternal(Call->getDirectCallee(),
500bdd1243dSDimitry Andric                        llvm::ArrayRef(Call->getArgs(), Call->getNumArgs()));
501bdd1243dSDimitry Andric 
502bdd1243dSDimitry Andric   return Env;
503bdd1243dSDimitry Andric }
504bdd1243dSDimitry Andric 
505bdd1243dSDimitry Andric Environment Environment::pushCall(const CXXConstructExpr *Call) const {
506bdd1243dSDimitry Andric   Environment Env(*this);
507bdd1243dSDimitry Andric 
50806c3fb27SDimitry Andric   Env.ThisPointeeLoc = &Env.getResultObjectLocation(*Call);
509bdd1243dSDimitry Andric 
510bdd1243dSDimitry Andric   Env.pushCallInternal(Call->getConstructor(),
511bdd1243dSDimitry Andric                        llvm::ArrayRef(Call->getArgs(), Call->getNumArgs()));
512bdd1243dSDimitry Andric 
513bdd1243dSDimitry Andric   return Env;
514bdd1243dSDimitry Andric }
515bdd1243dSDimitry Andric 
516bdd1243dSDimitry Andric void Environment::pushCallInternal(const FunctionDecl *FuncDecl,
517bdd1243dSDimitry Andric                                    ArrayRef<const Expr *> Args) {
51806c3fb27SDimitry Andric   // Canonicalize to the definition of the function. This ensures that we're
51906c3fb27SDimitry Andric   // putting arguments into the same `ParamVarDecl`s` that the callee will later
52006c3fb27SDimitry Andric   // be retrieving them from.
52106c3fb27SDimitry Andric   assert(FuncDecl->getDefinition() != nullptr);
52206c3fb27SDimitry Andric   FuncDecl = FuncDecl->getDefinition();
52306c3fb27SDimitry Andric 
524bdd1243dSDimitry Andric   CallStack.push_back(FuncDecl);
525bdd1243dSDimitry Andric 
52606c3fb27SDimitry Andric   initFieldsGlobalsAndFuncs(FuncDecl);
527bdd1243dSDimitry Andric 
528bdd1243dSDimitry Andric   const auto *ParamIt = FuncDecl->param_begin();
529972a253aSDimitry Andric 
530972a253aSDimitry Andric   // FIXME: Parameters don't always map to arguments 1:1; examples include
531972a253aSDimitry Andric   // overloaded operators implemented as member functions, and parameter packs.
532bdd1243dSDimitry Andric   for (unsigned ArgIndex = 0; ArgIndex < Args.size(); ++ParamIt, ++ArgIndex) {
533972a253aSDimitry Andric     assert(ParamIt != FuncDecl->param_end());
534972a253aSDimitry Andric     const VarDecl *Param = *ParamIt;
53506c3fb27SDimitry Andric     setStorageLocation(*Param, createObject(*Param, Args[ArgIndex]));
536bdd1243dSDimitry Andric   }
537972a253aSDimitry Andric }
538972a253aSDimitry Andric 
53906c3fb27SDimitry Andric void Environment::popCall(const CallExpr *Call, const Environment &CalleeEnv) {
5405f757f3fSDimitry Andric   // We ignore some entries of `CalleeEnv`:
5415f757f3fSDimitry Andric   // - `DACtx` because is already the same in both
5425f757f3fSDimitry Andric   // - We don't want the callee's `DeclCtx`, `ReturnVal`, `ReturnLoc` or
5435f757f3fSDimitry Andric   //   `ThisPointeeLoc` because they don't apply to us.
5445f757f3fSDimitry Andric   // - `DeclToLoc`, `ExprToLoc`, and `ExprToVal` capture information from the
5455f757f3fSDimitry Andric   //   callee's local scope, so when popping that scope, we do not propagate
5465f757f3fSDimitry Andric   //   the maps.
547bdd1243dSDimitry Andric   this->LocToVal = std::move(CalleeEnv.LocToVal);
548bdd1243dSDimitry Andric   this->FlowConditionToken = std::move(CalleeEnv.FlowConditionToken);
54906c3fb27SDimitry Andric 
55006c3fb27SDimitry Andric   if (Call->isGLValue()) {
55106c3fb27SDimitry Andric     if (CalleeEnv.ReturnLoc != nullptr)
5525f757f3fSDimitry Andric       setStorageLocation(*Call, *CalleeEnv.ReturnLoc);
55306c3fb27SDimitry Andric   } else if (!Call->getType()->isVoidType()) {
55406c3fb27SDimitry Andric     if (CalleeEnv.ReturnVal != nullptr)
5555f757f3fSDimitry Andric       setValue(*Call, *CalleeEnv.ReturnVal);
55606c3fb27SDimitry Andric   }
55706c3fb27SDimitry Andric }
55806c3fb27SDimitry Andric 
55906c3fb27SDimitry Andric void Environment::popCall(const CXXConstructExpr *Call,
56006c3fb27SDimitry Andric                           const Environment &CalleeEnv) {
56106c3fb27SDimitry Andric   // See also comment in `popCall(const CallExpr *, const Environment &)` above.
56206c3fb27SDimitry Andric   this->LocToVal = std::move(CalleeEnv.LocToVal);
56306c3fb27SDimitry Andric   this->FlowConditionToken = std::move(CalleeEnv.FlowConditionToken);
56406c3fb27SDimitry Andric 
56506c3fb27SDimitry Andric   if (Value *Val = CalleeEnv.getValue(*CalleeEnv.ThisPointeeLoc)) {
5665f757f3fSDimitry Andric     setValue(*Call, *Val);
56706c3fb27SDimitry Andric   }
568972a253aSDimitry Andric }
569972a253aSDimitry Andric 
5701fd87a68SDimitry Andric bool Environment::equivalentTo(const Environment &Other,
5711fd87a68SDimitry Andric                                Environment::ValueModel &Model) const {
57204eeddc0SDimitry Andric   assert(DACtx == Other.DACtx);
5731fd87a68SDimitry Andric 
57406c3fb27SDimitry Andric   if (ReturnVal != Other.ReturnVal)
57506c3fb27SDimitry Andric     return false;
57606c3fb27SDimitry Andric 
577bdd1243dSDimitry Andric   if (ReturnLoc != Other.ReturnLoc)
578bdd1243dSDimitry Andric     return false;
579bdd1243dSDimitry Andric 
580bdd1243dSDimitry Andric   if (ThisPointeeLoc != Other.ThisPointeeLoc)
581bdd1243dSDimitry Andric     return false;
582bdd1243dSDimitry Andric 
5831fd87a68SDimitry Andric   if (DeclToLoc != Other.DeclToLoc)
5841fd87a68SDimitry Andric     return false;
5851fd87a68SDimitry Andric 
5861fd87a68SDimitry Andric   if (ExprToLoc != Other.ExprToLoc)
5871fd87a68SDimitry Andric     return false;
5881fd87a68SDimitry Andric 
5895f757f3fSDimitry Andric   if (!compareKeyToValueMaps(ExprToVal, Other.ExprToVal, *this, Other, Model))
5901fd87a68SDimitry Andric     return false;
5915f757f3fSDimitry Andric 
5925f757f3fSDimitry Andric   if (!compareKeyToValueMaps(LocToVal, Other.LocToVal, *this, Other, Model))
5935f757f3fSDimitry Andric     return false;
5941fd87a68SDimitry Andric 
5951fd87a68SDimitry Andric   return true;
59604eeddc0SDimitry Andric }
59704eeddc0SDimitry Andric 
598bdd1243dSDimitry Andric LatticeJoinEffect Environment::widen(const Environment &PrevEnv,
599bdd1243dSDimitry Andric                                      Environment::ValueModel &Model) {
600bdd1243dSDimitry Andric   assert(DACtx == PrevEnv.DACtx);
60106c3fb27SDimitry Andric   assert(ReturnVal == PrevEnv.ReturnVal);
602bdd1243dSDimitry Andric   assert(ReturnLoc == PrevEnv.ReturnLoc);
603bdd1243dSDimitry Andric   assert(ThisPointeeLoc == PrevEnv.ThisPointeeLoc);
604bdd1243dSDimitry Andric   assert(CallStack == PrevEnv.CallStack);
605bdd1243dSDimitry Andric 
606bdd1243dSDimitry Andric   auto Effect = LatticeJoinEffect::Unchanged;
607bdd1243dSDimitry Andric 
608bdd1243dSDimitry Andric   // By the API, `PrevEnv` is a previous version of the environment for the same
609bdd1243dSDimitry Andric   // block, so we have some guarantees about its shape. In particular, it will
610bdd1243dSDimitry Andric   // be the result of a join or widen operation on previous values for this
6115f757f3fSDimitry Andric   // block. For `DeclToLoc`, `ExprToVal`, and `ExprToLoc`, join guarantees that
6125f757f3fSDimitry Andric   // these maps are subsets of the maps in `PrevEnv`. So, as long as we maintain
6135f757f3fSDimitry Andric   // this property here, we don't need change their current values to widen.
614bdd1243dSDimitry Andric   assert(DeclToLoc.size() <= PrevEnv.DeclToLoc.size());
6155f757f3fSDimitry Andric   assert(ExprToVal.size() <= PrevEnv.ExprToVal.size());
616bdd1243dSDimitry Andric   assert(ExprToLoc.size() <= PrevEnv.ExprToLoc.size());
617bdd1243dSDimitry Andric 
6185f757f3fSDimitry Andric   ExprToVal = widenKeyToValueMap(ExprToVal, PrevEnv.ExprToVal, *this, PrevEnv,
6195f757f3fSDimitry Andric                                  Model, Effect);
620bdd1243dSDimitry Andric 
6215f757f3fSDimitry Andric   LocToVal = widenKeyToValueMap(LocToVal, PrevEnv.LocToVal, *this, PrevEnv,
6225f757f3fSDimitry Andric                                 Model, Effect);
623bdd1243dSDimitry Andric   if (DeclToLoc.size() != PrevEnv.DeclToLoc.size() ||
624bdd1243dSDimitry Andric       ExprToLoc.size() != PrevEnv.ExprToLoc.size() ||
6255f757f3fSDimitry Andric       ExprToVal.size() != PrevEnv.ExprToVal.size() ||
62606c3fb27SDimitry Andric       LocToVal.size() != PrevEnv.LocToVal.size())
627bdd1243dSDimitry Andric     Effect = LatticeJoinEffect::Changed;
628bdd1243dSDimitry Andric 
629bdd1243dSDimitry Andric   return Effect;
630bdd1243dSDimitry Andric }
631bdd1243dSDimitry Andric 
63206c3fb27SDimitry Andric Environment Environment::join(const Environment &EnvA, const Environment &EnvB,
6331fd87a68SDimitry Andric                               Environment::ValueModel &Model) {
63406c3fb27SDimitry Andric   assert(EnvA.DACtx == EnvB.DACtx);
63506c3fb27SDimitry Andric   assert(EnvA.ThisPointeeLoc == EnvB.ThisPointeeLoc);
63606c3fb27SDimitry Andric   assert(EnvA.CallStack == EnvB.CallStack);
63704eeddc0SDimitry Andric 
63806c3fb27SDimitry Andric   Environment JoinedEnv(*EnvA.DACtx);
63904eeddc0SDimitry Andric 
64006c3fb27SDimitry Andric   JoinedEnv.CallStack = EnvA.CallStack;
64106c3fb27SDimitry Andric   JoinedEnv.ThisPointeeLoc = EnvA.ThisPointeeLoc;
64281ad6265SDimitry Andric 
64306c3fb27SDimitry Andric   if (EnvA.ReturnVal == nullptr || EnvB.ReturnVal == nullptr) {
64406c3fb27SDimitry Andric     // `ReturnVal` might not always get set -- for example if we have a return
64506c3fb27SDimitry Andric     // statement of the form `return some_other_func()` and we decide not to
64606c3fb27SDimitry Andric     // analyze `some_other_func()`.
64706c3fb27SDimitry Andric     // In this case, we can't say anything about the joined return value -- we
64806c3fb27SDimitry Andric     // don't simply want to propagate the return value that we do have, because
64906c3fb27SDimitry Andric     // it might not be the correct one.
65006c3fb27SDimitry Andric     // This occurs for example in the test `ContextSensitiveMutualRecursion`.
65106c3fb27SDimitry Andric     JoinedEnv.ReturnVal = nullptr;
65206c3fb27SDimitry Andric   } else if (areEquivalentValues(*EnvA.ReturnVal, *EnvB.ReturnVal)) {
65306c3fb27SDimitry Andric     JoinedEnv.ReturnVal = EnvA.ReturnVal;
65406c3fb27SDimitry Andric   } else {
65506c3fb27SDimitry Andric     assert(!EnvA.CallStack.empty());
65606c3fb27SDimitry Andric     // FIXME: Make `CallStack` a vector of `FunctionDecl` so we don't need this
65706c3fb27SDimitry Andric     // cast.
65806c3fb27SDimitry Andric     auto *Func = dyn_cast<FunctionDecl>(EnvA.CallStack.back());
65906c3fb27SDimitry Andric     assert(Func != nullptr);
66006c3fb27SDimitry Andric     if (Value *MergedVal =
66106c3fb27SDimitry Andric             mergeDistinctValues(Func->getReturnType(), *EnvA.ReturnVal, EnvA,
66206c3fb27SDimitry Andric                                 *EnvB.ReturnVal, EnvB, JoinedEnv, Model))
66306c3fb27SDimitry Andric       JoinedEnv.ReturnVal = MergedVal;
66406c3fb27SDimitry Andric   }
665bdd1243dSDimitry Andric 
66606c3fb27SDimitry Andric   if (EnvA.ReturnLoc == EnvB.ReturnLoc)
66706c3fb27SDimitry Andric     JoinedEnv.ReturnLoc = EnvA.ReturnLoc;
66806c3fb27SDimitry Andric   else
66906c3fb27SDimitry Andric     JoinedEnv.ReturnLoc = nullptr;
67004eeddc0SDimitry Andric 
6715f757f3fSDimitry Andric   JoinedEnv.DeclToLoc = intersectDeclToLoc(EnvA.DeclToLoc, EnvB.DeclToLoc);
67281ad6265SDimitry Andric 
673bdd1243dSDimitry Andric   // FIXME: update join to detect backedges and simplify the flow condition
674bdd1243dSDimitry Andric   // accordingly.
67506c3fb27SDimitry Andric   JoinedEnv.FlowConditionToken = EnvA.DACtx->joinFlowConditions(
67606c3fb27SDimitry Andric       EnvA.FlowConditionToken, EnvB.FlowConditionToken);
67781ad6265SDimitry Andric 
6785f757f3fSDimitry Andric   JoinedEnv.LocToVal =
6795f757f3fSDimitry Andric       joinLocToVal(EnvA.LocToVal, EnvB.LocToVal, EnvA, EnvB, JoinedEnv, Model);
68004eeddc0SDimitry Andric 
6815f757f3fSDimitry Andric   // We intentionally leave `JoinedEnv.ExprToLoc` and `JoinedEnv.ExprToVal`
6825f757f3fSDimitry Andric   // empty, as we never need to access entries in these maps outside of the
6835f757f3fSDimitry Andric   // basic block that sets them.
68404eeddc0SDimitry Andric 
68506c3fb27SDimitry Andric   return JoinedEnv;
68604eeddc0SDimitry Andric }
68704eeddc0SDimitry Andric 
68804eeddc0SDimitry Andric StorageLocation &Environment::createStorageLocation(QualType Type) {
689bdd1243dSDimitry Andric   return DACtx->createStorageLocation(Type);
69004eeddc0SDimitry Andric }
69104eeddc0SDimitry Andric 
6925f757f3fSDimitry Andric StorageLocation &Environment::createStorageLocation(const ValueDecl &D) {
69304eeddc0SDimitry Andric   // Evaluated declarations are always assigned the same storage locations to
69404eeddc0SDimitry Andric   // ensure that the environment stabilizes across loop iterations. Storage
69504eeddc0SDimitry Andric   // locations for evaluated declarations are stored in the analysis context.
69681ad6265SDimitry Andric   return DACtx->getStableStorageLocation(D);
69704eeddc0SDimitry Andric }
69804eeddc0SDimitry Andric 
69904eeddc0SDimitry Andric StorageLocation &Environment::createStorageLocation(const Expr &E) {
70004eeddc0SDimitry Andric   // Evaluated expressions are always assigned the same storage locations to
70104eeddc0SDimitry Andric   // ensure that the environment stabilizes across loop iterations. Storage
70204eeddc0SDimitry Andric   // locations for evaluated expressions are stored in the analysis context.
70381ad6265SDimitry Andric   return DACtx->getStableStorageLocation(E);
70404eeddc0SDimitry Andric }
70504eeddc0SDimitry Andric 
70604eeddc0SDimitry Andric void Environment::setStorageLocation(const ValueDecl &D, StorageLocation &Loc) {
70706c3fb27SDimitry Andric   assert(!DeclToLoc.contains(&D));
70804eeddc0SDimitry Andric   DeclToLoc[&D] = &Loc;
70904eeddc0SDimitry Andric }
71004eeddc0SDimitry Andric 
71106c3fb27SDimitry Andric StorageLocation *Environment::getStorageLocation(const ValueDecl &D) const {
71204eeddc0SDimitry Andric   auto It = DeclToLoc.find(&D);
71306c3fb27SDimitry Andric   if (It == DeclToLoc.end())
71406c3fb27SDimitry Andric     return nullptr;
71506c3fb27SDimitry Andric 
71606c3fb27SDimitry Andric   StorageLocation *Loc = It->second;
71706c3fb27SDimitry Andric 
71806c3fb27SDimitry Andric   return Loc;
71904eeddc0SDimitry Andric }
72004eeddc0SDimitry Andric 
7215f757f3fSDimitry Andric void Environment::removeDecl(const ValueDecl &D) { DeclToLoc.erase(&D); }
72204eeddc0SDimitry Andric 
7235f757f3fSDimitry Andric void Environment::setStorageLocation(const Expr &E, StorageLocation &Loc) {
72406c3fb27SDimitry Andric   // `DeclRefExpr`s to builtin function types aren't glvalues, for some reason,
72506c3fb27SDimitry Andric   // but we still want to be able to associate a `StorageLocation` with them,
72606c3fb27SDimitry Andric   // so allow these as an exception.
72706c3fb27SDimitry Andric   assert(E.isGLValue() ||
72806c3fb27SDimitry Andric          E.getType()->isSpecificBuiltinType(BuiltinType::BuiltinFn));
729*cb14a3feSDimitry Andric   const Expr &CanonE = ignoreCFGOmittedNodes(E);
730*cb14a3feSDimitry Andric   assert(!ExprToLoc.contains(&CanonE));
731*cb14a3feSDimitry Andric   ExprToLoc[&CanonE] = &Loc;
73206c3fb27SDimitry Andric }
73306c3fb27SDimitry Andric 
7345f757f3fSDimitry Andric StorageLocation *Environment::getStorageLocation(const Expr &E) const {
7355f757f3fSDimitry Andric   // See comment in `setStorageLocation()`.
73606c3fb27SDimitry Andric   assert(E.isGLValue() ||
73706c3fb27SDimitry Andric          E.getType()->isSpecificBuiltinType(BuiltinType::BuiltinFn));
738*cb14a3feSDimitry Andric   auto It = ExprToLoc.find(&ignoreCFGOmittedNodes(E));
739*cb14a3feSDimitry Andric   return It == ExprToLoc.end() ? nullptr : &*It->second;
740*cb14a3feSDimitry Andric }
741*cb14a3feSDimitry Andric 
742*cb14a3feSDimitry Andric // Returns whether a prvalue of record type is the one that originally
743*cb14a3feSDimitry Andric // constructs the object (i.e. it doesn't propagate it from one of its
744*cb14a3feSDimitry Andric // children).
745*cb14a3feSDimitry Andric static bool isOriginalRecordConstructor(const Expr &RecordPRValue) {
746*cb14a3feSDimitry Andric   if (auto *Init = dyn_cast<InitListExpr>(&RecordPRValue))
747*cb14a3feSDimitry Andric     return !Init->isSemanticForm() || !Init->isTransparent();
748*cb14a3feSDimitry Andric   return isa<CXXConstructExpr>(RecordPRValue) || isa<CallExpr>(RecordPRValue) ||
749*cb14a3feSDimitry Andric          isa<LambdaExpr>(RecordPRValue) ||
750*cb14a3feSDimitry Andric          // The framework currently does not propagate the objects created in
751*cb14a3feSDimitry Andric          // the two branches of a `ConditionalOperator` because there is no way
752*cb14a3feSDimitry Andric          // to reconcile their storage locations, which are different. We
753*cb14a3feSDimitry Andric          // therefore claim that the `ConditionalOperator` is the expression
754*cb14a3feSDimitry Andric          // that originally constructs the object.
755*cb14a3feSDimitry Andric          // Ultimately, this will be fixed by propagating locations down from
756*cb14a3feSDimitry Andric          // the result object, rather than up from the original constructor as
757*cb14a3feSDimitry Andric          // we do now (see also the FIXME in the documentation for
758*cb14a3feSDimitry Andric          // `getResultObjectLocation()`).
759*cb14a3feSDimitry Andric          isa<ConditionalOperator>(RecordPRValue);
76006c3fb27SDimitry Andric }
76106c3fb27SDimitry Andric 
7625f757f3fSDimitry Andric RecordStorageLocation &
763*cb14a3feSDimitry Andric Environment::getResultObjectLocation(const Expr &RecordPRValue) const {
76406c3fb27SDimitry Andric   assert(RecordPRValue.getType()->isRecordType());
76506c3fb27SDimitry Andric   assert(RecordPRValue.isPRValue());
76606c3fb27SDimitry Andric 
767*cb14a3feSDimitry Andric   // Returns a storage location that we can use if assertions fail.
768*cb14a3feSDimitry Andric   auto FallbackForAssertFailure =
769*cb14a3feSDimitry Andric       [this, &RecordPRValue]() -> RecordStorageLocation & {
770*cb14a3feSDimitry Andric     return cast<RecordStorageLocation>(
77106c3fb27SDimitry Andric         DACtx->getStableStorageLocation(RecordPRValue));
772*cb14a3feSDimitry Andric   };
773*cb14a3feSDimitry Andric 
774*cb14a3feSDimitry Andric   if (isOriginalRecordConstructor(RecordPRValue)) {
775*cb14a3feSDimitry Andric     auto *Val = cast_or_null<RecordValue>(getValue(RecordPRValue));
776*cb14a3feSDimitry Andric     // The builtin transfer function should have created a `RecordValue` for all
777*cb14a3feSDimitry Andric     // original record constructors.
778*cb14a3feSDimitry Andric     assert(Val);
779*cb14a3feSDimitry Andric     if (!Val)
780*cb14a3feSDimitry Andric       return FallbackForAssertFailure();
781*cb14a3feSDimitry Andric     return Val->getLoc();
782*cb14a3feSDimitry Andric   }
783*cb14a3feSDimitry Andric 
784*cb14a3feSDimitry Andric   // Expression nodes that propagate a record prvalue should have exactly one
785*cb14a3feSDimitry Andric   // child.
786*cb14a3feSDimitry Andric   llvm::SmallVector<const Stmt *> children(RecordPRValue.child_begin(),
787*cb14a3feSDimitry Andric                                            RecordPRValue.child_end());
788*cb14a3feSDimitry Andric   assert(children.size() == 1);
789*cb14a3feSDimitry Andric   if (children.empty())
790*cb14a3feSDimitry Andric     return FallbackForAssertFailure();
791*cb14a3feSDimitry Andric 
792*cb14a3feSDimitry Andric   return getResultObjectLocation(*cast<Expr>(children[0]));
79304eeddc0SDimitry Andric }
79404eeddc0SDimitry Andric 
79581ad6265SDimitry Andric PointerValue &Environment::getOrCreateNullPointerValue(QualType PointeeType) {
79681ad6265SDimitry Andric   return DACtx->getOrCreateNullPointerValue(PointeeType);
79781ad6265SDimitry Andric }
79881ad6265SDimitry Andric 
79904eeddc0SDimitry Andric void Environment::setValue(const StorageLocation &Loc, Value &Val) {
8005f757f3fSDimitry Andric   assert(!isa<RecordValue>(&Val) || &cast<RecordValue>(&Val)->getLoc() == &Loc);
80106c3fb27SDimitry Andric 
80204eeddc0SDimitry Andric   LocToVal[&Loc] = &Val;
80306c3fb27SDimitry Andric }
80406c3fb27SDimitry Andric 
8055f757f3fSDimitry Andric void Environment::setValue(const Expr &E, Value &Val) {
806*cb14a3feSDimitry Andric   if (auto *RecordVal = dyn_cast<RecordValue>(&Val)) {
807*cb14a3feSDimitry Andric     assert(isOriginalRecordConstructor(E) ||
808*cb14a3feSDimitry Andric            &RecordVal->getLoc() == &getResultObjectLocation(E));
809*cb14a3feSDimitry Andric   }
810*cb14a3feSDimitry Andric 
81106c3fb27SDimitry Andric   assert(E.isPRValue());
8125f757f3fSDimitry Andric   ExprToVal[&E] = &Val;
81304eeddc0SDimitry Andric }
81404eeddc0SDimitry Andric 
81504eeddc0SDimitry Andric Value *Environment::getValue(const StorageLocation &Loc) const {
81606c3fb27SDimitry Andric   return LocToVal.lookup(&Loc);
81704eeddc0SDimitry Andric }
81804eeddc0SDimitry Andric 
81906c3fb27SDimitry Andric Value *Environment::getValue(const ValueDecl &D) const {
82006c3fb27SDimitry Andric   auto *Loc = getStorageLocation(D);
82104eeddc0SDimitry Andric   if (Loc == nullptr)
82204eeddc0SDimitry Andric     return nullptr;
82304eeddc0SDimitry Andric   return getValue(*Loc);
82404eeddc0SDimitry Andric }
82504eeddc0SDimitry Andric 
8265f757f3fSDimitry Andric Value *Environment::getValue(const Expr &E) const {
8275f757f3fSDimitry Andric   if (E.isPRValue()) {
8285f757f3fSDimitry Andric     auto It = ExprToVal.find(&ignoreCFGOmittedNodes(E));
8295f757f3fSDimitry Andric     return It == ExprToVal.end() ? nullptr : It->second;
83004eeddc0SDimitry Andric   }
83104eeddc0SDimitry Andric 
8325f757f3fSDimitry Andric   auto It = ExprToLoc.find(&ignoreCFGOmittedNodes(E));
8335f757f3fSDimitry Andric   if (It == ExprToLoc.end())
8345f757f3fSDimitry Andric     return nullptr;
8355f757f3fSDimitry Andric   return getValue(*It->second);
83606c3fb27SDimitry Andric }
83706c3fb27SDimitry Andric 
83804eeddc0SDimitry Andric Value *Environment::createValue(QualType Type) {
83904eeddc0SDimitry Andric   llvm::DenseSet<QualType> Visited;
84081ad6265SDimitry Andric   int CreatedValuesCount = 0;
84181ad6265SDimitry Andric   Value *Val = createValueUnlessSelfReferential(Type, Visited, /*Depth=*/0,
84281ad6265SDimitry Andric                                                 CreatedValuesCount);
84381ad6265SDimitry Andric   if (CreatedValuesCount > MaxCompositeValueSize) {
84481ad6265SDimitry Andric     llvm::errs() << "Attempting to initialize a huge value of type: " << Type
84581ad6265SDimitry Andric                  << '\n';
84681ad6265SDimitry Andric   }
84781ad6265SDimitry Andric   return Val;
84804eeddc0SDimitry Andric }
84904eeddc0SDimitry Andric 
85004eeddc0SDimitry Andric Value *Environment::createValueUnlessSelfReferential(
85181ad6265SDimitry Andric     QualType Type, llvm::DenseSet<QualType> &Visited, int Depth,
85281ad6265SDimitry Andric     int &CreatedValuesCount) {
85304eeddc0SDimitry Andric   assert(!Type.isNull());
8545f757f3fSDimitry Andric   assert(!Type->isReferenceType());
85504eeddc0SDimitry Andric 
85681ad6265SDimitry Andric   // Allow unlimited fields at depth 1; only cap at deeper nesting levels.
85781ad6265SDimitry Andric   if ((Depth > 1 && CreatedValuesCount > MaxCompositeValueSize) ||
85881ad6265SDimitry Andric       Depth > MaxCompositeValueDepth)
85981ad6265SDimitry Andric     return nullptr;
86081ad6265SDimitry Andric 
86181ad6265SDimitry Andric   if (Type->isBooleanType()) {
86281ad6265SDimitry Andric     CreatedValuesCount++;
86381ad6265SDimitry Andric     return &makeAtomicBoolValue();
86481ad6265SDimitry Andric   }
86581ad6265SDimitry Andric 
86604eeddc0SDimitry Andric   if (Type->isIntegerType()) {
867bdd1243dSDimitry Andric     // FIXME: consider instead `return nullptr`, given that we do nothing useful
868bdd1243dSDimitry Andric     // with integers, and so distinguishing them serves no purpose, but could
869bdd1243dSDimitry Andric     // prevent convergence.
87081ad6265SDimitry Andric     CreatedValuesCount++;
87106c3fb27SDimitry Andric     return &arena().create<IntegerValue>();
87204eeddc0SDimitry Andric   }
87304eeddc0SDimitry Andric 
8745f757f3fSDimitry Andric   if (Type->isPointerType()) {
87581ad6265SDimitry Andric     CreatedValuesCount++;
87606c3fb27SDimitry Andric     QualType PointeeType = Type->getPointeeType();
87706c3fb27SDimitry Andric     StorageLocation &PointeeLoc =
87806c3fb27SDimitry Andric         createLocAndMaybeValue(PointeeType, Visited, Depth, CreatedValuesCount);
87904eeddc0SDimitry Andric 
88006c3fb27SDimitry Andric     return &arena().create<PointerValue>(PointeeLoc);
88104eeddc0SDimitry Andric   }
88204eeddc0SDimitry Andric 
88306c3fb27SDimitry Andric   if (Type->isRecordType()) {
88481ad6265SDimitry Andric     CreatedValuesCount++;
88506c3fb27SDimitry Andric     llvm::DenseMap<const ValueDecl *, StorageLocation *> FieldLocs;
88606c3fb27SDimitry Andric     for (const FieldDecl *Field : DACtx->getModeledFields(Type)) {
88704eeddc0SDimitry Andric       assert(Field != nullptr);
88804eeddc0SDimitry Andric 
88904eeddc0SDimitry Andric       QualType FieldType = Field->getType();
89004eeddc0SDimitry Andric 
89106c3fb27SDimitry Andric       FieldLocs.insert(
89206c3fb27SDimitry Andric           {Field, &createLocAndMaybeValue(FieldType, Visited, Depth + 1,
89306c3fb27SDimitry Andric                                           CreatedValuesCount)});
89404eeddc0SDimitry Andric     }
89504eeddc0SDimitry Andric 
8965f757f3fSDimitry Andric     RecordStorageLocation::SyntheticFieldMap SyntheticFieldLocs;
8975f757f3fSDimitry Andric     for (const auto &Entry : DACtx->getSyntheticFields(Type)) {
8985f757f3fSDimitry Andric       SyntheticFieldLocs.insert(
8995f757f3fSDimitry Andric           {Entry.getKey(),
9005f757f3fSDimitry Andric            &createLocAndMaybeValue(Entry.getValue(), Visited, Depth + 1,
9015f757f3fSDimitry Andric                                    CreatedValuesCount)});
9025f757f3fSDimitry Andric     }
90306c3fb27SDimitry Andric 
9045f757f3fSDimitry Andric     RecordStorageLocation &Loc = DACtx->createRecordStorageLocation(
9055f757f3fSDimitry Andric         Type, std::move(FieldLocs), std::move(SyntheticFieldLocs));
9065f757f3fSDimitry Andric     RecordValue &RecordVal = create<RecordValue>(Loc);
9075f757f3fSDimitry Andric 
9085f757f3fSDimitry Andric     // As we already have a storage location for the `RecordValue`, we can and
90906c3fb27SDimitry Andric     // should associate them in the environment.
9105f757f3fSDimitry Andric     setValue(Loc, RecordVal);
91106c3fb27SDimitry Andric 
9125f757f3fSDimitry Andric     return &RecordVal;
91304eeddc0SDimitry Andric   }
91404eeddc0SDimitry Andric 
91504eeddc0SDimitry Andric   return nullptr;
91604eeddc0SDimitry Andric }
91704eeddc0SDimitry Andric 
91806c3fb27SDimitry Andric StorageLocation &
91906c3fb27SDimitry Andric Environment::createLocAndMaybeValue(QualType Ty,
92006c3fb27SDimitry Andric                                     llvm::DenseSet<QualType> &Visited,
92106c3fb27SDimitry Andric                                     int Depth, int &CreatedValuesCount) {
92206c3fb27SDimitry Andric   if (!Visited.insert(Ty.getCanonicalType()).second)
92306c3fb27SDimitry Andric     return createStorageLocation(Ty.getNonReferenceType());
92406c3fb27SDimitry Andric   Value *Val = createValueUnlessSelfReferential(
92506c3fb27SDimitry Andric       Ty.getNonReferenceType(), Visited, Depth, CreatedValuesCount);
92606c3fb27SDimitry Andric   Visited.erase(Ty.getCanonicalType());
92706c3fb27SDimitry Andric 
92806c3fb27SDimitry Andric   Ty = Ty.getNonReferenceType();
92906c3fb27SDimitry Andric 
93006c3fb27SDimitry Andric   if (Val == nullptr)
93106c3fb27SDimitry Andric     return createStorageLocation(Ty);
93206c3fb27SDimitry Andric 
93306c3fb27SDimitry Andric   if (Ty->isRecordType())
9345f757f3fSDimitry Andric     return cast<RecordValue>(Val)->getLoc();
93506c3fb27SDimitry Andric 
93606c3fb27SDimitry Andric   StorageLocation &Loc = createStorageLocation(Ty);
93706c3fb27SDimitry Andric   setValue(Loc, *Val);
93806c3fb27SDimitry Andric   return Loc;
93906c3fb27SDimitry Andric }
94006c3fb27SDimitry Andric 
9415f757f3fSDimitry Andric StorageLocation &Environment::createObjectInternal(const ValueDecl *D,
94206c3fb27SDimitry Andric                                                    QualType Ty,
94306c3fb27SDimitry Andric                                                    const Expr *InitExpr) {
94406c3fb27SDimitry Andric   if (Ty->isReferenceType()) {
94506c3fb27SDimitry Andric     // Although variables of reference type always need to be initialized, it
94606c3fb27SDimitry Andric     // can happen that we can't see the initializer, so `InitExpr` may still
94706c3fb27SDimitry Andric     // be null.
94806c3fb27SDimitry Andric     if (InitExpr) {
9495f757f3fSDimitry Andric       if (auto *InitExprLoc = getStorageLocation(*InitExpr))
95006c3fb27SDimitry Andric           return *InitExprLoc;
95106c3fb27SDimitry Andric     }
95206c3fb27SDimitry Andric 
95306c3fb27SDimitry Andric     // Even though we have an initializer, we might not get an
95406c3fb27SDimitry Andric     // InitExprLoc, for example if the InitExpr is a CallExpr for which we
95506c3fb27SDimitry Andric     // don't have a function body. In this case, we just invent a storage
95606c3fb27SDimitry Andric     // location and value -- it's the best we can do.
95706c3fb27SDimitry Andric     return createObjectInternal(D, Ty.getNonReferenceType(), nullptr);
95806c3fb27SDimitry Andric   }
95906c3fb27SDimitry Andric 
96006c3fb27SDimitry Andric   Value *Val = nullptr;
96106c3fb27SDimitry Andric   if (InitExpr)
96206c3fb27SDimitry Andric     // In the (few) cases where an expression is intentionally
96306c3fb27SDimitry Andric     // "uninterpreted", `InitExpr` is not associated with a value.  There are
96406c3fb27SDimitry Andric     // two ways to handle this situation: propagate the status, so that
96506c3fb27SDimitry Andric     // uninterpreted initializers result in uninterpreted variables, or
96606c3fb27SDimitry Andric     // provide a default value. We choose the latter so that later refinements
96706c3fb27SDimitry Andric     // of the variable can be used for reasoning about the surrounding code.
96806c3fb27SDimitry Andric     // For this reason, we let this case be handled by the `createValue()`
96906c3fb27SDimitry Andric     // call below.
97006c3fb27SDimitry Andric     //
97106c3fb27SDimitry Andric     // FIXME. If and when we interpret all language cases, change this to
97206c3fb27SDimitry Andric     // assert that `InitExpr` is interpreted, rather than supplying a
97306c3fb27SDimitry Andric     // default value (assuming we don't update the environment API to return
97406c3fb27SDimitry Andric     // references).
9755f757f3fSDimitry Andric     Val = getValue(*InitExpr);
97606c3fb27SDimitry Andric   if (!Val)
97706c3fb27SDimitry Andric     Val = createValue(Ty);
97806c3fb27SDimitry Andric 
97906c3fb27SDimitry Andric   if (Ty->isRecordType())
9805f757f3fSDimitry Andric     return cast<RecordValue>(Val)->getLoc();
98106c3fb27SDimitry Andric 
98206c3fb27SDimitry Andric   StorageLocation &Loc =
98306c3fb27SDimitry Andric       D ? createStorageLocation(*D) : createStorageLocation(Ty);
98406c3fb27SDimitry Andric 
98506c3fb27SDimitry Andric   if (Val)
98606c3fb27SDimitry Andric     setValue(Loc, *Val);
98706c3fb27SDimitry Andric 
98806c3fb27SDimitry Andric   return Loc;
98906c3fb27SDimitry Andric }
99006c3fb27SDimitry Andric 
9915f757f3fSDimitry Andric void Environment::assume(const Formula &F) {
9925f757f3fSDimitry Andric   DACtx->addFlowConditionConstraint(FlowConditionToken, F);
99304eeddc0SDimitry Andric }
99404eeddc0SDimitry Andric 
9955f757f3fSDimitry Andric bool Environment::proves(const Formula &F) const {
9965f757f3fSDimitry Andric   return DACtx->flowConditionImplies(FlowConditionToken, F);
99704eeddc0SDimitry Andric }
99804eeddc0SDimitry Andric 
9995f757f3fSDimitry Andric bool Environment::allows(const Formula &F) const {
10005f757f3fSDimitry Andric   return DACtx->flowConditionAllows(FlowConditionToken, F);
100181ad6265SDimitry Andric }
100281ad6265SDimitry Andric 
1003bdd1243dSDimitry Andric void Environment::dump(raw_ostream &OS) const {
1004bdd1243dSDimitry Andric   // FIXME: add printing for remaining fields and allow caller to decide what
1005bdd1243dSDimitry Andric   // fields are printed.
1006bdd1243dSDimitry Andric   OS << "DeclToLoc:\n";
1007bdd1243dSDimitry Andric   for (auto [D, L] : DeclToLoc)
100806c3fb27SDimitry Andric     OS << "  [" << D->getNameAsString() << ", " << L << "]\n";
1009bdd1243dSDimitry Andric 
1010bdd1243dSDimitry Andric   OS << "ExprToLoc:\n";
1011bdd1243dSDimitry Andric   for (auto [E, L] : ExprToLoc)
1012bdd1243dSDimitry Andric     OS << "  [" << E << ", " << L << "]\n";
1013bdd1243dSDimitry Andric 
10145f757f3fSDimitry Andric   OS << "ExprToVal:\n";
10155f757f3fSDimitry Andric   for (auto [E, V] : ExprToVal)
10165f757f3fSDimitry Andric     OS << "  [" << E << ", " << V << ": " << *V << "]\n";
10175f757f3fSDimitry Andric 
1018bdd1243dSDimitry Andric   OS << "LocToVal:\n";
1019bdd1243dSDimitry Andric   for (auto [L, V] : LocToVal) {
1020bdd1243dSDimitry Andric     OS << "  [" << L << ", " << V << ": " << *V << "]\n";
1021bdd1243dSDimitry Andric   }
1022bdd1243dSDimitry Andric 
10235f757f3fSDimitry Andric   OS << "\n";
102406c3fb27SDimitry Andric   DACtx->dumpFlowCondition(FlowConditionToken, OS);
1025fcaf7f86SDimitry Andric }
1026fcaf7f86SDimitry Andric 
1027bdd1243dSDimitry Andric void Environment::dump() const {
1028bdd1243dSDimitry Andric   dump(llvm::dbgs());
1029bdd1243dSDimitry Andric }
1030bdd1243dSDimitry Andric 
10315f757f3fSDimitry Andric RecordStorageLocation *getImplicitObjectLocation(const CXXMemberCallExpr &MCE,
103206c3fb27SDimitry Andric                                                  const Environment &Env) {
103306c3fb27SDimitry Andric   Expr *ImplicitObject = MCE.getImplicitObjectArgument();
103406c3fb27SDimitry Andric   if (ImplicitObject == nullptr)
103506c3fb27SDimitry Andric     return nullptr;
103606c3fb27SDimitry Andric   if (ImplicitObject->getType()->isPointerType()) {
1037*cb14a3feSDimitry Andric     if (auto *Val = Env.get<PointerValue>(*ImplicitObject))
10385f757f3fSDimitry Andric       return &cast<RecordStorageLocation>(Val->getPointeeLoc());
103906c3fb27SDimitry Andric     return nullptr;
104006c3fb27SDimitry Andric   }
10415f757f3fSDimitry Andric   return cast_or_null<RecordStorageLocation>(
10425f757f3fSDimitry Andric       Env.getStorageLocation(*ImplicitObject));
104306c3fb27SDimitry Andric }
104406c3fb27SDimitry Andric 
10455f757f3fSDimitry Andric RecordStorageLocation *getBaseObjectLocation(const MemberExpr &ME,
104606c3fb27SDimitry Andric                                              const Environment &Env) {
104706c3fb27SDimitry Andric   Expr *Base = ME.getBase();
104806c3fb27SDimitry Andric   if (Base == nullptr)
104906c3fb27SDimitry Andric     return nullptr;
105006c3fb27SDimitry Andric   if (ME.isArrow()) {
1051*cb14a3feSDimitry Andric     if (auto *Val = Env.get<PointerValue>(*Base))
10525f757f3fSDimitry Andric       return &cast<RecordStorageLocation>(Val->getPointeeLoc());
105306c3fb27SDimitry Andric     return nullptr;
105406c3fb27SDimitry Andric   }
1055*cb14a3feSDimitry Andric   return Env.get<RecordStorageLocation>(*Base);
105606c3fb27SDimitry Andric }
105706c3fb27SDimitry Andric 
105806c3fb27SDimitry Andric std::vector<FieldDecl *> getFieldsForInitListExpr(const RecordDecl *RD) {
105906c3fb27SDimitry Andric   // Unnamed bitfields are only used for padding and do not appear in
106006c3fb27SDimitry Andric   // `InitListExpr`'s inits. However, those fields do appear in `RecordDecl`'s
106106c3fb27SDimitry Andric   // field list, and we thus need to remove them before mapping inits to
106206c3fb27SDimitry Andric   // fields to avoid mapping inits to the wrongs fields.
106306c3fb27SDimitry Andric   std::vector<FieldDecl *> Fields;
106406c3fb27SDimitry Andric   llvm::copy_if(
106506c3fb27SDimitry Andric       RD->fields(), std::back_inserter(Fields),
106606c3fb27SDimitry Andric       [](const FieldDecl *Field) { return !Field->isUnnamedBitfield(); });
106706c3fb27SDimitry Andric   return Fields;
106806c3fb27SDimitry Andric }
106906c3fb27SDimitry Andric 
10705f757f3fSDimitry Andric RecordValue &refreshRecordValue(RecordStorageLocation &Loc, Environment &Env) {
10715f757f3fSDimitry Andric   auto &NewVal = Env.create<RecordValue>(Loc);
107206c3fb27SDimitry Andric   Env.setValue(Loc, NewVal);
107306c3fb27SDimitry Andric   return NewVal;
107406c3fb27SDimitry Andric }
107506c3fb27SDimitry Andric 
10765f757f3fSDimitry Andric RecordValue &refreshRecordValue(const Expr &Expr, Environment &Env) {
107706c3fb27SDimitry Andric   assert(Expr.getType()->isRecordType());
107806c3fb27SDimitry Andric 
107906c3fb27SDimitry Andric   if (Expr.isPRValue()) {
1080*cb14a3feSDimitry Andric     if (auto *ExistingVal = Env.get<RecordValue>(Expr)) {
10815f757f3fSDimitry Andric       auto &NewVal = Env.create<RecordValue>(ExistingVal->getLoc());
10825f757f3fSDimitry Andric       Env.setValue(Expr, NewVal);
1083*cb14a3feSDimitry Andric       Env.setValue(NewVal.getLoc(), NewVal);
108406c3fb27SDimitry Andric       return NewVal;
108506c3fb27SDimitry Andric     }
108606c3fb27SDimitry Andric 
10875f757f3fSDimitry Andric     auto &NewVal = *cast<RecordValue>(Env.createValue(Expr.getType()));
10885f757f3fSDimitry Andric     Env.setValue(Expr, NewVal);
108906c3fb27SDimitry Andric     return NewVal;
109006c3fb27SDimitry Andric   }
109106c3fb27SDimitry Andric 
1092*cb14a3feSDimitry Andric   if (auto *Loc = Env.get<RecordStorageLocation>(Expr)) {
10935f757f3fSDimitry Andric     auto &NewVal = Env.create<RecordValue>(*Loc);
109406c3fb27SDimitry Andric     Env.setValue(*Loc, NewVal);
109506c3fb27SDimitry Andric     return NewVal;
109606c3fb27SDimitry Andric   }
109706c3fb27SDimitry Andric 
10985f757f3fSDimitry Andric   auto &NewVal = *cast<RecordValue>(Env.createValue(Expr.getType()));
10995f757f3fSDimitry Andric   Env.setStorageLocation(Expr, NewVal.getLoc());
110006c3fb27SDimitry Andric   return NewVal;
110106c3fb27SDimitry Andric }
110206c3fb27SDimitry Andric 
110304eeddc0SDimitry Andric } // namespace dataflow
110404eeddc0SDimitry Andric } // namespace clang
1105