[clang] 3c0a136 - [clang][Sema] Suggest static_cast in C++ code

Alex Brachet via cfe-commits cfe-commits at lists.llvm.org
Fri Jul 14 09:24:52 PDT 2023


Author: Alex Brachet
Date: 2023-07-14T16:22:06Z
New Revision: 3c0a136ce4b724221a7f75b656b9f7af3de6b64c

URL: https://github.com/llvm/llvm-project/commit/3c0a136ce4b724221a7f75b656b9f7af3de6b64c
DIFF: https://github.com/llvm/llvm-project/commit/3c0a136ce4b724221a7f75b656b9f7af3de6b64c.diff

LOG: [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

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/Sema/SemaChecking.cpp
    clang/test/FixIt/format.mm

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 53a83b9c94176d..0423c054bd0b58 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -415,6 +415,8 @@ Improvements to Clang's diagnostics
     source:1:6: note: candidate function not viable: no known conversion from 'const char[4]' to 'int' for 2nd argument
     void func(int aa, int bb);
          ^            ~~~~~~
+- ``-Wformat`` cast fix-its will now suggest ``static_cast`` instead of C-style casts
+  for C++ code.
 
 Bug Fixes in This Version
 -------------------------

diff  --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index f9a50f6ef3be6f..66a1a8f3f90ee3 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -11184,9 +11184,9 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
       // if necessary).
       SmallString<16> CastBuf;
       llvm::raw_svector_ostream CastFix(CastBuf);
-      CastFix << "(";
+      CastFix << (S.LangOpts.CPlusPlus ? "static_cast<" : "(");
       IntendedTy.print(CastFix, S.Context.getPrintingPolicy());
-      CastFix << ")";
+      CastFix << (S.LangOpts.CPlusPlus ? ">" : ")");
 
       SmallVector<FixItHint,4> Hints;
       if (!AT.matchesType(S.Context, IntendedTy) || ShouldNotPrintDirectly)
@@ -11197,7 +11197,7 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
         SourceRange CastRange(CCast->getLParenLoc(), CCast->getRParenLoc());
         Hints.push_back(FixItHint::CreateReplacement(CastRange, CastFix.str()));
 
-      } else if (!requiresParensToAddCast(E)) {
+      } else if (!requiresParensToAddCast(E) && !S.LangOpts.CPlusPlus) {
         // If the expression has high enough precedence,
         // just write the C-style cast.
         Hints.push_back(

diff  --git a/clang/test/FixIt/format.mm b/clang/test/FixIt/format.mm
index eed7c981f2c455..f630db41b37844 100644
--- a/clang/test/FixIt/format.mm
+++ b/clang/test/FixIt/format.mm
@@ -9,22 +9,22 @@ void test_percent_C() {
 
   const wchar_t wchar_data = L'a';
   NSLog(@"%C", wchar_data);  // expected-warning{{format specifies type 'unichar' (aka 'unsigned short') but the argument has type 'wchar_t'}}
-  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:16-[[@LINE-1]]:16}:"(unsigned short)"
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:16-[[@LINE-1]]:16}:"static_cast<unsigned short>(
 
   NSLog(@"%C", 0x260300);  // expected-warning{{format specifies type 'unichar' (aka 'unsigned short') but the argument has type 'int'}}
   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%d"
-  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:16}:"(unsigned short)"
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:16}:"static_cast<unsigned short>(
 
   typedef unsigned short unichar;
 
   NSLog(@"%C", wchar_data);  // expected-warning{{format specifies type 'unichar' (aka 'unsigned short') but the argument has type 'wchar_t'}}
-  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:16-[[@LINE-1]]:16}:"(unichar)"
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:16-[[@LINE-1]]:16}:"static_cast<unichar>(
 
   NSLog(@"%C", 0x260300);  // expected-warning{{format specifies type 'unichar' (aka 'unsigned short') but the argument has type 'int'}}
   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%d"
-  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:16}:"(unichar)"
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:16}:"static_cast<unichar>(
 
   NSLog(@"%C", 0.0); // expected-warning{{format specifies type 'unichar' (aka 'unsigned short') but the argument has type 'double'}}
   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%f"
-  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:16}:"(unichar)"
+  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:16}:"static_cast<unichar>(
 }


        


More information about the cfe-commits mailing list