njames93 updated this revision to Diff 240584.
njames93 marked an inline comment as done.
njames93 added a comment.

- Added test case when the inc and dec operators are found in a base class


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D72553

Files:
  clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp
  clang-tools-extra/clang-tidy/performance/CMakeLists.txt
  clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
  clang-tools-extra/clang-tidy/performance/PreferPreIncrementCheck.cpp
  clang-tools-extra/clang-tidy/performance/PreferPreIncrementCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/docs/clang-tidy/checks/llvm-prefer-pre-increment.rst
  clang-tools-extra/docs/clang-tidy/checks/performance-prefer-pre-increment.rst
  
clang-tools-extra/test/clang-tidy/checkers/Inputs/performance-prefer-pre-increment/iterator.h
  
clang-tools-extra/test/clang-tidy/checkers/performance-prefer-pre-increment-disable-cpp-opcalls.cpp
  clang-tools-extra/test/clang-tidy/checkers/performance-prefer-pre-increment.c
  
clang-tools-extra/test/clang-tidy/checkers/performance-prefer-pre-increment.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/performance-prefer-pre-increment.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/performance-prefer-pre-increment.cpp
@@ -0,0 +1,55 @@
+// RUN: %check_clang_tidy %s performance-prefer-pre-increment %t -- -- \
+// RUN: -I%S/Inputs/performance-prefer-pre-increment
+
+#include "iterator.h"
+
+class IntIterator : public Iterator<int>{
+  using Iterator<int>::Iterator;
+};
+
+void foo() {
+  int Array[32];
+  Iterator<int> It(&Array[0]);
+  It++; // fooNormal
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Use pre-increment instead of post-increment
+  // CHECK-FIXES: {{^}}  ++It; // fooNormal
+  It--; // fooNormal
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Use pre-decrement instead of post-decrement
+  // CHECK-FIXES: {{^}}  --It; // fooNormal
+  (*It)++; // fooNormal
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Use pre-increment instead of post-increment
+  // CHECK-FIXES: {{^}}  ++(*It); // fooNormal
+  (*It)--; // fooNormal
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Use pre-decrement instead of post-decrement
+  // CHECK-FIXES: {{^}}  --(*It); // fooNormal
+  *It++; // fooNormal
+  *It--; // fooNormal
+
+  PostfixIterator<int> PfIt(&Array[0]);
+  PfIt++; // fooPostfix
+  PfIt--; // fooPostfix
+  (*PfIt)++; // fooPostfix
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Use pre-increment instead of post-increment
+  // CHECK-FIXES: {{^}}  ++(*PfIt); // fooPostfix
+  (*PfIt)--; // fooPostfix
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Use pre-decrement instead of post-decrement
+  // CHECK-FIXES: {{^}}  --(*PfIt); // fooPostfix
+  *PfIt++; // fooPostfix
+  *PfIt--; // fooPostfix
+
+  IntIterator IntIt(&Array[0]);
+  IntIt++;
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Use pre-increment instead of post-increment
+  // CHECK-FIXES: {{^}}  ++IntIt;
+  IntIt--;
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Use pre-decrement instead of post-decrement
+  // CHECK-FIXES: {{^}}  --IntIt;
+  (*IntIt)++;
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Use pre-increment instead of post-increment
+  // CHECK-FIXES: {{^}}  ++(*IntIt);
+  (*IntIt)--;
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Use pre-decrement instead of post-decrement
+  // CHECK-FIXES: {{^}}  --(*IntIt);
+  *IntIt++;
+  *IntIt--;
+}
Index: clang-tools-extra/test/clang-tidy/checkers/performance-prefer-pre-increment.c
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/performance-prefer-pre-increment.c
@@ -0,0 +1,128 @@
+// RUN: %check_clang_tidy %s performance-prefer-pre-increment %t
+
+#define INC(X) X++
+#define DEC(X) X--
+
+void foo(int A) {
+  for (int I = 0; I < 10; I++) {
+    // CHECK-MESSAGES: [[@LINE-1]]:27: warning: Use pre-increment instead of post-increment
+    // CHECK-FIXES: {{^}}  for (int I = 0; I < 10; ++I) {
+  }
+  for (int I = 0; I < 10; ++I) {
+    // CHECK-MESSAGES-NOT: [[@LINE-1]]:{{\d*}}: warning: Use pre-increment instead of post-increment
+  }
+  for (int I = 0; I < 10; A = I++) {
+    // CHECK-MESSAGES-NOT: [[@LINE-1]]:{{\d*}}: warning: Use pre-increment instead of post-increment
+  }
+
+  for (int I = 10; I < 0; I--) {
+    // CHECK-MESSAGES: [[@LINE-1]]:27: warning: Use pre-decrement instead of post-decrement
+    // CHECK-FIXES: {{^}}  for (int I = 10; I < 0; --I) {
+  }
+  for (int I = 10; I < 0; --I) {
+    // CHECK-MESSAGES-NOT: [[@LINE-1]]:{{\d*}}: warning: Use pre-decrement instead of post-decrement
+  }
+  for (int I = 10; I < 0; A = I--) {
+    // CHECK-MESSAGES-NOT: [[@LINE-1]]:{{\d*}}: warning: Use pre-decrement instead of post-decrement
+  }
+
+  for (int I = 0; I < 10; INC(I)) {
+    // CHECK-MESSAGES: [[@LINE-1]]:31: warning: Use pre-increment instead of post-increment
+  }
+  for (int I = 0; I < 10; DEC(I)) {
+    // CHECK-MESSAGES: [[@LINE-1]]:31: warning: Use pre-decrement instead of post-decrement
+  }
+  for (int I = 0; I < 10; A = INC(I)) {
+    // CHECK-MESSAGES-NOT: [[@LINE-1]]:{{\d*}}: warning: Use pre-increment instead of post-increment
+  }
+}
+
+void bar(int *Begin, int *End) {
+  for (int *I = Begin; I != End;) {
+    *I++ = 0;
+    // CHECK-MESSAGES-NOT: [[@LINE-1]]:{{\d*}}: warning: Use pre-increment instead of post-increment
+  }
+  for (int *I = Begin; I != End; I++) {
+    // CHECK-MESSAGES: [[@LINE-1]]:34: warning: Use pre-increment instead of post-increment
+    // CHECK-FIXES: {{^}}  for (int *I = Begin; I != End; ++I) {
+    *I = 0;
+  }
+  for (int *I = Begin; I != End; ++I) {
+    // CHECK-MESSAGES-NOT: [[@LINE-1]]:{{\d*}}: warning: Use pre-increment instead of post-increment
+    *I = 0;
+  }
+  for (int *I = Begin; I != End; I++) {
+    // CHECK-MESSAGES: [[@LINE-1]]:34: warning: Use pre-increment instead of post-increment
+    // CHECK-FIXES: {{^}}  for (int *I = Begin; I != End; ++I) {
+    (*I)++; // c1
+    // CHECK-MESSAGES: [[@LINE-1]]:5: warning: Use pre-increment instead of post-increment
+    // CHECK-FIXES: {{^}}    ++(*I); // c1
+    (*I)++; // c2
+    // CHECK-MESSAGES: [[@LINE-1]]:5: warning: Use pre-increment instead of post-increment
+    // CHECK-FIXES: {{^}}    ++(*I); // c2
+    (*I)++; // c3
+    // CHECK-MESSAGES: [[@LINE-1]]:5: warning: Use pre-increment instead of post-increment
+    // CHECK-FIXES: {{^}}    ++(*I); // c3
+  }
+}
+
+int handle(int);
+
+void baz() {
+  int I = 0;
+  handle(I++);
+  // CHECK-MESSAGES-NOT: [[@LINE-1]]:{{\d*}}: warning: Use pre-increment instead of post-increment
+  int J = I++;
+  // CHECK-MESSAGES-NOT: [[@LINE-1]]:{{\d*}}: warning: Use pre-increment instead of post-increment
+  if (J++) {
+  }
+  // CHECK-MESSAGES-NOT: [[@LINE-2]]:{{\d*}}: warning: Use pre-increment instead of post-increment
+  switch (J++) {}
+  // CHECK-MESSAGES-NOT: [[@LINE-1]]:{{\d*}}: warning: Use pre-increment instead of post-increment
+  while (J++) {
+  }
+  // CHECK-MESSAGES-NOT: [[@LINE-2]]:{{\d*}}: warning: Use pre-increment instead of post-increment
+  do {
+  } while (J++);
+  // CHECK-MESSAGES-NOT: [[@LINE-1]]:{{\d*}}: warning: Use pre-increment instead of post-increment
+  for (; J++;) {
+  }
+  // CHECK-MESSAGES-NOT: [[@LINE-2]]:{{\d*}}: warning: Use pre-increment instead of post-increment
+  J++ ? J-- : J++;
+  // CHECK-MESSAGES-NOT: [[@LINE-1]]:{{\d*}}: warning: Use pre-increment instead of post-increment
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wgnu-conditional-omitted-operand"
+  J++ ?: J--;
+  // CHECK-MESSAGES-NOT: [[@LINE-1]]:{{\d*}}: warning: Use pre-increment instead of post-increment
+#pragma clang diagnostic pop
+  J++;
+  // CHECK-MESSAGES: [[@LINE-1]]:{{3}}: warning: Use pre-increment instead of post-increment
+  // CHECK-FIXES: {{^}}  ++J;
+}
+
+struct Foo {
+  int Bar;
+};
+
+struct Baz {
+  struct Foo Bar;
+};
+
+int foobar(struct Baz Foobar, struct Foo *Bar) {
+  Foobar.Bar.Bar++;
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Use pre-increment instead of post-increment
+  // CHECK-FIXES: {{^}}  ++Foobar.Bar.Bar;
+  Bar->Bar++;
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Use pre-increment instead of post-increment
+  // CHECK-FIXES: {{^}}  ++Bar->Bar;
+  // clang-format off
+  Foobar.
+  Bar.
+  Bar++;
+  // CHECK-MESSAGES: [[@LINE-3]]:3: warning: Use pre-increment instead of post-increment
+  // CHECK-FIXES:      {{^}}  ++Foobar.
+  // CHECK-FIXES-NEXT: {{^}}  Bar.
+  // CHECK-FIXES-NEXT: {{^}}  Bar;
+  // clang-format on
+  return Bar->Bar++;
+}
Index: clang-tools-extra/test/clang-tidy/checkers/performance-prefer-pre-increment-disable-cpp-opcalls.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/performance-prefer-pre-increment-disable-cpp-opcalls.cpp
@@ -0,0 +1,47 @@
+// RUN: %check_clang_tidy %s performance-prefer-pre-increment %t -- \
+// RUN: -config='{CheckOptions: \
+// RUN:  [{key: performance-prefer-pre-increment.TransformCxxOpCalls, value: 0}]}' \
+// RUN: -- -I%S/Inputs/performance-prefer-pre-increment
+
+#include "iterator.h"
+
+void foo() {
+  int Array[32];
+  Iterator<int> It(&Array[0]);
+  It++;
+  // CHECK-MESSAGES-NOT: [[@LINE-1]]:{{\d*}}: warning: Use pre-increment instead of post-increment
+  // CHECK-FIXES-NOT: {{^}}  ++It;
+  It--;
+  // CHECK-MESSAGES-NOT: [[@LINE-1]]:{{\d*}}: warning: Use pre-decrement instead of post-decrement
+  // CHECK-FIXES-NOT: {{^}}  --It;
+  (*It)++;
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Use pre-increment instead of post-increment
+  // CHECK-FIXES: {{^}}  ++(*It);
+  (*It)--;
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Use pre-decrement instead of post-decrement
+  // CHECK-FIXES: {{^}}  --(*It);
+
+  *It++;
+  // CHECK-MESSAGES-NOT: [[@LINE-1]]:{{\d*}}: warning: Use pre-increment instead of post-increment
+  *It--;
+  // CHECK-MESSAGES-NOT: [[@LINE-1]]:{{\d*}}: warning: Use pre-decrement instead of post-decrement
+
+  PostfixIterator<int> PfIt(&Array[0]);
+  PfIt++;
+  // CHECK-MESSAGES-NOT: [[@LINE-1]]:{{\d*}}: warning: Use pre-increment instead of post-increment
+  // CHECK-FIXES-NOT: {{^}}  ++PfIt;
+  PfIt--;
+  // CHECK-MESSAGES-NOT: [[@LINE-1]]:{{\d*}}: warning: Use pre-decrement instead of post-decrement
+  // CHECK-FIXES-NOT: {{^}}  --PfIt;
+  (*PfIt)++;
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Use pre-increment instead of post-increment
+  // CHECK-FIXES: {{^}}  ++(*PfIt);
+  (*PfIt)--;
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Use pre-decrement instead of post-decrement
+  // CHECK-FIXES: {{^}}  --(*PfIt);
+
+  *PfIt++;
+  // CHECK-MESSAGES-NOT: [[@LINE-1]]:4: warning: Use pre-increment instead of post-increment
+  *PfIt--;
+  // CHECK-MESSAGES-NOT: [[@LINE-1]]:4: warning: Use pre-decrement instead of post-decrement
+}
Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/performance-prefer-pre-increment/iterator.h
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/Inputs/performance-prefer-pre-increment/iterator.h
@@ -0,0 +1,44 @@
+#ifndef PERFORMANCE_PREFER_PRE_INCREMENT_ITERATOR_H
+#define PERFORMANCE_PREFER_PRE_INCREMENT_ITERATOR_H
+
+template <typename T>
+class Iterator {
+  T *Current;
+
+public:
+  Iterator(T *Pointer) : Current(Pointer) {}
+  T &operator*() const { return *Current; }
+  Iterator &operator++() { return ++Current, *this; }
+  Iterator operator++(int) {
+    Iterator Copy = *this;
+    ++Current;
+    return Copy;
+  }
+  Iterator &operator--() { return --Current, *this; }
+  Iterator operator--(int) {
+    Iterator Copy = *this;
+    --Current;
+    return Copy;
+  }
+};
+
+template <typename T>
+class PostfixIterator {
+  T *Current;
+
+public:
+  PostfixIterator(T *Pointer) : Current(Pointer) {}
+  T &operator*() const { return *Current; }
+  PostfixIterator operator++(int) {
+    PostfixIterator Copy = *this;
+    ++Current;
+    return Copy;
+  }
+  PostfixIterator operator--(int) {
+    PostfixIterator Copy = *this;
+    --Current;
+    return Copy;
+  }
+};
+
+#endif // PERFORMANCE_PREFER_PRE_INCREMENT_ITERATOR_H
Index: clang-tools-extra/docs/clang-tidy/checks/performance-prefer-pre-increment.rst
===================================================================
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/performance-prefer-pre-increment.rst
@@ -0,0 +1,33 @@
+.. title:: clang-tidy - performance-prefer-pre-increment
+
+performance-prefer-pre-increment
+================================
+
+Flags usages of the unary postfix increment and decrement operators where the
+result isnt used which could be replaced with the more efficient prefix variety.
+
+.. code-block:: c++
+
+  // Finds these
+  for (int I = 0; I < 10; I++) {}
+  (*Ptr)++;
+  // Replaces with
+  for (int I = 0; I < 10; ++I) {}
+  ++(*Ptr);
+
+  // Doesn't replace these
+  *Ptr++ = 0;
+  call(I++);
+  Index = I++;
+
+Options
+-------
+
+.. option:: TransformCxxOpCalls
+
+   Enables checking postfix operations on classes and structures that overload
+   both the prefix and postfix operator ``++`` or ``--``.
+   Default value is `1`.
+
+This check helps to enforce this `LLVM Coding Standards recommendation
+<https://llvm.org/docs/CodingStandards.html#prefer-preincrement>`_.
Index: clang-tools-extra/docs/clang-tidy/checks/llvm-prefer-pre-increment.rst
===================================================================
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/llvm-prefer-pre-increment.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - llvm-prefer-pre-increment
+.. meta::
+   :http-equiv=refresh: 5;URL=performance-prefer-pre-increment.html
+
+llvm-prefer-pre-increment
+=========================
+
+The llvm-prefer-pre-increment check is an alias, please see
+`performance-prefer-pre-increment <performance-prefer-pre-increment.html>`_
+for more information.
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
@@ -248,6 +248,7 @@
    `performance-move-constructor-init <performance-move-constructor-init.html>`_, "Yes"
    `performance-no-automatic-move <performance-no-automatic-move.html>`_,
    `performance-noexcept-move-constructor <performance-noexcept-move-constructor.html>`_, "Yes"
