Teach analyzer that blocks with no captures are globals. Fixes <rdar://problem/10348049>.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150896 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/StaticAnalyzer/Core/MemRegion.cpp b/lib/StaticAnalyzer/Core/MemRegion.cpp
index 04e21fc..e08a641 100644
--- a/lib/StaticAnalyzer/Core/MemRegion.cpp
+++ b/lib/StaticAnalyzer/Core/MemRegion.cpp
@@ -690,18 +690,24 @@
MemRegionManager::getBlockDataRegion(const BlockTextRegion *BC,
const LocationContext *LC) {
const MemRegion *sReg = 0;
-
- if (LC) {
- // FIXME: Once we implement scope handling, we want the parent region
- // to be the scope.
- const StackFrameContext *STC = LC->getCurrentStackFrame();
- assert(STC);
- sReg = getStackLocalsRegion(STC);
+ const BlockDecl *BD = BC->getDecl();
+ if (!BD->hasCaptures()) {
+ // This handles 'static' blocks.
+ sReg = getGlobalsRegion(MemRegion::GlobalImmutableSpaceRegionKind);
}
else {
- // We allow 'LC' to be NULL for cases where want BlockDataRegions
- // without context-sensitivity.
- sReg = getUnknownRegion();
+ if (LC) {
+ // FIXME: Once we implement scope handling, we want the parent region
+ // to be the scope.
+ const StackFrameContext *STC = LC->getCurrentStackFrame();
+ assert(STC);
+ sReg = getStackLocalsRegion(STC);
+ }
+ else {
+ // We allow 'LC' to be NULL for cases where want BlockDataRegions
+ // without context-sensitivity.
+ sReg = getUnknownRegion();
+ }
}
return getSubRegion<BlockDataRegion>(BC, LC, sReg);
diff --git a/test/Analysis/stack-addr-ps.c b/test/Analysis/stack-addr-ps.c
index 558986d..a443a32 100644
--- a/test/Analysis/stack-addr-ps.c
+++ b/test/Analysis/stack-addr-ps.c
@@ -57,8 +57,15 @@
typedef int (^ComparatorBlock)(int a, int b);
ComparatorBlock test_return_block(void) {
+ // This block is a global since it has no captures.
ComparatorBlock b = ^int(int a, int b){ return a > b; };
- return b; // expected-warning{{Address of stack-allocated block declared on line 60 returned to caller}}
+ return b; // no-warning
+}
+
+ComparatorBlock test_return_block_with_capture(int x) {
+ // This block is stack allocated because it has captures.
+ ComparatorBlock b = ^int(int a, int b){ return a > b + x; };
+ return b; // expected-warning{{Address of stack-allocated block}}
}
ComparatorBlock test_return_block_neg_aux(void);
@@ -73,4 +80,13 @@
return a; // expected-warning 2 {{ddress of stack memory associated with local variable 'a' returned}}
};
+// Handle blocks that have no captures or are otherwise declared 'static'.
+// <rdar://problem/10348049>
+typedef int (^RDar10348049)(int value);
+RDar10348049 test_rdar10348049(void) {
+ static RDar10348049 b = ^int(int x) {
+ return x + 2;
+ };
+ return b; // no-warning
+}