]> granicus.if.org Git - clang/commitdiff
Add some more diagnostics for va_start, fix tests so they pass with these new diags.
authorAnders Carlsson <andersca@mac.com>
Fri, 12 Oct 2007 17:48:41 +0000 (17:48 +0000)
committerAnders Carlsson <andersca@mac.com>
Fri, 12 Oct 2007 17:48:41 +0000 (17:48 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@42917 91177308-0d34-0410-b5e6-96231b3b80d8

Sema/SemaChecking.cpp
include/clang/Basic/DiagnosticKinds.def
test/Sema/format-strings.c
test/Sema/varargs.c [new file with mode: 0644]

index ea63b7dc1ca065f3c1c0e53e4b201a79e46f9f32..f764d80df25d2757e33e8afcc69eabcbde2325ad 100644 (file)
@@ -43,6 +43,37 @@ Sema::CheckFunctionCall(Expr *Fn,
     assert(NumArgsInCall == 1 &&
            "Wrong number of arguments to builtin CFStringMakeConstantString");
     return CheckBuiltinCFStringArgument(Args[0]);
+  } else if (FnInfo->getBuiltinID() == Builtin::BI__builtin_va_start) {
+    if (NumArgsInCall > 2) {
+      Diag(Args[2]->getLocStart(), 
+           diag::err_typecheck_call_too_many_args, Fn->getSourceRange(),
+           SourceRange(Args[2]->getLocStart(),
+                       Args[NumArgsInCall - 1]->getLocEnd()));
+      return true;
+    }
+    
+    FunctionTypeProto* proto = 
+      cast<FunctionTypeProto>(CurFunctionDecl->getType());      
+    if (!proto->isVariadic()) {
+      Diag(Fn->getLocStart(),
+           diag::err_va_start_used_in_non_variadic_function);
+      return true;
+    }
+      
+    bool SecondArgIsLastNamedArgument = false;
+    if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Args[1])) {
+      if (ParmVarDecl *PV = dyn_cast<ParmVarDecl>(DR->getDecl())) {
+        ParmVarDecl *LastNamedArg = 
+          CurFunctionDecl->getParamDecl(CurFunctionDecl->getNumParams() - 1);
+              
+        if (PV == LastNamedArg)
+          SecondArgIsLastNamedArgument = true;
+      }
+    }
+      
+    if (!SecondArgIsLastNamedArgument)
+      Diag(Args[1]->getLocStart(), 
+           diag::warn_second_parameter_of_va_start_not_last_named_argument);
   }
   
   // Search the KnownFunctionIDs for the identifier.
index 16fccb62bc2af36c720ac7832128e6561b71e829..81aaa5caf791f7b35022359c624702aaab090825 100644 (file)
@@ -847,6 +847,10 @@ DIAG(err_multiple_default_labels_defined, ERROR,
     "multiple default labels in one switch")
 DIAG(warn_empty_if_body, WARNING,
     "if statement has empty body")
+DIAG(err_va_start_used_in_non_variadic_function, ERROR,
+    "'va_start' used in function with fixed args")
+DIAG(warn_second_parameter_of_va_start_not_last_named_argument, WARNING,
+    "second parameter of 'va_start' not last named argument")
 
 DIAG(warn_return_missing_expr, WARNING,
      "non-void function '%0' should return a value")
index 83947cf7c356a98dc8f99f3bd883706fcc2dfccf..8b3be6856b523aba9a5775038a95edc30ae9443b 100644 (file)
@@ -45,7 +45,7 @@ void check_null_char_string(char* b)
   printf("%\0d",1); // expected-warning {{string contains '\0'}}
 }
 
-void check_empty_format_string(char* buf)
+void check_empty_format_string(char* buf, ...)
 {
   va_list ap;
   va_start(ap,buf);
@@ -53,9 +53,8 @@ void check_empty_format_string(char* buf)
   sprintf(buf,""); // expected-warning {{format string is empty}}
 }
 
-void check_wide_string()
+void check_wide_string(char* b, ...)
 {
-  char *b;
   va_list ap;
   va_start(ap,b);
 
diff --git a/test/Sema/varargs.c b/test/Sema/varargs.c
new file mode 100644 (file)
index 0000000..92faf9f
--- /dev/null
@@ -0,0 +1,18 @@
+// RUN: clang -fsyntax-only -verify %s
+
+void f1(int a)
+{
+    __builtin_va_list ap;
+    
+    __builtin_va_start(ap, a, a); // expected-error {{too many arguments to function}}
+    __builtin_va_start(ap, a); // expected-error {{'va_start' used in function with fixed args}}
+}
+
+void f2(int a, int b, ...)
+{
+    __builtin_va_list ap;
+    
+    __builtin_va_start(ap, 10); // expected-warning {{second parameter of 'va_start' not last named argument}}
+    __builtin_va_start(ap, a); // expected-warning {{second parameter of 'va_start' not last named argument}}
+    __builtin_va_start(ap, b);
+}