Author: Richard Date: 2022-04-19T21:28:17-06:00 New Revision: 08881c2de66b267446f01b908ea2e7297bdf3083
URL: https://github.com/llvm/llvm-project/commit/08881c2de66b267446f01b908ea2e7297bdf3083 DIFF: https://github.com/llvm/llvm-project/commit/08881c2de66b267446f01b908ea2e7297bdf3083.diff LOG: [clang-tidy] Improve macro handling in modernize-macro-to-enum When a macro is undef'ed or used in a preprocessor conditional expression, we need to remember that macro should it later be defined in the file to an integral value. We need to exclude such macro names from being turned into an enum. Maintain a blacklist of identifiers that we've seen in an undef or conditional preprocessor directive. When the file is done processing, remove all the blacklisted identifiers from conversion to an enum. Differential Revision: https://reviews.llvm.org/D123889 Fixes #54842 Added: Modified: clang-tools-extra/clang-tidy/modernize/MacroToEnumCheck.cpp clang-tools-extra/test/clang-tidy/checkers/modernize-macro-to-enum.cpp Removed: ################################################################################ diff --git a/clang-tools-extra/clang-tidy/modernize/MacroToEnumCheck.cpp b/clang-tools-extra/clang-tidy/modernize/MacroToEnumCheck.cpp index 07e1788857f29..90d3fe0b99822 100644 --- a/clang-tools-extra/clang-tidy/modernize/MacroToEnumCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/MacroToEnumCheck.cpp @@ -222,6 +222,8 @@ class MacroToEnumCallbacks : public PPCallbacks { void conditionStart(const SourceLocation &Loc); void checkCondition(SourceRange ConditionRange); void checkName(const Token &MacroNameTok); + void rememberExpressionName(const Token &MacroNameTok); + void invalidateExpressionNames(); void warnMacroEnum(const EnumMacro &Macro) const; void fixEnumMacro(const MacroList &MacroList) const; @@ -230,6 +232,7 @@ class MacroToEnumCallbacks : public PPCallbacks { const SourceManager &SM; SmallVector<MacroList> Enums; SmallVector<FileState> Files; + std::vector<std::string> ExpressionNames; FileState *CurrentFile = nullptr; }; @@ -284,8 +287,9 @@ void MacroToEnumCallbacks::checkCondition(SourceRange Range) { } void MacroToEnumCallbacks::checkName(const Token &MacroNameTok) { - StringRef Id = getTokenName(MacroNameTok); + rememberExpressionName(MacroNameTok); + StringRef Id = getTokenName(MacroNameTok); llvm::erase_if(Enums, [&Id](const MacroList &MacroList) { return llvm::any_of(MacroList, [&Id](const EnumMacro &Macro) { return getTokenName(Macro.Name) == Id; @@ -293,6 +297,14 @@ void MacroToEnumCallbacks::checkName(const Token &MacroNameTok) { }); } +void MacroToEnumCallbacks::rememberExpressionName(const Token &MacroNameTok) { + std::string Id = getTokenName(MacroNameTok).str(); + auto Pos = llvm::lower_bound(ExpressionNames, Id); + if (Pos == ExpressionNames.end() || *Pos != Id) { + ExpressionNames.insert(Pos, Id); + } +} + void MacroToEnumCallbacks::FileChanged(SourceLocation Loc, FileChangeReason Reason, SrcMgr::CharacteristicKind FileType, @@ -384,6 +396,8 @@ void MacroToEnumCallbacks::MacroDefined(const Token &MacroNameTok, void MacroToEnumCallbacks::MacroUndefined(const Token &MacroNameTok, const MacroDefinition &MD, const MacroDirective *Undef) { + rememberExpressionName(MacroNameTok); + auto MatchesToken = [&MacroNameTok](const EnumMacro &Macro) { return getTokenName(Macro.Name) == getTokenName(MacroNameTok); }; @@ -447,7 +461,19 @@ void MacroToEnumCallbacks::PragmaDirective(SourceLocation Loc, CurrentFile->GuardScanner = IncludeGuard::IfGuard; } +void MacroToEnumCallbacks::invalidateExpressionNames() { + for (const std::string &Id : ExpressionNames) { + llvm::erase_if(Enums, [Id](const MacroList &MacroList) { + return llvm::any_of(MacroList, [&Id](const EnumMacro &Macro) { + return getTokenName(Macro.Name) == Id; + }); + }); + } +} + void MacroToEnumCallbacks::EndOfMainFile() { + invalidateExpressionNames(); + for (const MacroList &MacroList : Enums) { if (MacroList.empty()) continue; 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 index 7727ce0e3a604..e065e83a0e1dc 100644 --- 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 @@ -181,6 +181,12 @@ #define USE_IFDEF 1 #define USE_IFNDEF 1 +// Undef'ing first and then defining later should still exclude this macro +#undef USE_UINT64 +#define USE_UINT64 0 +#undef USE_INT64 +#define USE_INT64 0 + #if defined(USE_FOO) && USE_FOO extern void foo(); #else @@ -243,6 +249,27 @@ inline void used_ifndef() {} #define IFNDEF3 3 #endif +// Macros used in conditions are invalidated, even if they look +// like enums after they are used in conditions. +#if DEFINED_LATER1 +#endif +#ifdef DEFINED_LATER2 +#endif +#ifndef DEFINED_LATER3 +#endif +#undef DEFINED_LATER4 +#if ((defined(DEFINED_LATER5) || DEFINED_LATER6) && DEFINED_LATER7) || (DEFINED_LATER8 > 10) +#endif + +#define DEFINED_LATER1 1 +#define DEFINED_LATER2 2 +#define DEFINED_LATER3 3 +#define DEFINED_LATER4 4 +#define DEFINED_LATER5 5 +#define DEFINED_LATER6 6 +#define DEFINED_LATER7 7 +#define DEFINED_LATER8 8 + // Sometimes an argument to ifdef can be classified as a keyword token. #ifdef __restrict #endif _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits