1 // { dg-do compile { target c++11 } }
2 // Minimized from the testcase for PR c++/88146,
3 // then turned into multiple variants.
5 // We issue an error when calling an inherited ctor with at least one
6 // argument passed through a varargs ellipsis, if the call is in an
7 // evaluated context. Even in nonevaluated contexts, we will
8 // instantiate constexpr templates (unlike non-constexpr templates),
9 // which might then issue errors that in nonevlauated contexts
10 // wouldn't be issued.
12 // In these variants, the inherited ctor is constexpr, but it's only
13 // called in unevaluated contexts, so no error is issued. The
14 // templateness of the ctor doesn't matter, because the only call that
15 // passes args through the ellipsis is in a noexcept expr, that is not
16 // evaluated. The ctors in derived classes are created and
17 // instantiated, discarding arguments passed through the ellipsis when
18 // calling base ctors, but that's not reported: we only report a
19 // problem when *calling* ctors that behave this way.
20 namespace unevaled_call {
21 namespace no_arg_before_ellipsis {
22 namespace without_template {
32 void f() noexcept(noexcept(bar{0}));
35 namespace with_template {
37 template <typename... T>
46 void f() noexcept(noexcept(bar{0}));
50 namespace one_arg_before_ellipsis {
51 namespace without_template {
53 constexpr foo(int, ...) {}
61 void f() noexcept(noexcept(bar{0,1}));
64 namespace with_template {
67 constexpr foo(T, ...) {}
75 void f() noexcept(noexcept(bar{0,1}));
80 // In these variants, the inherited ctor is constexpr, and it's called
81 // in unevaluated contexts in ways that would otherwise trigger the
82 // sorry message. Here we check that the message is not issued at
83 // those calls, nor at subsequent calls that use the same ctor without
84 // passing arguments through its ellipsis. We check that it is issued
85 // later, when we pass the ctor arguments through the ellipsis.
86 namespace evaled_bad_call_in_u {
87 namespace one_arg_before_ellipsis {
88 namespace without_template {
90 constexpr foo(int, ...) {}
98 void f() noexcept(noexcept(bar{0, 1}));
100 bar u(0, 1); // { dg-message "sorry, unimplemented: passing arguments to ellipsis" }
103 namespace with_template {
105 template <typename T>
106 constexpr foo(T, ...) {}
114 void f() noexcept(noexcept(bar{0,1}));
116 bar u(0,1); // { dg-message "sorry, unimplemented: passing arguments to ellipsis" }
120 namespace no_arg_before_ellipsis {
121 namespace without_template {
123 constexpr foo(...) {}
131 void f() noexcept(noexcept(bar{0}));
132 bar u(0); // { dg-message "sorry, unimplemented: passing arguments to ellipsis" }
135 namespace with_template {
137 template <typename... T>
138 constexpr foo(...) {}
146 void f() noexcept(noexcept(bar{0}));
147 bar u(0); // { dg-message "sorry, unimplemented: passing arguments to ellipsis" }
152 // Now, instead of instantiating a class that uses a derived ctor, we
153 // introduce another template ctor that will use the varargs ctor to
154 // initialize its base class. The idea is to verify that the error
155 // message is issued, even if the instantiation occurs in a
156 // nonevaluated context, e.g., for constexpr templates. In the
157 // inherited_derived_ctor, we check that even an inherited ctor of a
158 // constexpr ctor is instantiated and have an error message issued.
159 namespace derived_ctor {
160 namespace direct_derived_ctor {
161 namespace constexpr_noninherited_ctor {
163 template <typename T>
164 constexpr foo(T, ...) {}
170 template <typename ...T>
171 constexpr bar(T ... args) : boo(args...) {}
173 void f() noexcept(noexcept(bar{0,1}));
176 namespace no_constexpr_noninherited_ctor {
178 template <typename T>
179 constexpr foo(T, ...) {}
185 template <typename ...T>
186 /* constexpr */ bar(T ... args) : boo(args...) {}
188 void f() noexcept(noexcept(bar{0,1}));
192 namespace inherited_derived_ctor {
193 namespace constexpr_noninherited_ctor {
195 template <typename T>
196 constexpr foo(T, ...) {}
202 template <typename ...T>
203 constexpr bor(T ... args) : boo(args...) {}
208 void f() noexcept(noexcept(bar{0,1}));
211 namespace no_constexpr_noninherited_ctor {
213 template <typename T>
214 constexpr foo(T, ...) {}
220 template <typename ...T>
221 /* constexpr */ bor(T ... args) : boo(args...) {}
226 void f() noexcept(noexcept(bar{0,1}));