Commit Graph

11 Commits

Author SHA1 Message Date
Richard b418ef5cb9 [clang-tidy] Reject invalid enum initializers in C files
C requires that enum values fit into an int.  Scan the macro tokens
present in an initializing expression and reject macros that contain
tokens that have suffixes making them larger than int.

C forbids the comma operator in enum initializing expressions, so
optionally reject comma operator.

Differential Revision: https://reviews.llvm.org/D125622

Fixes #55467
2022-06-01 22:25:39 -06:00
Richard 5122738331 [clang-tidy] Support expressions of literals in modernize-macro-to-enum
Add a recursive descent parser to match macro expansion tokens against
fully formed valid expressions of integral literals.  Partial
expressions will not be matched -- they can't be valid initializing
expressions for an enum.

Differential Revision: https://reviews.llvm.org/D124500

Fixes #55055
2022-05-13 18:45:54 -06:00
Richard 693246e03f [clang-tidy] Modernize-macro-to-enum should skip macros used in other macros
If a macro is used in the expansion of another macro, that can cause
a compile error if the macro is replaced with an enum.  Token-pasting is
an example where converting a macro defined as an integral constant can
cause code to no longer compile.

This change causes such macros to be skipped from the conversion
process in order to prevent fixits from creating code that no longer
compiles.

A subsequent enhancement will examine macro usage in more detail to
allow more cases to be handled without breaking code.

Differential Revision: https://reviews.llvm.org/D124316

Fixes #54948
2022-04-26 21:09:13 -06:00
Richard b985b6e3c1 [clang-tidy] Ignore macros defined within declarations
Modernize-macro-to-enum shouldn't try to convert macros to enums
when they are defined inside a declaration or definition, only
when the macros are defined at the top level.  Since preprocessing
is disconnected from AST traversal, match nodes in the AST and then
invalidate source ranges spanning AST nodes before issuing diagnostics.

ClangTidyCheck::onEndOfTranslationUnit is called before
PPCallbacks::EndOfMainFile, so defer final diagnostics to the
PPCallbacks implementation.

Differential Revision: https://reviews.llvm.org/D124066

Fixes #54883
2022-04-22 17:46:54 -06:00
Richard 08881c2de6 [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
2022-04-19 21:28:17 -06:00
Jan Svoboda d79ad2f1db [clang][lex] NFCI: Use FileEntryRef in PPCallbacks::InclusionDirective()
This patch changes type of the `File` parameter in `PPCallbacks::InclusionDirective()` from `const FileEntry *` to `Optional<FileEntryRef>`.

With the API change in place, this patch then removes some uses of the deprecated `FileEntry::getName()` (e.g. in `DependencyGraph.cpp` and `ModuleDependencyCollector.cpp`).

Reviewed By: dexonsmith, bnbarham

Differential Revision: https://reviews.llvm.org/D123574
2022-04-14 10:46:12 +02:00
Richard d563c2d0e5 [clang-tidy] Support parenthesized literals in modernize-macro-to-enum
When scanning a macro expansion to examine it as a candidate enum,
first strip off arbitrary matching parentheses from the outside in,
then examine what remains to see if it is Lit, +Lit, -Lit or ~Lit.
If not, reject it as a possible enum candidate.

Differential Revision: https://reviews.llvm.org/D123479

Fixes #54843
2022-04-11 14:06:48 -06:00
Richard 88a7508b1f [clang-tidy] Deal with keyword tokens in preprocessor conditions
When a "keyword" token like __restrict was present in a macro condition,
modernize-macro-to-enum would assert in non-release builds.  However,
even for a "keyword" token, calling getIdentifierInfo()->getName() would
retrieve the text of the token, which is what we want.  Our intention is
to scan names that appear in conditional expressions in potential enum
clusters and invalidate those clusters if they contain the name.

Also, guard against "raw identifiers" appearing as potential enums.
This shouldn't happen, but it doesn't hurt to generalize the code.

Differential Revision: https://reviews.llvm.org/D123349

Fixes #54775
2022-04-08 16:06:06 -06:00
Richard f547fc89c0 [clang-tidy] Add modernize-macro-to-enum check
[buildbot issues fixed]

This check performs basic analysis of macros and replaces them
with an anonymous unscoped enum.  Using an unscoped anonymous enum
ensures that everywhere the macro token was used previously, the
enumerator name may be safely used.

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.
- 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.
- Macros must not be defined adjacent to other preprocessor directives.
- Macros must not be used in preprocessor conditions

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.

The check cppcoreguidelines-macro-to-enum is an alias for this check.

Fixes #27408

Differential Revision: https://reviews.llvm.org/D117522
2022-04-01 15:24:21 -06:00
Douglas Yung cef52105bd Revert "[clang-tidy] Add modernize-macro-to-enum check"
This reverts commit 39b80c8380.

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
2022-03-25 11:53:42 -07:00
Richard 39b80c8380 [clang-tidy] Add modernize-macro-to-enum check
This check performs basic analysis of macros and replaces them
with an anonymous unscoped enum.  Using an unscoped anonymous enum
ensures that everywhere the macro token was used previously, the
enumerator name may be safely used.

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.
- 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.
- Macros must not be defined adjacent to other preprocessor directives.
- Macros must not be used in preprocessor conditions

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.

The check cppcoreguidelines-macro-to-enum is an alias for this check.

Fixes #27408

Differential Revision: https://reviews.llvm.org/D117522
2022-03-25 09:45:55 -06:00