summaryrefslogtreecommitdiffstats
path: root/clang/test
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2017-01-26 20:40:47 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2017-01-26 20:40:47 +0000
commit600b5261c4c5b8a1095a019396ed8771ea50f631 (patch)
tree8b843e1b9b46c2c7161a57e2545c9df46b91178c /clang/test
parentb26530cd69d7d5c25c70bb4dc47ae0dd45becd9e (diff)
downloadbcm5719-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.cpp2
-rw-r--r--clang/test/CXX/drs/dr5xx.cpp16
-rw-r--r--clang/test/Parser/backtrack-off-by-one.cpp9
-rw-r--r--clang/test/Parser/cxx1z-class-template-argument-deduction.cpp131
-rw-r--r--clang/test/SemaTemplate/temp_arg.cpp2
-rw-r--r--clang/test/SemaTemplate/typename-specifier-3.cpp3
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}}
OpenPOWER on IntegriCloud