diff options
| author | Richard Smith <richard-llvm@metafoo.co.uk> | 2017-01-26 20:40:47 +0000 |
|---|---|---|
| committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2017-01-26 20:40:47 +0000 |
| commit | 600b5261c4c5b8a1095a019396ed8771ea50f631 (patch) | |
| tree | 8b843e1b9b46c2c7161a57e2545c9df46b91178c /clang/test | |
| parent | b26530cd69d7d5c25c70bb4dc47ae0dd45becd9e (diff) | |
| download | bcm5719-llvm-600b5261c4c5b8a1095a019396ed8771ea50f631.tar.gz bcm5719-llvm-600b5261c4c5b8a1095a019396ed8771ea50f631.zip | |
PR0091R3: Implement parsing support for using templates as types.
This change adds a new type node, DeducedTemplateSpecializationType, to
represent a type template name that has been used as a type. This is modeled
around AutoType, and shares a common base class for representing a deduced
placeholder type.
We allow deduced class template types in a few more places than the standard
does: in conditions and for-range-declarators, and in new-type-ids. This is
consistent with GCC and with discussion on the core reflector. This patch
does not yet support deduced class template types being named in typename
specifiers.
llvm-svn: 293207
Diffstat (limited to 'clang/test')
| -rw-r--r-- | clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp | 2 | ||||
| -rw-r--r-- | clang/test/CXX/drs/dr5xx.cpp | 16 | ||||
| -rw-r--r-- | clang/test/Parser/backtrack-off-by-one.cpp | 9 | ||||
| -rw-r--r-- | clang/test/Parser/cxx1z-class-template-argument-deduction.cpp | 131 | ||||
| -rw-r--r-- | clang/test/SemaTemplate/temp_arg.cpp | 2 | ||||
| -rw-r--r-- | clang/test/SemaTemplate/typename-specifier-3.cpp | 3 |
6 files changed, 156 insertions, 7 deletions
diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp index 0cdf3c6e053..a260f99f5cf 100644 --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp @@ -9,7 +9,7 @@ struct S { void f() throw (auto); // expected-error{{'auto' not allowed here}} - friend auto; // expected-error{{'auto' not allowed in non-static struct member}} + friend auto; // expected-error{{'auto' not allowed in friend declaration}} operator auto(); // expected-error{{'auto' not allowed in conversion function type}} }; diff --git a/clang/test/CXX/drs/dr5xx.cpp b/clang/test/CXX/drs/dr5xx.cpp index 89e404f5fd6..cdb75219b1c 100644 --- a/clang/test/CXX/drs/dr5xx.cpp +++ b/clang/test/CXX/drs/dr5xx.cpp @@ -877,13 +877,25 @@ namespace dr583 { // dr583: 4 namespace dr585 { // dr585: yes template<typename> struct T; struct A { - friend T; // expected-error {{requires a type specifier}} expected-error {{can only be classes or functions}} + friend T; +#if __cplusplus <= 201402L + // expected-error@-2 {{requires a type specifier}} expected-error@-2 {{can only be classes or functions}} +#else + // expected-error@-4 {{use of class template 'T' requires template arguments; argument deduction not allowed in friend declaration}} + // expected-note@-7 {{here}} +#endif // FIXME: It's not clear whether the standard allows this or what it means, // but the DR585 writeup suggests it as an alternative. template<typename U> friend T<U>; // expected-error {{must use an elaborated type}} }; template<template<typename> class T> struct B { - friend T; // expected-error {{requires a type specifier}} expected-error {{can only be classes or functions}} + friend T; +#if __cplusplus <= 201402L + // expected-error@-2 {{requires a type specifier}} expected-error@-2 {{can only be classes or functions}} +#else + // expected-error@-4 {{use of template template parameter 'T' requires template arguments; argument deduction not allowed in friend declaration}} + // expected-note@-6 {{here}} +#endif template<typename U> friend T<U>; // expected-error {{must use an elaborated type}} }; } diff --git a/clang/test/Parser/backtrack-off-by-one.cpp b/clang/test/Parser/backtrack-off-by-one.cpp index efb95a5a225..52e1c414783 100644 --- a/clang/test/Parser/backtrack-off-by-one.cpp +++ b/clang/test/Parser/backtrack-off-by-one.cpp @@ -1,6 +1,7 @@ // RUN: %clang_cc1 -verify %s // RUN: %clang_cc1 -verify %s -std=c++98 // RUN: %clang_cc1 -verify %s -std=c++11 +// RUN: %clang_cc1 -verify %s -std=c++1z // PR25946 // We had an off-by-one error in an assertion when annotating A<int> below. Our @@ -13,9 +14,13 @@ template <typename T> class A {}; // expected-error@+1 {{expected '{' after base class list}} template <typename T> class B : T // not ',' or '{' #if __cplusplus < 201103L -// expected-error@+4 {{expected ';' after top level declarator}} +// expected-error@+8 {{expected ';' after top level declarator}} +#endif +#if __cplusplus <= 201402L +// expected-error@+5 {{C++ requires a type specifier for all declarations}} +#else +// expected-error@+3 {{expected unqualified-id}} #endif -// expected-error@+2 {{C++ requires a type specifier for all declarations}} // expected-error@+1 {{expected ';' after class}} A<int> { }; diff --git a/clang/test/Parser/cxx1z-class-template-argument-deduction.cpp b/clang/test/Parser/cxx1z-class-template-argument-deduction.cpp new file mode 100644 index 00000000000..e53d64f2ed4 --- /dev/null +++ b/clang/test/Parser/cxx1z-class-template-argument-deduction.cpp @@ -0,0 +1,131 @@ +// RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -verify %s + +template<typename T> struct A {}; // expected-note 31{{declared here}} + +// Make sure we still correctly parse cases where a template can appear without arguments. +namespace template_template_arg { + template<template<typename> typename> struct X {}; + template<typename> struct Y {}; + + X<A> xa; + Y<A> ya; // expected-error {{requires template arguments}} + X<::A> xcca; + Y<::A> ycca; // expected-error {{requires template arguments}} + + template<template<typename> typename = A> struct XD {}; + template<typename = A> struct YD {}; // expected-error {{requires template arguments}} + template<template<typename> typename = ::A> struct XCCD {}; + template<typename = ::A> struct YCCD {}; // expected-error {{requires template arguments}} + + // FIXME: replacing the invalid type with 'int' here is horrible + template <A a = A<int>()> class C { }; // expected-error {{requires template arguments}} expected-error {{not implicitly convertible to 'int'}} + template<typename T = A> struct G { }; // expected-error {{requires template arguments}} +} + +namespace injected_class_name { + template<typename T> struct A { + A(T); + void f(int) { + A a = 1; + injected_class_name::A b = 1; // expected-error {{not yet supported}} + } + void f(T); + }; + A<short> ai = 1; + A<double>::A b(1); // expected-error {{constructor name}} +} + +struct member { + A a; // expected-error {{requires template arguments}} + A *b; // expected-error {{requires template arguments}} + const A c; // expected-error {{requires template arguments}} + + void f() throw (A); // expected-error {{requires template arguments}} + + friend A; // expected-error {{requires template arguments; argument deduction not allowed in friend declaration}} + + operator A(); // expected-error {{requires template arguments; argument deduction not allowed in conversion function type}} + + static A x; // expected-error {{requires an initializer}} + static A y = 0; // expected-error {{not yet supported}} +}; + +namespace in_typedef { + typedef A *AutoPtr; // expected-error {{requires template arguments; argument deduction not allowed in typedef}} + typedef A (*PFun)(int a); // expected-error{{requires template arguments; argument deduction not allowed in typedef}} + typedef A Fun(int a) -> decltype(a + a); // expected-error{{requires template arguments; argument deduction not allowed in function return type}} +} + +namespace stmt { + void g(A a) { // expected-error{{requires template arguments; argument deduction not allowed in function prototype}} + try { } + catch (A &a) { } // expected-error{{requires template arguments; argument deduction not allowed in exception declaration}} + catch (const A a) { } // expected-error{{requires template arguments; argument deduction not allowed in exception declaration}} + try { } catch (A a) { } // expected-error{{requires template arguments; argument deduction not allowed in exception declaration}} + + // FIXME: The standard only permits class template argument deduction in a + // simple-declaration or cast. We also permit it in conditions, + // for-range-declarations, member-declarations for static data members, and + // new-expressions, because not doing so would be bizarre. + A local = 0; // expected-error {{not yet supported}} + static A local_static = 0; // expected-error {{not yet supported}} + static thread_local A thread_local_static = 0; // expected-error {{not yet supported}} + if (A a = 0) {} // expected-error {{not yet supported}} + if (A a = 0; a) {} // expected-error {{not yet supported}} + switch (A a = 0) {} // expected-error {{not yet supported}} + switch (A a = 0; a) {} // expected-error {{not yet supported}} + for (A a = 0; a; /**/) {} // expected-error {{not yet supported}} + for (/**/; A a = 0; /**/) {} // expected-error {{not yet supported}} + while (A a = 0) {} // expected-error {{not yet supported}} + int arr[3]; + for (A a : arr) {} // expected-error {{not yet supported}} + } + + namespace std { + class type_info; + } +} + +namespace expr { + template<typename T> struct U {}; + void j() { + (void)typeid(A); // expected-error{{requires template arguments; argument deduction not allowed here}} + (void)sizeof(A); // expected-error{{requires template arguments; argument deduction not allowed here}} + (void)__alignof(A); // expected-error{{requires template arguments; argument deduction not allowed here}} + + U<A> v; // expected-error {{requires template arguments}} + + int n; + (void)dynamic_cast<A&>(n); // expected-error{{requires template arguments; argument deduction not allowed here}} + (void)static_cast<A*>(&n); // expected-error{{requires template arguments; argument deduction not allowed here}} + (void)reinterpret_cast<A*>(&n); // expected-error{{requires template arguments; argument deduction not allowed here}} + (void)const_cast<A>(n); // expected-error{{requires template arguments; argument deduction not allowed here}} + (void)*(A*)(&n); // expected-error{{requires template arguments; argument deduction not allowed here}} + + (void)A(n); // expected-error {{not yet supported}} + (void)A{n}; // expected-error {{not yet supported}} + (void)new A(n); // expected-error {{not yet supported}} + (void)new A{n}; // expected-error {{not yet supported}} + // FIXME: We should diagnose the lack of an initializer here. + (void)new A; // expected-error {{not yet supported}} + } +} + +namespace decl { + enum E : A {}; // expected-error{{requires template arguments; argument deduction not allowed here}} + struct F : A {}; // expected-error{{expected class name}} + + using B = A; // expected-error{{requires template arguments}} + + auto k() -> A; // expected-error{{requires template arguments}} + + A a; // expected-error {{requires an initializer}} + A b = 0; // expected-error {{not yet supported}} + A (parens) = 0; // expected-error {{cannot use parentheses when declaring variable with deduced class template specialization type}} + A *p = 0; // expected-error {{cannot form pointer to deduced class template specialization type}} + A &r = *p; // expected-error {{cannot form reference to deduced class template specialization type}} + A arr[3] = 0; // expected-error {{cannot form array of deduced class template specialization type}} + A F::*pm = 0; // expected-error {{cannot form pointer to deduced class template specialization type}} + A (*fp)() = 0; // expected-error {{cannot form function returning deduced class template specialization type}} + A [x, y] = 0; // expected-error {{cannot be declared with type 'A'}} expected-error {{not yet supported}} +} diff --git a/clang/test/SemaTemplate/temp_arg.cpp b/clang/test/SemaTemplate/temp_arg.cpp index 052c19ef639..df5bf875f3b 100644 --- a/clang/test/SemaTemplate/temp_arg.cpp +++ b/clang/test/SemaTemplate/temp_arg.cpp @@ -10,7 +10,7 @@ A<int, 0, X> * a1; A<float, 1, X, double> *a2; // expected-error{{too many template arguments for class template 'A'}} A<float, 1> *a3; // expected-error{{too few template arguments for class template 'A'}} -A a3; // expected-error{{use of class template 'A' requires template arguments}} +A a4; // expected-error{{use of class template 'A' requires template arguments}} namespace test0 { template <class t> class foo {}; diff --git a/clang/test/SemaTemplate/typename-specifier-3.cpp b/clang/test/SemaTemplate/typename-specifier-3.cpp index a463d88752c..dfab5a0130f 100644 --- a/clang/test/SemaTemplate/typename-specifier-3.cpp +++ b/clang/test/SemaTemplate/typename-specifier-3.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s // PR4364 -template<class T> struct a { +template<class T> struct a { // expected-note {{here}} T b() { return typename T::x(); } @@ -17,3 +17,4 @@ B c() { // Some extra tests for invalid cases template<class T> struct test2 { T b() { return typename T::a; } }; // expected-error{{expected '(' for function-style cast or type construction}} template<class T> struct test3 { T b() { return typename a; } }; // expected-error{{expected a qualified name after 'typename'}} +template<class T> struct test4 { T b() { return typename ::a; } }; // expected-error{{refers to non-type member}} expected-error{{expected '(' for function-style cast or type construction}} |

