aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2012-07-02 19:28:04 +0000
committerJordan Rose <jordan_rose@apple.com>2012-07-02 19:28:04 +0000
commitde507eaf3cb54d3cb234dc14499c10ab3373d15f (patch)
treed6f5328cba078ef92f7825cdb3b2f7053a90e854 /lib/StaticAnalyzer
parentcde8cdbd6a662c636164465ad309b5f17ff01064 (diff)
[analyzer] Finish replacing ObjCMessage with ObjCMethodDecl and friends.
The preObjCMessage and postObjCMessage callbacks now take an ObjCMethodCall argument, which can represent an explicit message send (ObjCMessageSend) or an implicit message generated by a property access (ObjCPropertyAccess). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@159559 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer')
-rw-r--r--lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp53
-rw-r--r--lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp121
-rw-r--r--lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp4
-rw-r--r--lib/StaticAnalyzer/Checkers/MallocChecker.cpp16
-rw-r--r--lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp23
-rw-r--r--lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp6
-rw-r--r--lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp1
-rw-r--r--lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp29
-rw-r--r--lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp14
-rw-r--r--lib/StaticAnalyzer/Core/Calls.cpp2
-rw-r--r--lib/StaticAnalyzer/Core/CheckerManager.cpp10
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngine.cpp4
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineObjC.cpp1
13 files changed, 124 insertions, 160 deletions
diff --git a/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp b/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
index c75c86faf4..1d0c4b336b 100644
--- a/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
+++ b/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
@@ -17,10 +17,10 @@
#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/Calls.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
@@ -46,10 +46,10 @@ public:
// Utility functions.
//===----------------------------------------------------------------------===//
-static const char* GetReceiverNameType(const ObjCMessage &msg) {
+static StringRef GetReceiverInterfaceName(const ObjCMethodCall &msg) {
if (const ObjCInterfaceDecl *ID = msg.getReceiverInterface())
- return ID->getIdentifier()->getNameStart();
- return 0;
+ return ID->getIdentifier()->getName();
+ return StringRef();
}
enum FoundationClass {
@@ -95,15 +95,15 @@ namespace {
mutable OwningPtr<APIMisuse> BT;
void WarnNilArg(CheckerContext &C,
- const ObjCMessage &msg, unsigned Arg) const;
+ const ObjCMethodCall &msg, unsigned Arg) const;
public:
- void checkPreObjCMessage(ObjCMessage msg, CheckerContext &C) const;
+ void checkPreObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
};
}
void NilArgChecker::WarnNilArg(CheckerContext &C,
- const ObjCMessage &msg,
+ const ObjCMethodCall &msg,
unsigned int Arg) const
{
if (!BT)
@@ -112,7 +112,7 @@ void NilArgChecker::WarnNilArg(CheckerContext &C,
if (ExplodedNode *N = C.generateSink()) {
SmallString<128> sbuf;
llvm::raw_svector_ostream os(sbuf);
- os << "Argument to '" << GetReceiverNameType(msg) << "' method '"
+ os << "Argument to '" << GetReceiverInterfaceName(msg) << "' method '"
<< msg.getSelector().getAsString() << "' cannot be nil";
BugReport *R = new BugReport(*BT, os.str(), N);
@@ -121,7 +121,7 @@ void NilArgChecker::WarnNilArg(CheckerContext &C,
}
}
-void NilArgChecker::checkPreObjCMessage(ObjCMessage msg,
+void NilArgChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
CheckerContext &C) const {
const ObjCInterfaceDecl *ID = msg.getReceiverInterface();
if (!ID)
@@ -151,7 +151,7 @@ void NilArgChecker::checkPreObjCMessage(ObjCMessage msg,
Name == "compare:options:range:locale:" ||
Name == "componentsSeparatedByCharactersInSet:" ||
Name == "initWithFormat:") {
- if (isNil(msg.getArgSVal(0, C.getLocationContext(), C.getState())))
+ if (isNil(msg.getArgSVal(0)))
WarnNilArg(C, msg, 0);
}
}
@@ -455,11 +455,11 @@ class ClassReleaseChecker : public Checker<check::PreObjCMessage> {
mutable OwningPtr<BugType> BT;
public:
- void checkPreObjCMessage(ObjCMessage msg, CheckerContext &C) const;
+ void checkPreObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const;
};
}
-void ClassReleaseChecker::checkPreObjCMessage(ObjCMessage msg,
+void ClassReleaseChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
CheckerContext &C) const {
if (!BT) {
@@ -511,18 +511,18 @@ class VariadicMethodTypeChecker : public Checker<check::PreObjCMessage> {
mutable Selector initWithObjectsAndKeysS;
mutable OwningPtr<BugType> BT;
- bool isVariadicMessage(const ObjCMessage &msg) const;
+ bool isVariadicMessage(const ObjCMethodCall &msg) const;
public:
- void checkPreObjCMessage(ObjCMessage msg, CheckerContext &C) const;
+ void checkPreObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const;
};
}
/// isVariadicMessage - Returns whether the given message is a variadic message,
/// where all arguments must be Objective-C types.
bool
-VariadicMethodTypeChecker::isVariadicMessage(const ObjCMessage &msg) const {
- const ObjCMethodDecl *MD = msg.getMethodDecl();
+VariadicMethodTypeChecker::isVariadicMessage(const ObjCMethodCall &msg) const {
+ const ObjCMethodDecl *MD = msg.getDecl();
if (!MD || !MD->isVariadic() || isa<ObjCProtocolDecl>(MD->getDeclContext()))
return false;
@@ -566,7 +566,7 @@ VariadicMethodTypeChecker::isVariadicMessage(const ObjCMessage &msg) const {
}
}
-void VariadicMethodTypeChecker::checkPreObjCMessage(ObjCMessage msg,
+void VariadicMethodTypeChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
CheckerContext &C) const {
if (!BT) {
BT.reset(new APIMisuse("Arguments passed to variadic method aren't all "
@@ -602,7 +602,7 @@ void VariadicMethodTypeChecker::checkPreObjCMessage(ObjCMessage msg,
ProgramStateRef state = C.getState();
for (unsigned I = variadicArgsBegin; I != variadicArgsEnd; ++I) {
- QualType ArgTy = msg.getArgType(I);
+ QualType ArgTy = msg.getArgExpr(I)->getType();
if (ArgTy->isObjCObjectPointerType())
continue;
@@ -611,8 +611,7 @@ void VariadicMethodTypeChecker::checkPreObjCMessage(ObjCMessage msg,
continue;
// Ignore pointer constants.
- if (isa<loc::ConcreteInt>(msg.getArgSVal(I, C.getLocationContext(),
- state)))
+ if (isa<loc::ConcreteInt>(msg.getArgSVal(I)))
continue;
// Ignore pointer types annotated with 'NSObject' attribute.
@@ -624,9 +623,8 @@ void VariadicMethodTypeChecker::checkPreObjCMessage(ObjCMessage msg,
continue;
// Generate only one error node to use for all bug reports.
- if (!errorNode.hasValue()) {
+ if (!errorNode.hasValue())
errorNode = C.addTransition();
- }
if (!errorNode.getValue())
continue;
@@ -634,17 +632,18 @@ void VariadicMethodTypeChecker::checkPreObjCMessage(ObjCMessage msg,
SmallString<128> sbuf;
llvm::raw_svector_ostream os(sbuf);
- if (const char *TypeName = GetReceiverNameType(msg))
+ StringRef TypeName = GetReceiverInterfaceName(msg);
+ if (!TypeName.empty())
os << "Argument to '" << TypeName << "' method '";
else
os << "Argument to method '";
os << msg.getSelector().getAsString()
- << "' should be an Objective-C pointer type, not '"
- << ArgTy.getAsString() << "'";
+ << "' should be an Objective-C pointer type, not '";
+ ArgTy.print(os, C.getLangOpts());
+ os << "'";
- BugReport *R = new BugReport(*BT, os.str(),
- errorNode.getValue());
+ BugReport *R = new BugReport(*BT, os.str(), errorNode.getValue());
R->addRange(msg.getArgSourceRange(I));
C.EmitReport(R);
}
diff --git a/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp b/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
index 30be60c9a6..083f21ea3f 100644
--- a/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
@@ -17,7 +17,6 @@
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/Calls.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/AST/ParentMap.h"
#include "clang/Basic/TargetInfo.h"
@@ -39,7 +38,7 @@ class CallAndMessageChecker
public:
void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
- void checkPreObjCMessage(ObjCMessage msg, CheckerContext &C) const;
+ void checkPreObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const;
private:
static void PreVisitProcessArgs(CheckerContext &C, const CallEvent &Call,
@@ -51,12 +50,12 @@ private:
OwningPtr<BugType> &BT);
static void EmitBadCall(BugType *BT, CheckerContext &C, const CallExpr *CE);
- void emitNilReceiverBug(CheckerContext &C, const ObjCMessage &msg,
+ void emitNilReceiverBug(CheckerContext &C, const ObjCMethodCall &msg,
ExplodedNode *N) const;
void HandleNilReceiver(CheckerContext &C,
ProgramStateRef state,
- ObjCMessage msg) const;
+ const ObjCMethodCall &msg) const;
static void LazyInit_BT(const char *desc, OwningPtr<BugType> &BT) {
if (!BT)
@@ -248,65 +247,61 @@ void CallAndMessageChecker::checkPreStmt(const CallExpr *CE,
}
}
-void CallAndMessageChecker::checkPreObjCMessage(ObjCMessage msg,
+void CallAndMessageChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
CheckerContext &C) const {
+ SVal recVal = msg.getReceiverSVal();
+ if (recVal.isUndef()) {
+ if (ExplodedNode *N = C.generateSink()) {
+ BugType *BT = 0;
+ if (isa<ObjCPropertyAccess>(msg)) {
+ if (!BT_objc_prop_undef)
+ BT_objc_prop_undef.reset(new BuiltinBug("Property access on an "
+ "uninitialized object pointer"));
+ BT = BT_objc_prop_undef.get();
+ } else {
+ if (!BT_msg_undef)
+ BT_msg_undef.reset(new BuiltinBug("Receiver in message expression "
+ "is an uninitialized value"));
+ BT = BT_msg_undef.get();
+ }
+ BugReport *R = new BugReport(*BT, BT->getName(), N);
+ R->addRange(msg.getReceiverSourceRange());
- ProgramStateRef state = C.getState();
- const LocationContext *LCtx = C.getLocationContext();
-
- // FIXME: Handle 'super'?
- if (const Expr *receiver = msg.getInstanceReceiver()) {
- SVal recVal = state->getSVal(receiver, LCtx);
- if (recVal.isUndef()) {
- if (ExplodedNode *N = C.generateSink()) {
- BugType *BT = 0;
- if (msg.isPureMessageExpr()) {
- if (!BT_msg_undef)
- BT_msg_undef.reset(new BuiltinBug("Receiver in message expression "
- "is an uninitialized value"));
- BT = BT_msg_undef.get();
- }
- else {
- if (!BT_objc_prop_undef)
- BT_objc_prop_undef.reset(new BuiltinBug("Property access on an "
- "uninitialized object pointer"));
- BT = BT_objc_prop_undef.get();
- }
- BugReport *R =
- new BugReport(*BT, BT->getName(), N);
- R->addRange(receiver->getSourceRange());
+ // FIXME: getTrackNullOrUndefValueVisitor can't handle "super" yet.
+ if (const Expr *ReceiverE = msg.getInstanceReceiverExpr())
R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N,
- receiver,
+ ReceiverE,
R));
- C.EmitReport(R);
- }
+ C.EmitReport(R);
+ }
+ return;
+ } else {
+ // Bifurcate the state into nil and non-nil ones.
+ DefinedOrUnknownSVal receiverVal = cast<DefinedOrUnknownSVal>(recVal);
+
+ ProgramStateRef state = C.getState();
+ ProgramStateRef notNilState, nilState;
+ llvm::tie(notNilState, nilState) = state->assume(receiverVal);
+
+ // Handle receiver must be nil.
+ if (nilState && !notNilState) {
+ HandleNilReceiver(C, state, msg);
return;
- } else {
- // Bifurcate the state into nil and non-nil ones.
- DefinedOrUnknownSVal receiverVal = cast<DefinedOrUnknownSVal>(recVal);
-
- ProgramStateRef notNilState, nilState;
- llvm::tie(notNilState, nilState) = state->assume(receiverVal);
-
- // Handle receiver must be nil.
- if (nilState && !notNilState) {
- HandleNilReceiver(C, state, msg);
- return;
- }
}
}
- const char *bugDesc = msg.isPropertySetter() ?
- "Argument for property setter is an uninitialized value"
- : "Argument in message expression is an uninitialized value";
+ const char *bugDesc = "Argument in message expression is an "
+ "uninitialized value";
+ if (const ObjCPropertyAccess *Prop = dyn_cast<ObjCPropertyAccess>(&msg))
+ if (Prop->isSetter())
+ bugDesc = "Argument for property setter is an uninitialized value";
+
// Check for any arguments that are uninitialized/undefined.
- // FIXME: ObjCMessage is set to be removed soon.
- PreVisitProcessArgs(C, ObjCMessageSend(msg.getMessageExpr(), state, LCtx),
- bugDesc, BT_msg_arg);
+ PreVisitProcessArgs(C, msg, bugDesc, BT_msg_arg);
}
void CallAndMessageChecker::emitNilReceiverBug(CheckerContext &C,
- const ObjCMessage &msg,
+ const ObjCMethodCall &msg,
ExplodedNode *N) const {
if (!BT_msg_ret)
@@ -317,11 +312,13 @@ void CallAndMessageChecker::emitNilReceiverBug(CheckerContext &C,
SmallString<200> buf;
llvm::raw_svector_ostream os(buf);
os << "The receiver of message '" << msg.getSelector().getAsString()
- << "' is nil and returns a value of type '"
- << msg.getType(C.getASTContext()).getAsString() << "' that will be garbage";
+ << "' is nil and returns a value of type '";
+ msg.getResultType().print(os, C.getLangOpts());
+ os << "' that will be garbage";
BugReport *report = new BugReport(*BT_msg_ret, os.str(), N);
- if (const Expr *receiver = msg.getInstanceReceiver()) {
+ // FIXME: This won't track "self" in messages to super.
+ if (const Expr *receiver = msg.getInstanceReceiverExpr()) {
report->addRange(receiver->getSourceRange());
report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N,
receiver,
@@ -338,25 +335,25 @@ static bool supportsNilWithFloatRet(const llvm::Triple &triple) {
void CallAndMessageChecker::HandleNilReceiver(CheckerContext &C,
ProgramStateRef state,
- ObjCMessage msg) const {
+ const ObjCMethodCall &Msg) const {
ASTContext &Ctx = C.getASTContext();
// Check the return type of the message expression. A message to nil will
// return different values depending on the return type and the architecture.
- QualType RetTy = msg.getType(Ctx);
+ QualType RetTy = Msg.getResultType();
CanQualType CanRetTy = Ctx.getCanonicalType(RetTy);
const LocationContext *LCtx = C.getLocationContext();
if (CanRetTy->isStructureOrClassType()) {
// Structure returns are safe since the compiler zeroes them out.
- SVal V = C.getSValBuilder().makeZeroVal(msg.getType(Ctx));
- C.addTransition(state->BindExpr(msg.getMessageExpr(), LCtx, V));
+ SVal V = C.getSValBuilder().makeZeroVal(RetTy);
+ C.addTransition(state->BindExpr(Msg.getOriginExpr(), LCtx, V));
return;
}
// Other cases: check if sizeof(return type) > sizeof(void*)
if (CanRetTy != Ctx.VoidTy && C.getLocationContext()->getParentMap()
- .isConsumedExpr(msg.getMessageExpr())) {
+ .isConsumedExpr(Msg.getOriginExpr())) {
// Compute: sizeof(void *) and sizeof(return type)
const uint64_t voidPtrSize = Ctx.getTypeSize(Ctx.VoidPtrTy);
const uint64_t returnTypeSize = Ctx.getTypeSize(CanRetTy);
@@ -369,7 +366,7 @@ void CallAndMessageChecker::HandleNilReceiver(CheckerContext &C,
Ctx.LongLongTy == CanRetTy ||
Ctx.UnsignedLongLongTy == CanRetTy))) {
if (ExplodedNode *N = C.generateSink(state))
- emitNilReceiverBug(C, msg, N);
+ emitNilReceiverBug(C, Msg, N);
return;
}
@@ -386,8 +383,8 @@ void CallAndMessageChecker::HandleNilReceiver(CheckerContext &C,
// it most likely isn't nil. We should assume the semantics
// of this case unless we have *a lot* more knowledge.
//
- SVal V = C.getSValBuilder().makeZeroVal(msg.getType(Ctx));
- C.addTransition(state->BindExpr(msg.getMessageExpr(), LCtx, V));
+ SVal V = C.getSValBuilder().makeZeroVal(RetTy);
+ C.addTransition(state->BindExpr(Msg.getOriginExpr(), LCtx, V));
return;
}
diff --git a/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp b/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
index 61582d028a..751b8f4c89 100644
--- a/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
+++ b/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
@@ -76,10 +76,10 @@ public:
void checkPostStmt(const CallExpr *DS, CheckerContext &C) const;
/// \brief Pre-visit the Objective C messages.
- void checkPreObjCMessage(const ObjCMessage &Msg, CheckerContext &C) const {}
+ void checkPreObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const {}
/// \brief Post-visit the Objective C messages.
- void checkPostObjCMessage(const ObjCMessage &Msg, CheckerContext &C) const {}
+ void checkPostObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const {}
/// \brief Pre-visit of the condition statement of a branch (such as IfStmt).
void checkBranchCondition(const Stmt *Condition, CheckerContext &Ctx) const {}
diff --git a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index 2c960921a4..41cd80e01e 100644
--- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -124,7 +124,7 @@ public:
void checkPreStmt(const CallExpr *S, CheckerContext &C) const;
void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
- void checkPreObjCMessage(const ObjCMessage &Msg, CheckerContext &C) const;
+ void checkPreObjCMessage(const ObjCMethodCall &Call, CheckerContext &C) const;
void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const;
void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
void checkEndPath(CheckerContext &C) const;
@@ -491,29 +491,21 @@ static bool isFreeWhenDoneSetToZero(const ObjCMethodCall &Call) {
return false;
}
-void MallocChecker::checkPreObjCMessage(const ObjCMessage &Msg,
+void MallocChecker::checkPreObjCMessage(const ObjCMethodCall &Call,
CheckerContext &C) const {
- const ObjCMethodDecl *MD = Msg.getMethodDecl();
- if (!MD)
- return;
-
- // FIXME: ObjCMessage is going away soon.
- ObjCMessageSend Call(Msg.getMessageExpr(), C.getState(),
- C.getLocationContext());
- Selector S = Msg.getSelector();
-
// If the first selector is dataWithBytesNoCopy, assume that the memory will
// be released with 'free' by the new object.
// Ex: [NSData dataWithBytesNoCopy:bytes length:10];
// Unless 'freeWhenDone' param set to 0.
// TODO: Check that the memory was allocated with malloc.
+ Selector S = Call.getSelector();
if ((S.getNameForSlot(0) == "dataWithBytesNoCopy" ||
S.getNameForSlot(0) == "initWithBytesNoCopy" ||
S.getNameForSlot(0) == "initWithCharactersNoCopy") &&
!isFreeWhenDoneSetToZero(Call)){
unsigned int argIdx = 0;
C.addTransition(FreeMemAux(C, Call.getArgExpr(argIdx),
- Msg.getMessageExpr(), C.getState(), true));
+ Call.getOriginExpr(), C.getState(), true));
}
}
diff --git a/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp b/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp
index 4989ba8868..bc0835a9ed 100644
--- a/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp
@@ -20,9 +20,9 @@
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/Calls.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Decl.h"
@@ -36,29 +36,20 @@ class NSAutoreleasePoolChecker
mutable Selector releaseS;
public:
- void checkPreObjCMessage(ObjCMessage msg, CheckerContext &C) const;
+ void checkPreObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const;
};
} // end anonymous namespace
-void NSAutoreleasePoolChecker::checkPreObjCMessage(ObjCMessage msg,
+void NSAutoreleasePoolChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
CheckerContext &C) const {
-
- const Expr *receiver = msg.getInstanceReceiver();
- if (!receiver)
+ if (!msg.isInstanceMessage())
return;
-
- // FIXME: Enhance with value-tracking information instead of consulting
- // the type of the expression.
- const ObjCObjectPointerType* PT =
- receiver->getType()->getAs<ObjCObjectPointerType>();
-
- if (!PT)
- return;
- const ObjCInterfaceDecl *OD = PT->getInterfaceDecl();
+
+ const ObjCInterfaceDecl *OD = msg.getReceiverInterface();
if (!OD)
return;
- if (!OD->getIdentifier()->getName().equals("NSAutoreleasePool"))
+ if (!OD->getIdentifier()->isStr("NSAutoreleasePool"))
return;
if (releaseS.isNull())
diff --git a/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp b/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp
index c2d7c09cf3..b3b212f8f4 100644
--- a/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp
@@ -15,8 +15,8 @@
#include "ClangSACheckers.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/Calls.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
#include "llvm/ADT/StringSwitch.h"
#include <cstdarg>
@@ -29,7 +29,7 @@ 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;
+ void checkPostObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const;
};
}
@@ -98,7 +98,7 @@ static bool END_WITH_NULL isMultiArgSelector(const Selector *Sel, ...) {
return (Arg == NULL);
}
-void NoReturnFunctionChecker::checkPostObjCMessage(const ObjCMessage &Msg,
+void NoReturnFunctionChecker::checkPostObjCMessage(const ObjCMethodCall &Msg,
CheckerContext &C) const {
// HACK: This entire check is to handle two messages in the Cocoa frameworks:
// -[NSAssertionHandler
diff --git a/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp b/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp
index f4655b6793..2ab49ed12a 100644
--- a/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp
@@ -21,7 +21,6 @@
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/AST/ParentMap.h"
diff --git a/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp b/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
index c25da87405..40eb381999 100644
--- a/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
@@ -42,7 +42,6 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/Calls.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/AST/ParentMap.h"
@@ -51,7 +50,7 @@ using namespace ento;
static bool shouldRunOnFunctionOrMethod(const NamedDecl *ND);
static bool isInitializationMethod(const ObjCMethodDecl *MD);
-static bool isInitMessage(const ObjCMessage &msg);
+static bool isInitMessage(const ObjCMethodCall &Msg);
static bool isSelfVar(SVal location, CheckerContext &C);
namespace {
@@ -64,8 +63,8 @@ class ObjCSelfInitChecker : public Checker< check::PreObjCMessage,
check::Location,
check::Bind > {
public:
- void checkPreObjCMessage(ObjCMessage msg, CheckerContext &C) const;
- void checkPostObjCMessage(ObjCMessage msg, CheckerContext &C) const;
+ void checkPreObjCMessage(const ObjCMethodCall &Msg, CheckerContext &C) const;
+ void checkPostObjCMessage(const ObjCMethodCall &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;
@@ -184,7 +183,7 @@ static void checkForInvalidSelf(const Expr *E, CheckerContext &C,
C.EmitReport(report);
}
-void ObjCSelfInitChecker::checkPostObjCMessage(ObjCMessage msg,
+void ObjCSelfInitChecker::checkPostObjCMessage(const ObjCMethodCall &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
@@ -195,7 +194,7 @@ void ObjCSelfInitChecker::checkPostObjCMessage(ObjCMessage msg,
C.getCurrentAnalysisDeclContext()->getDecl())))
return;
- if (isInitMessage(msg)) {
+ if (isInitMessage(Msg)) {
// Tag the return value as the result of an initializer.
ProgramStateRef state = C.getState();
@@ -204,15 +203,12 @@ void ObjCSelfInitChecker::checkPostObjCMessage(ObjCMessage msg,
// value out when we return from this method.
state = state->set<CalledInit>(true);
- SVal V = state->getSVal(msg.getMessageExpr(), C.getLocationContext());
+ SVal V = state->getSVal(Msg.getOriginExpr(), C.getLocationContext());
addSelfFlag(state, V, SelfFlag_InitRes, C);
return;
}
- // FIXME: ObjCMessage is going away.
- ObjCMessageSend MsgWrapper(msg.getMessageExpr(), C.getState(),
- C.getLocationContext());
- checkPostStmt(MsgWrapper, C);
+ checkPostStmt(Msg, C);
// We don't check for an invalid 'self' in an obj-c message expression to cut
// down false positives where logging functions get information from self
@@ -300,12 +296,9 @@ void ObjCSelfInitChecker::checkPostStmt(const CallExpr *CE,
}
}
-void ObjCSelfInitChecker::checkPreObjCMessage(ObjCMessage Msg,
+void ObjCSelfInitChecker::checkPreObjCMessage(const ObjCMethodCall &Msg,
CheckerContext &C) const {
- // FIXME: ObjCMessage is going away.
- ObjCMessageSend MsgWrapper(Msg.getMessageExpr(), C.getState(),
- C.getLocationContext());
- checkPreStmt(MsgWrapper, C);
+ checkPreStmt(Msg, C);
}
void ObjCSelfInitChecker::checkPreStmt(const CallEvent &CE,
@@ -440,8 +433,8 @@ static bool isInitializationMethod(const ObjCMethodDecl *MD) {
return MD->getMethodFamily() == OMF_init;
}
-static bool isInitMessage(const ObjCMessage &msg) {
- return msg.getMethodFamily() == OMF_init;
+static bool isInitMessage(const ObjCMethodCall &Call) {
+ return Call.getMethodFamily() == OMF_init;
}
//===----------------------------------------------------------------------===//
diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
index 12b74e7e29..80ebaa2e69 100644
--- a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
@@ -27,7 +27,6 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/ImmutableList.h"
@@ -2530,7 +2529,7 @@ public:
void checkPostStmt(const ObjCDictionaryLiteral *DL, CheckerContext &C) const;
void checkPostStmt(const ObjCBoxedExpr *BE, CheckerContext &C) const;
- void checkPostObjCMessage(const ObjCMessage &Msg, CheckerContext &C) const;
+ void checkPostObjCMessage(const ObjCMethodCall &Msg, CheckerContext &C) const;
void checkSummary(const RetainSummary &Summ, const CallEvent &Call,
CheckerContext &C) const;
@@ -2792,17 +2791,12 @@ void RetainCountChecker::checkPostStmt(const ObjCBoxedExpr *Ex,
C.addTransition(State);
}
-void RetainCountChecker::checkPostObjCMessage(const ObjCMessage &Msg,
+void RetainCountChecker::checkPostObjCMessage(const ObjCMethodCall &Msg,
CheckerContext &C) const {
- ProgramStateRef state = C.getState();
- const LocationContext *LC = C.getLocationContext();
- // FIXME: ObjCMessage is going away.
- ObjCMessageSend Call(Msg.getMessageExpr(), state, LC);
-
RetainSummaryManager &Summaries = getSummaryManager(C);
- const RetainSummary *Summ = Summaries.getSummary(Call, state);
+ const RetainSummary *Summ = Summaries.getSummary(Msg, C.getState());
- checkSummary(*Summ, Call, C);
+ checkSummary(*Summ, Msg, C);
}
/// GetReturnType - Used to get the return type of a message expression or
diff --git a/lib/StaticAnalyzer/Core/Calls.cpp b/lib/StaticAnalyzer/Core/Calls.cpp
index bdd4508cea..4fec757e0e 100644
--- a/lib/StaticAnalyzer/Core/Calls.cpp
+++ b/lib/StaticAnalyzer/Core/Calls.cpp
@@ -14,8 +14,8 @@
//===----------------------------------------------------------------------===//
#include "clang/StaticAnalyzer/Core/PathSensitive/Calls.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/StringExtras.h"
using namespace clang;
using namespace ento;
diff --git a/lib/StaticAnalyzer/Core/CheckerManager.cpp b/lib/StaticAnalyzer/Core/CheckerManager.cpp
index b3d93cfe35..5cb1b49c15 100644
--- a/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ b/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -14,7 +14,7 @@
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/Calls.h"
#include "clang/Analysis/ProgramPoint.h"
#include "clang/AST/DeclBase.h"
@@ -178,14 +178,14 @@ namespace {
typedef std::vector<CheckerManager::CheckObjCMessageFunc> CheckersTy;
bool IsPreVisit;
const CheckersTy &Checkers;
- const ObjCMessage &Msg;
+ const ObjCMethodCall &Msg;
ExprEngine &Eng;
CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
CheckObjCMessageContext(bool isPreVisit, const CheckersTy &checkers,
- const ObjCMessage &msg, ExprEngine &eng)
+ const ObjCMethodCall &msg, ExprEngine &eng)
: IsPreVisit(isPreVisit), Checkers(checkers), Msg(msg), Eng(eng) { }
void runChecker(CheckerManager::CheckObjCMessageFunc checkFn,
@@ -193,7 +193,7 @@ namespace {