diff --git a/libcxx/include/__iterator/concepts.h b/libcxx/include/__iterator/concepts.h --- a/libcxx/include/__iterator/concepts.h +++ b/libcxx/include/__iterator/concepts.h @@ -171,7 +171,6 @@ derived_from<_ITER_CONCEPT<_Ip>, contiguous_iterator_tag> && is_lvalue_reference_v> && same_as, remove_cvref_t>> && - (is_pointer_v<_Ip> || requires { sizeof(__pointer_traits_element_type<_Ip>); }) && requires(const _Ip& __i) { { _VSTD::to_address(__i) } -> same_as>>; }; diff --git a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.random.access/contiguous_iterator.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.random.access/contiguous_iterator.compile.pass.cpp --- a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.random.access/contiguous_iterator.compile.pass.cpp +++ b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.random.access/contiguous_iterator.compile.pass.cpp @@ -101,9 +101,10 @@ struct wrong_iter_reference_t { typedef std::contiguous_iterator_tag iterator_category; typedef short value_type; + typedef short element_type; typedef std::ptrdiff_t difference_type; - typedef int* pointer; - typedef short& reference; + typedef short* pointer; + typedef int& reference; typedef wrong_iter_reference_t self; wrong_iter_reference_t(); @@ -132,40 +133,6 @@ static_assert(std::random_access_iterator); static_assert(!std::contiguous_iterator); -struct no_element_type { - typedef std::contiguous_iterator_tag iterator_category; - typedef int value_type; - typedef std::ptrdiff_t difference_type; - typedef int* pointer; - typedef int& reference; - typedef no_element_type self; - - no_element_type(); - - reference operator*() const; - pointer operator->() const; - auto operator<=>(const self&) const = default; - - self& operator++(); - self operator++(int); - - self& operator--(); - self operator--(int); - - self& operator+=(difference_type n); - self operator+(difference_type n) const; - friend self operator+(difference_type n, self x); - - self& operator-=(difference_type n); - self operator-(difference_type n) const; - difference_type operator-(const self& n) const; - - reference operator[](difference_type n) const; -}; - -static_assert(std::random_access_iterator); -static_assert(!std::contiguous_iterator); - struct to_address_wrong_return_type { typedef std::contiguous_iterator_tag iterator_category; typedef int value_type; diff --git a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.random.access/contiguous_iterator.verify.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.random.access/contiguous_iterator.verify.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.random.access/contiguous_iterator.verify.cpp @@ -0,0 +1,59 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts + +// template +// concept contiguous_iterator; + +#include +#include +#include +#include + +// Expect failures with a type missing an `element_type` type alias + +struct no_element_type { + typedef std::contiguous_iterator_tag iterator_category; + typedef int value_type; + typedef std::ptrdiff_t difference_type; + typedef int* pointer; + typedef int& reference; + typedef no_element_type self; + + no_element_type(); + + reference operator*() const; + pointer operator->() const; + auto operator<=>(const self&) const = default; + + self& operator++(); + self operator++(int); + + self& operator--(); + self operator--(int); + + self& operator+=(difference_type n); + self operator+(difference_type n) const; + friend self operator+(difference_type n, self x); + + self& operator-=(difference_type n); + self operator-(difference_type n) const; + difference_type operator-(const self& n) const; + + reference operator[](difference_type n) const; +}; + +void test() { + // In checking constraints in `std::contiguous_iterator`, the call to + // std::to_address` is not SFINAE-friendly, resulting in a hard error + // when used with a type missing an `element_type` type alias. + (void) std::contiguous_iterator; // expected-note@__iterator/concepts.h:* {{to_address}} + // expected-error@*:* {{implicit instantiation of undefined template}} +}