This is an archive of the discontinued LLVM Phabricator instance.

[clang-tidy] Add a checker for converting into C++17 variable template type traits
AbandonedPublic

Authored by royjacobson on Oct 6 2022, 2:22 PM.

Details

Summary

This adds a clang-tidy checker that can transform C++11-style type traits into C++17-style
variable templates. Variable templates can compile faster because they can be implemented
without instantiating classes.

I'm not very familiar with clang matchers; There's probably a better way to do what I
want than regex + hacky type checking, so suggestions are very welcome.

Diff Detail

Event Timeline

royjacobson created this revision.Oct 6 2022, 2:22 PM
Herald added a project: Restricted Project. · View Herald TranscriptOct 6 2022, 2:22 PM
royjacobson requested review of this revision.Oct 6 2022, 2:22 PM
Herald added a project: Restricted Project. · View Herald TranscriptOct 6 2022, 2:22 PM
Herald added a subscriber: cfe-commits. · View Herald Transcript

Why limit this to just the value type traits, makes sense to also support type type traits.

clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp
73

Won't this assert if a pointer is supplied but it isn't a ClassTemplateSpecializationDefl. Wouldn't dyn_cast be needed.
In any case a test where you access a static variable from a non template class needs adding to make sure no warning is emitter.

82

Make the diagnostic a bit clearer.

86

This fixit logic looks cumbersome, just replace the qualifier loc(::)to the declared with an _v. But only iff the qualified name loc is not a macro.

clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.h
34

We don't need an ordering here, so an llvm::DenseSet<StringRef> may be more suited here.

clang-tools-extra/docs/clang-tidy/checks/modernize/type-traits.rst
28

I'm not sure this option would ever be used in the wild as it would override all the default values in the stl.

royjacobson marked 2 inline comments as done.Oct 8 2022, 7:06 AM

Why limit this to just the value type traits, makes sense to also support type type traits.

I'd love to, but I can't match against the ::type usages with DeclRefExpr. I think I'd have to match all types in the program or something like that, but I'm not sure if even that's enough because of unevaluated contexts etc... So I decided to focus on this first.

clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp
73

Definitely need a dyn_cast here, thanks!

86

I think to do that I have to get the location of the template-id of the qualifier from the ClassTemplateSpecializationDecl, but I haven't really managed to do that. Or is there maybe a way to get the lexer tokens list of a source range or something like that?

clang-tools-extra/docs/clang-tidy/checks/modernize/type-traits.rst
28

The intended use case is one-time running of this check over a code base to modernize it, and you want to add your own type traits that you define across your own libraries. I think that's useful, at least.

Maybe this should just _add_ traits, and not replace them? Is this something that clang-tidy does? I basically copied this from the modernize-use-emplace check.

Addrees CR comments

friendly ping @njames93
FWIW I ran this over the LLVM codebase and have seen no crashes or false positives.

I'd also suggest using the IgnoreUnlessSpelledInSource traversal kind here. Given that most of the time these will be instantiated we don't want to warn and emit a fix for each instantiation, Or you could just add unless(isInTemplateInstantiation()) to your matcher.

clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp
86

Take a look here https://godbolt.org/z/Wj5bjbqGh
You'd want to create an insertion of _v at the start of the <
getQualifierLoc().getTypeLoc().getAs<clang::TemplateSpecializationTypeLoc>().getLAngleLoc()
Then a removal from the start of the :: until the end of the whole expr
{getQualifierLoc().getEndLoc(), getEndLoc()}

clang-tools-extra/docs/clang-tidy/checks/modernize/type-traits.rst
34

Newline

royjacobson marked 4 inline comments as done.

Address comments.

I'd also suggest using the IgnoreUnlessSpelledInSource traversal kind here. Given that most of the time these will be instantiated we don't want to warn and emit a fix for each instantiation, Or you could just add unless(isInTemplateInstantiation()) to your matcher.

I'm not sure what to do here... Until this is instantiated, I have only a DependentScopeDeclRefExpr that is not resolved yet. And it's important to have this check for dependent contexts because that's how it's usually used.

clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp
86

That's great debugging tool, thanks! :)

royjacobson abandoned this revision.Nov 3 2022, 3:15 AM

Closing in favor of the much more mature D137302.