diff --git a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp index 04e21fc09e61..e08a64156894 100644 --- a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp +++ b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp @@ -690,18 +690,24 @@ const BlockDataRegion * 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(BC, LC, sReg); diff --git a/clang/test/Analysis/stack-addr-ps.c b/clang/test/Analysis/stack-addr-ps.c index 558986d308d4..a443a32396f5 100644 --- a/clang/test/Analysis/stack-addr-ps.c +++ b/clang/test/Analysis/stack-addr-ps.c @@ -57,8 +57,15 @@ int struct_test(struct baz byVal, int flag) { 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 @@ int *rdar_7523821_f2() { 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'. +// +typedef int (^RDar10348049)(int value); +RDar10348049 test_rdar10348049(void) { + static RDar10348049 b = ^int(int x) { + return x + 2; + }; + return b; // no-warning +}