[clang] [Sema] Fix fixit cast printing inside macros (PR #66853)
https://github.com/smeenai closed https://github.com/llvm/llvm-project/pull/66853 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Sema] Fix fixit cast printing inside macros (PR #66853)
https://github.com/smeenai updated https://github.com/llvm/llvm-project/pull/66853 >From 701b1d99515e40eec8dcbaba3a0b2dc436bf9652 Mon Sep 17 00:00:00 2001 From: Shoaib Meenai Date: Tue, 19 Sep 2023 19:46:56 -0700 Subject: [PATCH] [Sema] Fix fixit cast printing inside macros `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 }; 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( 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( ) 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 --- clang/lib/Sema/SemaChecking.cpp | 6 - clang/test/FixIt/format.cpp | 48 ++--- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index fad70223362eddd..b867d55c174e68b 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -11470,7 +11470,11 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier , Hints.push_back( FixItHint::CreateInsertion(E->getBeginLoc(), CastFix.str())); -SourceLocation After = S.getLocForEndOfToken(E->getEndLoc()); +// We don't use getLocForEndOfToken because it returns invalid source +// locations for macro expansions (by design). +SourceLocation EndLoc = S.SourceMgr.getSpellingLoc(E->getEndLoc()); +SourceLocation After = EndLoc.getLocWithOffset( +Lexer::MeasureTokenLength(EndLoc, S.SourceMgr, S.LangOpts)); Hints.push_back(FixItHint::CreateInsertion(After, ")")); } diff --git a/clang/test/FixIt/format.cpp b/clang/test/FixIt/format.cpp index 9cc4c2600eb6670..5016ee587ed1c43 100644 --- a/clang/test/FixIt/format.cpp +++ b/clang/test/FixIt/format.cpp @@ -1,19 +1,61 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wformat %s // RUN: %clang_cc1 -fsyntax-only -fdiagnostics-parseable-fixits -Wformat %s 2>&1 | FileCheck %s extern "C" int printf(const char *, ...); +#define LOG(...) printf(__VA_ARGS__) namespace N { enum class E { One }; } -void a() { +struct S { + N::E Type; +}; + +void a(N::E NEVal, S *SPtr, S ) { printf("%d", N::E::One); // expected-warning{{format specifies type 'int' but the argument has type 'N::E'}} // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:16-[[@LINE-1]]:16}:"static_cast(" // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:25-[[@LINE-2]]:25}:")" - printf("%hd", N::E::One); + printf("%hd", N::E::One); // expected-warning{{format specifies type 'short' but the argument has type 'N::E'}} // CHECK: "static_cast(" - printf("%hu", N::E::One); + printf("%hu", N::E::One); // expected-warning{{format specifies type 'unsigned short' but the argument has type 'N::E'}} // CHECK: "static_cast(" + + LOG("%d", N::E::One); // expected-warning{{format specifies type 'int' but the argument has type 'N::E'}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:13-[[@LINE-1]]:13}:"static_cast(" + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:22-[[@LINE-2]]:22}:")" + + printf("%d", NEVal); // expected-warning{{format specifies type 'int' but the argument has type 'N::E'}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:16-[[@LINE-1]]:16}:"static_cast(" + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:21-[[@LINE-2]]:21}:")" + + LOG("%d", NEVal); // expected-warning{{format specifies type 'int' but the argument has type 'N::E'}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:13-[[@LINE-1]]:13}:"static_cast(" + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:18-[[@LINE-2]]:18}:")" + + printf( + "%d", + SPtr->Type // expected-warning{{format specifies type 'int' but the argument has type 'N::E'}} + ); + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:7-[[@LINE-2]]:7}:"static_cast(" + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:17-[[@LINE-3]]:17}:")" + + LOG( //
[clang] [Sema] Fix fixit cast printing inside macros (PR #66853)
https://github.com/abrachet approved this pull request. Awesome! I couldn't figure this out when I looked :) https://github.com/llvm/llvm-project/pull/66853 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Sema] Fix fixit cast printing inside macros (PR #66853)
smeenai wrote: I updated the PR description with an example. https://github.com/llvm/llvm-project/pull/66853 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Sema] Fix fixit cast printing inside macros (PR #66853)
https://github.com/smeenai edited https://github.com/llvm/llvm-project/pull/66853 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Sema] Fix fixit cast printing inside macros (PR #66853)
tbaederr wrote: Since this is a diagnostic improvement, can you post the before and after output of an example? https://github.com/llvm/llvm-project/pull/66853 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Sema] Fix fixit cast printing inside macros (PR #66853)
llvmbot wrote: @llvm/pr-subscribers-clang Changes `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. Fixes https://github.com/llvm/llvm-project/issues/63462 --- Full diff: https://github.com/llvm/llvm-project/pull/66853.diff 2 Files Affected: - (modified) clang/lib/Sema/SemaChecking.cpp (+4-1) - (modified) clang/test/FixIt/format.cpp (+5) ``diff diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index fad70223362eddd..4fbdb315ddc87b4 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -11470,7 +11470,10 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier , Hints.push_back( FixItHint::CreateInsertion(E->getBeginLoc(), CastFix.str())); -SourceLocation After = S.getLocForEndOfToken(E->getEndLoc()); +// We don't use getLocForEndOfToken because it returns invalid source +// locations for macro expansions (by design). +SourceLocation After = E->getEndLoc().getLocWithOffset( +Lexer::MeasureTokenLength(E->getEndLoc(), S.SourceMgr, S.LangOpts)); Hints.push_back(FixItHint::CreateInsertion(After, ")")); } diff --git a/clang/test/FixIt/format.cpp b/clang/test/FixIt/format.cpp index 9cc4c2600eb6670..46a0a0a11cc850a 100644 --- a/clang/test/FixIt/format.cpp +++ b/clang/test/FixIt/format.cpp @@ -1,6 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -fdiagnostics-parseable-fixits -Wformat %s 2>&1 | FileCheck %s extern "C" int printf(const char *, ...); +#define LOG(...) printf(__VA_ARGS__) namespace N { enum class E { One }; @@ -16,4 +17,8 @@ void a() { printf("%hu", N::E::One); // CHECK: "static_cast(" + + LOG("%d", N::E::One); // expected-warning{{format specifies type 'int' but the argument has type 'N::E'}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:13-[[@LINE-1]]:13}:"static_cast(" + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:22-[[@LINE-2]]:22}:")" } `` https://github.com/llvm/llvm-project/pull/66853 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Sema] Fix fixit cast printing inside macros (PR #66853)
https://github.com/smeenai created https://github.com/llvm/llvm-project/pull/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. Fixes https://github.com/llvm/llvm-project/issues/63462 >From 66e12c0c192f6b490be5df694b2d7faedd1d1b74 Mon Sep 17 00:00:00 2001 From: Shoaib Meenai Date: Tue, 19 Sep 2023 19:46:56 -0700 Subject: [PATCH] [Sema] Fix fixit cast printing inside macros `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. Fixes https://github.com/llvm/llvm-project/issues/63462 --- clang/lib/Sema/SemaChecking.cpp | 5 - clang/test/FixIt/format.cpp | 5 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index fad70223362eddd..4fbdb315ddc87b4 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -11470,7 +11470,10 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier , Hints.push_back( FixItHint::CreateInsertion(E->getBeginLoc(), CastFix.str())); -SourceLocation After = S.getLocForEndOfToken(E->getEndLoc()); +// We don't use getLocForEndOfToken because it returns invalid source +// locations for macro expansions (by design). +SourceLocation After = E->getEndLoc().getLocWithOffset( +Lexer::MeasureTokenLength(E->getEndLoc(), S.SourceMgr, S.LangOpts)); Hints.push_back(FixItHint::CreateInsertion(After, ")")); } diff --git a/clang/test/FixIt/format.cpp b/clang/test/FixIt/format.cpp index 9cc4c2600eb6670..46a0a0a11cc850a 100644 --- a/clang/test/FixIt/format.cpp +++ b/clang/test/FixIt/format.cpp @@ -1,6 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -fdiagnostics-parseable-fixits -Wformat %s 2>&1 | FileCheck %s extern "C" int printf(const char *, ...); +#define LOG(...) printf(__VA_ARGS__) namespace N { enum class E { One }; @@ -16,4 +17,8 @@ void a() { printf("%hu", N::E::One); // CHECK: "static_cast(" + + LOG("%d", N::E::One); // expected-warning{{format specifies type 'int' but the argument has type 'N::E'}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:13-[[@LINE-1]]:13}:"static_cast(" + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:22-[[@LINE-2]]:22}:")" } ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits