This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGe8a1560d1de9: [clang][dataflow] Various changes to handling
of modeled fields. (authored by mboehme).
Changed prior to commit:
https://reviews.llvm.org/D154586?vs=537636&id=538515#toc
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D154586/new/
https://reviews.llvm.org/D154586
Files:
clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
Index: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
===================================================================
--- clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -170,8 +170,7 @@
}
static void
-getFieldsGlobalsAndFuncs(const Decl &D,
- llvm::DenseSet<const FieldDecl *> &Fields,
+getFieldsGlobalsAndFuncs(const Decl &D, FieldSet &Fields,
llvm::DenseSet<const VarDecl *> &Vars,
llvm::DenseSet<const FunctionDecl *> &Funcs) {
insertIfGlobal(D, Vars);
@@ -188,8 +187,7 @@
/// global variables and functions that are declared in or referenced from
/// sub-statements.
static void
-getFieldsGlobalsAndFuncs(const Stmt &S,
- llvm::DenseSet<const FieldDecl *> &Fields,
+getFieldsGlobalsAndFuncs(const Stmt &S, FieldSet &Fields,
llvm::DenseSet<const VarDecl *> &Vars,
llvm::DenseSet<const FunctionDecl *> &Funcs) {
for (auto *Child : S.children())
@@ -222,7 +220,7 @@
void Environment::initFieldsGlobalsAndFuncs(const FunctionDecl *FuncDecl) {
assert(FuncDecl->getBody() != nullptr);
- llvm::DenseSet<const FieldDecl *> Fields;
+ FieldSet Fields;
llvm::DenseSet<const VarDecl *> Vars;
llvm::DenseSet<const FunctionDecl *> Funcs;
@@ -708,7 +706,7 @@
const QualType Type = AggregateLoc.getType();
assert(Type->isRecordType());
- for (const FieldDecl *Field : DACtx->getReferencedFields(Type)) {
+ for (const FieldDecl *Field : DACtx->getModeledFields(Type)) {
assert(Field != nullptr);
StorageLocation &FieldLoc = AggregateLoc.getChild(*Field);
MemberLocToStruct[&FieldLoc] = std::make_pair(StructVal, Field);
@@ -846,7 +844,7 @@
if (Type->isRecordType()) {
CreatedValuesCount++;
llvm::DenseMap<const ValueDecl *, Value *> FieldValues;
- for (const FieldDecl *Field : DACtx->getReferencedFields(Type)) {
+ for (const FieldDecl *Field : DACtx->getModeledFields(Type)) {
assert(Field != nullptr);
QualType FieldType = Field->getType();
Index: clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
===================================================================
--- clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
+++ clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
@@ -40,31 +40,28 @@
namespace clang {
namespace dataflow {
-void DataflowAnalysisContext::addModeledFields(
- const llvm::DenseSet<const FieldDecl *> &Fields) {
- llvm::set_union(ModeledFields, Fields);
+FieldSet DataflowAnalysisContext::getModeledFields(QualType Type) {
+ // During context-sensitive analysis, a struct may be allocated in one
+ // function, but its field accessed in a function lower in the stack than
+ // the allocation. Since we only collect fields used in the function where
+ // the allocation occurs, we can't apply that filter when performing
+ // context-sensitive analysis. But, this only applies to storage locations,
+ // since field access it not allowed to fail. In contrast, field *values*
+ // don't need this allowance, since the API allows for uninitialized fields.
+ if (Opts.ContextSensitiveOpts)
+ return getObjectFields(Type);
+
+ return llvm::set_intersection(getObjectFields(Type), ModeledFields);
}
-llvm::DenseSet<const FieldDecl *>
-DataflowAnalysisContext::getReferencedFields(QualType Type) {
- llvm::DenseSet<const FieldDecl *> Fields = getObjectFields(Type);
- llvm::set_intersect(Fields, ModeledFields);
- return Fields;
+void DataflowAnalysisContext::addModeledFields(const FieldSet &Fields) {
+ ModeledFields.set_union(Fields);
}
StorageLocation &DataflowAnalysisContext::createStorageLocation(QualType Type) {
if (!Type.isNull() && Type->isRecordType()) {
llvm::DenseMap<const ValueDecl *, StorageLocation *> FieldLocs;
- // During context-sensitive analysis, a struct may be allocated in one
- // function, but its field accessed in a function lower in the stack than
- // the allocation. Since we only collect fields used in the function where
- // the allocation occurs, we can't apply that filter when performing
- // context-sensitive analysis. But, this only applies to storage locations,
- // since field access it not allowed to fail. In contrast, field *values*
- // don't need this allowance, since the API allows for uninitialized fields.
- auto Fields = Opts.ContextSensitiveOpts ? getObjectFields(Type)
- : getReferencedFields(Type);
- for (const FieldDecl *Field : Fields)
+ for (const FieldDecl *Field : getModeledFields(Type))
FieldLocs.insert({Field, &createStorageLocation(Field->getType())});
return arena().create<AggregateStorageLocation>(Type, std::move(FieldLocs));
}
@@ -305,9 +302,8 @@
// FIXME: Does not precisely handle non-virtual diamond inheritance. A single
// field decl will be modeled for all instances of the inherited field.
-static void
-getFieldsFromClassHierarchy(QualType Type,
- llvm::DenseSet<const FieldDecl *> &Fields) {
+static void getFieldsFromClassHierarchy(QualType Type,
+ clang::dataflow::FieldSet &Fields) {
if (Type->isIncompleteType() || Type->isDependentType() ||
!Type->isRecordType())
return;
@@ -320,9 +316,8 @@
}
/// Gets the set of all fields in the type.
-llvm::DenseSet<const FieldDecl *>
-clang::dataflow::getObjectFields(QualType Type) {
- llvm::DenseSet<const FieldDecl *> Fields;
+clang::dataflow::FieldSet clang::dataflow::getObjectFields(QualType Type) {
+ FieldSet Fields;
getFieldsFromClassHierarchy(Type, Fields);
return Fields;
}
Index: clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
===================================================================
--- clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
+++ clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
@@ -51,8 +51,12 @@
const Expr &ignoreCFGOmittedNodes(const Expr &E);
const Stmt &ignoreCFGOmittedNodes(const Stmt &S);
+/// A set of `FieldDecl *`. Use `SmallSetVector` to guarantee deterministic
+/// iteration order.
+using FieldSet = llvm::SmallSetVector<const FieldDecl *, 4>;
+
/// Returns the set of all fields in the type.
-llvm::DenseSet<const FieldDecl *> getObjectFields(QualType Type);
+FieldSet getObjectFields(QualType Type);
struct ContextSensitiveOptions {
/// The maximum depth to analyze. A value of zero is equivalent to disabling
@@ -181,6 +185,10 @@
/// been stored in flow conditions.
Solver::Result querySolver(llvm::SetVector<const Formula *> Constraints);
+ /// Returns the fields of `Type`, limited to the set of fields modeled by this
+ /// context.
+ FieldSet getModeledFields(QualType Type);
+
private:
friend class Environment;
@@ -196,11 +204,7 @@
};
// Extends the set of modeled field declarations.
- void addModeledFields(const llvm::DenseSet<const FieldDecl *> &Fields);
-
- /// Returns the fields of `Type`, limited to the set of fields modeled by this
- /// context.
- llvm::DenseSet<const FieldDecl *> getReferencedFields(QualType Type);
+ void addModeledFields(const FieldSet &Fields);
/// Adds all constraints of the flow condition identified by `Token` and all
/// of its transitive dependencies to `Constraints`. `VisitedTokens` is used
@@ -257,7 +261,7 @@
llvm::DenseMap<const FunctionDecl *, ControlFlowContext> FunctionContexts;
// Fields modeled by environments covered by this context.
- llvm::DenseSet<const FieldDecl *> ModeledFields;
+ FieldSet ModeledFields;
std::unique_ptr<Logger> LogOwner; // If created via flags.
};
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits