This is an archive of the discontinued LLVM Phabricator instance.

[clang] Enable the special enable_if_t diagnostics for libc++'s __enable_if_t as well.
ClosedPublic

Authored by Quuxplusone on Sep 7 2021, 7:16 PM.

Details

Summary

This comes from lengthy discussion between @Quuxplusone and @ldionne over on D108216.
Right now, libc++ uses a "SCARY metaprogramming" version of _EnableIf that bypasses all of Clang's clever diagnostic stuff and produces bad diagnostics. My recent benchmarks ( https://quuxplusone.github.io/blog/2021/09/04/enable-if-benchmark/ ) have determined that the SCARYness is not buying us any speedup; therefore we are happy to drop it and go back to using the standard std::enable_if for all our SFINAE needs. However, we don't want to type out typename std::enable_if<X>::type all over the library; we want to use an alias template. And we can't use std::enable_if_t because we need a solution that works in C++11, and we do not provide std::enable_if_t in C++11.

Therefore, D109435 switches us from SCARY _EnableIf to a normal __enable_if_t (at least in C++11 mode, and possibly everywhere for consistency). Simultaneously, this Clang patch enables the good diagnostics for __enable_if_t. We don't need to enable good diagnostics for _EnableIf because the name _EnableIf has only ever been used for the SCARY version where the good diagnostics don't trigger anyway.

(Btw, this existing code is all sorts of broken, theoretically speaking. I filed https://bugs.llvm.org/show_bug.cgi?id=51696 about it last week. So if someone wants to use this PR as an excuse to go down the rabbit hole and fix it for real, that would be cool too.)

Diff Detail

Event Timeline

Quuxplusone requested review of this revision.Sep 7 2021, 7:16 PM
Quuxplusone created this revision.

Would at. least need a test case, but otherwise sounds OK to make things a bit better.

This shouldn't be necessary anymore since we won't be using _EnableIf in libc++ going forward.

Actually, scratch that, we could tweak this patch so it accepts __enable_if_t as well (that will be the new spelling for enable_if_t for pre-C++14 places going forward.

Quuxplusone retitled this revision from [clang] Enable the special enable_if_t diagnostics for libc++'s _EnableIf as well. to [clang] Enable the special enable_if_t diagnostics for libc++'s __enable_if_t as well..
Quuxplusone edited the summary of this revision. (Show Details)

Okay, I think I've got it all sorted out in my head. This path forward seems reasonable to me:

D109435 switches us from SCARY _EnableIf to a normal __enable_if_t (at least in C++11 mode, and possibly everywhere for consistency). Simultaneously, this Clang patch enables the good diagnostics for __enable_if_t. We don't need to enable good diagnostics for _EnableIf because the name _EnableIf has only ever been used for the SCARY version where the good diagnostics don't trigger anyway.

Added a test case.

ldionne accepted this revision.Sep 8 2021, 12:19 PM

This seems reasonable to me.

clang/lib/Sema/SemaTemplate.cpp
3514

Nit: libc++ >= 14

This revision is now accepted and ready to land.Sep 8 2021, 12:19 PM

Looks like most of the testing for the enable_if custom dialog was added in clang/test/SemaTemplate/overload-candidates.cpp in rG6f8d2c6c9c3451effdf075a7034bbe77045bfeba. (improved in rG00fa10b43f25d98e88cc81b653dfe8d49327722d - though no substantially novel test coverage added, just updating the improved diagnostic text) - maybe pull that test coverage over into this new dedicated test file? But no big deal.

Looks like most of the testing for the enable_if custom dialog was added in clang/test/SemaTemplate/overload-candidates.cpp in rG6f8d2c6c9c3451effdf075a7034bbe77045bfeba. (improved in rG00fa10b43f25d98e88cc81b653dfe8d49327722d - though no substantially novel test coverage added, just updating the improved diagnostic text) - maybe pull that test coverage over into this new dedicated test file? But no big deal.

Yeah, I noticed those changed-but-not-really-added tests over there. I did deliberately make a new file because I wanted it to explicitly test alias templates like enable_if_t, whereas overload-candidates.cpp runs in C++98 and thus cannot contain alias templates. I don't know if the existing tests are adding super much value, but I don't think it would add any more value to pull them over into this new file (in fact we'd have to stop running them in C++98 mode), and I'm not confident enough that they add zero value to go entirely remove them. So, status quo is I just left them alone.

Anyone particularly want to jump in here? because otherwise I think I'll land this tomorrow-ish.