Index: clang-tidy/readability/CMakeLists.txt =================================================================== --- clang-tidy/readability/CMakeLists.txt +++ clang-tidy/readability/CMakeLists.txt @@ -15,6 +15,7 @@ MisplacedArrayIndexCheck.cpp NamedParameterCheck.cpp NamespaceCommentCheck.cpp + OperatorsRepresentationCheck.cpp NonConstParameterCheck.cpp ReadabilityTidyModule.cpp RedundantControlFlowCheck.cpp Index: clang-tidy/readability/OperatorsRepresentationCheck.h =================================================================== --- /dev/null +++ clang-tidy/readability/OperatorsRepresentationCheck.h @@ -0,0 +1,35 @@ +//===--- OperatorsRepresentationCheck.h - clang-tidy-----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_OPERATORS_REPRESENTATION_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_OPERATORS_REPRESENTATION_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { +namespace readability { + +/// Flags alternative tokens for operators, such as 'compl', 'not' and 'or'. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/readability-operators-representation.html +class OperatorsRepresentationCheck : public ClangTidyCheck { +public: + OperatorsRepresentationCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace readability +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_OPERATORS_REPRESENTATION_H Index: clang-tidy/readability/OperatorsRepresentationCheck.cpp =================================================================== --- /dev/null +++ clang-tidy/readability/OperatorsRepresentationCheck.cpp @@ -0,0 +1,75 @@ +//===--- OperatorsRepresentationCheck.cpp - clang-tidy---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "OperatorsRepresentationCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Lex/Lexer.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace readability { + +void OperatorsRepresentationCheck::registerMatchers(MatchFinder *Finder) { + // We ignore implicit != operators in C++11 range-based for loops. + Finder->addMatcher(binaryOperator(unless(hasLHS(ignoringImpCasts( + declRefExpr(to(isImplicit())))))) + .bind("binary"), + this); + Finder->addMatcher(unaryOperator().bind("unary"), this); +} + +void OperatorsRepresentationCheck::check(const MatchFinder::MatchResult &Result) { + StringRef PrimarySpelling; + SourceLocation OpLoc; + + if (const auto *B = Result.Nodes.getNodeAs("binary")) { + switch (B->getOpcode()) { + case BO_NE: + case BO_And: + case BO_Xor: + case BO_Or: + case BO_LAnd: + case BO_LOr: + case BO_AndAssign: + case BO_OrAssign: + case BO_XorAssign: + break; + default: + return; + } + PrimarySpelling = B->getOpcodeStr(); + OpLoc = B->getOperatorLoc(); + } + + if (const auto *U = Result.Nodes.getNodeAs("unary")) { + auto OpCode = U->getOpcode(); + if (OpCode != UO_Not && OpCode != UO_LNot) + return; + PrimarySpelling = UnaryOperator::getOpcodeStr(OpCode); + OpLoc = U->getOperatorLoc(); + } + + auto &SM = *Result.SourceManager; + OpLoc = SM.getSpellingLoc(OpLoc); + + auto TokenRange = CharSourceRange::getTokenRange(OpLoc); + StringRef Spelling = Lexer::getSourceText(TokenRange, SM, getLangOpts()); + + if (PrimarySpelling != Spelling) { + diag(OpLoc, "operator uses alternative spelling") + << FixItHint::CreateReplacement(TokenRange, PrimarySpelling); + } +} + +} // namespace readability +} // namespace tidy +} // namespace clang Index: clang-tidy/readability/ReadabilityTidyModule.cpp =================================================================== --- clang-tidy/readability/ReadabilityTidyModule.cpp +++ clang-tidy/readability/ReadabilityTidyModule.cpp @@ -23,6 +23,7 @@ #include "MisleadingIndentationCheck.h" #include "MisplacedArrayIndexCheck.h" #include "NamedParameterCheck.h" +#include "OperatorsRepresentationCheck.h" #include "NonConstParameterCheck.h" #include "RedundantControlFlowCheck.h" #include "RedundantDeclarationCheck.h" @@ -66,6 +67,8 @@ "readability-misleading-indentation"); CheckFactories.registerCheck( "readability-misplaced-array-index"); + CheckFactories.registerCheck( + "readability-operators-representation"); CheckFactories.registerCheck( "readability-redundant-function-ptr-dereference"); CheckFactories.registerCheck( Index: docs/ReleaseNotes.rst =================================================================== --- docs/ReleaseNotes.rst +++ docs/ReleaseNotes.rst @@ -72,6 +72,12 @@ Finds misleading indentation where braces should be introduced or the code should be reformatted. +- New `readability-operators-representation + `_ check + + Flags (and replaces) the alternative tokens for binary and unary operators, + such as ``not`` (for ``!``) and ``or`` (for ``||``). + - Added `ParameterThreshold` to `readability-function-size`. Finds functions that have more then `ParameterThreshold` parameters and emits a warning. Index: docs/clang-tidy/checks/list.rst =================================================================== --- docs/clang-tidy/checks/list.rst +++ docs/clang-tidy/checks/list.rst @@ -145,6 +145,7 @@ readability-misleading-indentation readability-misplaced-array-index readability-named-parameter + readability-operators-representation readability-non-const-parameter readability-redundant-control-flow readability-redundant-declaration Index: docs/clang-tidy/checks/readability-operators-representation.rst =================================================================== --- /dev/null +++ docs/clang-tidy/checks/readability-operators-representation.rst @@ -0,0 +1,8 @@ +.. title:: clang-tidy - readability-operators-representation + +readability-operators-representation +================================= + +Flags (and replaces) the alternative tokens for binary and unary operators, +such as ``not`` (for ``!``), ``bitand`` (for ``&``), ``or`` (for ``||``) or ``not_eq`` +(for ``!=``). Index: test/clang-tidy/readability-operators-representation.cpp =================================================================== --- /dev/null +++ test/clang-tidy/readability-operators-representation.cpp @@ -0,0 +1,54 @@ +// RUN: %check_clang_tidy %s readability-operators-representation %t + +void f() { + bool a, b, c; + + c = a and b; + // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: operator uses alternative spelling [readability-operators-representation] + // CHECK-FIXES: c = a && b; + c and_eq a; + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: operator + // CHECK-FIXES: c &= a; + c = a bitand b; + // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: operator + // CHECK-FIXES: c = a & b; + c = a bitor b; + // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: operator + // CHECK-FIXES: c = a | b; + c = compl a; + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: operator + // CHECK-FIXES: c = ~ a; + c = not a; + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: operator + // CHECK-FIXES: c = ! a; + c = a not_eq b; + // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: operator + // CHECK-FIXES: c = a != b; + c = a or b; + // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: operator + // CHECK-FIXES: c = a || b; + c or_eq a; + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: operator + // CHECK-FIXES: c |= a; + c = a xor b; + // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: operator + // CHECK-FIXES: c = a ^ b; + c xor_eq a; + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: operator + // CHECK-FIXES: c ^= a; + +#define M a xor + // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: operator + // CHECK-FIXES: #define M a ^ + c = M b; + + int arr[2]; + for (int i : arr) // OK (Here is an implicit != operator.) + ; + + auto ptr = &c; // OK + auto i = -1; // OK + c = a && b; // OK + c &= a; // OK + c = !a; // OK +}