Skip to content

Commit

Permalink
[analyzer] Fix zero-initialization of stack VLAs under ObjC ARC.
Browse files Browse the repository at this point in the history
Using ARC, strong, weak, and autoreleasing stack variables are implicitly
initialized with nil. This includes variable-length arrays of Objective-C object
pointers. However, in the analyzer we don't zero-initialize them. We used to,
but it accidentally regressed after r289618.

Under ARC, the array variable's initializer within DeclStmt is an
ImplicitValueInitExpr. Environment doesn't maintain any bindings for this
expression kind - instead it always knows that it's a known constant
(0 in our case), so it just returns the known value by calling
SValBuilder::makeZeroVal() (see EnvironmentManager::getSVal().
Commit r289618 had introduced reasonable behavior of SValBuilder::makeZeroVal()
for the arrays, which produces a zero-length compoundVal{}. When such value
is bound to arrays, in RegionStoreManager::bindArray() "remaining" items in the
array are default-initialized with zero, as in
RegionStoreManager::setImplicitDefaultValue(). The similar mechanism works when
an array is initialized by an initializer list that is too short, eg.
  int a[3] = { 1, 2 };
would result in a[2] initialized with 0. However, in case of variable-length
arrays it didn't know if any more items need to be added,
because, well, the length is variable.

Add the default binding anyway, regardless of how many actually need
to be added. We don't really care how many, because the default binding covers
the whole array anyway.

Differential Revision: https://reviews.llvm.org/D41478
rdar://problem/35477763

llvm-svn: 321290
  • Loading branch information
haoNoQ committed Dec 21, 2017
1 parent 4de5bb0 commit 9d3ca9a
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 3 deletions.
7 changes: 4 additions & 3 deletions clang/lib/StaticAnalyzer/Core/RegionStore.cpp
Expand Up @@ -2132,9 +2132,10 @@ RegionStoreManager::bindArray(RegionBindingsConstRef B,
NewB = bind(NewB, loc::MemRegionVal(ER), *VI);
}

// If the init list is shorter than the array length, set the
// array default value.
if (Size.hasValue() && i < Size.getValue())
// If the init list is shorter than the array length (or the array has
// variable length), set the array default value. Values that are already set
// are not overwritten.
if (!Size.hasValue() || i < Size.getValue())
NewB = setImplicitDefaultValue(NewB, R, ElementTy);

return NewB;
Expand Down
46 changes: 46 additions & 0 deletions clang/test/Analysis/arc-zero-init.m
@@ -0,0 +1,46 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s
// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify -fobjc-arc %s

#if __has_feature(objc_arc)
// expected-no-diagnostics
#endif

@interface SomeClass
@end

void simpleStrongPointerValue() {
SomeClass *x;
if (x) {}
#if !__has_feature(objc_arc)
// expected-warning@-2{{Branch condition evaluates to a garbage value}}
#endif
}

void simpleArray() {
SomeClass *vlaArray[5];

if (vlaArray[0]) {}
#if !__has_feature(objc_arc)
// expected-warning@-2{{Branch condition evaluates to a garbage value}}
#endif
}

void variableLengthArray() {
int count = 1;
SomeClass * vlaArray[count];

if (vlaArray[0]) {}
#if !__has_feature(objc_arc)
// expected-warning@-2{{Branch condition evaluates to a garbage value}}
#endif
}

void variableLengthArrayWithExplicitStrongAttribute() {
int count = 1;
__attribute__((objc_ownership(strong))) SomeClass * vlaArray[count];

if (vlaArray[0]) {}
#if !__has_feature(objc_arc)
// expected-warning@-2{{Branch condition evaluates to a garbage value}}
#endif
}

0 comments on commit 9d3ca9a

Please sign in to comment.