[clang-tools-extra] 08881c2 - [clang-tidy] Improve macro handling in modernize-macro-to-enum
via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 19 21:05:27 PDT 2022
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
More information about the cfe-commits
mailing list