jmarrec updated this revision to Diff 368881.
jmarrec added a comment.

documentation updates


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D107900/new/

https://reviews.llvm.org/D107900

Files:
  clang-tools-extra/clang-tidy/misc/CMakeLists.txt
  clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
  clang-tools-extra/clang-tidy/misc/PodConstRefToValueCheck.cpp
  clang-tools-extra/clang-tidy/misc/PodConstRefToValueCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/docs/clang-tidy/checks/misc-pod-const-ref-to-value.rst
  clang-tools-extra/test/clang-tidy/checkers/misc-pod-const-ref-to-value.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/misc-pod-const-ref-to-value.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/misc-pod-const-ref-to-value.cpp
@@ -0,0 +1,75 @@
+// RUN: %check_clang_tidy %s misc-pod-const-ref-to-value %t
+
+int f1(const int &i);
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: argument 'i' is a trivially copyable type and should not be passed by const-reference but by value [misc-pod-const-ref-to-value]
+// CHECK-FIXES: int f1(int i);
+int f2(const int &i, double d);
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: argument 'i' is a trivially copyable type and should not be passed by const-reference but by value [misc-pod-const-ref-to-value]
+// CHECK-FIXES: int f2(int i, double d);
+
+int f3(double d, const int &i);
+// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: argument 'i' is a trivially copyable type and should not be passed by const-reference but by value [misc-pod-const-ref-to-value]
+// CHECK-FIXES: int f3(double d, int i);
+
+int f4(const double &d, const double &d2);
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: argument 'd' is a trivially copyable type and should not be passed by const-reference but by value [misc-pod-const-ref-to-value]
+// CHECK-MESSAGES: :[[@LINE-2]]:25: warning: argument 'd2' is a trivially copyable type and should not be passed by const-reference but by value [misc-pod-const-ref-to-value]
+// CHECK-FIXES: int f4(double d, double d2);
+
+// clang-format off
+int f5(const int& i);
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: argument 'i' is a trivially copyable type and should not be passed by const-reference but by value [misc-pod-const-ref-to-value]
+// CHECK-FIXES: int f5(int i);
+// clang-format on
+
+namespace n1 {
+class A {
+  static int g(const double &d);
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: argument 'd' is a trivially copyable type and should not be passed by const-reference but by value [misc-pod-const-ref-to-value]
+  // CHECK-FIXES: static int g(double d);
+};
+
+int A::g(const double &d) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: argument 'd' is a trivially copyable type and should not be passed by const-reference but by value [misc-pod-const-ref-to-value]
+  // CHECK-FIXES: int A::g(double d) {
+  return static_cast<int>(d);
+}
+} // namespace n1
+
+// Not triggering the check
+
+int f5(int i);
+int f6(int i, double d);
+int f7(int &i); // Might be used for return...
+
+namespace n2 {
+class A {
+  static int g(double d);
+};
+
+int A::g(double d) {
+  return static_cast<int>(d);
+}
+
+class B {
+  static int g(double &d);
+};
+
+int B::g(double &d) {
+  return static_cast<int>(d);
+}
+} // namespace n2
+
+template <typename... Args>
+void f(Args &&...args);
+
+struct Widget {
+  int a[1000];
+};
+void f(const Widget &);
+
+template <class T>
+struct Max {
+  static T max(const T &a, const T &b);
+};
+int x = Max<int>::max(1, 2); // passes `int` by const reference, but this is fine
Index: clang-tools-extra/docs/clang-tidy/checks/misc-pod-const-ref-to-value.rst
===================================================================
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/misc-pod-const-ref-to-value.rst
@@ -0,0 +1,25 @@
+.. title:: clang-tidy - misc-pod-const-ref-to-value
+
+misc-pod-const-ref-to-value
+===========================
+
+This check detects when ``trivially_copyable`` types are passed by const-reference
+to a function and changes that to by value/
+
+For example in the following code, it is replaced by ``void f(int i, double d)``:
+
+.. code-block:: c++
+
+  void f(const int& i, const double& d);
+
+
+Options
+-------
+
+.. option:: RestrictToBuiltInTypes
+
+   If set to `true`, this check will limit itself to the `builtinType()` types. Default is `false`.
+
+.. option:: MaxSize
+
+   MaxSize: int, default 16. Above this size, passing by const-reference makes sense
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===================================================================
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -215,6 +215,7 @@
    `misc-no-recursion <misc-no-recursion.html>`_,
    `misc-non-copyable-objects <misc-non-copyable-objects.html>`_,
    `misc-non-private-member-variables-in-classes <misc-non-private-member-variables-in-classes.html>`_,
