mboehme created this revision. Herald added subscribers: martong, xazax.hun. Herald added a reviewer: NoQ. Herald added a project: All. mboehme requested review of this revision. Herald added subscribers: cfe-commits, wangpc. Herald added a project: clang.
Besides being a useful abstraction, this function will help insulate existing clients of the framework from upcoming changes to the API of `StructValue` and `AggregateStorageLocation`. Depends On D155202 <https://reviews.llvm.org/D155202> Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D155204 Files: clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp
Index: clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp =================================================================== --- clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp +++ clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp @@ -370,13 +370,6 @@ // FIXME: Called functions at point `p` should contain only "foo". } -StructValue &createNewStructValue(AggregateStorageLocation &Loc, - Environment &Env) { - auto &Val = *cast<StructValue>(Env.createValue(Loc.getType())); - Env.setValue(Loc, Val); - return Val; -} - // Models an analysis that uses flow conditions. class SpecialBoolAnalysis final : public DataflowAnalysis<SpecialBoolAnalysis, NoopLattice> { @@ -407,7 +400,7 @@ auto &ObjectLoc = *cast<AggregateStorageLocation>(getImplicitObjectLocation(*E, Env)); - createNewStructValue(ObjectLoc, Env) + refreshStructValue(ObjectLoc, Env) .setProperty("is_set", Env.getBoolLiteralValue(true)); } } @@ -561,10 +554,7 @@ auto *Object = E->getArg(0); assert(Object != nullptr); - auto &ObjectLoc = *cast<AggregateStorageLocation>( - Env.getStorageLocation(*Object, SkipPast::Reference)); - - createNewStructValue(ObjectLoc, Env) + refreshStructValue(*Object, Env) .setProperty("has_value", Env.getBoolLiteralValue(true)); } } Index: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp =================================================================== --- clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -993,5 +993,30 @@ return Fields; } +StructValue &refreshStructValue(AggregateStorageLocation &Loc, + Environment &Env) { + auto &NewVal = *cast<StructValue>(Env.createValue(Loc.getType())); + Env.setValue(Loc, NewVal); + return NewVal; +} + +StructValue &refreshStructValue(const Expr &Expr, Environment &Env) { + assert(Expr.getType()->isRecordType()); + + auto &NewVal = *cast<StructValue>(Env.createValue(Expr.getType())); + + if (Expr.isPRValue()) { + Env.setValueStrict(Expr, NewVal); + } else { + StorageLocation *Loc = Env.getStorageLocationStrict(Expr); + if (Loc == nullptr) { + Loc = &Env.createStorageLocation(Expr); + } + Env.setValue(*Loc, NewVal); + } + + return NewVal; +} + } // namespace dataflow } // namespace clang Index: clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h =================================================================== --- clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h +++ clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h @@ -389,6 +389,12 @@ /// necessary storage locations and values for indirections until it finds a /// non-pointer/non-reference type. /// + /// If `Type` is one of the following types, this function will always return + /// a non-null pointer: + /// - `bool` + /// - Any integer type + /// - Any class, struct, or union type + /// /// Requirements: /// /// `Type` must not be null. @@ -694,6 +700,24 @@ /// order in which they appear in `InitListExpr::inits()`. std::vector<FieldDecl *> getFieldsForInitListExpr(const RecordDecl *RD); +/// Associates a new `StructValue` 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 `StructValue`s to model the state of these values. Such checks +/// should avoid modifying the properties of an existing `StructValue` because +/// these changes would be visible to other `Environment`s that share the same +/// `StructValue`. Instead, call `refreshStructValue()`, then set the properties +/// on the new `StructValue` that it returns. Typical usage: +/// +/// refreshStructValue(Loc, Env).setProperty("my_prop", MyPropValue); +StructValue &refreshStructValue(AggregateStorageLocation &Loc, + Environment &Env); + +/// Associates a new `StructValue` with `Expr` and returns the new value. +/// See also documentation for the overload above. +StructValue &refreshStructValue(const Expr &Expr, Environment &Env); + } // namespace dataflow } // namespace clang
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits