]> granicus.if.org Git - clang/commitdiff
Extend -Wnon-pod-varargs to check calls made from function pointers.
authorRichard Trieu <rtrieu@google.com>
Thu, 20 Jun 2013 21:03:13 +0000 (21:03 +0000)
committerRichard Trieu <rtrieu@google.com>
Thu, 20 Jun 2013 21:03:13 +0000 (21:03 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@184470 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Sema/Sema.h
lib/Sema/SemaChecking.cpp
lib/Sema/SemaExpr.cpp
test/SemaCXX/vararg-non-pod.cpp

index 6b719c9b2104dc3da9fea673d835f6af6bbff91a..f45b089e044670fcccf7b69ea383885c0721337f 100644 (file)
@@ -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,
index c6d2362908fe0d33557960c1528feb37ef278da6..729de0d1cd891ce8c4ef44a669cbcbac5da7fec1 100644 (file)
@@ -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,
index 56ece247c6c54f1d3601cfe061edd30ff54bc4a3..d0debba65e4bef92e679d2cab81c29c7c6463d67 100644 (file)
@@ -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();
   }
 
index da06d957180e9f12016c7f079e43c6034fb8caa5..f1ab9b162ce9eb1115828c40da33683236870774 100644 (file)
@@ -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, ...);