Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 21 additions & 7 deletions clang-tools-extra/clang-tidy/modernize/RawStringLiteralCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Lex/Lexer.h"
#include "llvm/ADT/StringRef.h"

using namespace clang::ast_matchers;

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

void RawStringLiteralCheck::replaceWithRawStringLiteral(
const MatchFinder::MatchResult &Result, const StringLiteral *Literal,
StringRef Replacement) {
CharSourceRange CharRange = Lexer::makeFileCharRange(
CharSourceRange::getTokenRange(Literal->getSourceRange()),
*Result.SourceManager, getLangOpts());
diag(Literal->getBeginLoc(),
"escaped string literal can be written as a raw string literal")
<< FixItHint::CreateReplacement(CharRange, Replacement);
std::string Replacement) {
DiagnosticBuilder Builder =
diag(Literal->getBeginLoc(),
"escaped string literal can be written as a raw string literal");
const SourceManager &SM = *Result.SourceManager;
const CharSourceRange TokenRange =
CharSourceRange::getTokenRange(Literal->getSourceRange());
Token T;
if (Lexer::getRawToken(Literal->getBeginLoc(), T, SM, getLangOpts()))
return;
const CharSourceRange CharRange =
Lexer::makeFileCharRange(TokenRange, SM, getLangOpts());
if (T.hasUDSuffix()) {
const StringRef Text = Lexer::getSourceText(CharRange, SM, getLangOpts());
const size_t UDSuffixPos = Text.find_last_of('"');
if (UDSuffixPos == StringRef::npos)
return;
Replacement += Text.slice(UDSuffixPos + 1, Text.size());
}
Builder << FixItHint::CreateReplacement(CharRange, Replacement);
}

} // namespace clang::tidy::modernize
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class RawStringLiteralCheck : public ClangTidyCheck {
private:
void replaceWithRawStringLiteral(
const ast_matchers::MatchFinder::MatchResult &Result,
const StringLiteral *Literal, StringRef Replacement);
const StringLiteral *Literal, std::string Replacement);

std::string DelimiterStem;
CharsBitSet DisallowedChars;
Expand Down
4 changes: 4 additions & 0 deletions clang-tools-extra/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,10 @@ Changes in existing checks
a false positive when only an implicit conversion happened inside an
initializer list.

- Improved :doc:`modernize-raw-string-literal
<clang-tidy/checks/modernize/raw-string-literal>` check to fix incorrect
fix-it when the string contains a user-defined suffix.

- Improved :doc:`modernize-use-designated-initializers
<clang-tidy/checks/modernize/use-designated-initializers>` check to fix a
crash when a class is declared but not defined.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,16 @@ void callFn() {
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: {{.*}} can be written as a raw string literal
// CHECK-FIXES: {{^}} fn<double>(R"(foo\bar)");{{$}}
}

namespace std {
using size_t = decltype(sizeof(0));
namespace ud {
int operator""_abc(const char *str, std::size_t len);
} // namespace ud
} // namespace std
namespace gh97243 {
using namespace std::ud;
auto UserDefinedLiteral = "foo\\bar"_abc;
// CHECK-MESSAGES: :[[@LINE-1]]:27: warning: {{.*}} can be written as a raw string literal
// CHECK-FIXES: {{^}}auto UserDefinedLiteral = R"(foo\bar)"_abc;
} // namespace gh97243
Loading