summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Trieu <rtrieu@google.com>2013-06-20 21:03:13 +0000
committerRichard Trieu <rtrieu@google.com>2013-06-20 21:03:13 +0000
commit664c4c678b5144b217f2773102adb3bc9ea8734a (patch)
tree838610684ac78e7bc0a50626ac50973cf1783c43
parent05001b9f382c769cfee86e550ee51278b15f0c5f (diff)
downloadbcm5719-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.h4
-rw-r--r--clang/lib/Sema/SemaChecking.cpp16
-rw-r--r--clang/lib/Sema/SemaExpr.cpp2
-rw-r--r--clang/test/SemaCXX/vararg-non-pod.cpp14
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, ...);
OpenPOWER on IntegriCloud