summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clang-tidy
diff options
context:
space:
mode:
Diffstat (limited to 'clang-tools-extra/clang-tidy')
-rw-r--r--clang-tools-extra/clang-tidy/misc/CMakeLists.txt1
-rw-r--r--clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp3
-rw-r--r--clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp133
-rw-r--r--clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.h35
4 files changed, 172 insertions, 0 deletions
diff --git a/clang-tools-extra/clang-tidy/misc/CMakeLists.txt b/clang-tools-extra/clang-tidy/misc/CMakeLists.txt
index b0aea581436..3aee73ecb80 100644
--- a/clang-tools-extra/clang-tidy/misc/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/misc/CMakeLists.txt
@@ -23,6 +23,7 @@ add_clang_library(clangTidyMiscModule
NoexceptMoveConstructorCheck.cpp
NonCopyableObjects.cpp
PointerAndIntegralOperationCheck.cpp
+ RedundantExpressionCheck.cpp
SizeofContainerCheck.cpp
SizeofExpressionCheck.cpp
StaticAssertCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp b/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
index 8281bf7a064..9aecdc1c447 100644
--- a/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
@@ -31,6 +31,7 @@
#include "NoexceptMoveConstructorCheck.h"
#include "NonCopyableObjects.h"
#include "PointerAndIntegralOperationCheck.h"
+#include "RedundantExpressionCheck.h"
#include "SizeofContainerCheck.h"
#include "SizeofExpressionCheck.h"
#include "StaticAssertCheck.h"
@@ -98,6 +99,8 @@ public:
"misc-non-copyable-objects");
CheckFactories.registerCheck<PointerAndIntegralOperationCheck>(
"misc-pointer-and-integral-operation");
+ CheckFactories.registerCheck<RedundantExpressionCheck>(
+ "misc-redundant-expression");
CheckFactories.registerCheck<SizeofContainerCheck>("misc-sizeof-container");
CheckFactories.registerCheck<SizeofExpressionCheck>(
"misc-sizeof-expression");
diff --git a/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp b/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp
new file mode 100644
index 00000000000..fee7b03a74e
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp
@@ -0,0 +1,133 @@
+//===--- RedundantExpressionCheck.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 "RedundantExpressionCheck.h"
+#include "../utils/Matchers.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+static bool AreIdenticalExpr(const Expr *Left, const Expr *Right) {
+ if (!Left || !Right)
+ return !Left && !Right;
+
+ Left = Left->IgnoreParens();
+ Right = Right->IgnoreParens();
+
+ // Compare classes.
+ if (Left->getStmtClass() != Right->getStmtClass())
+ return false;
+
+ // Compare children.
+ Expr::const_child_iterator LeftIter = Left->child_begin();
+ Expr::const_child_iterator RightIter = Right->child_begin();
+ while (LeftIter != Left->child_end() && RightIter != Right->child_end()) {
+ if (!AreIdenticalExpr(dyn_cast<Expr>(*LeftIter),
+ dyn_cast<Expr>(*RightIter)))
+ return false;
+ ++LeftIter;
+ ++RightIter;
+ }
+ if (LeftIter != Left->child_end() || RightIter != Right->child_end())
+ return false;
+
+ // Perform extra checks.
+ switch (Left->getStmtClass()) {
+ default:
+ return false;
+
+ case Stmt::CharacterLiteralClass:
+ return cast<CharacterLiteral>(Left)->getValue() ==
+ cast<CharacterLiteral>(Right)->getValue();
+ case Stmt::IntegerLiteralClass: {
+ llvm::APInt LeftLit = cast<IntegerLiteral>(Left)->getValue();
+ llvm::APInt RightLit = cast<IntegerLiteral>(Right)->getValue();
+ return LeftLit.getBitWidth() == RightLit.getBitWidth() && LeftLit == RightLit;
+ }
+ case Stmt::FloatingLiteralClass:
+ return cast<FloatingLiteral>(Left)->getValue().bitwiseIsEqual(
+ cast<FloatingLiteral>(Right)->getValue());
+ case Stmt::StringLiteralClass:
+ return cast<StringLiteral>(Left)->getBytes() ==
+ cast<StringLiteral>(Right)->getBytes();
+
+ case Stmt::DeclRefExprClass:
+ return cast<DeclRefExpr>(Left)->getDecl() ==
+ cast<DeclRefExpr>(Right)->getDecl();
+ case Stmt::MemberExprClass:
+ return cast<MemberExpr>(Left)->getMemberDecl() ==
+ cast<MemberExpr>(Right)->getMemberDecl();
+
+ case Stmt::CStyleCastExprClass:
+ return cast<CStyleCastExpr>(Left)->getTypeAsWritten() ==
+ cast<CStyleCastExpr>(Right)->getTypeAsWritten();
+
+ case Stmt::CallExprClass:
+ case Stmt::ImplicitCastExprClass:
+ case Stmt::ArraySubscriptExprClass:
+ return true;
+
+ case Stmt::UnaryOperatorClass:
+ if (cast<UnaryOperator>(Left)->isIncrementDecrementOp())
+ return false;
+ return cast<UnaryOperator>(Left)->getOpcode() ==
+ cast<UnaryOperator>(Right)->getOpcode();
+ case Stmt::BinaryOperatorClass:
+ return cast<BinaryOperator>(Left)->getOpcode() ==
+ cast<BinaryOperator>(Right)->getOpcode();
+ }
+}
+
+AST_MATCHER(BinaryOperator, OperandsAreEquivalent) {
+ return AreIdenticalExpr(Node.getLHS(), Node.getRHS());
+}
+
+AST_MATCHER(BinaryOperator, isInMacro) {
+ return Node.getOperatorLoc().isMacroID();
+}
+
+AST_MATCHER(Expr, isInstantiationDependent) {
+ return Node.isInstantiationDependent();
+}
+
+void RedundantExpressionCheck::registerMatchers(MatchFinder *Finder) {
+ const auto AnyLiteralExpr = ignoringParenImpCasts(
+ anyOf(cxxBoolLiteral(), characterLiteral(), integerLiteral()));
+
+ Finder->addMatcher(
+ binaryOperator(anyOf(hasOperatorName("-"), hasOperatorName("/"),
+ hasOperatorName("%"), hasOperatorName("|"),
+ hasOperatorName("&"), hasOperatorName("^"),
+ matchers::isComparisonOperator(),
+ hasOperatorName("&&"), hasOperatorName("||"),
+ hasOperatorName("=")),
+ OperandsAreEquivalent(),
+ // Filter noisy false positives.
+ unless(isInstantiationDependent()),
+ unless(isInMacro()),
+ unless(hasType(realFloatingPointType())),
+ unless(hasEitherOperand(hasType(realFloatingPointType()))),
+ unless(hasLHS(AnyLiteralExpr)))
+ .bind("binary"),
+ this);
+}
+
+void RedundantExpressionCheck::check(const MatchFinder::MatchResult &Result) {
+ if (const auto *BinOp = Result.Nodes.getNodeAs<BinaryOperator>("binary"))
+ diag(BinOp->getOperatorLoc(), "both side of operator are equivalent");
+}
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.h b/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.h
new file mode 100644
index 00000000000..80460a63d09
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.h
@@ -0,0 +1,35 @@
+//===--- RedundantExpressionCheck.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_MISC_REDUNDANT_EXPRESSION_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_REDUNDANT_EXPRESSION_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+/// Detect useless or suspicious redundant expressions.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/misc-redundant-expression.html
+class RedundantExpressionCheck : public ClangTidyCheck {
+public:
+ RedundantExpressionCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_REDUNDANT_EXPRESSION_H
OpenPOWER on IntegriCloud