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