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