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