This is an archive of the discontinued LLVM Phabricator instance.

[clang-tidy] Ignore macros defined within declarations in modernize-macro-to-enum
ClosedPublic

Authored by LegalizeAdulthood on Apr 19 2022, 10:39 PM.

Details

Summary

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.

Fixes #54883

Diff Detail

Event Timeline

Herald added a project: Restricted Project. · View Herald TranscriptApr 19 2022, 10:39 PM
LegalizeAdulthood requested review of this revision.Apr 19 2022, 10:39 PM

Add comments describing test cases

Delete debugging aids

This seems like a case where we might want a configuration option (maybe). Some of the test cases where you silence the diagnostic look like places I would expect us to be able to use a (local) enumeration. e.g.,

void g(int x)
{
  if (x != 0) {
#define INSIDE1 1
#define INSIDE2 2
// No reason the above can't be replaced with enum { INSIDE1 = 1, INSIDE2 = 2 };
    if (INSIDE1 > 1) {
      f();
    }
  } else {
    if (INSIDE2 == 1) {
      f();
    }
  }
}

struct S {
#define INSIDE5 5
#define INSIDE6 6
// The above could reasonably be: enum { INSIDE5 = 5, INSIDE6 = 6 }; especially in C++
  char storage[INSIDE5];
};

WDYT?

This seems like a case where we might want a configuration option (maybe). [...]
WDYT?

In my bug report on this problem, I sketch out a plan of attack:

  1. DON'T BREAK MY CODE -- that is this review :)
  2. Do some analysis of macro expansion locations to determine the nearest enclosing scope at which the enum should be declared.

https://github.com/llvm/llvm-project/issues/54883

Should probably split that bug report into 2 bugs for the two phases of attack.

The main problem with scenario 2) is the weird interaction between when PPCallbacks methods are invoked and AST traversal is invoked.

aaron.ballman accepted this revision.Apr 22 2022, 12:07 PM

This seems like a case where we might want a configuration option (maybe). [...]
WDYT?

In my bug report on this problem, I sketch out a plan of attack:

  1. DON'T BREAK MY CODE -- that is this review :)
  2. Do some analysis of macro expansion locations to determine the nearest enclosing scope at which the enum should be declared.

https://github.com/llvm/llvm-project/issues/54883

Ah, thank you for the explanation. I like not breaking code. :-) LGTM aside from a possible simplification for the matchers.

clang-tools-extra/clang-tidy/modernize/MacroToEnumCheck.cpp
561–567

Can we mix these together with anyOf() so we're not adding so many matchers? e.g.,

Finder->addMatcher(anyOf(varDecl(TopLevelDecl), functionDecl(topLevelDecl()), ...).bind("top"), this);
This revision is now accepted and ready to land.Apr 22 2022, 12:07 PM
LegalizeAdulthood marked an inline comment as done.Apr 22 2022, 2:15 PM
LegalizeAdulthood added inline comments.
clang-tools-extra/clang-tidy/modernize/MacroToEnumCheck.cpp
561–567

Oh, good idea, yep can do that.

LegalizeAdulthood marked an inline comment as done.Apr 22 2022, 3:04 PM
LegalizeAdulthood added inline comments.
clang-tools-extra/clang-tidy/modernize/MacroToEnumCheck.cpp
561–567

Can't actually do anyOf as it is a narrowing matcher, but I think I can collapse all of these to just matching on decl, so I'm trying that.

This revision was landed with ongoing or failed builds.Apr 22 2022, 4:47 PM
This revision was automatically updated to reflect the committed changes.

Update from review comments