pfultz2 created this revision. pfultz2 added reviewers: aaron.ballman, alexfh. pfultz2 added a project: clang-tools-extra. Herald added subscribers: carlosgalvezp, mgorny. Herald added a project: All. pfultz2 requested review of this revision. Herald added a subscriber: cfe-commits.
This check diagnoses instances where an enum is implicitly converted to an integer. In C++11, enums can be defined as `enum class` which will prevent such implicit conversion, however, `enum` provides no such guarantees to prevent bugs. There can be many reasons why `enum` cannot be replaced with `enum class` such as compatibility with C or legacy libraries. This check will diagnose similar implicit conversions when using `enum` to find the same class of bugs. Currently it will only warn on function or constructor calls as such conversions are not clear to the user, but this could be expanded in the future. void foo(int i); void f() { foo(e1); // e1 is implictly converted to an int } Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D129570 Files: clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt clang-tools-extra/clang-tidy/bugprone/EnumToIntCheck.cpp clang-tools-extra/clang-tidy/bugprone/EnumToIntCheck.h clang-tools-extra/docs/ReleaseNotes.rst clang-tools-extra/docs/clang-tidy/checks/bugprone/enum-to-int.rst clang-tools-extra/docs/clang-tidy/checks/list.rst clang-tools-extra/test/clang-tidy/checkers/bugprone/enum-to-int.cpp
Index: clang-tools-extra/test/clang-tidy/checkers/bugprone/enum-to-int.cpp =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/checkers/bugprone/enum-to-int.cpp @@ -0,0 +1,28 @@ +// RUN: %check_clang_tidy %s bugprone-enum-to-int %t + +enum A { e1, + e2 }; + +struct bar { + bar(int); +}; +void foo(int i); +void f1() { + foo(e1); + // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: Enum is implictly converted to an integral. [bugprone-enum-to-int] +} +void f2() { + foo(static_cast<int>(e1)); +} +void f3() { + int i = e1; + foo(i); +} +void f4() { + bar a(e1); + // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: Enum is implictly converted to an integral. [bugprone-enum-to-int] +} +void f5() { + auto a = bar{e1}; + // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: Enum is implictly converted to an integral. [bugprone-enum-to-int] +} Index: clang-tools-extra/docs/clang-tidy/checks/list.rst =================================================================== --- clang-tools-extra/docs/clang-tidy/checks/list.rst +++ clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -85,6 +85,7 @@ `bugprone-dangling-handle <bugprone/dangling-handle.html>`_, `bugprone-dynamic-static-initializers <bugprone/dynamic-static-initializers.html>`_, `bugprone-easily-swappable-parameters <bugprone/easily-swappable-parameters.html>`_, + `bugprone-enum-to-int <bugprone/enum-to-int.html>`_, `bugprone-exception-escape <bugprone/exception-escape.html>`_, `bugprone-fold-init-type <bugprone/fold-init-type.html>`_, `bugprone-forward-declaration-namespace <bugprone/forward-declaration-namespace.html>`_, Index: clang-tools-extra/docs/clang-tidy/checks/bugprone/enum-to-int.rst =================================================================== --- /dev/null +++ clang-tools-extra/docs/clang-tidy/checks/bugprone/enum-to-int.rst @@ -0,0 +1,24 @@ +.. title:: clang-tidy - bugprone-enum-to-int + +bugprone-enum-to-int +==================== + +This check diagnoses instances where an enum is implicitly converted to an +integer. In C++11, enums can be defined as ``enum class`` which will prevent +such implicit conversion, however, ``enum`` provides no such guarantess to +prevent bugs. There can be many reasons why ``enum`` cannot be replaced with +``enum class`` such as compatibility with C or legacy libraries. + +This check will diagnose similiar implicit conversions whne using ``enum`` to +find the same class of bugs. Currently it will only warn on function or +constructor calls as such conversions are not clear to the usr, but this +could be expanded in the future. + +Examples: + +.. code-block:: c++ + + void foo(int i); + void f() { + foo(e1); // e1 is implictly converted to an int + } Index: clang-tools-extra/docs/ReleaseNotes.rst =================================================================== --- clang-tools-extra/docs/ReleaseNotes.rst +++ clang-tools-extra/docs/ReleaseNotes.rst @@ -118,6 +118,11 @@ New checks ^^^^^^^^^^ +- New :doc:`bugprone-enum-to-int + <clang-tidy/checks/bugprone/enum-to-int>` check. + + Finds implicit conversion of enum to an integral type. + - New :doc:`bugprone-shared-ptr-array-mismatch <clang-tidy/checks/bugprone/shared-ptr-array-mismatch>` check. Finds initializations of C++ shared pointers to non-array type that are initialized with an array. Index: clang-tools-extra/clang-tidy/bugprone/EnumToIntCheck.h =================================================================== --- /dev/null +++ clang-tools-extra/clang-tidy/bugprone/EnumToIntCheck.h @@ -0,0 +1,34 @@ +//===--- EnumToIntCheck.h - clang-tidy --------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_ENUMTOINTCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_ENUMTOINTCHECK_H + +#include "../ClangTidyCheck.h" + +namespace clang { +namespace tidy { +namespace bugprone { + +/// FIXME: Write a short description. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone/enum-to-int.html +class EnumToIntCheck : public ClangTidyCheck { +public: + EnumToIntCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace bugprone +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_ENUMTOINTCHECK_H Index: clang-tools-extra/clang-tidy/bugprone/EnumToIntCheck.cpp =================================================================== --- /dev/null +++ clang-tools-extra/clang-tidy/bugprone/EnumToIntCheck.cpp @@ -0,0 +1,37 @@ +//===--- EnumToIntCheck.cpp - clang-tidy ----------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "EnumToIntCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace bugprone { + +void EnumToIntCheck::registerMatchers(MatchFinder *Finder) { + auto ImplicitEnumToInt = implicitCastExpr( + hasCastKind(CK_IntegralCast), + hasSourceExpression(expr(hasType(enumType()))), + anyOf(hasParent(callExpr()), hasParent(cxxConstructExpr()))); + Finder->addMatcher(ImplicitEnumToInt.bind("x"), this); +} + +void EnumToIntCheck::check(const MatchFinder::MatchResult &Result) { + // FIXME: Add callback implementation. + const auto *MatchedExpr = Result.Nodes.getNodeAs<Expr>("x"); + diag(MatchedExpr->getBeginLoc(), + "Enum is implictly converted to an integral.") + << MatchedExpr->getSourceRange(); +} + +} // namespace bugprone +} // namespace tidy +} // namespace clang Index: clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt =================================================================== --- clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt +++ clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt @@ -14,6 +14,7 @@ DanglingHandleCheck.cpp DynamicStaticInitializersCheck.cpp EasilySwappableParametersCheck.cpp + EnumToIntCheck.cpp ExceptionEscapeCheck.cpp FoldInitTypeCheck.cpp ForwardDeclarationNamespaceCheck.cpp Index: clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp =================================================================== --- clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp +++ clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp @@ -19,6 +19,7 @@ #include "DanglingHandleCheck.h" #include "DynamicStaticInitializersCheck.h" #include "EasilySwappableParametersCheck.h" +#include "EnumToIntCheck.h" #include "ExceptionEscapeCheck.h" #include "FoldInitTypeCheck.h" #include "ForwardDeclarationNamespaceCheck.h" @@ -98,6 +99,7 @@ "bugprone-dynamic-static-initializers"); CheckFactories.registerCheck<EasilySwappableParametersCheck>( "bugprone-easily-swappable-parameters"); + CheckFactories.registerCheck<EnumToIntCheck>("bugprone-enum-to-int"); CheckFactories.registerCheck<ExceptionEscapeCheck>( "bugprone-exception-escape"); CheckFactories.registerCheck<FoldInitTypeCheck>(
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits