r184616 - Extend -Wnon-pod-varargs to more cases, such as function pointers as return

Richard Trieu rtrieu at google.com
Fri Jun 21 17:20:42 PDT 2013


Author: rtrieu
Date: Fri Jun 21 19:20:41 2013
New Revision: 184616

URL: http://llvm.org/viewvc/llvm-project?rev=184616&view=rev
Log:
Extend -Wnon-pod-varargs to more cases, such as function pointers as return
types and function pointer arrays.

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

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=184616&r1=184615&r2=184616&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Fri Jun 21 19:20:41 2013
@@ -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,

Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=184616&r1=184615&r2=184616&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Fri Jun 21 19:20:41 2013
@@ -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);
-
-  // 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());
+  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());
+    }
   }
 }
 
@@ -627,6 +632,23 @@ bool Sema::CheckPointerCall(NamedDecl *N
   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());

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=184616&r1=184615&r2=184616&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Jun 21 19:20:41 2013
@@ -4466,6 +4466,9 @@ Sema::BuildResolvedCallExpr(Expr *Fn, Na
   } else if (NDecl) {
     if (CheckPointerCall(NDecl, TheCall, Proto))
       return ExprError();
+  } else {
+    if (CheckOtherCall(TheCall, Proto))
+      return ExprError();
   }
 
   return MaybeBindToTemporary(TheCall);

Modified: cfe/trunk/test/SemaCXX/vararg-non-pod.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/vararg-non-pod.cpp?rev=184616&r1=184615&r2=184616&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/vararg-non-pod.cpp (original)
+++ cfe/trunk/test/SemaCXX/vararg-non-pod.cpp Fri Jun 21 19:20:41 2013
@@ -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);
+  }
+}





More information about the cfe-commits mailing list