Skip to content

Commit 64b571f

Browse files
[clang] Fix FP -Wformat in functions with 2+ attribute((format))
When defining functions with two or more format attributes, if the format strings don't have the same format family, there is a false positive warning that the incorrect kind of format string is being passed at forwarded format string call sites.
1 parent 77363f7 commit 64b571f

File tree

2 files changed

+32
-11
lines changed

2 files changed

+32
-11
lines changed

clang/lib/Sema/SemaChecking.cpp

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6149,18 +6149,19 @@ static StringLiteralCheckType checkFormatStringExpr(
61496149
if (!Sema::getFormatStringInfo(D, PVFormat->getFormatIdx(),
61506150
PVFormat->getFirstArg(), &CallerFSI))
61516151
continue;
6152-
// We also check if the formats are compatible.
6153-
// We can't pass a 'scanf' string to a 'printf' function.
6154-
if (Type != S.GetFormatStringType(PVFormat)) {
6155-
S.Diag(Args[format_idx]->getBeginLoc(),
6156-
diag::warn_format_string_type_incompatible)
6157-
<< PVFormat->getType()->getName()
6158-
<< S.GetFormatStringTypeName(Type);
6159-
if (!InFunctionCall) {
6160-
S.Diag(E->getBeginLoc(), diag::note_format_string_defined);
6152+
if (PV->getFunctionScopeIndex() == CallerFSI.FormatIdx) {
6153+
// We also check if the formats are compatible.
6154+
// We can't pass a 'scanf' string to a 'printf' function.
6155+
if (Type != S.GetFormatStringType(PVFormat)) {
6156+
S.Diag(Args[format_idx]->getBeginLoc(),
6157+
diag::warn_format_string_type_incompatible)
6158+
<< PVFormat->getType()->getName()
6159+
<< S.GetFormatStringTypeName(Type);
6160+
if (!InFunctionCall) {
6161+
S.Diag(E->getBeginLoc(), diag::note_format_string_defined);
6162+
}
6163+
return SLCT_UncheckedLiteral;
61616164
}
6162-
return SLCT_UncheckedLiteral;
6163-
} else if (PV->getFunctionScopeIndex() == CallerFSI.FormatIdx) {
61646165
// Lastly, check that argument passing kinds transition in a
61656166
// way that makes sense:
61666167
// from a caller with FAPK_VAList, allow FAPK_VAList

clang/test/Sema/format-strings.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,26 @@ void rdar8332221(va_list ap, int *x, long *y) {
496496
rdar8332221_vprintf_scanf("%", ap, "%d", x); // expected-warning{{incomplete format specifier}}
497497
}
498498

499+
void rdar8332221_vprintf_scanf(const char *p, va_list ap, const char *s, ...) {
500+
vprintf(p, ap);
501+
502+
va_list vs;
503+
va_start(vs, s);
504+
vscanf(s, vs);
505+
va_end(vs);
506+
}
507+
508+
__attribute__((__format__(__printf__, 1, 0)))
509+
__attribute__((__format__(__scanf__, 3, 4)))
510+
void vprintf_scanf_bad(const char *p, va_list ap, const char *s, ...) {
511+
vscanf(p, ap); // expected-warning{{passing 'printf' format string where 'scanf' format string is expected}}
512+
513+
va_list vs;
514+
va_start(vs, s);
515+
vprintf(s, vs); // expected-warning{{passing 'scanf' format string where 'printf' format string is expected}}
516+
va_end(vs);
517+
}
518+
499519
// PR8641
500520
void pr8641(void) {
501521
printf("%#x\n", 10);

0 commit comments

Comments
 (0)