Extend -Wnon-pod-varargs to more cases, such as function pointers as return

types and function pointer arrays.

llvm-svn: 184616
This commit is contained in:
Richard Trieu 2013-06-22 00:20:41 +00:00
parent 091dd7be12
commit 41bc0994c3
4 changed files with 76 additions and 14 deletions

View File

@ -7463,6 +7463,7 @@ private:
ArrayRef<const Expr *> Args);
bool CheckPointerCall(NamedDecl *NDecl, CallExpr *TheCall,
const FunctionProtoType *Proto);
bool CheckOtherCall(CallExpr *TheCall, const FunctionProtoType *Proto);
void CheckConstructorCall(FunctionDecl *FDecl,
ArrayRef<const Expr *> Args,
const FunctionProtoType *Proto,

View File

@ -499,11 +499,13 @@ void Sema::checkCall(NamedDecl *FDecl,
// Printf and scanf checking.
bool HandledFormatString = false;
for (specific_attr_iterator<FormatAttr>
I = FDecl->specific_attr_begin<FormatAttr>(),
E = FDecl->specific_attr_end<FormatAttr>(); I != E ; ++I)
if (CheckFormatArguments(*I, Args, IsMemberFunction, CallType, Loc, Range))
HandledFormatString = true;
if (FDecl)
for (specific_attr_iterator<FormatAttr>
I = FDecl->specific_attr_begin<FormatAttr>(),
E = FDecl->specific_attr_end<FormatAttr>(); I != E ; ++I)
if (CheckFormatArguments(*I, Args, IsMemberFunction, CallType, Loc,
Range))
HandledFormatString = true;
// Refuse POD arguments that weren't caught by the format string
// checks above.
@ -514,16 +516,19 @@ void Sema::checkCall(NamedDecl *FDecl,
variadicArgumentPODCheck(Arg, CallType);
}
for (specific_attr_iterator<NonNullAttr>
I = FDecl->specific_attr_begin<NonNullAttr>(),
E = FDecl->specific_attr_end<NonNullAttr>(); I != E; ++I)
CheckNonNullArguments(*I, Args.data(), Loc);
if (FDecl) {
for (specific_attr_iterator<NonNullAttr>
I = FDecl->specific_attr_begin<NonNullAttr>(),
E = FDecl->specific_attr_end<NonNullAttr>(); I != E; ++I)
CheckNonNullArguments(*I, Args.data(), Loc);
// Type safety checking.
for (specific_attr_iterator<ArgumentWithTypeTagAttr>
i = FDecl->specific_attr_begin<ArgumentWithTypeTagAttr>(),
e = FDecl->specific_attr_end<ArgumentWithTypeTagAttr>(); i != e; ++i) {
CheckArgumentWithTypeTag(*i, Args.data());
// Type safety checking.
for (specific_attr_iterator<ArgumentWithTypeTagAttr>
i = FDecl->specific_attr_begin<ArgumentWithTypeTagAttr>(),
e = FDecl->specific_attr_end<ArgumentWithTypeTagAttr>();
i != e; ++i) {
CheckArgumentWithTypeTag(*i, Args.data());
}
}
}
@ -627,6 +632,23 @@ bool Sema::CheckPointerCall(NamedDecl *NDecl, CallExpr *TheCall,
return false;
}
/// Checks function calls when a FunctionDecl or a NamedDecl is not available,
/// such as function pointers returned from functions.
bool Sema::CheckOtherCall(CallExpr *TheCall, const FunctionProtoType *Proto) {
VariadicCallType CallType = getVariadicCallType(/*FDecl=*/0, Proto,
TheCall->getCallee());
unsigned NumProtoArgs = Proto ? Proto->getNumArgs() : 0;
checkCall(/*FDecl=*/0,
llvm::makeArrayRef<const Expr *>(TheCall->getArgs(),
TheCall->getNumArgs()),
NumProtoArgs, /*IsMemberFunction=*/false,
TheCall->getRParenLoc(),
TheCall->getCallee()->getSourceRange(), CallType);
return false;
}
ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
AtomicExpr::AtomicOp Op) {
CallExpr *TheCall = cast<CallExpr>(TheCallResult.get());

View File

@ -4466,6 +4466,9 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
} else if (NDecl) {
if (CheckPointerCall(NDecl, TheCall, Proto))
return ExprError();
} else {
if (CheckOtherCall(TheCall, Proto))
return ExprError();
}
return MaybeBindToTemporary(TheCall);

View File

@ -153,3 +153,39 @@ namespace t10 {
s(f);
}
}
namespace t11 {
typedef void(*function_ptr)(int, ...);
typedef void(C::*member_ptr)(int, ...);
typedef void(^block_ptr)(int, ...);
function_ptr get_f_ptr();
member_ptr get_m_ptr();
block_ptr get_b_ptr();
function_ptr arr_f_ptr[5];
member_ptr arr_m_ptr[5];
block_ptr arr_b_ptr[5];
void test() {
C c(10);
(get_f_ptr())(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic function; call will abort at runtime}}
(get_f_ptr())(10, version);
(c.*get_m_ptr())(10, c); // TODO: This should also warn.
(c.*get_m_ptr())(10, version);
(get_b_ptr())(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic block; call will abort at runtime}}
(get_b_ptr())(10, version);
(arr_f_ptr[3])(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic function; call will abort at runtime}}
(arr_f_ptr[3])(10, version);
(c.*arr_m_ptr[3])(10, c); // TODO: This should also warn.
(c.*arr_m_ptr[3])(10, version);
(arr_b_ptr[3])(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic block; call will abort at runtime}}
(arr_b_ptr[3])(10, version);
}
}