+   `performance-prefer-pre-increment <performance-prefer-pre-increment.html>`_, "Yes"
    `performance-trivially-destructible <performance-trivially-destructible.html>`_, "Yes"
    `performance-type-promotion-in-math-fn <performance-type-promotion-in-math-fn.html>`_, "Yes"
    `performance-unnecessary-copy-initialization <performance-unnecessary-copy-initialization.html>`_,
@@ -405,4 +406,5 @@
    `hicpp-use-nullptr <hicpp-use-nullptr.html>`_, `modernize-use-nullptr <modernize-use-nullptr.html>`_, "Yes"
    `hicpp-use-override <hicpp-use-override.html>`_, `modernize-use-override <modernize-use-override.html>`_, "Yes"
    `hicpp-vararg <hicpp-vararg.html>`_, `cppcoreguidelines-pro-type-vararg <cppcoreguidelines-pro-type-vararg.html>`_,
+   `llvm-prefer-pre-increment <llvm-prefer-pre-increment.html>`_, `performance-prefer-pre-increment <performance-prefer-pre-increment.html>`_, "Yes"
    `llvm-qualified-auto <llvm-qualified-auto.html>`_, `readability-qualified-auto <readability-qualified-auto.html>`_, "Yes"
Index: clang-tools-extra/docs/ReleaseNotes.rst
===================================================================
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -87,6 +87,12 @@
   
   Flags use of the `C` standard library functions ``memset``, ``memcpy`` and
   ``memcmp`` and similar derivatives on non-trivial types.
