[PATCH] D16529: [clang-tidy] Add modernize-raw-string-literal check

Alexander Kornienko via cfe-commits cfe-commits at lists.llvm.org
Wed Jan 27 07:13:47 PST 2016


alexfh added inline comments.

================
Comment at: clang-tidy/modernize/RawStringLiteralCheck.cpp:27
@@ +26,3 @@
+  // we only transform ASCII string literals
+  if (!Literal->isAscii())
+    return false;
----------------
Why can't the check convert non-ascii string literals to corresponding raw string literals?

================
Comment at: clang-tidy/modernize/RawStringLiteralCheck.cpp:57
@@ +56,3 @@
+
+  // already a raw string literal if R comes before "
+  if (Text.find_first_of("R") < Text.find_first_of(R"(")"))
----------------
nit: Capitalization, punctuation. Same for other comments in the file.

================
Comment at: clang-tidy/modernize/RawStringLiteralCheck.cpp:58
@@ +57,3 @@
+  // already a raw string literal if R comes before "
+  if (Text.find_first_of("R") < Text.find_first_of(R"(")"))
+    return false;
----------------
aaron.ballman wrote:
> I think it might make more sense to block on D16012 (which will hopefully be reviewed relatively soon), and then just use the StringLiteral object to specify whether it's a raw string literal or not.
Also, why `find_first_of` instead of just `find(char)`? It will allow you to get rid of the `R"(")"` awfulness ;)

================
Comment at: clang-tidy/modernize/RawStringLiteralCheck.cpp:61
@@ +60,3 @@
+
+  const bool HasBackSlash = Text.find(R"(\\)") != StringRef::npos;
+  const bool HasNewLine = Text.find(R"(\n)") != StringRef::npos;
----------------
I'd remove these variables and either just combine all these to a single condition (which would make the code benefit from short-circuiting) or just use a regular expression, which can be more effective than N lookups in a row (not sure for which N though). Another benefit of the regular expression is reduction of the number of `R"(`s in the code: `R"(\\[n'"?\\])"` ;).

================
Comment at: clang-tidy/modernize/RawStringLiteralCheck.cpp:77
@@ +76,3 @@
+  std::string Delimiter;
+  for (int Counter = 0; containsDelimiter(Bytes, Delimiter); ++Counter) {
+    if (Counter == 0) {
----------------
Why don't you try an empty delimiter? It will cover a majority of cases.

Also, even though the function is used only when generating fix-it hints, it still should be more effective than it is now. Most of the heap allocations and copies caused by the usage of std::ostringstream, std::string and std::string::operator+ can be avoided, e.g. like this:

  static const StringRef Delimiters[2][] =
    {{"", "R\"(", ")\""}, {"lit", "R\"lit(", ")lit\""}, {"str", "R\"str(", ")str\""},
    /* add more different ones to make it unlikely to meet all of these in a single literal in the wild */};
  for (const auto &Delim : Delimiters) {
    if (Bytes.find(Delim[2]) != StringRef::npos)
      return (Delim[1] + Bytes + Delim[2]).str();
  }
  // Give up gracefully on literals having all our delimiters.

================
Comment at: clang-tidy/modernize/RawStringLiteralCheck.cpp:107
@@ +106,3 @@
+  if (const auto *Literal = Result.Nodes.getNodeAs<StringLiteral>("lit"))
+    preferRawStringLiterals(Result, Literal);
+}
----------------
I don't see a reason to have a separate function, I'd just inline it here.

================
Comment at: clang-tidy/modernize/RawStringLiteralCheck.cpp:113
@@ +112,3 @@
+  if (containsEscapedCharacters(Result, Literal)) {
+    SourceRange ReplacementRange = Literal->getSourceRange();
+    CharSourceRange CharRange = Lexer::makeFileCharRange(
----------------
I'd just use the expression instead of the variable.

================
Comment at: clang-tidy/modernize/RawStringLiteralCheck.cpp:117
@@ +116,3 @@
+        Result.Context->getLangOpts());
+    StringRef Replacement = asRawStringLiteral(Literal);
+    diag(Literal->getLocStart(),
----------------
`Replacement` will point to deleted memory right after this line.


http://reviews.llvm.org/D16529





More information about the cfe-commits mailing list