Skip to content

Commit 361f363

Browse files
authored
[clang-tidy]fix incorrect fix-it for the string contains a user-defined suffix (llvm#122901)
Fixed: llvm#97243
1 parent 6dcb2a0 commit 361f363

File tree

4 files changed

+39
-8
lines changed

4 files changed

+39
-8
lines changed

clang-tools-extra/clang-tidy/modernize/RawStringLiteralCheck.cpp

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "clang/AST/ASTContext.h"
1111
#include "clang/ASTMatchers/ASTMatchFinder.h"
1212
#include "clang/Lex/Lexer.h"
13+
#include "llvm/ADT/StringRef.h"
1314

1415
using namespace clang::ast_matchers;
1516

@@ -136,13 +137,26 @@ void RawStringLiteralCheck::check(const MatchFinder::MatchResult &Result) {
136137

137138
void RawStringLiteralCheck::replaceWithRawStringLiteral(
138139
const MatchFinder::MatchResult &Result, const StringLiteral *Literal,
139-
StringRef Replacement) {
140-
CharSourceRange CharRange = Lexer::makeFileCharRange(
141-
CharSourceRange::getTokenRange(Literal->getSourceRange()),
142-
*Result.SourceManager, getLangOpts());
143-
diag(Literal->getBeginLoc(),
144-
"escaped string literal can be written as a raw string literal")
145-
<< FixItHint::CreateReplacement(CharRange, Replacement);
140+
std::string Replacement) {
141+
DiagnosticBuilder Builder =
142+
diag(Literal->getBeginLoc(),
143+
"escaped string literal can be written as a raw string literal");
144+
const SourceManager &SM = *Result.SourceManager;
145+
const CharSourceRange TokenRange =
146+
CharSourceRange::getTokenRange(Literal->getSourceRange());
147+
Token T;
148+
if (Lexer::getRawToken(Literal->getBeginLoc(), T, SM, getLangOpts()))
149+
return;
150+
const CharSourceRange CharRange =
151+
Lexer::makeFileCharRange(TokenRange, SM, getLangOpts());
152+
if (T.hasUDSuffix()) {
153+
const StringRef Text = Lexer::getSourceText(CharRange, SM, getLangOpts());
154+
const size_t UDSuffixPos = Text.find_last_of('"');
155+
if (UDSuffixPos == StringRef::npos)
156+
return;
157+
Replacement += Text.slice(UDSuffixPos + 1, Text.size());
158+
}
159+
Builder << FixItHint::CreateReplacement(CharRange, Replacement);
146160
}
147161

148162
} // namespace clang::tidy::modernize

clang-tools-extra/clang-tidy/modernize/RawStringLiteralCheck.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class RawStringLiteralCheck : public ClangTidyCheck {
3535
private:
3636
void replaceWithRawStringLiteral(
3737
const ast_matchers::MatchFinder::MatchResult &Result,
38-
const StringLiteral *Literal, StringRef Replacement);
38+
const StringLiteral *Literal, std::string Replacement);
3939

4040
std::string DelimiterStem;
4141
CharsBitSet DisallowedChars;

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,10 @@ Changes in existing checks
321321
a false positive when only an implicit conversion happened inside an
322322
initializer list.
323323

324+
- Improved :doc:`modernize-raw-string-literal
325+
<clang-tidy/checks/modernize/raw-string-literal>` check to fix incorrect
326+
fix-it when the string contains a user-defined suffix.
327+
324328
- Improved :doc:`modernize-use-designated-initializers
325329
<clang-tidy/checks/modernize/use-designated-initializers>` check to fix a
326330
crash when a class is declared but not defined.

clang-tools-extra/test/clang-tidy/checkers/modernize/raw-string-literal.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,3 +129,16 @@ void callFn() {
129129
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: {{.*}} can be written as a raw string literal
130130
// CHECK-FIXES: {{^}} fn<double>(R"(foo\bar)");{{$}}
131131
}
132+
133+
namespace std {
134+
using size_t = decltype(sizeof(0));
135+
namespace ud {
136+
int operator""_abc(const char *str, std::size_t len);
137+
} // namespace ud
138+
} // namespace std
139+
namespace gh97243 {
140+
using namespace std::ud;
141+
auto UserDefinedLiteral = "foo\\bar"_abc;
142+
// CHECK-MESSAGES: :[[@LINE-1]]:27: warning: {{.*}} can be written as a raw string literal
143+
// CHECK-FIXES: {{^}}auto UserDefinedLiteral = R"(foo\bar)"_abc;
144+
} // namespace gh97243

0 commit comments

Comments
 (0)