diff options
-rw-r--r-- | Sema/SemaChecking.cpp | 28 | ||||
-rw-r--r-- | test/Sema/format-strings.c | 13 |
2 files changed, 34 insertions, 7 deletions
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<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; } 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 <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() |