Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:25

0001 //===-- DataflowEnvironment.h -----------------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 //  This file defines an Environment class that is used by dataflow analyses
0010 //  that run over Control-Flow Graphs (CFGs) to keep track of the state of the
0011 //  program at given program points.
0012 //
0013 //===----------------------------------------------------------------------===//
0014 
0015 #ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWENVIRONMENT_H
0016 #define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWENVIRONMENT_H
0017 
0018 #include "clang/AST/Decl.h"
0019 #include "clang/AST/DeclBase.h"
0020 #include "clang/AST/Expr.h"
0021 #include "clang/AST/Type.h"
0022 #include "clang/Analysis/FlowSensitive/ASTOps.h"
0023 #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
0024 #include "clang/Analysis/FlowSensitive/DataflowLattice.h"
0025 #include "clang/Analysis/FlowSensitive/Formula.h"
0026 #include "clang/Analysis/FlowSensitive/Logger.h"
0027 #include "clang/Analysis/FlowSensitive/StorageLocation.h"
0028 #include "clang/Analysis/FlowSensitive/Value.h"
0029 #include "llvm/ADT/DenseMap.h"
0030 #include "llvm/ADT/DenseSet.h"
0031 #include "llvm/ADT/MapVector.h"
0032 #include "llvm/Support/Compiler.h"
0033 #include "llvm/Support/ErrorHandling.h"
0034 #include <cassert>
0035 #include <memory>
0036 #include <type_traits>
0037 #include <utility>
0038 #include <vector>
0039 
0040 namespace clang {
0041 namespace dataflow {
0042 
0043 /// Indicates the result of a tentative comparison.
0044 enum class ComparisonResult {
0045   Same,
0046   Different,
0047   Unknown,
0048 };
0049 
0050 /// The result of a `widen` operation.
0051 struct WidenResult {
0052   /// Non-null pointer to a potentially widened version of the input value.
0053   Value *V;
0054   /// Whether `V` represents a "change" (that is, a different value) with
0055   /// respect to the previous value in the sequence.
0056   LatticeEffect Effect;
0057 };
0058 
0059 /// Holds the state of the program (store and heap) at a given program point.
0060 ///
0061 /// WARNING: Symbolic values that are created by the environment for static
0062 /// local and global variables are not currently invalidated on function calls.
0063 /// This is unsound and should be taken into account when designing dataflow
0064 /// analyses.
0065 class Environment {
0066 public:
0067   /// Supplements `Environment` with non-standard comparison and join
0068   /// operations.
0069   class ValueModel {
0070   public:
0071     virtual ~ValueModel() = default;
0072 
0073     /// Returns:
0074     ///   `Same`: `Val1` is equivalent to `Val2`, according to the model.
0075     ///   `Different`: `Val1` is distinct from `Val2`, according to the model.
0076     ///   `Unknown`: The model can't determine a relationship between `Val1` and
0077     ///    `Val2`.
0078     ///
0079     /// Requirements:
0080     ///
0081     ///  `Val1` and `Val2` must be distinct.
0082     ///
0083     ///  `Val1` and `Val2` must model values of type `Type`.
0084     ///
0085     ///  `Val1` and `Val2` must be assigned to the same storage location in
0086     ///  `Env1` and `Env2` respectively.
0087     virtual ComparisonResult compare(QualType Type, const Value &Val1,
0088                                      const Environment &Env1, const Value &Val2,
0089                                      const Environment &Env2) {
0090       // FIXME: Consider adding `QualType` to `Value` and removing the `Type`
0091       // argument here.
0092       return ComparisonResult::Unknown;
0093     }
0094 
0095     /// Modifies `JoinedVal` to approximate both `Val1` and `Val2`. This should
0096     /// obey the properties of a lattice join.
0097     ///
0098     /// `Env1` and `Env2` can be used to query child values and path condition
0099     /// implications of `Val1` and `Val2` respectively.
0100     ///
0101     /// Requirements:
0102     ///
0103     ///  `Val1` and `Val2` must be distinct.
0104     ///
0105     ///  `Val1`, `Val2`, and `JoinedVal` must model values of type `Type`.
0106     ///
0107     ///  `Val1` and `Val2` must be assigned to the same storage location in
0108     ///  `Env1` and `Env2` respectively.
0109     virtual void join(QualType Type, const Value &Val1, const Environment &Env1,
0110                       const Value &Val2, const Environment &Env2,
0111                       Value &JoinedVal, Environment &JoinedEnv) {}
0112 
0113     /// This function may widen the current value -- replace it with an
0114     /// approximation that can reach a fixed point more quickly than iterated
0115     /// application of the transfer function alone. The previous value is
0116     /// provided to inform the choice of widened value. The function must also
0117     /// serve as a comparison operation, by indicating whether the widened value
0118     /// is equivalent to the previous value.
0119     ///
0120     /// Returns one of the folowing:
0121     /// *  `std::nullopt`, if this value is not of interest to the
0122     ///     model.
0123     /// *  A `WidenResult` with:
0124     ///    *  A non-null `Value *` that points either to `Current` or a widened
0125     ///       version of `Current`. This value must be consistent with
0126     ///       the flow condition of `CurrentEnv`. We particularly caution
0127     ///       against using `Prev`, which is rarely consistent.
0128     ///    *  A `LatticeEffect` indicating whether the value should be
0129     ///       considered a new value (`Changed`) or one *equivalent* (if not
0130     ///       necessarily equal) to `Prev` (`Unchanged`).
0131     ///
0132     /// `PrevEnv` and `CurrentEnv` can be used to query child values and path
0133     /// condition implications of `Prev` and `Current`, respectively.
0134     ///
0135     /// Requirements:
0136     ///
0137     ///  `Prev` and `Current` must model values of type `Type`.
0138     ///
0139     ///  `Prev` and `Current` must be assigned to the same storage location in
0140     ///  `PrevEnv` and `CurrentEnv`, respectively.
0141     virtual std::optional<WidenResult> widen(QualType Type, Value &Prev,
0142                                              const Environment &PrevEnv,
0143                                              Value &Current,
0144                                              Environment &CurrentEnv) {
0145       // The default implementation reduces to just comparison, since comparison
0146       // is required by the API, even if no widening is performed.
0147       switch (compare(Type, Prev, PrevEnv, Current, CurrentEnv)) {
0148       case ComparisonResult::Unknown:
0149         return std::nullopt;
0150       case ComparisonResult::Same:
0151         return WidenResult{&Current, LatticeEffect::Unchanged};
0152       case ComparisonResult::Different:
0153         return WidenResult{&Current, LatticeEffect::Changed};
0154       }
0155       llvm_unreachable("all cases in switch covered");
0156     }
0157   };
0158 
0159   /// Creates an environment that uses `DACtx` to store objects that encompass
0160   /// the state of a program.
0161   explicit Environment(DataflowAnalysisContext &DACtx)
0162       : DACtx(&DACtx),
0163         FlowConditionToken(DACtx.arena().makeFlowConditionToken()) {}
0164 
0165   /// Creates an environment that uses `DACtx` to store objects that encompass
0166   /// the state of a program, with `S` as the statement to analyze.
0167   Environment(DataflowAnalysisContext &DACtx, Stmt &S) : Environment(DACtx) {
0168     InitialTargetStmt = &S;
0169   }
0170 
0171   /// Creates an environment that uses `DACtx` to store objects that encompass
0172   /// the state of a program, with `FD` as the function to analyze.
0173   ///
0174   /// Requirements:
0175   ///
0176   ///  The function must have a body, i.e.
0177   ///  `FunctionDecl::doesThisDecalarationHaveABody()` must be true.
0178   Environment(DataflowAnalysisContext &DACtx, const FunctionDecl &FD)
0179       : Environment(DACtx, *FD.getBody()) {
0180     assert(FD.doesThisDeclarationHaveABody());
0181     InitialTargetFunc = &FD;
0182   }
0183 
0184   // Copy-constructor is private, Environments should not be copied. See fork().
0185   Environment &operator=(const Environment &Other) = delete;
0186 
0187   Environment(Environment &&Other) = default;
0188   Environment &operator=(Environment &&Other) = default;
0189 
0190   /// Assigns storage locations and values to all parameters, captures, global
0191   /// variables, fields and functions referenced in the `Stmt` or `FunctionDecl`
0192   /// passed to the constructor.
0193   ///
0194   /// If no `Stmt` or `FunctionDecl` was supplied, this function does nothing.
0195   void initialize();
0196 
0197   /// Returns a new environment that is a copy of this one.
0198   ///
0199   /// The state of the program is initially the same, but can be mutated without
0200   /// affecting the original.
0201   ///
0202   /// However the original should not be further mutated, as this may interfere
0203   /// with the fork. (In practice, values are stored independently, but the
0204   /// forked flow condition references the original).
0205   Environment fork() const;
0206 
0207   /// Creates and returns an environment to use for an inline analysis of the
0208   /// callee. Uses the storage location from each argument in the `Call` as the
0209   /// storage location for the corresponding parameter in the callee.
0210   ///
0211   /// Requirements:
0212   ///
0213   ///  The callee of `Call` must be a `FunctionDecl`.
0214   ///
0215   ///  The body of the callee must not reference globals.
0216   ///
0217   ///  The arguments of `Call` must map 1:1 to the callee's parameters.
0218   Environment pushCall(const CallExpr *Call) const;
0219   Environment pushCall(const CXXConstructExpr *Call) const;
0220 
0221   /// Moves gathered information back into `this` from a `CalleeEnv` created via
0222   /// `pushCall`.
0223   void popCall(const CallExpr *Call, const Environment &CalleeEnv);
0224   void popCall(const CXXConstructExpr *Call, const Environment &CalleeEnv);
0225 
0226   /// Returns true if and only if the environment is equivalent to `Other`, i.e
0227   /// the two environments:
0228   ///  - have the same mappings from declarations to storage locations,
0229   ///  - have the same mappings from expressions to storage locations,
0230   ///  - have the same or equivalent (according to `Model`) values assigned to
0231   ///    the same storage locations.
0232   ///
0233   /// Requirements:
0234   ///
0235   ///  `Other` and `this` must use the same `DataflowAnalysisContext`.
0236   bool equivalentTo(const Environment &Other,
0237                     Environment::ValueModel &Model) const;
0238 
0239   /// How to treat expression state (`ExprToLoc` and `ExprToVal`) in a join.
0240   /// If the join happens within a full expression, expression state should be
0241   /// kept; otherwise, we can discard it.
0242   enum ExprJoinBehavior {
0243     DiscardExprState,
0244     KeepExprState,
0245   };
0246 
0247   /// Joins two environments by taking the intersection of storage locations and
0248   /// values that are stored in them. Distinct values that are assigned to the
0249   /// same storage locations in `EnvA` and `EnvB` are merged using `Model`.
0250   ///
0251   /// Requirements:
0252   ///
0253   ///  `EnvA` and `EnvB` must use the same `DataflowAnalysisContext`.
0254   static Environment join(const Environment &EnvA, const Environment &EnvB,
0255                           Environment::ValueModel &Model,
0256                           ExprJoinBehavior ExprBehavior);
0257 
0258   /// Returns a value that approximates both `Val1` and `Val2`, or null if no
0259   /// such value can be produced.
0260   ///
0261   /// `Env1` and `Env2` can be used to query child values and path condition
0262   /// implications of `Val1` and `Val2` respectively. The joined value will be
0263   /// produced in `JoinedEnv`.
0264   ///
0265   /// Requirements:
0266   ///
0267   ///  `Val1` and `Val2` must model values of type `Type`.
0268   static Value *joinValues(QualType Ty, Value *Val1, const Environment &Env1,
0269                            Value *Val2, const Environment &Env2,
0270                            Environment &JoinedEnv,
0271                            Environment::ValueModel &Model);
0272 
0273   /// Widens the environment point-wise, using `PrevEnv` as needed to inform the
0274   /// approximation.
0275   ///
0276   /// Requirements:
0277   ///
0278   ///  `PrevEnv` must be the immediate previous version of the environment.
0279   ///  `PrevEnv` and `this` must use the same `DataflowAnalysisContext`.
0280   LatticeEffect widen(const Environment &PrevEnv,
0281                       Environment::ValueModel &Model);
0282 
0283   // FIXME: Rename `createOrGetStorageLocation` to `getOrCreateStorageLocation`,
0284   // `getStableStorageLocation`, or something more appropriate.
0285 
0286   /// Creates a storage location appropriate for `Type`. Does not assign a value
0287   /// to the returned storage location in the environment.
0288   ///
0289   /// Requirements:
0290   ///
0291   ///  `Type` must not be null.
0292   StorageLocation &createStorageLocation(QualType Type);
0293 
0294   /// Creates a storage location for `D`. Does not assign the returned storage
0295   /// location to `D` in the environment. Does not assign a value to the
0296   /// returned storage location in the environment.
0297   StorageLocation &createStorageLocation(const ValueDecl &D);
0298 
0299   /// Creates a storage location for `E`. Does not assign the returned storage
0300   /// location to `E` in the environment. Does not assign a value to the
0301   /// returned storage location in the environment.
0302   StorageLocation &createStorageLocation(const Expr &E);
0303 
0304   /// Assigns `Loc` as the storage location of `D` in the environment.
0305   ///
0306   /// Requirements:
0307   ///
0308   ///  `D` must not already have a storage location in the environment.
0309   void setStorageLocation(const ValueDecl &D, StorageLocation &Loc);
0310 
0311   /// Returns the storage location assigned to `D` in the environment, or null
0312   /// if `D` isn't assigned a storage location in the environment.
0313   StorageLocation *getStorageLocation(const ValueDecl &D) const;
0314 
0315   /// Removes the location assigned to `D` in the environment (if any).
0316   void removeDecl(const ValueDecl &D);
0317 
0318   /// Assigns `Loc` as the storage location of the glvalue `E` in the
0319   /// environment.
0320   ///
0321   /// Requirements:
0322   ///
0323   ///  `E` must not be assigned a storage location in the environment.
0324   ///  `E` must be a glvalue or a `BuiltinType::BuiltinFn`
0325   void setStorageLocation(const Expr &E, StorageLocation &Loc);
0326 
0327   /// Returns the storage location assigned to the glvalue `E` in the
0328   /// environment, or null if `E` isn't assigned a storage location in the
0329   /// environment.
0330   ///
0331   /// Requirements:
0332   ///  `E` must be a glvalue or a `BuiltinType::BuiltinFn`
0333   StorageLocation *getStorageLocation(const Expr &E) const;
0334 
0335   /// Returns the result of casting `getStorageLocation(...)` to a subclass of
0336   /// `StorageLocation` (using `cast_or_null<T>`).
0337   /// This assert-fails if the result of `getStorageLocation(...)` is not of
0338   /// type `T *`; if the storage location is not guaranteed to have type `T *`,
0339   /// consider using `dyn_cast_or_null<T>(getStorageLocation(...))` instead.
0340   template <typename T>
0341   std::enable_if_t<std::is_base_of_v<StorageLocation, T>, T *>
0342   get(const ValueDecl &D) const {
0343     return cast_or_null<T>(getStorageLocation(D));
0344   }
0345   template <typename T>
0346   std::enable_if_t<std::is_base_of_v<StorageLocation, T>, T *>
0347   get(const Expr &E) const {
0348     return cast_or_null<T>(getStorageLocation(E));
0349   }
0350 
0351   /// Returns the storage location assigned to the `this` pointee in the
0352   /// environment or null if the `this` pointee has no assigned storage location
0353   /// in the environment.
0354   RecordStorageLocation *getThisPointeeStorageLocation() const {
0355     return ThisPointeeLoc;
0356   }
0357 
0358   /// Sets the storage location assigned to the `this` pointee in the
0359   /// environment.
0360   void setThisPointeeStorageLocation(RecordStorageLocation &Loc) {
0361     ThisPointeeLoc = &Loc;
0362   }
0363 
0364   /// Returns the location of the result object for a record-type prvalue.
0365   ///
0366   /// In C++, prvalues of record type serve only a limited purpose: They can
0367   /// only be used to initialize a result object (e.g. a variable or a
0368   /// temporary). This function returns the location of that result object.
0369   ///
0370   /// When creating a prvalue of record type, we already need the storage
0371   /// location of the result object to pass in `this`, even though prvalues are
0372   /// otherwise not associated with storage locations.
0373   ///
0374   /// Requirements:
0375   ///  `E` must be a prvalue of record type.
0376   RecordStorageLocation &
0377   getResultObjectLocation(const Expr &RecordPRValue) const;
0378 
0379   /// Returns the return value of the function currently being analyzed.
0380   /// This can be null if:
0381   /// - The function has a void return type
0382   /// - No return value could be determined for the function, for example
0383   ///   because it calls a function without a body.
0384   ///
0385   /// Requirements:
0386   ///  The current analysis target must be a function and must have a
0387   ///  non-reference return type.
0388   Value *getReturnValue() const {
0389     assert(getCurrentFunc() != nullptr &&
0390            !getCurrentFunc()->getReturnType()->isReferenceType());
0391     return ReturnVal;
0392   }
0393 
0394   /// Returns the storage location for the reference returned by the function
0395   /// currently being analyzed. This can be null if the function doesn't return
0396   /// a single consistent reference.
0397   ///
0398   /// Requirements:
0399   ///  The current analysis target must be a function and must have a reference
0400   ///  return type.
0401   StorageLocation *getReturnStorageLocation() const {
0402     assert(getCurrentFunc() != nullptr &&
0403            getCurrentFunc()->getReturnType()->isReferenceType());
0404     return ReturnLoc;
0405   }
0406 
0407   /// Sets the return value of the function currently being analyzed.
0408   ///
0409   /// Requirements:
0410   ///  The current analysis target must be a function and must have a
0411   ///  non-reference return type.
0412   void setReturnValue(Value *Val) {
0413     assert(getCurrentFunc() != nullptr &&
0414            !getCurrentFunc()->getReturnType()->isReferenceType());
0415     ReturnVal = Val;
0416   }
0417 
0418   /// Sets the storage location for the reference returned by the function
0419   /// currently being analyzed.
0420   ///
0421   /// Requirements:
0422   ///  The current analysis target must be a function and must have a reference
0423   ///  return type.
0424   void setReturnStorageLocation(StorageLocation *Loc) {
0425     assert(getCurrentFunc() != nullptr &&
0426            getCurrentFunc()->getReturnType()->isReferenceType());
0427     ReturnLoc = Loc;
0428   }
0429 
0430   /// Returns a pointer value that represents a null pointer. Calls with
0431   /// `PointeeType` that are canonically equivalent will return the same result.
0432   PointerValue &getOrCreateNullPointerValue(QualType PointeeType);
0433 
0434   /// Creates a value appropriate for `Type`, if `Type` is supported, otherwise
0435   /// returns null.
0436   ///
0437   /// If `Type` is a pointer or reference type, creates all the necessary
0438   /// storage locations and values for indirections until it finds a
0439   /// non-pointer/non-reference type.
0440   ///
0441   /// If `Type` is one of the following types, this function will always return
0442   /// a non-null pointer:
0443   /// - `bool`
0444   /// - Any integer type
0445   ///
0446   /// Requirements:
0447   ///
0448   ///  - `Type` must not be null.
0449   ///  - `Type` must not be a reference type or record type.
0450   Value *createValue(QualType Type);
0451 
0452   /// Creates an object (i.e. a storage location with an associated value) of
0453   /// type `Ty`. If `InitExpr` is non-null and has a value associated with it,
0454   /// initializes the object with this value. Otherwise, initializes the object
0455   /// with a value created using `createValue()`.
0456   StorageLocation &createObject(QualType Ty, const Expr *InitExpr = nullptr) {
0457     return createObjectInternal(nullptr, Ty, InitExpr);
0458   }
0459 
0460   /// Creates an object for the variable declaration `D`. If `D` has an
0461   /// initializer and this initializer is associated with a value, initializes
0462   /// the object with this value.  Otherwise, initializes the object with a
0463   /// value created using `createValue()`. Uses the storage location returned by
0464   /// `DataflowAnalysisContext::getStableStorageLocation(D)`.
0465   StorageLocation &createObject(const VarDecl &D) {
0466     return createObjectInternal(&D, D.getType(), D.getInit());
0467   }
0468 
0469   /// Creates an object for the variable declaration `D`. If `InitExpr` is
0470   /// non-null and has a value associated with it, initializes the object with
0471   /// this value. Otherwise, initializes the object with a value created using
0472   /// `createValue()`.  Uses the storage location returned by
0473   /// `DataflowAnalysisContext::getStableStorageLocation(D)`.
0474   StorageLocation &createObject(const ValueDecl &D, const Expr *InitExpr) {
0475     return createObjectInternal(&D, D.getType(), InitExpr);
0476   }
0477 
0478   /// Initializes the fields (including synthetic fields) of `Loc` with values,
0479   /// unless values of the field type are not supported or we hit one of the
0480   /// limits at which we stop producing values.
0481   /// If a field already has a value, that value is preserved.
0482   /// If `Type` is provided, initializes only those fields that are modeled for
0483   /// `Type`; this is intended for use in cases where `Loc` is a derived type
0484   /// and we only want to initialize the fields of a base type.
0485   void initializeFieldsWithValues(RecordStorageLocation &Loc, QualType Type);
0486   void initializeFieldsWithValues(RecordStorageLocation &Loc) {
0487     initializeFieldsWithValues(Loc, Loc.getType());
0488   }
0489 
0490   /// Assigns `Val` as the value of `Loc` in the environment.
0491   ///
0492   /// Requirements:
0493   ///
0494   ///  `Loc` must not be a `RecordStorageLocation`.
0495   void setValue(const StorageLocation &Loc, Value &Val);
0496 
0497   /// Clears any association between `Loc` and a value in the environment.
0498   void clearValue(const StorageLocation &Loc) { LocToVal.erase(&Loc); }
0499 
0500   /// Assigns `Val` as the value of the prvalue `E` in the environment.
0501   ///
0502   /// Requirements:
0503   ///
0504   ///  - `E` must be a prvalue.
0505   ///  - `E` must not have record type.
0506   void setValue(const Expr &E, Value &Val);
0507 
0508   /// Returns the value assigned to `Loc` in the environment or null if `Loc`
0509   /// isn't assigned a value in the environment.
0510   ///
0511   /// Requirements:
0512   ///
0513   ///  `Loc` must not be a `RecordStorageLocation`.
0514   Value *getValue(const StorageLocation &Loc) const;
0515 
0516   /// Equivalent to `getValue(getStorageLocation(D))` if `D` is assigned a
0517   /// storage location in the environment, otherwise returns null.
0518   ///
0519   /// Requirements:
0520   ///
0521   ///  `D` must not have record type.
0522   Value *getValue(const ValueDecl &D) const;
0523 
0524   /// Equivalent to `getValue(getStorageLocation(E, SP))` if `E` is assigned a
0525   /// storage location in the environment, otherwise returns null.
0526   Value *getValue(const Expr &E) const;
0527 
0528   /// Returns the result of casting `getValue(...)` to a subclass of `Value`
0529   /// (using `cast_or_null<T>`).
0530   /// This assert-fails if the result of `getValue(...)` is not of type `T *`;
0531   /// if the value is not guaranteed to have type `T *`, consider using
0532   /// `dyn_cast_or_null<T>(getValue(...))` instead.
0533   template <typename T>
0534   std::enable_if_t<std::is_base_of_v<Value, T>, T *>
0535   get(const StorageLocation &Loc) const {
0536     return cast_or_null<T>(getValue(Loc));
0537   }
0538   template <typename T>
0539   std::enable_if_t<std::is_base_of_v<Value, T>, T *>
0540   get(const ValueDecl &D) const {
0541     return cast_or_null<T>(getValue(D));
0542   }
0543   template <typename T>
0544   std::enable_if_t<std::is_base_of_v<Value, T>, T *> get(const Expr &E) const {
0545     return cast_or_null<T>(getValue(E));
0546   }
0547 
0548   // FIXME: should we deprecate the following & call arena().create() directly?
0549 
0550   /// Creates a `T` (some subclass of `Value`), forwarding `args` to the
0551   /// constructor, and returns a reference to it.
0552   ///
0553   /// The analysis context takes ownership of the created object. The object
0554   /// will be destroyed when the analysis context is destroyed.
0555   template <typename T, typename... Args>
0556   std::enable_if_t<std::is_base_of<Value, T>::value, T &>
0557   create(Args &&...args) {
0558     return arena().create<T>(std::forward<Args>(args)...);
0559   }
0560 
0561   /// Returns a symbolic integer value that models an integer literal equal to
0562   /// `Value`
0563   IntegerValue &getIntLiteralValue(llvm::APInt Value) const {
0564     return arena().makeIntLiteral(Value);
0565   }
0566 
0567   /// Returns a symbolic boolean value that models a boolean literal equal to
0568   /// `Value`
0569   BoolValue &getBoolLiteralValue(bool Value) const {
0570     return arena().makeBoolValue(arena().makeLiteral(Value));
0571   }
0572 
0573   /// Returns an atomic boolean value.
0574   BoolValue &makeAtomicBoolValue() const {
0575     return arena().makeAtomValue();
0576   }
0577 
0578   /// Returns a unique instance of boolean Top.
0579   BoolValue &makeTopBoolValue() const {
0580     return arena().makeTopValue();
0581   }
0582 
0583   /// Returns a boolean value that represents the conjunction of `LHS` and
0584   /// `RHS`. Subsequent calls with the same arguments, regardless of their
0585   /// order, will return the same result. If the given boolean values represent
0586   /// the same value, the result will be the value itself.
0587   BoolValue &makeAnd(BoolValue &LHS, BoolValue &RHS) const {
0588     return arena().makeBoolValue(
0589         arena().makeAnd(LHS.formula(), RHS.formula()));
0590   }
0591 
0592   /// Returns a boolean value that represents the disjunction of `LHS` and
0593   /// `RHS`. Subsequent calls with the same arguments, regardless of their
0594   /// order, will return the same result. If the given boolean values represent
0595   /// the same value, the result will be the value itself.
0596   BoolValue &makeOr(BoolValue &LHS, BoolValue &RHS) const {
0597     return arena().makeBoolValue(
0598         arena().makeOr(LHS.formula(), RHS.formula()));
0599   }
0600 
0601   /// Returns a boolean value that represents the negation of `Val`. Subsequent
0602   /// calls with the same argument will return the same result.
0603   BoolValue &makeNot(BoolValue &Val) const {
0604     return arena().makeBoolValue(arena().makeNot(Val.formula()));
0605   }
0606 
0607   /// Returns a boolean value represents `LHS` => `RHS`. Subsequent calls with
0608   /// the same arguments, will return the same result. If the given boolean
0609   /// values represent the same value, the result will be a value that
0610   /// represents the true boolean literal.
0611   BoolValue &makeImplication(BoolValue &LHS, BoolValue &RHS) const {
0612     return arena().makeBoolValue(
0613         arena().makeImplies(LHS.formula(), RHS.formula()));
0614   }
0615 
0616   /// Returns a boolean value represents `LHS` <=> `RHS`. Subsequent calls with
0617   /// the same arguments, regardless of their order, will return the same
0618   /// result. If the given boolean values represent the same value, the result
0619   /// will be a value that represents the true boolean literal.
0620   BoolValue &makeIff(BoolValue &LHS, BoolValue &RHS) const {
0621     return arena().makeBoolValue(
0622         arena().makeEquals(LHS.formula(), RHS.formula()));
0623   }
0624 
0625   /// Returns a boolean variable that identifies the flow condition (FC).
0626   ///
0627   /// The flow condition is a set of facts that are necessarily true when the
0628   /// program reaches the current point, expressed as boolean formulas.
0629   /// The flow condition token is equivalent to the AND of these facts.
0630   ///
0631   /// These may e.g. constrain the value of certain variables. A pointer
0632   /// variable may have a consistent modeled PointerValue throughout, but at a
0633   /// given point the Environment may tell us that the value must be non-null.
0634   ///
0635   /// The FC is necessary but not sufficient for this point to be reachable.
0636   /// In particular, where the FC token appears in flow conditions of successor
0637   /// environments, it means "point X may have been reached", not
0638   /// "point X was reached".
0639   Atom getFlowConditionToken() const { return FlowConditionToken; }
0640 
0641   /// Record a fact that must be true if this point in the program is reached.
0642   void assume(const Formula &);
0643 
0644   /// Returns true if the formula is always true when this point is reached.
0645   /// Returns false if the formula may be false (or the flow condition isn't
0646   /// sufficiently precise to prove that it is true) or if the solver times out.
0647   ///
0648   /// Note that there is an asymmetry between this function and `allows()` in
0649   /// that they both return false if the solver times out. The assumption is
0650   /// that if `proves()` or `allows()` returns true, this will result in a
0651   /// diagnostic, and we want to bias towards false negatives in the case where
0652   /// the solver times out.
0653   bool proves(const Formula &) const;
0654 
0655   /// Returns true if the formula may be true when this point is reached.
0656   /// Returns false if the formula is always false when this point is reached
0657   /// (or the flow condition is overly constraining) or if the solver times out.
0658   bool allows(const Formula &) const;
0659 
0660   /// Returns the function currently being analyzed, or null if the code being
0661   /// analyzed isn't part of a function.
0662   const FunctionDecl *getCurrentFunc() const {
0663     return CallStack.empty() ? InitialTargetFunc : CallStack.back();
0664   }
0665 
0666   /// Returns the size of the call stack, not counting the initial analysis
0667   /// target.
0668   size_t callStackSize() const { return CallStack.size(); }
0669 
0670   /// Returns whether this `Environment` can be extended to analyze the given
0671   /// `Callee` (i.e. if `pushCall` can be used).
0672   /// Recursion is not allowed. `MaxDepth` is the maximum size of the call stack
0673   /// (i.e. the maximum value that `callStackSize()` may assume after the call).
0674   bool canDescend(unsigned MaxDepth, const FunctionDecl *Callee) const;
0675 
0676   /// Returns the `DataflowAnalysisContext` used by the environment.
0677   DataflowAnalysisContext &getDataflowAnalysisContext() const { return *DACtx; }
0678 
0679   Arena &arena() const { return DACtx->arena(); }
0680 
0681   LLVM_DUMP_METHOD void dump() const;
0682   LLVM_DUMP_METHOD void dump(raw_ostream &OS) const;
0683 
0684 private:
0685   using PrValueToResultObject =
0686       llvm::DenseMap<const Expr *, RecordStorageLocation *>;
0687 
0688   // The copy-constructor is for use in fork() only.
0689   Environment(const Environment &) = default;
0690 
0691   /// Creates a value appropriate for `Type`, if `Type` is supported, otherwise
0692   /// return null.
0693   ///
0694   /// Recursively initializes storage locations and values until it sees a
0695   /// self-referential pointer or reference type. `Visited` is used to track
0696   /// which types appeared in the reference/pointer chain in order to avoid
0697   /// creating a cyclic dependency with self-referential pointers/references.
0698   ///
0699   /// Requirements:
0700   ///
0701   ///  `Type` must not be null.
0702   Value *createValueUnlessSelfReferential(QualType Type,
0703                                           llvm::DenseSet<QualType> &Visited,
0704                                           int Depth, int &CreatedValuesCount);
0705 
0706   /// Creates a storage location for `Ty`. Also creates and associates a value
0707   /// with the storage location, unless values of this type are not supported or
0708   /// we hit one of the limits at which we stop producing values (controlled by
0709   /// `Visited`, `Depth`, and `CreatedValuesCount`).
0710   StorageLocation &createLocAndMaybeValue(QualType Ty,
0711                                           llvm::DenseSet<QualType> &Visited,
0712                                           int Depth, int &CreatedValuesCount);
0713 
0714   /// Initializes the fields (including synthetic fields) of `Loc` with values,
0715   /// unless values of the field type are not supported or we hit one of the
0716   /// limits at which we stop producing values (controlled by `Visited`,
0717   /// `Depth`, and `CreatedValuesCount`). If `Type` is different from
0718   /// `Loc.getType()`, initializes only those fields that are modeled for
0719   /// `Type`.
0720   void initializeFieldsWithValues(RecordStorageLocation &Loc, QualType Type,
0721                                   llvm::DenseSet<QualType> &Visited, int Depth,
0722                                   int &CreatedValuesCount);
0723 
0724   /// Shared implementation of `createObject()` overloads.
0725   /// `D` and `InitExpr` may be null.
0726   StorageLocation &createObjectInternal(const ValueDecl *D, QualType Ty,
0727                                         const Expr *InitExpr);
0728 
0729   /// Shared implementation of `pushCall` overloads. Note that unlike
0730   /// `pushCall`, this member is invoked on the environment of the callee, not
0731   /// of the caller.
0732   void pushCallInternal(const FunctionDecl *FuncDecl,
0733                         ArrayRef<const Expr *> Args);
0734 
0735   /// Assigns storage locations and values to all global variables, fields
0736   /// and functions in `Referenced`.
0737   void initFieldsGlobalsAndFuncs(const ReferencedDecls &Referenced);
0738 
0739   static PrValueToResultObject
0740   buildResultObjectMap(DataflowAnalysisContext *DACtx,
0741                        const FunctionDecl *FuncDecl,
0742                        RecordStorageLocation *ThisPointeeLoc,
0743                        RecordStorageLocation *LocForRecordReturnVal);
0744 
0745   static PrValueToResultObject
0746   buildResultObjectMap(DataflowAnalysisContext *DACtx, Stmt *S,
0747                        RecordStorageLocation *ThisPointeeLoc,
0748                        RecordStorageLocation *LocForRecordReturnVal);
0749 
0750   // `DACtx` is not null and not owned by this object.
0751   DataflowAnalysisContext *DACtx;
0752 
0753   // FIXME: move the fields `CallStack`, `ResultObjectMap`, `ReturnVal`,
0754   // `ReturnLoc` and `ThisPointeeLoc` into a separate call-context object,
0755   // shared between environments in the same call.
0756   // https://github.com/llvm/llvm-project/issues/59005
0757 
0758   // The stack of functions called from the initial analysis target.
0759   std::vector<const FunctionDecl *> CallStack;
0760 
0761   // Initial function to analyze, if a function was passed to the constructor.
0762   // Null otherwise.
0763   const FunctionDecl *InitialTargetFunc = nullptr;
0764   // Top-level statement of the initial analysis target.
0765   // If a function was passed to the constructor, this is its body.
0766   // If a statement was passed to the constructor, this is that statement.
0767   // Null if no analysis target was passed to the constructor.
0768   Stmt *InitialTargetStmt = nullptr;
0769 
0770   // Maps from prvalues of record type to their result objects. Shared between
0771   // all environments for the same analysis target.
0772   // FIXME: It's somewhat unsatisfactory that we have to use a `shared_ptr`
0773   // here, though the cost is acceptable: The overhead of a `shared_ptr` is
0774   // incurred when it is copied, and this happens only relatively rarely (when
0775   // we fork the environment). The need for a `shared_ptr` will go away once we
0776   // introduce a shared call-context object (see above).
0777   std::shared_ptr<PrValueToResultObject> ResultObjectMap;
0778 
0779   // The following three member variables handle various different types of
0780   // return values when the current analysis target is a function.
0781   // - If the return type is not a reference and not a record: Value returned
0782   //   by the function.
0783   Value *ReturnVal = nullptr;
0784   // - If the return type is a reference: Storage location of the reference
0785   //   returned by the function.
0786   StorageLocation *ReturnLoc = nullptr;
0787   // - If the return type is a record or the function being analyzed is a
0788   //   constructor: Storage location into which the return value should be
0789   //   constructed.
0790   RecordStorageLocation *LocForRecordReturnVal = nullptr;
0791 
0792   // The storage location of the `this` pointee. Should only be null if the
0793   // analysis target is not a method.
0794   RecordStorageLocation *ThisPointeeLoc = nullptr;
0795 
0796   // Maps from declarations and glvalue expression to storage locations that are
0797   // assigned to them. Unlike the maps in `DataflowAnalysisContext`, these
0798   // include only storage locations that are in scope for a particular basic
0799   // block.
0800   llvm::DenseMap<const ValueDecl *, StorageLocation *> DeclToLoc;
0801   llvm::DenseMap<const Expr *, StorageLocation *> ExprToLoc;
0802   // Maps from prvalue expressions and storage locations to the values that
0803   // are assigned to them.
0804   // We preserve insertion order so that join/widen process values in
0805   // deterministic sequence. This in turn produces deterministic SAT formulas.
0806   llvm::MapVector<const Expr *, Value *> ExprToVal;
0807   llvm::MapVector<const StorageLocation *, Value *> LocToVal;
0808 
0809   Atom FlowConditionToken;
0810 };
0811 
0812 /// Returns the storage location for the implicit object of a
0813 /// `CXXMemberCallExpr`, or null if none is defined in the environment.
0814 /// Dereferences the pointer if the member call expression was written using
0815 /// `->`.
0816 RecordStorageLocation *getImplicitObjectLocation(const CXXMemberCallExpr &MCE,
0817                                                  const Environment &Env);
0818 
0819 /// Returns the storage location for the base object of a `MemberExpr`, or null
0820 /// if none is defined in the environment. Dereferences the pointer if the
0821 /// member expression was written using `->`.
0822 RecordStorageLocation *getBaseObjectLocation(const MemberExpr &ME,
0823                                              const Environment &Env);
0824 
0825 } // namespace dataflow
0826 } // namespace clang
0827 
0828 #endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWENVIRONMENT_H