This is an archive of the discontinued LLVM Phabricator instance.

clang-tidy: modernize-use-using uses AST and now supports struct defintions and multiple types in a typedef
ClosedPublic

Authored by poelmanc on Nov 14 2019, 1:14 PM.

Details

Summary

I'm a bit worried that this manual parsing technique will need fixing again in the future

That concern plus prior comments and help from clang -ast-dump led me to develop this new approach based entirely on the AST that completely eliminates manual parsing. It now handles typedefs that include comma-separated multiple types, and handles embedded struct definitions, which previously could not be automatically converted.

For example, with this patch modernize-use-using now can convert:

typedef struct { int a; } R_t, *R_p;

to:

using R_t = struct { int a; };
using R_p = R_t*;

-ast-dump showed that the CXXRecordDecl definitions and multiple TypedefDecls come consecutively in the tree, so check() stores information between calls to determine when it is receiving a second or additional TypedefDecl within a single typedef, or when the current TypedefDecl refers to an embedded CXXRecordDecl like a struct.

This patch fully replaces D67460 though it builds on its extended set of tests. All those tests pass, plus several that previously remained as typedef are now modernized to use using.

Diff Detail

Event Timeline

poelmanc created this revision.Nov 14 2019, 1:14 PM
Herald added a project: Restricted Project. · View Herald TranscriptNov 14 2019, 1:14 PM
mgehre removed a subscriber: mgehre.Nov 14 2019, 2:14 PM
aaron.ballman added inline comments.Nov 15 2019, 11:29 AM
clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp
30

It's unfortunate that we can't restrict this matcher more -- there tend to be a lot of struct declarations, so I am a bit worried about the performance of this matching on so many of them. At a minimum, I think you can restrict it to non-implicit structs here and simplify the code in check() a bit.

54–56

warn -> Warn
Add a full stop to the end of the comment.

56

Is there a purpose to the Diag local variable, or can it just be removed?

84

Should there be a newline here, to avoid putting all the using declarations on the same line?

poelmanc updated this revision to Diff 229678.Nov 15 2019, 8:32 PM
poelmanc edited the summary of this revision. (Show Details)
poelmanc marked 6 inline comments as done.Nov 15 2019, 8:41 PM
poelmanc added inline comments.
clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp
30

Done, thanks!

If there's a way to match only CXXRecordDecls that are immediately followed by a TypedefDecl, that would cut down the matches just to the ones we need. That said, at least the amount of work done on each check() call for the non-implicit CXXRecordDecls is minimal: it just stores its SourceRange and returns.

84

Done. Updated test cases and documentation to reflect this.

poelmanc marked 2 inline comments as done.Nov 15 2019, 8:44 PM

If there's a way to match only CXXRecordDecls that are immediately followed by a TypedefDecl...

Alternatively, within check() when we get the TypedefDecl, is there any way to navigate up the AST to find its immediately preceding sibling node in the AST and check whether it's a CXXRecordDecl? If so we could eliminate Finder->addMatcher(cxxRecordDecl(unless(isImplicit())).bind("struct"), this); altogether. I didn't see a way to do that though.

Any further feedback or thoughts on this?

poelmanc updated this revision to Diff 235039.Dec 21 2019, 11:25 PM
poelmanc added a subscriber: sammccall.

Update patch to rebase on latest: Changed SourceLocation::contains to SourceLocation::fullyContains, and removed new SourceLocation comparison operators since coincidentally @sammccall added them just days ago.

This revision is now accepted and ready to land.Dec 24 2019, 8:14 AM
This revision was automatically updated to reflect the committed changes.