xref: /llvm-project/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp (revision 5161a3f6e5e92c78c33aed5e38e0680a1a9b088e)
1 //===-- DataflowEnvironment.cpp ---------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 //  This file defines an Environment class that is used by dataflow analyses
10 //  that run over Control-Flow Graphs (CFGs) to keep track of the state of the
11 //  program at given program points.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
16 #include "clang/AST/Decl.h"
17 #include "clang/AST/DeclCXX.h"
18 #include "clang/AST/RecursiveASTVisitor.h"
19 #include "clang/AST/Stmt.h"
20 #include "clang/AST/Type.h"
21 #include "clang/Analysis/FlowSensitive/ASTOps.h"
22 #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
23 #include "clang/Analysis/FlowSensitive/DataflowLattice.h"
24 #include "clang/Analysis/FlowSensitive/Value.h"
25 #include "llvm/ADT/DenseMap.h"
26 #include "llvm/ADT/DenseSet.h"
27 #include "llvm/ADT/MapVector.h"
28 #include "llvm/ADT/PointerUnion.h"
29 #include "llvm/ADT/STLExtras.h"
30 #include "llvm/ADT/ScopeExit.h"
31 #include "llvm/Support/ErrorHandling.h"
32 #include <algorithm>
33 #include <cassert>
34 #include <memory>
35 #include <utility>
36 
37 #define DEBUG_TYPE "dataflow"
38 
39 namespace clang {
40 namespace dataflow {
41 
42 // FIXME: convert these to parameters of the analysis or environment. Current
43 // settings have been experimentaly validated, but only for a particular
44 // analysis.
45 static constexpr int MaxCompositeValueDepth = 3;
46 static constexpr int MaxCompositeValueSize = 1000;
47 
48 /// Returns a map consisting of key-value entries that are present in both maps.
49 static llvm::DenseMap<const ValueDecl *, StorageLocation *> intersectDeclToLoc(
50     const llvm::DenseMap<const ValueDecl *, StorageLocation *> &DeclToLoc1,
51     const llvm::DenseMap<const ValueDecl *, StorageLocation *> &DeclToLoc2) {
52   llvm::DenseMap<const ValueDecl *, StorageLocation *> Result;
53   for (auto &Entry : DeclToLoc1) {
54     auto It = DeclToLoc2.find(Entry.first);
55     if (It != DeclToLoc2.end() && Entry.second == It->second)
56       Result.insert({Entry.first, Entry.second});
57   }
58   return Result;
59 }
60 
61 // Performs a join on either `ExprToLoc` or `ExprToVal`.
62 // The maps must be consistent in the sense that any entries for the same
63 // expression must map to the same location / value. This is the case if we are
64 // performing a join for control flow within a full-expression (which is the
65 // only case when this function should be used).
66 template <typename MapT> MapT joinExprMaps(const MapT &Map1, const MapT &Map2) {
67   MapT Result = Map1;
68 
69   for (const auto &Entry : Map2) {
70     [[maybe_unused]] auto [It, Inserted] = Result.insert(Entry);
71     // If there was an existing entry, its value should be the same as for the
72     // entry we were trying to insert.
73     assert(It->second == Entry.second);
74   }
75 
76   return Result;
77 }
78 
79 // Whether to consider equivalent two values with an unknown relation.
80 //
81 // FIXME: this function is a hack enabling unsoundness to support
82 // convergence. Once we have widening support for the reference/pointer and
83 // struct built-in models, this should be unconditionally `false` (and inlined
84 // as such at its call sites).
85 static bool equateUnknownValues(Value::Kind K) {
86   switch (K) {
87   case Value::Kind::Integer:
88   case Value::Kind::Pointer:
89     return true;
90   default:
91     return false;
92   }
93 }
94 
95 static bool compareDistinctValues(QualType Type, Value &Val1,
96                                   const Environment &Env1, Value &Val2,
97                                   const Environment &Env2,
98                                   Environment::ValueModel &Model) {
99   // Note: Potentially costly, but, for booleans, we could check whether both
100   // can be proven equivalent in their respective environments.
101 
102   // FIXME: move the reference/pointers logic from `areEquivalentValues` to here
103   // and implement separate, join/widen specific handling for
104   // reference/pointers.
105   switch (Model.compare(Type, Val1, Env1, Val2, Env2)) {
106   case ComparisonResult::Same:
107     return true;
108   case ComparisonResult::Different:
109     return false;
110   case ComparisonResult::Unknown:
111     return equateUnknownValues(Val1.getKind());
112   }
113   llvm_unreachable("All cases covered in switch");
114 }
115 
116 /// Attempts to join distinct values `Val1` and `Val2` in `Env1` and `Env2`,
117 /// respectively, of the same type `Type`. Joining generally produces a single
118 /// value that (soundly) approximates the two inputs, although the actual
119 /// meaning depends on `Model`.
120 static Value *joinDistinctValues(QualType Type, Value &Val1,
121                                  const Environment &Env1, Value &Val2,
122                                  const Environment &Env2,
123                                  Environment &JoinedEnv,
124                                  Environment::ValueModel &Model) {
125   // Join distinct boolean values preserving information about the constraints
126   // in the respective path conditions.
127   if (isa<BoolValue>(&Val1) && isa<BoolValue>(&Val2)) {
128     // FIXME: Checking both values should be unnecessary, since they should have
129     // a consistent shape.  However, right now we can end up with BoolValue's in
130     // integer-typed variables due to our incorrect handling of
131     // boolean-to-integer casts (we just propagate the BoolValue to the result
132     // of the cast). So, a join can encounter an integer in one branch but a
133     // bool in the other.
134     // For example:
135     // ```
136     // std::optional<bool> o;
137     // int x;
138     // if (o.has_value())
139     //   x = o.value();
140     // ```
141     auto &Expr1 = cast<BoolValue>(Val1).formula();
142     auto &Expr2 = cast<BoolValue>(Val2).formula();
143     auto &A = JoinedEnv.arena();
144     auto &JoinedVal = A.makeAtomRef(A.makeAtom());
145     JoinedEnv.assume(
146         A.makeOr(A.makeAnd(A.makeAtomRef(Env1.getFlowConditionToken()),
147                            A.makeEquals(JoinedVal, Expr1)),
148                  A.makeAnd(A.makeAtomRef(Env2.getFlowConditionToken()),
149                            A.makeEquals(JoinedVal, Expr2))));
150     return &A.makeBoolValue(JoinedVal);
151   }
152 
153   Value *JoinedVal = JoinedEnv.createValue(Type);
154   if (JoinedVal)
155     Model.join(Type, Val1, Env1, Val2, Env2, *JoinedVal, JoinedEnv);
156 
157   return JoinedVal;
158 }
159 
160 static WidenResult widenDistinctValues(QualType Type, Value &Prev,
161                                        const Environment &PrevEnv,
162                                        Value &Current, Environment &CurrentEnv,
163                                        Environment::ValueModel &Model) {
164   // Boolean-model widening.
165   if (isa<BoolValue>(Prev) && isa<BoolValue>(Current)) {
166     // FIXME: Checking both values should be unnecessary, but we can currently
167     // end up with `BoolValue`s in integer-typed variables. See comment in
168     // `joinDistinctValues()` for details.
169     auto &PrevBool = cast<BoolValue>(Prev);
170     auto &CurBool = cast<BoolValue>(Current);
171 
172     if (isa<TopBoolValue>(Prev))
173       // Safe to return `Prev` here, because Top is never dependent on the
174       // environment.
175       return {&Prev, LatticeEffect::Unchanged};
176 
177     // We may need to widen to Top, but before we do so, check whether both
178     // values are implied to be either true or false in the current environment.
179     // In that case, we can simply return a literal instead.
180     bool TruePrev = PrevEnv.proves(PrevBool.formula());
181     bool TrueCur = CurrentEnv.proves(CurBool.formula());
182     if (TruePrev && TrueCur)
183       return {&CurrentEnv.getBoolLiteralValue(true), LatticeEffect::Unchanged};
184     if (!TruePrev && !TrueCur &&
185         PrevEnv.proves(PrevEnv.arena().makeNot(PrevBool.formula())) &&
186         CurrentEnv.proves(CurrentEnv.arena().makeNot(CurBool.formula())))
187       return {&CurrentEnv.getBoolLiteralValue(false), LatticeEffect::Unchanged};
188 
189     return {&CurrentEnv.makeTopBoolValue(), LatticeEffect::Changed};
190   }
191 
192   // FIXME: Add other built-in model widening.
193 
194   // Custom-model widening.
195   if (auto Result = Model.widen(Type, Prev, PrevEnv, Current, CurrentEnv))
196     return *Result;
197 
198   return {&Current, equateUnknownValues(Prev.getKind())
199                         ? LatticeEffect::Unchanged
200                         : LatticeEffect::Changed};
201 }
202 
203 // Returns whether the values in `Map1` and `Map2` compare equal for those
204 // keys that `Map1` and `Map2` have in common.
205 template <typename Key>
206 bool compareKeyToValueMaps(const llvm::MapVector<Key, Value *> &Map1,
207                            const llvm::MapVector<Key, Value *> &Map2,
208                            const Environment &Env1, const Environment &Env2,
209                            Environment::ValueModel &Model) {
210   for (auto &Entry : Map1) {
211     Key K = Entry.first;
212     assert(K != nullptr);
213 
214     Value *Val = Entry.second;
215     assert(Val != nullptr);
216 
217     auto It = Map2.find(K);
218     if (It == Map2.end())
219       continue;
220     assert(It->second != nullptr);
221 
222     if (!areEquivalentValues(*Val, *It->second) &&
223         !compareDistinctValues(K->getType(), *Val, Env1, *It->second, Env2,
224                                Model))
225       return false;
226   }
227 
228   return true;
229 }
230 
231 // Perform a join on two `LocToVal` maps.
232 static llvm::MapVector<const StorageLocation *, Value *>
233 joinLocToVal(const llvm::MapVector<const StorageLocation *, Value *> &LocToVal,
234              const llvm::MapVector<const StorageLocation *, Value *> &LocToVal2,
235              const Environment &Env1, const Environment &Env2,
236              Environment &JoinedEnv, Environment::ValueModel &Model) {
237   llvm::MapVector<const StorageLocation *, Value *> Result;
238   for (auto &Entry : LocToVal) {
239     const StorageLocation *Loc = Entry.first;
240     assert(Loc != nullptr);
241 
242     Value *Val = Entry.second;
243     assert(Val != nullptr);
244 
245     auto It = LocToVal2.find(Loc);
246     if (It == LocToVal2.end())
247       continue;
248     assert(It->second != nullptr);
249 
250     if (Value *JoinedVal = Environment::joinValues(
251             Loc->getType(), Val, Env1, It->second, Env2, JoinedEnv, Model)) {
252       Result.insert({Loc, JoinedVal});
253     }
254   }
255 
256   return Result;
257 }
258 
259 // Perform widening on either `LocToVal` or `ExprToVal`. `Key` must be either
260 // `const StorageLocation *` or `const Expr *`.
261 template <typename Key>
262 llvm::MapVector<Key, Value *>
263 widenKeyToValueMap(const llvm::MapVector<Key, Value *> &CurMap,
264                    const llvm::MapVector<Key, Value *> &PrevMap,
265                    Environment &CurEnv, const Environment &PrevEnv,
266                    Environment::ValueModel &Model, LatticeEffect &Effect) {
267   llvm::MapVector<Key, Value *> WidenedMap;
268   for (auto &Entry : CurMap) {
269     Key K = Entry.first;
270     assert(K != nullptr);
271 
272     Value *Val = Entry.second;
273     assert(Val != nullptr);
274 
275     auto PrevIt = PrevMap.find(K);
276     if (PrevIt == PrevMap.end())
277       continue;
278     assert(PrevIt->second != nullptr);
279 
280     if (areEquivalentValues(*Val, *PrevIt->second)) {
281       WidenedMap.insert({K, Val});
282       continue;
283     }
284 
285     auto [WidenedVal, ValEffect] = widenDistinctValues(
286         K->getType(), *PrevIt->second, PrevEnv, *Val, CurEnv, Model);
287     WidenedMap.insert({K, WidenedVal});
288     if (ValEffect == LatticeEffect::Changed)
289       Effect = LatticeEffect::Changed;
290   }
291 
292   return WidenedMap;
293 }
294 
295 namespace {
296 
297 // Visitor that builds a map from record prvalues to result objects.
298 // For each result object that it encounters, it propagates the storage location
299 // of the result object to all record prvalues that can initialize it.
300 class ResultObjectVisitor : public AnalysisASTVisitor<ResultObjectVisitor> {
301 public:
302   // `ResultObjectMap` will be filled with a map from record prvalues to result
303   // object. If this visitor will traverse a function that returns a record by
304   // value, `LocForRecordReturnVal` is the location to which this record should
305   // be written; otherwise, it is null.
306   explicit ResultObjectVisitor(
307       llvm::DenseMap<const Expr *, RecordStorageLocation *> &ResultObjectMap,
308       RecordStorageLocation *LocForRecordReturnVal,
309       DataflowAnalysisContext &DACtx)
310       : ResultObjectMap(ResultObjectMap),
311         LocForRecordReturnVal(LocForRecordReturnVal), DACtx(DACtx) {}
312 
313   // Traverse all member and base initializers of `Ctor`. This function is not
314   // called by `RecursiveASTVisitor`; it should be called manually if we are
315   // analyzing a constructor. `ThisPointeeLoc` is the storage location that
316   // `this` points to.
317   void TraverseConstructorInits(const CXXConstructorDecl *Ctor,
318                                 RecordStorageLocation *ThisPointeeLoc) {
319     assert(ThisPointeeLoc != nullptr);
320     for (const CXXCtorInitializer *Init : Ctor->inits()) {
321       Expr *InitExpr = Init->getInit();
322       if (FieldDecl *Field = Init->getMember();
323           Field != nullptr && Field->getType()->isRecordType()) {
324         PropagateResultObject(InitExpr, cast<RecordStorageLocation>(
325                                             ThisPointeeLoc->getChild(*Field)));
326       } else if (Init->getBaseClass()) {
327         PropagateResultObject(InitExpr, ThisPointeeLoc);
328       }
329 
330       // Ensure that any result objects within `InitExpr` (e.g. temporaries)
331       // are also propagated to the prvalues that initialize them.
332       TraverseStmt(InitExpr);
333 
334       // If this is a `CXXDefaultInitExpr`, also propagate any result objects
335       // within the default expression.
336       if (auto *DefaultInit = dyn_cast<CXXDefaultInitExpr>(InitExpr))
337         TraverseStmt(DefaultInit->getExpr());
338     }
339   }
340 
341   bool VisitVarDecl(VarDecl *VD) {
342     if (VD->getType()->isRecordType() && VD->hasInit())
343       PropagateResultObject(
344           VD->getInit(),
345           &cast<RecordStorageLocation>(DACtx.getStableStorageLocation(*VD)));
346     return true;
347   }
348 
349   bool VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *MTE) {
350     if (MTE->getType()->isRecordType())
351       PropagateResultObject(
352           MTE->getSubExpr(),
353           &cast<RecordStorageLocation>(DACtx.getStableStorageLocation(*MTE)));
354     return true;
355   }
356 
357   bool VisitReturnStmt(ReturnStmt *Return) {
358     Expr *RetValue = Return->getRetValue();
359     if (RetValue != nullptr && RetValue->getType()->isRecordType() &&
360         RetValue->isPRValue())
361       PropagateResultObject(RetValue, LocForRecordReturnVal);
362     return true;
363   }
364 
365   bool VisitExpr(Expr *E) {
366     // Clang's AST can have record-type prvalues without a result object -- for
367     // example as full-expressions contained in a compound statement or as
368     // arguments of call expressions. We notice this if we get here and a
369     // storage location has not yet been associated with `E`. In this case,
370     // treat this as if it was a `MaterializeTemporaryExpr`.
371     if (E->isPRValue() && E->getType()->isRecordType() &&
372         !ResultObjectMap.contains(E))
373       PropagateResultObject(
374           E, &cast<RecordStorageLocation>(DACtx.getStableStorageLocation(*E)));
375     return true;
376   }
377 
378   void
379   PropagateResultObjectToRecordInitList(const RecordInitListHelper &InitList,
380                                         RecordStorageLocation *Loc) {
381     for (auto [Base, Init] : InitList.base_inits()) {
382       assert(Base->getType().getCanonicalType() ==
383              Init->getType().getCanonicalType());
384 
385       // Storage location for the base class is the same as that of the
386       // derived class because we "flatten" the object hierarchy and put all
387       // fields in `RecordStorageLocation` of the derived class.
388       PropagateResultObject(Init, Loc);
389     }
390 
391     for (auto [Field, Init] : InitList.field_inits()) {
392       // Fields of non-record type are handled in
393       // `TransferVisitor::VisitInitListExpr()`.
394       if (Field->getType()->isRecordType())
395         PropagateResultObject(
396             Init, cast<RecordStorageLocation>(Loc->getChild(*Field)));
397     }
398   }
399 
400   // Assigns `Loc` as the result object location of `E`, then propagates the
401   // location to all lower-level prvalues that initialize the same object as
402   // `E` (or one of its base classes or member variables).
403   void PropagateResultObject(Expr *E, RecordStorageLocation *Loc) {
404     if (!E->isPRValue() || !E->getType()->isRecordType()) {
405       assert(false);
406       // Ensure we don't propagate the result object if we hit this in a
407       // release build.
408       return;
409     }
410 
411     ResultObjectMap[E] = Loc;
412 
413     // The following AST node kinds are "original initializers": They are the
414     // lowest-level AST node that initializes a given object, and nothing
415     // below them can initialize the same object (or part of it).
416     if (isa<CXXConstructExpr>(E) || isa<CallExpr>(E) || isa<LambdaExpr>(E) ||
417         isa<CXXDefaultArgExpr>(E) || isa<CXXDefaultInitExpr>(E) ||
418         isa<CXXStdInitializerListExpr>(E) ||
419         // We treat `BuiltinBitCastExpr` as an "original initializer" too as
420         // it may not even be casting from a record type -- and even if it is,
421         // the two objects are in general of unrelated type.
422         isa<BuiltinBitCastExpr>(E)) {
423       return;
424     }
425     if (auto *Op = dyn_cast<BinaryOperator>(E);
426         Op && Op->getOpcode() == BO_Cmp) {
427       // Builtin `<=>` returns a `std::strong_ordering` object.
428       return;
429     }
430 
431     if (auto *InitList = dyn_cast<InitListExpr>(E)) {
432       if (!InitList->isSemanticForm())
433         return;
434       if (InitList->isTransparent()) {
435         PropagateResultObject(InitList->getInit(0), Loc);
436         return;
437       }
438 
439       PropagateResultObjectToRecordInitList(RecordInitListHelper(InitList),
440                                             Loc);
441       return;
442     }
443 
444     if (auto *ParenInitList = dyn_cast<CXXParenListInitExpr>(E)) {
445       PropagateResultObjectToRecordInitList(RecordInitListHelper(ParenInitList),
446                                             Loc);
447       return;
448     }
449 
450     if (auto *Op = dyn_cast<BinaryOperator>(E); Op && Op->isCommaOp()) {
451       PropagateResultObject(Op->getRHS(), Loc);
452       return;
453     }
454 
455     if (auto *Cond = dyn_cast<AbstractConditionalOperator>(E)) {
456       PropagateResultObject(Cond->getTrueExpr(), Loc);
457       PropagateResultObject(Cond->getFalseExpr(), Loc);
458       return;
459     }
460 
461     if (auto *SE = dyn_cast<StmtExpr>(E)) {
462       PropagateResultObject(cast<Expr>(SE->getSubStmt()->body_back()), Loc);
463       return;
464     }
465 
466     // All other expression nodes that propagate a record prvalue should have
467     // exactly one child.
468     SmallVector<Stmt *, 1> Children(E->child_begin(), E->child_end());
469     LLVM_DEBUG({
470       if (Children.size() != 1)
471         E->dump();
472     });
473     assert(Children.size() == 1);
474     for (Stmt *S : Children)
475       PropagateResultObject(cast<Expr>(S), Loc);
476   }
477 
478 private:
479   llvm::DenseMap<const Expr *, RecordStorageLocation *> &ResultObjectMap;
480   RecordStorageLocation *LocForRecordReturnVal;
481   DataflowAnalysisContext &DACtx;
482 };
483 
484 } // namespace
485 
486 void Environment::initialize() {
487   if (InitialTargetStmt == nullptr)
488     return;
489 
490   if (InitialTargetFunc == nullptr) {
491     initFieldsGlobalsAndFuncs(getReferencedDecls(*InitialTargetStmt));
492     ResultObjectMap =
493         std::make_shared<PrValueToResultObject>(buildResultObjectMap(
494             DACtx, InitialTargetStmt, getThisPointeeStorageLocation(),
495             /*LocForRecordReturnValue=*/nullptr));
496     return;
497   }
498 
499   initFieldsGlobalsAndFuncs(getReferencedDecls(*InitialTargetFunc));
500 
501   for (const auto *ParamDecl : InitialTargetFunc->parameters()) {
502     assert(ParamDecl != nullptr);
503     setStorageLocation(*ParamDecl, createObject(*ParamDecl, nullptr));
504   }
505 
506   if (InitialTargetFunc->getReturnType()->isRecordType())
507     LocForRecordReturnVal = &cast<RecordStorageLocation>(
508         createStorageLocation(InitialTargetFunc->getReturnType()));
509 
510   if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(InitialTargetFunc)) {
511     auto *Parent = MethodDecl->getParent();
512     assert(Parent != nullptr);
513 
514     if (Parent->isLambda()) {
515       for (const auto &Capture : Parent->captures()) {
516         if (Capture.capturesVariable()) {
517           const auto *VarDecl = Capture.getCapturedVar();
518           assert(VarDecl != nullptr);
519           setStorageLocation(*VarDecl, createObject(*VarDecl, nullptr));
520         } else if (Capture.capturesThis()) {
521           const auto *SurroundingMethodDecl =
522               cast<CXXMethodDecl>(InitialTargetFunc->getNonClosureAncestor());
523           QualType ThisPointeeType =
524               SurroundingMethodDecl->getFunctionObjectParameterType();
525           setThisPointeeStorageLocation(
526               cast<RecordStorageLocation>(createObject(ThisPointeeType)));
527         }
528       }
529     } else if (MethodDecl->isImplicitObjectMemberFunction()) {
530       QualType ThisPointeeType = MethodDecl->getFunctionObjectParameterType();
531       auto &ThisLoc =
532           cast<RecordStorageLocation>(createStorageLocation(ThisPointeeType));
533       setThisPointeeStorageLocation(ThisLoc);
534       // Initialize fields of `*this` with values, but only if we're not
535       // analyzing a constructor; after all, it's the constructor's job to do
536       // this (and we want to be able to test that).
537       if (!isa<CXXConstructorDecl>(MethodDecl))
538         initializeFieldsWithValues(ThisLoc);
539     }
540   }
541 
542   // We do this below the handling of `CXXMethodDecl` above so that we can
543   // be sure that the storage location for `this` has been set.
544   ResultObjectMap =
545       std::make_shared<PrValueToResultObject>(buildResultObjectMap(
546           DACtx, InitialTargetFunc, getThisPointeeStorageLocation(),
547           LocForRecordReturnVal));
548 }
549 
550 // FIXME: Add support for resetting globals after function calls to enable the
551 // implementation of sound analyses.
552 
553 void Environment::initFieldsGlobalsAndFuncs(const ReferencedDecls &Referenced) {
554   // These have to be added before the lines that follow to ensure that
555   // `create*` work correctly for structs.
556   DACtx->addModeledFields(Referenced.Fields);
557 
558   for (const VarDecl *D : Referenced.Globals) {
559     if (getStorageLocation(*D) != nullptr)
560       continue;
561 
562     // We don't run transfer functions on the initializers of global variables,
563     // so they won't be associated with a value or storage location. We
564     // therefore intentionally don't pass an initializer to `createObject()`; in
565     // particular, this ensures that `createObject()` will initialize the fields
566     // of record-type variables with values.
567     setStorageLocation(*D, createObject(*D, nullptr));
568   }
569 
570   for (const FunctionDecl *FD : Referenced.Functions) {
571     if (getStorageLocation(*FD) != nullptr)
572       continue;
573     auto &Loc = createStorageLocation(*FD);
574     setStorageLocation(*FD, Loc);
575   }
576 }
577 
578 Environment Environment::fork() const {
579   Environment Copy(*this);
580   Copy.FlowConditionToken = DACtx->forkFlowCondition(FlowConditionToken);
581   return Copy;
582 }
583 
584 bool Environment::canDescend(unsigned MaxDepth,
585                              const FunctionDecl *Callee) const {
586   return CallStack.size() < MaxDepth && !llvm::is_contained(CallStack, Callee);
587 }
588 
589 Environment Environment::pushCall(const CallExpr *Call) const {
590   Environment Env(*this);
591 
592   if (const auto *MethodCall = dyn_cast<CXXMemberCallExpr>(Call)) {
593     if (const Expr *Arg = MethodCall->getImplicitObjectArgument()) {
594       if (!isa<CXXThisExpr>(Arg))
595         Env.ThisPointeeLoc =
596             cast<RecordStorageLocation>(getStorageLocation(*Arg));
597       // Otherwise (when the argument is `this`), retain the current
598       // environment's `ThisPointeeLoc`.
599     }
600   }
601 
602   if (Call->getType()->isRecordType() && Call->isPRValue())
603     Env.LocForRecordReturnVal = &Env.getResultObjectLocation(*Call);
604 
605   Env.pushCallInternal(Call->getDirectCallee(),
606                        llvm::ArrayRef(Call->getArgs(), Call->getNumArgs()));
607 
608   return Env;
609 }
610 
611 Environment Environment::pushCall(const CXXConstructExpr *Call) const {
612   Environment Env(*this);
613 
614   Env.ThisPointeeLoc = &Env.getResultObjectLocation(*Call);
615   Env.LocForRecordReturnVal = &Env.getResultObjectLocation(*Call);
616 
617   Env.pushCallInternal(Call->getConstructor(),
618                        llvm::ArrayRef(Call->getArgs(), Call->getNumArgs()));
619 
620   return Env;
621 }
622 
623 void Environment::pushCallInternal(const FunctionDecl *FuncDecl,
624                                    ArrayRef<const Expr *> Args) {
625   // Canonicalize to the definition of the function. This ensures that we're
626   // putting arguments into the same `ParamVarDecl`s` that the callee will later
627   // be retrieving them from.
628   assert(FuncDecl->getDefinition() != nullptr);
629   FuncDecl = FuncDecl->getDefinition();
630 
631   CallStack.push_back(FuncDecl);
632 
633   initFieldsGlobalsAndFuncs(getReferencedDecls(*FuncDecl));
634 
635   const auto *ParamIt = FuncDecl->param_begin();
636 
637   // FIXME: Parameters don't always map to arguments 1:1; examples include
638   // overloaded operators implemented as member functions, and parameter packs.
639   for (unsigned ArgIndex = 0; ArgIndex < Args.size(); ++ParamIt, ++ArgIndex) {
640     assert(ParamIt != FuncDecl->param_end());
641     const VarDecl *Param = *ParamIt;
642     setStorageLocation(*Param, createObject(*Param, Args[ArgIndex]));
643   }
644 
645   ResultObjectMap = std::make_shared<PrValueToResultObject>(
646       buildResultObjectMap(DACtx, FuncDecl, getThisPointeeStorageLocation(),
647                            LocForRecordReturnVal));
648 }
649 
650 void Environment::popCall(const CallExpr *Call, const Environment &CalleeEnv) {
651   // We ignore some entries of `CalleeEnv`:
652   // - `DACtx` because is already the same in both
653   // - We don't want the callee's `DeclCtx`, `ReturnVal`, `ReturnLoc` or
654   //   `ThisPointeeLoc` because they don't apply to us.
655   // - `DeclToLoc`, `ExprToLoc`, and `ExprToVal` capture information from the
656   //   callee's local scope, so when popping that scope, we do not propagate
657   //   the maps.
658   this->LocToVal = std::move(CalleeEnv.LocToVal);
659   this->FlowConditionToken = std::move(CalleeEnv.FlowConditionToken);
660 
661   if (Call->isGLValue()) {
662     if (CalleeEnv.ReturnLoc != nullptr)
663       setStorageLocation(*Call, *CalleeEnv.ReturnLoc);
664   } else if (!Call->getType()->isVoidType()) {
665     if (CalleeEnv.ReturnVal != nullptr)
666       setValue(*Call, *CalleeEnv.ReturnVal);
667   }
668 }
669 
670 void Environment::popCall(const CXXConstructExpr *Call,
671                           const Environment &CalleeEnv) {
672   // See also comment in `popCall(const CallExpr *, const Environment &)` above.
673   this->LocToVal = std::move(CalleeEnv.LocToVal);
674   this->FlowConditionToken = std::move(CalleeEnv.FlowConditionToken);
675 }
676 
677 bool Environment::equivalentTo(const Environment &Other,
678                                Environment::ValueModel &Model) const {
679   assert(DACtx == Other.DACtx);
680 
681   if (ReturnVal != Other.ReturnVal)
682     return false;
683 
684   if (ReturnLoc != Other.ReturnLoc)
685     return false;
686 
687   if (LocForRecordReturnVal != Other.LocForRecordReturnVal)
688     return false;
689 
690   if (ThisPointeeLoc != Other.ThisPointeeLoc)
691     return false;
692 
693   if (DeclToLoc != Other.DeclToLoc)
694     return false;
695 
696   if (ExprToLoc != Other.ExprToLoc)
697     return false;
698 
699   if (!compareKeyToValueMaps(ExprToVal, Other.ExprToVal, *this, Other, Model))
700     return false;
701 
702   if (!compareKeyToValueMaps(LocToVal, Other.LocToVal, *this, Other, Model))
703     return false;
704 
705   return true;
706 }
707 
708 LatticeEffect Environment::widen(const Environment &PrevEnv,
709                                  Environment::ValueModel &Model) {
710   assert(DACtx == PrevEnv.DACtx);
711   assert(ReturnVal == PrevEnv.ReturnVal);
712   assert(ReturnLoc == PrevEnv.ReturnLoc);
713   assert(LocForRecordReturnVal == PrevEnv.LocForRecordReturnVal);
714   assert(ThisPointeeLoc == PrevEnv.ThisPointeeLoc);
715   assert(CallStack == PrevEnv.CallStack);
716   assert(ResultObjectMap == PrevEnv.ResultObjectMap);
717   assert(InitialTargetFunc == PrevEnv.InitialTargetFunc);
718   assert(InitialTargetStmt == PrevEnv.InitialTargetStmt);
719 
720   auto Effect = LatticeEffect::Unchanged;
721 
722   // By the API, `PrevEnv` is a previous version of the environment for the same
723   // block, so we have some guarantees about its shape. In particular, it will
724   // be the result of a join or widen operation on previous values for this
725   // block. For `DeclToLoc`, `ExprToVal`, and `ExprToLoc`, join guarantees that
726   // these maps are subsets of the maps in `PrevEnv`. So, as long as we maintain
727   // this property here, we don't need change their current values to widen.
728   assert(DeclToLoc.size() <= PrevEnv.DeclToLoc.size());
729   assert(ExprToVal.size() <= PrevEnv.ExprToVal.size());
730   assert(ExprToLoc.size() <= PrevEnv.ExprToLoc.size());
731 
732   ExprToVal = widenKeyToValueMap(ExprToVal, PrevEnv.ExprToVal, *this, PrevEnv,
733                                  Model, Effect);
734 
735   LocToVal = widenKeyToValueMap(LocToVal, PrevEnv.LocToVal, *this, PrevEnv,
736                                 Model, Effect);
737   if (DeclToLoc.size() != PrevEnv.DeclToLoc.size() ||
738       ExprToLoc.size() != PrevEnv.ExprToLoc.size() ||
739       ExprToVal.size() != PrevEnv.ExprToVal.size() ||
740       LocToVal.size() != PrevEnv.LocToVal.size())
741     Effect = LatticeEffect::Changed;
742 
743   return Effect;
744 }
745 
746 Environment Environment::join(const Environment &EnvA, const Environment &EnvB,
747                               Environment::ValueModel &Model,
748                               ExprJoinBehavior ExprBehavior) {
749   assert(EnvA.DACtx == EnvB.DACtx);
750   assert(EnvA.LocForRecordReturnVal == EnvB.LocForRecordReturnVal);
751   assert(EnvA.ThisPointeeLoc == EnvB.ThisPointeeLoc);
752   assert(EnvA.CallStack == EnvB.CallStack);
753   assert(EnvA.ResultObjectMap == EnvB.ResultObjectMap);
754   assert(EnvA.InitialTargetFunc == EnvB.InitialTargetFunc);
755   assert(EnvA.InitialTargetStmt == EnvB.InitialTargetStmt);
756 
757   Environment JoinedEnv(*EnvA.DACtx);
758 
759   JoinedEnv.CallStack = EnvA.CallStack;
760   JoinedEnv.ResultObjectMap = EnvA.ResultObjectMap;
761   JoinedEnv.LocForRecordReturnVal = EnvA.LocForRecordReturnVal;
762   JoinedEnv.ThisPointeeLoc = EnvA.ThisPointeeLoc;
763   JoinedEnv.InitialTargetFunc = EnvA.InitialTargetFunc;
764   JoinedEnv.InitialTargetStmt = EnvA.InitialTargetStmt;
765 
766   const FunctionDecl *Func = EnvA.getCurrentFunc();
767   if (!Func) {
768     JoinedEnv.ReturnVal = nullptr;
769   } else {
770     JoinedEnv.ReturnVal =
771         joinValues(Func->getReturnType(), EnvA.ReturnVal, EnvA, EnvB.ReturnVal,
772                    EnvB, JoinedEnv, Model);
773   }
774 
775   if (EnvA.ReturnLoc == EnvB.ReturnLoc)
776     JoinedEnv.ReturnLoc = EnvA.ReturnLoc;
777   else
778     JoinedEnv.ReturnLoc = nullptr;
779 
780   JoinedEnv.DeclToLoc = intersectDeclToLoc(EnvA.DeclToLoc, EnvB.DeclToLoc);
781 
782   // FIXME: update join to detect backedges and simplify the flow condition
783   // accordingly.
784   JoinedEnv.FlowConditionToken = EnvA.DACtx->joinFlowConditions(
785       EnvA.FlowConditionToken, EnvB.FlowConditionToken);
786 
787   JoinedEnv.LocToVal =
788       joinLocToVal(EnvA.LocToVal, EnvB.LocToVal, EnvA, EnvB, JoinedEnv, Model);
789 
790   if (ExprBehavior == KeepExprState) {
791     JoinedEnv.ExprToVal = joinExprMaps(EnvA.ExprToVal, EnvB.ExprToVal);
792     JoinedEnv.ExprToLoc = joinExprMaps(EnvA.ExprToLoc, EnvB.ExprToLoc);
793   }
794 
795   return JoinedEnv;
796 }
797 
798 Value *Environment::joinValues(QualType Ty, Value *Val1,
799                                const Environment &Env1, Value *Val2,
800                                const Environment &Env2, Environment &JoinedEnv,
801                                Environment::ValueModel &Model) {
802   if (Val1 == nullptr || Val2 == nullptr)
803     // We can't say anything about the joined value -- even if one of the values
804     // is non-null, we don't want to simply propagate it, because it would be
805     // too specific: Because the other value is null, that means we have no
806     // information at all about the value (i.e. the value is unconstrained).
807     return nullptr;
808 
809   if (areEquivalentValues(*Val1, *Val2))
810     // Arbitrarily return one of the two values.
811     return Val1;
812 
813   return joinDistinctValues(Ty, *Val1, Env1, *Val2, Env2, JoinedEnv, Model);
814 }
815 
816 StorageLocation &Environment::createStorageLocation(QualType Type) {
817   return DACtx->createStorageLocation(Type);
818 }
819 
820 StorageLocation &Environment::createStorageLocation(const ValueDecl &D) {
821   // Evaluated declarations are always assigned the same storage locations to
822   // ensure that the environment stabilizes across loop iterations. Storage
823   // locations for evaluated declarations are stored in the analysis context.
824   return DACtx->getStableStorageLocation(D);
825 }
826 
827 StorageLocation &Environment::createStorageLocation(const Expr &E) {
828   // Evaluated expressions are always assigned the same storage locations to
829   // ensure that the environment stabilizes across loop iterations. Storage
830   // locations for evaluated expressions are stored in the analysis context.
831   return DACtx->getStableStorageLocation(E);
832 }
833 
834 void Environment::setStorageLocation(const ValueDecl &D, StorageLocation &Loc) {
835   assert(!DeclToLoc.contains(&D));
836   // The only kinds of declarations that may have a "variable" storage location
837   // are declarations of reference type and `BindingDecl`. For all other
838   // declaration, the storage location should be the stable storage location
839   // returned by `createStorageLocation()`.
840   assert(D.getType()->isReferenceType() || isa<BindingDecl>(D) ||
841          &Loc == &createStorageLocation(D));
842   DeclToLoc[&D] = &Loc;
843 }
844 
845 StorageLocation *Environment::getStorageLocation(const ValueDecl &D) const {
846   auto It = DeclToLoc.find(&D);
847   if (It == DeclToLoc.end())
848     return nullptr;
849 
850   StorageLocation *Loc = It->second;
851 
852   return Loc;
853 }
854 
855 void Environment::removeDecl(const ValueDecl &D) { DeclToLoc.erase(&D); }
856 
857 void Environment::setStorageLocation(const Expr &E, StorageLocation &Loc) {
858   // `DeclRefExpr`s to builtin function types aren't glvalues, for some reason,
859   // but we still want to be able to associate a `StorageLocation` with them,
860   // so allow these as an exception.
861   assert(E.isGLValue() ||
862          E.getType()->isSpecificBuiltinType(BuiltinType::BuiltinFn));
863   const Expr &CanonE = ignoreCFGOmittedNodes(E);
864   assert(!ExprToLoc.contains(&CanonE));
865   ExprToLoc[&CanonE] = &Loc;
866 }
867 
868 StorageLocation *Environment::getStorageLocation(const Expr &E) const {
869   // See comment in `setStorageLocation()`.
870   assert(E.isGLValue() ||
871          E.getType()->isSpecificBuiltinType(BuiltinType::BuiltinFn));
872   auto It = ExprToLoc.find(&ignoreCFGOmittedNodes(E));
873   return It == ExprToLoc.end() ? nullptr : &*It->second;
874 }
875 
876 RecordStorageLocation &
877 Environment::getResultObjectLocation(const Expr &RecordPRValue) const {
878   assert(RecordPRValue.getType()->isRecordType());
879   assert(RecordPRValue.isPRValue());
880 
881   assert(ResultObjectMap != nullptr);
882   RecordStorageLocation *Loc = ResultObjectMap->lookup(&RecordPRValue);
883   assert(Loc != nullptr);
884   // In release builds, use the "stable" storage location if the map lookup
885   // failed.
886   if (Loc == nullptr)
887     return cast<RecordStorageLocation>(
888         DACtx->getStableStorageLocation(RecordPRValue));
889   return *Loc;
890 }
891 
892 PointerValue &Environment::getOrCreateNullPointerValue(QualType PointeeType) {
893   return DACtx->getOrCreateNullPointerValue(PointeeType);
894 }
895 
896 void Environment::initializeFieldsWithValues(RecordStorageLocation &Loc,
897                                              QualType Type) {
898   llvm::DenseSet<QualType> Visited;
899   int CreatedValuesCount = 0;
900   initializeFieldsWithValues(Loc, Type, Visited, 0, CreatedValuesCount);
901   if (CreatedValuesCount > MaxCompositeValueSize) {
902     llvm::errs() << "Attempting to initialize a huge value of type: " << Type
903                  << '\n';
904   }
905 }
906 
907 void Environment::setValue(const StorageLocation &Loc, Value &Val) {
908   // Records should not be associated with values.
909   assert(!isa<RecordStorageLocation>(Loc));
910   LocToVal[&Loc] = &Val;
911 }
912 
913 void Environment::setValue(const Expr &E, Value &Val) {
914   const Expr &CanonE = ignoreCFGOmittedNodes(E);
915 
916   assert(CanonE.isPRValue());
917   // Records should not be associated with values.
918   assert(!CanonE.getType()->isRecordType());
919   ExprToVal[&CanonE] = &Val;
920 }
921 
922 Value *Environment::getValue(const StorageLocation &Loc) const {
923   // Records should not be associated with values.
924   assert(!isa<RecordStorageLocation>(Loc));
925   return LocToVal.lookup(&Loc);
926 }
927 
928 Value *Environment::getValue(const ValueDecl &D) const {
929   auto *Loc = getStorageLocation(D);
930   if (Loc == nullptr)
931     return nullptr;
932   return getValue(*Loc);
933 }
934 
935 Value *Environment::getValue(const Expr &E) const {
936   // Records should not be associated with values.
937   assert(!E.getType()->isRecordType());
938 
939   if (E.isPRValue()) {
940     auto It = ExprToVal.find(&ignoreCFGOmittedNodes(E));
941     return It == ExprToVal.end() ? nullptr : It->second;
942   }
943 
944   auto It = ExprToLoc.find(&ignoreCFGOmittedNodes(E));
945   if (It == ExprToLoc.end())
946     return nullptr;
947   return getValue(*It->second);
948 }
949 
950 Value *Environment::createValue(QualType Type) {
951   llvm::DenseSet<QualType> Visited;
952   int CreatedValuesCount = 0;
953   Value *Val = createValueUnlessSelfReferential(Type, Visited, /*Depth=*/0,
954                                                 CreatedValuesCount);
955   if (CreatedValuesCount > MaxCompositeValueSize) {
956     llvm::errs() << "Attempting to initialize a huge value of type: " << Type
957                  << '\n';
958   }
959   return Val;
960 }
961 
962 Value *Environment::createValueUnlessSelfReferential(
963     QualType Type, llvm::DenseSet<QualType> &Visited, int Depth,
964     int &CreatedValuesCount) {
965   assert(!Type.isNull());
966   assert(!Type->isReferenceType());
967   assert(!Type->isRecordType());
968 
969   // Allow unlimited fields at depth 1; only cap at deeper nesting levels.
970   if ((Depth > 1 && CreatedValuesCount > MaxCompositeValueSize) ||
971       Depth > MaxCompositeValueDepth)
972     return nullptr;
973 
974   if (Type->isBooleanType()) {
975     CreatedValuesCount++;
976     return &makeAtomicBoolValue();
977   }
978 
979   if (Type->isIntegerType()) {
980     // FIXME: consider instead `return nullptr`, given that we do nothing useful
981     // with integers, and so distinguishing them serves no purpose, but could
982     // prevent convergence.
983     CreatedValuesCount++;
984     return &arena().create<IntegerValue>();
985   }
986 
987   if (Type->isPointerType()) {
988     CreatedValuesCount++;
989     QualType PointeeType = Type->getPointeeType();
990     StorageLocation &PointeeLoc =
991         createLocAndMaybeValue(PointeeType, Visited, Depth, CreatedValuesCount);
992 
993     return &arena().create<PointerValue>(PointeeLoc);
994   }
995 
996   return nullptr;
997 }
998 
999 StorageLocation &
1000 Environment::createLocAndMaybeValue(QualType Ty,
1001                                     llvm::DenseSet<QualType> &Visited,
1002                                     int Depth, int &CreatedValuesCount) {
1003   if (!Visited.insert(Ty.getCanonicalType()).second)
1004     return createStorageLocation(Ty.getNonReferenceType());
1005   auto EraseVisited = llvm::make_scope_exit(
1006       [&Visited, Ty] { Visited.erase(Ty.getCanonicalType()); });
1007 
1008   Ty = Ty.getNonReferenceType();
1009 
1010   if (Ty->isRecordType()) {
1011     auto &Loc = cast<RecordStorageLocation>(createStorageLocation(Ty));
1012     initializeFieldsWithValues(Loc, Ty, Visited, Depth, CreatedValuesCount);
1013     return Loc;
1014   }
1015 
1016   StorageLocation &Loc = createStorageLocation(Ty);
1017 
1018   if (Value *Val = createValueUnlessSelfReferential(Ty, Visited, Depth,
1019                                                     CreatedValuesCount))
1020     setValue(Loc, *Val);
1021 
1022   return Loc;
1023 }
1024 
1025 void Environment::initializeFieldsWithValues(RecordStorageLocation &Loc,
1026                                              QualType Type,
1027                                              llvm::DenseSet<QualType> &Visited,
1028                                              int Depth,
1029                                              int &CreatedValuesCount) {
1030   auto initField = [&](QualType FieldType, StorageLocation &FieldLoc) {
1031     if (FieldType->isRecordType()) {
1032       auto &FieldRecordLoc = cast<RecordStorageLocation>(FieldLoc);
1033       initializeFieldsWithValues(FieldRecordLoc, FieldRecordLoc.getType(),
1034                                  Visited, Depth + 1, CreatedValuesCount);
1035     } else {
1036       if (getValue(FieldLoc) != nullptr)
1037         return;
1038       if (!Visited.insert(FieldType.getCanonicalType()).second)
1039         return;
1040       if (Value *Val = createValueUnlessSelfReferential(
1041               FieldType, Visited, Depth + 1, CreatedValuesCount))
1042         setValue(FieldLoc, *Val);
1043       Visited.erase(FieldType.getCanonicalType());
1044     }
1045   };
1046 
1047   for (const FieldDecl *Field : DACtx->getModeledFields(Type)) {
1048     assert(Field != nullptr);
1049     QualType FieldType = Field->getType();
1050 
1051     if (FieldType->isReferenceType()) {
1052       Loc.setChild(*Field,
1053                    &createLocAndMaybeValue(FieldType, Visited, Depth + 1,
1054                                            CreatedValuesCount));
1055     } else {
1056       StorageLocation *FieldLoc = Loc.getChild(*Field);
1057       assert(FieldLoc != nullptr);
1058       initField(FieldType, *FieldLoc);
1059     }
1060   }
1061   for (const auto &[FieldName, FieldType] : DACtx->getSyntheticFields(Type)) {
1062     // Synthetic fields cannot have reference type, so we don't need to deal
1063     // with this case.
1064     assert(!FieldType->isReferenceType());
1065     initField(FieldType, Loc.getSyntheticField(FieldName));
1066   }
1067 }
1068 
1069 StorageLocation &Environment::createObjectInternal(const ValueDecl *D,
1070                                                    QualType Ty,
1071                                                    const Expr *InitExpr) {
1072   if (Ty->isReferenceType()) {
1073     // Although variables of reference type always need to be initialized, it
1074     // can happen that we can't see the initializer, so `InitExpr` may still
1075     // be null.
1076     if (InitExpr) {
1077       if (auto *InitExprLoc = getStorageLocation(*InitExpr))
1078         return *InitExprLoc;
1079     }
1080 
1081     // Even though we have an initializer, we might not get an
1082     // InitExprLoc, for example if the InitExpr is a CallExpr for which we
1083     // don't have a function body. In this case, we just invent a storage
1084     // location and value -- it's the best we can do.
1085     return createObjectInternal(D, Ty.getNonReferenceType(), nullptr);
1086   }
1087 
1088   StorageLocation &Loc =
1089       D ? createStorageLocation(*D) : createStorageLocation(Ty);
1090 
1091   if (Ty->isRecordType()) {
1092     auto &RecordLoc = cast<RecordStorageLocation>(Loc);
1093     if (!InitExpr)
1094       initializeFieldsWithValues(RecordLoc);
1095   } else {
1096     Value *Val = nullptr;
1097     if (InitExpr)
1098       // In the (few) cases where an expression is intentionally
1099       // "uninterpreted", `InitExpr` is not associated with a value.  There are
1100       // two ways to handle this situation: propagate the status, so that
1101       // uninterpreted initializers result in uninterpreted variables, or
1102       // provide a default value. We choose the latter so that later refinements
1103       // of the variable can be used for reasoning about the surrounding code.
1104       // For this reason, we let this case be handled by the `createValue()`
1105       // call below.
1106       //
1107       // FIXME. If and when we interpret all language cases, change this to
1108       // assert that `InitExpr` is interpreted, rather than supplying a
1109       // default value (assuming we don't update the environment API to return
1110       // references).
1111       Val = getValue(*InitExpr);
1112     if (!Val)
1113       Val = createValue(Ty);
1114     if (Val)
1115       setValue(Loc, *Val);
1116   }
1117 
1118   return Loc;
1119 }
1120 
1121 void Environment::assume(const Formula &F) {
1122   DACtx->addFlowConditionConstraint(FlowConditionToken, F);
1123 }
1124 
1125 bool Environment::proves(const Formula &F) const {
1126   return DACtx->flowConditionImplies(FlowConditionToken, F);
1127 }
1128 
1129 bool Environment::allows(const Formula &F) const {
1130   return DACtx->flowConditionAllows(FlowConditionToken, F);
1131 }
1132 
1133 void Environment::dump(raw_ostream &OS) const {
1134   llvm::DenseMap<const StorageLocation *, std::string> LocToName;
1135   if (LocForRecordReturnVal != nullptr)
1136     LocToName[LocForRecordReturnVal] = "(returned record)";
1137   if (ThisPointeeLoc != nullptr)
1138     LocToName[ThisPointeeLoc] = "this";
1139 
1140   OS << "DeclToLoc:\n";
1141   for (auto [D, L] : DeclToLoc) {
1142     auto Iter = LocToName.insert({L, D->getNameAsString()}).first;
1143     OS << "  [" << Iter->second << ", " << L << "]\n";
1144   }
1145   OS << "ExprToLoc:\n";
1146   for (auto [E, L] : ExprToLoc)
1147     OS << "  [" << E << ", " << L << "]\n";
1148 
1149   OS << "ExprToVal:\n";
1150   for (auto [E, V] : ExprToVal)
1151     OS << "  [" << E << ", " << V << ": " << *V << "]\n";
1152 
1153   OS << "LocToVal:\n";
1154   for (auto [L, V] : LocToVal) {
1155     OS << "  [" << L;
1156     if (auto Iter = LocToName.find(L); Iter != LocToName.end())
1157       OS << " (" << Iter->second << ")";
1158     OS << ", " << V << ": " << *V << "]\n";
1159   }
1160 
1161   if (const FunctionDecl *Func = getCurrentFunc()) {
1162     if (Func->getReturnType()->isReferenceType()) {
1163       OS << "ReturnLoc: " << ReturnLoc;
1164       if (auto Iter = LocToName.find(ReturnLoc); Iter != LocToName.end())
1165         OS << " (" << Iter->second << ")";
1166       OS << "\n";
1167     } else if (Func->getReturnType()->isRecordType() ||
1168                isa<CXXConstructorDecl>(Func)) {
1169       OS << "LocForRecordReturnVal: " << LocForRecordReturnVal << "\n";
1170     } else if (!Func->getReturnType()->isVoidType()) {
1171       if (ReturnVal == nullptr)
1172         OS << "ReturnVal: nullptr\n";
1173       else
1174         OS << "ReturnVal: " << *ReturnVal << "\n";
1175     }
1176 
1177     if (isa<CXXMethodDecl>(Func)) {
1178       OS << "ThisPointeeLoc: " << ThisPointeeLoc << "\n";
1179     }
1180   }
1181 
1182   OS << "\n";
1183   DACtx->dumpFlowCondition(FlowConditionToken, OS);
1184 }
1185 
1186 void Environment::dump() const { dump(llvm::dbgs()); }
1187 
1188 Environment::PrValueToResultObject Environment::buildResultObjectMap(
1189     DataflowAnalysisContext *DACtx, const FunctionDecl *FuncDecl,
1190     RecordStorageLocation *ThisPointeeLoc,
1191     RecordStorageLocation *LocForRecordReturnVal) {
1192   assert(FuncDecl->doesThisDeclarationHaveABody());
1193 
1194   PrValueToResultObject Map = buildResultObjectMap(
1195       DACtx, FuncDecl->getBody(), ThisPointeeLoc, LocForRecordReturnVal);
1196 
1197   ResultObjectVisitor Visitor(Map, LocForRecordReturnVal, *DACtx);
1198   if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(FuncDecl))
1199     Visitor.TraverseConstructorInits(Ctor, ThisPointeeLoc);
1200 
1201   return Map;
1202 }
1203 
1204 Environment::PrValueToResultObject Environment::buildResultObjectMap(
1205     DataflowAnalysisContext *DACtx, Stmt *S,
1206     RecordStorageLocation *ThisPointeeLoc,
1207     RecordStorageLocation *LocForRecordReturnVal) {
1208   PrValueToResultObject Map;
1209   ResultObjectVisitor Visitor(Map, LocForRecordReturnVal, *DACtx);
1210   Visitor.TraverseStmt(S);
1211   return Map;
1212 }
1213 
1214 RecordStorageLocation *getImplicitObjectLocation(const CXXMemberCallExpr &MCE,
1215                                                  const Environment &Env) {
1216   Expr *ImplicitObject = MCE.getImplicitObjectArgument();
1217   if (ImplicitObject == nullptr)
1218     return nullptr;
1219   if (ImplicitObject->getType()->isPointerType()) {
1220     if (auto *Val = Env.get<PointerValue>(*ImplicitObject))
1221       return &cast<RecordStorageLocation>(Val->getPointeeLoc());
1222     return nullptr;
1223   }
1224   return cast_or_null<RecordStorageLocation>(
1225       Env.getStorageLocation(*ImplicitObject));
1226 }
1227 
1228 RecordStorageLocation *getBaseObjectLocation(const MemberExpr &ME,
1229                                              const Environment &Env) {
1230   Expr *Base = ME.getBase();
1231   if (Base == nullptr)
1232     return nullptr;
1233   if (ME.isArrow()) {
1234     if (auto *Val = Env.get<PointerValue>(*Base))
1235       return &cast<RecordStorageLocation>(Val->getPointeeLoc());
1236     return nullptr;
1237   }
1238   return Env.get<RecordStorageLocation>(*Base);
1239 }
1240 
1241 } // namespace dataflow
1242 } // namespace clang
1243