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:
parent
091dd7be12
commit
41bc0994c3
|
@ -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,
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue