// RUN: %clang_cc1 -std=c++1z -verify %s -DERRORS -Wundefined-func-template // RUN: %clang_cc1 -std=c++1z -verify %s -UERRORS -Wundefined-func-template // This test is split into two because we only produce "undefined internal" // warnings if we didn't produce any errors. #if ERRORS namespace std { using size_t = decltype(sizeof(0)); template struct initializer_list { const T *p; size_t n; initializer_list(); }; // FIXME: This should probably not be necessary. template initializer_list(initializer_list) -> initializer_list; } template constexpr bool has_type(...) { return false; } template constexpr bool has_type(T&) { return true; } std::initializer_list il = {1, 2, 3, 4, 5}; template struct vector { template vector(Iter, Iter); vector(std::initializer_list); }; template vector(std::initializer_list) -> vector; template explicit vector(Iter, Iter) -> vector; template explicit vector(std::size_t, T) -> vector; vector v1 = {1, 2, 3, 4}; static_assert(has_type>(v1)); struct iter { typedef char value_type; } it, end; vector v2(it, end); static_assert(has_type>(v2)); vector v3(5, 5); static_assert(has_type>(v3)); vector v4 = {it, end}; static_assert(has_type>(v4)); vector v5{it, end}; static_assert(has_type>(v5)); template struct tuple { tuple(T...); }; template explicit tuple(T ...t) -> tuple; // expected-note {{declared}} // FIXME: Remove template tuple(tuple) -> tuple; const int n = 4; tuple ta = tuple{1, 'a', "foo", n}; static_assert(has_type>(ta)); tuple tb{ta}; static_assert(has_type>(tb)); // FIXME: This should be tuple>; when the above guide is removed. tuple tc = {ta}; static_assert(has_type>(tc)); tuple td = {1, 2, 3}; // expected-error {{selected an explicit deduction guide}} static_assert(has_type>(td)); // FIXME: This is a GCC extension for now; if CWG don't allow this, at least // add a warning for it. namespace new_expr { tuple *p = new tuple{0}; tuple *q = new tuple(1.0f, 2.0f); } namespace ambiguity { template struct A {}; A(unsigned short) -> A; // expected-note {{candidate}} A(short) -> A; // expected-note {{candidate}} A a = 0; // expected-error {{ambiguous deduction for template arguments of 'A'}} template struct B {}; template B(T(&)(int)) -> B; // expected-note {{candidate function [with T = int]}} template B(int(&)(T)) -> B; // expected-note {{candidate function [with T = int]}} int f(int); B b = f; // expected-error {{ambiguous deduction for template arguments of 'B'}} } // FIXME: Revisit this once CWG decides if attributes, and [[deprecated]] in // particular, should be permitted here. namespace deprecated { template struct A { A(int); }; [[deprecated]] A(int) -> A; // expected-note {{marked deprecated here}} A a = 0; // expected-warning {{'' is deprecated}} } namespace dependent { template typename A> decltype(auto) a = A{1, 2, 3}; static_assert(has_type>(a)); static_assert(has_type>(a)); struct B { template struct X { X(T); }; X(int) -> X; template using Y = X; // expected-note {{template}} }; template void f() { typename T::X tx = 0; typename T::Y ty = 0; // expected-error {{alias template 'Y' requires template arguments; argument deduction only allowed for class templates}} } template void f(); // expected-note {{in instantiation of}} template struct C { C(T); }; template C(T) -> C; template void g(T a) { C b = 0; C c = a; using U = decltype(b); // expected-note {{previous}} using U = decltype(c); // expected-error {{different types ('C' vs 'C')}} } void h() { g(0); g("foo"); // expected-note {{instantiation of}} } } namespace look_into_current_instantiation { template struct Q {}; template struct A { using U = T; template using V = Q::U>; template A(V); }; A a = Q(); // ok, can look through class-scope typedefs and alias // templates, and members of the current instantiation A &r = a; template struct B { // expected-note {{could not match 'B' against 'int'}} struct X { typedef T type; }; B(typename X::type); // expected-note {{couldn't infer template argument 'T'}} }; B b = 0; // expected-error {{no viable}} // We should have a substitution failure in the immediate context of // deduction when using the C(T, U) constructor (probably; core wording // unclear). template struct C { using U = typename T::type; C(T, U); }; struct R { R(int); typedef R type; }; C(...) -> C; C c = {1, 2}; } namespace nondeducible { template struct X {}; template // expected-note {{non-deducible template parameter 'A'}} X() -> X; // expected-error {{deduction guide template contains a template parameter that cannot be deduced}} template // expected-note {{non-deducible template parameter 'A'}} X(typename X::type) -> X; // expected-error {{deduction guide template contains a template parameter that cannot be deduced}} template // expected-note {{non-deducible template parameter 'B'}} X(int) -> X; // expected-error {{deduction guide template contains a template parameter that cannot be deduced}} template X(float) -> X; // ok template struct UnnamedTemplateParam {}; template // expected-note {{non-deducible template parameter (anonymous)}} UnnamedTemplateParam() -> UnnamedTemplateParam; // expected-error {{deduction guide template contains a template parameter that cannot be deduced}} } namespace default_args_from_ctor { template struct S { S(A = 0) {} }; S s(0); template struct T { template T(A = 0, B = 0) {} }; T t(0, 0); } namespace transform_params { template typename U, T (*X)[N]> struct A { template typename W> A(U, W); static constexpr T v = N; }; int n[12]; template struct Q {}; Q<&n> qn; A a(qn, qn); static_assert(a.v == 12); template struct B { template B(const T (&...p)[V]) { constexpr int Vs[] = {V...}; static_assert(Vs[0] == 3 && Vs[1] == 4 && Vs[2] == 4); } static constexpr int (*p)(T...) = (int(*)(int, char, char))nullptr; }; B b({1, 2, 3}, "foo", {'x', 'y', 'z', 'w'}); // ok template struct C { template typename X> C(X); }; template struct Y {}; C c(Y<0, 1, 2>{}); template struct D { template D(Y); }; D d(Y<0, 1, 2>{}); } namespace variadic { int arr3[3], arr4[4]; // PR32673 template struct A { template A(T, U...); }; A a(1, 2, 3); template struct B { template B(T, int (&...r)[N]); }; B b(1, arr3, arr4); template struct C { template typename ...U> C(T, U...); }; C c(1, a, b); template struct X { template X(T, U...); }; X x(1, 2, 3); template struct Y { template Y(T, int (&...r)[N]); }; Y y(1, arr3, arr4); template typename ...U> struct Z { template Z(T, U...); }; Z z(1, a, b); } namespace tuple_tests { // The converting n-ary constructor appears viable, deducing T as an empty // pack (until we check its SFINAE constraints). namespace libcxx_1 { template struct tuple { template struct X { static const bool value = false; }; template::value> tuple(U &&...u); }; tuple a = {1, 2, 3}; } // Don't get caught by surprise when X<...> doesn't even exist in the // selected specialization! namespace libcxx_2 { template struct tuple { template struct X { static const bool value = false; }; // Substitution into X::value succeeds but produces the // value-dependent expression // tuple::X<>::value // FIXME: Is that the right behavior? template::value> tuple(U &&...u); }; template <> class tuple<> {}; tuple a = {1, 2, 3}; // expected-error {{excess elements in struct initializer}} } namespace libcxx_3 { template struct scoped_lock { scoped_lock(T...); }; template<> struct scoped_lock<> {}; scoped_lock l = {}; } } namespace dependent { template struct X { X(T); }; template int Var(T t) { X x(t); return X(x) + 1; // expected-error {{invalid operands}} } template int Cast(T t) { return X(X(t)) + 1; // expected-error {{invalid operands}} } template int New(T t) { return X(new X(t)) + 1; // expected-error {{invalid operands}} }; template int Var(float); // expected-note {{instantiation of}} template int Cast(float); // expected-note {{instantiation of}} template int New(float); // expected-note {{instantiation of}} template int operator+(X, int); template int Var(int); template int Cast(int); template int New(int); template typename Y> void test() { Y(0); new Y(0); Y y(0); } template void test(); } namespace injected_class_name { template struct A { A(); template A(A); }; A a; A b = a; using T = decltype(a); using T = decltype(b); } namespace member_guides { // PR34520 template struct Foo { template struct Bar { Bar(...) {} }; Bar(int) -> Bar; }; Foo::Bar b = 0; struct A { template struct Public; // expected-note {{declared public}} Public(float) -> Public; protected: // expected-note {{declared protected by intervening access specifier}} template struct Protected; // expected-note 2{{declared protected}} Protected(float) -> Protected; Public(int) -> Public; // expected-error {{different access}} private: // expected-note {{declared private by intervening access specifier}} template struct Private; // expected-note {{declared private}} Protected(int) -> Protected; // expected-error {{different access}} public: // expected-note 2{{declared public by intervening access specifier}} template Public(T) -> Public; template Protected(T) -> Protected; // expected-error {{different access}} template Private(T) -> Private; // expected-error {{different access}} }; } namespace rdar41903969 { template struct A {}; template struct B; template struct C { C(A&); C(B&); }; void foo(A &a, B &b) { (void)C{b}; (void)C{a}; } template struct X { X(std::initializer_list) = delete; X(const X&); }; template struct D : X {}; void bar(D& d) { (void)X{d}; } } namespace rdar41330135 { template struct A {}; template struct S { template S(T a, U t, A); }; template struct D { D(T t, A); }; int f() { S s(0, 0, A()); D d(0, A()); } namespace test_dupls { template struct X {}; template struct A { A(T t, X); }; A a(0, {}); template struct B { B(U u, X); }; B b(0, {}); } } #pragma clang diagnostic push #pragma clang diagnostic warning "-Wctad-maybe-unsupported" namespace test_implicit_ctad_warning { template struct Tag {}; template struct NoExplicit { // expected-note {{add a deduction guide to suppress this warning}} NoExplicit(T) {} NoExplicit(T, int) {} }; // expected-warning@+1 {{'NoExplicit' may not intend to support class template argument deduction}} NoExplicit ne(42); template struct HasExplicit { HasExplicit(U) {} HasExplicit(U, int) {} }; template HasExplicit(U, int) -> HasExplicit>; HasExplicit he(42); // Motivating examples from (taken from Stephan Lavavej's 2018 Cppcon talk) template struct AmateurPair { // expected-note {{add a deduction guide to suppress this warning}} T first; U second; explicit AmateurPair(const T &t, const U &u) {} }; // expected-warning@+1 {{'AmateurPair' may not intend to support class template argument deduction}} AmateurPair p1(42, "hello world"); // deduces to Pair template struct AmateurPair2 { // expected-note {{add a deduction guide to suppress this warning}} T first; U second; explicit AmateurPair2(T t, U u) {} }; // expected-warning@+1 {{'AmateurPair2' may not intend to support class template argument deduction}} AmateurPair2 p2(42, "hello world"); // deduces to Pair2 template struct ProPair { T first; U second; explicit ProPair(T const& t, U const& u) {} }; template ProPair(T1, T2) -> ProPair; ProPair p3(42, "hello world"); // deduces to ProPair static_assert(__is_same(decltype(p3), ProPair)); // Test that user-defined explicit guides suppress the warning even if they // aren't used as candidates. template struct TestExplicitCtor { TestExplicitCtor(T) {} }; template explicit TestExplicitCtor(TestExplicitCtor const&) -> TestExplicitCtor; TestExplicitCtor ce1{42}; TestExplicitCtor ce2 = ce1; static_assert(__is_same(decltype(ce2), TestExplicitCtor), ""); struct allow_ctad_t { allow_ctad_t() = delete; }; template struct TestSuppression { TestSuppression(T) {} }; TestSuppression(allow_ctad_t)->TestSuppression; TestSuppression ta("abc"); static_assert(__is_same(decltype(ta), TestSuppression), ""); } #pragma clang diagnostic pop namespace PR41549 { template struct umm; template struct umm { umm(H h = 0, P p = 0); }; template struct umm; umm m(1); } namespace PR45124 { class a { int d; }; class b : a {}; struct x { ~x(); }; template class y { y(x = x()); }; template y(z)->y; // Not a constant initializer, but trivial default initialization. We won't // detect this as trivial default initialization if synthesizing the implicit // deduction guide 'template y(x = x()) -> Y;' leaves behind a // pending cleanup. __thread b g; } namespace PR47175 { template struct A { A(T); T x; }; template int &&n = A(T()).x; int m = n; } #else // expected-no-diagnostics namespace undefined_warnings { // Make sure we don't get an "undefined but used internal symbol" warning for the deduction guide here. namespace { template struct TemplDObj { explicit TemplDObj(T func) noexcept {} }; auto test1 = TemplDObj(0); TemplDObj(float) -> TemplDObj; auto test2 = TemplDObj(.0f); } } #endif