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