[cfe-commits] r138210 - in /cfe/trunk: lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp lib/StaticAnalyzer/Core/CFRefCount.cpp test/Analysis/CFRetainRelease_NSAssertionHandler.m
Jordy Rose
jediknil at belkadan.com
Sat Aug 20 13:55:40 PDT 2011
Author: jrose
Date: Sat Aug 20 15:55:40 2011
New Revision: 138210
URL: http://llvm.org/viewvc/llvm-project?rev=138210&view=rev
Log:
[analyzer] Move handling of hardcoded noreturn ("panic") methods from CFRefCount to NoReturnFunctionChecker. No functionality change intended.
Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp
cfe/trunk/lib/StaticAnalyzer/Core/CFRefCount.cpp
cfe/trunk/test/Analysis/CFRetainRelease_NSAssertionHandler.m
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp?rev=138210&r1=138209&r2=138210&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp Sat Aug 20 15:55:40 2011
@@ -17,15 +17,18 @@
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/DataTypes.h"
using namespace clang;
using namespace ento;
namespace {
-class NoReturnFunctionChecker : public Checker< check::PostStmt<CallExpr> > {
+class NoReturnFunctionChecker : public Checker< check::PostStmt<CallExpr>,
+ check::PostObjCMessage > {
public:
void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
+ void checkPostObjCMessage(const ObjCMessage &msg, CheckerContext &C) const;
};
}
@@ -76,6 +79,67 @@
C.generateSink(CE);
}
+static bool END_WITH_NULL isMultiArgSelector(Selector Sel, ...) {
+ va_list argp;
+ va_start(argp, Sel);
+
+ unsigned Slot = 0;
+ const char *Arg;
+ while ((Arg = va_arg(argp, const char *))) {
+ if (!Sel.getNameForSlot(Slot).equals(Arg))
+ break; // still need to va_end!
+ ++Slot;
+ }
+
+ va_end(argp);
+
+ // We only succeeded if we made it to the end of the argument list.
+ return (Arg == NULL);
+}
+
+void NoReturnFunctionChecker::checkPostObjCMessage(const ObjCMessage &Msg,
+ CheckerContext &C) const {
+ // HACK: This entire check is to handle two messages in the Cocoa frameworks:
+ // -[NSAssertionHandler
+ // handleFailureInMethod:object:file:lineNumber:description:]
+ // -[NSAssertionHandler
+ // handleFailureInFunction:file:lineNumber:description:]
+ // Eventually these should be annotated with __attribute__((noreturn)).
+ // Because ObjC messages use dynamic dispatch, it is not generally safe to
+ // assume certain methods can't return. In cases where it is definitely valid,
+ // see if you can mark the methods noreturn or analyzer_noreturn instead of
+ // adding more explicit checks to this method.
+
+ if (!Msg.isInstanceMessage())
+ return;
+
+ const ObjCInterfaceDecl *Receiver = Msg.getReceiverInterface();
+ if (!Receiver)
+ return;
+ if (!Receiver->getIdentifier()->isStr("NSAssertionHandler"))
+ return;
+
+ Selector Sel = Msg.getSelector();
+ switch (Sel.getNumArgs()) {
+ default:
+ return;
+ case 4:
+ if (!isMultiArgSelector(Sel, "handleFailureInFunction", "file",
+ "lineNumber", "description", NULL))
+ return;
+ break;
+ case 5:
+ if (!isMultiArgSelector(Sel, "handleFailureInMethod", "object", "file",
+ "lineNumber", "description", NULL))
+ return;
+ break;
+ }
+
+ // If we got here, it's one of the messages we care about.
+ C.generateSink();
+}
+
+
void ento::registerNoReturnFunctionChecker(CheckerManager &mgr) {
mgr.registerChecker<NoReturnFunctionChecker>();
}
Modified: cfe/trunk/lib/StaticAnalyzer/Core/CFRefCount.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CFRefCount.cpp?rev=138210&r1=138209&r2=138210&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/CFRefCount.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/CFRefCount.cpp Sat Aug 20 15:55:40 2011
@@ -431,15 +431,10 @@
/// alias of one of the arguments in the call, and so on.
RetEffect Ret;
- /// EndPath - Indicates that execution of this method/function should
- /// terminate the simulation of a path.
- bool EndPath;
-
public:
RetainSummary(ArgEffects A, RetEffect R, ArgEffect defaultEff,
- ArgEffect ReceiverEff, bool endpath = false)
- : Args(A), DefaultArgEffect(defaultEff), Receiver(ReceiverEff), Ret(R),
- EndPath(endpath) {}
+ ArgEffect ReceiverEff)
+ : Args(A), DefaultArgEffect(defaultEff), Receiver(ReceiverEff), Ret(R) {}
/// getArg - Return the argument effect on the argument specified by
/// idx (starting from 0).
@@ -465,10 +460,6 @@
/// setRetEffect - Set the effect of the return value of the call.
void setRetEffect(RetEffect E) { Ret = E; }
- /// isEndPath - Returns true if executing the given method/function should
- /// terminate the path.
- bool isEndPath() const { return EndPath; }
-
/// Sets the effect on the receiver of the message.
void setReceiverEffect(ArgEffect e) { Receiver = e; }
@@ -692,8 +683,7 @@
RetainSummary* getPersistentSummary(ArgEffects AE, RetEffect RetEff,
ArgEffect ReceiverEff = DoNothing,
- ArgEffect DefaultEff = MayEscape,
- bool isEndPath = false);
+ ArgEffect DefaultEff = MayEscape);
RetainSummary* getPersistentSummary(RetEffect RE,
ArgEffect ReceiverEff = DoNothing,
@@ -774,16 +764,6 @@
va_end(argp);
}
- void addPanicSummary(const char* Cls, ...) {
- RetainSummary* Summ = getPersistentSummary(AF.getEmptyMap(),
- RetEffect::MakeNoRet(),
- DoNothing, DoNothing, true);
- va_list argp;
- va_start (argp, Cls);
- addMethodSummary(&Ctx.Idents.get(Cls), ObjCMethodSummaries, Summ, argp);
- va_end(argp);
- }
-
public:
RetainSummaryManager(ASTContext &ctx, bool gcenabled, bool usesARC)
@@ -899,11 +879,10 @@
RetainSummary*
RetainSummaryManager::getPersistentSummary(ArgEffects AE, RetEffect RetEff,
ArgEffect ReceiverEff,
- ArgEffect DefaultEff,
- bool isEndPath) {
+ ArgEffect DefaultEff) {
// Create the summary and return it.
RetainSummary *Summ = (RetainSummary*) BPAlloc.Allocate<RetainSummary>();
- new (Summ) RetainSummary(AE, RetEff, DefaultEff, ReceiverEff, isEndPath);
+ new (Summ) RetainSummary(AE, RetEff, DefaultEff, ReceiverEff);
return Summ;
}
@@ -1569,13 +1548,6 @@
// exit a method.
addClassMethSummary("NSAutoreleasePool", "alloc", NoTrackYet);
- // Create NSAssertionHandler summaries.
- addPanicSummary("NSAssertionHandler", "handleFailureInFunction", "file",
- "lineNumber", "description", NULL);
-
- addPanicSummary("NSAssertionHandler", "handleFailureInMethod", "object",
- "file", "lineNumber", "description", NULL);
-
// Create summaries QCRenderer/QCView -createSnapShotImageOfType:
addInstMethSummary("QCRenderer", AllocSumm,
"createSnapshotImageOfType", NULL);
@@ -2846,10 +2818,7 @@
}
}
- // Generate a sink node if we are at the end of a path.
- ExplodedNode *NewNode =
- Summ.isEndPath() ? Builder.MakeSinkNode(Dst, Ex, Pred, state)
- : Builder.MakeNode(Dst, Ex, Pred, state);
+ ExplodedNode *NewNode = Builder.MakeNode(Dst, Ex, Pred, state);
// Annotate the edge with summary we used.
if (NewNode) SummaryLog[NewNode] = &Summ;
Modified: cfe/trunk/test/Analysis/CFRetainRelease_NSAssertionHandler.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/CFRetainRelease_NSAssertionHandler.m?rev=138210&r1=138209&r2=138210&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/CFRetainRelease_NSAssertionHandler.m (original)
+++ cfe/trunk/test/Analysis/CFRetainRelease_NSAssertionHandler.m Sat Aug 20 15:55:40 2011
@@ -20,6 +20,7 @@
@interface NSAssertionHandler : NSObject {}
+ (NSAssertionHandler *)currentHandler;
- (void)handleFailureInMethod:(SEL)selector object:(id)object file:(NSString *)fileName lineNumber:(NSInteger)line description:(NSString *)format,...;
+- (void)handleFailureInFunction:(NSString *)functionName file:(NSString *)fileName lineNumber:(NSInteger)line description:(NSString *)format,...;
@end
extern NSString * const NSConnectionReplyMode;
@@ -63,3 +64,10 @@
}
@end
+
+void pointerFunction (int *x) {
+ // Manual expansion of NSCAssert( x != 0, @"")
+ do { if (!((x != 0))) { [[NSAssertionHandler currentHandler] handleFailureInFunction:[NSString stringWithUTF8String:__PRETTY_FUNCTION__] file:[NSString stringWithUTF8String:__FILE__] lineNumber:__LINE__ description:((@""))]; } } while(0);
+
+ *x = 1; // no-warning
+}
More information about the cfe-commits
mailing list