Skip to content

Commit 3c0a136

Browse files
committed
[clang][Sema] Suggest static_cast in C++ code
This patch changes the -Wformat diagnostic to suggest static_cast over a C-style cast for {,Objective}C++ when recommending the argument be casted rather than changing the format string. Before: ``` clang/test/FixIt/format.mm:11:16: warning: format specifies type 'unichar' (aka 'unsigned short') but the argument has type 'wchar_t' [-Wformat] 11 | NSLog(@"%C", wchar_data); // expected-warning{{format specifies type 'unichar' (aka 'unsigned short') but the argument has type 'wchar_t'}} | ~~ ^~~~~~~~~~ | (unsigned short) ``` After: ``` clang/test/FixIt/format.mm:11:16: warning: format specifies type 'unichar' (aka 'unsigned short') but the argument has type 'wchar_t' [-Wformat] 11 | NSLog(@"%C", wchar_data); // expected-warning{{format specifies type 'unichar' (aka 'unsigned short') but the argument has type 'wchar_t'}} | ~~ ^~~~~~~~~~ | static_cast<unsigned short>( ) ``` Differential Revision: https://reviews.llvm.org/D153622
1 parent 424392b commit 3c0a136

File tree

3 files changed

+10
-8
lines changed

3 files changed

+10
-8
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,8 @@ Improvements to Clang's diagnostics
415415
source:1:6: note: candidate function not viable: no known conversion from 'const char[4]' to 'int' for 2nd argument
416416
void func(int aa, int bb);
417417
^ ~~~~~~
418+
- ``-Wformat`` cast fix-its will now suggest ``static_cast`` instead of C-style casts
419+
for C++ code.
418420

419421
Bug Fixes in This Version
420422
-------------------------

clang/lib/Sema/SemaChecking.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11184,9 +11184,9 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
1118411184
// if necessary).
1118511185
SmallString<16> CastBuf;
1118611186
llvm::raw_svector_ostream CastFix(CastBuf);
11187-
CastFix << "(";
11187+
CastFix << (S.LangOpts.CPlusPlus ? "static_cast<" : "(");
1118811188
IntendedTy.print(CastFix, S.Context.getPrintingPolicy());
11189-
CastFix << ")";
11189+
CastFix << (S.LangOpts.CPlusPlus ? ">" : ")");
1119011190

1119111191
SmallVector<FixItHint,4> Hints;
1119211192
if (!AT.matchesType(S.Context, IntendedTy) || ShouldNotPrintDirectly)
@@ -11197,7 +11197,7 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
1119711197
SourceRange CastRange(CCast->getLParenLoc(), CCast->getRParenLoc());
1119811198
Hints.push_back(FixItHint::CreateReplacement(CastRange, CastFix.str()));
1119911199

11200-
} else if (!requiresParensToAddCast(E)) {
11200+
} else if (!requiresParensToAddCast(E) && !S.LangOpts.CPlusPlus) {
1120111201
// If the expression has high enough precedence,
1120211202
// just write the C-style cast.
1120311203
Hints.push_back(

clang/test/FixIt/format.mm

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,22 @@ void test_percent_C() {
99

1010
const wchar_t wchar_data = L'a';
1111
NSLog(@"%C", wchar_data); // expected-warning{{format specifies type 'unichar' (aka 'unsigned short') but the argument has type 'wchar_t'}}
12-
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:16-[[@LINE-1]]:16}:"(unsigned short)"
12+
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:16-[[@LINE-1]]:16}:"static_cast<unsigned short>(
1313

1414
NSLog(@"%C", 0x260300); // expected-warning{{format specifies type 'unichar' (aka 'unsigned short') but the argument has type 'int'}}
1515
// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%d"
16-
// CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:16}:"(unsigned short)"
16+
// CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:16}:"static_cast<unsigned short>(
1717

1818
typedef unsigned short unichar;
1919

2020
NSLog(@"%C", wchar_data); // expected-warning{{format specifies type 'unichar' (aka 'unsigned short') but the argument has type 'wchar_t'}}
21-
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:16-[[@LINE-1]]:16}:"(unichar)"
21+
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:16-[[@LINE-1]]:16}:"static_cast<unichar>(
2222

2323
NSLog(@"%C", 0x260300); // expected-warning{{format specifies type 'unichar' (aka 'unsigned short') but the argument has type 'int'}}
2424
// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%d"
25-
// CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:16}:"(unichar)"
25+
// CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:16}:"static_cast<unichar>(
2626

2727
NSLog(@"%C", 0.0); // expected-warning{{format specifies type 'unichar' (aka 'unsigned short') but the argument has type 'double'}}
2828
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%f"
29-
// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:16}:"(unichar)"
29+
// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:16}:"static_cast<unichar>(
3030
}

0 commit comments

Comments
 (0)