diff --git a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt --- a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt @@ -20,6 +20,7 @@ TypePromotionInMathFnCheck.cpp UnnecessaryCopyInitialization.cpp UnnecessaryValueParamCheck.cpp + UsePreincrementCheck.cpp LINK_LIBS clangTidy diff --git a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp --- a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp @@ -24,6 +24,7 @@ #include "TypePromotionInMathFnCheck.h" #include "UnnecessaryCopyInitialization.h" #include "UnnecessaryValueParamCheck.h" +#include "UsePreincrementCheck.h" namespace clang { namespace tidy { @@ -61,6 +62,8 @@ "performance-unnecessary-copy-initialization"); CheckFactories.registerCheck( "performance-unnecessary-value-param"); + CheckFactories.registerCheck( + "performance-use-preincrement"); } }; diff --git a/clang-tools-extra/clang-tidy/performance/UsePreincrementCheck.h b/clang-tools-extra/clang-tidy/performance/UsePreincrementCheck.h new file mode 100644 --- /dev/null +++ b/clang-tools-extra/clang-tidy/performance/UsePreincrementCheck.h @@ -0,0 +1,34 @@ +//===--- UsePreincrementCheck.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_USEPREINCREMENTCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_USEPREINCREMENTCHECK_H + +#include "../ClangTidyCheck.h" + +namespace clang { +namespace tidy { +namespace performance { + +/// Checks that preincrement is used when there is no need for postincrement +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/performance-use-preincrement.html +class UsePreincrementCheck : public ClangTidyCheck { +public: + UsePreincrementCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace performance +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_USEPREINCREMENTCHECK_H diff --git a/clang-tools-extra/clang-tidy/performance/UsePreincrementCheck.cpp b/clang-tools-extra/clang-tidy/performance/UsePreincrementCheck.cpp new file mode 100644 --- /dev/null +++ b/clang-tools-extra/clang-tidy/performance/UsePreincrementCheck.cpp @@ -0,0 +1,46 @@ +//===--- UsePreincrementCheck.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 "UsePreincrementCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace performance { + +void UsePreincrementCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher( + unaryOperator(hasOperatorName("++"), hasParent(compoundStmt())) + .bind("unaryOperator"), + this); +} + +void UsePreincrementCheck::check(const MatchFinder::MatchResult &Result) { + const auto *Operator = Result.Nodes.getNodeAs("unaryOperator"); + if (Operator->isPrefix()) + return; + + auto PostIncRange = + CharSourceRange::getTokenRange(Operator->getSourceRange()); + auto ValRange = + CharSourceRange::getTokenRange(Operator->getSubExpr()->getSourceRange()); + + auto Diag = + diag(Operator->getOperatorLoc(), + "Preincrement could be used instead of postincrement.") + << FixItHint::CreateInsertion(ValRange.getBegin().getLocWithOffset(-2), + "++") + << FixItHint::CreateRemoval(PostIncRange.getEnd().getLocWithOffset(1)); +} + +} // namespace performance +} // namespace tidy +} // namespace clang diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -103,6 +103,11 @@ Finds initializations of C++ shared pointers to non-array type that are initialized with an array. +- New :doc:`performance-use-preincrement + ` check. + + FIXME: add release notes. + New check aliases ^^^^^^^^^^^^^^^^^ diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -84,7 +84,7 @@ `bugprone-posix-return `_, "Yes" `bugprone-redundant-branch-condition `_, "Yes" `bugprone-reserved-identifier `_, "Yes" - `bugprone-shared-ptr-array-mismatch `_, "Yes" + `bugprone-shared-ptr-array-mismatch `_, `bugprone-signal-handler `_, `bugprone-signed-char-misuse `_, `bugprone-sizeof-container `_, @@ -286,6 +286,7 @@ `performance-type-promotion-in-math-fn `_, "Yes" `performance-unnecessary-copy-initialization `_, "Yes" `performance-unnecessary-value-param `_, "Yes" + `performance-use-preincrement `_, "Yes" `portability-restrict-system-includes `_, "Yes" `portability-simd-intrinsics `_, `readability-avoid-const-params-in-decls `_, "Yes" diff --git a/clang-tools-extra/docs/clang-tidy/checks/performance-use-preincrement.rst b/clang-tools-extra/docs/clang-tidy/checks/performance-use-preincrement.rst new file mode 100644 --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/performance-use-preincrement.rst @@ -0,0 +1,7 @@ +.. title:: clang-tidy - performance-use-preincrement + +performance-use-preincrement +============================ + +Checks that preincrement is used when there is no need for postincrement. +This can lead to improved performance with iterators that are not trivially copyable. diff --git a/clang-tools-extra/test/clang-tidy/checkers/performance-use-preincrement.cpp b/clang-tools-extra/test/clang-tidy/checkers/performance-use-preincrement.cpp new file mode 100644 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/performance-use-preincrement.cpp @@ -0,0 +1,23 @@ +// RUN: %check_clang_tidy %s performance-use-preincrement %t + +void positivePostincrement() { + int I = 0; + I++; + // CHECK-MESSAGES: [[@LINE-1]]:4: warning: Preincrement could be used instead of postincrement. [performance-use-preincrement] +} + +void negativePreincrement() { + int I = 0; + ++I; +} + +void negativeUsedPostincrement() { + int I = 0; + int J = I++; + ++J; + J = I++; +} + +int negativeReturn(int &I) { + return I++; +}