1 //===-- DataflowEnvironment.h -----------------------------------*- 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 #ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWENVIRONMENT_H
16 #define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWENVIRONMENT_H
17 
18 #include "clang/AST/Decl.h"
19 #include "clang/AST/DeclBase.h"
20 #include "clang/AST/Expr.h"
21 #include "clang/AST/Type.h"
22 #include "clang/Analysis/FlowSensitive/ControlFlowContext.h"
23 #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
24 #include "clang/Analysis/FlowSensitive/DataflowLattice.h"
25 #include "clang/Analysis/FlowSensitive/Formula.h"
26 #include "clang/Analysis/FlowSensitive/Logger.h"
27 #include "clang/Analysis/FlowSensitive/StorageLocation.h"
28 #include "clang/Analysis/FlowSensitive/Value.h"
29 #include "llvm/ADT/DenseMap.h"
30 #include "llvm/ADT/DenseSet.h"
31 #include "llvm/ADT/MapVector.h"
32 #include "llvm/Support/Compiler.h"
33 #include "llvm/Support/ErrorHandling.h"
34 #include <memory>
35 #include <type_traits>
36 #include <utility>
37 
38 namespace clang {
39 namespace dataflow {
40 
41 /// Indicates what kind of indirections should be skipped past when retrieving
42 /// storage locations or values.
43 ///
44 /// FIXME: Consider renaming this or replacing it with a more appropriate model.
45 /// See the discussion in https://reviews.llvm.org/D116596 for context.
46 enum class SkipPast {
47   /// No indirections should be skipped past.
48   None,
49   /// An optional reference should be skipped past.
50   Reference,
51 };
52 
53 /// Indicates the result of a tentative comparison.
54 enum class ComparisonResult {
55   Same,
56   Different,
57   Unknown,
58 };
59 
60 /// Holds the state of the program (store and heap) at a given program point.
61 ///
62 /// WARNING: Symbolic values that are created by the environment for static
63 /// local and global variables are not currently invalidated on function calls.
64 /// This is unsound and should be taken into account when designing dataflow
65 /// analyses.
66 class Environment {
67 public:
68   /// Supplements `Environment` with non-standard comparison and join
69   /// operations.
70   class ValueModel {
71   public:
72     virtual ~ValueModel() = default;
73 
74     /// Returns:
75     ///   `Same`: `Val1` is equivalent to `Val2`, according to the model.
76     ///   `Different`: `Val1` is distinct from `Val2`, according to the model.
77     ///   `Unknown`: The model can't determine a relationship between `Val1` and
78     ///    `Val2`.
79     ///
80     /// Requirements:
81     ///
82     ///  `Val1` and `Val2` must be distinct.
83     ///
84     ///  `Val1` and `Val2` must model values of type `Type`.
85     ///
86     ///  `Val1` and `Val2` must be assigned to the same storage location in
87     ///  `Env1` and `Env2` respectively.
88     virtual ComparisonResult compare(QualType Type, const Value &Val1,
89                                      const Environment &Env1, const Value &Val2,
90                                      const Environment &Env2) {
91       // FIXME: Consider adding QualType to StructValue and removing the Type
92       // argument here.
93       return ComparisonResult::Unknown;
94     }
95 
96     /// Modifies `MergedVal` to approximate both `Val1` and `Val2`. This could
97     /// be a strict lattice join or a more general widening operation.
98     ///
99     /// If this function returns true, `MergedVal` will be assigned to a storage
100     /// location of type `Type` in `MergedEnv`.
101     ///
102     /// `Env1` and `Env2` can be used to query child values and path condition
103     /// implications of `Val1` and `Val2` respectively.
104     ///
105     /// Requirements:
106     ///
107     ///  `Val1` and `Val2` must be distinct.
108     ///
109     ///  `Val1`, `Val2`, and `MergedVal` must model values of type `Type`.
110     ///
111     ///  `Val1` and `Val2` must be assigned to the same storage location in
112     ///  `Env1` and `Env2` respectively.
113     virtual bool merge(QualType Type, const Value &Val1,
114                        const Environment &Env1, const Value &Val2,
115                        const Environment &Env2, Value &MergedVal,
116                        Environment &MergedEnv) {
117       return true;
118     }
119 
120     /// This function may widen the current value -- replace it with an
121     /// approximation that can reach a fixed point more quickly than iterated
122     /// application of the transfer function alone. The previous value is
123     /// provided to inform the choice of widened value. The function must also
124     /// serve as a comparison operation, by indicating whether the widened value
125     /// is equivalent to the previous value.
126     ///
127     /// Returns either:
128     ///
129     ///   `nullptr`, if this value is not of interest to the model, or
130     ///
131     ///   `&Prev`, if the widened value is equivalent to `Prev`, or
132     ///
133     ///   A non-null value that approximates `Current`. `Prev` is available to
134     ///   inform the chosen approximation.
135     ///
136     /// `PrevEnv` and `CurrentEnv` can be used to query child values and path
137     /// condition implications of `Prev` and `Current`, respectively.
138     ///
139     /// Requirements:
140     ///
141     ///  `Prev` and `Current` must model values of type `Type`.
142     ///
143     ///  `Prev` and `Current` must be assigned to the same storage location in
144     ///  `PrevEnv` and `CurrentEnv`, respectively.
145     virtual Value *widen(QualType Type, Value &Prev, const Environment &PrevEnv,
146                          Value &Current, Environment &CurrentEnv) {
147       // The default implementation reduces to just comparison, since comparison
148       // is required by the API, even if no widening is performed.
149       switch (compare(Type, Prev, PrevEnv, Current, CurrentEnv)) {
150         case ComparisonResult::Same:
151           return &Prev;
152         case ComparisonResult::Different:
153           return &Current;
154         case ComparisonResult::Unknown:
155           return nullptr;
156       }
157       llvm_unreachable("all cases in switch covered");
158     }
159   };
160 
161   /// Creates an environment that uses `DACtx` to store objects that encompass
162   /// the state of a program.
163   explicit Environment(DataflowAnalysisContext &DACtx);
164 
165   // Copy-constructor is private, Environments should not be copied. See fork().
166   Environment &operator=(const Environment &Other) = delete;
167 
168   Environment(Environment &&Other) = default;
169   Environment &operator=(Environment &&Other) = default;
170 
171   /// Creates an environment that uses `DACtx` to store objects that encompass
172   /// the state of a program.
173   ///
174   /// If `DeclCtx` is a function, initializes the environment with symbolic
175   /// representations of the function parameters.
176   ///
177   /// If `DeclCtx` is a non-static member function, initializes the environment
178   /// with a symbolic representation of the `this` pointee.
179   Environment(DataflowAnalysisContext &DACtx, const DeclContext &DeclCtx);
180 
181   /// Returns a new environment that is a copy of this one.
182   ///
183   /// The state of the program is initially the same, but can be mutated without
184   /// affecting the original.
185   ///
186   /// However the original should not be further mutated, as this may interfere
187   /// with the fork. (In practice, values are stored independently, but the
188   /// forked flow condition references the original).
189   Environment fork() const;
190 
191   /// Creates and returns an environment to use for an inline analysis  of the
192   /// callee. Uses the storage location from each argument in the `Call` as the
193   /// storage location for the corresponding parameter in the callee.
194   ///
195   /// Requirements:
196   ///
197   ///  The callee of `Call` must be a `FunctionDecl`.
198   ///
199   ///  The body of the callee must not reference globals.
200   ///
201   ///  The arguments of `Call` must map 1:1 to the callee's parameters.
202   Environment pushCall(const CallExpr *Call) const;
203   Environment pushCall(const CXXConstructExpr *Call) const;
204 
205   /// Moves gathered information back into `this` from a `CalleeEnv` created via
206   /// `pushCall`.
207   void popCall(const CallExpr *Call, const Environment &CalleeEnv);
208   void popCall(const CXXConstructExpr *Call, const Environment &CalleeEnv);
209 
210   /// Returns true if and only if the environment is equivalent to `Other`, i.e
211   /// the two environments:
212   ///  - have the same mappings from declarations to storage locations,
213   ///  - have the same mappings from expressions to storage locations,
214   ///  - have the same or equivalent (according to `Model`) values assigned to
215   ///    the same storage locations.
216   ///
217   /// Requirements:
218   ///
219   ///  `Other` and `this` must use the same `DataflowAnalysisContext`.
220   bool equivalentTo(const Environment &Other,
221                     Environment::ValueModel &Model) const;
222 
223   /// Joins two environments by taking the intersection of storage locations and
224   /// values that are stored in them. Distinct values that are assigned to the
225   /// same storage locations in `EnvA` and `EnvB` are merged using `Model`.
226   ///
227   /// Requirements:
228   ///
229   ///  `EnvA` and `EnvB` must use the same `DataflowAnalysisContext`.
230   static Environment join(const Environment &EnvA, const Environment &EnvB,
231                           Environment::ValueModel &Model);
232 
233   /// Widens the environment point-wise, using `PrevEnv` as needed to inform the
234   /// approximation.
235   ///
236   /// Requirements:
237   ///
238   ///  `PrevEnv` must be the immediate previous version of the environment.
239   ///  `PrevEnv` and `this` must use the same `DataflowAnalysisContext`.
240   LatticeJoinEffect widen(const Environment &PrevEnv,
241                           Environment::ValueModel &Model);
242 
243   // FIXME: Rename `createOrGetStorageLocation` to `getOrCreateStorageLocation`,
244   // `getStableStorageLocation`, or something more appropriate.
245 
246   /// Creates a storage location appropriate for `Type`. Does not assign a value
247   /// to the returned storage location in the environment.
248   ///
249   /// Requirements:
250   ///
251   ///  `Type` must not be null.
252   StorageLocation &createStorageLocation(QualType Type);
253 
254   /// Creates a storage location for `D`. Does not assign the returned storage
255   /// location to `D` in the environment. Does not assign a value to the
256   /// returned storage location in the environment.
257   StorageLocation &createStorageLocation(const VarDecl &D);
258 
259   /// Creates a storage location for `E`. Does not assign the returned storage
260   /// location to `E` in the environment. Does not assign a value to the
261   /// returned storage location in the environment.
262   StorageLocation &createStorageLocation(const Expr &E);
263 
264   /// Assigns `Loc` as the storage location of `D` in the environment.
265   ///
266   /// Requirements:
267   ///
268   ///  `D` must not already have a storage location in the environment.
269   ///
270   ///  If `D` has reference type, `Loc` must refer directly to the referenced
271   ///  object (if any), not to a `ReferenceValue`, and it is not permitted to
272   ///  later change `Loc` to refer to a `ReferenceValue.`
273   void setStorageLocation(const ValueDecl &D, StorageLocation &Loc);
274 
275   /// Returns the storage location assigned to `D` in the environment, or null
276   /// if `D` isn't assigned a storage location in the environment.
277   ///
278   /// Note that if `D` has reference type, the storage location that is returned
279   /// refers directly to the referenced object, not a `ReferenceValue`.
280   StorageLocation *getStorageLocation(const ValueDecl &D) const;
281 
282   /// Assigns `Loc` as the storage location of `E` in the environment.
283   ///
284   /// This function is deprecated; prefer `setStorageLocationStrict()`.
285   /// For details, see https://discourse.llvm.org/t/70086.
286   ///
287   /// Requirements:
288   ///
289   ///  `E` must not be assigned a storage location in the environment.
290   void setStorageLocation(const Expr &E, StorageLocation &Loc);
291 
292   /// Assigns `Loc` as the storage location of the glvalue `E` in the
293   /// environment.
294   ///
295   /// This function is the preferred alternative to
296   /// `setStorageLocation(const Expr &, StorageLocation &)`. Once the migration
297   /// to strict handling of value categories is complete (see
298   /// https://discourse.llvm.org/t/70086), `setStorageLocation()` will be
299   /// removed and this function will be renamed to `setStorageLocation()`.
300   ///
301   /// Requirements:
302   ///
303   ///  `E` must not be assigned a storage location in the environment.
304   ///  `E` must be a glvalue or a `BuiltinType::BuiltinFn`
305   void setStorageLocationStrict(const Expr &E, StorageLocation &Loc);
306 
307   /// Returns the storage location assigned to `E` in the environment, applying
308   /// the `SP` policy for skipping past indirections, or null if `E` isn't
309   /// assigned a storage location in the environment.
310   ///
311   /// This function is deprecated; prefer `getStorageLocationStrict()`.
312   /// For details, see https://discourse.llvm.org/t/70086.
313   StorageLocation *getStorageLocation(const Expr &E, SkipPast SP) const;
314 
315   /// Returns the storage location assigned to the glvalue `E` in the
316   /// environment, or null if `E` isn't assigned a storage location in the
317   /// environment.
318   ///
319   /// If the storage location for `E` is associated with a
320   /// `ReferenceValue RefVal`, returns `RefVal.getReferentLoc()` instead.
321   ///
322   /// This function is the preferred alternative to
323   /// `getStorageLocation(const Expr &, SkipPast)`. Once the migration
324   /// to strict handling of value categories is complete (see
325   /// https://discourse.llvm.org/t/70086), `getStorageLocation()` will be
326   /// removed and this function will be renamed to `getStorageLocation()`.
327   ///
328   /// Requirements:
329   ///  `E` must be a glvalue or a `BuiltinType::BuiltinFn`
330   StorageLocation *getStorageLocationStrict(const Expr &E) const;
331 
332   /// Returns the storage location assigned to the `this` pointee in the
333   /// environment or null if the `this` pointee has no assigned storage location
334   /// in the environment.
335   AggregateStorageLocation *getThisPointeeStorageLocation() const;
336 
337   /// Returns the location of the result object for a record-type prvalue.
338   ///
339   /// In C++, prvalues of record type serve only a limited purpose: They can
340   /// only be used to initialize a result object (e.g. a variable or a
341   /// temporary). This function returns the location of that result object.
342   ///
343   /// When creating a prvalue of record type, we already need the storage
344   /// location of the result object to pass in `this`, even though prvalues are
345   /// otherwise not associated with storage locations.
346   ///
347   /// FIXME: Currently, this simply returns a stable storage location for `E`,
348   /// but this doesn't do the right thing in scenarios like the following:
349   /// ```
350   /// MyClass c = some_condition()? MyClass(foo) : MyClass(bar);
351   /// ```
352   /// Here, `MyClass(foo)` and `MyClass(bar)` will have two different storage
353   /// locations, when in fact their storage locations should be the same.
354   /// Eventually, we want to propagate storage locations from result objects
355   /// down to the prvalues that initialize them, similar to the way that this is
356   /// done in Clang's CodeGen.
357   ///
358   /// Requirements:
359   ///  `E` must be a prvalue of record type.
360   AggregateStorageLocation &getResultObjectLocation(const Expr &RecordPRValue);
361 
362   /// Returns the return value of the current function. This can be null if:
363   /// - The function has a void return type
364   /// - No return value could be determined for the function, for example
365   ///   because it calls a function without a body.
366   ///
367   /// Requirements:
368   ///  The current function must have a non-reference return type.
369   Value *getReturnValue() const {
370     assert(getCurrentFunc() != nullptr &&
371            !getCurrentFunc()->getReturnType()->isReferenceType());
372     return ReturnVal;
373   }
374 
375   /// Returns the storage location for the reference returned by the current
376   /// function. This can be null if function doesn't return a single consistent
377   /// reference.
378   ///
379   /// Requirements:
380   ///  The current function must have a reference return type.
381   StorageLocation *getReturnStorageLocation() const {
382     assert(getCurrentFunc() != nullptr &&
383            getCurrentFunc()->getReturnType()->isReferenceType());
384     return ReturnLoc;
385   }
386 
387   /// Sets the return value of the current function.
388   ///
389   /// Requirements:
390   ///  The current function must have a non-reference return type.
391   void setReturnValue(Value *Val) {
392     assert(getCurrentFunc() != nullptr &&
393            !getCurrentFunc()->getReturnType()->isReferenceType());
394     ReturnVal = Val;
395   }
396 
397   /// Sets the storage location for the reference returned by the current
398   /// function.
399   ///
400   /// Requirements:
401   ///  The current function must have a reference return type.
402   void setReturnStorageLocation(StorageLocation *Loc) {
403     assert(getCurrentFunc() != nullptr &&
404            getCurrentFunc()->getReturnType()->isReferenceType());
405     ReturnLoc = Loc;
406   }
407 
408   /// Returns a pointer value that represents a null pointer. Calls with
409   /// `PointeeType` that are canonically equivalent will return the same result.
410   PointerValue &getOrCreateNullPointerValue(QualType PointeeType);
411 
412   /// Creates a value appropriate for `Type`, if `Type` is supported, otherwise
413   /// returns null.
414   ///
415   /// If `Type` is a pointer or reference type, creates all the necessary
416   /// storage locations and values for indirections until it finds a
417   /// non-pointer/non-reference type.
418   ///
419   /// If `Type` is a class, struct, or union type, calls `setValue()` to
420   /// associate the `StructValue` with its storage location
421   /// (`StructValue::getAggregateLoc()`).
422   ///
423   /// If `Type` is one of the following types, this function will always return
424   /// a non-null pointer:
425   /// - `bool`
426   /// - Any integer type
427   /// - Any class, struct, or union type
428   ///
429   /// Requirements:
430   ///
431   ///  `Type` must not be null.
432   Value *createValue(QualType Type);
433 
434   /// Creates an object (i.e. a storage location with an associated value) of
435   /// type `Ty`. If `InitExpr` is non-null and has a value associated with it,
436   /// initializes the object with this value. Otherwise, initializes the object
437   /// with a value created using `createValue()`.
438   StorageLocation &createObject(QualType Ty, const Expr *InitExpr = nullptr) {
439     return createObjectInternal(nullptr, Ty, InitExpr);
440   }
441 
442   /// Creates an object for the variable declaration `D`. If `D` has an
443   /// initializer and this initializer is associated with a value, initializes
444   /// the object with this value.  Otherwise, initializes the object with a
445   /// value created using `createValue()`. Uses the storage location returned by
446   /// `DataflowAnalysisContext::getStableStorageLocation(D)`.
447   StorageLocation &createObject(const VarDecl &D) {
448     return createObjectInternal(&D, D.getType(), D.getInit());
449   }
450 
451   /// Creates an object for the variable declaration `D`. If `InitExpr` is
452   /// non-null and has a value associated with it, initializes the object with
453   /// this value. Otherwise, initializes the object with a value created using
454   /// `createValue()`.  Uses the storage location returned by
455   /// `DataflowAnalysisContext::getStableStorageLocation(D)`.
456   StorageLocation &createObject(const VarDecl &D, const Expr *InitExpr) {
457     return createObjectInternal(&D, D.getType(), InitExpr);
458   }
459 
460   /// Assigns `Val` as the value of `Loc` in the environment.
461   void setValue(const StorageLocation &Loc, Value &Val);
462 
463   /// Clears any association between `Loc` and a value in the environment.
464   void clearValue(const StorageLocation &Loc) { LocToVal.erase(&Loc); }
465 
466   /// Assigns `Val` as the value of the prvalue `E` in the environment.
467   ///
468   /// If `E` is not yet associated with a storage location, associates it with
469   /// a newly created storage location. In any case, associates the storage
470   /// location of `E` with `Val`.
471   ///
472   /// Once the migration to strict handling of value categories is complete
473   /// (see https://discourse.llvm.org/t/70086), this function will be renamed to
474   /// `setValue()`. At this point, prvalue expressions will be associated
475   /// directly with `Value`s, and the legacy behavior of associating prvalue
476   /// expressions with storage locations (as described above) will be
477   /// eliminated.
478   ///
479   /// Requirements:
480   ///
481   ///  `E` must be a prvalue
482   ///  `Val` must not be a `ReferenceValue`
483   ///  If `Val` is a `StructValue`, its `AggregateStorageLocation` must be the
484   ///  same as that of any `StructValue` that has already been associated with
485   ///  `E`. This is to guarantee that the result object initialized by a prvalue
486   ///  `StructValue` has a durable storage location.
487   void setValueStrict(const Expr &E, Value &Val);
488 
489   /// Returns the value assigned to `Loc` in the environment or null if `Loc`
490   /// isn't assigned a value in the environment.
491   Value *getValue(const StorageLocation &Loc) const;
492 
493   /// Equivalent to `getValue(getStorageLocation(D, SP), SkipPast::None)` if `D`
494   /// is assigned a storage location in the environment, otherwise returns null.
495   Value *getValue(const ValueDecl &D) const;
496 
497   /// Equivalent to `getValue(getStorageLocation(E, SP), SkipPast::None)` if `E`
498   /// is assigned a storage location in the environment, otherwise returns null.
499   ///
500   /// This function is deprecated; prefer `getValueStrict()`. For details, see
501   /// https://discourse.llvm.org/t/70086.
502   Value *getValue(const Expr &E, SkipPast SP) const;
503 
504   /// Returns the `Value` assigned to the prvalue `E` in the environment, or
505   /// null if `E` isn't assigned a value in the environment.
506   ///
507   /// This function is the preferred alternative to
508   /// `getValue(const Expr &, SkipPast)`. Once the migration to strict handling
509   /// of value categories is complete (see https://discourse.llvm.org/t/70086),
510   /// `getValue()` will be removed and this function will be renamed to
511   /// `getValue()`.
512   ///
513   /// Requirements:
514   ///
515   ///  `E` must be a prvalue
516   Value *getValueStrict(const Expr &E) const;
517 
518   // FIXME: should we deprecate the following & call arena().create() directly?
519 
520   /// Creates a `T` (some subclass of `Value`), forwarding `args` to the
521   /// constructor, and returns a reference to it.
522   ///
523   /// The analysis context takes ownership of the created object. The object
524   /// will be destroyed when the analysis context is destroyed.
525   template <typename T, typename... Args>
526   std::enable_if_t<std::is_base_of<Value, T>::value, T &>
527   create(Args &&...args) {
528     return arena().create<T>(std::forward<Args>(args)...);
529   }
530 
531   /// Returns a symbolic integer value that models an integer literal equal to
532   /// `Value`
533   IntegerValue &getIntLiteralValue(llvm::APInt Value) const {
534     return arena().makeIntLiteral(Value);
535   }
536 
537   /// Returns a symbolic boolean value that models a boolean literal equal to
538   /// `Value`
539   AtomicBoolValue &getBoolLiteralValue(bool Value) const {
540     return cast<AtomicBoolValue>(
541         arena().makeBoolValue(arena().makeLiteral(Value)));
542   }
543 
544   /// Returns an atomic boolean value.
545   BoolValue &makeAtomicBoolValue() const {
546     return arena().makeAtomValue();
547   }
548 
549   /// Returns a unique instance of boolean Top.
550   BoolValue &makeTopBoolValue() const {
551     return arena().makeTopValue();
552   }
553 
554   /// Returns a boolean value that represents the conjunction of `LHS` and
555   /// `RHS`. Subsequent calls with the same arguments, regardless of their
556   /// order, will return the same result. If the given boolean values represent
557   /// the same value, the result will be the value itself.
558   BoolValue &makeAnd(BoolValue &LHS, BoolValue &RHS) const {
559     return arena().makeBoolValue(
560         arena().makeAnd(LHS.formula(), RHS.formula()));
561   }
562 
563   /// Returns a boolean value that represents the disjunction of `LHS` and
564   /// `RHS`. Subsequent calls with the same arguments, regardless of their
565   /// order, will return the same result. If the given boolean values represent
566   /// the same value, the result will be the value itself.
567   BoolValue &makeOr(BoolValue &LHS, BoolValue &RHS) const {
568     return arena().makeBoolValue(
569         arena().makeOr(LHS.formula(), RHS.formula()));
570   }
571 
572   /// Returns a boolean value that represents the negation of `Val`. Subsequent
573   /// calls with the same argument will return the same result.
574   BoolValue &makeNot(BoolValue &Val) const {
575     return arena().makeBoolValue(arena().makeNot(Val.formula()));
576   }
577 
578   /// Returns a boolean value represents `LHS` => `RHS`. Subsequent calls with
579   /// the same arguments, will return the same result. If the given boolean
580   /// values represent the same value, the result will be a value that
581   /// represents the true boolean literal.
582   BoolValue &makeImplication(BoolValue &LHS, BoolValue &RHS) const {
583     return arena().makeBoolValue(
584         arena().makeImplies(LHS.formula(), RHS.formula()));
585   }
586 
587   /// Returns a boolean value represents `LHS` <=> `RHS`. Subsequent calls with
588   /// the same arguments, regardless of their order, will return the same
589   /// result. If the given boolean values represent the same value, the result
590   /// will be a value that represents the true boolean literal.
591   BoolValue &makeIff(BoolValue &LHS, BoolValue &RHS) const {
592     return arena().makeBoolValue(
593         arena().makeEquals(LHS.formula(), RHS.formula()));
594   }
595 
596   /// Returns a boolean variable that identifies the flow condition (FC).
597   ///
598   /// The flow condition is a set of facts that are necessarily true when the
599   /// program reaches the current point, expressed as boolean formulas.
600   /// The flow condition token is equivalent to the AND of these facts.
601   ///
602   /// These may e.g. constrain the value of certain variables. A pointer
603   /// variable may have a consistent modeled PointerValue throughout, but at a
604   /// given point the Environment may tell us that the value must be non-null.
605   ///
606   /// The FC is necessary but not sufficient for this point to be reachable.
607   /// In particular, where the FC token appears in flow conditions of successor
608   /// environments, it means "point X may have been reached", not
609   /// "point X was reached".
610   Atom getFlowConditionToken() const { return FlowConditionToken; }
611 
612   /// Record a fact that must be true if this point in the program is reached.
613   void addToFlowCondition(const Formula &);
614 
615   /// Returns true if the formula is always true when this point is reached.
616   /// Returns false if the formula may be false, or if the flow condition isn't
617   /// sufficiently precise to prove that it is true.
618   bool flowConditionImplies(const Formula &) const;
619 
620   /// Returns the `DeclContext` of the block being analysed, if any. Otherwise,
621   /// returns null.
622   const DeclContext *getDeclCtx() const { return CallStack.back(); }
623 
624   /// Returns the function currently being analyzed, or null if the code being
625   /// analyzed isn't part of a function.
626   const FunctionDecl *getCurrentFunc() const {
627     return dyn_cast<FunctionDecl>(getDeclCtx());
628   }
629 
630   /// Returns whether this `Environment` can be extended to analyze the given
631   /// `Callee` (i.e. if `pushCall` can be used), with recursion disallowed and a
632   /// given `MaxDepth`.
633   bool canDescend(unsigned MaxDepth, const DeclContext *Callee) const;
634 
635   /// Returns the `DataflowAnalysisContext` used by the environment.
636   DataflowAnalysisContext &getDataflowAnalysisContext() const { return *DACtx; }
637 
638   Arena &arena() const { return DACtx->arena(); }
639 
640   LLVM_DUMP_METHOD void dump() const;
641   LLVM_DUMP_METHOD void dump(raw_ostream &OS) const;
642 
643 private:
644   // The copy-constructor is for use in fork() only.
645   Environment(const Environment &) = default;
646 
647   /// Creates a value appropriate for `Type`, if `Type` is supported, otherwise
648   /// return null.
649   ///
650   /// Recursively initializes storage locations and values until it sees a
651   /// self-referential pointer or reference type. `Visited` is used to track
652   /// which types appeared in the reference/pointer chain in order to avoid
653   /// creating a cyclic dependency with self-referential pointers/references.
654   ///
655   /// Requirements:
656   ///
657   ///  `Type` must not be null.
658   Value *createValueUnlessSelfReferential(QualType Type,
659                                           llvm::DenseSet<QualType> &Visited,
660                                           int Depth, int &CreatedValuesCount);
661 
662   /// Creates a storage location for `Ty`. Also creates and associates a value
663   /// with the storage location, unless values of this type are not supported or
664   /// we hit one of the limits at which we stop producing values (controlled by
665   /// `Visited`, `Depth`, and `CreatedValuesCount`).
666   StorageLocation &createLocAndMaybeValue(QualType Ty,
667                                           llvm::DenseSet<QualType> &Visited,
668                                           int Depth, int &CreatedValuesCount);
669 
670   /// Shared implementation of `createObject()` overloads.
671   /// `D` and `InitExpr` may be null.
672   StorageLocation &createObjectInternal(const VarDecl *D, QualType Ty,
673                                         const Expr *InitExpr);
674 
675   StorageLocation &skip(StorageLocation &Loc, SkipPast SP) const;
676   const StorageLocation &skip(const StorageLocation &Loc, SkipPast SP) const;
677 
678   /// Shared implementation of `pushCall` overloads. Note that unlike
679   /// `pushCall`, this member is invoked on the environment of the callee, not
680   /// of the caller.
681   void pushCallInternal(const FunctionDecl *FuncDecl,
682                         ArrayRef<const Expr *> Args);
683 
684   /// Assigns storage locations and values to all global variables, fields
685   /// and functions referenced in `FuncDecl`. `FuncDecl` must have a body.
686   void initFieldsGlobalsAndFuncs(const FunctionDecl *FuncDecl);
687 
688   // `DACtx` is not null and not owned by this object.
689   DataflowAnalysisContext *DACtx;
690 
691   // FIXME: move the fields `CallStack`, `ReturnVal`, `ReturnLoc` and
692   // `ThisPointeeLoc` into a separate call-context object, shared between
693   // environments in the same call.
694   // https://github.com/llvm/llvm-project/issues/59005
695 
696   // `DeclContext` of the block being analysed if provided.
697   std::vector<const DeclContext *> CallStack;
698 
699   // Value returned by the function (if it has non-reference return type).
700   Value *ReturnVal = nullptr;
701   // Storage location of the reference returned by the function (if it has
702   // reference return type).
703   StorageLocation *ReturnLoc = nullptr;
704   // The storage location of the `this` pointee. Should only be null if the
705   // function being analyzed is only a function and not a method.
706   AggregateStorageLocation *ThisPointeeLoc = nullptr;
707 
708   // Maps from program declarations and statements to storage locations that are
709   // assigned to them. Unlike the maps in `DataflowAnalysisContext`, these
710   // include only storage locations that are in scope for a particular basic
711   // block.
712   llvm::DenseMap<const ValueDecl *, StorageLocation *> DeclToLoc;
713   llvm::DenseMap<const Expr *, StorageLocation *> ExprToLoc;
714   // We preserve insertion order so that join/widen process values in
715   // deterministic sequence. This in turn produces deterministic SAT formulas.
716   llvm::MapVector<const StorageLocation *, Value *> LocToVal;
717 
718   Atom FlowConditionToken;
719 };
720 
721 /// Returns the storage location for the implicit object of a
722 /// `CXXMemberCallExpr`, or null if none is defined in the environment.
723 /// Dereferences the pointer if the member call expression was written using
724 /// `->`.
725 AggregateStorageLocation *
726 getImplicitObjectLocation(const CXXMemberCallExpr &MCE, const Environment &Env);
727 
728 /// Returns the storage location for the base object of a `MemberExpr`, or null
729 /// if none is defined in the environment. Dereferences the pointer if the
730 /// member expression was written using `->`.
731 AggregateStorageLocation *getBaseObjectLocation(const MemberExpr &ME,
732                                                 const Environment &Env);
733 
734 /// Returns the fields of `RD` that are initialized by an `InitListExpr`, in the
735 /// order in which they appear in `InitListExpr::inits()`.
736 std::vector<FieldDecl *> getFieldsForInitListExpr(const RecordDecl *RD);
737 
738 /// Associates a new `StructValue` with `Loc` and returns the new value.
739 /// It is not defined whether the field values remain the same or not.
740 ///
741 /// This function is primarily intended for use by checks that set custom
742 /// properties on `StructValue`s to model the state of these values. Such checks
743 /// should avoid modifying the properties of an existing `StructValue` because
744 /// these changes would be visible to other `Environment`s that share the same
745 /// `StructValue`. Instead, call `refreshStructValue()`, then set the properties
746 /// on the new `StructValue` that it returns. Typical usage:
747 ///
748 ///   refreshStructValue(Loc, Env).setProperty("my_prop", MyPropValue);
749 StructValue &refreshStructValue(AggregateStorageLocation &Loc,
750                                 Environment &Env);
751 
752 /// Associates a new `StructValue` with `Expr` and returns the new value.
753 /// See also documentation for the overload above.
754 StructValue &refreshStructValue(const Expr &Expr, Environment &Env);
755 
756 } // namespace dataflow
757 } // namespace clang
758 
759 #endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWENVIRONMENT_H
760