[cfe-commits] r89524 - in /cfe/trunk: include/clang/Analysis/PathSensitive/GRExprEngine.h lib/Analysis/BadCallChecker.cpp lib/Analysis/CMakeLists.txt lib/Analysis/GRExprEngine.cpp lib/Analysis/GRExprEngineInternalChecks.cpp lib/Analysis/GRExprEngineInternalChecks.h lib/Analysis/UndefinedArgChecker.cpp test/Analysis/uninit-msg-expr.m test/Analysis/uninit-ps-rdar6145427.m
Ted Kremenek
kremenek at apple.com
Fri Nov 20 17:25:38 PST 2009
Author: kremenek
Date: Fri Nov 20 19:25:37 2009
New Revision: 89524
URL: http://llvm.org/viewvc/llvm-project?rev=89524&view=rev
Log:
Pull BadCallChecker int UndefinedArgChecker, and have UndefinedArgChecker also handled undefined receivers in message expressions.
Removed:
cfe/trunk/lib/Analysis/BadCallChecker.cpp
Modified:
cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h
cfe/trunk/lib/Analysis/CMakeLists.txt
cfe/trunk/lib/Analysis/GRExprEngine.cpp
cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp
cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.h
cfe/trunk/lib/Analysis/UndefinedArgChecker.cpp
cfe/trunk/test/Analysis/uninit-msg-expr.m
cfe/trunk/test/Analysis/uninit-ps-rdar6145427.m
Modified: cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h?rev=89524&r1=89523&r2=89524&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h Fri Nov 20 19:25:37 2009
@@ -126,10 +126,6 @@
/// by the result is not. Excludes divide-by-zero errors.
ErrorNodes UndefResults;
- /// UndefReceiver - Nodes in the ExplodedGraph resulting from message
- /// ObjC message expressions where the receiver is undefined (uninitialized).
- ErrorNodes UndefReceivers;
-
public:
GRExprEngine(AnalysisManager &mgr);
@@ -223,16 +219,6 @@
undef_result_iterator undef_results_begin() { return UndefResults.begin(); }
undef_result_iterator undef_results_end() { return UndefResults.end(); }
- typedef ErrorNodes::iterator undef_receivers_iterator;
-
- undef_receivers_iterator undef_receivers_begin() {
- return UndefReceivers.begin();
- }
-
- undef_receivers_iterator undef_receivers_end() {
- return UndefReceivers.end();
- }
-
void AddCheck(GRSimpleAPICheck* A, Stmt::StmtClass C);
void AddCheck(GRSimpleAPICheck* A);
Removed: cfe/trunk/lib/Analysis/BadCallChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/BadCallChecker.cpp?rev=89523&view=auto
==============================================================================
--- cfe/trunk/lib/Analysis/BadCallChecker.cpp (original)
+++ cfe/trunk/lib/Analysis/BadCallChecker.cpp (removed)
@@ -1,57 +0,0 @@
-//===--- BadCallChecker.h - Bad call checker --------------------*- C++ -*--==//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This defines BadCallChecker, a builtin check in GRExprEngine that performs
-// checks for bad callee at call sites.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
-#include "clang/Analysis/PathSensitive/BugReporter.h"
-#include "GRExprEngineInternalChecks.h"
-
-using namespace clang;
-
-namespace {
-class VISIBILITY_HIDDEN BadCallChecker : public CheckerVisitor<BadCallChecker> {
- BuiltinBug *BT;
-public:
- BadCallChecker() : BT(0) {}
- static void *getTag() {
- static int x = 0;
- return &x;
- }
- void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
-};
-} // end anonymous namespace
-
-void clang::RegisterBadCallChecker(GRExprEngine &Eng) {
- Eng.registerCheck(new BadCallChecker());
-}
-
-void BadCallChecker::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
- const Expr *Callee = CE->getCallee()->IgnoreParens();
- SVal L = C.getState()->getSVal(Callee);
-
- if (L.isUndef() || isa<loc::ConcreteInt>(L)) {
- if (ExplodedNode *N = C.GenerateNode(CE, true)) {
- if (!BT)
- BT = new BuiltinBug("Invalid function call",
- "Called function pointer is a null or undefined pointer value");
-
- EnhancedBugReport *R =
- new EnhancedBugReport(*BT, BT->getDescription(), N);
-
- R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
- bugreporter::GetCalleeExpr(N));
-
- C.EmitReport(R);
- }
- }
-}
Modified: cfe/trunk/lib/Analysis/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CMakeLists.txt?rev=89524&r1=89523&r2=89524&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/CMakeLists.txt (original)
+++ cfe/trunk/lib/Analysis/CMakeLists.txt Fri Nov 20 19:25:37 2009
@@ -4,7 +4,6 @@
AnalysisContext.cpp
ArrayBoundChecker.cpp
AttrNonNullChecker.cpp
- BadCallChecker.cpp
BasicConstraintManager.cpp
BasicObjCFoundationChecks.cpp
BasicStore.cpp
Modified: cfe/trunk/lib/Analysis/GRExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngine.cpp?rev=89524&r1=89523&r2=89524&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngine.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngine.cpp Fri Nov 20 19:25:37 2009
@@ -1850,177 +1850,164 @@
ExplodedNode* Pred,
ExplodedNodeSet& Dst) {
- // FIXME: More logic for the processing the method call.
-
- const GRState* state = GetState(Pred);
- bool RaisesException = false;
+ // Handle previsits checks.
+ ExplodedNodeSet Src, DstTmp;
+ Src.Add(Pred);
+ CheckerVisit(ME, DstTmp, Src, true);
+
+ unsigned size = Dst.size();
+ for (ExplodedNodeSet::iterator DI = DstTmp.begin(), DE = DstTmp.end();
+ DI!=DE; ++DI) {
+ Pred = *DI;
+ // FIXME: More logic for the processing the method call.
+ const GRState* state = GetState(Pred);
+ bool RaisesException = false;
- if (Expr* Receiver = ME->getReceiver()) {
+ if (Expr* Receiver = ME->getReceiver()) {
+ SVal L_untested = state->getSVal(Receiver);
- SVal L_untested = state->getSVal(Receiver);
+ // "Assume" that the receiver is not NULL.
+ DefinedOrUnknownSVal L = cast<DefinedOrUnknownSVal>(L_untested);
+ const GRState *StNotNull = state->Assume(L, true);
- // Check for undefined control-flow.
- if (L_untested.isUndef()) {
- ExplodedNode* N = Builder->generateNode(ME, state, Pred);
+ // "Assume" that the receiver is NULL.
+ const GRState *StNull = state->Assume(L, false);
- if (N) {
- N->markAsSink();
- UndefReceivers.insert(N);
- }
+ if (StNull) {
+ QualType RetTy = ME->getType();
- return;
- }
-
- // "Assume" that the receiver is not NULL.
- DefinedOrUnknownSVal L = cast<DefinedOrUnknownSVal>(L_untested);
- const GRState *StNotNull = state->Assume(L, true);
-
- // "Assume" that the receiver is NULL.
- const GRState *StNull = state->Assume(L, false);
-
- if (StNull) {
- QualType RetTy = ME->getType();
-
- // Check if the receiver was nil and the return value a struct.
- if (RetTy->isRecordType()) {
- if (Pred->getParentMap().isConsumedExpr(ME)) {
- // The [0 ...] expressions will return garbage. Flag either an
- // explicit or implicit error. Because of the structure of this
- // function we currently do not bifurfacte the state graph at
- // this point.
- // FIXME: We should bifurcate and fill the returned struct with
- // garbage.
- if (ExplodedNode* N = Builder->generateNode(ME, StNull, Pred)) {
- N->markAsSink();
- if (StNotNull)
- NilReceiverStructRetImplicit.insert(N);
- else
- NilReceiverStructRetExplicit.insert(N);
+ // Check if the receiver was nil and the return value a struct.
+ if (RetTy->isRecordType()) {
+ if (Pred->getParentMap().isConsumedExpr(ME)) {
+ // The [0 ...] expressions will return garbage. Flag either an
+ // explicit or implicit error. Because of the structure of this
+ // function we currently do not bifurfacte the state graph at
+ // this point.
+ // FIXME: We should bifurcate and fill the returned struct with
+ // garbage.
+ if (ExplodedNode* N = Builder->generateNode(ME, StNull, Pred)) {
+ N->markAsSink();
+ if (StNotNull)
+ NilReceiverStructRetImplicit.insert(N);
+ else
+ NilReceiverStructRetExplicit.insert(N);
+ }
}
}
- }
- else {
- ASTContext& Ctx = getContext();
- if (RetTy != Ctx.VoidTy) {
- if (Pred->getParentMap().isConsumedExpr(ME)) {
- // sizeof(void *)
- const uint64_t voidPtrSize = Ctx.getTypeSize(Ctx.VoidPtrTy);
- // sizeof(return type)
- const uint64_t returnTypeSize = Ctx.getTypeSize(ME->getType());
-
- if (voidPtrSize < returnTypeSize) {
- if (ExplodedNode* N = Builder->generateNode(ME, StNull, Pred)) {
- N->markAsSink();
- if (StNotNull)
- NilReceiverLargerThanVoidPtrRetImplicit.insert(N);
- else
- NilReceiverLargerThanVoidPtrRetExplicit.insert(N);
+ else {
+ ASTContext& Ctx = getContext();
+ if (RetTy != Ctx.VoidTy) {
+ if (Pred->getParentMap().isConsumedExpr(ME)) {
+ // sizeof(void *)
+ const uint64_t voidPtrSize = Ctx.getTypeSize(Ctx.VoidPtrTy);
+ // sizeof(return type)
+ const uint64_t returnTypeSize = Ctx.getTypeSize(ME->getType());
+
+ if (voidPtrSize < returnTypeSize) {
+ if (ExplodedNode* N = Builder->generateNode(ME, StNull, Pred)) {
+ N->markAsSink();
+ if (StNotNull)
+ NilReceiverLargerThanVoidPtrRetImplicit.insert(N);
+ else
+ NilReceiverLargerThanVoidPtrRetExplicit.insert(N);
+ }
+ }
+ else if (!StNotNull) {
+ // Handle the safe cases where the return value is 0 if the
+ // receiver is nil.
+ //
+ // FIXME: For now take the conservative approach that we only
+ // return null values if we *know* that the receiver is nil.
+ // This is because we can have surprises like:
+ //
+ // ... = [[NSScreens screens] objectAtIndex:0];
+ //
+ // What can happen is that [... screens] could return nil, but
+ // it most likely isn't nil. We should assume the semantics
+ // of this case unless we have *a lot* more knowledge.
+ //
+ SVal V = ValMgr.makeZeroVal(ME->getType());
+ MakeNode(Dst, ME, Pred, StNull->BindExpr(ME, V));
+ return;
}
- }
- else if (!StNotNull) {
- // Handle the safe cases where the return value is 0 if the
- // receiver is nil.
- //
- // FIXME: For now take the conservative approach that we only
- // return null values if we *know* that the receiver is nil.
- // This is because we can have surprises like:
- //
- // ... = [[NSScreens screens] objectAtIndex:0];
- //
- // What can happen is that [... screens] could return nil, but
- // it most likely isn't nil. We should assume the semantics
- // of this case unless we have *a lot* more knowledge.
- //
- SVal V = ValMgr.makeZeroVal(ME->getType());
- MakeNode(Dst, ME, Pred, StNull->BindExpr(ME, V));
- return;
}
}
}
+ // We have handled the cases where the receiver is nil. The remainder
+ // of this method should assume that the receiver is not nil.
+ if (!StNotNull)
+ return;
+
+ state = StNotNull;
}
- // We have handled the cases where the receiver is nil. The remainder
- // of this method should assume that the receiver is not nil.
- if (!StNotNull)
- return;
- state = StNotNull;
+ // Check if the "raise" message was sent.
+ if (ME->getSelector() == RaiseSel)
+ RaisesException = true;
}
+ else {
- // Check if the "raise" message was sent.
- if (ME->getSelector() == RaiseSel)
- RaisesException = true;
- }
- else {
-
- IdentifierInfo* ClsName = ME->getClassName();
- Selector S = ME->getSelector();
+ IdentifierInfo* ClsName = ME->getClassName();
+ Selector S = ME->getSelector();
- // Check for special instance methods.
+ // Check for special instance methods.
- if (!NSExceptionII) {
- ASTContext& Ctx = getContext();
+ if (!NSExceptionII) {
+ ASTContext& Ctx = getContext();
- NSExceptionII = &Ctx.Idents.get("NSException");
- }
+ NSExceptionII = &Ctx.Idents.get("NSException");
+ }
- if (ClsName == NSExceptionII) {
+ if (ClsName == NSExceptionII) {
- enum { NUM_RAISE_SELECTORS = 2 };
+ enum { NUM_RAISE_SELECTORS = 2 };
- // Lazily create a cache of the selectors.
+ // Lazily create a cache of the selectors.
- if (!NSExceptionInstanceRaiseSelectors) {
+ if (!NSExceptionInstanceRaiseSelectors) {
- ASTContext& Ctx = getContext();
+ ASTContext& Ctx = getContext();
- NSExceptionInstanceRaiseSelectors = new Selector[NUM_RAISE_SELECTORS];
+ NSExceptionInstanceRaiseSelectors = new Selector[NUM_RAISE_SELECTORS];
- llvm::SmallVector<IdentifierInfo*, NUM_RAISE_SELECTORS> II;
- unsigned idx = 0;
+ llvm::SmallVector<IdentifierInfo*, NUM_RAISE_SELECTORS> II;
+ unsigned idx = 0;
- // raise:format:
- II.push_back(&Ctx.Idents.get("raise"));
- II.push_back(&Ctx.Idents.get("format"));
- NSExceptionInstanceRaiseSelectors[idx++] =
- Ctx.Selectors.getSelector(II.size(), &II[0]);
-
- // raise:format::arguments:
- II.push_back(&Ctx.Idents.get("arguments"));
- NSExceptionInstanceRaiseSelectors[idx++] =
- Ctx.Selectors.getSelector(II.size(), &II[0]);
- }
+ // raise:format:
+ II.push_back(&Ctx.Idents.get("raise"));
+ II.push_back(&Ctx.Idents.get("format"));
+ NSExceptionInstanceRaiseSelectors[idx++] =
+ Ctx.Selectors.getSelector(II.size(), &II[0]);
- for (unsigned i = 0; i < NUM_RAISE_SELECTORS; ++i)
- if (S == NSExceptionInstanceRaiseSelectors[i]) {
- RaisesException = true; break;
+ // raise:format::arguments:
+ II.push_back(&Ctx.Idents.get("arguments"));
+ NSExceptionInstanceRaiseSelectors[idx++] =
+ Ctx.Selectors.getSelector(II.size(), &II[0]);
}
+
+ for (unsigned i = 0; i < NUM_RAISE_SELECTORS; ++i)
+ if (S == NSExceptionInstanceRaiseSelectors[i]) {
+ RaisesException = true; break;
+ }
+ }
}
- }
- // Handle previsits checks.
- ExplodedNodeSet Src, DstTmp;
- Src.Add(Pred);
- CheckerVisit(ME, DstTmp, Src, true);
-
- // Check if we raise an exception. For now treat these as sinks. Eventually
- // we will want to handle exceptions properly.
- SaveAndRestore<bool> OldSink(Builder->BuildSinks);
- if (RaisesException)
- Builder->BuildSinks = true;
+ // Check if we raise an exception. For now treat these as sinks. Eventually
+ // we will want to handle exceptions properly.
+ SaveAndRestore<bool> OldSink(Builder->BuildSinks);
+ if (RaisesException)
+ Builder->BuildSinks = true;
- // Dispatch to plug-in transfer function.
- unsigned size = Dst.size();
- SaveOr OldHasGen(Builder->HasGeneratedNode);
-
- for (ExplodedNodeSet::iterator DI = DstTmp.begin(), DE = DstTmp.end();
- DI!=DE; ++DI)
- EvalObjCMessageExpr(Dst, ME, *DI);
+ // Dispatch to plug-in transfer function.
+ SaveOr OldHasGen(Builder->HasGeneratedNode);
+ EvalObjCMessageExpr(Dst, ME, Pred);
+ }
// Handle the case where no nodes where generated. Auto-generate that
// contains the updated state if we aren't generating sinks.
if (!Builder->BuildSinks && Dst.size() == size && !Builder->HasGeneratedNode)
- MakeNode(Dst, ME, Pred, state);
+ MakeNode(Dst, ME, Pred, GetState(Pred));
}
//===----------------------------------------------------------------------===//
Modified: cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp?rev=89524&r1=89523&r2=89524&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp Fri Nov 20 19:25:37 2009
@@ -219,34 +219,6 @@
const Stmt *getArg() const { return Arg; }
};
-class VISIBILITY_HIDDEN BadReceiver : public BuiltinBug {
-public:
- BadReceiver(GRExprEngine* eng)
- : BuiltinBug(eng,"Uninitialized receiver",
- "Receiver in message expression is an uninitialized value") {}
-
- void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
- for (GRExprEngine::ErrorNodes::iterator I=Eng.undef_receivers_begin(),
- End = Eng.undef_receivers_end(); I!=End; ++I) {
-
- // Generate a report for this bug.
- BuiltinBugReport *report = new BuiltinBugReport(*this, desc.c_str(), *I);
- ExplodedNode* N = *I;
- const Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
- const Expr* E = cast<ObjCMessageExpr>(S)->getReceiver();
- assert (E && "Receiver cannot be NULL");
- report->addRange(E->getSourceRange());
- BR.EmitReport(report);
- }
- }
-
- void registerInitialVisitors(BugReporterContext& BRC,
- const ExplodedNode* N,
- BuiltinBugReport *R) {
- registerTrackNullOrUndefValue(BRC, GetReceiverExpr(N), N);
- }
-};
-
class VISIBILITY_HIDDEN UndefBranch : public BuiltinBug {
struct VISIBILITY_HIDDEN FindUndefExpr {
GRStateManager& VM;
@@ -337,7 +309,6 @@
// to 'FlushReports' from BugReporter.
BR.Register(new UndefBranch(this));
BR.Register(new UndefResult(this));
- BR.Register(new BadReceiver(this));
BR.Register(new NilReceiverStructRet(this));
BR.Register(new NilReceiverLargerThanVoidPtrRet(this));
@@ -350,7 +321,6 @@
RegisterAttrNonNullChecker(*this);
RegisterUndefinedArgChecker(*this);
- RegisterBadCallChecker(*this);
RegisterDereferenceChecker(*this);
RegisterVLASizeChecker(*this);
RegisterDivZeroChecker(*this);
Modified: cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.h?rev=89524&r1=89523&r2=89524&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.h (original)
+++ cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.h Fri Nov 20 19:25:37 2009
@@ -20,7 +20,6 @@
class GRExprEngine;
void RegisterAttrNonNullChecker(GRExprEngine &Eng);
-void RegisterBadCallChecker(GRExprEngine &Eng);
void RegisterDereferenceChecker(GRExprEngine &Eng);
void RegisterDivZeroChecker(GRExprEngine &Eng);
void RegisterReturnPointerRangeChecker(GRExprEngine &Eng);
Modified: cfe/trunk/lib/Analysis/UndefinedArgChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/UndefinedArgChecker.cpp?rev=89524&r1=89523&r2=89524&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/UndefinedArgChecker.cpp (original)
+++ cfe/trunk/lib/Analysis/UndefinedArgChecker.cpp Fri Nov 20 19:25:37 2009
@@ -21,16 +21,23 @@
namespace {
class VISIBILITY_HIDDEN UndefinedArgChecker
: public CheckerVisitor<UndefinedArgChecker> {
- BugType *BT_call;
- BugType *BT_msg;
+ BugType *BT_call_null;
+ BugType *BT_call_undef;
+ BugType *BT_call_arg;
+ BugType *BT_msg_undef;
+ BugType *BT_msg_arg;
public:
- UndefinedArgChecker() : BT_call(0), BT_msg(0) {}
+ UndefinedArgChecker() :
+ BT_call_null(0), BT_call_undef(0), BT_call_arg(0),
+ BT_msg_undef(0), BT_msg_arg(0) {}
static void *getTag() {
static int x = 0;
return &x;
}
void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
void PreVisitObjCMessageExpr(CheckerContext &C, const ObjCMessageExpr *ME);
+private:
+ void EmitBadCall(BugType *BT, CheckerContext &C, const CallExpr *CE);
};
} // end anonymous namespace
@@ -38,18 +45,49 @@
Eng.registerCheck(new UndefinedArgChecker());
}
+void UndefinedArgChecker::EmitBadCall(BugType *BT, CheckerContext &C,
+ const CallExpr *CE) {
+ ExplodedNode *N = C.GenerateNode(CE, true);
+ if (!N)
+ return;
+
+ EnhancedBugReport *R = new EnhancedBugReport(*BT, BT->getName(), N);
+ R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
+ bugreporter::GetCalleeExpr(N));
+ C.EmitReport(R);
+}
+
void UndefinedArgChecker::PreVisitCallExpr(CheckerContext &C,
const CallExpr *CE){
+
+ const Expr *Callee = CE->getCallee()->IgnoreParens();
+ SVal L = C.getState()->getSVal(Callee);
+
+ if (L.isUndef()) {
+ if (!BT_call_undef)
+ BT_call_undef =
+ new BuiltinBug("Called function pointer is an undefined pointer value");
+ EmitBadCall(BT_call_undef, C, CE);
+ return;
+ }
+
+ if (isa<loc::ConcreteInt>(L)) {
+ if (!BT_call_null)
+ BT_call_null =
+ new BuiltinBug("Called function pointer is null (null dereference)");
+ EmitBadCall(BT_call_null, C, CE);
+ }
+
for (CallExpr::const_arg_iterator I = CE->arg_begin(), E = CE->arg_end();
I != E; ++I) {
if (C.getState()->getSVal(*I).isUndef()) {
if (ExplodedNode *N = C.GenerateNode(CE, true)) {
- if (!BT_call)
- BT_call = new BuiltinBug("Pass-by-value argument in function call is "
- "undefined");
+ if (!BT_call_arg)
+ BT_call_arg = new BuiltinBug("Pass-by-value argument in function call"
+ " is undefined");
// Generate a report for this bug.
- EnhancedBugReport *R = new EnhancedBugReport(*BT_call,
- BT_call->getName(), N);
+ EnhancedBugReport *R = new EnhancedBugReport(*BT_call_arg,
+ BT_call_arg->getName(), N);
R->addRange((*I)->getSourceRange());
R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, *I);
C.EmitReport(R);
@@ -62,18 +100,36 @@
void UndefinedArgChecker::PreVisitObjCMessageExpr(CheckerContext &C,
const ObjCMessageExpr *ME) {
- // Check for any arguments that are uninitialized/undefined.
const GRState *state = C.getState();
+
+ if (const Expr *receiver = ME->getReceiver())
+ if (state->getSVal(receiver).isUndef()) {
+ if (ExplodedNode *N = C.GenerateNode(ME, true)) {
+ if (!BT_msg_undef)
+ BT_msg_undef =
+ new BuiltinBug("Receiver in message expression is a garbage value");
+ EnhancedBugReport *R =
+ new EnhancedBugReport(*BT_msg_undef, BT_msg_undef->getName(), N);
+ R->addRange(receiver->getSourceRange());
+ R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
+ receiver);
+ C.EmitReport(R);
+ }
+ return;
+ }
+
+ // Check for any arguments that are uninitialized/undefined.
for (ObjCMessageExpr::const_arg_iterator I = ME->arg_begin(), E = ME->arg_end();
I != E; ++I) {
if (state->getSVal(*I).isUndef()) {
if (ExplodedNode *N = C.GenerateNode(ME, true)) {
- if (!BT_msg)
- BT_msg = new BuiltinBug("Pass-by-value argument in message expression"
- " is undefined");
+ if (!BT_msg_arg)
+ BT_msg_arg =
+ new BuiltinBug("Pass-by-value argument in message expression"
+ " is undefined");
// Generate a report for this bug.
- EnhancedBugReport *R = new EnhancedBugReport(*BT_msg, BT_msg->getName(),
- N);
+ EnhancedBugReport *R = new EnhancedBugReport(*BT_msg_arg,
+ BT_msg_arg->getName(), N);
R->addRange((*I)->getSourceRange());
R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, *I);
C.EmitReport(R);
Modified: cfe/trunk/test/Analysis/uninit-msg-expr.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/uninit-msg-expr.m?rev=89524&r1=89523&r2=89524&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/uninit-msg-expr.m (original)
+++ cfe/trunk/test/Analysis/uninit-msg-expr.m Fri Nov 20 19:25:37 2009
@@ -42,7 +42,7 @@
unsigned f1() {
NSString *aString;
- return [aString length]; // expected-warning {{Receiver in message expression is an uninitialized value}}
+ return [aString length]; // expected-warning {{Receiver in message expression is a garbage value}}
}
unsigned f2() {
Modified: cfe/trunk/test/Analysis/uninit-ps-rdar6145427.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/uninit-ps-rdar6145427.m?rev=89524&r1=89523&r2=89524&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/uninit-ps-rdar6145427.m (original)
+++ cfe/trunk/test/Analysis/uninit-ps-rdar6145427.m Fri Nov 20 19:25:37 2009
@@ -30,7 +30,7 @@
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
- id someUnintializedPointer = [someUnintializedPointer objectAtIndex:0]; // expected-warning{{Receiver in message expression is an uninitialized value.}}
+ id someUnintializedPointer = [someUnintializedPointer objectAtIndex:0]; // expected-warning{{Receiver in message expression is a garbage value}}
NSLog(@"%@", someUnintializedPointer);
[pool drain];
return 0;
More information about the cfe-commits
mailing list