[clang] 92bf652 - [Static Analyzer] Small array binding policy
via cfe-commits
cfe-commits at lists.llvm.org
Fri Jun 17 09:56:22 PDT 2022
Author: isuckatcs
Date: 2022-06-17T18:56:13+02:00
New Revision: 92bf652d40740b947de6c41fe09f282ec0530dc5
URL: https://github.com/llvm/llvm-project/commit/92bf652d40740b947de6c41fe09f282ec0530dc5
DIFF: https://github.com/llvm/llvm-project/commit/92bf652d40740b947de6c41fe09f282ec0530dc5.diff
LOG: [Static Analyzer] Small array binding policy
If a lazyCompoundVal to a struct is bound to the store, there is a policy which decides
whether a copy gets created instead.
This patch introduces a similar policy for arrays, which is required to model structured
binding to arrays without false negatives.
Differential Revision: https://reviews.llvm.org/D128064
Added:
Modified:
clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
clang/lib/StaticAnalyzer/Core/RegionStore.cpp
clang/test/Analysis/analyzer-config.c
Removed:
################################################################################
diff --git a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
index d7075fb39fc89..9974ea9392acb 100644
--- a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
+++ b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
@@ -440,11 +440,19 @@ ANALYZER_OPTION(
ANALYZER_OPTION(
unsigned, RegionStoreSmallStructLimit, "region-store-small-struct-limit",
"The largest number of fields a struct can have and still be considered "
- "small This is currently used to decide whether or not it is worth forcing "
+ "small. This is currently used to decide whether or not it is worth forcing "
"a LazyCompoundVal on bind. To disable all small-struct-dependent "
"behavior, set the option to 0.",
2)
+ANALYZER_OPTION(
+ unsigned, RegionStoreSmallArrayLimit, "region-store-small-array-limit",
+ "The largest number of elements an array can have and still be considered "
+ "small. This is currently used to decide whether or not it is worth forcing "
+ "a LazyCompoundVal on bind. To disable all small-array-dependent "
+ "behavior, set the option to 0.",
+ 5)
+
//===----------------------------------------------------------------------===//
// String analyzer options.
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
index 8a50cb27c8d3a..b432247bad7d8 100644
--- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -345,6 +345,16 @@ class RegionStoreManager : public StoreManager {
/// To disable all small-struct-dependent behavior, set the option to "0".
unsigned SmallStructLimit;
+ /// The largest number of element an array can have and still be
+ /// considered "small".
+ ///
+ /// This is currently used to decide whether or not it is worth "forcing" a
+ /// LazyCompoundVal on bind.
+ ///
+ /// This is controlled by 'region-store-small-struct-limit' option.
+ /// To disable all small-struct-dependent behavior, set the option to "0".
+ unsigned SmallArrayLimit;
+
/// A helper used to populate the work list with the given set of
/// regions.
void populateWorkList(InvalidateRegionsWorker &W,
@@ -354,10 +364,11 @@ class RegionStoreManager : public StoreManager {
public:
RegionStoreManager(ProgramStateManager &mgr)
: StoreManager(mgr), RBFactory(mgr.getAllocator()),
- CBFactory(mgr.getAllocator()), SmallStructLimit(0) {
+ CBFactory(mgr.getAllocator()), SmallStructLimit(0), SmallArrayLimit(0) {
ExprEngine &Eng = StateMgr.getOwningEngine();
AnalyzerOptions &Options = Eng.getAnalysisManager().options;
SmallStructLimit = Options.RegionStoreSmallStructLimit;
+ SmallArrayLimit = Options.RegionStoreSmallArrayLimit;
}
/// setImplicitDefaultValue - Set the default binding for the provided
@@ -487,6 +498,11 @@ class RegionStoreManager : public StoreManager {
RegionBindingsRef bindVector(RegionBindingsConstRef B,
const TypedValueRegion* R, SVal V);
+ Optional<RegionBindingsRef> tryBindSmallArray(RegionBindingsConstRef B,
+ const TypedValueRegion *R,
+ const ArrayType *AT,
+ nonloc::LazyCompoundVal LCV);
+
RegionBindingsRef bindArray(RegionBindingsConstRef B,
const TypedValueRegion* R,
SVal V);
@@ -2392,6 +2408,40 @@ RegionStoreManager::setImplicitDefaultValue(RegionBindingsConstRef B,
return B.addBinding(R, BindingKey::Default, V);
}
+Optional<RegionBindingsRef> RegionStoreManager::tryBindSmallArray(
+ RegionBindingsConstRef B, const TypedValueRegion *R, const ArrayType *AT,
+ nonloc::LazyCompoundVal LCV) {
+
+ auto CAT = dyn_cast<ConstantArrayType>(AT);
+
+ // If we don't know the size, create a lazyCompoundVal instead.
+ if (!CAT)
+ return None;
+
+ QualType Ty = CAT->getElementType();
+ if (!(Ty->isScalarType() || Ty->isReferenceType()))
+ return None;
+
+ // If the array is too big, create a LCV instead.
+ uint64_t ArrSize = CAT->getSize().getLimitedValue();
+ if (ArrSize > SmallArrayLimit)
+ return None;
+
+ RegionBindingsRef NewB = B;
+
+ for (uint64_t i = 0; i < ArrSize; ++i) {
+ auto Idx = svalBuilder.makeArrayIndex(i);
+ const ElementRegion *SrcER =
+ MRMgr.getElementRegion(Ty, Idx, LCV.getRegion(), Ctx);
+ SVal V = getBindingForElement(getRegionBindings(LCV.getStore()), SrcER);
+
+ const ElementRegion *DstER = MRMgr.getElementRegion(Ty, Idx, R, Ctx);
+ NewB = bind(NewB, loc::MemRegionVal(DstER), V);
+ }
+
+ return NewB;
+}
+
RegionBindingsRef
RegionStoreManager::bindArray(RegionBindingsConstRef B,
const TypedValueRegion* R,
@@ -2413,8 +2463,13 @@ RegionStoreManager::bindArray(RegionBindingsConstRef B,
}
// Handle lazy compound values.
- if (isa<nonloc::LazyCompoundVal>(Init))
+ if (Optional<nonloc::LazyCompoundVal> LCV =
+ Init.getAs<nonloc::LazyCompoundVal>()) {
+ if (Optional<RegionBindingsRef> NewB = tryBindSmallArray(B, R, AT, *LCV))
+ return *NewB;
+
return bindAggregate(B, R, Init);
+ }
if (Init.isUnknown())
return bindAggregate(B, R, UnknownVal());
diff --git a/clang/test/Analysis/analyzer-config.c b/clang/test/Analysis/analyzer-config.c
index 440547b62345a..9f22be6742c1f 100644
--- a/clang/test/Analysis/analyzer-config.c
+++ b/clang/test/Analysis/analyzer-config.c
@@ -114,6 +114,7 @@
// CHECK-NEXT: osx.NumberObjectConversion:Pedantic = false
// CHECK-NEXT: osx.cocoa.RetainCount:TrackNSCFStartParam = false
// CHECK-NEXT: prune-paths = true
+// CHECK-NEXT: region-store-small-array-limit = 5
// CHECK-NEXT: region-store-small-struct-limit = 2
// CHECK-NEXT: report-in-main-source-file = false
// CHECK-NEXT: serialize-stats = false
More information about the cfe-commits
mailing list