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 + NoAlternativeTokensCheck.cpp NonConstParameterCheck.cpp ReadabilityTidyModule.cpp RedundantControlFlowCheck.cpp Index: clang-tidy/readability/NoAlternativeTokensCheck.h =================================================================== --- /dev/null +++ clang-tidy/readability/NoAlternativeTokensCheck.h @@ -0,0 +1,35 @@ +//===--- NoAlternativeTokensCheck.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_NO_ALTERNATIVE_TOKENS_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_NO_ALTERNATIVE_TOKENS_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-no-alternative-tokens.html +class NoAlternativeTokensCheck : public ClangTidyCheck { +public: + NoAlternativeTokensCheck(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_NO_ALTERNATIVE_TOKENS_H Index: clang-tidy/readability/NoAlternativeTokensCheck.cpp =================================================================== --- /dev/null +++ clang-tidy/readability/NoAlternativeTokensCheck.cpp @@ -0,0 +1,75 @@ +//===--- NoAlternativeTokensCheck.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 "NoAlternativeTokensCheck.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 NoAlternativeTokensCheck::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 NoAlternativeTokensCheck::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 "NoAlternativeTokensCheck.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-no-alternative-tokens"); 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-no-alternative-tokens + `_ 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 @@ -144,6 +144,7 @@ readability-misleading-indentation readability-misplaced-array-index readability-named-parameter + readability-no-alternative-tokens readability-non-const-parameter readability-redundant-control-flow readability-redundant-declaration Index: docs/clang-tidy/checks/readability-no-alternative-tokens.rst =================================================================== --- /dev/null +++ docs/clang-tidy/checks/readability-no-alternative-tokens.rst @@ -0,0 +1,8 @@ +.. title:: clang-tidy - readability-no-alternative-tokens + +readability-no-alternative-tokens +================================= + +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-no-alternative-tokens.cpp =================================================================== --- /dev/null +++ test/clang-tidy/readability-no-alternative-tokens.cpp @@ -0,0 +1,54 @@ +// RUN: %check_clang_tidy %s readability-no-alternative-tokens %t + +void f() { + bool a, b, c; + + c = a and b; + // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: operator uses alternative spelling [readability-no-alternative-tokens] + // 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 +}