aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
diff options
context:
space:
mode:
authorYitzhak Mandelbaum <yitzhakm@google.com>2022-12-27 14:21:29 +0000
committerYitzhak Mandelbaum <yitzhakm@google.com>2023-01-05 21:46:39 +0000
commit5e8f597c2fedc740b71f07dfdb1ef3c2d348b193 (patch)
tree8ef2f0a7db76686b8faad09f0dc7a051b99440ff /clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
parent69f2b5fcf1be2226181cce21066f072279ba5d14 (diff)
downloadllvm-5e8f597c2fedc740b71f07dfdb1ef3c2d348b193.zip
llvm-5e8f597c2fedc740b71f07dfdb1ef3c2d348b193.tar.gz
llvm-5e8f597c2fedc740b71f07dfdb1ef3c2d348b193.tar.bz2
[clang][dataflow] Only model struct fields that are used in the function being analyzed.
Previously, the model for structs modeled all fields in a struct when `createValue` was called for that type. This patch adds a prepass on the function under analysis to discover the fields referenced in the scope and then limits modeling to only those fields. This reduces wasted memory usage (modeling unused fields) which can be important for programss that use large structs. Note: This patch obviates the need for https://reviews.llvm.org/D123032. Differential Revision: https://reviews.llvm.org/D140694
Diffstat (limited to 'clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp')
-rw-r--r--clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp27
1 files changed, 24 insertions, 3 deletions
diff --git a/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp b/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
index af2f1fcb..6b7b2dc 100644
--- a/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
+++ b/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
@@ -16,6 +16,7 @@
#include "clang/AST/ExprCXX.h"
#include "clang/Analysis/FlowSensitive/DebugSupport.h"
#include "clang/Analysis/FlowSensitive/Value.h"
+#include "llvm/ADT/SetOperations.h"
#include "llvm/Support/Debug.h"
#include <cassert>
#include <memory>
@@ -24,13 +25,33 @@
namespace clang {
namespace dataflow {
+void DataflowAnalysisContext::addFieldsReferencedInScope(
+ llvm::DenseSet<const FieldDecl *> Fields) {
+ llvm::set_union(FieldsReferencedInScope, Fields);
+}
+
+llvm::DenseSet<const FieldDecl *>
+DataflowAnalysisContext::getReferencedFields(QualType Type) {
+ llvm::DenseSet<const FieldDecl *> Fields = getObjectFields(Type);
+ llvm::set_intersect(Fields, FieldsReferencedInScope);
+ return Fields;
+}
+
StorageLocation &DataflowAnalysisContext::createStorageLocation(QualType Type) {
if (!Type.isNull() &&
(Type->isStructureOrClassType() || Type->isUnionType())) {
- // FIXME: Explore options to avoid eager initialization of fields as some of
- // them might not be needed for a particular analysis.
llvm::DenseMap<const ValueDecl *, StorageLocation *> FieldLocs;
- for (const FieldDecl *Field : getObjectFields(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 fields access it not allowed to fail. In contrast, field *values*
+ // don't need this allowance, since the API allows for uninitialized fields.
+ auto Fields = Options.EnableContextSensitiveAnalysis
+ ? getObjectFields(Type)
+ : getReferencedFields(Type);
+ for (const FieldDecl *Field : Fields)
FieldLocs.insert({Field, &createStorageLocation(Field->getType())});
return takeOwnership(
std::make_unique<AggregateStorageLocation>(Type, std::move(FieldLocs)));