diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index fc96ccb992ed7..e9c4010665b7c 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -205,6 +205,9 @@ Bug Fixes in This Version - For function multi-versioning using the ``target`` or ``target_clones`` attributes, remove comdat for internal linkage functions. (`#65114 `_) +- Clang now reports ``-Wformat`` for bool value and char specifier confusion + in scanf. Fixes + (`#64987 `_) Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/AST/FormatString.cpp b/clang/lib/AST/FormatString.cpp index f86278e4b5163..e0c9e18cfe3a2 100644 --- a/clang/lib/AST/FormatString.cpp +++ b/clang/lib/AST/FormatString.cpp @@ -368,8 +368,11 @@ ArgType::matchesType(ASTContext &C, QualType argTy) const { case BuiltinType::SChar: case BuiltinType::UChar: case BuiltinType::Char_U: + return Match; case BuiltinType::Bool: - return Match; + if (!Ptr) + return Match; + break; } // "Partially matched" because of promotions? if (!Ptr) { @@ -410,11 +413,14 @@ ArgType::matchesType(ASTContext &C, QualType argTy) const { switch (BT->getKind()) { default: break; + case BuiltinType::Bool: + if (Ptr && (T == C.UnsignedCharTy || T == C.SignedCharTy)) + return NoMatch; + [[fallthrough]]; case BuiltinType::Char_S: case BuiltinType::SChar: case BuiltinType::Char_U: case BuiltinType::UChar: - case BuiltinType::Bool: if (T == C.UnsignedShortTy || T == C.ShortTy) return NoMatchTypeConfusion; if (T == C.UnsignedCharTy || T == C.SignedCharTy) diff --git a/clang/test/SemaCXX/format-strings-scanf.cpp b/clang/test/SemaCXX/format-strings-scanf.cpp index f78d334d1685e..25fe5346791a0 100644 --- a/clang/test/SemaCXX/format-strings-scanf.cpp +++ b/clang/test/SemaCXX/format-strings-scanf.cpp @@ -29,6 +29,8 @@ union bag { void test(void) { bag b; + // expected-warning@+2 {{format specifies type 'char *' but the argument has type 'bool *'}} + // expected-warning@+1 {{format specifies type 'unsigned char *' but the argument has type 'bool *'}} scan("%hhi %hhu %hhi %hhu", &b.sc, &b.uc, &b.b, &b.b); scan("%hi %hu", &b.ss, &b.us); scan("%i %u", &b.si, &b.ui);