[llvm-bugs] [Bug 51696] New: enable_if "requirement not satisfied" diagnostics could be more robust and general

via llvm-bugs llvm-bugs at lists.llvm.org
Tue Aug 31 19:40:31 PDT 2021


https://bugs.llvm.org/show_bug.cgi?id=51696

            Bug ID: 51696
           Summary: enable_if "requirement not satisfied" diagnostics
                    could be more robust and general
           Product: clang
           Version: trunk
          Hardware: PC
                OS: All
            Status: NEW
          Severity: enhancement
          Priority: P
         Component: -New Bugs
          Assignee: unassignedclangbugs at nondot.org
          Reporter: arthur.j.odwyer at gmail.com
                CC: htmldeveloper at gmail.com, llvm-bugs at lists.llvm.org,
                    neeilans at live.com, richard-llvm at metafoo.co.uk

// https://godbolt.org/z/E5d63q77E

cat >test.cpp <<EOF
template<bool B, class T = void> struct enable_if { using type = T; };
template<class T> struct enable_if<false, T> {};

// LIES AND DECEPTION
template<bool Dummy, bool B> using enable_if_t = typename enable_if<B>::type;

template<class T> auto f() -> enable_if_t<true, sizeof(T) != 1> {}

void test() {
    f<char>();
}
EOF
clang++ -c test.cpp

test.cpp:10:5: error: no matching function for call to 'f'
    f<char>();
    ^~~~~~~
test.cpp:7:24: note: candidate template ignored: requirement 'true' was not
satisfied [with T = char]
template<class T> auto f() -> enable_if_t<true, sizeof(T) != 1> {}
                       ^


The problem is that the diagnostic is looking for the specific names
`enable_if` and `enable_if_t`, and then *assuming* that if the templates have
those names (regardless of namespace), their parameters must follow the
expected pattern.

It would be nicer if Clang could follow the outline I sketched in
https://reviews.llvm.org/D108216 :

> Well, remember that our _EnableIf has a different shape from the standard
> enable_if_t. Ours is _MetaBase<B>::_EnableIfImpl<R>, whereas enable_if_t
> is enable_if<B, R>::type. So I think the criterion would be something
> like "We failed to find a member in a class template of the form
> template<[...], bool, [...]>, where that bool parameter is false,
> and where, if the bool parameter had been true, we would have found
> such a member." If that's too backtracky (Clang sucks at
> backtracking/hypotheticals), we could say "We failed to find a member
> in a class template of the form template<[...], bool, [...]>,
> where that bool parameter is false, and where the class template
> has at least one partial or explicit specialization." I would not
> look at the name of the member, nor the name of the class, nor
> the reason-we're-looking-for-that-member (e.g. the name of the
> alias template).

If Clang could do this, then not only would it not get tricked by stupid
contrived examples like mine above, but also it would be able to detect
"requirements" even when they were implemented in SCARY-template ways such as
the above-mentioned _MetaBase<B>::_EnableIfImpl<R>. As long as there's *a* bool
argument, that is false, and where if it were true we would have found a
member, that should be good enough to trigger Clang's special-case diagnostics
about "requirement was not satisfied".

Even though this bug report is phrased in terms of a "bad diagnostic on
contrived input," *really* what I'm hoping to get out of it is "good
diagnostics on realistic input" (and specifically, on libc++'s _EnableIf). My
contrived example merely demonstrates that the existing code in Clang cannot be
defended on the grounds of "being safely conservative," in case anyone was
going to try that.

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20210901/9bce7dce/attachment.html>


More information about the llvm-bugs mailing list