LLVM Bugzilla is read-only and represents the historical archive of all LLVM issues filled before November 26, 2021. Use github to submit LLVM bugs

Bug 50715 - Undefined uses of std::is_invocable in <concepts> and <ranges> tests
Summary: Undefined uses of std::is_invocable in <concepts> and <ranges> tests
Status: NEW
Alias: None
Product: libc++
Classification: Unclassified
Component: All Bugs (show other bugs)
Version: 12.0
Hardware: All All
: P normal
Assignee: Unassigned Clang Bugs
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2021-06-15 04:43 PDT by Jonathan Wakely
Modified: 2021-06-15 04:43 PDT (History)
2 users (show)

See Also:
Fixed By Commit(s):


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jonathan Wakely 2021-06-15 04:43:14 PDT
The tests for the std::invocable concept use std::is_invocable with an argument of incomplete type, which is undefined (it violates the precondition for std::is_invocable):

In file included from /home/jwakely/gcc/12/include/c++/12.0.0/ratio:39,
                 from /home/jwakely/gcc/12/include/c++/12.0.0/chrono:39,
                 from std/concepts/concepts.callable/concept.invocable/invocable.compile.pass.cpp:15:
/home/jwakely/gcc/12/include/c++/12.0.0/type_traits: In instantiation of 'struct std::is_invocable<int S::*, S>':
/home/jwakely/gcc/12/include/c++/12.0.0/type_traits:3001:73:   required from 'constexpr const bool std::is_invocable_v<int S::*, S>'
/home/jwakely/gcc/12/include/c++/12.0.0/concepts:338:25:   required from 'constexpr bool pointer_to_member_functions::check_member_is_invocable() [with Member = int S::*; T = S; Args = {}]'
std/concepts/concepts.callable/concept.invocable/invocable.compile.pass.cpp:259:53:   required from here
/home/jwakely/gcc/12/include/c++/12.0.0/type_traits:2942:7: error: static assertion failed: each argument type must be a complete class or an unbounded array

Similarly for std::regular_invocable:

In file included from /home/jwakely/gcc/12/include/c++/12.0.0/ratio:39,
                 from /home/jwakely/gcc/12/include/c++/12.0.0/chrono:39,
                 from std/concepts/concepts.callable/concept.regularinvocable/regular_invocable.compile.pass.cpp:15:
/home/jwakely/gcc/12/include/c++/12.0.0/type_traits: In instantiation of 'struct std::is_invocable<int S::*, S>':
/home/jwakely/gcc/12/include/c++/12.0.0/type_traits:3001:73:   required from 'constexpr const bool std::is_invocable_v<int S::*, S>'
/home/jwakely/gcc/12/include/c++/12.0.0/concepts:338:25:   required from 'constexpr bool pointer_to_member_functions::check_member_is_invocable() [with Member = int S::*; T = S; Args = {}]'
std/concepts/concepts.callable/concept.regularinvocable/regular_invocable.compile.pass.cpp:285:53:   required from here
/home/jwakely/gcc/12/include/c++/12.0.0/type_traits:2942:7: error: static assertion failed: each argument type must be a complete class or an unbounded array



The tests for std::ranges::data use std::is_invocable_v to check that an array of incomplete type can't be used, but that's undefined as stated above:

In file included from /home/jwakely/gcc/12/include/c++/12.0.0/concepts:44,
                 from /home/jwakely/gcc/12/include/c++/12.0.0/ranges:37,
                 from std/ranges/range.access/range.prim/data.pass.cpp:15:
/home/jwakely/gcc/12/include/c++/12.0.0/type_traits: In instantiation of 'struct std::is_invocable<const std::ranges::__cust_access::_Data, Incomplete [2]>':
/home/jwakely/gcc/12/include/c++/12.0.0/type_traits:3001:73:   required from 'constexpr const bool std::is_invocable_v<const std::ranges::__cust_access::_Data, Incomplete [2]>'
std/ranges/range.access/range.prim/data.pass.cpp:28:21:   required from here
/home/jwakely/gcc/12/include/c++/12.0.0/type_traits:2942:7: error: static assertion failed: each argument type must be a complete class or an unbounded array

Shouldn't those first three static assertions in std/ranges/range.access/range.prim/data.pass.cpp be using a reference to an array anyway? An array rvalue is not a borrowed_range, so it's ill-formed. If they are supposed to be testing the array of incomplete type condition, they aren't doing that, they're testing the "lvalue or borrowed range" condition.

Also, that test is not portable (should it be guarded by a preprocessor check?) because the standard doesn't require a diagnostic for trying to use ranges::data on an array of incomplete type. With libstdc++ you do get an error, but not in the immediate context (so it's not SFINAE-friendly and you can't check for it with is_invocable).