]> granicus.if.org Git - clang/commitdiff
Warn when someone tries to pass a variable with a non-POD type to a varargs function...
authorAnders Carlsson <andersca@mac.com>
Tue, 13 Jan 2009 05:48:52 +0000 (05:48 +0000)
committerAnders Carlsson <andersca@mac.com>
Tue, 13 Jan 2009 05:48:52 +0000 (05:48 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@62148 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticKinds.def
lib/Sema/SemaExpr.cpp
lib/Sema/SemaExprObjC.cpp
lib/Sema/SemaOverload.cpp
test/SemaCXX/vararg-non-pod.cpp [new file with mode: 0644]
test/SemaObjCXX/vararg-non-pod.mm [new file with mode: 0644]

index ee0cad4d13f966451a5d367087a957e0e2d7de5a..a9f60d2d630675a08e8ce6b187d927837ef33bc6 100644 (file)
@@ -1410,6 +1410,9 @@ DIAG(err_typecheck_call_too_few_args, ERROR,
      "too few arguments to %select{function|block|method}0 call")
 DIAG(err_typecheck_call_too_many_args, ERROR,
      "too many arguments to %select{function|block|method}0 call")
+DIAG(warn_cannot_pass_non_pod_arg_to_vararg, WARNING,
+     "cannot pass object of non-POD type %0 through variadic "
+     "%select{function|block|method}1; call will abort at runtime")
 DIAG(err_typecheck_closure_too_many_args, ERROR,
      "too many arguments to closure call")
 DIAG(err_typecheck_call_invalid_ordered_compare, ERROR,
index d3d3d3556c40150af32319feec3ffe5db48a7127..2721bb8dc60f8d23148b2b08a93703223f0e49d4 100644 (file)
@@ -1688,6 +1688,17 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
     // Promote the arguments (C99 6.5.2.2p7).
     for (unsigned i = NumArgsInProto; i != NumArgs; i++) {
       Expr *Arg = Args[i];
+      if (!Arg->getType()->isPODType()) {
+        int CallType = 0;
+        if (Fn->getType()->isBlockPointerType())
+          CallType = 1; // Block
+        else if (isa<MemberExpr>(Fn))
+          CallType = 2;
+        
+        Diag(Arg->getLocStart(), 
+             diag::warn_cannot_pass_non_pod_arg_to_vararg) << 
+        Arg->getType() << CallType;
+      }
       DefaultArgumentPromotion(Arg);
       Call->setArg(i, Arg);
     }
index 415bc947594fb623b4b23bdf9f77651fb51acff9..a73f386dabec810309937624c70b867138b87ad5 100644 (file)
@@ -156,8 +156,15 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs,
 
   // Promote additional arguments to variadic methods.
   if (Method->isVariadic()) {
-    for (unsigned i = NumNamedArgs; i < NumArgs; ++i)
+    for (unsigned i = NumNamedArgs; i < NumArgs; ++i) {
+      if (!Args[i]->getType()->isPODType()) {
+        Diag(Args[i]->getLocStart(), 
+             diag::warn_cannot_pass_non_pod_arg_to_vararg) << 
+        Args[i]->getType() << 2; // Method
+      }
+      
       DefaultArgumentPromotion(Args[i]);
+    }
   } else {
     // Check for extra arguments to non-variadic methods.
     if (NumArgs != NumNamedArgs) {
index c66db173ebd2a2825709f2ef363310b063b0beaf..d74a5d54b9690a9009d443e9af1ce9c740e23728 100644 (file)
@@ -3576,6 +3576,13 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
     // Promote the arguments (C99 6.5.2.2p7).
     for (unsigned i = NumArgsInProto; i != NumArgs; i++) {
       Expr *Arg = Args[i];
+        
+      if (!Arg->getType()->isPODType()) {
+        Diag(Arg->getLocStart(), 
+             diag::warn_cannot_pass_non_pod_arg_to_vararg) << 
+        Arg->getType() << 2; // Method
+      }
+
       DefaultArgumentPromotion(Arg);
       TheCall->setArg(i + 1, Arg);
     }
diff --git a/test/SemaCXX/vararg-non-pod.cpp b/test/SemaCXX/vararg-non-pod.cpp
new file mode 100644 (file)
index 0000000..d413335
--- /dev/null
@@ -0,0 +1,49 @@
+// RUN: clang -fsyntax-only -verify -fblocks %s
+
+class C {
+public:
+  C(int);
+  void g(int a, ...);
+  static void h(int a, ...);
+};
+
+void g(int a, ...);
+
+void t1()
+{
+  C c(10);
+  
+  g(10, c); // expected-warning{{cannot pass object of non-POD type 'class C' through variadic function; call will abort at runtime}}
+}
+
+void t2()
+{
+  C c(10);
+
+  c.g(10, c); // expected-warning{{cannot pass object of non-POD type 'class C' through variadic method; call will abort at runtime}}
+  
+  C::h(10, c); // expected-warning{{cannot pass object of non-POD type 'class C' through variadic function; call will abort at runtime}}
+}
+
+int (^block)(int, ...);
+
+void t3()
+{
+  C c(10);
+  
+  block(10, c); // expected-warning{{cannot pass object of non-POD type 'class C' through variadic block; call will abort at runtime}}
+}
+
+class D {
+public:
+  void operator() (int a, ...);
+};
+
+void t4()
+{
+  C c(10);
+
+  D d;
+  
+  d(10, c); // expected-warning{{Line 48: cannot pass object of non-POD type 'class C' through variadic method; call will abort at runtime}}
+}
diff --git a/test/SemaObjCXX/vararg-non-pod.mm b/test/SemaObjCXX/vararg-non-pod.mm
new file mode 100644 (file)
index 0000000..3431dea
--- /dev/null
@@ -0,0 +1,18 @@
+// RUN: clang -fsyntax-only -verify %s
+
+class C {
+public:
+  C(int);
+};
+
+@interface D 
+- (void)g:(int)a, ...;
+@end
+
+void t1(D *d)
+{
+  C c(10);
+
+  [d g:10, c]; // expected-warning{{cannot pass object of non-POD type 'class C' through variadic method; call will abort at runtime}}
+}
+