diff options
Diffstat (limited to 'contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h')
-rw-r--r-- | contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h | 80 |
1 files changed, 44 insertions, 36 deletions
diff --git a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h index d7e39ab2616f..e8c27d6c1203 100644 --- a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h +++ b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h @@ -289,6 +289,22 @@ public: /// `E` must be a glvalue or a `BuiltinType::BuiltinFn` StorageLocation *getStorageLocation(const Expr &E) const; + /// Returns the result of casting `getStorageLocation(...)` to a subclass of + /// `StorageLocation` (using `cast_or_null<T>`). + /// This assert-fails if the result of `getStorageLocation(...)` is not of + /// type `T *`; if the storage location is not guaranteed to have type `T *`, + /// consider using `dyn_cast_or_null<T>(getStorageLocation(...))` instead. + template <typename T> + std::enable_if_t<std::is_base_of_v<StorageLocation, T>, T *> + get(const ValueDecl &D) const { + return cast_or_null<T>(getStorageLocation(D)); + } + template <typename T> + std::enable_if_t<std::is_base_of_v<StorageLocation, T>, T *> + get(const Expr &E) const { + return cast_or_null<T>(getStorageLocation(E)); + } + /// Returns the storage location assigned to the `this` pointee in the /// environment or null if the `this` pointee has no assigned storage location /// in the environment. @@ -325,7 +341,8 @@ public: /// /// Requirements: /// `E` must be a prvalue of record type. - RecordStorageLocation &getResultObjectLocation(const Expr &RecordPRValue); + RecordStorageLocation & + getResultObjectLocation(const Expr &RecordPRValue) const; /// Returns the return value of the current function. This can be null if: /// - The function has a void return type @@ -434,24 +451,14 @@ public: /// Assigns `Val` as the value of the prvalue `E` in the environment. /// - /// If `E` is not yet associated with a storage location, associates it with - /// a newly created storage location. In any case, associates the storage - /// location of `E` with `Val`. - /// - /// Once the migration to strict handling of value categories is complete - /// (see https://discourse.llvm.org/t/70086), this function will be renamed to - /// `setValue()`. At this point, prvalue expressions will be associated - /// directly with `Value`s, and the legacy behavior of associating prvalue - /// expressions with storage locations (as described above) will be - /// eliminated. - /// /// Requirements: /// - /// `E` must be a prvalue - /// If `Val` is a `RecordValue`, its `RecordStorageLocation` must be the - /// same as that of any `RecordValue` that has already been associated with - /// `E`. This is to guarantee that the result object initialized by a prvalue - /// `RecordValue` has a durable storage location. + /// - `E` must be a prvalue + /// - If `Val` is a `RecordValue`, its `RecordStorageLocation` must be + /// `getResultObjectLocation(E)`. An exception to this is if `E` is an + /// expression that originally creates a `RecordValue` (such as a + /// `CXXConstructExpr` or `CallExpr`), as these establish the location of + /// the result object in the first place. void setValue(const Expr &E, Value &Val); /// Returns the value assigned to `Loc` in the environment or null if `Loc` @@ -466,6 +473,26 @@ public: /// storage location in the environment, otherwise returns null. Value *getValue(const Expr &E) const; + /// Returns the result of casting `getValue(...)` to a subclass of `Value` + /// (using `cast_or_null<T>`). + /// This assert-fails if the result of `getValue(...)` is not of type `T *`; + /// if the value is not guaranteed to have type `T *`, consider using + /// `dyn_cast_or_null<T>(getValue(...))` instead. + template <typename T> + std::enable_if_t<std::is_base_of_v<Value, T>, T *> + get(const StorageLocation &Loc) const { + return cast_or_null<T>(getValue(Loc)); + } + template <typename T> + std::enable_if_t<std::is_base_of_v<Value, T>, T *> + get(const ValueDecl &D) const { + return cast_or_null<T>(getValue(D)); + } + template <typename T> + std::enable_if_t<std::is_base_of_v<Value, T>, T *> get(const Expr &E) const { + return cast_or_null<T>(getValue(E)); + } + // FIXME: should we deprecate the following & call arena().create() directly? /// Creates a `T` (some subclass of `Value`), forwarding `args` to the @@ -608,14 +635,6 @@ private: // The copy-constructor is for use in fork() only. Environment(const Environment &) = default; - /// Internal version of `setStorageLocation()` that doesn't check if the - /// expression is a prvalue. - void setStorageLocationInternal(const Expr &E, StorageLocation &Loc); - - /// Internal version of `getStorageLocation()` that doesn't check if the - /// expression is a prvalue. - StorageLocation *getStorageLocationInternal(const Expr &E) const; - /// Creates a value appropriate for `Type`, if `Type` is supported, otherwise /// return null. /// @@ -708,20 +727,9 @@ RecordStorageLocation *getBaseObjectLocation(const MemberExpr &ME, std::vector<FieldDecl *> getFieldsForInitListExpr(const RecordDecl *RD); /// Associates a new `RecordValue` with `Loc` and returns the new value. -/// It is not defined whether the field values remain the same or not. -/// -/// This function is primarily intended for use by checks that set custom -/// properties on `RecordValue`s to model the state of these values. Such checks -/// should avoid modifying the properties of an existing `RecordValue` because -/// these changes would be visible to other `Environment`s that share the same -/// `RecordValue`. Instead, call `refreshRecordValue()`, then set the properties -/// on the new `RecordValue` that it returns. Typical usage: -/// -/// refreshRecordValue(Loc, Env).setProperty("my_prop", MyPropValue); RecordValue &refreshRecordValue(RecordStorageLocation &Loc, Environment &Env); /// Associates a new `RecordValue` with `Expr` and returns the new value. -/// See also documentation for the overload above. RecordValue &refreshRecordValue(const Expr &Expr, Environment &Env); } // namespace dataflow |