1// Copyright 2018 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// This is a "No Compile Test" suite.
6// http://dev.chromium.org/developers/testing/no-compile-tests
7
8#include <type_traits>
9
10#include "base/optional.h"
11
12namespace base {
13
14#if defined(NCTEST_EXPLICIT_CONVERTING_COPY_CONSTRUCTOR)  // [r"fatal error: no matching function for call to object of type"]
15
16// Optional<T>(const Optional<U>& arg) constructor is marked explicit if
17// T is not convertible from "const U&".
18void WontCompile() {
19  struct Test {
20    // Declares as explicit so that Test is still constructible from int,
21    // but not convertible.
22    explicit Test(int a) {}
23  };
24
25  static_assert(!std::is_convertible<const int&, Test>::value,
26                "const int& to Test is convertible");
27  const Optional<int> arg(in_place, 1);
28  ([](Optional<Test> param) {})(arg);
29}
30
31#elif defined(NCTEST_EXPLICIT_CONVERTING_MOVE_CONSTRUCTOR)  // [r"fatal error: no matching function for call to object of type"]
32
33// Optional<T>(Optional<U>&& arg) constructor is marked explicit if
34// T is not convertible from "U&&".
35void WontCompile() {
36  struct Test {
37    // Declares as explicit so that Test is still constructible from int,
38    // but not convertible.
39    explicit Test(int a) {}
40  };
41
42  static_assert(!std::is_convertible<int&&, Test>::value,
43                "int&& to Test is convertible");
44  ([](Optional<Test> param) {})(Optional<int>(in_place, 1));
45}
46
47#elif defined(NCTEST_EXPLICIT_VALUE_FORWARD_CONSTRUCTOR)  // [r"fatal error: no matching function for call to object of type"]
48
49// Optional<T>(U&&) constructor is marked explicit if T is not convertible
50// from U&&.
51void WontCompile() {
52  struct Test {
53    // Declares as explicit so that Test is still constructible from int,
54    // but not convertible.
55    explicit Test(int a) {}
56  };
57
58  static_assert(!std::is_convertible<int&&, Test>::value,
59                "int&& to Test is convertible");
60  ([](Optional<Test> param) {})(1);
61}
62
63#elif defined(NCTEST_ILL_FORMED_IN_PLACET_T)  // [r"instantiation of base::Optional with in_place_t is ill-formed"]
64
65// Optional<T> is ill-formed if T is `in_place_t`.
66void WontCompile() {
67  Optional<base::in_place_t> optional;
68  optional.has_value();
69}
70
71#elif defined(NCTEST_ILL_FORMED_CONST_IN_PLACET_T)  // [r"instantiation of base::Optional with in_place_t is ill-formed"]
72
73// Optional<T> is ill-formed if T is `const in_place_t`.
74void WontCompile() {
75  Optional<const base::in_place_t> optional;
76  optional.has_value();
77}
78
79#elif defined(NCTEST_ILL_FORMED_NULLOPT_T)  // [r"instantiation of base::Optional with nullopt_t is ill-formed"]
80
81// Optional<T> is ill-formed if T is `const nullopt_t`.
82void WontCompile() {
83  Optional<const base::nullopt_t> optional;
84  optional.has_value();
85}
86
87#elif defined(NCTEST_ILL_FORMED_CONST_NULLOPT_T)  // [r"instantiation of base::Optional with nullopt_t is ill-formed"]
88
89// Optional<T> is ill-formed if T is `const nullopt_t`.
90void WontCompile() {
91  Optional<const base::nullopt_t> optional;
92  optional.has_value();
93}
94
95#elif defined(NCTEST_ILL_FORMED_NON_DESTRUCTIBLE)  // [r"instantiation of base::Optional with a non-destructible type is ill-formed"]
96
97// Optional<T> is ill-formed if T is non-destructible.
98void WontCompile() {
99  struct T {
100   private:
101    ~T();
102  };
103
104  static_assert(!std::is_destructible<T>::value, "T is not destructible");
105
106  Optional<T> optional;
107  optional.has_value();
108}
109
110// TODO(crbug.com/967722): the error message should be about the instantiation of an
111// ill-formed base::Optional.
112#elif defined(NCTEST_ILL_FORMED_REFERENCE)  // [r"fatal error: union member 'value_' has reference type 'int &'"]
113
114// Optional<T> is ill-formed if T is a reference.
115void WontCompile() {
116  using T = int&;
117
118  static_assert(std::is_reference<T>::value, "T is a reference");
119
120  Optional<T> optional;
121  optional.has_value();
122}
123
124// TODO(crbug.com/967722): the error message should be about the instantiation of an
125// ill-formed base::Optional.
126#elif defined(NCTEST_ILL_FORMED_CONST_REFERENCE)  // [r"fatal error: union member 'value_' has reference type 'const int &'"]
127
128// Optional<T> is ill-formed if T is a const reference.
129void WontCompile() {
130  using T = const int&;
131
132  static_assert(std::is_reference<T>::value, "T is a reference");
133
134  Optional<T> optional;
135  optional.has_value();
136}
137
138#elif defined(NCTEST_ILL_FORMED_FIXED_LENGTH_ARRAY)  // [r"instantiation of base::Optional with an array type is ill-formed"]
139
140// Optional<T> is ill-formed if T is a fixed length array.
141void WontCompile() {
142  using T = char[4];
143
144  static_assert(std::is_array<T>::value, "T is an array");
145
146  Optional<T> optional;
147  optional.has_value();
148}
149
150// TODO(crbug.com/967722): the error message should be about the instantiation of an
151// ill-formed base::Optional.
152#elif defined(NCTEST_ILL_FORMED_UNDEFINED_LENGTH_ARRAY)  // [r"fatal error: base class 'OptionalStorageBase' has a flexible array member"]
153
154// Optional<T> is ill-formed if T is a undefined length array.
155void WontCompile() {
156  using T = char[];
157
158  static_assert(std::is_array<T>::value, "T is an array");
159
160  Optional<T> optional;
161  optional.has_value();
162}
163
164#endif
165
166}  // namespace base
167