Skip to content

Commit aa33e98

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 e7c3386 commit aa33e98

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
@@ -5934,18 +5934,19 @@ static StringLiteralCheckType checkFormatStringExpr(
59345934
if (!Sema::getFormatStringInfo(D, PVFormat->getFormatIdx(),
59355935
PVFormat->getFirstArg(), &CallerFSI))
59365936
continue;
5937-
// We also check if the formats are compatible.
5938-
// We can't pass a 'scanf' string to a 'printf' function.
5939-
if (Type != S.GetFormatStringType(PVFormat)) {
5940-
S.Diag(Args[format_idx]->getBeginLoc(),
5941-
diag::warn_format_string_type_incompatible)
5942-
<< PVFormat->getType()->getName()
5943-
<< S.GetFormatStringTypeName(Type);
5944-
if (!InFunctionCall) {
5945-
S.Diag(E->getBeginLoc(), diag::note_format_string_defined);
5937+
if (PV->getFunctionScopeIndex() == CallerFSI.FormatIdx) {
5938+
// We also check if the formats are compatible.
5939+
// We can't pass a 'scanf' string to a 'printf' function.
5940+
if (Type != S.GetFormatStringType(PVFormat)) {
5941+
S.Diag(Args[format_idx]->getBeginLoc(),
5942+
diag::warn_format_string_type_incompatible)
5943+
<< PVFormat->getType()->getName()
5944+
<< S.GetFormatStringTypeName(Type);
5945+
if (!InFunctionCall) {
5946+
S.Diag(E->getBeginLoc(), diag::note_format_string_defined);
5947+
}
5948+
return SLCT_UncheckedLiteral;
59465949
}
5947-
return SLCT_UncheckedLiteral;
5948-
} else if (PV->getFunctionScopeIndex() == CallerFSI.FormatIdx) {
59495950
// Lastly, check that argument passing kinds transition in a
59505951
// way that makes sense:
59515952
// 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)