Teak CallAndMessageChecker to only warn about uninitialized struct fields in call arguments
when the called function is never inlined. Fixes <rdar://problem/10977037>. llvm-svn: 152073
This commit is contained in:
parent
a5b86343f5
commit
6762a94040
|
@ -44,7 +44,10 @@ private:
|
|||
static void PreVisitProcessArgs(CheckerContext &C,CallOrObjCMessage callOrMsg,
|
||||
const char *BT_desc, OwningPtr<BugType> &BT);
|
||||
static bool PreVisitProcessArg(CheckerContext &C, SVal V,SourceRange argRange,
|
||||
const Expr *argEx, const char *BT_desc, OwningPtr<BugType> &BT);
|
||||
const Expr *argEx,
|
||||
const bool checkUninitFields,
|
||||
const char *BT_desc,
|
||||
OwningPtr<BugType> &BT);
|
||||
|
||||
static void EmitBadCall(BugType *BT, CheckerContext &C, const CallExpr *CE);
|
||||
void emitNilReceiverBug(CheckerContext &C, const ObjCMessage &msg,
|
||||
|
@ -77,9 +80,19 @@ void CallAndMessageChecker::PreVisitProcessArgs(CheckerContext &C,
|
|||
CallOrObjCMessage callOrMsg,
|
||||
const char *BT_desc,
|
||||
OwningPtr<BugType> &BT) {
|
||||
// Don't check for uninitialized field values in arguments if the
|
||||
// caller has a body that is available and we have the chance to inline it.
|
||||
// This is a hack, but is a reasonable compromise betweens sometimes warning
|
||||
// and sometimes not depending on if we decide to inline a function.
|
||||
const Decl *D = callOrMsg.getDecl();
|
||||
const bool checkUninitFields =
|
||||
!(C.getAnalysisManager().shouldInlineCall() &&
|
||||
(D && D->getBody()));
|
||||
|
||||
for (unsigned i = 0, e = callOrMsg.getNumArgs(); i != e; ++i)
|
||||
if (PreVisitProcessArg(C, callOrMsg.getArgSVal(i),
|
||||
callOrMsg.getArgSourceRange(i), callOrMsg.getArg(i),
|
||||
checkUninitFields,
|
||||
BT_desc, BT))
|
||||
return;
|
||||
}
|
||||
|
@ -87,9 +100,9 @@ void CallAndMessageChecker::PreVisitProcessArgs(CheckerContext &C,
|
|||
bool CallAndMessageChecker::PreVisitProcessArg(CheckerContext &C,
|
||||
SVal V, SourceRange argRange,
|
||||
const Expr *argEx,
|
||||
const bool checkUninitFields,
|
||||
const char *BT_desc,
|
||||
OwningPtr<BugType> &BT) {
|
||||
|
||||
if (V.isUndef()) {
|
||||
if (ExplodedNode *N = C.generateSink()) {
|
||||
LazyInit_BT(BT_desc, BT);
|
||||
|
@ -104,6 +117,9 @@ bool CallAndMessageChecker::PreVisitProcessArg(CheckerContext &C,
|
|||
return true;
|
||||
}
|
||||
|
||||
if (!checkUninitFields)
|
||||
return false;
|
||||
|
||||
if (const nonloc::LazyCompoundVal *LV =
|
||||
dyn_cast<nonloc::LazyCompoundVal>(&V)) {
|
||||
|
||||
|
|
|
@ -77,3 +77,16 @@ char *test_return_stack_memory_bad() {
|
|||
return x; // expected-warning {{stack memory associated}}
|
||||
}
|
||||
|
||||
// Test that passing a struct value with an uninitialized field does
|
||||
// not trigger a warning if we are inlining and the body is available.
|
||||
struct rdar10977037 { int x, y; };
|
||||
int test_rdar10977037_aux(struct rdar10977037 v) { return v.y; }
|
||||
int test_rdar10977037_aux_2(struct rdar10977037 v);
|
||||
int test_rdar10977037() {
|
||||
struct rdar10977037 v;
|
||||
v.y = 1;
|
||||
v. y += test_rdar10977037_aux(v); // no-warning
|
||||
return test_rdar10977037_aux_2(v); // expected-warning {{Passed-by-value struct argument contains uninitialized data}}
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue