Fix idempotent operations false positive caused by ivars not being invalidated in function

calls when the enclosing object had retain/release state.  Fixes <rdar://problem/8261992>.

llvm-svn: 110068
This commit is contained in:
Ted Kremenek 2010-08-02 21:59:12 +00:00
parent 7f5f2809e8
commit 297e2e5bf6
2 changed files with 38 additions and 2 deletions

View File

@ -2623,19 +2623,25 @@ void CFRefCount::EvalSummary(ExplodedNodeSet& Dst,
llvm::SmallVector<const MemRegion*, 10> RegionsToInvalidate;
// HACK: Symbols that have ref-count state that are referenced directly
// (not as structure or array elements, or via bindings) by an argument
// should not have their ref-count state stripped after we have
// done an invalidation pass.
llvm::DenseSet<SymbolRef> WhitelistedSymbols;
for (ConstExprIterator I = arg_beg; I != arg_end; ++I, ++idx) {
SVal V = state->getSValAsScalarOrLoc(*I);
SymbolRef Sym = V.getAsLocSymbol();
if (Sym)
if (RefBindings::data_type* T = state->get<RefBindings>(Sym)) {
WhitelistedSymbols.insert(Sym);
state = Update(state, Sym, *T, Summ.getArg(idx), hasErr);
if (hasErr) {
ErrorRange = (*I)->getSourceRange();
ErrorSym = Sym;
break;
}
continue;
}
tryAgain:
@ -2721,7 +2727,10 @@ void CFRefCount::EvalSummary(ExplodedNodeSet& Dst,
state = state->makeWithStore(store);
for (StoreManager::InvalidatedSymbols::iterator I = IS.begin(),
E = IS.end(); I!=E; ++I) {
// Remove any existing reference-count binding.
SymbolRef sym = *I;
if (WhitelistedSymbols.count(sym))
continue;
// Remove any existing reference-count binding.
state = state->remove<RefBindings>(*I);
}

View File

@ -50,6 +50,7 @@ typedef struct _NSZone NSZone;
@end @protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder;
@end
@interface NSObject <NSObject> {}
- (id)init;
+ (id)allocWithZone:(NSZone *)zone;
+ (id)alloc;
- (void)dealloc;
@ -223,3 +224,29 @@ void pr6699(int x) {
}
}
// <rdar://problem/8261992> Idempotent operation checker false positive with ObjC ivars
@interface R8261992 : NSObject {
@package int myIvar;
}
@end
static void R8261992_ChangeMyIvar(R8261992 *tc) {
tc->myIvar = 5;
}
void R8261992_test(R8261992 *tc) {
int temp = tc->myIvar;
// The ivar binding for tc->myIvar gets invalidated.
R8261992_ChangeMyIvar(tc);
tc->myIvar = temp; // no-warning
tc = [[R8261992 alloc] init];
temp = tc->myIvar; // no-warning
// The ivar binding for tc->myIvar gets invalidated.
R8261992_ChangeMyIvar(tc);
tc->myIvar = temp;
[tc release]; // no-warning
// did we analyze this?
int *p = 0x0;
*p = 0xDEADBEEF; // expected-warning{{null}}
}