From: Richard Trieu Date: Thu, 20 Jun 2013 21:03:13 +0000 (+0000) Subject: Extend -Wnon-pod-varargs to check calls made from function pointers. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f462b0152f10eed0b989b07bcf457b6fb0d83bdb;p=clang Extend -Wnon-pod-varargs to check calls made from function pointers. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@184470 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 6b719c9b21..f45b089e04 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -7461,8 +7461,8 @@ private: const FunctionProtoType *Proto); bool CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation loc, ArrayRef Args); - bool CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall, - const FunctionProtoType *Proto); + bool CheckPointerCall(NamedDecl *NDecl, CallExpr *TheCall, + const FunctionProtoType *Proto); void CheckConstructorCall(FunctionDecl *FDecl, ArrayRef Args, const FunctionProtoType *Proto, diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index c6d2362908..729de0d1cd 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -597,18 +597,24 @@ bool Sema::CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation lbrac, return false; } -bool Sema::CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall, - const FunctionProtoType *Proto) { +bool Sema::CheckPointerCall(NamedDecl *NDecl, CallExpr *TheCall, + const FunctionProtoType *Proto) { const VarDecl *V = dyn_cast(NDecl); if (!V) return false; QualType Ty = V->getType(); - if (!Ty->isBlockPointerType()) + if (!Ty->isBlockPointerType() && !Ty->isFunctionPointerType()) return false; - VariadicCallType CallType = - Proto && Proto->isVariadic() ? VariadicBlock : VariadicDoesNotApply ; + VariadicCallType CallType; + if (!Proto) { + CallType = VariadicDoesNotApply; + } else if (Ty->isBlockPointerType()) { + CallType = VariadicBlock; + } else { // Ty->isFunctionPointerType() + CallType = VariadicFunction; + } unsigned NumProtoArgs = Proto ? Proto->getNumArgs() : 0; checkCall(NDecl, diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 56ece247c6..d0debba65e 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -4464,7 +4464,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, if (BuiltinID) return CheckBuiltinFunctionCall(BuiltinID, TheCall); } else if (NDecl) { - if (CheckBlockCall(NDecl, TheCall, Proto)) + if (CheckPointerCall(NDecl, TheCall, Proto)) return ExprError(); } diff --git a/test/SemaCXX/vararg-non-pod.cpp b/test/SemaCXX/vararg-non-pod.cpp index da06d95718..f1ab9b162c 100644 --- a/test/SemaCXX/vararg-non-pod.cpp +++ b/test/SemaCXX/vararg-non-pod.cpp @@ -17,6 +17,10 @@ void t1() g(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic function; call will abort at runtime}} g(10, version); + + void (*ptr)(int, ...) = g; + ptr(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic function; call will abort at runtime}} + ptr(10, version); } void t2() @@ -25,9 +29,17 @@ void t2() c.g(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic method; call will abort at runtime}} c.g(10, version); - + + void (C::*ptr)(int, ...) = &C::g; + (c.*ptr)(10, c); // TODO: This should also warn. + (c.*ptr)(10, version); + C::h(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic function; call will abort at runtime}} C::h(10, version); + + void (*static_ptr)(int, ...) = &C::h; + static_ptr(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic function; call will abort at runtime}} + static_ptr(10, version); } int (^block)(int, ...);