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