[Sema] Fix fixit cast printing inside macros (#66853)
authorShoaib Meenai <smeenai@fb.com>
Thu, 21 Sep 2023 00:32:35 +0000 (17:32 -0700)
committerTobias Hieta <tobias@hieta.se>
Fri, 29 Sep 2023 06:23:57 +0000 (08:23 +0200)
commit45066b9fbc7b84dfcf5363d01fadd3d42c049e7f
tree4a56200ea5c9b692c8fbaf09195e1ce31180f088
parent87ec1f460d0efbc565e89f817af73c2496361749
[Sema] Fix fixit cast printing inside macros (#66853)

`Lexer::getLocForEndOfToken` is documented as returning an invalid
source location when the end of the token is inside a macro expansion.
We don't want that for this particular application, so just calculate
the end location directly instead.

Before this, format fix-its would omit the closing parenthesis (thus
producing invalid code) for macros, e.g.:

```
$ cat format.cpp
extern "C" int printf(const char *, ...);
enum class Foo { Bar };
#define LOG(...) printf(__VA_ARGS__)
void f(Foo foo) { LOG("%d\n", foo); }

$ clang -fsyntax-only format.cpp
format.cpp:4:29: warning: format specifies type 'int' but the argument has type 'Foo' [-Wformat]
    4 | void f(Foo f) { LOG("%d\n", f); }
      |                      ~~     ^
      |                             static_cast<int>(
format.cpp:3:25: note: expanded from macro 'LOG'
    3 | #define LOG(...) printf(__VA_ARGS__)
      |                         ^~~~~~~~~~~
1 warning generated.
```

We now emit a valid fix-it:

```
$ clang -fsyntax-only format.cpp
format.cpp:4:31: warning: format specifies type 'int' but the argument has type 'Foo' [-Wformat]
    4 | void f(Foo foo) { LOG("%d\n", foo); }
      |                        ~~     ^~~
      |                               static_cast<int>( )
format.cpp:3:25: note: expanded from macro 'LOG'
    3 | #define LOG(...) printf(__VA_ARGS__)
      |                         ^~~~~~~~~~~
1 warning generated.
```

Fixes https://github.com/llvm/llvm-project/issues/63462

(cherry picked from commit 61c5ad8857a71510e4393680a1e42740da4ba6fa)
clang/lib/Sema/SemaChecking.cpp
clang/test/FixIt/format.cpp