njames93 updated this revision to Diff 244555.
njames93 added a comment.
- Added option to enable transforming template dependent types
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,63 @@
+// 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--;
+}
+
+template <typename T>
+void tempDependent(){
+ typename T::iterator it;
+ it++; //depType
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Use pre-increment instead of post-increment
+ // CHECK-FIXES-NOT: {{^}} ++it; //depType
+}
\ No newline at end of file
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,57 @@
+.. 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
+
+ When set to `1`, this enables checking postfix operations on classes and
+ structures that overload both the prefix and postfix operator ``++`` or
+ ``--``.
+ Default value is `1`.
+
+.. option:: TransformDependentType
+
+ When set to `1`, this will change all postfix operators that are template
+ dependent to their prefix variation. This can cause errors if instantiations
+ don't overload the prefix ``++`` or ``--`` operator.
+ Default value is `0`.
+
+.. code-block:: c++
+
+ template <typename T>
+ void Inc(T& val) {
+ val++;
+ }
+
+When `TransformDependentType` is set to `1` becomes:
+
+.. code-block:: c++
+
+ template <typename T>
+ void Inc(T& val) {
+ ++val;
+ }
+
+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
@@ -249,6 +249,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>`_,
@@ -406,4 +407,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 :doc:`objc-dealloc-in-category
<clang-tidy/checks/objc-dealloc-in-category>` check.
@@ -105,6 +111,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,42 @@
+//===--- 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 processMatch(SourceRange Range, SourceLocation OperatorLoc,
+ bool IsIncrement, bool WarnOnly);
+
+ const bool TransformCxxOpCalls;
+ const bool TransformDependentType;
+};
+
+} // 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,124 @@
+//===--- 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/ASTMatchers/ASTMatchers.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", true)),
+ TransformDependentType(Options.get("TransformDependentType", false)) {}
+
+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,
+ unless(isInTemplateInstantiation()))
+ .bind("op++"),
+ this);
+ Finder->addMatcher(unaryOperator(isOperator(UnaryOperatorKind::UO_PostDec),
+ UnusedInParent,
+ unless(isInTemplateInstantiation()))
+ .bind("op--"),
+ this);
+
+ if (!getLangOpts().CPlusPlus || !TransformCxxOpCalls)
+ return;
+
+ auto FindCxxOpCalls = [&](llvm::StringRef PostfixName) {
+ Finder->addMatcher(
+ cxxOperatorCallExpr(
+ UnusedInParent, unless(isInTemplateInstantiation()),
+ callee(cxxMethodDecl(
+ hasName(PostfixName), parameterCountIs(1),
+ hasParent(cxxRecordDecl(hasMethod(cxxMethodDecl(
+ hasName(PostfixName), parameterCountIs(0))))))))
+ .bind(PostfixName),
+ this);
+ };
+ FindCxxOpCalls("operator++");
+ FindCxxOpCalls("operator--");
+}
+
+void PreferPreIncrementCheck::processMatch(SourceRange Range,
+ SourceLocation OperatorLoc,
+ bool IsIncrement, bool WarnOnly) {
+ // 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 (WarnOnly)
+ return;
+ 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) {
+ auto ShouldWarnOnly = [&](const Expr *E) -> bool {
+ return !TransformDependentType && E->getType()->isDependentType();
+ };
+ if (const auto *UnaryOp = Result.Nodes.getNodeAs<UnaryOperator>("op++"))
+ return processMatch(UnaryOp->getSourceRange(), UnaryOp->getOperatorLoc(),
+ true, ShouldWarnOnly(UnaryOp));
+ if (const auto *UnaryOp = Result.Nodes.getNodeAs<UnaryOperator>("op--"))
+ return processMatch(UnaryOp->getSourceRange(), UnaryOp->getOperatorLoc(),
+ false, ShouldWarnOnly(UnaryOp));
+ if (const auto *OpCall =
+ Result.Nodes.getNodeAs<CXXOperatorCallExpr>("operator++"))
+ return processMatch(OpCall->getSourceRange(), OpCall->getOperatorLoc(),
+ true, ShouldWarnOnly(OpCall));
+ if (const auto *OpCall =
+ Result.Nodes.getNodeAs<CXXOperatorCallExpr>("operator--"))
+ return processMatch(OpCall->getSourceRange(), OpCall->getOperatorLoc(),
+ false, ShouldWarnOnly(OpCall));
+}
+
+} // 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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits