diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-1y.cpp | 33 | ||||
-rw-r--r-- | test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6-1y.cpp | 31 | ||||
-rw-r--r-- | test/SemaCXX/cxx1y-deduced-return-type.cpp | 338 |
3 files changed, 401 insertions, 1 deletions
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-1y.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-1y.cpp index 7245b9b47f..39c547b9ae 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-1y.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-1y.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++1y +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++1y -DCXX1Y // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 -Wno-c++1y-extensions // FIXME: This is in p11 (?) in C++1y. @@ -41,3 +41,34 @@ void i() { decltype(auto) x = 5; decltype(auto) int r; // expected-error {{cannot combine with previous 'decltype(auto)' declaration specifier}} expected-error {{requires an initializer}} } + +namespace p3_example { + template<typename T, typename U> struct is_same_impl { + static const bool value = false; + }; + template<typename T> struct is_same_impl<T, T> { + static const bool value = true; + }; + template<typename T, typename U> constexpr bool is_same() { + return is_same_impl<T,U>::value; + } + + auto x = 5; + const auto *v = &x, u = 6; + static auto y = 0.0; + auto int r; // expected-warning {{storage class}} expected-error {{file-scope}} + + static_assert(is_same<decltype(x), int>(), ""); + static_assert(is_same<decltype(v), const int*>(), ""); + static_assert(is_same<decltype(u), const int>(), ""); + static_assert(is_same<decltype(y), double>(), ""); + +#ifdef CXX1Y + auto f() -> int; + auto g() { return 0.0; } + auto h(); + + static_assert(is_same<decltype(f), int()>(), ""); + static_assert(is_same<decltype(g), double()>(), ""); +#endif +} diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6-1y.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6-1y.cpp index 25b5f1984c..66085eda3d 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6-1y.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6-1y.cpp @@ -64,3 +64,34 @@ decltype(auto) *v4 = { 0 }; // expected-error {{cannot form pointer to 'decltype auto multi1a = 0, &multi1b = multi1a; auto multi1c = multi1a, multi1d = multi1b; decltype(auto) multi1e = multi1a, multi1f = multi1b; // expected-error {{'decltype(auto)' deduced as 'int' in declaration of 'multi1e' and deduced as 'int &' in declaration of 'multi1f'}} + +auto f1a() { return 0; } +decltype(auto) f1d() { return 0; } +using Int = decltype(f1a()); +using Int = decltype(f1d()); + +auto f2a(int n) { return n; } +decltype(auto) f2d(int n) { return n; } +using Int = decltype(f2a(0)); +using Int = decltype(f2d(0)); + +auto f3a(int n) { return (n); } +decltype(auto) f3d(int n) { return (n); } // expected-warning {{reference to stack memory}} +using Int = decltype(f3a(0)); +using IntLRef = decltype(f3d(0)); + +auto f4a(int n) { return f(); } +decltype(auto) f4d(int n) { return f(); } +using Int = decltype(f4a(0)); +using IntRRef = decltype(f4d(0)); + +auto f5aa(int n) { auto x = f(); return x; } +auto f5ad(int n) { decltype(auto) x = f(); return x; } +decltype(auto) f5da(int n) { auto x = f(); return x; } +decltype(auto) f5dd(int n) { decltype(auto) x = f(); return x; } // expected-error {{rvalue reference to type 'int' cannot bind to lvalue}} +using Int = decltype(f5aa(0)); +using Int = decltype(f5ad(0)); +using Int = decltype(f5da(0)); + +auto init_list_1() { return { 1, 2, 3 }; } // expected-error {{cannot deduce return type from initializer list}} +decltype(auto) init_list_2() { return { 1, 2, 3 }; } // expected-error {{cannot deduce return type from initializer list}} diff --git a/test/SemaCXX/cxx1y-deduced-return-type.cpp b/test/SemaCXX/cxx1y-deduced-return-type.cpp new file mode 100644 index 0000000000..f0146f88d6 --- /dev/null +++ b/test/SemaCXX/cxx1y-deduced-return-type.cpp @@ -0,0 +1,338 @@ +// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only %s + +auto f(); // expected-note {{previous}} +int f(); // expected-error {{differ only in their return type}} + +auto &g(); +auto g() -> auto &; + +auto h() -> auto *; +auto *h(); + +struct Conv1 { + operator auto(); // expected-note {{declared here}} +} conv1; +int conv1a = conv1; // expected-error {{function 'operator auto' with deduced return type cannot be used before it is defined}} +// expected-error@-1 {{no viable conversion}} +Conv1::operator auto() { return 123; } +int conv1b = conv1; +int conv1c = conv1.operator auto(); +int conv1d = conv1.operator int(); // expected-error {{no member named 'operator int'}} + +struct Conv2 { + operator auto() { return 0; } // expected-note 2{{previous}} + operator auto() { return 0.; } // expected-error {{cannot be redeclared}} expected-error {{redefinition of 'operator auto'}} +}; + +struct Conv3 { + operator auto() { int *p = nullptr; return p; } // expected-note {{candidate}} + operator auto*() { int *p = nullptr; return p; } // expected-note {{candidate}} +} conv3; +int *conv3a = conv3; // expected-error {{ambiguous}} +int *conv3b = conv3.operator auto(); +int *conv3c = conv3.operator auto*(); + +template<typename T> +struct Conv4 { + operator auto() { return T(); } +}; +Conv4<int> conv4int; +int conv4a = conv4int; +int conv4b = conv4int.operator auto(); + +auto a(); +auto a() { return 0; } +using T = decltype(a()); +using T = int; +auto a(); // expected-note {{previous}} +using T = decltype(a()); +auto *a(); // expected-error {{differ only in their return type}} + +auto b(bool k) { + if (k) + return "hello"; + return "goodbye"; +} + +auto *ptr_1() { + return 100; // expected-error {{cannot deduce return type 'auto *' from returned value of type 'int'}} +} + +const auto &ref_1() { + return 0; // expected-warning {{returning reference to local temporary}} +} + +auto init_list() { + return { 1, 2, 3 }; // expected-error {{cannot deduce return type from initializer list}} +} + +auto fwd_decl(); // expected-note 2{{here}} + +int n = fwd_decl(); // expected-error {{function 'fwd_decl' with deduced return type cannot be used before it is defined}} +int k = sizeof(fwd_decl()); // expected-error {{used before it is defined}} + +auto fac(int n) { + if (n <= 2) + return n; + return n * fac(n-1); // ok +} + +auto fac_2(int n) { // expected-note {{declared here}} + if (n > 2) + return n * fac_2(n-1); // expected-error {{cannot be used before it is defined}} + return n; +} + +auto void_ret() {} +using Void = void; +using Void = decltype(void_ret()); + +auto &void_ret_2() {} // expected-error {{cannot deduce return type 'auto &' for function with no return statements}} +const auto void_ret_3() {} // ok, return type 'const void' is adjusted to 'void' + +const auto void_ret_4() { + if (false) + return void(); + if (false) + return; + return 0; // expected-error {{'auto' in return type deduced as 'int' here but deduced as 'void' in earlier return statement}} +} + +namespace Templates { + template<typename T> auto f1() { + return T() + 1; + } + template<typename T> auto &f2(T &&v) { return v; } + int a = f1<int>(); + const int &b = f2(0); + double d; + float &c = f2(0.0); // expected-error {{non-const lvalue reference to type 'float' cannot bind to a value of unrelated type 'double'}} + + template<typename T> auto fwd_decl(); // expected-note {{declared here}} + int e = fwd_decl<int>(); // expected-error {{cannot be used before it is defined}} + template<typename T> auto fwd_decl() { return 0; } + int f = fwd_decl<int>(); + template<typename T> auto fwd_decl(); + int g = fwd_decl<char>(); + + auto (*p)() = f1; // expected-error {{incompatible initializer}} + auto (*q)() = f1<int>; // ok + + typedef decltype(f2(1.2)) dbl; // expected-note {{previous}} + typedef float dbl; // expected-error {{typedef redefinition with different types ('float' vs 'decltype(f2(1.2))' (aka 'double &'))}} + + extern template auto fwd_decl<double>(); + int k1 = fwd_decl<double>(); + extern template int fwd_decl<char>(); // expected-error {{does not refer to a function template}} + int k2 = fwd_decl<char>(); + + template<typename T> auto instantiate() { T::error; } // expected-error {{has no members}} + extern template auto instantiate<int>(); // ok + int k = instantiate<int>(); // expected-note {{in instantiation of}} + template<> auto instantiate<char>() {} // ok + template<> void instantiate<double>() {} // expected-error {{no function template matches}} + + template<typename T> auto arg_single() { return 0; } + template<typename T> auto arg_multi() { return 0l; } + template<typename T> auto arg_multi(int) { return "bad"; } + template<typename T> struct Outer { + static auto arg_single() { return 0.f; } + static auto arg_multi() { return 0.; } + static auto arg_multi(int) { return "bad"; } + }; + template<typename T> T &take_fn(T (*p)()); + + int &check1 = take_fn(arg_single); // expected-error {{no matching}} expected-note@-2 {{couldn't infer}} + int &check2 = take_fn(arg_single<int>); + int &check3 = take_fn<int>(arg_single); // expected-error {{no matching}} expected-note@-4{{no overload of 'arg_single'}} + int &check4 = take_fn<int>(arg_single<int>); + long &check5 = take_fn(arg_multi); // expected-error {{no matching}} expected-note@-6 {{couldn't infer}} + long &check6 = take_fn(arg_multi<int>); + long &check7 = take_fn<long>(arg_multi); // expected-error {{no matching}} expected-note@-8{{no overload of 'arg_multi'}} + long &check8 = take_fn<long>(arg_multi<int>); + + float &mem_check1 = take_fn(Outer<int>::arg_single); + float &mem_check2 = take_fn<float>(Outer<char>::arg_single); + double &mem_check3 = take_fn(Outer<long>::arg_multi); + double &mem_check4 = take_fn<double>(Outer<double>::arg_multi); + + namespace Deduce1 { + template<typename T> auto f() { return 0; } // expected-note {{candidate}} + template<typename T> void g(T(*)()); // expected-note 2{{candidate}} + void h() { + auto p = f<int>; + auto (*q)() = f<int>; + int (*r)() = f; // expected-error {{does not match}} + g(f<int>); + g<int>(f); // expected-error {{no matching function}} + g(f); // expected-error {{no matching function}} + } + } + + namespace Deduce2 { + template<typename T> auto f(int) { return 0; } // expected-note {{candidate}} + template<typename T> void g(T(*)(int)); // expected-note 2{{candidate}} + void h() { + auto p = f<int>; + auto (*q)(int) = f<int>; + int (*r)(int) = f; // expected-error {{does not match}} + g(f<int>); + g<int>(f); // expected-error {{no matching function}} + g(f); // expected-error {{no matching function}} + } + } + + namespace Deduce3 { + template<typename T> auto f(T) { return 0; } + template<typename T> void g(T(*)(int)); // expected-note {{couldn't infer}} + void h() { + auto p = f<int>; + auto (*q)(int) = f<int>; + int (*r)(int) = f; // ok + g(f<int>); + g<int>(f); // ok + g(f); // expected-error {{no matching function}} + } + } + + namespace DeduceInDeducedReturnType { + template<typename T, typename U> auto f() -> auto (T::*)(U) { + int (T::*result)(U) = nullptr; + return result; + } + struct S {}; + int (S::*(*p)())(double) = f; + int (S::*(*q)())(double) = f<S, double>; + } +} + +auto fwd_decl_using(); +namespace N { using ::fwd_decl_using; } +auto fwd_decl_using() { return 0; } +namespace N { int k = N::fwd_decl_using(); } + +namespace OverloadResolutionNonTemplate { + auto f(); + auto f(int); // expected-note {{here}} + + int &g(int (*f)()); // expected-note {{not viable: no overload of 'f' matching 'int (*)()'}} + char &g(int (*f)(int)); // expected-note {{not viable: no overload of 'f' matching 'int (*)(int)'}} + + int a = g(f); // expected-error {{no matching function}} + + auto f() { return 0; } + + // FIXME: It's not completely clear whether this should be ill-formed. + int &b = g(f); // expected-error {{used before it is defined}} + + auto f(int) { return 0.0; } + + int &c = g(f); // ok +} + +namespace OverloadResolutionTemplate { + auto f(); + template<typename T> auto f(T); + + int &g(int (*f)()); // expected-note {{not viable: no overload of 'f' matching 'int (*)()'}} expected-note {{candidate}} + char &g(int (*f)(int)); // expected-note {{not viable: no overload of 'f' matching 'int (*)(int)'}} expected-note {{candidate}} + + int a = g(f); // expected-error {{no matching function}} + + auto f() { return 0; } + + int &b = g(f); // ok (presumably), due to deduction failure forming type of 'f<int>' + + template<typename T> auto f(T) { return 0; } + + int &c = g(f); // expected-error {{ambiguous}} +} + +namespace DefaultedMethods { + struct A { + auto operator=(const A&) = default; // expected-error {{must return 'DefaultedMethods::A &'}} + A &operator=(A&&); // expected-note {{previous}} + }; + auto A::operator=(A&&) = default; // expected-error {{differs from the declaration in the return type}} +} + +namespace Constexpr { + constexpr auto f1(int n) { return n; } + struct NonLiteral { ~NonLiteral(); } nl; // expected-note {{user-provided destructor}} + constexpr auto f2(int n) { return nl; } // expected-error {{return type 'Constexpr::NonLiteral' is not a literal type}} +} + +// It's not really clear whether these are valid, but this matches g++. +using size_t = decltype(sizeof(0)); +auto operator new(size_t n, const char*); // expected-error {{must return type 'void *'}} +auto operator delete(void *, const char*); // expected-error {{must return type 'void'}} + +namespace Virtual { + struct S { + virtual auto f() { return 0; } // expected-error {{function with deduced return type cannot be virtual}} expected-note {{here}} + }; + // Allow 'auto' anyway for error recovery. + struct T : S { + int f(); + }; + struct U : S { + auto f(); // expected-error {{different return}} + }; + + // And here's why... + struct V { virtual auto f(); }; // expected-error {{cannot be virtual}} + struct W : V { virtual auto f(); }; // expected-error {{cannot be virtual}} + auto V::f() { return 0; } // in tu1.cpp + auto W::f() { return 0.0; } // in tu2.cpp + W w; + int k1 = w.f(); + int k2 = ((V&)w).f(); +} + +namespace std_examples { + +namespace NoReturn { + auto f() {} + void (*p)() = &f; + + auto *g() {} // expected-error {{cannot deduce return type 'auto *' for function with no return statements}} +} + +namespace UseBeforeComplete { + auto n = n; // expected-error {{variable 'n' declared with 'auto' type cannot appear in its own initializer}} + auto f(); // expected-note {{declared here}} + void g() { &f; } // expected-error {{function 'f' with deduced return type cannot be used before it is defined}} + auto sum(int i) { + if (i == 1) + return i; + else + return sum(i - 1) + i; + } +} + +namespace Redecl { + auto f(); + auto f() { return 42; } + auto f(); // expected-note 2{{previous}} + int f(); // expected-error {{functions that differ only in their return type cannot be overloaded}} + decltype(auto) f(); // expected-error {{cannot be overloaded}} + + template<typename T> auto g(T t) { return t; } // expected-note {{candidate}} + template auto g(int); + template char g(char); // expected-error {{does not refer to a function}} + template<> auto g(double); + + template<typename T> T g(T t) { return t; } // expected-note {{candidate}} + template char g(char); + template auto g(float); + + void h() { return g(42); } // expected-error {{ambiguous}} +} + +namespace ExplicitInstantiationDecl { + template<typename T> auto f(T t) { return t; } + extern template auto f(int); + int (*p)(int) = f; +} + +} |