+   `misc-pod-const-ref-to-value <misc-pod-const-ref-to-value.html>`_, "Yes"
    `misc-redundant-expression <misc-redundant-expression.html>`_, "Yes"
    `misc-static-assert <misc-static-assert.html>`_, "Yes"
    `misc-throw-by-value-catch-by-reference <misc-throw-by-value-catch-by-reference.html>`_,
Index: clang-tools-extra/docs/ReleaseNotes.rst
===================================================================
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -82,6 +82,12 @@
 
   Reports identifiers whose names are too short. Currently checks local variables and function parameters only.
 
+- New :doc:`misc-pod-const-ref-to-value
+  <clang-tidy/checks/misc-pod-const-ref-to-value>` check.
+
+  Finds when ``trivially_copyable`` types are passed by const-reference to a function
+  and changes that to by value.
+
 New check aliases
 ^^^^^^^^^^^^^^^^^
 
Index: clang-tools-extra/clang-tidy/misc/PodConstRefToValueCheck.h
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/misc/PodConstRefToValueCheck.h
@@ -0,0 +1,39 @@
+//===--- PodConstRefToValueCheck.h - clang-tidy -----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_PODCONSTREFTOVALUECHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_PODCONSTREFTOVALUECHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+/// The check detects when trivially_copyable types are passed by
+/// const-reference to a function and changes that to by value.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/misc-pod-const-ref-to-value.html
+class PodConstRefToValueCheck : public ClangTidyCheck {
+public:
+  PodConstRefToValueCheck(StringRef Name, ClangTidyContext *Context);
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+
+private:
+  const bool RestrictToBuiltInTypes;
+  const int MaxSize = 16;
+};
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_PODCONSTREFTOVALUECHECK_H
Index: clang-tools-extra/clang-tidy/misc/PodConstRefToValueCheck.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/misc/PodConstRefToValueCheck.cpp
@@ -0,0 +1,133 @@
+//===--- PodConstRefToValueCheck.cpp - clang-tidy -------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "PodConstRefToValueCheck.h"
+#include "../utils/LexerUtils.h"
+#include "../utils/OptionsUtils.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+bool isSharedPtr(const QualType &T) {
+  if (auto *R = T->getAsCXXRecordDecl())
+    return R->getQualifiedNameAsString() == "std::shared_ptr" ||
+           R->getQualifiedNameAsString() == "boost::shared_ptr";
+  return false;
+}
+
+SourceRange getTypeRange(const ParmVarDecl &Param) {
+  return SourceRange(Param.getBeginLoc(),
+                     Param.getLocation().getLocWithOffset(-1));
+}
+
+PodConstRefToValueCheck::PodConstRefToValueCheck(StringRef Name,
+                                                 ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      RestrictToBuiltInTypes(Options.get("RestrictToBuiltInTypes", false)),
+      MaxSize(16) {}
+
+void PodConstRefToValueCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "RestrictToBuiltInTypes", RestrictToBuiltInTypes);
+  Options.store(Opts, "MaxSize", MaxSize);
+}
+
+void PodConstRefToValueCheck::registerMatchers(MatchFinder *Finder) {
+  if (RestrictToBuiltInTypes) {
+    Finder->addMatcher(
+        functionDecl(
+            allOf(has(typeLoc(forEach(
+                      parmVarDecl(hasType(referenceType(pointee(qualType(
+                                      isConstQualified(), builtinType())))))
+                          .bind("param")))),
+                  unless(ast_matchers::isTemplateInstantiation())))
+            .bind("func"),
+        this);
+  } else {
+    Finder->addMatcher(
+        functionDecl(allOf(has(typeLoc(forEach(
+                               parmVarDecl(hasType(referenceType(pointee(
+                                               qualType(isConstQualified())))))
+                                   .bind("param")))),
+                           unless(ast_matchers::isTemplateInstantiation())))
+            .bind("func"),
+        this);
+  }
+}
+
+void PodConstRefToValueCheck::check(const MatchFinder::MatchResult &Result) {
+
+  const auto *FuncDecl = Result.Nodes.getNodeAs<FunctionDecl>("func");
+  const auto *ParamDecl = Result.Nodes.getNodeAs<ParmVarDecl>("param");
+
+  // if (!ParamDecl->getType().isLocalConstQualified()) {
+  //  return;
+  // }
+
+  const QualType &T = ParamDecl->getType().getNonReferenceType();
+
+  // If the parameter is NOT trivial to copy, const-ref makes sense
+  if (!T.isTriviallyCopyableType(*Result.Context)) {
+    return;
+  }
+
+  // Skip shared_ptr
+  if (isSharedPtr(T)) {
+    return;
+  }
+
+  // Skip types whose size is unknown or greater than MaxSize
+  Optional<CharUnits> Size = Result.Context->getTypeSizeInCharsIfKnown(T);
+  if (!Size.hasValue() || Size->getQuantity() > MaxSize) {
+    return;
+  }
+
+  auto Diag = diag(ParamDecl->getBeginLoc(),
+                   "argument %0 is a trivially copyable type and should not be "
+                   "passed by const-reference but by value");
+  if (ParamDecl->getName().empty()) {
+    for (unsigned int I = 0; I < FuncDecl->getNumParams(); ++I) {
+      if (ParamDecl == FuncDecl->getParamDecl(I)) {
+        Diag << (I + 1);
+        break;
+      }
+    }
+  } else {
+    Diag << ParamDecl;
+  }
+
+  // CharSourceRange FileRange = Lexer::makeFileCharRange(
+  // CharSourceRange::getTokenRange(getTypeRange(*ParamDecl)),
+  //*Result.SourceManager, getLangOpts());
+
+  // if (!FileRange.isValid()) {
+  // return;
+  //}
+
+  // auto Tok = tidy::utils::lexer::getQualifyingToken(
+  // tok::kw_const, FileRange, *Result.Context, *Result.SourceManager);
+  // if (!Tok)
+  // return;
+
+  Diag << FixItHint::CreateReplacement(
+      getTypeRange(*ParamDecl),
+      ParamDecl->getType()
+              .getNonReferenceType()
+              .getUnqualifiedType()
+              .getAsString(Result.Context->getPrintingPolicy()) +
+          " ");
+}
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
Index: clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
===================================================================
--- clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
+++ clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
@@ -15,6 +15,7 @@
 #include "NoRecursionCheck.h"
 #include "NonCopyableObjects.h"
 #include "NonPrivateMemberVariablesInClassesCheck.h"
