Index: clang-tidy/misc/CMakeLists.txt =================================================================== --- clang-tidy/misc/CMakeLists.txt +++ clang-tidy/misc/CMakeLists.txt @@ -6,6 +6,7 @@ MisplacedConstCheck.cpp UnconventionalAssignOperatorCheck.cpp BoolPointerImplicitConversionCheck.cpp + ComparisonFunctionAddressCheck.cpp DanglingHandleCheck.cpp DefinitionsInHeadersCheck.cpp FoldInitTypeCheck.cpp Index: clang-tidy/misc/ComparisonFunctionAddressCheck.h =================================================================== --- /dev/null +++ clang-tidy/misc/ComparisonFunctionAddressCheck.h @@ -0,0 +1,38 @@ +//===--- ComparisonFunctionAddressCheck.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_COMPARISON_FUNCTION_ADDRESS_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_COMPARISON_FUNCTION_ADDRESS_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { +namespace misc { + +/// This Checker gives a warning if address of a function is compared. +/// For example: the programmer wants to write getc()==0 but writes getc==0. +/// As a general rule, function pointers can be compared to other function +/// pointers, function, 0, nullptr, functions can be compared only against +/// function pointers +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/misc-comparison-function-address.html +class ComparisonFunctionAddressCheck : public ClangTidyCheck { +public: + ComparisonFunctionAddressCheck(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_COMPARISON_FUNCTION_ADDRESS_H Index: clang-tidy/misc/ComparisonFunctionAddressCheck.cpp =================================================================== --- /dev/null +++ clang-tidy/misc/ComparisonFunctionAddressCheck.cpp @@ -0,0 +1,39 @@ +//===--- ComparisonFunctionAddressCheck.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 "ComparisonFunctionAddressCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace misc { + +void ComparisonFunctionAddressCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher( + binaryOperator( + hasEitherOperand(hasType(pointerType(pointee(functionType())))), + unless(hasEitherOperand(ignoringImpCasts( + declRefExpr(hasDeclaration(varDecl(hasType(pointerType())))))))) + .bind("funcAdd"), + this); +} + +void ComparisonFunctionAddressCheck::check( + const MatchFinder::MatchResult &Result) { + const auto *MatchedDecl = Result.Nodes.getNodeAs("funcAdd"); + diag(MatchedDecl->getOperatorLoc(), "Address of function is compared"); +} + +} // namespace misc +} // namespace tidy +} // namespace clang + Index: clang-tidy/misc/MiscTidyModule.cpp =================================================================== --- clang-tidy/misc/MiscTidyModule.cpp +++ clang-tidy/misc/MiscTidyModule.cpp @@ -15,6 +15,7 @@ #include "MisplacedConstCheck.h" #include "UnconventionalAssignOperatorCheck.h" #include "BoolPointerImplicitConversionCheck.h" +#include "ComparisonFunctionAddressCheck.h" #include "DanglingHandleCheck.h" #include "DefinitionsInHeadersCheck.h" #include "FoldInitTypeCheck.h" @@ -68,6 +69,8 @@ "misc-unconventional-assign-operator"); CheckFactories.registerCheck( "misc-bool-pointer-implicit-conversion"); + CheckFactories.registerCheck( + "misc-comparison-function-address"); CheckFactories.registerCheck( "misc-dangling-handle"); CheckFactories.registerCheck( Index: docs/clang-tidy/checks/list.rst =================================================================== --- docs/clang-tidy/checks/list.rst +++ docs/clang-tidy/checks/list.rst @@ -55,6 +55,7 @@ misc-argument-comment misc-assert-side-effect misc-bool-pointer-implicit-conversion + misc-comparison-function-address misc-dangling-handle misc-definitions-in-headers misc-fold-init-type Index: docs/clang-tidy/checks/misc-comparison-function-address.rst =================================================================== --- /dev/null +++ docs/clang-tidy/checks/misc-comparison-function-address.rst @@ -0,0 +1,19 @@ +.. title:: clang-tidy - misc-comparison-function-address + +misc-comparison-function-address +================================ + +This Checker gives a warning if address of a function is compared. +For example: the programmer wants to write ``getc()==0`` but writes ``getc==0`` + +.. code-block:: c++ + if (getc== 0); // warning: Address of strlen is compared + +but comparison to function pointer should be allowed + +.. code-block:: c++ + int (* myfp)(char const * ) = 0; + if (getc ==myfp); // should be ok + +as a general rule, function pointers can be compared to other function pointers, function, 0, nullptr +functions can be compared only against function pointers Index: test/clang-tidy/misc-comparison-function-address.cpp =================================================================== --- /dev/null +++ test/clang-tidy/misc-comparison-function-address.cpp @@ -0,0 +1,51 @@ +// RUN: %check_clang_tidy %s misc-comparison-function-address %t + +#define nullptr 0 +#define NULL 0 + +struct __sFile { + int unused; +}; + +typedef struct __sFILE FILE; + +int getc(FILE * stream); +char func(); +char * func2(); + + +void test_function_warning() { + if (getc == 0); + // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: Address of function is compared [misc-comparison-function-address] + + if (0 == getc); + // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: Address of function is compared [misc-comparison-function-address] + + if (getc == nullptr); + // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: Address of function is compared [misc-comparison-function-address] + + if (NULL == func); + // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: Address of function is compared [misc-comparison-function-address] +} + + +void test_function_awsome() { + FILE * pFile; + int (*myfp)(FILE *) = 0; + char (*myfp2)(); + + if (getc == myfp); + + if (0 == myfp); + + if (getc(pFile) == 0); + + if (myfp == getc); + + if (myfp == 0); + + if (myfp == NULL); + + if (func == myfp2); +} +