summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEtienne Bergeron <etienneb@google.com>2016-04-15 16:31:15 +0000
committerEtienne Bergeron <etienneb@google.com>2016-04-15 16:31:15 +0000
commit3c5be6c9a72bad003348459a578b6b37678b075e (patch)
tree45050b741332121ab3581141e4fafd2e72ff0a68
parent19124d3d7e01fd0f88e4884e92f757f3801a1e86 (diff)
downloadbcm5719-llvm-3c5be6c9a72bad003348459a578b6b37678b075e.tar.gz
bcm5719-llvm-3c5be6c9a72bad003348459a578b6b37678b075e.zip
[clang-tidy] Add checker for operations between integrals and pointers
Summary: This check is finding suspicious operations involving pointers and integral types; which are most likely bugs. Examples: subversion/v1_6/subversion/libsvn_subr/utf.c ``` static const char * fuzzy_escape(const char *src, apr_size_t len, apr_pool_t *pool) { [...] while (src_orig < src_end) { if (! svn_ctype_isascii(*src_orig) || src_orig == '\0') // Should be *src_orig { ``` apache2/v2_2_23/modules/metadata/mod_headers.c ``` static char *parse_format_tag(apr_pool_t *p, format_tag *tag, const char **sa) { [...] tag->arg = '\0'; // ERROR: tag->arg has type char* /* grab the argument if there is one */ if (*s == '{') { ++s; tag->arg = ap_getword(p,&s,'}'); } ``` Reviewers: alexfh Subscribers: Eugene.Zelenko, cfe-commits Differential Revision: http://reviews.llvm.org/D19118 llvm-svn: 266450
-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/PointerAndIntegralOperationCheck.cpp104
-rw-r--r--clang-tools-extra/clang-tidy/misc/PointerAndIntegralOperationCheck.h35
-rw-r--r--clang-tools-extra/docs/ReleaseNotes.rst5
-rw-r--r--clang-tools-extra/docs/clang-tidy/checks/list.rst1
-rw-r--r--clang-tools-extra/docs/clang-tidy/checks/misc-pointer-and-integral-operation.rst24
-rw-r--r--clang-tools-extra/test/clang-tidy/misc-pointer-and-integral-operation-cxx98.cpp45
-rw-r--r--clang-tools-extra/test/clang-tidy/misc-pointer-and-integral-operation.cpp30
9 files changed, 248 insertions, 0 deletions
diff --git a/clang-tools-extra/clang-tidy/misc/CMakeLists.txt b/clang-tools-extra/clang-tidy/misc/CMakeLists.txt
index c3ee5c3a6b2..ae0b0dfdb78 100644
--- a/clang-tools-extra/clang-tidy/misc/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/misc/CMakeLists.txt
@@ -21,6 +21,7 @@ add_clang_library(clangTidyMiscModule
NewDeleteOverloadsCheck.cpp
NoexceptMoveConstructorCheck.cpp
NonCopyableObjects.cpp
+ PointerAndIntegralOperationCheck.cpp
SizeofContainerCheck.cpp
StaticAssertCheck.cpp
StringIntegerAssignmentCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp b/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
index df335fa6e51..bbc0eb714e8 100644
--- a/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
@@ -29,6 +29,7 @@
#include "NewDeleteOverloadsCheck.h"
#include "NoexceptMoveConstructorCheck.h"
#include "NonCopyableObjects.h"
+#include "PointerAndIntegralOperationCheck.h"
#include "SizeofContainerCheck.h"
#include "StaticAssertCheck.h"
#include "StringIntegerAssignmentCheck.h"
@@ -88,6 +89,8 @@ public:
"misc-noexcept-move-constructor");
CheckFactories.registerCheck<NonCopyableObjectsCheck>(
"misc-non-copyable-objects");
+ CheckFactories.registerCheck<PointerAndIntegralOperationCheck>(
+ "misc-pointer-and-integral-operation");
CheckFactories.registerCheck<SizeofContainerCheck>("misc-sizeof-container");
CheckFactories.registerCheck<StaticAssertCheck>(
"misc-static-assert");
diff --git a/clang-tools-extra/clang-tidy/misc/PointerAndIntegralOperationCheck.cpp b/clang-tools-extra/clang-tidy/misc/PointerAndIntegralOperationCheck.cpp
new file mode 100644
index 00000000000..e154e8dac81
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/misc/PointerAndIntegralOperationCheck.cpp
@@ -0,0 +1,104 @@
+//===--- PointerAndIntegralOperationCheck.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 "PointerAndIntegralOperationCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+void PointerAndIntegralOperationCheck::registerMatchers(MatchFinder *Finder) {
+ const auto PointerExpr = expr(hasType(pointerType()));
+ const auto BoolExpr = ignoringParenImpCasts(hasType(booleanType()));
+ const auto CharExpr = ignoringParenImpCasts(hasType(isAnyCharacter()));
+
+ const auto BinOpWithPointerExpr =
+ binaryOperator(unless(anyOf(hasOperatorName(","), hasOperatorName("="))),
+ hasEitherOperand(PointerExpr));
+
+ const auto AssignToPointerExpr =
+ binaryOperator(hasOperatorName("="), hasLHS(PointerExpr));
+
+ const auto CompareToPointerExpr =
+ binaryOperator(anyOf(hasOperatorName("<"), hasOperatorName("<="),
+ hasOperatorName(">"), hasOperatorName(">=")),
+ hasEitherOperand(PointerExpr));
+
+ // Detect expression like: ptr = (x != y);
+ Finder->addMatcher(binaryOperator(AssignToPointerExpr, hasRHS(BoolExpr))
+ .bind("assign-bool-to-pointer"),
+ this);
+
+ // Detect expression like: ptr = A[i]; where A is char*.
+ Finder->addMatcher(binaryOperator(AssignToPointerExpr, hasRHS(CharExpr))
+ .bind("assign-char-to-pointer"),
+ this);
+
+ // Detect expression like: ptr < false;
+ Finder->addMatcher(
+ binaryOperator(BinOpWithPointerExpr,
+ hasEitherOperand(ignoringParenImpCasts(cxxBoolLiteral())))
+ .bind("pointer-and-bool-literal"),
+ this);
+
+ // Detect expression like: ptr < 'a';
+ Finder->addMatcher(binaryOperator(BinOpWithPointerExpr,
+ hasEitherOperand(ignoringParenImpCasts(
+ characterLiteral())))
+ .bind("pointer-and-char-literal"),
+ this);
+
+ // Detect expression like: ptr < 0;
+ Finder->addMatcher(binaryOperator(CompareToPointerExpr,
+ hasEitherOperand(ignoringParenImpCasts(
+ integerLiteral(equals(0)))))
+ .bind("compare-pointer-to-zero"),
+ this);
+
+ // Detect expression like: ptr < nullptr;
+ Finder->addMatcher(binaryOperator(CompareToPointerExpr,
+ hasEitherOperand(ignoringParenImpCasts(
+ cxxNullPtrLiteralExpr())))
+ .bind("compare-pointer-to-null"),
+ this);
+}
+
+void PointerAndIntegralOperationCheck::check(
+ const MatchFinder::MatchResult &Result) {
+ if (const auto *E =
+ Result.Nodes.getNodeAs<BinaryOperator>("assign-bool-to-pointer")) {
+ diag(E->getOperatorLoc(), "suspicious assignment from bool to pointer");
+ } else if (const auto *E = Result.Nodes.getNodeAs<BinaryOperator>(
+ "assign-char-to-pointer")) {
+ diag(E->getOperatorLoc(), "suspicious assignment from char to pointer");
+ } else if (const auto *E = Result.Nodes.getNodeAs<BinaryOperator>(
+ "pointer-and-bool-literal")) {
+ diag(E->getOperatorLoc(),
+ "suspicious operation between pointer and bool literal");
+ } else if (const auto *E = Result.Nodes.getNodeAs<BinaryOperator>(
+ "pointer-and-char-literal")) {
+ diag(E->getOperatorLoc(),
+ "suspicious operation between pointer and character literal");
+ } else if (const auto *E = Result.Nodes.getNodeAs<BinaryOperator>(
+ "compare-pointer-to-zero")) {
+ diag(E->getOperatorLoc(), "suspicious comparison of pointer with zero");
+ } else if (const auto *E = Result.Nodes.getNodeAs<BinaryOperator>(
+ "compare-pointer-to-null")) {
+ diag(E->getOperatorLoc(),
+ "suspicious comparison of pointer with null expression");
+ }
+}
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tools-extra/clang-tidy/misc/PointerAndIntegralOperationCheck.h b/clang-tools-extra/clang-tidy/misc/PointerAndIntegralOperationCheck.h
new file mode 100644
index 00000000000..996253e8e69
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/misc/PointerAndIntegralOperationCheck.h
@@ -0,0 +1,35 @@
+//===--- PointerAndIntegralOperationCheck.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_POINTER_AND_INTEGRAL_OPERATION_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_POINTER_AND_INTEGRAL_OPERATION_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+/// Find suspicious expressions involving pointer and integral types.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/misc-pointer-and-integral-operation.html
+class PointerAndIntegralOperationCheck : public ClangTidyCheck {
+public:
+ PointerAndIntegralOperationCheck(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_POINTER_AND_INTEGRAL_OPERATION_H
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index c61121988cb..578551e4da4 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -103,6 +103,11 @@ identified. The improvements since the 3.8 release include:
Warns when there is a explicit redundant cast of a calculation result to a
bigger type.
+- New `misc-pointer-and-integral-operation
+ <http://clang.llvm.org/extra/clang-tidy/checks/misc-misc-pointer-and-integral-operation.html>`_ check
+
+ Warns about suspicious operations involving pointers and integral types.
+
- New `misc-string-literal-with-embedded-nul
<http://clang.llvm.org/extra/clang-tidy/checks/misc-string-literal-with-embedded-nul.html>`_ check
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index 5fab245a14c..8af60124e02 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -65,6 +65,7 @@ Clang-Tidy Checks
misc-new-delete-overloads
misc-noexcept-move-constructor
misc-non-copyable-objects
+ misc-pointer-and-integral-operation
misc-sizeof-container
misc-static-assert
misc-string-integer-assignment
diff --git a/clang-tools-extra/docs/clang-tidy/checks/misc-pointer-and-integral-operation.rst b/clang-tools-extra/docs/clang-tidy/checks/misc-pointer-and-integral-operation.rst
new file mode 100644
index 00000000000..d32d8245da6
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy/checks/misc-pointer-and-integral-operation.rst
@@ -0,0 +1,24 @@
+.. title:: clang-tidy - misc-pointer-and-integral-operation
+
+misc-pointer-and-integral-operation
+===================================
+
+Looks for operation involving pointers and integral types. A common mistake is
+to forget to dereference a pointer. These errors may be detected when a pointer
+object is compare to an object with integral type.
+
+Examples:
+
+.. code:: c++
+
+ char* ptr;
+ if ((ptr = malloc(...)) < nullptr) // Pointer comparison with operator '<'
+ ... // Should probably be '!='
+
+ if (ptr == '\0') // Should probably be *ptr
+ ...
+
+ void Process(std::string path, bool* error) {
+ [...]
+ if (error != false) // Should probably be *error
+ ...
diff --git a/clang-tools-extra/test/clang-tidy/misc-pointer-and-integral-operation-cxx98.cpp b/clang-tools-extra/test/clang-tidy/misc-pointer-and-integral-operation-cxx98.cpp
new file mode 100644
index 00000000000..4834a469e76
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/misc-pointer-and-integral-operation-cxx98.cpp
@@ -0,0 +1,45 @@
+// RUN: %check_clang_tidy %s misc-pointer-and-integral-operation %t -- -- -std=c++98
+
+bool* pb;
+char* pc;
+int* pi;
+
+int Test() {
+ pb = false;
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: suspicious assignment from bool to pointer [misc-pointer-and-integral-operation]
+ pc = '\0';
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: suspicious assignment from char to pointer
+
+ pb = (false?false:false);
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: suspicious assignment from bool to pointer
+ pb = (4 != 5?false:false);
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: suspicious assignment from bool to pointer
+
+ if (pb < false) return 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious operation between pointer and bool literal
+ if (pb != false) return 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious operation between pointer and bool literal
+ if (pc < '\0') return 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious operation between pointer and character literal
+ if (pc != '\0') return 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious operation between pointer and character literal
+ if (pi < '\0') return 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious operation between pointer and character literal
+ if (pi != '\0') return 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious operation between pointer and character literal
+
+ return 1;
+}
+
+int Valid() {
+ *pb = false;
+ *pc = '\0';
+
+ pb += 0;
+ pc += 0;
+ pi += 0;
+
+ pb += (pb != 0);
+ pc += (pc != 0);
+ pi += (pi != 0);
+}
diff --git a/clang-tools-extra/test/clang-tidy/misc-pointer-and-integral-operation.cpp b/clang-tools-extra/test/clang-tidy/misc-pointer-and-integral-operation.cpp
new file mode 100644
index 00000000000..6591f0af360
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/misc-pointer-and-integral-operation.cpp
@@ -0,0 +1,30 @@
+// RUN: %check_clang_tidy %s misc-pointer-and-integral-operation %t
+
+bool* pb;
+char* pc;
+int* pi;
+
+int Test() {
+ if (pi < 0) return 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious comparison of pointer with zero [misc-pointer-and-integral-operation]
+ if (pi <= 0) return 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious comparison of pointer with zero
+
+ if (nullptr <= pb) return 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: suspicious comparison of pointer with null
+ if (pc < nullptr) return 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious comparison of pointer with null
+ if (pi > nullptr) return 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious comparison of pointer with null
+
+ return 1;
+}
+
+int Valid() {
+ *pb = false;
+ *pc = '\0';
+
+ pi += (pi != nullptr);
+ pi -= (pi == nullptr);
+ pc += (pb != nullptr);
+}
OpenPOWER on IntegriCloud