Author: Douglas Yung Date: 2022-03-25T11:53:42-07:00 New Revision: cef52105bd4b639a76de71cc84ed8d56bdaede1d
URL: https://github.com/llvm/llvm-project/commit/cef52105bd4b639a76de71cc84ed8d56bdaede1d DIFF: https://github.com/llvm/llvm-project/commit/cef52105bd4b639a76de71cc84ed8d56bdaede1d.diff LOG: Revert "[clang-tidy] Add modernize-macro-to-enum check" This reverts commit 39b80c8380c86539de391600efaa17184b5a52b4. This change was causing build failures on several build bots: - https://lab.llvm.org/buildbot/#/builders/139/builds/19210 - https://lab.llvm.org/buildbot/#/builders/93/builds/7956 Added: Modified: clang-tools-extra/clang-tidy/modernize/CMakeLists.txt clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp clang-tools-extra/docs/ReleaseNotes.rst clang-tools-extra/docs/clang-tidy/checks/list.rst Removed: clang-tools-extra/clang-tidy/modernize/MacroToEnumCheck.cpp clang-tools-extra/clang-tidy/modernize/MacroToEnumCheck.h clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-macro-to-enum.rst clang-tools-extra/docs/clang-tidy/checks/modernize-macro-to-enum.rst clang-tools-extra/test/clang-tidy/checkers/Inputs/modernize-macro-to-enum/modernize-macro-to-enum.h clang-tools-extra/test/clang-tidy/checkers/Inputs/modernize-macro-to-enum/modernize-macro-to-enum2.h clang-tools-extra/test/clang-tidy/checkers/Inputs/modernize-macro-to-enum/modernize-macro-to-enum3.h clang-tools-extra/test/clang-tidy/checkers/modernize-macro-to-enum.cpp ################################################################################ diff --git a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt index 6bf20552e0182..147c2741d59e4 100644 --- a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt @@ -11,7 +11,6 @@ add_clang_library(clangTidyModernizeModule DeprecatedIosBaseAliasesCheck.cpp LoopConvertCheck.cpp LoopConvertUtils.cpp - MacroToEnumCheck.cpp MakeSharedCheck.cpp MakeSmartPtrCheck.cpp MakeUniqueCheck.cpp diff --git a/clang-tools-extra/clang-tidy/modernize/MacroToEnumCheck.cpp b/clang-tools-extra/clang-tidy/modernize/MacroToEnumCheck.cpp deleted file mode 100644 index 834943483cffb..0000000000000 --- a/clang-tools-extra/clang-tidy/modernize/MacroToEnumCheck.cpp +++ /dev/null @@ -1,482 +0,0 @@ -//===--- MacroToEnumCheck.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 "MacroToEnumCheck.h" -#include "clang/AST/ASTContext.h" -#include "clang/ASTMatchers/ASTMatchFinder.h" -#include "clang/Lex/Preprocessor.h" -#include "llvm/ADT/STLExtras.h" -#include <algorithm> -#include <cassert> -#include <cctype> -#include <string> - -namespace clang { -namespace tidy { -namespace modernize { - -static bool hasOnlyComments(SourceLocation Loc, const LangOptions &Options, - StringRef Text) { - // Use a lexer to look for tokens; if we find something other than a single - // hash, then there were intervening tokens between macro definitions. - std::string Buffer{Text}; - Lexer Lex(Loc, Options, Buffer.c_str(), Buffer.c_str(), - Buffer.c_str() + Buffer.size()); - Token Tok; - bool SeenHash = false; - while (!Lex.LexFromRawLexer(Tok)) { - if (Tok.getKind() == tok::hash && !SeenHash) { - SeenHash = true; - continue; - } - return false; - } - - // Everything in between was whitespace, so now just look for two blank lines, - // consisting of two consecutive EOL sequences, either '\n', '\r' or '\r\n'. - enum class WhiteSpace { - Nothing, - CR, - LF, - CRLF, - CRLFCR, - }; - - WhiteSpace State = WhiteSpace::Nothing; - for (char C : Text) { - switch (C) { - case '\r': - if (State == WhiteSpace::CR) - return false; - - State = State == WhiteSpace::CRLF ? WhiteSpace::CRLFCR : WhiteSpace::CR; - break; - - case '\n': - if (State == WhiteSpace::LF || State == WhiteSpace::CRLFCR) - return false; - - State = State == WhiteSpace::CR ? WhiteSpace::CRLF : WhiteSpace::LF; - break; - - default: - State = WhiteSpace::Nothing; - break; - } - } - - return true; -} - -// Validate that this literal token is a valid integer literal. A literal token -// could be a floating-point token, which isn't acceptable as a value for an -// enumeration. A floating-point token must either have a decimal point or an -// exponent ('E' or 'P'). -static bool isIntegralConstant(const Token &Token) { - const char *Begin = Token.getLiteralData(); - const char *End = Begin + Token.getLength(); - - // not a hexadecimal floating-point literal - if (Token.getLength() > 2 && Begin[0] == '0' && std::toupper(Begin[1]) == 'X') - return std::none_of(Begin + 2, End, [](char C) { - return C == '.' || std::toupper(C) == 'P'; - }); - - // not a decimal floating-point literal - return std::none_of( - Begin, End, [](char C) { return C == '.' || std::toupper(C) == 'E'; }); -} - -namespace { - -struct EnumMacro { - EnumMacro(Token Name, const MacroDirective *Directive) - : Name(Name), Directive(Directive) {} - - Token Name; - const MacroDirective *Directive; -}; - -using MacroList = SmallVector<EnumMacro>; - -enum class IncludeGuard { None, FileChanged, IfGuard, DefineGuard }; - -struct FileState { - FileState() - : ConditionScopes(0), LastLine(0), GuardScanner(IncludeGuard::None) {} - - int ConditionScopes; - unsigned int LastLine; - IncludeGuard GuardScanner; - SourceLocation LastMacroLocation; -}; - -class MacroToEnumCallbacks : public PPCallbacks { -public: - MacroToEnumCallbacks(MacroToEnumCheck *Check, const LangOptions &LangOptions, - const SourceManager &SM) - : Check(Check), LangOptions(LangOptions), SM(SM) {} - - void FileChanged(SourceLocation Loc, FileChangeReason Reason, - SrcMgr::CharacteristicKind FileType, - FileID PrevFID) override; - - void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, - StringRef FileName, bool IsAngled, - CharSourceRange FilenameRange, const FileEntry *File, - StringRef SearchPath, StringRef RelativePath, - const Module *Imported, - SrcMgr::CharacteristicKind FileType) override { - clearCurrentEnum(HashLoc); - } - - // Keep track of macro definitions that look like enums. - void MacroDefined(const Token &MacroNameTok, - const MacroDirective *MD) override; - - // Undefining an enum-like macro results in the enum set being dropped. - void MacroUndefined(const Token &MacroNameTok, const MacroDefinition &MD, - const MacroDirective *Undef) override; - - // Conditional compilation clears any adjacent enum-like macros. - // Macros used in conditional expressions clear any adjacent enum-like - // macros. - // Include guards are either - // #if !defined(GUARD) - // or - // #ifndef GUARD - void If(SourceLocation Loc, SourceRange ConditionRange, - ConditionValueKind ConditionValue) override { - conditionStart(Loc); - checkCondition(ConditionRange); - } - void Ifndef(SourceLocation Loc, const Token &MacroNameTok, - const MacroDefinition &MD) override { - conditionStart(Loc); - checkName(MacroNameTok); - } - void Ifdef(SourceLocation Loc, const Token &MacroNameTok, - const MacroDefinition &MD) override { - conditionStart(Loc); - checkName(MacroNameTok); - } - void Elif(SourceLocation Loc, SourceRange ConditionRange, - ConditionValueKind ConditionValue, SourceLocation IfLoc) override { - checkCondition(ConditionRange); - } - void Elifdef(SourceLocation Loc, const Token &MacroNameTok, - const MacroDefinition &MD) override { - checkName(MacroNameTok); - } - void Elifndef(SourceLocation Loc, const Token &MacroNameTok, - const MacroDefinition &MD) override { - checkName(MacroNameTok); - } - void Endif(SourceLocation Loc, SourceLocation IfLoc) override; - void PragmaDirective(SourceLocation Loc, - PragmaIntroducerKind Introducer) override; - - // After we've seen everything, issue warnings and fix-its. - void EndOfMainFile() override; - -private: - void newEnum() { - if (Enums.empty() || !Enums.back().empty()) - Enums.emplace_back(); - } - bool insideConditional() const { - return (CurrentFile->GuardScanner == IncludeGuard::DefineGuard && - CurrentFile->ConditionScopes > 1) || - (CurrentFile->GuardScanner != IncludeGuard::DefineGuard && - CurrentFile->ConditionScopes > 0); - } - bool isConsecutiveMacro(const MacroDirective *MD) const; - void rememberLastMacroLocation(const MacroDirective *MD) { - CurrentFile->LastLine = SM.getSpellingLineNumber(MD->getLocation()); - CurrentFile->LastMacroLocation = Lexer::getLocForEndOfToken( - MD->getMacroInfo()->getDefinitionEndLoc(), 0, SM, LangOptions); - } - void clearLastMacroLocation() { - CurrentFile->LastLine = 0; - CurrentFile->LastMacroLocation = SourceLocation{}; - } - void clearCurrentEnum(SourceLocation Loc); - void conditionStart(const SourceLocation &Loc); - void checkCondition(SourceRange ConditionRange); - void checkName(const Token &MacroNameTok); - void warnMacroEnum(const EnumMacro &Macro) const; - void fixEnumMacro(const MacroList &MacroList) const; - - MacroToEnumCheck *Check; - const LangOptions &LangOptions; - const SourceManager &SM; - SmallVector<MacroList> Enums; - SmallVector<FileState> Files; - FileState *CurrentFile = nullptr; -}; - -bool MacroToEnumCallbacks::isConsecutiveMacro(const MacroDirective *MD) const { - if (CurrentFile->LastMacroLocation.isInvalid()) - return false; - - SourceLocation Loc = MD->getLocation(); - if (CurrentFile->LastLine + 1 == SM.getSpellingLineNumber(Loc)) - return true; - - SourceLocation Define = - SM.translateLineCol(SM.getFileID(Loc), SM.getSpellingLineNumber(Loc), 1); - CharSourceRange BetweenMacros{ - SourceRange{CurrentFile->LastMacroLocation, Define}, true}; - CharSourceRange CharRange = - Lexer::makeFileCharRange(BetweenMacros, SM, LangOptions); - StringRef BetweenText = Lexer::getSourceText(CharRange, SM, LangOptions); - return hasOnlyComments(Define, LangOptions, BetweenText); -} - -void MacroToEnumCallbacks::clearCurrentEnum(SourceLocation Loc) { - // Only drop the most recent Enum set if the directive immediately follows. - if (!Enums.empty() && !Enums.back().empty() && - SM.getSpellingLineNumber(Loc) == CurrentFile->LastLine + 1) - Enums.pop_back(); - - clearLastMacroLocation(); -} - -void MacroToEnumCallbacks::conditionStart(const SourceLocation &Loc) { - ++CurrentFile->ConditionScopes; - clearCurrentEnum(Loc); - if (CurrentFile->GuardScanner == IncludeGuard::FileChanged) - CurrentFile->GuardScanner = IncludeGuard::IfGuard; -} - -void MacroToEnumCallbacks::checkCondition(SourceRange Range) { - CharSourceRange CharRange = Lexer::makeFileCharRange( - CharSourceRange::getTokenRange(Range), SM, LangOptions); - std::string Text = Lexer::getSourceText(CharRange, SM, LangOptions).str(); - Lexer Lex(CharRange.getBegin(), LangOptions, Text.data(), Text.data(), - Text.data() + Text.size()); - Token Tok; - bool End = false; - while (!End) { - End = Lex.LexFromRawLexer(Tok); - if (Tok.is(tok::raw_identifier) && - Tok.getRawIdentifier().str() != "defined") - checkName(Tok); - } -} - -void MacroToEnumCallbacks::checkName(const Token &MacroNameTok) { - std::string Id; - if (MacroNameTok.is(tok::raw_identifier)) - Id = MacroNameTok.getRawIdentifier().str(); - else if (MacroNameTok.is(tok::identifier)) - Id = MacroNameTok.getIdentifierInfo()->getName().str(); - else { - assert(false && "Expected either an identifier or raw identifier token"); - return; - } - - llvm::erase_if(Enums, [&Id](const MacroList &MacroList) { - return llvm::any_of(MacroList, [&Id](const EnumMacro &Macro) { - return Macro.Name.getIdentifierInfo()->getName().str() == Id; - }); - }); -} - -void MacroToEnumCallbacks::FileChanged(SourceLocation Loc, - FileChangeReason Reason, - SrcMgr::CharacteristicKind FileType, - FileID PrevFID) { - newEnum(); - if (Reason == EnterFile) { - Files.emplace_back(); - if (!SM.isInMainFile(Loc)) - Files.back().GuardScanner = IncludeGuard::FileChanged; - } else if (Reason == ExitFile) { - assert(CurrentFile->ConditionScopes == 0); - Files.pop_back(); - } - CurrentFile = &Files.back(); -} - -void MacroToEnumCallbacks::MacroDefined(const Token &MacroNameTok, - const MacroDirective *MD) { - // Include guards are never candidates for becoming an enum. - if (CurrentFile->GuardScanner == IncludeGuard::IfGuard) { - CurrentFile->GuardScanner = IncludeGuard::DefineGuard; - return; - } - - if (insideConditional()) - return; - - if (SM.getFilename(MD->getLocation()).empty()) - return; - - const MacroInfo *Info = MD->getMacroInfo(); - if (Info->isFunctionLike() || Info->isBuiltinMacro() || - Info->tokens().empty() || Info->tokens().size() > 2) - return; - - // It can be +Lit, -Lit or just Lit. - Token Tok = Info->tokens().front(); - if (Info->tokens().size() == 2) { - if (!Tok.isOneOf(tok::TokenKind::minus, tok::TokenKind::plus, - tok::TokenKind::tilde)) - return; - Tok = Info->tokens().back(); - } - if (!Tok.isLiteral() || isStringLiteral(Tok.getKind()) || - !isIntegralConstant(Tok)) - return; - - if (!isConsecutiveMacro(MD)) - newEnum(); - Enums.back().emplace_back(MacroNameTok, MD); - rememberLastMacroLocation(MD); -} - -// Any macro that is undefined removes all adjacent macros from consideration as -// an enum and starts a new enum scan. -void MacroToEnumCallbacks::MacroUndefined(const Token &MacroNameTok, - const MacroDefinition &MD, - const MacroDirective *Undef) { - auto MatchesToken = [&MacroNameTok](const EnumMacro &Macro) { - return Macro.Name.getIdentifierInfo()->getName() == - MacroNameTok.getIdentifierInfo()->getName(); - }; - - auto It = llvm::find_if(Enums, [MatchesToken](const MacroList &MacroList) { - return llvm::any_of(MacroList, MatchesToken); - }); - if (It != Enums.end()) - Enums.erase(It); - - clearLastMacroLocation(); - CurrentFile->GuardScanner = IncludeGuard::None; -} - -void MacroToEnumCallbacks::Endif(SourceLocation Loc, SourceLocation IfLoc) { - // The if directive for the include guard isn't counted in the - // ConditionScopes. - if (CurrentFile->ConditionScopes == 0 && - CurrentFile->GuardScanner == IncludeGuard::DefineGuard) - return; - - // We don't need to clear the current enum because the start of the - // conditional block already took care of that. - assert(CurrentFile->ConditionScopes > 0); - --CurrentFile->ConditionScopes; -} - -namespace { - -template <size_t N> -bool textEquals(const char (&Needle)[N], const char *HayStack) { - return StringRef{HayStack, N - 1} == Needle; -} - -template <size_t N> size_t len(const char (&)[N]) { return N - 1; } - -} // namespace - -void MacroToEnumCallbacks::PragmaDirective(SourceLocation Loc, - PragmaIntroducerKind Introducer) { - if (CurrentFile->GuardScanner != IncludeGuard::FileChanged) - return; - - bool Invalid = false; - const char *Text = SM.getCharacterData( - Lexer::getLocForEndOfToken(Loc, 0, SM, LangOptions), &Invalid); - if (Invalid) - return; - - while (*Text && std::isspace(*Text)) - ++Text; - - if (textEquals("pragma", Text)) - return; - - Text += len("pragma"); - while (*Text && std::isspace(*Text)) - ++Text; - - if (textEquals("once", Text)) - CurrentFile->GuardScanner = IncludeGuard::IfGuard; -} - -void MacroToEnumCallbacks::EndOfMainFile() { - for (const MacroList &MacroList : Enums) { - if (MacroList.empty()) - continue; - - for (const EnumMacro &Macro : MacroList) - warnMacroEnum(Macro); - - fixEnumMacro(MacroList); - } -} - -void MacroToEnumCallbacks::warnMacroEnum(const EnumMacro &Macro) const { - Check->diag(Macro.Directive->getLocation(), - "macro %0 defines an integral constant; prefer an enum instead") - << Macro.Name.getIdentifierInfo(); -} - -void MacroToEnumCallbacks::fixEnumMacro(const MacroList &MacroList) const { - SourceLocation Begin = - MacroList.front().Directive->getMacroInfo()->getDefinitionLoc(); - Begin = SM.translateLineCol(SM.getFileID(Begin), - SM.getSpellingLineNumber(Begin), 1); - DiagnosticBuilder Diagnostic = - Check->diag(Begin, "replace macro with enum") - << FixItHint::CreateInsertion(Begin, "enum {\n"); - - for (size_t I = 0u; I < MacroList.size(); ++I) { - const EnumMacro &Macro = MacroList[I]; - SourceLocation DefineEnd = - Macro.Directive->getMacroInfo()->getDefinitionLoc(); - SourceLocation DefineBegin = SM.translateLineCol( - SM.getFileID(DefineEnd), SM.getSpellingLineNumber(DefineEnd), 1); - CharSourceRange DefineRange; - DefineRange.setBegin(DefineBegin); - DefineRange.setEnd(DefineEnd); - Diagnostic << FixItHint::CreateRemoval(DefineRange); - - SourceLocation NameEnd = Lexer::getLocForEndOfToken( - Macro.Directive->getMacroInfo()->getDefinitionLoc(), 0, SM, - LangOptions); - Diagnostic << FixItHint::CreateInsertion(NameEnd, " ="); - - SourceLocation ValueEnd = Lexer::getLocForEndOfToken( - Macro.Directive->getMacroInfo()->getDefinitionEndLoc(), 0, SM, - LangOptions); - if (I < MacroList.size() - 1) - Diagnostic << FixItHint::CreateInsertion(ValueEnd, ","); - } - - SourceLocation End = Lexer::getLocForEndOfToken( - MacroList.back().Directive->getMacroInfo()->getDefinitionEndLoc(), 0, SM, - LangOptions); - End = SM.translateLineCol(SM.getFileID(End), - SM.getSpellingLineNumber(End) + 1, 1); - Diagnostic << FixItHint::CreateInsertion(End, "};\n"); -} - -} // namespace - -void MacroToEnumCheck::registerPPCallbacks(const SourceManager &SM, - Preprocessor *PP, - Preprocessor *ModuleExpanderPP) { - PP->addPPCallbacks( - std::make_unique<MacroToEnumCallbacks>(this, getLangOpts(), SM)); -} - -} // namespace modernize -} // namespace tidy -} // namespace clang diff --git a/clang-tools-extra/clang-tidy/modernize/MacroToEnumCheck.h b/clang-tools-extra/clang-tidy/modernize/MacroToEnumCheck.h deleted file mode 100644 index 667ff49d671a1..0000000000000 --- a/clang-tools-extra/clang-tidy/modernize/MacroToEnumCheck.h +++ /dev/null @@ -1,34 +0,0 @@ -//===--- MacroToEnumCheck.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_MODERNIZE_MACROTOENUMCHECK_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_MACROTOENUMCHECK_H - -#include "../ClangTidyCheck.h" - -namespace clang { -namespace tidy { -namespace modernize { - -/// Replaces groups of related macros with an unscoped anonymous enum. -/// -/// For the user-facing documentation see: -/// http://clang.llvm.org/extra/clang-tidy/checks/modernize-macro-to-enum.html -class MacroToEnumCheck : public ClangTidyCheck { -public: - MacroToEnumCheck(StringRef Name, ClangTidyContext *Context) - : ClangTidyCheck(Name, Context) {} - void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP, - Preprocessor *ModuleExpanderPP) override; -}; - -} // namespace modernize -} // namespace tidy -} // namespace clang - -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_MACROTOENUMCHECK_H diff --git a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp index 08076354dbe4b..d9ccd2cd0ad7f 100644 --- a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp @@ -15,7 +15,6 @@ #include "DeprecatedHeadersCheck.h" #include "DeprecatedIosBaseAliasesCheck.h" #include "LoopConvertCheck.h" -#include "MacroToEnumCheck.h" #include "MakeSharedCheck.h" #include "MakeUniqueCheck.h" #include "PassByValueCheck.h" @@ -60,7 +59,6 @@ class ModernizeModule : public ClangTidyModule { CheckFactories.registerCheck<DeprecatedIosBaseAliasesCheck>( "modernize-deprecated-ios-base-aliases"); CheckFactories.registerCheck<LoopConvertCheck>("modernize-loop-convert"); - CheckFactories.registerCheck<MacroToEnumCheck>("modernize-macro-to-enum"); CheckFactories.registerCheck<MakeSharedCheck>("modernize-make-shared"); CheckFactories.registerCheck<MakeUniqueCheck>("modernize-make-unique"); CheckFactories.registerCheck<PassByValueCheck>("modernize-pass-by-value"); diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 282cf1d0a4cc1..2d144aae75e65 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -106,18 +106,9 @@ New checks Finds initializations of C++ shared pointers to non-array type that are initialized with an array. -- New :doc:`modernize-macro-to-enum - <clang-tidy/checks/modernize-macro-to-enum>` check. - - Replaces groups of adjacent macros with an unscoped anonymous enum. - New check aliases ^^^^^^^^^^^^^^^^^ -- New alias :doc:`cppcoreguidelines-macro-to-enum - <clang-tidy/checks/cppcoreguidelines-macro-to-enum>` to :doc:`modernize-macro-to-enum - <clang-tidy/checks/modernize-macro-to-enum>` was added. - Changes in existing checks ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-macro-to-enum.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-macro-to-enum.rst deleted file mode 100644 index c9601c652ad99..0000000000000 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-macro-to-enum.rst +++ /dev/null @@ -1,9 +0,0 @@ -.. title:: clang-tidy - cppcoreguidelines-macro-to-enum -.. meta:: - :http-equiv=refresh: 5;URL=modernize-macro-to-enum.html - -cppcoreguidelines-macro-to-enum -=============================== - -The cppcoreguidelines-macro-to-enum check is an alias, please see -:doc:`modernize-macro-to-enum <modernize-macro-to-enum>` for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index e9367216ac515..ebdcd7ae1041e 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -234,7 +234,6 @@ Clang-Tidy Checks `modernize-deprecated-headers <modernize-deprecated-headers.html>`_, "Yes" `modernize-deprecated-ios-base-aliases <modernize-deprecated-ios-base-aliases.html>`_, "Yes" `modernize-loop-convert <modernize-loop-convert.html>`_, "Yes" - `modernize-macro-to-enum <modernize-macro-to-enum.html>`_, "Yes" `modernize-make-shared <modernize-make-shared.html>`_, "Yes" `modernize-make-unique <modernize-make-unique.html>`_, "Yes" `modernize-pass-by-value <modernize-pass-by-value.html>`_, "Yes" @@ -427,7 +426,6 @@ Clang-Tidy Checks `cppcoreguidelines-avoid-magic-numbers <cppcoreguidelines-avoid-magic-numbers.html>`_, `readability-magic-numbers <readability-magic-numbers.html>`_, `cppcoreguidelines-c-copy-assignment-signature <cppcoreguidelines-c-copy-assignment-signature.html>`_, `misc-unconventional-assign-operator <misc-unconventional-assign-operator.html>`_, `cppcoreguidelines-explicit-virtual-functions <cppcoreguidelines-explicit-virtual-functions.html>`_, `modernize-use-override <modernize-use-override.html>`_, "Yes" - `cppcoreguidelines-macro-to-enum <cppcoreguidelines-macro-to-enum.html>`_, `modernize-macro-to-enum <modernize-macro-to-enum.html>`_, "Yes" `cppcoreguidelines-non-private-member-variables-in-classes <cppcoreguidelines-non-private-member-variables-in-classes.html>`_, `misc-non-private-member-variables-in-classes <misc-non-private-member-variables-in-classes.html>`_, `fuchsia-header-anon-namespaces <fuchsia-header-anon-namespaces.html>`_, `google-build-namespaces <google-build-namespaces.html>`_, `google-readability-braces-around-statements <google-readability-braces-around-statements.html>`_, `readability-braces-around-statements <readability-braces-around-statements.html>`_, "Yes" diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize-macro-to-enum.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize-macro-to-enum.rst deleted file mode 100644 index 6be406544ba87..0000000000000 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize-macro-to-enum.rst +++ /dev/null @@ -1,66 +0,0 @@ -.. title:: clang-tidy - modernize-macro-to-enum - -modernize-macro-to-enum -======================= - -Replaces groups of adjacent macros with an unscoped anonymous enum. -Using an unscoped anonymous enum ensures that everywhere the macro -token was used previously, the enumerator name may be safely used. - -This check can be used to enforce the C++ core guideline `Enum.1: -Prefer enumerations over macros -<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#enum1-prefer-enumerations-over-macros>`_, -within the constraints outlined below. - -Potential macros for replacement must meet the following constraints: - -- Macros must expand only to integral literal tokens. The unary operators - plus, minus and tilde are recognized to allow for positive, negative - and bitwise negated integers. More complicated integral constant - expressions are not currently recognized by this check. -- Macros must be defined on sequential source file lines, or with - only comment lines in between macro definitions. -- Macros must all be defined in the same source file. -- Macros must not be defined within a conditional compilation block. - (Conditional include guards are exempt from this constraint.) -- Macros must not be defined adjacent to other preprocessor directives. -- Macros must not be used in any conditional preprocessing directive. -- Macros must not be undefined. - -Each cluster of macros meeting the above constraints is presumed to -be a set of values suitable for replacement by an anonymous enum. -From there, a developer can give the anonymous enum a name and -continue refactoring to a scoped enum if desired. Comments on the -same line as a macro definition or between subsequent macro definitions -are preserved in the output. No formatting is assumed in the provided -replacements, although clang-tidy can optionally format all fixes. - -Examples: - -.. code-block:: c++ - - #define RED 0xFF0000 - #define GREEN 0x00FF00 - #define BLUE 0x0000FF - - #define TM_ONE 1 // Use tailored method one. - #define TM_TWO 2 // Use tailored method two. Method two - // is preferable to method one. - #define TM_THREE 3 // Use tailored method three. - -becomes - -.. code-block:: c++ - - enum { - RED = 0xFF0000, - GREEN = 0x00FF00, - BLUE = 0x0000FF - }; - - enum { - TM_ONE = 1, // Use tailored method one. - TM_TWO = 2, // Use tailored method two. Method two - // is preferable to method one. - TM_THREE = 3 // Use tailored method three. - }; diff --git a/clang-tools-extra/test/clang-tidy/checkers/Inputs/modernize-macro-to-enum/modernize-macro-to-enum.h b/clang-tools-extra/test/clang-tidy/checkers/Inputs/modernize-macro-to-enum/modernize-macro-to-enum.h deleted file mode 100644 index f747be4761bb4..0000000000000 --- a/clang-tools-extra/test/clang-tidy/checkers/Inputs/modernize-macro-to-enum/modernize-macro-to-enum.h +++ /dev/null @@ -1,25 +0,0 @@ -#if !defined(MODERNIZE_MACRO_TO_ENUM_H) -#define MODERNIZE_MACRO_TO_ENUM_H - -#include "modernize-macro-to-enum2.h" - -#define GG_RED 0xFF0000 -#define GG_GREEN 0x00FF00 -#define GG_BLUE 0x0000FF -// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: replace macro with enum -// CHECK-MESSAGES: :[[@LINE-4]]:9: warning: macro 'GG_RED' defines an integral constant; prefer an enum instead -// CHECK-MESSAGES: :[[@LINE-4]]:9: warning: macro 'GG_GREEN' defines an integral constant; prefer an enum instead -// CHECK-MESSAGES: :[[@LINE-4]]:9: warning: macro 'GG_BLUE' defines an integral constant; prefer an enum instead -// CHECK-FIXES: enum { -// CHECK-FIXES-NEXT: GG_RED = 0xFF0000, -// CHECK-FIXES-NEXT: GG_GREEN = 0x00FF00, -// CHECK-FIXES-NEXT: GG_BLUE = 0x0000FF -// CHECK-FIXES-NEXT: }; - -#if 1 -#define RR_RED 1 -#define RR_GREEN 2 -#define RR_BLUE 3 -#endif - -#endif diff --git a/clang-tools-extra/test/clang-tidy/checkers/Inputs/modernize-macro-to-enum/modernize-macro-to-enum2.h b/clang-tools-extra/test/clang-tidy/checkers/Inputs/modernize-macro-to-enum/modernize-macro-to-enum2.h deleted file mode 100644 index 1616302a5b693..0000000000000 --- a/clang-tools-extra/test/clang-tidy/checkers/Inputs/modernize-macro-to-enum/modernize-macro-to-enum2.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef MODERNIZE_MACRO_TO_ENUM2_H -#define MODERNIZE_MACRO_TO_ENUM2_H - -#include "modernize-macro-to-enum3.h" - -#define GG2_RED 0xFF0000 -#define GG2_GREEN 0x00FF00 -#define GG2_BLUE 0x0000FF -// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: replace macro with enum -// CHECK-MESSAGES: :[[@LINE-4]]:9: warning: macro 'GG2_RED' defines an integral constant; prefer an enum instead -// CHECK-MESSAGES: :[[@LINE-4]]:9: warning: macro 'GG2_GREEN' defines an integral constant; prefer an enum instead -// CHECK-MESSAGES: :[[@LINE-4]]:9: warning: macro 'GG2_BLUE' defines an integral constant; prefer an enum instead -// CHECK-FIXES: enum { -// CHECK-FIXES-NEXT: GG2_RED = 0xFF0000, -// CHECK-FIXES-NEXT: GG2_GREEN = 0x00FF00, -// CHECK-FIXES-NEXT: GG2_BLUE = 0x0000FF -// CHECK-FIXES-NEXT: }; - -#if 1 -#define RR2_RED 1 -#define RR2_GREEN 2 -#define RR2_BLUE 3 -#endif - -#endif diff --git a/clang-tools-extra/test/clang-tidy/checkers/Inputs/modernize-macro-to-enum/modernize-macro-to-enum3.h b/clang-tools-extra/test/clang-tidy/checkers/Inputs/modernize-macro-to-enum/modernize-macro-to-enum3.h deleted file mode 100644 index a9f1fb7e0fa47..0000000000000 --- a/clang-tools-extra/test/clang-tidy/checkers/Inputs/modernize-macro-to-enum/modernize-macro-to-enum3.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#define GG3_RED 0xFF0000 -#define GG3_GREEN 0x00FF00 -#define GG3_BLUE 0x0000FF -// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: replace macro with enum -// CHECK-MESSAGES: :[[@LINE-4]]:9: warning: macro 'GG3_RED' defines an integral constant; prefer an enum instead -// CHECK-MESSAGES: :[[@LINE-4]]:9: warning: macro 'GG3_GREEN' defines an integral constant; prefer an enum instead -// CHECK-MESSAGES: :[[@LINE-4]]:9: warning: macro 'GG3_BLUE' defines an integral constant; prefer an enum instead -// CHECK-FIXES: enum { -// CHECK-FIXES-NEXT: GG3_RED = 0xFF0000, -// CHECK-FIXES-NEXT: GG3_GREEN = 0x00FF00, -// CHECK-FIXES-NEXT: GG3_BLUE = 0x0000FF -// CHECK-FIXES-NEXT: }; - -#if 1 -#define RR3_RED 1 -#define RR3_GREEN 2 -#define RR3_BLUE 3 -#endif diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize-macro-to-enum.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize-macro-to-enum.cpp deleted file mode 100644 index 5a5514fc074cb..0000000000000 --- a/clang-tools-extra/test/clang-tidy/checkers/modernize-macro-to-enum.cpp +++ /dev/null @@ -1,239 +0,0 @@ -// RUN: %check_clang_tidy -std=c++14-or-later %s modernize-macro-to-enum %t -- -- -I%S/Inputs/modernize-macro-to-enum -// C++14 or later required for binary literals. - -#if 1 -#include "modernize-macro-to-enum.h" - -// These macros are skipped due to being inside a conditional compilation block. -#define GOO_RED 1 -#define GOO_GREEN 2 -#define GOO_BLUE 3 - -#endif - -#define RED 0xFF0000 -#define GREEN 0x00FF00 -#define BLUE 0x0000FF -// CHECK-MESSAGES: :[[@LINE-3]]:1: warning: replace macro with enum [modernize-macro-to-enum] -// CHECK-MESSAGES: :[[@LINE-4]]:9: warning: macro 'RED' defines an integral constant; prefer an enum instead -// CHECK-MESSAGES: :[[@LINE-4]]:9: warning: macro 'GREEN' defines an integral constant; prefer an enum instead -// CHECK-MESSAGES: :[[@LINE-4]]:9: warning: macro 'BLUE' defines an integral constant; prefer an enum instead -// CHECK-FIXES: enum { -// CHECK-FIXES-NEXT: RED = 0xFF0000, -// CHECK-FIXES-NEXT: GREEN = 0x00FF00, -// CHECK-FIXES-NEXT: BLUE = 0x0000FF -// CHECK-FIXES-NEXT: }; - -// Verify that comments are preserved. -#define CoordModeOrigin 0 /* relative to the origin */ -#define CoordModePrevious 1 /* relative to previous point */ -// CHECK-MESSAGES: :[[@LINE-2]]:1: warning: replace macro with enum -// CHECK-MESSAGES: :[[@LINE-3]]:9: warning: macro 'CoordModeOrigin' defines an integral constant; prefer an enum instead -// CHECK-MESSAGES: :[[@LINE-3]]:9: warning: macro 'CoordModePrevious' defines an integral constant; prefer an enum instead -// CHECK-FIXES: enum { -// CHECK-FIXES-NEXT: CoordModeOrigin = 0, /* relative to the origin */ -// CHECK-FIXES-NEXT: CoordModePrevious = 1 /* relative to previous point */ -// CHECK-FIXES-NEXT: }; - -// Verify that multiline comments are preserved. -#define BadDrawable 9 /* parameter not a Pixmap or Window */ -#define BadAccess 10 /* depending on context: - - key/button already grabbed - - attempt to free an illegal - cmap entry - - attempt to store into a read-only - color map entry. */ - // - attempt to modify the access control - // list from other than the local host. - // -#define BadAlloc 11 /* insufficient resources */ -// CHECK-MESSAGES: :[[@LINE-11]]:1: warning: replace macro with enum -// CHECK-MESSAGES: :[[@LINE-12]]:9: warning: macro 'BadDrawable' defines an integral constant; prefer an enum instead -// CHECK-MESSAGES: :[[@LINE-12]]:9: warning: macro 'BadAccess' defines an integral constant; prefer an enum instead -// CHECK-MESSAGES: :[[@LINE-4]]:9: warning: macro 'BadAlloc' defines an integral constant; prefer an enum instead -// CHECK-FIXES: enum { -// CHECK-FIXES-NEXT: BadDrawable = 9, /* parameter not a Pixmap or Window */ -// CHECK-FIXES-NEXT: BadAccess = 10, /* depending on context: -// CHECK-FIXES-NEXT: - key/button already grabbed -// CHECK-FIXES-NEXT: - attempt to free an illegal -// CHECK-FIXES-NEXT: cmap entry -// CHECK-FIXES-NEXT: - attempt to store into a read-only -// CHECK-FIXES-NEXT: color map entry. */ -// CHECK-FIXES-NEXT: // - attempt to modify the access control -// CHECK-FIXES-NEXT: // list from other than the local host. -// CHECK-FIXES-NEXT: // -// CHECK-FIXES-NEXT: BadAlloc = 11 /* insufficient resources */ -// CHECK-FIXES-NEXT: }; - -// Undefining a macro invalidates adjacent macros -// from being considered as an enum. -#define REMOVED1 1 -#define REMOVED2 2 -#define REMOVED3 3 -#undef REMOVED2 -#define VALID1 1 -// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: replace macro with enum -// CHECK-MESSAGES: :[[@LINE-2]]:9: warning: macro 'VALID1' defines an integral constant; prefer an enum instead -// CHECK-FIXES: enum { -// CHECK-FIXES-NEXT: VALID1 = 1 -// CHECK-FIXES-NEXT: }; - -#define UNDEF1 1 -#define UNDEF2 2 -#define UNDEF3 3 - -// Undefining a macro later invalidates the set of possible adjacent macros -// from being considered as an enum. -#undef UNDEF2 - -// Integral constants can have an optional sign -#define SIGNED1 +1 -#define SIGNED2 -1 -// CHECK-MESSAGES: :[[@LINE-2]]:1: warning: replace macro with enum -// CHECK-MESSAGES: :[[@LINE-3]]:9: warning: macro 'SIGNED1' defines an integral constant; prefer an enum instead -// CHECK-MESSAGES: :[[@LINE-3]]:9: warning: macro 'SIGNED2' defines an integral constant; prefer an enum instead -// CHECK-FIXES: enum { -// CHECK-FIXES-NEXT: SIGNED1 = +1, -// CHECK-FIXES-NEXT: SIGNED2 = -1 -// CHECK-FIXES-NEXT: }; - -// Integral constants with bitwise negated values -#define UNOP1 ~0U -#define UNOP2 ~1U -// CHECK-MESSAGES: :[[@LINE-2]]:1: warning: replace macro with enum -// CHECK-MESSAGES: :[[@LINE-3]]:9: warning: macro 'UNOP1' defines an integral constant; prefer an enum instead -// CHECK-MESSAGES: :[[@LINE-3]]:9: warning: macro 'UNOP2' defines an integral constant; prefer an enum instead -// CHECK-FIXES: enum { -// CHECK-FIXES-NEXT: UNOP1 = ~0U, -// CHECK-FIXES-NEXT: UNOP2 = ~1U -// CHECK-FIXES-NEXT: }; - -// Integral constants in other bases and with suffixes are OK -#define BASE1 0777 // octal -#define BASE2 0xDEAD // hexadecimal -#define BASE3 0b0011 // binary -#define SUFFIX1 +1U -#define SUFFIX2 -1L -#define SUFFIX3 +1UL -#define SUFFIX4 -1LL -#define SUFFIX5 +1ULL -// CHECK-MESSAGES: :[[@LINE-8]]:1: warning: replace macro with enum -// CHECK-MESSAGES: :[[@LINE-9]]:9: warning: macro 'BASE1' defines an integral constant; prefer an enum instead -// CHECK-MESSAGES: :[[@LINE-9]]:9: warning: macro 'BASE2' defines an integral constant; prefer an enum instead -// CHECK-MESSAGES: :[[@LINE-9]]:9: warning: macro 'BASE3' defines an integral constant; prefer an enum instead -// CHECK-MESSAGES: :[[@LINE-9]]:9: warning: macro 'SUFFIX1' defines an integral constant; prefer an enum instead -// CHECK-MESSAGES: :[[@LINE-9]]:9: warning: macro 'SUFFIX2' defines an integral constant; prefer an enum instead -// CHECK-MESSAGES: :[[@LINE-9]]:9: warning: macro 'SUFFIX3' defines an integral constant; prefer an enum instead -// CHECK-MESSAGES: :[[@LINE-9]]:9: warning: macro 'SUFFIX4' defines an integral constant; prefer an enum instead -// CHECK-MESSAGES: :[[@LINE-9]]:9: warning: macro 'SUFFIX5' defines an integral constant; prefer an enum instead -// CHECK-FIXES: enum { -// CHECK-FIXES-NEXT: BASE1 = 0777, // octal -// CHECK-FIXES-NEXT: BASE2 = 0xDEAD, // hexadecimal -// CHECK-FIXES-NEXT: BASE3 = 0b0011, // binary -// CHECK-FIXES-NEXT: SUFFIX1 = +1U, -// CHECK-FIXES-NEXT: SUFFIX2 = -1L, -// CHECK-FIXES-NEXT: SUFFIX3 = +1UL, -// CHECK-FIXES-NEXT: SUFFIX4 = -1LL, -// CHECK-FIXES-NEXT: SUFFIX5 = +1ULL -// CHECK-FIXES-NEXT: }; - -// Macros appearing in conditional expressions can't be replaced -// by enums. -#define USE_FOO 1 -#define USE_BAR 0 -#define USE_IF 1 -#define USE_ELIF 1 -#define USE_IFDEF 1 -#define USE_IFNDEF 1 - -#if defined(USE_FOO) && USE_FOO -extern void foo(); -#else -inline void foo() {} -#endif - -#if USE_BAR -extern void bar(); -#else -inline void bar() {} -#endif - -#if USE_IF -inline void used_if() {} -#endif - -#if 0 -#elif USE_ELIF -inline void used_elif() {} -#endif - -#ifdef USE_IFDEF -inline void used_ifdef() {} -#endif - -#ifndef USE_IFNDEF -#else -inline void used_ifndef() {} -#endif - -// Regular conditional compilation blocks should leave previous -// macro enums alone. -#if 0 -#include <non-existent.h> -#endif - -// Conditional compilation blocks invalidate adjacent macros -// from being considered as an enum. Conditionally compiled -// blocks could contain macros that should rightly be included -// in the enum, but we can't explore multiple branches of a -// conditionally compiled section in clang-tidy, only the active -// branch based on compilation options. -#define CONDITION1 1 -#define CONDITION2 2 -#if 0 -#define CONDITION3 3 -#else -#define CONDITION3 -3 -#endif - -#define IFDEF1 1 -#define IFDEF2 2 -#ifdef FROB -#define IFDEF3 3 -#endif - -#define IFNDEF1 1 -#define IFNDEF2 2 -#ifndef GOINK -#define IFNDEF3 3 -#endif - -// These macros do not expand to integral constants. -#define HELLO "Hello, " -#define WORLD "World" -#define EPS1 1.0F -#define EPS2 1e5 -#define EPS3 1. - -#define DO_RED draw(RED) -#define DO_GREEN draw(GREEN) -#define DO_BLUE draw(BLUE) - -#define FN_RED(x) draw(RED | x) -#define FN_GREEN(x) draw(GREEN | x) -#define FN_BLUE(x) draw(BLUE | x) - -extern void draw(unsigned int Color); - -void f() -{ - draw(RED); - draw(GREEN); - draw(BLUE); - DO_RED; - DO_GREEN; - DO_BLUE; - FN_RED(0); - FN_GREEN(0); - FN_BLUE(0); -} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits