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