diff options
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 11 | ||||
-rw-r--r-- | clang/test/SemaObjC/format-strings-oslog.m | 5 |
3 files changed, 18 insertions, 1 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 502c771..f72d5c25 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -9901,6 +9901,9 @@ def warn_format_invalid_annotation : Warning< def warn_format_P_no_precision : Warning< "using '%%P' format specifier without precision">, InGroup<Format>; +def warn_format_P_with_objc_pointer : Warning< + "using '%%P' format specifier with an Objective-C pointer results in dumping runtime object structure, not object value">, + InGroup<Format>; def warn_printf_ignored_flag: Warning< "flag '%0' is ignored when flag '%1' is present">, InGroup<Format>; diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index e26cf20..cf8840c 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -12559,6 +12559,17 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, return true; } + // Diagnose attempts to use '%P' with ObjC object types, which will result in + // dumping raw class data (like is-a pointer), not actual data. + if (FS.getConversionSpecifier().getKind() == ConversionSpecifier::PArg && + ExprTy->isObjCObjectPointerType()) { + const CharSourceRange &CSR = + getSpecifierRange(StartSpecifier, SpecifierLen); + EmitFormatDiagnostic(S.PDiag(diag::warn_format_P_with_objc_pointer), + E->getExprLoc(), false, CSR); + return true; + } + ArgType::MatchKind ImplicitMatch = ArgType::NoMatch; ArgType::MatchKind Match = AT.matchesType(S.Context, ExprTy); ArgType::MatchKind OrigMatch = Match; diff --git a/clang/test/SemaObjC/format-strings-oslog.m b/clang/test/SemaObjC/format-strings-oslog.m index 20fec93..af5aef3 100644 --- a/clang/test/SemaObjC/format-strings-oslog.m +++ b/clang/test/SemaObjC/format-strings-oslog.m @@ -44,15 +44,18 @@ void test_os_log_format(const char *pc, int i, void *p, void *buf) { } // Test os_log_format primitive with ObjC string literal format argument. -void test_objc(const char *pc, int i, void *p, void *buf, NSString *nss) { +void test_objc(const char *pc, int i, void *p, void *buf, NSString *nss, id obj) { __builtin_os_log_format(buf, @""); __builtin_os_log_format(buf, @"%d"); // expected-warning {{more '%' conversions than data arguments}} __builtin_os_log_format(buf, @"%d", i); + __builtin_os_log_format(buf, @"%P", p); // expected-warning {{using '%P' format specifier without precision}} __builtin_os_log_format(buf, @"%.10P", p); __builtin_os_log_format(buf, @"%.*P", p); // expected-warning {{field precision should have type 'int', but argument has type 'void *'}} __builtin_os_log_format(buf, @"%.*P", i, p); __builtin_os_log_format(buf, @"%.*P", i, i); // expected-warning {{format specifies type 'void *' but the argument has type 'int'}} + __builtin_os_log_format(buf, @"%.8P", nss); // expected-warning {{using '%P' format specifier with an Objective-C pointer results in dumping runtime object structure, not object value}} + __builtin_os_log_format(buf, @"%.*P", i, obj); // expected-warning {{using '%P' format specifier with an Objective-C pointer results in dumping runtime object structure, not object value}} __builtin_os_log_format(buf, @"%{private}s", pc); __builtin_os_log_format(buf, @"%@", nss); |