diff options
author | Richard Trieu <rtrieu@google.com> | 2013-06-20 21:03:13 +0000 |
---|---|---|
committer | Richard Trieu <rtrieu@google.com> | 2013-06-20 21:03:13 +0000 |
commit | 664c4c678b5144b217f2773102adb3bc9ea8734a (patch) | |
tree | 838610684ac78e7bc0a50626ac50973cf1783c43 | |
parent | 05001b9f382c769cfee86e550ee51278b15f0c5f (diff) | |
download | bcm5719-llvm-664c4c678b5144b217f2773102adb3bc9ea8734a.tar.gz bcm5719-llvm-664c4c678b5144b217f2773102adb3bc9ea8734a.zip |
Extend -Wnon-pod-varargs to check calls made from function pointers.
llvm-svn: 184470
-rw-r--r-- | clang/include/clang/Sema/Sema.h | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 16 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 2 | ||||
-rw-r--r-- | clang/test/SemaCXX/vararg-non-pod.cpp | 14 |
4 files changed, 27 insertions, 9 deletions
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 6b719c9b210..f45b089e044 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -7461,8 +7461,8 @@ private: const FunctionProtoType *Proto); bool CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation loc, ArrayRef<const Expr *> Args); - bool CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall, - const FunctionProtoType *Proto); + bool CheckPointerCall(NamedDecl *NDecl, CallExpr *TheCall, + const FunctionProtoType *Proto); void CheckConstructorCall(FunctionDecl *FDecl, ArrayRef<const Expr *> Args, const FunctionProtoType *Proto, diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index c6d2362908f..729de0d1cd8 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/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<VarDecl>(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/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 56ece247c6c..d0debba65e4 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/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/clang/test/SemaCXX/vararg-non-pod.cpp b/clang/test/SemaCXX/vararg-non-pod.cpp index da06d957180..f1ab9b162ce 100644 --- a/clang/test/SemaCXX/vararg-non-pod.cpp +++ b/clang/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, ...); |