Skip to content

Commit

Permalink
[clang][dataflow] Add refreshStructValue().
Browse files Browse the repository at this point in the history
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

Reviewed By: ymandel, xazax.hun

Differential Revision: https://reviews.llvm.org/D155204
  • Loading branch information
martinboehme committed Jul 17, 2023
1 parent 243a79c commit d17f455
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 12 deletions.
24 changes: 24 additions & 0 deletions clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,12 @@ class Environment {
/// 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.
Expand Down Expand Up @@ -692,6 +698,24 @@ AggregateStorageLocation *getBaseObjectLocation(const MemberExpr &ME,
/// 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

Expand Down
25 changes: 25 additions & 0 deletions clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -987,5 +987,30 @@ std::vector<FieldDecl *> getFieldsForInitListExpr(const RecordDecl *RD) {
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
Original file line number Diff line number Diff line change
Expand Up @@ -370,13 +370,6 @@ TEST_F(NoreturnDestructorTest, ConditionalOperatorNestedBranchReturns) {
// 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> {
Expand Down Expand Up @@ -407,7 +400,7 @@ class SpecialBoolAnalysis final
auto &ObjectLoc =
*cast<AggregateStorageLocation>(getImplicitObjectLocation(*E, Env));

createNewStructValue(ObjectLoc, Env)
refreshStructValue(ObjectLoc, Env)
.setProperty("is_set", Env.getBoolLiteralValue(true));
}
}
Expand Down Expand Up @@ -562,10 +555,7 @@ class OptionalIntAnalysis final
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));
}
}
Expand Down

0 comments on commit d17f455

Please sign in to comment.