[clang-tidy] Move formatDereference to FixitHintUtils
authorMike Crowe <mac@mcrowe.com>
Tue, 13 Jun 2023 18:15:13 +0000 (18:15 +0000)
committerPiotr Zegar <me@piotrzegar.pl>
Tue, 13 Jun 2023 18:54:49 +0000 (18:54 +0000)
I'd like to use RedundantStringCStrCheck's formatDereference function
from the up-coming modernize-use-std-print check. Let's move it to
FixItHintUtils so that the implementation can be shared.

Reviewed By: PiotrZSL

Differential Revision: https://reviews.llvm.org/D150602

clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp
clang-tools-extra/clang-tidy/utils/CMakeLists.txt
clang-tools-extra/clang-tidy/utils/FixItHintUtils.cpp
clang-tools-extra/clang-tidy/utils/FixItHintUtils.h

index 27fa07e..5bf77bb 100644 (file)
@@ -11,6 +11,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "RedundantStringCStrCheck.h"
+#include "../utils/FixItHintUtils.h"
 #include "../utils/Matchers.h"
 #include "../utils/OptionsUtils.h"
 #include "clang/Lex/Lexer.h"
@@ -22,49 +23,6 @@ namespace clang::tidy::readability {
 
 namespace {
 
-// Return true if expr needs to be put in parens when it is an argument of a
-// prefix unary operator, e.g. when it is a binary or ternary operator
-// syntactically.
-bool needParensAfterUnaryOperator(const Expr &ExprNode) {
-  if (isa<clang::BinaryOperator>(&ExprNode) ||
-      isa<clang::ConditionalOperator>(&ExprNode)) {
-    return true;
-  }
-  if (const auto *Op = dyn_cast<CXXOperatorCallExpr>(&ExprNode)) {
-    return Op->getNumArgs() == 2 && Op->getOperator() != OO_PlusPlus &&
-           Op->getOperator() != OO_MinusMinus && Op->getOperator() != OO_Call &&
-           Op->getOperator() != OO_Subscript;
-  }
-  return false;
-}
-
-// Format a pointer to an expression: prefix with '*' but simplify
-// when it already begins with '&'.  Return empty string on failure.
-std::string
-formatDereference(const ast_matchers::MatchFinder::MatchResult &Result,
-                  const Expr &ExprNode) {
-  if (const auto *Op = dyn_cast<clang::UnaryOperator>(&ExprNode)) {
-    if (Op->getOpcode() == UO_AddrOf) {
-      // Strip leading '&'.
-      return std::string(tooling::fixit::getText(
-          *Op->getSubExpr()->IgnoreParens(), *Result.Context));
-    }
-  }
-  StringRef Text = tooling::fixit::getText(ExprNode, *Result.Context);
-
-  if (Text.empty())
-    return std::string();
-
-  // Remove remaining '->' from overloaded operator call
-  Text.consume_back("->");
-
-  // Add leading '*'.
-  if (needParensAfterUnaryOperator(ExprNode)) {
-    return (llvm::Twine("*(") + Text + ")").str();
-  }
-  return (llvm::Twine("*") + Text).str();
-}
-
 AST_MATCHER(MaterializeTemporaryExpr, isBoundToLValue) {
   return Node.isBoundToLvalueReference();
 }
@@ -217,7 +175,7 @@ void RedundantStringCStrCheck::check(const MatchFinder::MatchResult &Result) {
   // Replace the "call" node with the "arg" node, prefixed with '*'
   // if the call was using '->' rather than '.'.
   std::string ArgText =
-      Arrow ? formatDereference(Result, *Arg)
+      Arrow ? utils::fixit::formatDereference(*Arg, *Result.Context)
             : tooling::fixit::getText(*Arg, *Result.Context).str();
   if (ArgText.empty())
     return;
index 4556d7b..50d1cf8 100644 (file)
@@ -37,5 +37,6 @@ clang_target_link_libraries(clangTidyUtils
   clangBasic
   clangLex
   clangSema
+  clangTooling
   clangTransformer
   )
index 4f11c9b..a0758fc 100644 (file)
@@ -9,7 +9,9 @@
 #include "FixItHintUtils.h"
 #include "LexerUtils.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/ExprCXX.h"
 #include "clang/AST/Type.h"
+#include "clang/Tooling/FixIt.h"
 #include <optional>
 
 namespace clang::tidy::utils::fixit {
@@ -221,4 +223,46 @@ std::optional<FixItHint> addQualifierToVarDecl(const VarDecl &Var,
 
   return std::nullopt;
 }
+
+// Return true if expr needs to be put in parens when it is an argument of a
+// prefix unary operator, e.g. when it is a binary or ternary operator
+// syntactically.
+static bool needParensAfterUnaryOperator(const Expr &ExprNode) {
+  if (isa<clang::BinaryOperator>(&ExprNode) ||
+      isa<clang::ConditionalOperator>(&ExprNode)) {
+    return true;
+  }
+  if (const auto *Op = dyn_cast<CXXOperatorCallExpr>(&ExprNode)) {
+    return Op->getNumArgs() == 2 && Op->getOperator() != OO_PlusPlus &&
+           Op->getOperator() != OO_MinusMinus && Op->getOperator() != OO_Call &&
+           Op->getOperator() != OO_Subscript;
+  }
+  return false;
+}
+
+// Format a pointer to an expression: prefix with '*' but simplify
+// when it already begins with '&'.  Return empty string on failure.
+std::string formatDereference(const Expr &ExprNode, const ASTContext &Context) {
+  if (const auto *Op = dyn_cast<clang::UnaryOperator>(&ExprNode)) {
+    if (Op->getOpcode() == UO_AddrOf) {
+      // Strip leading '&'.
+      return std::string(
+          tooling::fixit::getText(*Op->getSubExpr()->IgnoreParens(), Context));
+    }
+  }
+  StringRef Text = tooling::fixit::getText(ExprNode, Context);
+
+  if (Text.empty())
+    return std::string();
+
+  // Remove remaining '->' from overloaded operator call
+  Text.consume_back("->");
+
+  // Add leading '*'.
+  if (needParensAfterUnaryOperator(ExprNode)) {
+    return (llvm::Twine("*(") + Text + ")").str();
+  }
+  return (llvm::Twine("*") + Text).str();
+}
+
 } // namespace clang::tidy::utils::fixit
index 6371f99..bb5410f 100644 (file)
@@ -44,6 +44,9 @@ addQualifierToVarDecl(const VarDecl &Var, const ASTContext &Context,
                       DeclSpec::TQ Qualifier,
                       QualifierTarget CT = QualifierTarget::Pointee,
                       QualifierPolicy CP = QualifierPolicy::Left);
+
+// \brief Format a pointer to an expression
+std::string formatDereference(const Expr &ExprNode, const ASTContext &Context);
 } // namespace clang::tidy::utils::fixit
 
 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_FIXITHINTUTILS_H