diff options
author | apple-fcloutier <75502309+apple-fcloutier@users.noreply.github.com> | 2025-03-06 09:12:22 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-03-06 09:12:22 -0800 |
commit | c628e8e9ea86a225af846875740d0189f7cd3722 (patch) | |
tree | 6992c2814497eca1cab1542c57d2b8ab1c5b9c49 /clang/lib/Sema/SemaChecking.cpp | |
parent | 81089f0fd16e4eaae06f1a4be9611303c4f1cabf (diff) | |
download | llvm-c628e8e9ea86a225af846875740d0189f7cd3722.zip llvm-c628e8e9ea86a225af846875740d0189f7cd3722.tar.gz llvm-c628e8e9ea86a225af846875740d0189f7cd3722.tar.bz2 |
[clang] Fix FP -Wformat in functions with 2+ attribute((format)) (#129954)
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.
This happens because we check that the format string family of each
format attribute is compatible before we check that we're using the
associated format parameter. The fix is to move the check down one
scope, after we've established that we are checking the right parameter.
Tests are updated to include a true negative and a true positive of this
situation.
Diffstat (limited to 'clang/lib/Sema/SemaChecking.cpp')
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 23 |
1 files changed, 12 insertions, 11 deletions
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index f9926c6..9cac9cf 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -6149,18 +6149,19 @@ tryAgain: if (!Sema::getFormatStringInfo(D, PVFormat->getFormatIdx(), PVFormat->getFirstArg(), &CallerFSI)) continue; - // We also check if the formats are compatible. - // We can't pass a 'scanf' string to a 'printf' function. - if (Type != S.GetFormatStringType(PVFormat)) { - S.Diag(Args[format_idx]->getBeginLoc(), - diag::warn_format_string_type_incompatible) - << PVFormat->getType()->getName() - << S.GetFormatStringTypeName(Type); - if (!InFunctionCall) { - S.Diag(E->getBeginLoc(), diag::note_format_string_defined); + if (PV->getFunctionScopeIndex() == CallerFSI.FormatIdx) { + // We also check if the formats are compatible. + // We can't pass a 'scanf' string to a 'printf' function. + if (Type != S.GetFormatStringType(PVFormat)) { + S.Diag(Args[format_idx]->getBeginLoc(), + diag::warn_format_string_type_incompatible) + << PVFormat->getType()->getName() + << S.GetFormatStringTypeName(Type); + if (!InFunctionCall) { + S.Diag(E->getBeginLoc(), diag::note_format_string_defined); + } + return SLCT_UncheckedLiteral; } - return SLCT_UncheckedLiteral; - } else if (PV->getFunctionScopeIndex() == CallerFSI.FormatIdx) { // Lastly, check that argument passing kinds transition in a // way that makes sense: // from a caller with FAPK_VAList, allow FAPK_VAList |