xref: /llvm-project/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp (revision 7d935d083659c9ddaf3389c1747fc8c59f07e3fc)
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/Casting.h"
26 #include "llvm/Support/ErrorHandling.h"
27 #include <cassert>
28 #include <memory>
29 #include <utility>
30 
31 namespace clang {
32 namespace dataflow {
33 
34 // FIXME: convert these to parameters of the analysis or environment. Current
35 // settings have been experimentaly validated, but only for a particular
36 // analysis.
37 static constexpr int MaxCompositeValueDepth = 3;
38 static constexpr int MaxCompositeValueSize = 1000;
39 
40 /// Returns a map consisting of key-value entries that are present in both maps.
41 template <typename K, typename V>
42 llvm::DenseMap<K, V> intersectDenseMaps(const llvm::DenseMap<K, V> &Map1,
43                                         const llvm::DenseMap<K, V> &Map2) {
44   llvm::DenseMap<K, V> Result;
45   for (auto &Entry : Map1) {
46     auto It = Map2.find(Entry.first);
47     if (It != Map2.end() && Entry.second == It->second)
48       Result.insert({Entry.first, Entry.second});
49   }
50   return Result;
51 }
52 
53 static bool compareDistinctValues(QualType Type, Value &Val1,
54                                   const Environment &Env1, Value &Val2,
55                                   const Environment &Env2,
56                                   Environment::ValueModel &Model) {
57   // Note: Potentially costly, but, for booleans, we could check whether both
58   // can be proven equivalent in their respective environments.
59 
60   // FIXME: move the reference/pointers logic from `areEquivalentValues` to here
61   // and implement separate, join/widen specific handling for
62   // reference/pointers.
63   switch (Model.compare(Type, Val1, Env1, Val2, Env2)) {
64   case ComparisonResult::Same:
65     return true;
66   case ComparisonResult::Different:
67     return false;
68   case ComparisonResult::Unknown:
69     switch (Val1.getKind()) {
70     case Value::Kind::Integer:
71     case Value::Kind::Reference:
72     case Value::Kind::Pointer:
73     case Value::Kind::Struct:
74       // FIXME: this choice intentionally introduces unsoundness to allow
75       // for convergence. Once we have widening support for the
76       // reference/pointer and struct built-in models, this should be
77       // `false`.
78       return true;
79     default:
80       return false;
81     }
82   }
83   llvm_unreachable("All cases covered in switch");
84 }
85 
86 /// Attempts to merge distinct values `Val1` and `Val2` in `Env1` and `Env2`,
87 /// respectively, of the same type `Type`. Merging generally produces a single
88 /// value that (soundly) approximates the two inputs, although the actual
89 /// meaning depends on `Model`.
90 static Value *mergeDistinctValues(QualType Type, Value &Val1,
91                                   const Environment &Env1, Value &Val2,
92                                   const Environment &Env2,
93                                   Environment &MergedEnv,
94                                   Environment::ValueModel &Model) {
95   // Join distinct boolean values preserving information about the constraints
96   // in the respective path conditions.
97   if (isa<BoolValue>(&Val1) && isa<BoolValue>(&Val2)) {
98     // FIXME: Checking both values should be unnecessary, since they should have
99     // a consistent shape.  However, right now we can end up with BoolValue's in
100     // integer-typed variables due to our incorrect handling of
101     // boolean-to-integer casts (we just propagate the BoolValue to the result
102     // of the cast). So, a join can encounter an integer in one branch but a
103     // bool in the other.
104     // For example:
105     // ```
106     // std::optional<bool> o;
107     // int x;
108     // if (o.has_value())
109     //   x = o.value();
110     // ```
111     auto &Expr1 = cast<BoolValue>(Val1).formula();
112     auto &Expr2 = cast<BoolValue>(Val2).formula();
113     auto &A = MergedEnv.arena();
114     auto &MergedVal = A.makeAtomRef(A.makeAtom());
115     MergedEnv.addToFlowCondition(
116         A.makeOr(A.makeAnd(A.makeAtomRef(Env1.getFlowConditionToken()),
117                            A.makeEquals(MergedVal, Expr1)),
118                  A.makeAnd(A.makeAtomRef(Env2.getFlowConditionToken()),
119                            A.makeEquals(MergedVal, Expr2))));
120     return &A.makeBoolValue(MergedVal);
121   }
122 
123   // FIXME: Consider destroying `MergedValue` immediately if `ValueModel::merge`
124   // returns false to avoid storing unneeded values in `DACtx`.
125   // FIXME: Creating the value based on the type alone creates misshapen values
126   // for lvalues, since the type does not reflect the need for `ReferenceValue`.
127   // This issue will be resolved when `ReferenceValue` is eliminated as part
128   // of the ongoing migration to strict handling of value categories (see
129   // https://discourse.llvm.org/t/70086 for details).
130   if (Value *MergedVal = MergedEnv.createValue(Type))
131     if (Model.merge(Type, Val1, Env1, Val2, Env2, *MergedVal, MergedEnv))
132       return MergedVal;
133 
134   return nullptr;
135 }
136 
137 // When widening does not change `Current`, return value will equal `&Prev`.
138 static Value &widenDistinctValues(QualType Type, Value &Prev,
139                                   const Environment &PrevEnv, Value &Current,
140                                   Environment &CurrentEnv,
141                                   Environment::ValueModel &Model) {
142   // Boolean-model widening.
143   if (isa<BoolValue>(&Prev)) {
144     assert(isa<BoolValue>(Current));
145     // Widen to Top, because we know they are different values. If previous was
146     // already Top, re-use that to (implicitly) indicate that no change occured.
147     if (isa<TopBoolValue>(Prev))
148       return Prev;
149     return CurrentEnv.makeTopBoolValue();
150   }
151 
152   // FIXME: Add other built-in model widening.
153 
154   // Custom-model widening.
155   if (auto *W = Model.widen(Type, Prev, PrevEnv, Current, CurrentEnv))
156     return *W;
157 
158   // Default of widening is a no-op: leave the current value unchanged.
159   return Current;
160 }
161 
162 /// Initializes a global storage value.
163 static void insertIfGlobal(const Decl &D,
164                            llvm::DenseSet<const VarDecl *> &Vars) {
165   if (auto *V = dyn_cast<VarDecl>(&D))
166     if (V->hasGlobalStorage())
167       Vars.insert(V);
168 }
169 
170 static void insertIfFunction(const Decl &D,
171                              llvm::DenseSet<const FunctionDecl *> &Funcs) {
172   if (auto *FD = dyn_cast<FunctionDecl>(&D))
173     Funcs.insert(FD);
174 }
175 
176 static void
177 getFieldsGlobalsAndFuncs(const Decl &D, FieldSet &Fields,
178                          llvm::DenseSet<const VarDecl *> &Vars,
179                          llvm::DenseSet<const FunctionDecl *> &Funcs) {
180   insertIfGlobal(D, Vars);
181   insertIfFunction(D, Funcs);
182   if (const auto *Decomp = dyn_cast<DecompositionDecl>(&D))
183     for (const auto *B : Decomp->bindings())
184       if (auto *ME = dyn_cast_or_null<MemberExpr>(B->getBinding()))
185         // FIXME: should we be using `E->getFoundDecl()`?
186         if (const auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl()))
187           Fields.insert(FD);
188 }
189 
190 /// Traverses `S` and inserts into `Fields`, `Vars` and `Funcs` any fields,
191 /// global variables and functions that are declared in or referenced from
192 /// sub-statements.
193 static void
194 getFieldsGlobalsAndFuncs(const Stmt &S, FieldSet &Fields,
195                          llvm::DenseSet<const VarDecl *> &Vars,
196                          llvm::DenseSet<const FunctionDecl *> &Funcs) {
197   for (auto *Child : S.children())
198     if (Child != nullptr)
199       getFieldsGlobalsAndFuncs(*Child, Fields, Vars, Funcs);
200   if (const auto *DefaultInit = dyn_cast<CXXDefaultInitExpr>(&S))
201     getFieldsGlobalsAndFuncs(*DefaultInit->getExpr(), Fields, Vars, Funcs);
202 
203   if (auto *DS = dyn_cast<DeclStmt>(&S)) {
204     if (DS->isSingleDecl())
205       getFieldsGlobalsAndFuncs(*DS->getSingleDecl(), Fields, Vars, Funcs);
206     else
207       for (auto *D : DS->getDeclGroup())
208         getFieldsGlobalsAndFuncs(*D, Fields, Vars, Funcs);
209   } else if (auto *E = dyn_cast<DeclRefExpr>(&S)) {
210     insertIfGlobal(*E->getDecl(), Vars);
211     insertIfFunction(*E->getDecl(), Funcs);
212   } else if (auto *E = dyn_cast<MemberExpr>(&S)) {
213     // FIXME: should we be using `E->getFoundDecl()`?
214     const ValueDecl *VD = E->getMemberDecl();
215     insertIfGlobal(*VD, Vars);
216     insertIfFunction(*VD, Funcs);
217     if (const auto *FD = dyn_cast<FieldDecl>(VD))
218       Fields.insert(FD);
219   } else if (auto *InitList = dyn_cast<InitListExpr>(&S)) {
220     if (RecordDecl *RD = InitList->getType()->getAsRecordDecl())
221       for (const auto *FD : getFieldsForInitListExpr(RD))
222         Fields.insert(FD);
223   }
224 }
225 
226 // FIXME: Add support for resetting globals after function calls to enable
227 // the implementation of sound analyses.
228 void Environment::initFieldsGlobalsAndFuncs(const FunctionDecl *FuncDecl) {
229   assert(FuncDecl->getBody() != nullptr);
230 
231   FieldSet Fields;
232   llvm::DenseSet<const VarDecl *> Vars;
233   llvm::DenseSet<const FunctionDecl *> Funcs;
234 
235   // Look for global variable and field references in the
236   // constructor-initializers.
237   if (const auto *CtorDecl = dyn_cast<CXXConstructorDecl>(FuncDecl)) {
238     for (const auto *Init : CtorDecl->inits()) {
239       if (Init->isMemberInitializer()) {
240         Fields.insert(Init->getMember());
241       } else if (Init->isIndirectMemberInitializer()) {
242         for (const auto *I : Init->getIndirectMember()->chain())
243           Fields.insert(cast<FieldDecl>(I));
244       }
245       const Expr *E = Init->getInit();
246       assert(E != nullptr);
247       getFieldsGlobalsAndFuncs(*E, Fields, Vars, Funcs);
248     }
249     // Add all fields mentioned in default member initializers.
250     for (const FieldDecl *F : CtorDecl->getParent()->fields())
251       if (const auto *I = F->getInClassInitializer())
252           getFieldsGlobalsAndFuncs(*I, Fields, Vars, Funcs);
253   }
254   getFieldsGlobalsAndFuncs(*FuncDecl->getBody(), Fields, Vars, Funcs);
255 
256   // These have to be added before the lines that follow to ensure that
257   // `create*` work correctly for structs.
258   DACtx->addModeledFields(Fields);
259 
260   for (const VarDecl *D : Vars) {
261     if (getStorageLocation(*D) != nullptr)
262       continue;
263     auto &Loc = createStorageLocation(D->getType().getNonReferenceType());
264     setStorageLocation(*D, Loc);
265     if (auto *Val = createValue(D->getType().getNonReferenceType()))
266       setValue(Loc, *Val);
267   }
268 
269   for (const FunctionDecl *FD : Funcs) {
270     if (getStorageLocation(*FD) != nullptr)
271       continue;
272     auto &Loc = createStorageLocation(FD->getType());
273     setStorageLocation(*FD, Loc);
274   }
275 }
276 
277 Environment::Environment(DataflowAnalysisContext &DACtx)
278     : DACtx(&DACtx),
279       FlowConditionToken(DACtx.arena().makeFlowConditionToken()) {}
280 
281 Environment Environment::fork() const {
282   Environment Copy(*this);
283   Copy.FlowConditionToken = DACtx->forkFlowCondition(FlowConditionToken);
284   return Copy;
285 }
286 
287 Environment::Environment(DataflowAnalysisContext &DACtx,
288                          const DeclContext &DeclCtx)
289     : Environment(DACtx) {
290   CallStack.push_back(&DeclCtx);
291 
292   if (const auto *FuncDecl = dyn_cast<FunctionDecl>(&DeclCtx)) {
293     assert(FuncDecl->getBody() != nullptr);
294 
295     initFieldsGlobalsAndFuncs(FuncDecl);
296 
297     for (const auto *ParamDecl : FuncDecl->parameters()) {
298       assert(ParamDecl != nullptr);
299       // References aren't objects, so the reference itself doesn't have a
300       // storage location. Instead, the storage location for a reference refers
301       // directly to an object of the referenced type -- so strip off any
302       // reference from the type.
303       auto &ParamLoc =
304           createStorageLocation(ParamDecl->getType().getNonReferenceType());
305       setStorageLocation(*ParamDecl, ParamLoc);
306       if (Value *ParamVal =
307               createValue(ParamDecl->getType().getNonReferenceType()))
308           setValue(ParamLoc, *ParamVal);
309     }
310   }
311 
312   if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(&DeclCtx)) {
313     auto *Parent = MethodDecl->getParent();
314     assert(Parent != nullptr);
315     if (Parent->isLambda())
316       MethodDecl = dyn_cast<CXXMethodDecl>(Parent->getDeclContext());
317 
318     // FIXME: Initialize the ThisPointeeLoc of lambdas too.
319     if (MethodDecl && !MethodDecl->isStatic()) {
320       QualType ThisPointeeType = MethodDecl->getThisObjectType();
321       ThisPointeeLoc = &cast<AggregateStorageLocation>(
322           createStorageLocation(ThisPointeeType));
323       if (Value *ThisPointeeVal = createValue(ThisPointeeType))
324         setValue(*ThisPointeeLoc, *ThisPointeeVal);
325     }
326   }
327 }
328 
329 bool Environment::canDescend(unsigned MaxDepth,
330                              const DeclContext *Callee) const {
331   return CallStack.size() <= MaxDepth && !llvm::is_contained(CallStack, Callee);
332 }
333 
334 Environment Environment::pushCall(const CallExpr *Call) const {
335   Environment Env(*this);
336 
337   if (const auto *MethodCall = dyn_cast<CXXMemberCallExpr>(Call)) {
338     if (const Expr *Arg = MethodCall->getImplicitObjectArgument()) {
339       if (!isa<CXXThisExpr>(Arg))
340         Env.ThisPointeeLoc = cast<AggregateStorageLocation>(
341             getStorageLocation(*Arg, SkipPast::Reference));
342       // Otherwise (when the argument is `this`), retain the current
343       // environment's `ThisPointeeLoc`.
344     }
345   }
346 
347   Env.pushCallInternal(Call->getDirectCallee(),
348                        llvm::ArrayRef(Call->getArgs(), Call->getNumArgs()));
349 
350   return Env;
351 }
352 
353 Environment Environment::pushCall(const CXXConstructExpr *Call) const {
354   Environment Env(*this);
355 
356   Env.ThisPointeeLoc = &cast<AggregateStorageLocation>(
357       Env.createStorageLocation(Call->getType()));
358   if (Value *Val = Env.createValue(Call->getType()))
359     Env.setValue(*Env.ThisPointeeLoc, *Val);
360 
361   Env.pushCallInternal(Call->getConstructor(),
362                        llvm::ArrayRef(Call->getArgs(), Call->getNumArgs()));
363 
364   return Env;
365 }
366 
367 void Environment::pushCallInternal(const FunctionDecl *FuncDecl,
368                                    ArrayRef<const Expr *> Args) {
369   // Canonicalize to the definition of the function. This ensures that we're
370   // putting arguments into the same `ParamVarDecl`s` that the callee will later
371   // be retrieving them from.
372   assert(FuncDecl->getDefinition() != nullptr);
373   FuncDecl = FuncDecl->getDefinition();
374 
375   CallStack.push_back(FuncDecl);
376 
377   initFieldsGlobalsAndFuncs(FuncDecl);
378 
379   const auto *ParamIt = FuncDecl->param_begin();
380 
381   // FIXME: Parameters don't always map to arguments 1:1; examples include
382   // overloaded operators implemented as member functions, and parameter packs.
383   for (unsigned ArgIndex = 0; ArgIndex < Args.size(); ++ParamIt, ++ArgIndex) {
384     assert(ParamIt != FuncDecl->param_end());
385 
386     const Expr *Arg = Args[ArgIndex];
387     auto *ArgLoc = getStorageLocation(*Arg, SkipPast::Reference);
388     if (ArgLoc == nullptr)
389       continue;
390 
391     const VarDecl *Param = *ParamIt;
392 
393     QualType ParamType = Param->getType();
394     if (ParamType->isReferenceType()) {
395       setStorageLocation(*Param, *ArgLoc);
396     } else {
397       auto &Loc = createStorageLocation(*Param);
398       setStorageLocation(*Param, Loc);
399 
400       if (auto *ArgVal = getValue(*ArgLoc)) {
401         setValue(Loc, *ArgVal);
402       } else if (Value *Val = createValue(ParamType)) {
403         setValue(Loc, *Val);
404       }
405     }
406   }
407 }
408 
409 void Environment::popCall(const CallExpr *Call, const Environment &CalleeEnv) {
410   // We ignore `DACtx` because it's already the same in both. We don't want the
411   // callee's `DeclCtx`, `ReturnVal`, `ReturnLoc` or `ThisPointeeLoc`. We don't
412   // bring back `DeclToLoc` and `ExprToLoc` because we want to be able to later
413   // analyze the same callee in a different context, and `setStorageLocation`
414   // requires there to not already be a storage location assigned. Conceptually,
415   // these maps capture information from the local scope, so when popping that
416   // scope, we do not propagate the maps.
417   this->LocToVal = std::move(CalleeEnv.LocToVal);
418   this->MemberLocToStruct = std::move(CalleeEnv.MemberLocToStruct);
419   this->FlowConditionToken = std::move(CalleeEnv.FlowConditionToken);
420 
421   if (Call->isGLValue()) {
422     if (CalleeEnv.ReturnLoc != nullptr)
423       setStorageLocationStrict(*Call, *CalleeEnv.ReturnLoc);
424   } else if (!Call->getType()->isVoidType()) {
425     if (CalleeEnv.ReturnVal != nullptr)
426       setValueStrict(*Call, *CalleeEnv.ReturnVal);
427   }
428 }
429 
430 void Environment::popCall(const CXXConstructExpr *Call,
431                           const Environment &CalleeEnv) {
432   // See also comment in `popCall(const CallExpr *, const Environment &)` above.
433   this->LocToVal = std::move(CalleeEnv.LocToVal);
434   this->MemberLocToStruct = std::move(CalleeEnv.MemberLocToStruct);
435   this->FlowConditionToken = std::move(CalleeEnv.FlowConditionToken);
436 
437   if (Value *Val = CalleeEnv.getValue(*CalleeEnv.ThisPointeeLoc)) {
438     setValueStrict(*Call, *Val);
439   }
440 }
441 
442 bool Environment::equivalentTo(const Environment &Other,
443                                Environment::ValueModel &Model) const {
444   assert(DACtx == Other.DACtx);
445 
446   if (ReturnVal != Other.ReturnVal)
447     return false;
448 
449   if (ReturnLoc != Other.ReturnLoc)
450     return false;
451 
452   if (ThisPointeeLoc != Other.ThisPointeeLoc)
453     return false;
454 
455   if (DeclToLoc != Other.DeclToLoc)
456     return false;
457 
458   if (ExprToLoc != Other.ExprToLoc)
459     return false;
460 
461   // Compare the contents for the intersection of their domains.
462   for (auto &Entry : LocToVal) {
463     const StorageLocation *Loc = Entry.first;
464     assert(Loc != nullptr);
465 
466     Value *Val = Entry.second;
467     assert(Val != nullptr);
468 
469     auto It = Other.LocToVal.find(Loc);
470     if (It == Other.LocToVal.end())
471       continue;
472     assert(It->second != nullptr);
473 
474     if (!areEquivalentValues(*Val, *It->second) &&
475         !compareDistinctValues(Loc->getType(), *Val, *this, *It->second, Other,
476                                Model))
477       return false;
478   }
479 
480   return true;
481 }
482 
483 LatticeJoinEffect Environment::widen(const Environment &PrevEnv,
484                                      Environment::ValueModel &Model) {
485   assert(DACtx == PrevEnv.DACtx);
486   assert(ReturnVal == PrevEnv.ReturnVal);
487   assert(ReturnLoc == PrevEnv.ReturnLoc);
488   assert(ThisPointeeLoc == PrevEnv.ThisPointeeLoc);
489   assert(CallStack == PrevEnv.CallStack);
490 
491   auto Effect = LatticeJoinEffect::Unchanged;
492 
493   // By the API, `PrevEnv` is a previous version of the environment for the same
494   // block, so we have some guarantees about its shape. In particular, it will
495   // be the result of a join or widen operation on previous values for this
496   // block. For `DeclToLoc` and `ExprToLoc`, join guarantees that these maps are
497   // subsets of the maps in `PrevEnv`. So, as long as we maintain this property
498   // here, we don't need change their current values to widen.
499   //
500   // FIXME: `MemberLocToStruct` does not share the above property, because
501   // `join` can cause the map size to increase (when we add fresh data in places
502   // of conflict). Once this issue with join is resolved, re-enable the
503   // assertion below or replace with something that captures the desired
504   // invariant.
505   assert(DeclToLoc.size() <= PrevEnv.DeclToLoc.size());
506   assert(ExprToLoc.size() <= PrevEnv.ExprToLoc.size());
507   // assert(MemberLocToStruct.size() <= PrevEnv.MemberLocToStruct.size());
508 
509   llvm::MapVector<const StorageLocation *, Value *> WidenedLocToVal;
510   for (auto &Entry : LocToVal) {
511     const StorageLocation *Loc = Entry.first;
512     assert(Loc != nullptr);
513 
514     Value *Val = Entry.second;
515     assert(Val != nullptr);
516 
517     auto PrevIt = PrevEnv.LocToVal.find(Loc);
518     if (PrevIt == PrevEnv.LocToVal.end())
519       continue;
520     assert(PrevIt->second != nullptr);
521 
522     if (areEquivalentValues(*Val, *PrevIt->second)) {
523       WidenedLocToVal.insert({Loc, Val});
524       continue;
525     }
526 
527     Value &WidenedVal = widenDistinctValues(Loc->getType(), *PrevIt->second,
528                                             PrevEnv, *Val, *this, Model);
529     WidenedLocToVal.insert({Loc, &WidenedVal});
530     if (&WidenedVal != PrevIt->second)
531       Effect = LatticeJoinEffect::Changed;
532   }
533   LocToVal = std::move(WidenedLocToVal);
534   // FIXME: update the equivalence calculation for `MemberLocToStruct`, once we
535   // have a systematic way of soundly comparing this map.
536   if (DeclToLoc.size() != PrevEnv.DeclToLoc.size() ||
537       ExprToLoc.size() != PrevEnv.ExprToLoc.size() ||
538       LocToVal.size() != PrevEnv.LocToVal.size() ||
539       MemberLocToStruct.size() != PrevEnv.MemberLocToStruct.size())
540     Effect = LatticeJoinEffect::Changed;
541 
542   return Effect;
543 }
544 
545 Environment Environment::join(const Environment &EnvA, const Environment &EnvB,
546                               Environment::ValueModel &Model) {
547   assert(EnvA.DACtx == EnvB.DACtx);
548   assert(EnvA.ThisPointeeLoc == EnvB.ThisPointeeLoc);
549   assert(EnvA.CallStack == EnvB.CallStack);
550 
551   Environment JoinedEnv(*EnvA.DACtx);
552 
553   JoinedEnv.CallStack = EnvA.CallStack;
554   JoinedEnv.ThisPointeeLoc = EnvA.ThisPointeeLoc;
555 
556   if (EnvA.ReturnVal == nullptr || EnvB.ReturnVal == nullptr) {
557     // `ReturnVal` might not always get set -- for example if we have a return
558     // statement of the form `return some_other_func()` and we decide not to
559     // analyze `some_other_func()`.
560     // In this case, we can't say anything about the joined return value -- we
561     // don't simply want to propagate the return value that we do have, because
562     // it might not be the correct one.
563     // This occurs for example in the test `ContextSensitiveMutualRecursion`.
564     JoinedEnv.ReturnVal = nullptr;
565   } else if (areEquivalentValues(*EnvA.ReturnVal, *EnvB.ReturnVal)) {
566     JoinedEnv.ReturnVal = EnvA.ReturnVal;
567   } else {
568     assert(!EnvA.CallStack.empty());
569     // FIXME: Make `CallStack` a vector of `FunctionDecl` so we don't need this
570     // cast.
571     auto *Func = dyn_cast<FunctionDecl>(EnvA.CallStack.back());
572     assert(Func != nullptr);
573     if (Value *MergedVal =
574             mergeDistinctValues(Func->getReturnType(), *EnvA.ReturnVal, EnvA,
575                                 *EnvB.ReturnVal, EnvB, JoinedEnv, Model))
576       JoinedEnv.ReturnVal = MergedVal;
577   }
578 
579   if (EnvA.ReturnLoc == EnvB.ReturnLoc)
580     JoinedEnv.ReturnLoc = EnvA.ReturnLoc;
581   else
582     JoinedEnv.ReturnLoc = nullptr;
583 
584   // FIXME: Once we're able to remove declarations from `DeclToLoc` when their
585   // lifetime ends, add an assertion that there aren't any entries in
586   // `DeclToLoc` and `Other.DeclToLoc` that map the same declaration to
587   // different storage locations.
588   JoinedEnv.DeclToLoc = intersectDenseMaps(EnvA.DeclToLoc, EnvB.DeclToLoc);
589 
590   JoinedEnv.ExprToLoc = intersectDenseMaps(EnvA.ExprToLoc, EnvB.ExprToLoc);
591 
592   JoinedEnv.MemberLocToStruct =
593       intersectDenseMaps(EnvA.MemberLocToStruct, EnvB.MemberLocToStruct);
594 
595   // FIXME: update join to detect backedges and simplify the flow condition
596   // accordingly.
597   JoinedEnv.FlowConditionToken = EnvA.DACtx->joinFlowConditions(
598       EnvA.FlowConditionToken, EnvB.FlowConditionToken);
599 
600   for (auto &Entry : EnvA.LocToVal) {
601     const StorageLocation *Loc = Entry.first;
602     assert(Loc != nullptr);
603 
604     Value *Val = Entry.second;
605     assert(Val != nullptr);
606 
607     auto It = EnvB.LocToVal.find(Loc);
608     if (It == EnvB.LocToVal.end())
609       continue;
610     assert(It->second != nullptr);
611 
612     if (areEquivalentValues(*Val, *It->second)) {
613       JoinedEnv.LocToVal.insert({Loc, Val});
614       continue;
615     }
616 
617     if (Value *MergedVal = mergeDistinctValues(
618             Loc->getType(), *Val, EnvA, *It->second, EnvB, JoinedEnv, Model)) {
619       JoinedEnv.LocToVal.insert({Loc, MergedVal});
620     }
621   }
622 
623   return JoinedEnv;
624 }
625 
626 StorageLocation &Environment::createStorageLocation(QualType Type) {
627   return DACtx->createStorageLocation(Type);
628 }
629 
630 StorageLocation &Environment::createStorageLocation(const VarDecl &D) {
631   // Evaluated declarations are always assigned the same storage locations to
632   // ensure that the environment stabilizes across loop iterations. Storage
633   // locations for evaluated declarations are stored in the analysis context.
634   return DACtx->getStableStorageLocation(D);
635 }
636 
637 StorageLocation &Environment::createStorageLocation(const Expr &E) {
638   // Evaluated expressions are always assigned the same storage locations to
639   // ensure that the environment stabilizes across loop iterations. Storage
640   // locations for evaluated expressions are stored in the analysis context.
641   return DACtx->getStableStorageLocation(E);
642 }
643 
644 void Environment::setStorageLocation(const ValueDecl &D, StorageLocation &Loc) {
645   assert(!DeclToLoc.contains(&D));
646   assert(!isa_and_nonnull<ReferenceValue>(getValue(Loc)));
647   DeclToLoc[&D] = &Loc;
648 }
649 
650 StorageLocation *Environment::getStorageLocation(const ValueDecl &D) const {
651   auto It = DeclToLoc.find(&D);
652   if (It == DeclToLoc.end())
653     return nullptr;
654 
655   StorageLocation *Loc = It->second;
656 
657   assert(!isa_and_nonnull<ReferenceValue>(getValue(*Loc)));
658 
659   return Loc;
660 }
661 
662 void Environment::setStorageLocation(const Expr &E, StorageLocation &Loc) {
663   const Expr &CanonE = ignoreCFGOmittedNodes(E);
664   assert(!ExprToLoc.contains(&CanonE));
665   ExprToLoc[&CanonE] = &Loc;
666 }
667 
668 void Environment::setStorageLocationStrict(const Expr &E,
669                                            StorageLocation &Loc) {
670   // `DeclRefExpr`s to builtin function types aren't glvalues, for some reason,
671   // but we still want to be able to associate a `StorageLocation` with them,
672   // so allow these as an exception.
673   assert(E.isGLValue() ||
674          E.getType()->isSpecificBuiltinType(BuiltinType::BuiltinFn));
675   setStorageLocation(E, Loc);
676 }
677 
678 StorageLocation *Environment::getStorageLocation(const Expr &E,
679                                                  SkipPast SP) const {
680   // FIXME: Add a test with parens.
681   auto It = ExprToLoc.find(&ignoreCFGOmittedNodes(E));
682   return It == ExprToLoc.end() ? nullptr : &skip(*It->second, SP);
683 }
684 
685 StorageLocation *Environment::getStorageLocationStrict(const Expr &E) const {
686   // See comment in `setStorageLocationStrict()`.
687   assert(E.isGLValue() ||
688          E.getType()->isSpecificBuiltinType(BuiltinType::BuiltinFn));
689   StorageLocation *Loc = getStorageLocation(E, SkipPast::None);
690 
691   if (Loc == nullptr)
692     return nullptr;
693 
694   if (auto *RefVal = dyn_cast_or_null<ReferenceValue>(getValue(*Loc)))
695     return &RefVal->getReferentLoc();
696 
697   return Loc;
698 }
699 
700 AggregateStorageLocation *Environment::getThisPointeeStorageLocation() const {
701   return ThisPointeeLoc;
702 }
703 
704 PointerValue &Environment::getOrCreateNullPointerValue(QualType PointeeType) {
705   return DACtx->getOrCreateNullPointerValue(PointeeType);
706 }
707 
708 void Environment::setValue(const StorageLocation &Loc, Value &Val) {
709   LocToVal[&Loc] = &Val;
710 
711   if (auto *StructVal = dyn_cast<StructValue>(&Val)) {
712     auto &AggregateLoc = *cast<AggregateStorageLocation>(&Loc);
713 
714     const QualType Type = AggregateLoc.getType();
715     assert(Type->isRecordType());
716 
717     for (const FieldDecl *Field : DACtx->getModeledFields(Type)) {
718       assert(Field != nullptr);
719       StorageLocation &FieldLoc = AggregateLoc.getChild(*Field);
720       MemberLocToStruct[&FieldLoc] = std::make_pair(StructVal, Field);
721       if (auto *FieldVal = StructVal->getChild(*Field))
722         setValue(FieldLoc, *FieldVal);
723     }
724   }
725 
726   auto It = MemberLocToStruct.find(&Loc);
727   if (It != MemberLocToStruct.end()) {
728     // `Loc` is the location of a struct member so we need to also update the
729     // value of the member in the corresponding `StructValue`.
730 
731     assert(It->second.first != nullptr);
732     StructValue &StructVal = *It->second.first;
733 
734     assert(It->second.second != nullptr);
735     const ValueDecl &Member = *It->second.second;
736 
737     StructVal.setChild(Member, Val);
738   }
739 }
740 
741 void Environment::clearValue(const StorageLocation &Loc) {
742   LocToVal.erase(&Loc);
743 
744   if (auto It = MemberLocToStruct.find(&Loc); It != MemberLocToStruct.end()) {
745     // `Loc` is the location of a struct member so we need to also clear the
746     // member in the corresponding `StructValue`.
747 
748     assert(It->second.first != nullptr);
749     StructValue &StructVal = *It->second.first;
750 
751     assert(It->second.second != nullptr);
752     const ValueDecl &Member = *It->second.second;
753 
754     StructVal.clearChild(Member);
755   }
756 }
757 
758 void Environment::setValueStrict(const Expr &E, Value &Val) {
759   assert(E.isPRValue());
760   assert(!isa<ReferenceValue>(Val));
761 
762   StorageLocation *Loc = getStorageLocation(E, SkipPast::None);
763   if (Loc == nullptr) {
764     Loc = &createStorageLocation(E);
765     setStorageLocation(E, *Loc);
766   }
767   setValue(*Loc, Val);
768 }
769 
770 Value *Environment::getValue(const StorageLocation &Loc) const {
771   return LocToVal.lookup(&Loc);
772 }
773 
774 Value *Environment::getValue(const ValueDecl &D) const {
775   auto *Loc = getStorageLocation(D);
776   if (Loc == nullptr)
777     return nullptr;
778   return getValue(*Loc);
779 }
780 
781 Value *Environment::getValue(const Expr &E, SkipPast SP) const {
782   auto *Loc = getStorageLocation(E, SP);
783   if (Loc == nullptr)
784     return nullptr;
785   return getValue(*Loc);
786 }
787 
788 Value *Environment::getValueStrict(const Expr &E) const {
789   assert(E.isPRValue());
790   Value *Val = getValue(E, SkipPast::None);
791 
792   assert(Val == nullptr || !isa<ReferenceValue>(Val));
793 
794   return Val;
795 }
796 
797 Value *Environment::createValue(QualType Type) {
798   llvm::DenseSet<QualType> Visited;
799   int CreatedValuesCount = 0;
800   Value *Val = createValueUnlessSelfReferential(Type, Visited, /*Depth=*/0,
801                                                 CreatedValuesCount);
802   if (CreatedValuesCount > MaxCompositeValueSize) {
803     llvm::errs() << "Attempting to initialize a huge value of type: " << Type
804                  << '\n';
805   }
806   return Val;
807 }
808 
809 Value *Environment::createValueUnlessSelfReferential(
810     QualType Type, llvm::DenseSet<QualType> &Visited, int Depth,
811     int &CreatedValuesCount) {
812   assert(!Type.isNull());
813 
814   // Allow unlimited fields at depth 1; only cap at deeper nesting levels.
815   if ((Depth > 1 && CreatedValuesCount > MaxCompositeValueSize) ||
816       Depth > MaxCompositeValueDepth)
817     return nullptr;
818 
819   if (Type->isBooleanType()) {
820     CreatedValuesCount++;
821     return &makeAtomicBoolValue();
822   }
823 
824   if (Type->isIntegerType()) {
825     // FIXME: consider instead `return nullptr`, given that we do nothing useful
826     // with integers, and so distinguishing them serves no purpose, but could
827     // prevent convergence.
828     CreatedValuesCount++;
829     return &arena().create<IntegerValue>();
830   }
831 
832   if (Type->isReferenceType() || Type->isPointerType()) {
833     CreatedValuesCount++;
834     QualType PointeeType = Type->getPointeeType();
835     auto &PointeeLoc = createStorageLocation(PointeeType);
836 
837     if (Visited.insert(PointeeType.getCanonicalType()).second) {
838       Value *PointeeVal = createValueUnlessSelfReferential(
839           PointeeType, Visited, Depth, CreatedValuesCount);
840       Visited.erase(PointeeType.getCanonicalType());
841 
842       if (PointeeVal != nullptr)
843         setValue(PointeeLoc, *PointeeVal);
844     }
845 
846     if (Type->isReferenceType())
847       return &arena().create<ReferenceValue>(PointeeLoc);
848     else
849       return &arena().create<PointerValue>(PointeeLoc);
850   }
851 
852   if (Type->isRecordType()) {
853     CreatedValuesCount++;
854     llvm::DenseMap<const ValueDecl *, Value *> FieldValues;
855     for (const FieldDecl *Field : DACtx->getModeledFields(Type)) {
856       assert(Field != nullptr);
857 
858       QualType FieldType = Field->getType();
859       if (Visited.contains(FieldType.getCanonicalType()))
860         continue;
861 
862       Visited.insert(FieldType.getCanonicalType());
863       if (auto *FieldValue = createValueUnlessSelfReferential(
864               FieldType, Visited, Depth + 1, CreatedValuesCount))
865         FieldValues.insert({Field, FieldValue});
866       Visited.erase(FieldType.getCanonicalType());
867     }
868 
869     return &arena().create<StructValue>(std::move(FieldValues));
870   }
871 
872   return nullptr;
873 }
874 
875 StorageLocation &Environment::skip(StorageLocation &Loc, SkipPast SP) const {
876   switch (SP) {
877   case SkipPast::None:
878     return Loc;
879   case SkipPast::Reference:
880     // References cannot be chained so we only need to skip past one level of
881     // indirection.
882     if (auto *Val = dyn_cast_or_null<ReferenceValue>(getValue(Loc)))
883       return Val->getReferentLoc();
884     return Loc;
885   }
886   llvm_unreachable("bad SkipPast kind");
887 }
888 
889 const StorageLocation &Environment::skip(const StorageLocation &Loc,
890                                          SkipPast SP) const {
891   return skip(*const_cast<StorageLocation *>(&Loc), SP);
892 }
893 
894 void Environment::addToFlowCondition(const Formula &Val) {
895   DACtx->addFlowConditionConstraint(FlowConditionToken, Val);
896 }
897 void Environment::addToFlowCondition(BoolValue &Val) {
898   addToFlowCondition(Val.formula());
899 }
900 
901 bool Environment::flowConditionImplies(const Formula &Val) const {
902   return DACtx->flowConditionImplies(FlowConditionToken, Val);
903 }
904 bool Environment::flowConditionImplies(BoolValue &Val) const {
905   return flowConditionImplies(Val.formula());
906 }
907 
908 void Environment::dump(raw_ostream &OS) const {
909   // FIXME: add printing for remaining fields and allow caller to decide what
910   // fields are printed.
911   OS << "DeclToLoc:\n";
912   for (auto [D, L] : DeclToLoc)
913     OS << "  [" << D->getNameAsString() << ", " << L << "]\n";
914 
915   OS << "ExprToLoc:\n";
916   for (auto [E, L] : ExprToLoc)
917     OS << "  [" << E << ", " << L << "]\n";
918 
919   OS << "LocToVal:\n";
920   for (auto [L, V] : LocToVal) {
921     OS << "  [" << L << ", " << V << ": " << *V << "]\n";
922   }
923 
924   OS << "FlowConditionToken:\n";
925   DACtx->dumpFlowCondition(FlowConditionToken, OS);
926 }
927 
928 void Environment::dump() const {
929   dump(llvm::dbgs());
930 }
931 
932 AggregateStorageLocation *
933 getImplicitObjectLocation(const CXXMemberCallExpr &MCE,
934                           const Environment &Env) {
935   Expr *ImplicitObject = MCE.getImplicitObjectArgument();
936   if (ImplicitObject == nullptr)
937     return nullptr;
938   StorageLocation *Loc =
939       Env.getStorageLocation(*ImplicitObject, SkipPast::Reference);
940   if (Loc == nullptr)
941     return nullptr;
942   if (ImplicitObject->getType()->isPointerType()) {
943     if (auto *Val = cast_or_null<PointerValue>(Env.getValue(*Loc)))
944       return &cast<AggregateStorageLocation>(Val->getPointeeLoc());
945     return nullptr;
946   }
947   return cast<AggregateStorageLocation>(Loc);
948 }
949 
950 AggregateStorageLocation *getBaseObjectLocation(const MemberExpr &ME,
951                                                 const Environment &Env) {
952   Expr *Base = ME.getBase();
953   if (Base == nullptr)
954     return nullptr;
955   StorageLocation *Loc = Env.getStorageLocation(*Base, SkipPast::Reference);
956   if (Loc == nullptr)
957     return nullptr;
958   if (ME.isArrow()) {
959     if (auto *Val = cast_or_null<PointerValue>(Env.getValue(*Loc)))
960       return &cast<AggregateStorageLocation>(Val->getPointeeLoc());
961     return nullptr;
962   }
963   return cast<AggregateStorageLocation>(Loc);
964 }
965 
966 std::vector<FieldDecl *> getFieldsForInitListExpr(const RecordDecl *RD) {
967   // Unnamed bitfields are only used for padding and do not appear in
968   // `InitListExpr`'s inits. However, those fields do appear in `RecordDecl`'s
969   // field list, and we thus need to remove them before mapping inits to
970   // fields to avoid mapping inits to the wrongs fields.
971   std::vector<FieldDecl *> Fields;
972   llvm::copy_if(
973       RD->fields(), std::back_inserter(Fields),
974       [](const FieldDecl *Field) { return !Field->isUnnamedBitfield(); });
975   return Fields;
976 }
977 
978 } // namespace dataflow
979 } // namespace clang
980