xref: /llvm-project/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp (revision 597a3150e932a9423c65b5ea4b53dd431aff5865)
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   // Don't traverse expressions in unevaluated contexts, as we don't model
354   // fields that are only used in these.
355   // Note: The operand of the `noexcept` operator is an unevaluated operand, but
356   // nevertheless it appears in the Clang CFG, so we don't exclude it here.
357   bool TraverseDecltypeTypeLoc(DecltypeTypeLoc) { return true; }
358   bool TraverseTypeOfExprTypeLoc(TypeOfExprTypeLoc) { return true; }
359   bool TraverseCXXTypeidExpr(CXXTypeidExpr *) { return true; }
360   bool TraverseUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *) {
361     return true;
362   }
363 
364   bool TraverseBindingDecl(BindingDecl *BD) {
365     // `RecursiveASTVisitor` doesn't traverse holding variables for
366     // `BindingDecl`s by itself, so we need to tell it to.
367     if (VarDecl *HoldingVar = BD->getHoldingVar())
368       TraverseDecl(HoldingVar);
369     return RecursiveASTVisitor<ResultObjectVisitor>::TraverseBindingDecl(BD);
370   }
371 
372   bool VisitVarDecl(VarDecl *VD) {
373     if (VD->getType()->isRecordType() && VD->hasInit())
374       PropagateResultObject(
375           VD->getInit(),
376           &cast<RecordStorageLocation>(DACtx.getStableStorageLocation(*VD)));
377     return true;
378   }
379 
380   bool VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *MTE) {
381     if (MTE->getType()->isRecordType())
382       PropagateResultObject(
383           MTE->getSubExpr(),
384           &cast<RecordStorageLocation>(DACtx.getStableStorageLocation(*MTE)));
385     return true;
386   }
387 
388   bool VisitReturnStmt(ReturnStmt *Return) {
389     Expr *RetValue = Return->getRetValue();
390     if (RetValue != nullptr && RetValue->getType()->isRecordType() &&
391         RetValue->isPRValue())
392       PropagateResultObject(RetValue, LocForRecordReturnVal);
393     return true;
394   }
395 
396   bool VisitExpr(Expr *E) {
397     // Clang's AST can have record-type prvalues without a result object -- for
398     // example as full-expressions contained in a compound statement or as
399     // arguments of call expressions. We notice this if we get here and a
400     // storage location has not yet been associated with `E`. In this case,
401     // treat this as if it was a `MaterializeTemporaryExpr`.
402     if (E->isPRValue() && E->getType()->isRecordType() &&
403         !ResultObjectMap.contains(E))
404       PropagateResultObject(
405           E, &cast<RecordStorageLocation>(DACtx.getStableStorageLocation(*E)));
406     return true;
407   }
408 
409   void
410   PropagateResultObjectToRecordInitList(const RecordInitListHelper &InitList,
411                                         RecordStorageLocation *Loc) {
412     for (auto [Base, Init] : InitList.base_inits()) {
413       assert(Base->getType().getCanonicalType() ==
414              Init->getType().getCanonicalType());
415 
416       // Storage location for the base class is the same as that of the
417       // derived class because we "flatten" the object hierarchy and put all
418       // fields in `RecordStorageLocation` of the derived class.
419       PropagateResultObject(Init, Loc);
420     }
421 
422     for (auto [Field, Init] : InitList.field_inits()) {
423       // Fields of non-record type are handled in
424       // `TransferVisitor::VisitInitListExpr()`.
425       if (Field->getType()->isRecordType())
426         PropagateResultObject(
427             Init, cast<RecordStorageLocation>(Loc->getChild(*Field)));
428     }
429   }
430 
431   // Assigns `Loc` as the result object location of `E`, then propagates the
432   // location to all lower-level prvalues that initialize the same object as
433   // `E` (or one of its base classes or member variables).
434   void PropagateResultObject(Expr *E, RecordStorageLocation *Loc) {
435     if (!E->isPRValue() || !E->getType()->isRecordType()) {
436       assert(false);
437       // Ensure we don't propagate the result object if we hit this in a
438       // release build.
439       return;
440     }
441 
442     ResultObjectMap[E] = Loc;
443 
444     // The following AST node kinds are "original initializers": They are the
445     // lowest-level AST node that initializes a given object, and nothing
446     // below them can initialize the same object (or part of it).
447     if (isa<CXXConstructExpr>(E) || isa<CallExpr>(E) || isa<LambdaExpr>(E) ||
448         isa<CXXDefaultArgExpr>(E) || isa<CXXDefaultInitExpr>(E) ||
449         isa<CXXStdInitializerListExpr>(E) ||
450         // We treat `BuiltinBitCastExpr` as an "original initializer" too as
451         // it may not even be casting from a record type -- and even if it is,
452         // the two objects are in general of unrelated type.
453         isa<BuiltinBitCastExpr>(E)) {
454       return;
455     }
456     if (auto *Op = dyn_cast<BinaryOperator>(E);
457         Op && Op->getOpcode() == BO_Cmp) {
458       // Builtin `<=>` returns a `std::strong_ordering` object.
459       return;
460     }
461 
462     if (auto *InitList = dyn_cast<InitListExpr>(E)) {
463       if (!InitList->isSemanticForm())
464         return;
465       if (InitList->isTransparent()) {
466         PropagateResultObject(InitList->getInit(0), Loc);
467         return;
468       }
469 
470       PropagateResultObjectToRecordInitList(RecordInitListHelper(InitList),
471                                             Loc);
472       return;
473     }
474 
475     if (auto *ParenInitList = dyn_cast<CXXParenListInitExpr>(E)) {
476       PropagateResultObjectToRecordInitList(RecordInitListHelper(ParenInitList),
477                                             Loc);
478       return;
479     }
480 
481     if (auto *Op = dyn_cast<BinaryOperator>(E); Op && Op->isCommaOp()) {
482       PropagateResultObject(Op->getRHS(), Loc);
483       return;
484     }
485 
486     if (auto *Cond = dyn_cast<AbstractConditionalOperator>(E)) {
487       PropagateResultObject(Cond->getTrueExpr(), Loc);
488       PropagateResultObject(Cond->getFalseExpr(), Loc);
489       return;
490     }
491 
492     if (auto *SE = dyn_cast<StmtExpr>(E)) {
493       PropagateResultObject(cast<Expr>(SE->getSubStmt()->body_back()), Loc);
494       return;
495     }
496 
497     // All other expression nodes that propagate a record prvalue should have
498     // exactly one child.
499     SmallVector<Stmt *, 1> Children(E->child_begin(), E->child_end());
500     LLVM_DEBUG({
501       if (Children.size() != 1)
502         E->dump();
503     });
504     assert(Children.size() == 1);
505     for (Stmt *S : Children)
506       PropagateResultObject(cast<Expr>(S), Loc);
507   }
508 
509 private:
510   llvm::DenseMap<const Expr *, RecordStorageLocation *> &ResultObjectMap;
511   RecordStorageLocation *LocForRecordReturnVal;
512   DataflowAnalysisContext &DACtx;
513 };
514 
515 } // namespace
516 
517 Environment::Environment(DataflowAnalysisContext &DACtx)
518     : DACtx(&DACtx),
519       FlowConditionToken(DACtx.arena().makeFlowConditionToken()) {}
520 
521 Environment::Environment(DataflowAnalysisContext &DACtx,
522                          const DeclContext &DeclCtx)
523     : Environment(DACtx) {
524   CallStack.push_back(&DeclCtx);
525 }
526 
527 void Environment::initialize() {
528   const DeclContext *DeclCtx = getDeclCtx();
529   if (DeclCtx == nullptr)
530     return;
531 
532   const auto *FuncDecl = dyn_cast<FunctionDecl>(DeclCtx);
533   if (FuncDecl == nullptr)
534     return;
535 
536   assert(FuncDecl->doesThisDeclarationHaveABody());
537 
538   initFieldsGlobalsAndFuncs(FuncDecl);
539 
540   for (const auto *ParamDecl : FuncDecl->parameters()) {
541     assert(ParamDecl != nullptr);
542     setStorageLocation(*ParamDecl, createObject(*ParamDecl, nullptr));
543   }
544 
545   if (FuncDecl->getReturnType()->isRecordType())
546     LocForRecordReturnVal = &cast<RecordStorageLocation>(
547         createStorageLocation(FuncDecl->getReturnType()));
548 
549   if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(DeclCtx)) {
550     auto *Parent = MethodDecl->getParent();
551     assert(Parent != nullptr);
552 
553     if (Parent->isLambda()) {
554       for (const auto &Capture : Parent->captures()) {
555         if (Capture.capturesVariable()) {
556           const auto *VarDecl = Capture.getCapturedVar();
557           assert(VarDecl != nullptr);
558           setStorageLocation(*VarDecl, createObject(*VarDecl, nullptr));
559         } else if (Capture.capturesThis()) {
560           const auto *SurroundingMethodDecl =
561               cast<CXXMethodDecl>(DeclCtx->getNonClosureAncestor());
562           QualType ThisPointeeType =
563               SurroundingMethodDecl->getFunctionObjectParameterType();
564           setThisPointeeStorageLocation(
565               cast<RecordStorageLocation>(createObject(ThisPointeeType)));
566         }
567       }
568     } else if (MethodDecl->isImplicitObjectMemberFunction()) {
569       QualType ThisPointeeType = MethodDecl->getFunctionObjectParameterType();
570       auto &ThisLoc =
571           cast<RecordStorageLocation>(createStorageLocation(ThisPointeeType));
572       setThisPointeeStorageLocation(ThisLoc);
573       // Initialize fields of `*this` with values, but only if we're not
574       // analyzing a constructor; after all, it's the constructor's job to do
575       // this (and we want to be able to test that).
576       if (!isa<CXXConstructorDecl>(MethodDecl))
577         initializeFieldsWithValues(ThisLoc);
578     }
579   }
580 
581   // We do this below the handling of `CXXMethodDecl` above so that we can
582   // be sure that the storage location for `this` has been set.
583   ResultObjectMap = std::make_shared<PrValueToResultObject>(
584       buildResultObjectMap(DACtx, FuncDecl, getThisPointeeStorageLocation(),
585                            LocForRecordReturnVal));
586 }
587 
588 // FIXME: Add support for resetting globals after function calls to enable
589 // the implementation of sound analyses.
590 void Environment::initFieldsGlobalsAndFuncs(const FunctionDecl *FuncDecl) {
591   assert(FuncDecl->doesThisDeclarationHaveABody());
592 
593   ReferencedDecls Referenced = getReferencedDecls(*FuncDecl);
594 
595   // These have to be added before the lines that follow to ensure that
596   // `create*` work correctly for structs.
597   DACtx->addModeledFields(Referenced.Fields);
598 
599   for (const VarDecl *D : Referenced.Globals) {
600     if (getStorageLocation(*D) != nullptr)
601       continue;
602 
603     // We don't run transfer functions on the initializers of global variables,
604     // so they won't be associated with a value or storage location. We
605     // therefore intentionally don't pass an initializer to `createObject()`;
606     // in particular, this ensures that `createObject()` will initialize the
607     // fields of record-type variables with values.
608     setStorageLocation(*D, createObject(*D, nullptr));
609   }
610 
611   for (const FunctionDecl *FD : Referenced.Functions) {
612     if (getStorageLocation(*FD) != nullptr)
613       continue;
614     auto &Loc = createStorageLocation(*FD);
615     setStorageLocation(*FD, Loc);
616   }
617 }
618 
619 Environment Environment::fork() const {
620   Environment Copy(*this);
621   Copy.FlowConditionToken = DACtx->forkFlowCondition(FlowConditionToken);
622   return Copy;
623 }
624 
625 bool Environment::canDescend(unsigned MaxDepth,
626                              const DeclContext *Callee) const {
627   return CallStack.size() <= MaxDepth && !llvm::is_contained(CallStack, Callee);
628 }
629 
630 Environment Environment::pushCall(const CallExpr *Call) const {
631   Environment Env(*this);
632 
633   if (const auto *MethodCall = dyn_cast<CXXMemberCallExpr>(Call)) {
634     if (const Expr *Arg = MethodCall->getImplicitObjectArgument()) {
635       if (!isa<CXXThisExpr>(Arg))
636         Env.ThisPointeeLoc =
637             cast<RecordStorageLocation>(getStorageLocation(*Arg));
638       // Otherwise (when the argument is `this`), retain the current
639       // environment's `ThisPointeeLoc`.
640     }
641   }
642 
643   if (Call->getType()->isRecordType() && Call->isPRValue())
644     Env.LocForRecordReturnVal = &Env.getResultObjectLocation(*Call);
645 
646   Env.pushCallInternal(Call->getDirectCallee(),
647                        llvm::ArrayRef(Call->getArgs(), Call->getNumArgs()));
648 
649   return Env;
650 }
651 
652 Environment Environment::pushCall(const CXXConstructExpr *Call) const {
653   Environment Env(*this);
654 
655   Env.ThisPointeeLoc = &Env.getResultObjectLocation(*Call);
656   Env.LocForRecordReturnVal = &Env.getResultObjectLocation(*Call);
657 
658   Env.pushCallInternal(Call->getConstructor(),
659                        llvm::ArrayRef(Call->getArgs(), Call->getNumArgs()));
660 
661   return Env;
662 }
663 
664 void Environment::pushCallInternal(const FunctionDecl *FuncDecl,
665                                    ArrayRef<const Expr *> Args) {
666   // Canonicalize to the definition of the function. This ensures that we're
667   // putting arguments into the same `ParamVarDecl`s` that the callee will later
668   // be retrieving them from.
669   assert(FuncDecl->getDefinition() != nullptr);
670   FuncDecl = FuncDecl->getDefinition();
671 
672   CallStack.push_back(FuncDecl);
673 
674   initFieldsGlobalsAndFuncs(FuncDecl);
675 
676   const auto *ParamIt = FuncDecl->param_begin();
677 
678   // FIXME: Parameters don't always map to arguments 1:1; examples include
679   // overloaded operators implemented as member functions, and parameter packs.
680   for (unsigned ArgIndex = 0; ArgIndex < Args.size(); ++ParamIt, ++ArgIndex) {
681     assert(ParamIt != FuncDecl->param_end());
682     const VarDecl *Param = *ParamIt;
683     setStorageLocation(*Param, createObject(*Param, Args[ArgIndex]));
684   }
685 
686   ResultObjectMap = std::make_shared<PrValueToResultObject>(
687       buildResultObjectMap(DACtx, FuncDecl, getThisPointeeStorageLocation(),
688                            LocForRecordReturnVal));
689 }
690 
691 void Environment::popCall(const CallExpr *Call, const Environment &CalleeEnv) {
692   // We ignore some entries of `CalleeEnv`:
693   // - `DACtx` because is already the same in both
694   // - We don't want the callee's `DeclCtx`, `ReturnVal`, `ReturnLoc` or
695   //   `ThisPointeeLoc` because they don't apply to us.
696   // - `DeclToLoc`, `ExprToLoc`, and `ExprToVal` capture information from the
697   //   callee's local scope, so when popping that scope, we do not propagate
698   //   the maps.
699   this->LocToVal = std::move(CalleeEnv.LocToVal);
700   this->FlowConditionToken = std::move(CalleeEnv.FlowConditionToken);
701 
702   if (Call->isGLValue()) {
703     if (CalleeEnv.ReturnLoc != nullptr)
704       setStorageLocation(*Call, *CalleeEnv.ReturnLoc);
705   } else if (!Call->getType()->isVoidType()) {
706     if (CalleeEnv.ReturnVal != nullptr)
707       setValue(*Call, *CalleeEnv.ReturnVal);
708   }
709 }
710 
711 void Environment::popCall(const CXXConstructExpr *Call,
712                           const Environment &CalleeEnv) {
713   // See also comment in `popCall(const CallExpr *, const Environment &)` above.
714   this->LocToVal = std::move(CalleeEnv.LocToVal);
715   this->FlowConditionToken = std::move(CalleeEnv.FlowConditionToken);
716 }
717 
718 bool Environment::equivalentTo(const Environment &Other,
719                                Environment::ValueModel &Model) const {
720   assert(DACtx == Other.DACtx);
721 
722   if (ReturnVal != Other.ReturnVal)
723     return false;
724 
725   if (ReturnLoc != Other.ReturnLoc)
726     return false;
727 
728   if (LocForRecordReturnVal != Other.LocForRecordReturnVal)
729     return false;
730 
731   if (ThisPointeeLoc != Other.ThisPointeeLoc)
732     return false;
733 
734   if (DeclToLoc != Other.DeclToLoc)
735     return false;
736 
737   if (ExprToLoc != Other.ExprToLoc)
738     return false;
739 
740   if (!compareKeyToValueMaps(ExprToVal, Other.ExprToVal, *this, Other, Model))
741     return false;
742 
743   if (!compareKeyToValueMaps(LocToVal, Other.LocToVal, *this, Other, Model))
744     return false;
745 
746   return true;
747 }
748 
749 LatticeEffect Environment::widen(const Environment &PrevEnv,
750                                  Environment::ValueModel &Model) {
751   assert(DACtx == PrevEnv.DACtx);
752   assert(ReturnVal == PrevEnv.ReturnVal);
753   assert(ReturnLoc == PrevEnv.ReturnLoc);
754   assert(LocForRecordReturnVal == PrevEnv.LocForRecordReturnVal);
755   assert(ThisPointeeLoc == PrevEnv.ThisPointeeLoc);
756   assert(CallStack == PrevEnv.CallStack);
757   assert(ResultObjectMap == PrevEnv.ResultObjectMap);
758 
759   auto Effect = LatticeEffect::Unchanged;
760 
761   // By the API, `PrevEnv` is a previous version of the environment for the same
762   // block, so we have some guarantees about its shape. In particular, it will
763   // be the result of a join or widen operation on previous values for this
764   // block. For `DeclToLoc`, `ExprToVal`, and `ExprToLoc`, join guarantees that
765   // these maps are subsets of the maps in `PrevEnv`. So, as long as we maintain
766   // this property here, we don't need change their current values to widen.
767   assert(DeclToLoc.size() <= PrevEnv.DeclToLoc.size());
768   assert(ExprToVal.size() <= PrevEnv.ExprToVal.size());
769   assert(ExprToLoc.size() <= PrevEnv.ExprToLoc.size());
770 
771   ExprToVal = widenKeyToValueMap(ExprToVal, PrevEnv.ExprToVal, *this, PrevEnv,
772                                  Model, Effect);
773 
774   LocToVal = widenKeyToValueMap(LocToVal, PrevEnv.LocToVal, *this, PrevEnv,
775                                 Model, Effect);
776   if (DeclToLoc.size() != PrevEnv.DeclToLoc.size() ||
777       ExprToLoc.size() != PrevEnv.ExprToLoc.size() ||
778       ExprToVal.size() != PrevEnv.ExprToVal.size() ||
779       LocToVal.size() != PrevEnv.LocToVal.size())
780     Effect = LatticeEffect::Changed;
781 
782   return Effect;
783 }
784 
785 Environment Environment::join(const Environment &EnvA, const Environment &EnvB,
786                               Environment::ValueModel &Model,
787                               ExprJoinBehavior ExprBehavior) {
788   assert(EnvA.DACtx == EnvB.DACtx);
789   assert(EnvA.LocForRecordReturnVal == EnvB.LocForRecordReturnVal);
790   assert(EnvA.ThisPointeeLoc == EnvB.ThisPointeeLoc);
791   assert(EnvA.CallStack == EnvB.CallStack);
792   assert(EnvA.ResultObjectMap == EnvB.ResultObjectMap);
793 
794   Environment JoinedEnv(*EnvA.DACtx);
795 
796   JoinedEnv.CallStack = EnvA.CallStack;
797   JoinedEnv.ResultObjectMap = EnvA.ResultObjectMap;
798   JoinedEnv.LocForRecordReturnVal = EnvA.LocForRecordReturnVal;
799   JoinedEnv.ThisPointeeLoc = EnvA.ThisPointeeLoc;
800 
801   if (EnvA.CallStack.empty()) {
802     JoinedEnv.ReturnVal = nullptr;
803   } else {
804     // FIXME: Make `CallStack` a vector of `FunctionDecl` so we don't need this
805     // cast.
806     auto *Func = dyn_cast<FunctionDecl>(EnvA.CallStack.back());
807     assert(Func != nullptr);
808     JoinedEnv.ReturnVal =
809         joinValues(Func->getReturnType(), EnvA.ReturnVal, EnvA, EnvB.ReturnVal,
810                    EnvB, JoinedEnv, Model);
811   }
812 
813   if (EnvA.ReturnLoc == EnvB.ReturnLoc)
814     JoinedEnv.ReturnLoc = EnvA.ReturnLoc;
815   else
816     JoinedEnv.ReturnLoc = nullptr;
817 
818   JoinedEnv.DeclToLoc = intersectDeclToLoc(EnvA.DeclToLoc, EnvB.DeclToLoc);
819 
820   // FIXME: update join to detect backedges and simplify the flow condition
821   // accordingly.
822   JoinedEnv.FlowConditionToken = EnvA.DACtx->joinFlowConditions(
823       EnvA.FlowConditionToken, EnvB.FlowConditionToken);
824 
825   JoinedEnv.LocToVal =
826       joinLocToVal(EnvA.LocToVal, EnvB.LocToVal, EnvA, EnvB, JoinedEnv, Model);
827 
828   if (ExprBehavior == KeepExprState) {
829     JoinedEnv.ExprToVal = joinExprMaps(EnvA.ExprToVal, EnvB.ExprToVal);
830     JoinedEnv.ExprToLoc = joinExprMaps(EnvA.ExprToLoc, EnvB.ExprToLoc);
831   }
832 
833   return JoinedEnv;
834 }
835 
836 Value *Environment::joinValues(QualType Ty, Value *Val1,
837                                const Environment &Env1, Value *Val2,
838                                const Environment &Env2, Environment &JoinedEnv,
839                                Environment::ValueModel &Model) {
840   if (Val1 == nullptr || Val2 == nullptr)
841     // We can't say anything about the joined value -- even if one of the values
842     // is non-null, we don't want to simply propagate it, because it would be
843     // too specific: Because the other value is null, that means we have no
844     // information at all about the value (i.e. the value is unconstrained).
845     return nullptr;
846 
847   if (areEquivalentValues(*Val1, *Val2))
848     // Arbitrarily return one of the two values.
849     return Val1;
850 
851   return joinDistinctValues(Ty, *Val1, Env1, *Val2, Env2, JoinedEnv, Model);
852 }
853 
854 StorageLocation &Environment::createStorageLocation(QualType Type) {
855   return DACtx->createStorageLocation(Type);
856 }
857 
858 StorageLocation &Environment::createStorageLocation(const ValueDecl &D) {
859   // Evaluated declarations are always assigned the same storage locations to
860   // ensure that the environment stabilizes across loop iterations. Storage
861   // locations for evaluated declarations are stored in the analysis context.
862   return DACtx->getStableStorageLocation(D);
863 }
864 
865 StorageLocation &Environment::createStorageLocation(const Expr &E) {
866   // Evaluated expressions are always assigned the same storage locations to
867   // ensure that the environment stabilizes across loop iterations. Storage
868   // locations for evaluated expressions are stored in the analysis context.
869   return DACtx->getStableStorageLocation(E);
870 }
871 
872 void Environment::setStorageLocation(const ValueDecl &D, StorageLocation &Loc) {
873   assert(!DeclToLoc.contains(&D));
874   // The only kinds of declarations that may have a "variable" storage location
875   // are declarations of reference type and `BindingDecl`. For all other
876   // declaration, the storage location should be the stable storage location
877   // returned by `createStorageLocation()`.
878   assert(D.getType()->isReferenceType() || isa<BindingDecl>(D) ||
879          &Loc == &createStorageLocation(D));
880   DeclToLoc[&D] = &Loc;
881 }
882 
883 StorageLocation *Environment::getStorageLocation(const ValueDecl &D) const {
884   auto It = DeclToLoc.find(&D);
885   if (It == DeclToLoc.end())
886     return nullptr;
887 
888   StorageLocation *Loc = It->second;
889 
890   return Loc;
891 }
892 
893 void Environment::removeDecl(const ValueDecl &D) { DeclToLoc.erase(&D); }
894 
895 void Environment::setStorageLocation(const Expr &E, StorageLocation &Loc) {
896   // `DeclRefExpr`s to builtin function types aren't glvalues, for some reason,
897   // but we still want to be able to associate a `StorageLocation` with them,
898   // so allow these as an exception.
899   assert(E.isGLValue() ||
900          E.getType()->isSpecificBuiltinType(BuiltinType::BuiltinFn));
901   const Expr &CanonE = ignoreCFGOmittedNodes(E);
902   assert(!ExprToLoc.contains(&CanonE));
903   ExprToLoc[&CanonE] = &Loc;
904 }
905 
906 StorageLocation *Environment::getStorageLocation(const Expr &E) const {
907   // See comment in `setStorageLocation()`.
908   assert(E.isGLValue() ||
909          E.getType()->isSpecificBuiltinType(BuiltinType::BuiltinFn));
910   auto It = ExprToLoc.find(&ignoreCFGOmittedNodes(E));
911   return It == ExprToLoc.end() ? nullptr : &*It->second;
912 }
913 
914 RecordStorageLocation &
915 Environment::getResultObjectLocation(const Expr &RecordPRValue) const {
916   assert(RecordPRValue.getType()->isRecordType());
917   assert(RecordPRValue.isPRValue());
918 
919   assert(ResultObjectMap != nullptr);
920   RecordStorageLocation *Loc = ResultObjectMap->lookup(&RecordPRValue);
921   assert(Loc != nullptr);
922   // In release builds, use the "stable" storage location if the map lookup
923   // failed.
924   if (Loc == nullptr)
925     return cast<RecordStorageLocation>(
926         DACtx->getStableStorageLocation(RecordPRValue));
927   return *Loc;
928 }
929 
930 PointerValue &Environment::getOrCreateNullPointerValue(QualType PointeeType) {
931   return DACtx->getOrCreateNullPointerValue(PointeeType);
932 }
933 
934 void Environment::initializeFieldsWithValues(RecordStorageLocation &Loc,
935                                              QualType Type) {
936   llvm::DenseSet<QualType> Visited;
937   int CreatedValuesCount = 0;
938   initializeFieldsWithValues(Loc, Type, Visited, 0, CreatedValuesCount);
939   if (CreatedValuesCount > MaxCompositeValueSize) {
940     llvm::errs() << "Attempting to initialize a huge value of type: " << Type
941                  << '\n';
942   }
943 }
944 
945 void Environment::setValue(const StorageLocation &Loc, Value &Val) {
946   // Records should not be associated with values.
947   assert(!isa<RecordStorageLocation>(Loc));
948   LocToVal[&Loc] = &Val;
949 }
950 
951 void Environment::setValue(const Expr &E, Value &Val) {
952   const Expr &CanonE = ignoreCFGOmittedNodes(E);
953 
954   assert(CanonE.isPRValue());
955   // Records should not be associated with values.
956   assert(!CanonE.getType()->isRecordType());
957   ExprToVal[&CanonE] = &Val;
958 }
959 
960 Value *Environment::getValue(const StorageLocation &Loc) const {
961   // Records should not be associated with values.
962   assert(!isa<RecordStorageLocation>(Loc));
963   return LocToVal.lookup(&Loc);
964 }
965 
966 Value *Environment::getValue(const ValueDecl &D) const {
967   auto *Loc = getStorageLocation(D);
968   if (Loc == nullptr)
969     return nullptr;
970   return getValue(*Loc);
971 }
972 
973 Value *Environment::getValue(const Expr &E) const {
974   // Records should not be associated with values.
975   assert(!E.getType()->isRecordType());
976 
977   if (E.isPRValue()) {
978     auto It = ExprToVal.find(&ignoreCFGOmittedNodes(E));
979     return It == ExprToVal.end() ? nullptr : It->second;
980   }
981 
982   auto It = ExprToLoc.find(&ignoreCFGOmittedNodes(E));
983   if (It == ExprToLoc.end())
984     return nullptr;
985   return getValue(*It->second);
986 }
987 
988 Value *Environment::createValue(QualType Type) {
989   llvm::DenseSet<QualType> Visited;
990   int CreatedValuesCount = 0;
991   Value *Val = createValueUnlessSelfReferential(Type, Visited, /*Depth=*/0,
992                                                 CreatedValuesCount);
993   if (CreatedValuesCount > MaxCompositeValueSize) {
994     llvm::errs() << "Attempting to initialize a huge value of type: " << Type
995                  << '\n';
996   }
997   return Val;
998 }
999 
1000 Value *Environment::createValueUnlessSelfReferential(
1001     QualType Type, llvm::DenseSet<QualType> &Visited, int Depth,
1002     int &CreatedValuesCount) {
1003   assert(!Type.isNull());
1004   assert(!Type->isReferenceType());
1005   assert(!Type->isRecordType());
1006 
1007   // Allow unlimited fields at depth 1; only cap at deeper nesting levels.
1008   if ((Depth > 1 && CreatedValuesCount > MaxCompositeValueSize) ||
1009       Depth > MaxCompositeValueDepth)
1010     return nullptr;
1011 
1012   if (Type->isBooleanType()) {
1013     CreatedValuesCount++;
1014     return &makeAtomicBoolValue();
1015   }
1016 
1017   if (Type->isIntegerType()) {
1018     // FIXME: consider instead `return nullptr`, given that we do nothing useful
1019     // with integers, and so distinguishing them serves no purpose, but could
1020     // prevent convergence.
1021     CreatedValuesCount++;
1022     return &arena().create<IntegerValue>();
1023   }
1024 
1025   if (Type->isPointerType()) {
1026     CreatedValuesCount++;
1027     QualType PointeeType = Type->getPointeeType();
1028     StorageLocation &PointeeLoc =
1029         createLocAndMaybeValue(PointeeType, Visited, Depth, CreatedValuesCount);
1030 
1031     return &arena().create<PointerValue>(PointeeLoc);
1032   }
1033 
1034   return nullptr;
1035 }
1036 
1037 StorageLocation &
1038 Environment::createLocAndMaybeValue(QualType Ty,
1039                                     llvm::DenseSet<QualType> &Visited,
1040                                     int Depth, int &CreatedValuesCount) {
1041   if (!Visited.insert(Ty.getCanonicalType()).second)
1042     return createStorageLocation(Ty.getNonReferenceType());
1043   auto EraseVisited = llvm::make_scope_exit(
1044       [&Visited, Ty] { Visited.erase(Ty.getCanonicalType()); });
1045 
1046   Ty = Ty.getNonReferenceType();
1047 
1048   if (Ty->isRecordType()) {
1049     auto &Loc = cast<RecordStorageLocation>(createStorageLocation(Ty));
1050     initializeFieldsWithValues(Loc, Ty, Visited, Depth, CreatedValuesCount);
1051     return Loc;
1052   }
1053 
1054   StorageLocation &Loc = createStorageLocation(Ty);
1055 
1056   if (Value *Val = createValueUnlessSelfReferential(Ty, Visited, Depth,
1057                                                     CreatedValuesCount))
1058     setValue(Loc, *Val);
1059 
1060   return Loc;
1061 }
1062 
1063 void Environment::initializeFieldsWithValues(RecordStorageLocation &Loc,
1064                                              QualType Type,
1065                                              llvm::DenseSet<QualType> &Visited,
1066                                              int Depth,
1067                                              int &CreatedValuesCount) {
1068   auto initField = [&](QualType FieldType, StorageLocation &FieldLoc) {
1069     if (FieldType->isRecordType()) {
1070       auto &FieldRecordLoc = cast<RecordStorageLocation>(FieldLoc);
1071       initializeFieldsWithValues(FieldRecordLoc, FieldRecordLoc.getType(),
1072                                  Visited, Depth + 1, CreatedValuesCount);
1073     } else {
1074       if (getValue(FieldLoc) != nullptr)
1075         return;
1076       if (!Visited.insert(FieldType.getCanonicalType()).second)
1077         return;
1078       if (Value *Val = createValueUnlessSelfReferential(
1079               FieldType, Visited, Depth + 1, CreatedValuesCount))
1080         setValue(FieldLoc, *Val);
1081       Visited.erase(FieldType.getCanonicalType());
1082     }
1083   };
1084 
1085   for (const FieldDecl *Field : DACtx->getModeledFields(Type)) {
1086     assert(Field != nullptr);
1087     QualType FieldType = Field->getType();
1088 
1089     if (FieldType->isReferenceType()) {
1090       Loc.setChild(*Field,
1091                    &createLocAndMaybeValue(FieldType, Visited, Depth + 1,
1092                                            CreatedValuesCount));
1093     } else {
1094       StorageLocation *FieldLoc = Loc.getChild(*Field);
1095       assert(FieldLoc != nullptr);
1096       initField(FieldType, *FieldLoc);
1097     }
1098   }
1099   for (const auto &[FieldName, FieldType] : DACtx->getSyntheticFields(Type)) {
1100     // Synthetic fields cannot have reference type, so we don't need to deal
1101     // with this case.
1102     assert(!FieldType->isReferenceType());
1103     initField(FieldType, Loc.getSyntheticField(FieldName));
1104   }
1105 }
1106 
1107 StorageLocation &Environment::createObjectInternal(const ValueDecl *D,
1108                                                    QualType Ty,
1109                                                    const Expr *InitExpr) {
1110   if (Ty->isReferenceType()) {
1111     // Although variables of reference type always need to be initialized, it
1112     // can happen that we can't see the initializer, so `InitExpr` may still
1113     // be null.
1114     if (InitExpr) {
1115       if (auto *InitExprLoc = getStorageLocation(*InitExpr))
1116         return *InitExprLoc;
1117     }
1118 
1119     // Even though we have an initializer, we might not get an
1120     // InitExprLoc, for example if the InitExpr is a CallExpr for which we
1121     // don't have a function body. In this case, we just invent a storage
1122     // location and value -- it's the best we can do.
1123     return createObjectInternal(D, Ty.getNonReferenceType(), nullptr);
1124   }
1125 
1126   StorageLocation &Loc =
1127       D ? createStorageLocation(*D) : createStorageLocation(Ty);
1128 
1129   if (Ty->isRecordType()) {
1130     auto &RecordLoc = cast<RecordStorageLocation>(Loc);
1131     if (!InitExpr)
1132       initializeFieldsWithValues(RecordLoc);
1133   } else {
1134     Value *Val = nullptr;
1135     if (InitExpr)
1136       // In the (few) cases where an expression is intentionally
1137       // "uninterpreted", `InitExpr` is not associated with a value.  There are
1138       // two ways to handle this situation: propagate the status, so that
1139       // uninterpreted initializers result in uninterpreted variables, or
1140       // provide a default value. We choose the latter so that later refinements
1141       // of the variable can be used for reasoning about the surrounding code.
1142       // For this reason, we let this case be handled by the `createValue()`
1143       // call below.
1144       //
1145       // FIXME. If and when we interpret all language cases, change this to
1146       // assert that `InitExpr` is interpreted, rather than supplying a
1147       // default value (assuming we don't update the environment API to return
1148       // references).
1149       Val = getValue(*InitExpr);
1150     if (!Val)
1151       Val = createValue(Ty);
1152     if (Val)
1153       setValue(Loc, *Val);
1154   }
1155 
1156   return Loc;
1157 }
1158 
1159 void Environment::assume(const Formula &F) {
1160   DACtx->addFlowConditionConstraint(FlowConditionToken, F);
1161 }
1162 
1163 bool Environment::proves(const Formula &F) const {
1164   return DACtx->flowConditionImplies(FlowConditionToken, F);
1165 }
1166 
1167 bool Environment::allows(const Formula &F) const {
1168   return DACtx->flowConditionAllows(FlowConditionToken, F);
1169 }
1170 
1171 void Environment::dump(raw_ostream &OS) const {
1172   llvm::DenseMap<const StorageLocation *, std::string> LocToName;
1173   if (LocForRecordReturnVal != nullptr)
1174     LocToName[LocForRecordReturnVal] = "(returned record)";
1175   if (ThisPointeeLoc != nullptr)
1176     LocToName[ThisPointeeLoc] = "this";
1177 
1178   OS << "DeclToLoc:\n";
1179   for (auto [D, L] : DeclToLoc) {
1180     auto Iter = LocToName.insert({L, D->getNameAsString()}).first;
1181     OS << "  [" << Iter->second << ", " << L << "]\n";
1182   }
1183   OS << "ExprToLoc:\n";
1184   for (auto [E, L] : ExprToLoc)
1185     OS << "  [" << E << ", " << L << "]\n";
1186 
1187   OS << "ExprToVal:\n";
1188   for (auto [E, V] : ExprToVal)
1189     OS << "  [" << E << ", " << V << ": " << *V << "]\n";
1190 
1191   OS << "LocToVal:\n";
1192   for (auto [L, V] : LocToVal) {
1193     OS << "  [" << L;
1194     if (auto Iter = LocToName.find(L); Iter != LocToName.end())
1195       OS << " (" << Iter->second << ")";
1196     OS << ", " << V << ": " << *V << "]\n";
1197   }
1198 
1199   if (const FunctionDecl *Func = getCurrentFunc()) {
1200     if (Func->getReturnType()->isReferenceType()) {
1201       OS << "ReturnLoc: " << ReturnLoc;
1202       if (auto Iter = LocToName.find(ReturnLoc); Iter != LocToName.end())
1203         OS << " (" << Iter->second << ")";
1204       OS << "\n";
1205     } else if (Func->getReturnType()->isRecordType() ||
1206                isa<CXXConstructorDecl>(Func)) {
1207       OS << "LocForRecordReturnVal: " << LocForRecordReturnVal << "\n";
1208     } else if (!Func->getReturnType()->isVoidType()) {
1209       if (ReturnVal == nullptr)
1210         OS << "ReturnVal: nullptr\n";
1211       else
1212         OS << "ReturnVal: " << *ReturnVal << "\n";
1213     }
1214 
1215     if (isa<CXXMethodDecl>(Func)) {
1216       OS << "ThisPointeeLoc: " << ThisPointeeLoc << "\n";
1217     }
1218   }
1219 
1220   OS << "\n";
1221   DACtx->dumpFlowCondition(FlowConditionToken, OS);
1222 }
1223 
1224 void Environment::dump() const { dump(llvm::dbgs()); }
1225 
1226 Environment::PrValueToResultObject Environment::buildResultObjectMap(
1227     DataflowAnalysisContext *DACtx, const FunctionDecl *FuncDecl,
1228     RecordStorageLocation *ThisPointeeLoc,
1229     RecordStorageLocation *LocForRecordReturnVal) {
1230   assert(FuncDecl->doesThisDeclarationHaveABody());
1231 
1232   PrValueToResultObject Map;
1233 
1234   ResultObjectVisitor Visitor(Map, LocForRecordReturnVal, *DACtx);
1235   if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(FuncDecl))
1236     Visitor.TraverseConstructorInits(Ctor, ThisPointeeLoc);
1237   Visitor.TraverseStmt(FuncDecl->getBody());
1238 
1239   return Map;
1240 }
1241 
1242 RecordStorageLocation *getImplicitObjectLocation(const CXXMemberCallExpr &MCE,
1243                                                  const Environment &Env) {
1244   Expr *ImplicitObject = MCE.getImplicitObjectArgument();
1245   if (ImplicitObject == nullptr)
1246     return nullptr;
1247   if (ImplicitObject->getType()->isPointerType()) {
1248     if (auto *Val = Env.get<PointerValue>(*ImplicitObject))
1249       return &cast<RecordStorageLocation>(Val->getPointeeLoc());
1250     return nullptr;
1251   }
1252   return cast_or_null<RecordStorageLocation>(
1253       Env.getStorageLocation(*ImplicitObject));
1254 }
1255 
1256 RecordStorageLocation *getBaseObjectLocation(const MemberExpr &ME,
1257                                              const Environment &Env) {
1258   Expr *Base = ME.getBase();
1259   if (Base == nullptr)
1260     return nullptr;
1261   if (ME.isArrow()) {
1262     if (auto *Val = Env.get<PointerValue>(*Base))
1263       return &cast<RecordStorageLocation>(Val->getPointeeLoc());
1264     return nullptr;
1265   }
1266   return Env.get<RecordStorageLocation>(*Base);
1267 }
1268 
1269 } // namespace dataflow
1270 } // namespace clang
1271