summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2011-02-27 01:32:10 +0000
committerdim <dim@FreeBSD.org>2011-02-27 01:32:10 +0000
commitb951d621be1d00a520871c689c1cd687b6aa3ae6 (patch)
tree5c342f2374324ffec4626f558d9aa49f323f90b4 /contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
parent4004d6a3076e94bd23e681411c43682267a202fe (diff)
parenta0fb00f9837bd0d2e5948f16f6a6b82a7a628f51 (diff)
downloadFreeBSD-src-b951d621be1d00a520871c689c1cd687b6aa3ae6.zip
FreeBSD-src-b951d621be1d00a520871c689c1cd687b6aa3ae6.tar.gz
Update llvm/clang to trunk r126547.
There are several bugfixes in this update, but the most important one is to ensure __start_ and __stop_ symbols for linker sets and kernel module metadata are always emitted in object files: http://llvm.org/bugs/show_bug.cgi?id=9292 Before this fix, if you compiled kernel modules with clang, they would not be properly processed by kldxref, and if they had any dependencies, the kernel would fail to load those. Another problem occurred when attempting to mount a tmpfs filesystem, which would result in 'operation not supported by device'.
Diffstat (limited to 'contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp123
1 files changed, 67 insertions, 56 deletions
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
index 4f247ea..5f32bb8 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
@@ -47,8 +47,9 @@
// http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocAllocInit.html
#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
@@ -63,45 +64,23 @@ static bool isInitMessage(const ObjCMessage &msg);
static bool isSelfVar(SVal location, CheckerContext &C);
namespace {
-enum SelfFlagEnum {
- /// \brief No flag set.
- SelfFlag_None = 0x0,
- /// \brief Value came from 'self'.
- SelfFlag_Self = 0x1,
- /// \brief Value came from the result of an initializer (e.g. [super init]).
- SelfFlag_InitRes = 0x2
-};
-}
-
-namespace {
-class ObjCSelfInitChecker : public CheckerVisitor<ObjCSelfInitChecker> {
- /// \brief A call receiving a reference to 'self' invalidates the object that
- /// 'self' contains. This field keeps the "self flags" assigned to the 'self'
- /// object before the call and assign them to the new object that 'self'
- /// points to after the call.
- SelfFlagEnum preCallSelfFlags;
-
+class ObjCSelfInitChecker : public CheckerV2<
+ check::PostObjCMessage,
+ check::PostStmt<ObjCIvarRefExpr>,
+ check::PreStmt<ReturnStmt>,
+ check::PreStmt<CallExpr>,
+ check::PostStmt<CallExpr>,
+ check::Location > {
public:
- static void *getTag() { static int tag = 0; return &tag; }
- void postVisitObjCMessage(CheckerContext &C, ObjCMessage msg);
- void PostVisitObjCIvarRefExpr(CheckerContext &C, const ObjCIvarRefExpr *E);
- void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S);
- void PreVisitGenericCall(CheckerContext &C, const CallExpr *CE);
- void PostVisitGenericCall(CheckerContext &C, const CallExpr *CE);
- virtual void visitLocation(CheckerContext &C, const Stmt *S, SVal location,
- bool isLoad);
+ void checkPostObjCMessage(ObjCMessage msg, CheckerContext &C) const;
+ void checkPostStmt(const ObjCIvarRefExpr *E, CheckerContext &C) const;
+ void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
+ void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
+ void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
+ void checkLocation(SVal location, bool isLoad, CheckerContext &C) const;
};
} // end anonymous namespace
-static void RegisterObjCSelfInitChecker(ExprEngine &Eng) {
- if (Eng.getContext().getLangOptions().ObjC1)
- Eng.registerCheck(new ObjCSelfInitChecker());
-}
-
-void ento::registerObjCSelfInitChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterObjCSelfInitChecker);
-}
-
namespace {
class InitSelfBug : public BugType {
@@ -113,22 +92,40 @@ public:
} // end anonymous namespace
+namespace {
+enum SelfFlagEnum {
+ /// \brief No flag set.
+ SelfFlag_None = 0x0,
+ /// \brief Value came from 'self'.
+ SelfFlag_Self = 0x1,
+ /// \brief Value came from the result of an initializer (e.g. [super init]).
+ SelfFlag_InitRes = 0x2
+};
+}
+
typedef llvm::ImmutableMap<SymbolRef, unsigned> SelfFlag;
namespace { struct CalledInit {}; }
+namespace { struct PreCallSelfFlags {}; }
namespace clang {
namespace ento {
template<>
struct GRStateTrait<SelfFlag> : public GRStatePartialTrait<SelfFlag> {
- static void* GDMIndex() {
- static int index = 0;
- return &index;
- }
+ static void* GDMIndex() { static int index = 0; return &index; }
};
template <>
struct GRStateTrait<CalledInit> : public GRStatePartialTrait<bool> {
static void *GDMIndex() { static int index = 0; return &index; }
};
+
+ /// \brief A call receiving a reference to 'self' invalidates the object that
+ /// 'self' contains. This keeps the "self flags" assigned to the 'self'
+ /// object before the call so we can assign them to the new object that 'self'
+ /// points to after the call.
+ template <>
+ struct GRStateTrait<PreCallSelfFlags> : public GRStatePartialTrait<unsigned> {
+ static void *GDMIndex() { static int index = 0; return &index; }
+ };
}
}
@@ -188,8 +185,8 @@ static void checkForInvalidSelf(const Expr *E, CheckerContext &C,
C.EmitReport(report);
}
-void ObjCSelfInitChecker::postVisitObjCMessage(CheckerContext &C,
- ObjCMessage msg) {
+void ObjCSelfInitChecker::checkPostObjCMessage(ObjCMessage msg,
+ CheckerContext &C) const {
// When encountering a message that does initialization (init rule),
// tag the return value so that we know later on that if self has this value
// then it is properly initialized.
@@ -219,8 +216,8 @@ void ObjCSelfInitChecker::postVisitObjCMessage(CheckerContext &C,
// fails.
}
-void ObjCSelfInitChecker::PostVisitObjCIvarRefExpr(CheckerContext &C,
- const ObjCIvarRefExpr *E) {
+void ObjCSelfInitChecker::checkPostStmt(const ObjCIvarRefExpr *E,
+ CheckerContext &C) const {
// FIXME: A callback should disable checkers at the start of functions.
if (!shouldRunOnFunctionOrMethod(dyn_cast<NamedDecl>(
C.getCurrentAnalysisContext()->getDecl())))
@@ -231,8 +228,8 @@ void ObjCSelfInitChecker::PostVisitObjCIvarRefExpr(CheckerContext &C,
"'[(super or self) init...]'");
}
-void ObjCSelfInitChecker::PreVisitReturnStmt(CheckerContext &C,
- const ReturnStmt *S) {
+void ObjCSelfInitChecker::checkPreStmt(const ReturnStmt *S,
+ CheckerContext &C) const {
// FIXME: A callback should disable checkers at the start of functions.
if (!shouldRunOnFunctionOrMethod(dyn_cast<NamedDecl>(
C.getCurrentAnalysisContext()->getDecl())))
@@ -259,40 +256,46 @@ void ObjCSelfInitChecker::PreVisitReturnStmt(CheckerContext &C,
// 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) {
+void ObjCSelfInitChecker::checkPreStmt(const CallExpr *CE,
+ CheckerContext &C) const {
const GRState *state = C.getState();
for (CallExpr::const_arg_iterator
I = CE->arg_begin(), E = CE->arg_end(); I != E; ++I) {
SVal argV = state->getSVal(*I);
if (isSelfVar(argV, C)) {
- preCallSelfFlags = getSelfFlags(state->getSVal(cast<Loc>(argV)), C);
+ unsigned selfFlags = getSelfFlags(state->getSVal(cast<Loc>(argV)), C);
+ C.addTransition(state->set<PreCallSelfFlags>(selfFlags));
return;
} else if (hasSelfFlag(argV, SelfFlag_Self, C)) {
- preCallSelfFlags = getSelfFlags(argV, C);
+ unsigned selfFlags = getSelfFlags(argV, C);
+ C.addTransition(state->set<PreCallSelfFlags>(selfFlags));
return;
}
}
}
-void ObjCSelfInitChecker::PostVisitGenericCall(CheckerContext &C,
- const CallExpr *CE) {
+void ObjCSelfInitChecker::checkPostStmt(const CallExpr *CE,
+ CheckerContext &C) const {
const GRState *state = C.getState();
for (CallExpr::const_arg_iterator
I = CE->arg_begin(), E = CE->arg_end(); I != E; ++I) {
SVal argV = state->getSVal(*I);
if (isSelfVar(argV, C)) {
- addSelfFlag(state, state->getSVal(cast<Loc>(argV)), preCallSelfFlags, C);
+ SelfFlagEnum prevFlags = (SelfFlagEnum)state->get<PreCallSelfFlags>();
+ state = state->remove<PreCallSelfFlags>();
+ addSelfFlag(state, state->getSVal(cast<Loc>(argV)), prevFlags, C);
return;
} else if (hasSelfFlag(argV, SelfFlag_Self, C)) {
- addSelfFlag(state, state->getSVal(CE), preCallSelfFlags, C);
+ SelfFlagEnum prevFlags = (SelfFlagEnum)state->get<PreCallSelfFlags>();
+ state = state->remove<PreCallSelfFlags>();
+ addSelfFlag(state, state->getSVal(CE), prevFlags, C);
return;
}
}
}
-void ObjCSelfInitChecker::visitLocation(CheckerContext &C, const Stmt *S,
- SVal location, bool isLoad) {
+void ObjCSelfInitChecker::checkLocation(SVal location, bool isLoad,
+ CheckerContext &C) const {
// Tag the result of a load from 'self' so that we can easily know that the
// value is the object that 'self' points to.
const GRState *state = C.getState();
@@ -354,3 +357,11 @@ static bool isInitializationMethod(const ObjCMethodDecl *MD) {
static bool isInitMessage(const ObjCMessage &msg) {
return cocoa::deriveNamingConvention(msg.getSelector()) == cocoa::InitRule;
}
+
+//===----------------------------------------------------------------------===//
+// Registration.
+//===----------------------------------------------------------------------===//
+
+void ento::registerObjCSelfInitChecker(CheckerManager &mgr) {
+ mgr.registerChecker<ObjCSelfInitChecker>();
+}
OpenPOWER on IntegriCloud