From: Ted Kremenek Date: Mon, 17 Dec 2007 19:03:13 +0000 (+0000) Subject: Modified format-string checking to not emit a warning when all of the X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4a33646560c4faf8fb82a681360eb2dc0573d558;p=clang Modified format-string checking to not emit a warning when all of the 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 --- diff --git a/Sema/SemaChecking.cpp b/Sema/SemaChecking.cpp index 38b93ab1eb..b366a2b70f 100644 --- a/Sema/SemaChecking.cpp +++ b/Sema/SemaChecking.cpp @@ -237,8 +237,32 @@ Sema::CheckPrintfArguments(Expr *Fn, StringLiteral *FExpr = dyn_cast(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(IgnoreParen(OrigFormatExpr))) + if (isa(DR->getDecl())) + return; + + Diag(Args[format_idx]->getLocStart(), diag::warn_printf_not_string_constant, + Fn->getSourceRange()); + return; } diff --git a/test/Sema/format-strings.c b/test/Sema/format-strings.c index e5bbd70bfd..c1e690a3b8 100644 --- a/test/Sema/format-strings.c +++ b/test/Sema/format-strings.c @@ -3,6 +3,8 @@ #include #include +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()