[libc++] Tidy up tests for deduction guides and other compile-time failing properties in std::string

Instead of using `.fail.cpp` tests, use `.verify.cpp` to check for the
exact reason of the failure. In the case of deduction guides, use SFINAE
based tests instead since that is our preferred way of testing those.

Finally, ensure that we actually run the test in `iter_alloc_deduction.pass.cpp`,
since we were not running anything before.

Differential Revision: https://reviews.llvm.org/D123055
This commit is contained in:
Louis Dionne 2022-04-04 13:35:41 -04:00
parent 516333d632
commit 8ec4999766
12 changed files with 112 additions and 250 deletions

View File

@ -11,9 +11,4 @@
#include <string>
int main(int, char**)
{
std::basic_string<char, std::char_traits<char>, std::allocator<int> > s;
return 0;
}
std::basic_string<char, std::char_traits<char>, std::allocator<int> > s; // expected-error@*:* {{Allocator::value_type must be same type as value_type}}

View File

@ -1,54 +0,0 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
// <string>
// ... manipulating sequences of any non-array trivial standard-layout types.
#include <string>
#include "test_traits.h"
struct NotTrivial {
NotTrivial() : value(3) {}
int value;
};
struct NotStandardLayout {
public:
NotStandardLayout() : one(1), two(2) {}
int sum() const { return one + two; } // silences "unused field 'two' warning"
int one;
private:
int two;
};
int main(int, char**)
{
{
// array
typedef char C[3];
static_assert(std::is_array<C>::value, "");
std::basic_string<C, test_traits<C> > s;
// expected-error-re@string:* {{static_assert failed{{.*}} "Character type of basic_string must not be an array"}}
}
{
// not trivial
static_assert(!std::is_trivial<NotTrivial>::value, "");
std::basic_string<NotTrivial, test_traits<NotTrivial> > s;
// expected-error-re@string:* {{static_assert failed{{.*}} "Character type of basic_string must be trivial"}}
}
{
// not standard layout
static_assert(!std::is_standard_layout<NotStandardLayout>::value, "");
std::basic_string<NotStandardLayout, test_traits<NotStandardLayout> > s;
// expected-error-re@string:* {{static_assert failed{{.*}} "Character type of basic_string must be standard-layout"}}
}
return 0;
}

View File

@ -0,0 +1,51 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
// <string>
// ... manipulating sequences of any non-array trivial standard-layout types.
#include <string>
#include "test_traits.h"
struct NotTrivial {
NotTrivial() : value(3) {}
int value;
};
struct NotStandardLayout {
public:
NotStandardLayout() : one(1), two(2) {}
int sum() const { return one + two; } // silences "unused field 'two' warning"
int one;
private:
int two;
};
void f() {
{
// array
typedef char C[3];
static_assert(std::is_array<C>::value, "");
std::basic_string<C, test_traits<C> > s;
// expected-error-re@string:* {{static_assert failed{{.*}} "Character type of basic_string must not be an array"}}
}
{
// not trivial
static_assert(!std::is_trivial<NotTrivial>::value, "");
std::basic_string<NotTrivial, test_traits<NotTrivial> > s;
// expected-error-re@string:* {{static_assert failed{{.*}} "Character type of basic_string must be trivial"}}
}
{
// not standard layout
static_assert(!std::is_standard_layout<NotStandardLayout>::value, "");
std::basic_string<NotStandardLayout, test_traits<NotStandardLayout> > s;
// expected-error-re@string:* {{static_assert failed{{.*}} "Character type of basic_string must be standard-layout"}}
}
}

View File

@ -1,55 +0,0 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
// <string>
// UNSUPPORTED: c++03, c++11, c++14
// template<class InputIterator,
// class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
// basic_string(InputIterator, InputIterator, Allocator = Allocator())
// -> basic_string<typename iterator_traits<InputIterator>::value_type,
// char_traits<typename iterator_traits<InputIterator>::value_type>,
// Allocator>;
//
// The deduction guide shall not participate in overload resolution if InputIterator
// is a type that does not qualify as an input iterator, or if Allocator is a type
// that does not qualify as an allocator.
#include <string>
#include <iterator>
#include <cassert>
#include <cstddef>
#include "test_macros.h"
class NotAnIterator {};
template <typename T>
struct NotAnAllocator { typedef T value_type; };
int main(int, char**)
{
{ // Not an iterator at all
std::basic_string s1{NotAnIterator{}, NotAnIterator{}, std::allocator<char>{}}; // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'basic_string'}}
}
{ // Not an input iterator
std::basic_string<char16_t> s0;
std::basic_string s1{std::back_insert_iterator(s0), // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'basic_string'}}
std::back_insert_iterator(s0),
std::allocator<char16_t>{}};
}
{ // Not an allocator
const wchar_t* s = L"12345678901234";
(void)s;
std::basic_string s1{s, s+10, NotAnAllocator<wchar_t>{}}; // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'basic_string'}}
}
return 0;
}

View File

@ -9,10 +9,6 @@
// <string>
// UNSUPPORTED: c++03, c++11, c++14
// template<class InputIterator>
// basic_string(InputIterator begin, InputIterator end,
// const Allocator& a = Allocator());
// template<class InputIterator,
// class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
// basic_string(InputIterator, InputIterator, Allocator = Allocator())
@ -24,15 +20,35 @@
// is a type that does not qualify as an input iterator, or if Allocator is a type
// that does not qualify as an allocator.
#include <string>
#include <iterator>
#include <cassert>
#include <cstddef>
#include <iterator>
#include <string>
#include <type_traits>
#include "test_macros.h"
#include "test_allocator.h"
#include "min_allocator.h"
class NotAnIterator {};
using NotAnInputIterator = std::back_insert_iterator<std::basic_string<char16_t>>;
template <typename T>
struct NotAnAllocator { typedef T value_type; };
template <class Iter, class Alloc, class = void>
struct CanDeduce : std::false_type { };
template <class Iter, class Alloc>
struct CanDeduce<Iter, Alloc, decltype((void)
std::basic_string{std::declval<Iter>(), std::declval<Iter>(), std::declval<Alloc>()}
)> : std::true_type { };
static_assert( CanDeduce<int*, std::allocator<int>>::value);
static_assert(!CanDeduce<NotAnIterator, std::allocator<char>>::value);
static_assert(!CanDeduce<NotAnInputIterator, std::allocator<char16_t>>::value);
static_assert(!CanDeduce<wchar_t const*, NotAnAllocator<wchar_t>>::value);
bool test() {
{
const char* s = "12345678901234";
@ -90,6 +106,10 @@ bool test() {
int main(int, char**)
{
test();
#if TEST_STD_VER > 17
// static_assert(test());
#endif
return 0;
}

View File

@ -1,24 +0,0 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
// <string>
// explicit basic_string(basic_string_view<CharT, traits> sv, const Allocator& a = Allocator());
#include <string>
#include <string_view>
void foo ( const string &s ) {}
int main(int, char**)
{
std::string_view sv = "ABCDE";
foo(sv); // requires implicit conversion from string_view to string
return 0;
}

View File

@ -10,15 +10,19 @@
// explicit basic_string(basic_string_view<CharT, traits> sv, const Allocator& a = Allocator());
#include <string>
#include <string_view>
#include <stdexcept>
#include <algorithm>
#include <cassert>
#include <stdexcept>
#include <string_view>
#include <string>
#include <type_traits>
#include "test_macros.h"
#include "test_allocator.h"
#include "min_allocator.h"
#include "test_allocator.h"
#include "test_macros.h"
static_assert(!std::is_convertible<std::string_view, std::string const&>::value, "");
static_assert(!std::is_convertible<std::string_view, std::string>::value, "");
template <class charT>
TEST_CONSTEXPR_CXX20 void

View File

@ -1,40 +0,0 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
// <string>
// UNSUPPORTED: c++03, c++11, c++14
// template<class InputIterator>
// basic_string(InputIterator begin, InputIterator end,
// const Allocator& a = Allocator());
// template<class charT,
// class traits,
// class Allocator = allocator<charT>
// >
// basic_string(basic_string_view<charT, traits>, const Allocator& = Allocator())
// -> basic_string<charT, traits, Allocator>;
//
// The deduction guide shall not participate in overload resolution if Allocator
// is a type that does not qualify as an allocator.
#include <string>
#include <string_view>
#include <iterator>
#include <cassert>
#include <cstddef>
int main(int, char**)
{
{
std::string_view sv = "12345678901234";
std::basic_string s1{sv, 23}; // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'basic_string'}}
}
return 0;
}

View File

@ -9,10 +9,6 @@
// <string>
// UNSUPPORTED: c++03, c++11, c++14
// template<class InputIterator>
// basic_string(InputIterator begin, InputIterator end,
// const Allocator& a = Allocator());
// template<class charT,
// class traits,
// class Allocator = allocator<charT>
@ -35,6 +31,18 @@
#include "test_allocator.h"
#include "min_allocator.h"
template <class StringView, class Allocator, class = void>
struct CanDeduce : std::false_type { };
template <class StringView, class Allocator>
struct CanDeduce<StringView, Allocator, decltype((void)
std::basic_string{std::declval<StringView>(), std::declval<Allocator>()}
)> : std::true_type { };
struct NotAnAllocator { };
static_assert( CanDeduce<std::string_view, std::allocator<char>>::value);
static_assert(!CanDeduce<std::string_view, NotAnAllocator>::value);
bool test() {
{
std::string_view sv = "12345678901234";

View File

@ -1,46 +0,0 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
// <string>
// UNSUPPORTED: c++03, c++11, c++14
// template<class InputIterator>
// basic_string(InputIterator begin, InputIterator end,
// const Allocator& a = Allocator());
// template<class charT,
// class traits,
// class Allocator = allocator<charT>
// >
// basic_string(basic_string_view<charT, traits>,
// typename see below::size_type,
// typename see below::size_type,
// const Allocator& = Allocator())
// -> basic_string<charT, traits, Allocator>;
//
// A size_type parameter type in a basic_string deduction guide refers to the size_type
// member type of the type deduced by the deduction guide.
//
// The deduction guide shall not participate in overload resolution if Allocator
// is a type that does not qualify as an allocator.
#include <string>
#include <string_view>
#include <iterator>
#include <cassert>
#include <cstddef>
int main(int, char**)
{
{
std::string_view sv = "12345678901234";
std::basic_string s1{sv, 0, 4, 23}; // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'basic_string'}}
}
return 0;
}

View File

@ -9,10 +9,6 @@
// <string>
// UNSUPPORTED: c++03, c++11, c++14
// template<class InputIterator>
// basic_string(InputIterator begin, InputIterator end,
// const Allocator& a = Allocator());
// template<class charT,
// class traits,
// class Allocator = allocator<charT>
@ -39,6 +35,18 @@
#include "test_allocator.h"
#include "min_allocator.h"
template <class StringView, class Size, class Allocator, class = void>
struct CanDeduce : std::false_type { };
template <class StringView, class Size, class Allocator>
struct CanDeduce<StringView, Size, Allocator, decltype((void)
std::basic_string{std::declval<StringView>(), std::declval<Size>(), std::declval<Size>(), std::declval<Allocator>()}
)> : std::true_type { };
struct NotAnAllocator { };
static_assert( CanDeduce<std::string_view, std::size_t, std::allocator<char>>::value);
static_assert(!CanDeduce<std::string_view, std::size_t, NotAnAllocator>::value);
bool test() {
{
std::string_view sv = "12345678901234";

View File

@ -11,9 +11,4 @@
#include <string>
int main(int, char**)
{
std::basic_string<char, std::char_traits<wchar_t>> s;
return 0;
}
std::basic_string<char, std::char_traits<wchar_t> > s; // expected-error@*:* {{traits_type::char_type must be the same type as CharT}}