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