diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2011-02-05 05:54:53 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2011-02-05 05:54:53 +0000 |
commit | dd03d8ddaa18f9b197dc52c20894e34dae0a2462 (patch) | |
tree | d32a06ef5a1f936957ce5957cdb34d0b397f1ede /clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp | |
parent | 3d3208675f79d05fd0b026c735fbe83ecd20a98b (diff) | |
download | llvm-dd03d8ddaa18f9b197dc52c20894e34dae0a2462.zip llvm-dd03d8ddaa18f9b197dc52c20894e34dae0a2462.tar.gz llvm-dd03d8ddaa18f9b197dc52c20894e34dae0a2462.tar.bz2 |
[analyzer] Fix a false positive of the 'self' initialization checker.
A common pattern in classes with multiple initializers is to put the
subclass's common initialization bits into a static function that receives
the value of 'self', e.g:
if (!(self = [super init]))
return nil;
if (!(self = _commonInit(self)))
return nil;
It was reported that 'self' was not set to the result of [super init].
Until we can use inter-procedural analysis, in such a call, transfer the
ObjCSelfInitChecker flags associated with 'self' to the result of the call.
Fixes rdar://8937441 & http://llvm.org/PR9094
llvm-svn: 124940
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp')
-rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp index ff1e5dd..786a588 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp @@ -135,9 +135,7 @@ static SelfFlagEnum getSelfFlags(SVal val, CheckerContext &C) { static void addSelfFlag(SVal val, SelfFlagEnum flag, CheckerContext &C) { const GRState *state = C.getState(); - // FIXME: We tag the symbol that the SVal wraps but this is conceptually - // wrong, we should tag the SVal; the fact that there is a symbol behind the - // SVal is irrelevant. + // We tag the symbol that the SVal wraps. if (SymbolRef sym = val.getAsSymbol()) C.addTransition(state->set<SelfFlag>(sym, getSelfFlags(val, C) | flag)); } @@ -227,7 +225,19 @@ void ObjCSelfInitChecker::PreVisitReturnStmt(CheckerContext &C, // When a call receives a reference to 'self', [Pre/Post]VisitGenericCall pass // the SelfFlags from the object 'self' point to before the call, to the new -// object after the call. +// object after the call. This is to avoid invalidation of 'self' by logging +// functions. +// Another common pattern in classes with multiple initializers is to put the +// subclass's common initialization bits into a static function that receives +// the value of 'self', e.g: +// @code +// if (!(self = [super init])) +// return nil; +// if (!(self = _commonInit(self))) +// return nil; +// @endcode +// Until we can use inter-procedural analysis, in such a call, transfer the +// SelfFlags to the result of the call. void ObjCSelfInitChecker::PreVisitGenericCall(CheckerContext &C, const CallExpr *CE) { @@ -238,6 +248,9 @@ void ObjCSelfInitChecker::PreVisitGenericCall(CheckerContext &C, if (isSelfVar(argV, C)) { preCallSelfFlags = getSelfFlags(state->getSVal(cast<Loc>(argV)), C); return; + } else if (hasSelfFlag(argV, SelfFlag_Self, C)) { + preCallSelfFlags = getSelfFlags(argV, C); + return; } } } @@ -251,6 +264,9 @@ void ObjCSelfInitChecker::PostVisitGenericCall(CheckerContext &C, if (isSelfVar(argV, C)) { addSelfFlag(state->getSVal(cast<Loc>(argV)), preCallSelfFlags, C); return; + } else if (hasSelfFlag(argV, SelfFlag_Self, C)) { + addSelfFlag(state->getSVal(CE), preCallSelfFlags, C); + return; } } } |