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