janosbenjaminantal created this revision. janosbenjaminantal added reviewers: alexfh, njames93, xazax.hun, Eugene.Zelenko. Herald added subscribers: cfe-commits, aaron.ballman, rnkovacs, kbarton, mgorny, nemanjai. Herald added a project: clang. janosbenjaminantal requested review of this revision. Herald added a subscriber: wuzish.
This check aims to flag every occurence of unscoped enumerations and provide useful fix to convert them to scoped enumerations. It works for the most cases, except when an enumeration is defined within a macro, but the name of enumeration is a macro argument. This is indicated in the documentation. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D85697 Files: clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp clang-tools-extra/clang-tidy/cppcoreguidelines/PreferScopedEnumsOverUnscopedCheck.cpp clang-tools-extra/clang-tidy/cppcoreguidelines/PreferScopedEnumsOverUnscopedCheck.h clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-prefer-scoped-enums-over-unscoped.rst clang-tools-extra/docs/clang-tidy/checks/list.rst clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-prefer-scoped-enums-over-unscoped.cpp
Index: clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-prefer-scoped-enums-over-unscoped.cpp =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-prefer-scoped-enums-over-unscoped.cpp @@ -0,0 +1,33 @@ +// RUN: %check_clang_tidy %s cppcoreguidelines-prefer-scoped-enums-over-unscoped %t -- + +enum UnscopedEnum { + // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: enumeration 'UnscopedEnum' is not a scoped enumeration [cppcoreguidelines-prefer-scoped-enums-over-unscoped] + UE_FirstValue, + UE_SecondValue, +}; +// CHECK-FIXES: {{^}}enum class UnscopedEnum {{{$}} + +enum UnscopedEnumWithFixedUnderlyingType : char { + // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: enumeration 'UnscopedEnumWithFixedUnderlyingType' is not a scoped enumeration [cppcoreguidelines-prefer-scoped-enums-over-unscoped] + UEWFUT_FirstValue, + UEWFUT_SecondValue, +}; +// CHECK-FIXES: {{^}}enum class UnscopedEnumWithFixedUnderlyingType : char {{{$}} + +enum OpaqueUnscopedEnum : char; +// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: enumeration 'OpaqueUnscopedEnum' is not a scoped enumeration [cppcoreguidelines-prefer-scoped-enums-over-unscoped] +// CHECK-FIXES: {{^}}enum class OpaqueUnscopedEnum : char;{{$}} + +enum class ScopedEnumWithClass { + SEWC_FirstValue, + SEWC_SecondValue, +}; + +enum struct ScopedEnumWithStruct { + SEWC_FirstValue, + SEWC_SecondValue, +}; + +enum class OpaqueScopedEnum; + +enum class OpaqueScopedEnumWithFixedUnderlyingType : unsigned; 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 @@ -141,6 +141,7 @@ `cppcoreguidelines-narrowing-conversions <cppcoreguidelines-narrowing-conversions.html>`_, `cppcoreguidelines-no-malloc <cppcoreguidelines-no-malloc.html>`_, `cppcoreguidelines-owning-memory <cppcoreguidelines-owning-memory.html>`_, + `cppcoreguidelines-prefer-scoped-enums-over-unscoped <cppcoreguidelines-prefer-scoped-enums-over-unscoped.html>`_, "Yes" `cppcoreguidelines-pro-bounds-array-to-pointer-decay <cppcoreguidelines-pro-bounds-array-to-pointer-decay.html>`_, `cppcoreguidelines-pro-bounds-constant-array-index <cppcoreguidelines-pro-bounds-constant-array-index.html>`_, "Yes" `cppcoreguidelines-pro-bounds-pointer-arithmetic <cppcoreguidelines-pro-bounds-pointer-arithmetic.html>`_, Index: clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-prefer-scoped-enums-over-unscoped.rst =================================================================== --- /dev/null +++ clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-prefer-scoped-enums-over-unscoped.rst @@ -0,0 +1,64 @@ +.. title:: clang-tidy - cppcoreguidelines-prefer-scoped-enums-over-unscoped + +cppcoreguidelines-prefer-scoped-enums-over-unscoped +=================================================== + +Values of unscoped enumerations are implicitly-convertible to integral types. +To avoid such unwanted conversions, use scoped enumerations. + +This check implements +`Enum.3 <https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Renum-class>`_ +from the CppCoreGuidelines. + +Example: + +.. code-block:: c++ + + enum Foo { + A, + B + } + +After the fix is applied, the enum will become: + +.. code-block:: c++ + + enum class Foo { + A, + B + } + +Note: Although ``enum struct`` and ``enum class`` are exactly equivalent, the +latter is used mainly. + +Limitations +=========== + +If the enumeration is generated via a macro and the enumeration name is +received as a parameter, then the suggested fix would append the ``class`` +word before the name of enumeration at the macro invocation instead of the +macro definition. + +Example: + +.. code-block:: c++ + + #define CREATE_ENUM(Name) \ + enum Name { \ + A, \ + B \ + } + + CREATE_ENUM(Foo); + +After the fix is applied, it will become: + +.. code-block:: c++ + + #define CREATE_ENUM(Name) \ + enum Name { \ + A, \ + B \ + } + + CREATE_ENUM(class Foo); \ No newline at end of file Index: clang-tools-extra/clang-tidy/cppcoreguidelines/PreferScopedEnumsOverUnscopedCheck.h =================================================================== --- /dev/null +++ clang-tools-extra/clang-tidy/cppcoreguidelines/PreferScopedEnumsOverUnscopedCheck.h @@ -0,0 +1,37 @@ +//===--- PreferScopedEnumsOverUnscopedCheck.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_CPPCOREGUIDELINES_PREFERSCOPEDENUMSOVERUNSCOPEDCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PREFERSCOPEDENUMSOVERUNSCOPEDCHECK_H + +#include "../ClangTidyCheck.h" + +namespace clang { +namespace tidy { +namespace cppcoreguidelines { + +/// Checks Enum.3: +/// Flags every unscoped enumeration declaration. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-prefer-scoped-enums-over-unscoped.html +class PreferScopedEnumsOverUnscopedCheck : public ClangTidyCheck { +public: + PreferScopedEnumsOverUnscopedCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + bool isLanguageVersionSupported(const LangOptions &LangOpts) const override; + + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace cppcoreguidelines +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PREFERSCOPEDENUMSOVERUNSCOPEDCHECK_H Index: clang-tools-extra/clang-tidy/cppcoreguidelines/PreferScopedEnumsOverUnscopedCheck.cpp =================================================================== --- /dev/null +++ clang-tools-extra/clang-tidy/cppcoreguidelines/PreferScopedEnumsOverUnscopedCheck.cpp @@ -0,0 +1,42 @@ +//===--- PreferScopedEnumsOverUnscopedCheck.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 "PreferScopedEnumsOverUnscopedCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace cppcoreguidelines { + +bool PreferScopedEnumsOverUnscopedCheck::isLanguageVersionSupported( + const LangOptions &LangOpts) const { + return LangOpts.CPlusPlus11; +} + +void PreferScopedEnumsOverUnscopedCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher(enumDecl().bind("enumDecls"), this); +} + +void PreferScopedEnumsOverUnscopedCheck::check( + const MatchFinder::MatchResult &Result) { + const auto *MatchedDecl = Result.Nodes.getNodeAs<EnumDecl>("enumDecls"); + if (MatchedDecl->isScoped()) + return; + diag(MatchedDecl->getLocation(), "enumeration %0 is not a scoped enumeration") + << MatchedDecl; + diag(MatchedDecl->getLocation(), "use scoped enumeration instead", + DiagnosticIDs::Note) + << FixItHint::CreateInsertion(MatchedDecl->getLocation(), "class "); +} + +} // namespace cppcoreguidelines +} // namespace tidy +} // namespace clang Index: clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp =================================================================== --- clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp +++ clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp @@ -22,6 +22,7 @@ #include "NarrowingConversionsCheck.h" #include "NoMallocCheck.h" #include "OwningMemoryCheck.h" +#include "PreferScopedEnumsOverUnscopedCheck.h" #include "ProBoundsArrayToPointerDecayCheck.h" #include "ProBoundsConstantArrayIndexCheck.h" #include "ProBoundsPointerArithmeticCheck.h" @@ -66,6 +67,8 @@ "cppcoreguidelines-non-private-member-variables-in-classes"); CheckFactories.registerCheck<OwningMemoryCheck>( "cppcoreguidelines-owning-memory"); + CheckFactories.registerCheck<PreferScopedEnumsOverUnscopedCheck>( + "cppcoreguidelines-prefer-scoped-enums-over-unscoped"); CheckFactories.registerCheck<ProBoundsArrayToPointerDecayCheck>( "cppcoreguidelines-pro-bounds-array-to-pointer-decay"); CheckFactories.registerCheck<ProBoundsConstantArrayIndexCheck>( Index: clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt =================================================================== --- clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt +++ clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt @@ -13,6 +13,7 @@ NarrowingConversionsCheck.cpp NoMallocCheck.cpp OwningMemoryCheck.cpp + PreferScopedEnumsOverUnscopedCheck.cpp ProBoundsArrayToPointerDecayCheck.cpp ProBoundsConstantArrayIndexCheck.cpp ProBoundsPointerArithmeticCheck.cpp
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits