| 1 | //===----------------------------------------------------------------------===// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | |
| 9 | // UNSUPPORTED: c++03, c++11, c++14, c++17 |
| 10 | |
| 11 | // <utility> |
| 12 | |
| 13 | // LWG-3382 NTTP for pair and array: |
| 14 | // pair<T, U> is a structural type ([temp.param]) if T and U are both structural types. |
| 15 | |
| 16 | // This deprecated ABI switch makes pair a non-structural type. |
| 17 | // XFAIL: libcpp-deprecated-abi-disable-pair-trivial-copy-ctor |
| 18 | |
| 19 | #include <utility> |
| 20 | |
| 21 | #include <functional> |
| 22 | #include <string> |
| 23 | |
| 24 | struct LiteralBase {}; |
| 25 | struct LiteralNSDM {}; |
| 26 | |
| 27 | struct LiteralType : LiteralBase { |
| 28 | LiteralNSDM nsdm; |
| 29 | }; |
| 30 | |
| 31 | struct NotALiteral { |
| 32 | NotALiteral() {} |
| 33 | }; |
| 34 | |
| 35 | int i; |
| 36 | NotALiteral not_a_literal; |
| 37 | |
| 38 | namespace test_full_type { |
| 39 | template <class T, class U, std::pair<T, U> P> |
| 40 | struct test {}; |
| 41 | |
| 42 | using A = test<int, int, std::pair{0, 1}>; |
| 43 | using B = test<int&, int&, std::make_pair(std::ref(i), std::ref(i))>; |
| 44 | using C = test<const int&, const int&, std::make_pair(std::cref(i), std::cref(i))>; |
| 45 | using D = test<LiteralType, LiteralType, std::pair<LiteralType, LiteralType>{}>; |
| 46 | using E = test<int*, int*, std::pair<int*, int*>{&i, &i}>; |
| 47 | using F = test<NotALiteral&, NotALiteral&, std::make_pair(std::ref(not_a_literal), std::ref(not_a_literal))>; |
| 48 | |
| 49 | using G = test<int&&, int&&, std::pair<int&&, int&&>{std::move(i), std::move(i)}>; |
| 50 | // expected-error@*:* {{type 'std::pair<int &&, int &&>' of non-type template parameter is not a structural type}} |
| 51 | |
| 52 | using H = test<NotALiteral, NotALiteral, std::pair<NotALiteral, NotALiteral>{}>; |
| 53 | // expected-error@*:* {{non-type template parameter has non-literal type 'std::pair<NotALiteral, NotALiteral>'}} |
| 54 | |
| 55 | using I = test<std::string, std::string, std::pair<std::string, std::string>{}>; |
| 56 | // expected-error-re@*:* {{type 'std::pair<{{(std::)?}}string, {{(std::)?}}string>' {{(\(aka 'pair<basic_string<char>, basic_string<char>>'\) )?}}of non-type template parameter is not a structural type}} |
| 57 | } // namespace test_full_type |
| 58 | |
| 59 | namespace test_ctad { |
| 60 | template <std::pair P> |
| 61 | struct test {}; |
| 62 | |
| 63 | using A = test<std::pair{2, 3}>; |
| 64 | using B = test<std::make_pair(std::ref(i), std::ref(i))>; |
| 65 | using C = test<std::make_pair(std::cref(i), std::cref(i))>; |
| 66 | using D = test<std::pair<LiteralType, LiteralType>{}>; |
| 67 | using E = test<std::pair<int*, int*>{&i, &i}>; |
| 68 | using F = test<std::make_pair(std::ref(not_a_literal), std::ref(not_a_literal))>; |
| 69 | |
| 70 | using G = test<std::pair<int&&, int&&>{std::move(i), std::move(i)}>; |
| 71 | // expected-error@-1 {{type 'std::pair<int &&, int &&>' of non-type template parameter is not a structural type}} |
| 72 | |
| 73 | using H = test<std::pair<NotALiteral, NotALiteral>{}>; |
| 74 | // expected-error@-1 {{non-type template parameter has non-literal type 'std::pair<NotALiteral, NotALiteral>'}} |
| 75 | |
| 76 | using I = test<std::pair<std::string, std::string>{}>; |
| 77 | // expected-error-re@-1 {{type 'std::pair<{{(std::)?}}string, {{(std::)?}}string>'{{( \(aka 'std::pair<std::string, std::string>'\))?}} of non-type template parameter is not a structural type}} |
| 78 | } // namespace test_ctad |
| 79 | |
| 80 | namespace test_auto { |
| 81 | template <auto P> |
| 82 | struct test {}; |
| 83 | |
| 84 | using A = test<std::pair{4, 5}>; |
| 85 | using B = test<std::make_pair(std::ref(i), std::ref(i))>; |
| 86 | using C = test<std::make_pair(std::cref(i), std::cref(i))>; |
| 87 | using D = test<std::pair<LiteralType, LiteralType>{}>; |
| 88 | using E = test<std::pair<int*, int*>{&i, &i}>; |
| 89 | using F = test<std::make_pair(std::ref(not_a_literal), std::ref(not_a_literal))>; |
| 90 | |
| 91 | using G = test<std::pair<int&&, int&&>{std::move(i), std::move(i)}>; |
| 92 | // expected-error@-1 {{type 'std::pair<int &&, int &&>' of non-type template parameter is not a structural type}} |
| 93 | |
| 94 | using H = test<std::pair<NotALiteral, NotALiteral>{}>; |
| 95 | // expected-error@-1 {{non-type template parameter has non-literal type 'std::pair<NotALiteral, NotALiteral>'}} |
| 96 | |
| 97 | using I = test<std::pair<std::string, std::string>{}>; |
| 98 | // expected-error@-1 {{type 'std::pair<std::string, std::string>' (aka 'pair<basic_string<char>, basic_string<char>>') of non-type template parameter is not a structural type}} |
| 99 | } // namespace test_auto |
| 100 | |