njames93 updated this revision to Diff 238082.
njames93 added a comment.
- fix spelling mistake
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/CMakeLists.txt
clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp
clang-tools-extra/clang-tidy/llvm/PreferPreIncrementCheck.cpp
clang-tools-extra/clang-tidy/llvm/PreferPreIncrementCheck.h
clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
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/llvm-prefer-pre-increment-disable-cpp-opcalls.cpp
clang-tools-extra/test/clang-tidy/checkers/llvm-prefer-pre-increment.c
clang-tools-extra/test/clang-tidy/checkers/llvm-prefer-pre-increment.cpp
Index: clang-tools-extra/test/clang-tidy/checkers/llvm-prefer-pre-increment.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/llvm-prefer-pre-increment.cpp
@@ -0,0 +1,82 @@
+// RUN: %check_clang_tidy %s llvm-prefer-pre-increment %t
+
+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;
+ }
+};
+
+void foo() {
+ int Array[32];
+ Iterator<int> It(&Array[0]);
+ 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: [[@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]]:{{\d*}}: warning: Use Pre-increment instead of Post-increment
+ *PfIt--;
+ // CHECK-MESSAGES-NOT: [[@LINE-1]]:{{\d*}}: warning: Use Pre-decrement instead of Post-decrement
+}
Index: clang-tools-extra/test/clang-tidy/checkers/llvm-prefer-pre-increment.c
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/llvm-prefer-pre-increment.c
@@ -0,0 +1,123 @@
+// RUN: %check_clang_tidy %s llvm-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
+ J++ ?: J--;
+ // CHECK-MESSAGES-NOT: [[@LINE-1]]:{{\d*}}: warning: Use Pre-increment instead of Post-increment
+ 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;
+ 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;
+ return Bar->Bar++;
+}
Index: clang-tools-extra/test/clang-tidy/checkers/llvm-prefer-pre-increment-disable-cpp-opcalls.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/llvm-prefer-pre-increment-disable-cpp-opcalls.cpp
@@ -0,0 +1,84 @@
+// RUN: %check_clang_tidy %s llvm-prefer-pre-increment %t -- \
+// RUN: -config='{CheckOptions: \
+// RUN: [{key: llvm-prefer-pre-increment.TransformCxxOpCalls, value: 0}]}'
+
+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;
+ }
+};
+
+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/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,10 @@
+.. title:: clang-tidy - performance-prefer-pre-increment
+.. meta::
+ :http-equiv=refresh: 5;URL=llvm-prefer-pre-increment.html
+
+performance-prefer-pre-increment
+================================
+
+The performance-prefer-pre-increment check is an alias, please see
+`llvm-prefer-pre-increment <llvm-prefer-pre-increment.html>`_
+for more information.
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,33 @@
+.. title:: clang-tidy - llvm-prefer-pre-increment
+
+llvm-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/list.rst
===================================================================
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -182,6 +182,7 @@
`llvm-include-order <llvm-include-order.html>`_, "Yes"
`llvm-namespace-comment <llvm-namespace-comment.html>`_,
`llvm-prefer-isa-or-dyn-cast-in-conditionals <llvm-prefer-isa-or-dyn-cast-in-conditionals.html>`_, "Yes"
+ `llvm-prefer-pre-increment <llvm-prefer-pre-increment.html>`_, "Yes"
`llvm-prefer-register-over-unsigned <llvm-prefer-register-over-unsigned.html>`_, "Yes"
`llvm-twine-local <llvm-twine-local.html>`_, "Yes"
`misc-definitions-in-headers <misc-definitions-in-headers.html>`_, "Yes"
@@ -404,3 +405,4 @@
`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-qualified-auto <llvm-qualified-auto.html>`_, `readability-qualified-auto <readability-qualified-auto.html>`_, "Yes"
+ `performance-prefer-pre-increment <performance-prefer-pre-increment.html>`_, `llvm-prefer-pre-increment <llvm-prefer-pre-increment.html>`_, "Yes"
Index: clang-tools-extra/docs/ReleaseNotes.rst
===================================================================
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -136,6 +136,12 @@
Checks Linux kernel code to see if it uses the results from the functions in
``linux/err.h``.
+- New :doc:`llvm-prefer-pre-increment
+ <clang-tidy/checks/llvm-prefer-pre-increment>` check.
+
+ Flags usages of postfix increment and decrement which could be swapped for
+ their prefix alternatives.
+
- New :doc:`llvm-prefer-register-over-unsigned
<clang-tidy/checks/llvm-prefer-register-over-unsigned>` check.
@@ -190,6 +196,11 @@
:doc:`readability-qualified-auto
<clang-tidy/checks/readability-qualified-auto>` was added.
+- New alias :doc:`performance-prefer-pre-increment
+ <clang-tidy/checks/performance-prefer-pre-increment>` to
+ :doc:`llvm-prefer-pre-increment
+ <clang-tidy/checks/llvm-prefer-pre-increment>` was added.
+
Changes in existing checks
^^^^^^^^^^^^^^^^^^^^^^^^^^
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
@@ -9,6 +9,7 @@
#include "../ClangTidy.h"
#include "../ClangTidyModule.h"
#include "../ClangTidyModuleRegistry.h"
+#include "../llvm/PreferPreIncrementCheck.h"
#include "FasterStringFindCheck.h"
#include "ForRangeCopyCheck.h"
#include "ImplicitConversionInLoopCheck.h"
@@ -51,6 +52,8 @@
"performance-no-automatic-move");
CheckFactories.registerCheck<NoexceptMoveConstructorCheck>(
"performance-noexcept-move-constructor");
+ CheckFactories.registerCheck<llvm_check::PreferPreIncrementCheck>(
+ "performance-prefer-pre-increment");
CheckFactories.registerCheck<TriviallyDestructibleCheck>(
"performance-trivially-destructible");
CheckFactories.registerCheck<TypePromotionInMathFnCheck>(
Index: clang-tools-extra/clang-tidy/llvm/PreferPreIncrementCheck.h
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/llvm/PreferPreIncrementCheck.h
@@ -0,0 +1,38 @@
+//===--- 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_LLVM_PREFERPREINCREMENTCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_PREFERPREINCREMENTCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace llvm_check {
+
+/// 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/llvm-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:
+ const bool TransformCxxOpCalls;
+};
+
+} // namespace llvm_check
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_PREFERPREINCREMENTCHECK_H
Index: clang-tools-extra/clang-tidy/llvm/PreferPreIncrementCheck.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/llvm/PreferPreIncrementCheck.cpp
@@ -0,0 +1,118 @@
+//===--- 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"
+#include "llvm/ADT/SmallVector.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace llvm_check {
+
+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::check(const MatchFinder::MatchResult &Result) {
+ auto Apply = [&](SourceRange Range, SourceLocation OpLoc,
+ const Expr &Expression, 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 (OpLoc.isMacroID() || Range.getBegin().isMacroID() ||
+ Range.getEnd().isMacroID())
+ return;
+ llvm::SmallVector<char, 256> Buffer;
+ Diag << FixItHint::CreateReplacement(
+ Range,
+ ((IsIncrement ? "++" : "--") +
+ tooling::fixit::getText(Expression, *Result.Context).rtrim(("-+")))
+ .toStringRef(Buffer));
+ };
+
+ if (const auto *UnaryOp = Result.Nodes.getNodeAs<UnaryOperator>("op++"))
+ return Apply(UnaryOp->getSourceRange(), UnaryOp->getOperatorLoc(),
+ *UnaryOp->getSubExpr(), true);
+ if (const auto *UnaryOp = Result.Nodes.getNodeAs<UnaryOperator>("op--"))
+ return Apply(UnaryOp->getSourceRange(), UnaryOp->getOperatorLoc(),
+ *UnaryOp->getSubExpr(), false);
+ if (const auto *OpCall =
+ Result.Nodes.getNodeAs<CXXOperatorCallExpr>("operator++"))
+ return Apply(OpCall->getSourceRange(), OpCall->getOperatorLoc(),
+ *OpCall->getExprStmt(), true);
+ if (const auto *OpCall =
+ Result.Nodes.getNodeAs<CXXOperatorCallExpr>("operator--"))
+ return Apply(OpCall->getSourceRange(), OpCall->getOperatorLoc(),
+ *OpCall->getExprStmt(), false);
+}
+
+} // namespace llvm_check
+} // namespace tidy
+} // namespace clang
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
@@ -14,6 +14,7 @@
#include "HeaderGuardCheck.h"
#include "IncludeOrderCheck.h"
#include "PreferIsaOrDynCastInConditionalsCheck.h"
+#include "PreferPreIncrementCheck.h"
#include "PreferRegisterOverUnsignedCheck.h"
#include "TwineLocalCheck.h"
@@ -30,6 +31,8 @@
"llvm-namespace-comment");
CheckFactories.registerCheck<PreferIsaOrDynCastInConditionalsCheck>(
"llvm-prefer-isa-or-dyn-cast-in-conditionals");
+ CheckFactories.registerCheck<PreferPreIncrementCheck>(
+ "llvm-prefer-pre-increment");
CheckFactories.registerCheck<PreferRegisterOverUnsignedCheck>(
"llvm-prefer-register-over-unsigned");
CheckFactories.registerCheck<readability::QualifiedAutoCheck>(
Index: clang-tools-extra/clang-tidy/llvm/CMakeLists.txt
===================================================================
--- clang-tools-extra/clang-tidy/llvm/CMakeLists.txt
+++ clang-tools-extra/clang-tidy/llvm/CMakeLists.txt
@@ -5,6 +5,7 @@
IncludeOrderCheck.cpp
LLVMTidyModule.cpp
PreferIsaOrDynCastInConditionalsCheck.cpp
+ PreferPreIncrementCheck.cpp
PreferRegisterOverUnsignedCheck.cpp
TwineLocalCheck.cpp
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits