aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
diff options
context:
space:
mode:
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.h80
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