+#include "PodConstRefToValueCheck.h"
 #include "RedundantExpressionCheck.h"
 #include "StaticAssertCheck.h"
 #include "ThrowByValueCatchByReferenceCheck.h"
@@ -41,6 +42,8 @@
         "misc-non-copyable-objects");
     CheckFactories.registerCheck<NonPrivateMemberVariablesInClassesCheck>(
         "misc-non-private-member-variables-in-classes");
+    CheckFactories.registerCheck<PodConstRefToValueCheck>(
+        "misc-pod-const-ref-to-value");
     CheckFactories.registerCheck<RedundantExpressionCheck>(
         "misc-redundant-expression");
     CheckFactories.registerCheck<StaticAssertCheck>("misc-static-assert");
Index: clang-tools-extra/clang-tidy/misc/CMakeLists.txt
===================================================================
--- clang-tools-extra/clang-tidy/misc/CMakeLists.txt
+++ clang-tools-extra/clang-tidy/misc/CMakeLists.txt
@@ -11,6 +11,7 @@
   NoRecursionCheck.cpp
   NonCopyableObjects.cpp
   NonPrivateMemberVariablesInClassesCheck.cpp
+  PodConstRefToValueCheck.cpp
   RedundantExpressionCheck.cpp
   StaticAssertCheck.cpp
   ThrowByValueCatchByReferenceCheck.cpp
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to