]> granicus.if.org Git - clang/commitdiff
Modified format-string checking to not emit a warning when all of the
authorTed Kremenek <kremenek@apple.com>
Mon, 17 Dec 2007 19:03:13 +0000 (19:03 +0000)
committerTed Kremenek <kremenek@apple.com>
Mon, 17 Dec 2007 19:03:13 +0000 (19:03 +0000)
following hold:

(1) A vprintf-like function is called that takes the argument list via a
    via_list argument.

(2) The format string is a non-literal that is the parameter value of
    the enclosing function, e.g:

    void logmessage(const char *fmt,...) {
      va_list ap;
      va_start(ap,fmt);
      fprintf(fmt,ap);  // Do not emit a warning.
    }

In the future this special case will be enhanced to consult the "format"
attribute attached to a function declaration instead of just allowing a blank
check for all function parameters to be used as format strings to vprintf-like
functions. This will happen when more support for attributes becomes
available.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@45114 91177308-0d34-0410-b5e6-96231b3b80d8

Sema/SemaChecking.cpp
test/Sema/format-strings.c

index 38b93ab1ebd8abc39b2f3a6ae02e6d387ff0c78a..b366a2b70f9886636006035ea1725c3412bab404 100644 (file)
@@ -237,8 +237,32 @@ Sema::CheckPrintfArguments(Expr *Fn,
   StringLiteral *FExpr = dyn_cast<StringLiteral>(OrigFormatExpr);
   
   if (FExpr == NULL) {
-    Diag(Args[format_idx]->getLocStart(), 
-         diag::warn_printf_not_string_constant, Fn->getSourceRange());
+    // For vprintf* functions (i.e., HasVAListArg==true), we add a
+    // special check to see if the format string is a function parameter
+    // of the function calling the printf function.  If the function
+    // has an attribute indicating it is a printf-like function, then we
+    // should suppress warnings concerning non-literals being used in a call
+    // to a vprintf function.  For example:
+    //
+    // void
+    // logmessage(char const *fmt __attribute__ (format (printf, 1, 2)), ...) {
+    //      va_list ap;
+    //      va_start(ap, fmt);
+    //      vprintf(fmt, ap);  // Do NOT emit a warning about "fmt".
+    //      ...
+    //
+    //
+    //  FIXME: We don't have full attribute support yet, so just check to see
+    //    if the argument is a DeclRefExpr that references a parameter.  We'll
+    //    add proper support for checking the attribute later.
+    if (HasVAListArg)
+      if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(IgnoreParen(OrigFormatExpr)))
+          if (isa<ParmVarDecl>(DR->getDecl()))
+          return;
+    
+    Diag(Args[format_idx]->getLocStart(), diag::warn_printf_not_string_constant,
+         Fn->getSourceRange());
+          
     return;
   }
 
index e5bbd70bfde99ef57886dc044cbe75a105d8dcbd..c1e690a3b80e3c39b0090eb0895e8ee3896098e2 100644 (file)
@@ -3,6 +3,8 @@
 #include <stdio.h>
 #include <stdarg.h>
 
+char * global_fmt;
+
 void check_string_literal( FILE* fp, const char* s, char *buf, ... ) {
 
   char * b;
@@ -10,15 +12,16 @@ void check_string_literal( FILE* fp, const char* s, char *buf, ... ) {
   va_start(ap,buf);
 
   printf(s); // expected-warning {{format string is not a string literal}}
-  vprintf(s,ap); // expected-warning {{format string is not a string liter}}
+  vprintf(s,ap); // // no-warning
   fprintf(fp,s); // expected-warning {{format string is not a string literal}}
-  vfprintf(fp,s,ap); // expected-warning {{format string is not a string lit}}
+  vfprintf(fp,s,ap); // no-warning
   asprintf(&b,s); // expected-warning {{format string is not a string lit}}
-  vasprintf(&b,s,ap); // expected-warning {{format string is not a string lit}}
+  vasprintf(&b,s,ap); // no-warning
   sprintf(buf,s); // expected-warning {{format string is not a string literal}}
   snprintf(buf,2,s); // expected-warning {{format string is not a string lit}}
-  vsprintf(buf,s,ap); // expected-warning {{format string is not a string lit}}
-  vsnprintf(buf,2,s,ap); // expected-warning {{mat string is not a string lit}}
+  vsprintf(buf,s,ap); // no-warning
+  vsnprintf(buf,2,s,ap); // no-warning
+  vsnprintf(buf,2,global_fmt,ap); // expected-warning {{format string is not a string literal}}
 }
 
 void check_writeback_specifier()