+  
+- New :doc:`performance-prefer-pre-increment
+  <clang-tidy/checks/performance-prefer-pre-increment>` check.
+
+  Flags usages of postfix increment and decrement which could be swapped for
+  their prefix alternatives.
 
 New aliases
 ^^^^^^^^^^^
@@ -100,6 +106,11 @@
   <clang-tidy/checks/cert-dcl51-cpp>` to
   :doc:`bugprone-reserved-identifier
   <clang-tidy/checks/bugprone-reserved-identifier>` was added.
+  
+- New alias :doc:`llvm-prefer-pre-increment
+  <clang-tidy/checks/llvm-prefer-pre-increment>` to
+  :doc:`performance-prefer-pre-increment
+  <clang-tidy/checks/performance-prefer-pre-increment>` was added.
 
 Changes in existing checks
 ^^^^^^^^^^^^^^^^^^^^^^^^^^
Index: clang-tools-extra/clang-tidy/performance/PreferPreIncrementCheck.h
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/performance/PreferPreIncrementCheck.h
@@ -0,0 +1,41 @@
+//===--- PreferPreIncrementCheck.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_PERFORMANCE_PREFERPREINCREMENTCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_PREFERPREINCREMENTCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace performance {
+
+///  Flags usages of postfix increment and decrement which could be swapped for
+///  their prefix alternatives.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/performance-prefer-pre-increment.html
+class PreferPreIncrementCheck : public ClangTidyCheck {
+public:
+  PreferPreIncrementCheck(StringRef Name, ClangTidyContext *Context);
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  void applyReplacement(SourceRange Range, SourceLocation OperatorLoc,
+                        bool IsIncrement);
+
+  const bool TransformCxxOpCalls;
+};
+
+} // namespace performance
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_PREFERPREINCREMENTCHECK_H
Index: clang-tools-extra/clang-tidy/performance/PreferPreIncrementCheck.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/performance/PreferPreIncrementCheck.cpp
@@ -0,0 +1,115 @@
+//===--- PreferPreIncrementCheck.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 "PreferPreIncrementCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Tooling/FixIt.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace performance {
+
+namespace {
+AST_MATCHER_P(UnaryOperator, isOperator, UnaryOperatorKind, Opcode) {
+  return Node.getOpcode() == Opcode;
+}
+} // namespace
+
+PreferPreIncrementCheck::PreferPreIncrementCheck(StringRef Name,
+                                                 ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      TransformCxxOpCalls(Options.get("TransformCxxOpCalls", 1) != 0) {}
+
+void PreferPreIncrementCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "TransformCxxOpCalls", TransformCxxOpCalls);
+}
+
+void PreferPreIncrementCheck::registerMatchers(MatchFinder *Finder) {
+  // Ignore all unary ops with a parent decl or expr, those use the value
+  // returned. Reordering those would change the behaviour of the expression.
+  // FIXME: Add any more parents which could use the result of the operation.
+  auto BadParents =
+      unless(anyOf(hasParent(decl()), hasParent(expr()),
+                   hasParent(returnStmt()), hasParent(cxxThrowExpr())));
+  auto BoundExpr = expr().bind("ignore");
+  auto BoundChecks =
+      anyOf(hasParent(ifStmt(hasCondition(BoundExpr))),
+            hasParent(forStmt(hasCondition(BoundExpr))),
+            hasParent(switchStmt(hasCondition(BoundExpr))),
+            hasParent(whileStmt(hasCondition(BoundExpr))),
+            hasParent(doStmt(hasCondition(BoundExpr))),
+            hasParent(conditionalOperator(hasCondition(BoundExpr))),
+            hasParent(binaryConditionalOperator(hasCondition(BoundExpr))));
+
+  auto UnusedInParent =
+      allOf(BadParents, unless(allOf(BoundChecks, equalsBoundNode("ignore"))));
+
+  Finder->addMatcher(
+      unaryOperator(isOperator(UnaryOperatorKind::UO_PostInc), UnusedInParent)
+          .bind("op++"),
+      this);
+  Finder->addMatcher(
+      unaryOperator(isOperator(UnaryOperatorKind::UO_PostDec), UnusedInParent)
+          .bind("op--"),
+      this);
+
+  if (!getLangOpts().CPlusPlus || !TransformCxxOpCalls)
+    return;
+
+  auto FindCxxOpCalls = [&](llvm::StringRef PostfixName) {
+    Finder->addMatcher(
+        cxxOperatorCallExpr(
+            UnusedInParent,
+            callee(cxxMethodDecl(
+                hasName(PostfixName), parameterCountIs(1),
+                hasParent(cxxRecordDecl(hasMethod(cxxMethodDecl(
+                    hasName(PostfixName), parameterCountIs(0))))))))
+            .bind(PostfixName),
+        this);
+  };
+  FindCxxOpCalls("operator++");
+  FindCxxOpCalls("operator--");
+}
+
+void PreferPreIncrementCheck::applyReplacement(SourceRange Range,
+                                               SourceLocation OperatorLoc,
+                                               bool IsIncrement) {
+  // Warn for all occurances, but don't fix macro usage.
+  DiagnosticBuilder Diag =
+      diag(Range.getBegin(), "Use pre-%0 instead of post-%0")
+      << (IsIncrement ? "increment" : "decrement");
+  if (OperatorLoc.isMacroID() || Range.getBegin().isMacroID() ||
+      Range.getEnd().isMacroID())
+    return;
+  Diag << tooling::fixit::createRemoval(OperatorLoc);
+  Diag << FixItHint::CreateInsertion(Range.getBegin(),
+                                     IsIncrement ? "++" : "--");
+}
+
+void PreferPreIncrementCheck::check(const MatchFinder::MatchResult &Result) {
+  if (const auto *UnaryOp = Result.Nodes.getNodeAs<UnaryOperator>("op++"))
+    return applyReplacement(UnaryOp->getSourceRange(),
+                            UnaryOp->getOperatorLoc(), true);
+  if (const auto *UnaryOp = Result.Nodes.getNodeAs<UnaryOperator>("op--"))
+    return applyReplacement(UnaryOp->getSourceRange(),
+                            UnaryOp->getOperatorLoc(), false);
+  if (const auto *OpCall =
+          Result.Nodes.getNodeAs<CXXOperatorCallExpr>("operator++"))
+    return applyReplacement(OpCall->getSourceRange(), OpCall->getOperatorLoc(),
+                            true);
+  if (const auto *OpCall =
+          Result.Nodes.getNodeAs<CXXOperatorCallExpr>("operator--"))
+    return applyReplacement(OpCall->getSourceRange(), OpCall->getOperatorLoc(),
+                            false);
+}
+
+} // namespace performance
+} // namespace tidy
+} // namespace clang
Index: clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
===================================================================
--- clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
+++ clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
@@ -19,6 +19,7 @@
 #include "MoveConstructorInitCheck.h"
 #include "NoAutomaticMoveCheck.h"
 #include "NoexceptMoveConstructorCheck.h"
+#include "PreferPreIncrementCheck.h"
 #include "TriviallyDestructibleCheck.h"
 #include "TypePromotionInMathFnCheck.h"
 #include "UnnecessaryCopyInitialization.h"
@@ -51,6 +52,8 @@
         "performance-no-automatic-move");
     CheckFactories.registerCheck<NoexceptMoveConstructorCheck>(
         "performance-noexcept-move-constructor");
+    CheckFactories.registerCheck<PreferPreIncrementCheck>(
+        "performance-prefer-pre-increment");
     CheckFactories.registerCheck<TriviallyDestructibleCheck>(
         "performance-trivially-destructible");
     CheckFactories.registerCheck<TypePromotionInMathFnCheck>(
Index: clang-tools-extra/clang-tidy/performance/CMakeLists.txt
===================================================================
--- clang-tools-extra/clang-tidy/performance/CMakeLists.txt
+++ clang-tools-extra/clang-tidy/performance/CMakeLists.txt
@@ -12,6 +12,7 @@
   NoAutomaticMoveCheck.cpp
   NoexceptMoveConstructorCheck.cpp
   PerformanceTidyModule.cpp
+  PreferPreIncrementCheck.cpp
   TriviallyDestructibleCheck.cpp
   TypePromotionInMathFnCheck.cpp
   UnnecessaryCopyInitialization.cpp
Index: clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp
===================================================================
--- clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp
+++ clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp
@@ -9,6 +9,7 @@
 #include "../ClangTidy.h"
 #include "../ClangTidyModule.h"
 #include "../ClangTidyModuleRegistry.h"
+#include "../performance/PreferPreIncrementCheck.h"
 #include "../readability/NamespaceCommentCheck.h"
 #include "../readability/QualifiedAutoCheck.h"
 #include "HeaderGuardCheck.h"
@@ -30,6 +31,8 @@
         "llvm-namespace-comment");
     CheckFactories.registerCheck<PreferIsaOrDynCastInConditionalsCheck>(
         "llvm-prefer-isa-or-dyn-cast-in-conditionals");
+    CheckFactories.registerCheck<performance::PreferPreIncrementCheck>(
+        "llvm-prefer-pre-increment");
     CheckFactories.registerCheck<PreferRegisterOverUnsignedCheck>(
         "llvm-prefer-register-over-unsigned");
     CheckFactories.registerCheck<readability::QualifiedAutoCheck>(
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to