diff options
Diffstat (limited to 'test/SemaTemplate')
42 files changed, 799 insertions, 32 deletions
diff --git a/test/SemaTemplate/alias-templates.cpp b/test/SemaTemplate/alias-templates.cpp index 79d6849a6efe..75615ee29517 100644 --- a/test/SemaTemplate/alias-templates.cpp +++ b/test/SemaTemplate/alias-templates.cpp @@ -68,3 +68,35 @@ itt::thing ith(itr); itt::rebind<bool> btr; itt::rebind_thing<bool> btt(btr); + +namespace PR11848 { + template<typename T> using U = int; + + template<typename T, typename ...Ts> + void f(U<T> i, U<Ts> ...is) { // expected-error {{type 'U<Ts>' (aka 'int') of function parameter pack does not contain any unexpanded parameter packs}} + return i + f<Ts...>(is...); // expected-error {{pack expansion does not contain any unexpanded parameter packs}} + } + + template<typename ...Ts> + struct S { + S(U<Ts>...ts); // expected-error {{does not contain any unexpanded parameter packs}} + }; + + template<typename T> + struct Hidden1 { + template<typename ...Ts> + Hidden1(typename T::template U<Ts> ...ts); // expected-error{{type 'typename Hide::U<Ts>' (aka 'int') of function parameter pack does not contain any unexpanded parameter packs}} + }; + + template<typename T, typename ...Ts> + struct Hidden2 { + Hidden2(typename T::template U<Ts> ...ts); + }; + + struct Hide { + template<typename T> using U = int; + }; + + Hidden1<Hide> h1; // expected-note{{in instantiation of template class 'PR11848::Hidden1<PR11848::Hide>' requested here}} + Hidden2<Hide, double, char> h2(1, 2); +} diff --git a/test/SemaTemplate/atomics.cpp b/test/SemaTemplate/atomics.cpp index 7165bbe591e9..e9fdc9de3d23 100644 --- a/test/SemaTemplate/atomics.cpp +++ b/test/SemaTemplate/atomics.cpp @@ -6,3 +6,11 @@ template<typename T> T f(T* value) { } int g(long long* x) { return f(x); } int g(int* x) { return f(x); } + +namespace PR11320 { + template<typename T> + void g(unsigned *x) { + __sync_bool_compare_and_swap(x, 1, 4); + } + void h() { g<int>(0); } +} diff --git a/test/SemaTemplate/canonical-expr-type-0x.cpp b/test/SemaTemplate/canonical-expr-type-0x.cpp index 94ae360b43ef..d7379eadab1a 100644 --- a/test/SemaTemplate/canonical-expr-type-0x.cpp +++ b/test/SemaTemplate/canonical-expr-type-0x.cpp @@ -2,15 +2,24 @@ void f(); -// FIXME: would like to refer to the first function parameter in these test, -// but that won't work (yet). - // Test typeof(expr) canonicalization template<typename T, T N> -void f0(T x, decltype(f(N)) y) { } // expected-note{{previous}} +void f0(T x, decltype(f(N, x)) y) { } // expected-note{{previous}} template<typename T, T N> -void f0(T x, decltype((f)(N)) y) { } +void f0(T x, decltype((f)(N, x)) y) { } template<typename U, U M> -void f0(U u, decltype(f(M))) { } // expected-error{{redefinition}} +void f0(U u, decltype(f(M, u))) { } // expected-error{{redefinition}} + +// PR12438: Test sizeof...() canonicalization +template<int> struct N {}; + +template<typename...T> +N<sizeof...(T)> f1() {} // expected-note{{previous}} + +template<typename, typename...T> +N<sizeof...(T)> f1() {} + +template<class...U> +N<sizeof...(U)> f1() {} // expected-error{{redefinition}} diff --git a/test/SemaTemplate/class-template-ctor-initializer.cpp b/test/SemaTemplate/class-template-ctor-initializer.cpp index 81a5e2b9c662..44bb4bda791e 100644 --- a/test/SemaTemplate/class-template-ctor-initializer.cpp +++ b/test/SemaTemplate/class-template-ctor-initializer.cpp @@ -49,7 +49,7 @@ namespace PR7259 { int main (void) { - Final final(); + Final final; return 0; } } diff --git a/test/SemaTemplate/class-template-decl.cpp b/test/SemaTemplate/class-template-decl.cpp index 2e84e93ead97..ec4e0163855c 100644 --- a/test/SemaTemplate/class-template-decl.cpp +++ b/test/SemaTemplate/class-template-decl.cpp @@ -74,3 +74,24 @@ namespace PR8001 { Foo<int>::Bar<int> y(x); } } + +namespace rdar9676205 { + template <unsigned, class _Tp> class tuple_element; + + template <class _T1, class _T2> class pair; + + template <class _T1, class _T2> + class tuple_element<0, pair<_T1, _T2> > + { + template <class _Tp> + struct X + { + template <class _Up, bool = X<_Up>::value> + struct Y + : public X<_Up>, + public Y<_Up> + { }; + }; + }; +} + diff --git a/test/SemaTemplate/class-template-spec.cpp b/test/SemaTemplate/class-template-spec.cpp index 07a5e2982c7f..f9015b37ea09 100644 --- a/test/SemaTemplate/class-template-spec.cpp +++ b/test/SemaTemplate/class-template-spec.cpp @@ -86,7 +86,7 @@ namespace N { template<> struct N::B<int> { }; // okay -template<> struct N::B<float> { }; // expected-warning{{originally}} +template<> struct N::B<float> { }; // expected-warning{{C++11 extension}} namespace M { template<> struct ::N::B<short> { }; // expected-error{{class template specialization of 'B' not in a namespace enclosing 'N'}} @@ -109,3 +109,13 @@ Foo<int> x; // Template template parameters template<template<class T> class Wibble> class Wibble<int> { }; // expected-error{{cannot specialize a template template parameter}} + +namespace rdar9676205 { + template<typename T> + struct X { + template<typename U> + struct X<U*> { // expected-error{{explicit specialization of 'X' in class scope}} + }; + }; + +} diff --git a/test/SemaTemplate/constexpr-instantiate.cpp b/test/SemaTemplate/constexpr-instantiate.cpp new file mode 100644 index 000000000000..2f9fe0e4855b --- /dev/null +++ b/test/SemaTemplate/constexpr-instantiate.cpp @@ -0,0 +1,77 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +namespace UseBeforeDefinition { + struct A { + template<typename T> static constexpr T get() { return T(); } + // ok, not a constant expression. + int n = get<int>(); + }; + + // ok, constant expression. + constexpr int j = A::get<int>(); + + template<typename T> constexpr int consume(T); + // ok, not a constant expression. + const int k = consume(0); // expected-note {{here}} + + template<typename T> constexpr int consume(T) { return 0; } + // ok, constant expression. + constexpr int l = consume(0); + + constexpr int m = k; // expected-error {{constant expression}} expected-note {{initializer of 'k'}} +} + +namespace IntegralConst { + template<typename T> constexpr T f(T n) { return n; } + enum E { + v = f(0), w = f(1) // ok + }; + static_assert(w == 1, ""); + + char arr[f('x')]; // ok + static_assert(sizeof(arr) == 'x', ""); +} + +namespace ConvertedConst { + template<typename T> constexpr T f(T n) { return n; } + int f() { + switch (f()) { + case f(4): return 0; + } + return 1; + } +} + +namespace OverloadResolution { + template<typename T> constexpr T f(T t) { return t; } + + template<int n> struct S { }; + + template<typename T> auto g(T t) -> S<f(sizeof(T))> &; + char &f(...); + + template<typename T> auto h(T t[f(sizeof(T))]) -> decltype(&*t) { + return t; + } + + S<4> &k = g(0); + int *p, *q = h(p); +} + +namespace DataMember { + template<typename T> struct S { static const int k; }; + const int n = S<int>::k; // expected-note {{here}} + template<typename T> const int S<T>::k = 0; + constexpr int m = S<int>::k; // ok + constexpr int o = n; // expected-error {{constant expression}} expected-note {{initializer of 'n'}} +} + +namespace Reference { + const int k = 5; + template<typename T> struct S { + static volatile int &r; + }; + template<typename T> volatile int &S<T>::r = const_cast<volatile int&>(k); + constexpr int n = const_cast<int&>(S<int>::r); + static_assert(n == 5, ""); +} diff --git a/test/SemaTemplate/crash-10438657.cpp b/test/SemaTemplate/crash-10438657.cpp new file mode 100644 index 000000000000..2ee64bdfcdbb --- /dev/null +++ b/test/SemaTemplate/crash-10438657.cpp @@ -0,0 +1,15 @@ +// RUN: not %clang_cc1 -fsyntax-only %s 2> %t +// RUN: FileCheck %s < %t +// CHECK: 10 errors +template<typename _CharT> +class collate : public locale::facet { + +protected: +virtual ~collate() {} + class wxObject; + class __attribute__ ((visibility("default"))) wxGDIRefData + : public wxObjectRefData {}; + class __attribute__ ((visibility("default"))) wxGDIObject : public wxObject { \ + public: + virtual bool IsOk() const { + return m_refData && static_cast<wxGDIRefData *>(m_refData)->IsOk(); diff --git a/test/SemaTemplate/deduction-crash.cpp b/test/SemaTemplate/deduction-crash.cpp index fb23eda5bb9d..cf3899f5eda7 100644 --- a/test/SemaTemplate/deduction-crash.cpp +++ b/test/SemaTemplate/deduction-crash.cpp @@ -2,7 +2,7 @@ // Note that the error count below doesn't matter. We just want to // make sure that the parser doesn't crash. -// CHECK: 14 errors +// CHECK: 13 errors // PR7511 template<a> diff --git a/test/SemaTemplate/delegating-constructors.cpp b/test/SemaTemplate/delegating-constructors.cpp index d82343402b74..e177b50375f0 100644 --- a/test/SemaTemplate/delegating-constructors.cpp +++ b/test/SemaTemplate/delegating-constructors.cpp @@ -15,4 +15,17 @@ namespace PR10457 { void f() { string s("hello"); } + + struct Foo { + Foo(int) { } + + + template <typename T> + Foo(T, int i) : Foo(i) { } +}; + + void test_Foo() + { + Foo f(1, 1); + } } diff --git a/test/SemaTemplate/enum-forward.cpp b/test/SemaTemplate/enum-forward.cpp index 3a4f05c0baa4..b25c21fc4635 100644 --- a/test/SemaTemplate/enum-forward.cpp +++ b/test/SemaTemplate/enum-forward.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -fms-extensions %s +// RUN: %clang_cc1 -fsyntax-only -fms-compatibility %s template<typename T> struct X { diff --git a/test/SemaTemplate/explicit-instantiation.cpp b/test/SemaTemplate/explicit-instantiation.cpp index 63016fd71568..13d76befe289 100644 --- a/test/SemaTemplate/explicit-instantiation.cpp +++ b/test/SemaTemplate/explicit-instantiation.cpp @@ -94,6 +94,14 @@ namespace PR7622 { template<typename,typename> struct basic_streambuf{friend bob<>()}; // expected-error{{unknown type name 'bob'}} \ - // expected-error{{ expected member name or ';' after declaration specifiers}} + // expected-error{{expected member name or ';' after declaration specifiers}} template struct basic_streambuf<int>; } + +// Test that we do not crash. +class TC1 { + class TC2 { + template // FIXME: error here. + void foo() { } + }; +}; diff --git a/test/SemaTemplate/friend-template.cpp b/test/SemaTemplate/friend-template.cpp index d1284de35f18..9c95fa0151c1 100644 --- a/test/SemaTemplate/friend-template.cpp +++ b/test/SemaTemplate/friend-template.cpp @@ -224,3 +224,22 @@ namespace friend_type_template_no_tag { }; template struct S<int>; } + +namespace PR10660 { + struct A { + template <> friend class B; // expected-error{{extraneous 'template<>' in declaration of class 'B'}} + }; +} + +namespace rdar11147355 { + template <class T> + struct A { + template <class U> class B; + template <class S> template <class U> friend class A<S>::B; + }; + + template <class S> template <class U> class A<S>::B { + }; + + A<double>::B<double> ab; +} diff --git a/test/SemaTemplate/friend.cpp b/test/SemaTemplate/friend.cpp index 99685f2396cf..e78a067ef8fa 100644 --- a/test/SemaTemplate/friend.cpp +++ b/test/SemaTemplate/friend.cpp @@ -28,6 +28,6 @@ namespace PR6770 { template <class T> void f() { friend class f; // expected-error{{'friend' used outside of class}} - friend class f1; // expected-error{{ 'friend' used outside of class}} + friend class f1; // expected-error{{'friend' used outside of class}} } } diff --git a/test/SemaTemplate/instantiate-complete.cpp b/test/SemaTemplate/instantiate-complete.cpp index 4b27da7349f9..68d5ae3cfb48 100644 --- a/test/SemaTemplate/instantiate-complete.cpp +++ b/test/SemaTemplate/instantiate-complete.cpp @@ -28,7 +28,6 @@ void test_subscript(X<double> *ptr1, X<int(int)> *ptr2, int i) { void test_arith(X<signed char> *ptr1, X<unsigned char> *ptr2, X<char(char)> *ptr3, X<short(short)> *ptr4) { (void)(ptr1 + 5); - // FIXME: if I drop the ')' after void, below, it still parses (!) (void)(5 + ptr2); (void)(ptr3 + 5); // expected-note{{in instantiation of template class 'X<char (char)>' requested here}} (void)(5 + ptr4); // expected-note{{in instantiation of template class 'X<short (short)>' requested here}} @@ -145,4 +144,3 @@ namespace PR8425 { BaseT<int> bt(ft); } } - diff --git a/test/SemaTemplate/instantiate-declref-ice.cpp b/test/SemaTemplate/instantiate-declref-ice.cpp index 0f3c08b05620..49b1b63f5152 100644 --- a/test/SemaTemplate/instantiate-declref-ice.cpp +++ b/test/SemaTemplate/instantiate-declref-ice.cpp @@ -31,4 +31,4 @@ struct X1 { template<typename T> const unsigned X1<T>::value = sizeof(T); -int array3[X1<int>::value == sizeof(int)? 1 : -1]; // expected-error{{variable length array declaration not allowed at file scope}} +int array3[X1<int>::value == sizeof(int)? 1 : -1]; diff --git a/test/SemaTemplate/instantiate-expr-1.cpp b/test/SemaTemplate/instantiate-expr-1.cpp index 896437488d68..9395117e9ce4 100644 --- a/test/SemaTemplate/instantiate-expr-1.cpp +++ b/test/SemaTemplate/instantiate-expr-1.cpp @@ -34,7 +34,7 @@ void test_BitfieldMinus() { template<int I, int J> struct BitfieldDivide { - int bitfield : I / J; // expected-error{{expression is not an integer constant expression}} \ + int bitfield : I / J; // expected-error{{expression is not an integral constant expression}} \ // expected-note{{division by zero}} }; @@ -167,8 +167,15 @@ namespace PR6424 { new X(); // expected-note{{instantiation of}} } }; - + template void Y2<3>::f(); + + template<typename T> + void rdar10283928(int count) { + (void)new char[count](); + } + + template void rdar10283928<int>(int); } namespace PR10864 { diff --git a/test/SemaTemplate/instantiate-expr-4.cpp b/test/SemaTemplate/instantiate-expr-4.cpp index 9483f9b28366..d95ccfecd9b5 100644 --- a/test/SemaTemplate/instantiate-expr-4.cpp +++ b/test/SemaTemplate/instantiate-expr-4.cpp @@ -282,6 +282,16 @@ template struct ArrowMemRef0<ArrowWrapper<MemIntFunc*>, int (*)(int)>; template struct ArrowMemRef0<ArrowWrapper<MemInt*>, float&>; // expected-note{{instantiation}} template struct ArrowMemRef0<ArrowWrapper<ArrowWrapper<MemInt*> >, int&>; +struct UnresolvedMemRefArray { + int f(int); + int f(char); +}; +UnresolvedMemRefArray Arr[10]; +template<typename U> int UnresolvedMemRefArrayT(U u) { + return Arr->f(u); +} +template int UnresolvedMemRefArrayT<int>(int); + // FIXME: we should be able to return a MemInt without the reference! MemInt &createMemInt(int); diff --git a/test/SemaTemplate/instantiate-expr-5.cpp b/test/SemaTemplate/instantiate-expr-5.cpp index 6cdedda4d880..13b7eae21fd4 100644 --- a/test/SemaTemplate/instantiate-expr-5.cpp +++ b/test/SemaTemplate/instantiate-expr-5.cpp @@ -6,7 +6,7 @@ int y() { return x<int>(1); } namespace PR5880 { template<typename T> struct A { - static const int a = __builtin_offsetof(T, a.array[5].m); // expected-error{{error: no member named 'a' in 'HasM'}} + static const int a = __builtin_offsetof(T, a.array[5].m); // expected-error{{no member named 'a' in 'HasM'}} }; struct HasM { float m; diff --git a/test/SemaTemplate/instantiate-function-1.cpp b/test/SemaTemplate/instantiate-function-1.cpp index 5406fbcd1baf..ceef27437748 100644 --- a/test/SemaTemplate/instantiate-function-1.cpp +++ b/test/SemaTemplate/instantiate-function-1.cpp @@ -194,7 +194,7 @@ template struct IndirectGoto0<int>; // expected-note{{instantiation}} template<typename T> struct TryCatch0 { void f() { try { - } catch (T t) { // expected-warning{{incomplete type}} \ + } catch (T t) { // expected-error{{incomplete type}} \ // expected-error{{abstract class}} } catch (...) { } diff --git a/test/SemaTemplate/instantiate-member-class.cpp b/test/SemaTemplate/instantiate-member-class.cpp index c67eb4022a47..bb6427670c3e 100644 --- a/test/SemaTemplate/instantiate-member-class.cpp +++ b/test/SemaTemplate/instantiate-member-class.cpp @@ -118,3 +118,25 @@ namespace AliasTagDef { int m = F<int>::S().g(); int n = F<int>::U().g(); } + +namespace rdar10397846 { + template<int I> struct A + { + struct B + { + struct C { C() { int *ptr = I; } }; // expected-error{{cannot initialize a variable of type 'int *' with an rvalue of type 'int'}} + }; + }; + + template<int N> void foo() + { + class A<N>::B::C X; // expected-note{{in instantiation of member function}} + int A<N+1>::B::C::*member = 0; + } + + void bar() + { + foo<0>(); + foo<1>(); // expected-note{{in instantiation of function template}} + } +} diff --git a/test/SemaTemplate/instantiate-self.cpp b/test/SemaTemplate/instantiate-self.cpp new file mode 100644 index 000000000000..cfe902509f7f --- /dev/null +++ b/test/SemaTemplate/instantiate-self.cpp @@ -0,0 +1,89 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +// Check that we deal with cases where the instantiation of a class template +// recursively requires the instantiation of the same template. +namespace test1 { + template<typename T> struct A { + struct B { // expected-note {{not complete until the closing '}'}} + B b; // expected-error {{has incomplete type 'test1::A<int>::B'}} + }; + B b; // expected-note {{in instantiation of}} + }; + A<int> a; // expected-note {{in instantiation of}} +} + +namespace test2 { + template<typename T> struct A { + struct B { + struct C {}; + char c[1 + C()]; // expected-error {{invalid operands to binary expression}} + friend constexpr int operator+(int, C) { return 4; } + }; + B b; // expected-note {{in instantiation of}} + }; + A<int> a; // expected-note {{in instantiation of}} +} + +namespace test3 { + // PR12317 + template<typename T> struct A { + struct B { + enum { Val = 1 }; + char c[1 + Val]; // ok + }; + B b; + }; + A<int> a; +} + +namespace test4 { + template<typename T> struct M { typedef int type; }; + template<typename T> struct A { + struct B { // expected-note {{not complete until the closing '}'}} + int k[typename A<typename M<T>::type>::B().k[0] + 1]; // expected-error {{incomplete type}} + }; + B b; // expected-note {{in instantiation of}} + }; + A<int> a; // expected-note {{in instantiation of}} +} + +// FIXME: PR12298: Recursive constexpr function template instantiation leads to +// stack overflow. +#if 0 +namespace test5 { + template<typename T> struct A { + constexpr T f(T k) { return g(k); } + constexpr T g(T k) { + return k ? f(k-1)+1 : 0; + } + }; + // This should be accepted. + constexpr int x = A<int>().f(5); +} + +namespace test6 { + template<typename T> constexpr T f(T); + template<typename T> constexpr T g(T t) { + typedef int arr[f(T())]; + return t; + } + template<typename T> constexpr T f(T t) { + typedef int arr[g(T())]; + return t; + } + // This should be ill-formed. + int n = f(0); +} + +namespace test7 { + template<typename T> constexpr T g(T t) { + return t; + } + template<typename T> constexpr T f(T t) { + typedef int arr[g(T())]; + return t; + } + // This should be accepted. + int n = f(0); +} +#endif diff --git a/test/SemaTemplate/instantiate-sizeof.cpp b/test/SemaTemplate/instantiate-sizeof.cpp new file mode 100644 index 000000000000..00d63d0c2fe5 --- /dev/null +++ b/test/SemaTemplate/instantiate-sizeof.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +// Make sure we handle contexts correctly with sizeof +template<typename T> void f(T n) { + int buffer[n]; + [] { int x = sizeof(sizeof(buffer)); }(); +} +int main() { + f<int>(1); +} diff --git a/test/SemaTemplate/instantiate-static-var.cpp b/test/SemaTemplate/instantiate-static-var.cpp index d2b0459ccc58..f309f29eafab 100644 --- a/test/SemaTemplate/instantiate-static-var.cpp +++ b/test/SemaTemplate/instantiate-static-var.cpp @@ -2,7 +2,7 @@ template<typename T, T Divisor> class X { public: - static const T value = 10 / Divisor; // expected-error{{in-class initializer is not a constant expression}} + static const T value = 10 / Divisor; // expected-error{{in-class initializer for static data member is not a constant expression}} }; int array1[X<int, 2>::value == 5? 1 : -1]; @@ -114,4 +114,3 @@ namespace PR6449 { template class X1<char>; } - diff --git a/test/SemaTemplate/instantiate-typeof.cpp b/test/SemaTemplate/instantiate-typeof.cpp new file mode 100644 index 000000000000..92873cb4b0b6 --- /dev/null +++ b/test/SemaTemplate/instantiate-typeof.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +// Make sure we correctly treat __typeof as potentially-evaluated when appropriate +template<typename T> void f(T n) { + int buffer[n]; // expected-note {{declared here}} + [] { __typeof(buffer) x; }(); // expected-error {{variable 'buffer' with variably modified type cannot be captured in a lambda expression}} +} +int main() { + f<int>(1); // expected-note {{in instantiation}} +} diff --git a/test/SemaTemplate/instantiation-depth.cpp b/test/SemaTemplate/instantiation-depth.cpp index a2b9d2eb1513..8e1b80368d18 100644 --- a/test/SemaTemplate/instantiation-depth.cpp +++ b/test/SemaTemplate/instantiation-depth.cpp @@ -1,10 +1,12 @@ // RUN: %clang_cc1 -fsyntax-only -verify -ftemplate-depth 5 -ftemplate-backtrace-limit 4 %s +// RUN: %clang -fsyntax-only -Xclang -verify -ftemplate-depth-5 -ftemplate-backtrace-limit=4 %s +// RUN: %clang -fsyntax-only -Xclang -verify -ftemplate-depth=5 -ftemplate-backtrace-limit=4 %s template<typename T> struct X : X<T*> { }; \ // expected-error{{recursive template instantiation exceeded maximum depth of 5}} \ // expected-note 3 {{instantiation of template class}} \ // expected-note {{skipping 2 contexts in backtrace}} \ -// expected-note {{use -ftemplate-depth-N to increase recursive template instantiation depth}} +// expected-note {{use -ftemplate-depth=N to increase recursive template instantiation depth}} void test() { (void)sizeof(X<int>); // expected-note {{instantiation of template class}} diff --git a/test/SemaTemplate/instantiation-order.cpp b/test/SemaTemplate/instantiation-order.cpp new file mode 100644 index 000000000000..e058a5bc1873 --- /dev/null +++ b/test/SemaTemplate/instantiation-order.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +// From core issue 1227. + +template <class T> struct A { using X = typename T::X; }; // expected-error {{no members}} +template <class T> typename T::X f(typename A<T>::X); +template <class T> void f(...) {} +template <class T> auto g(typename A<T>::X) -> typename T::X; // expected-note {{here}} expected-note {{substituting}} +template <class T> void g(...) {} + +void h() +{ + f<int>(0); // ok, SFINAE in return type + g<int>(0); // not ok, substitution inside A<int> is a hard error +} diff --git a/test/SemaTemplate/member-access-ambig.cpp b/test/SemaTemplate/member-access-ambig.cpp index bf190435ecd5..f8a01d5fff2a 100644 --- a/test/SemaTemplate/member-access-ambig.cpp +++ b/test/SemaTemplate/member-access-ambig.cpp @@ -33,3 +33,13 @@ void X::g() // expected-error{{expected '(' for function-style cast}} \ // expected-error{{expected expression}} } + +namespace PR11134 { + template<typename Derived> class A; + template<typename Derived> class B : A<Derived> { + typedef A<Derived> Base; + using Base::member; + int member; + }; +} + diff --git a/test/SemaTemplate/member-template-access-expr.cpp b/test/SemaTemplate/member-template-access-expr.cpp index dbd27c456c51..c95b57d4b4fd 100644 --- a/test/SemaTemplate/member-template-access-expr.cpp +++ b/test/SemaTemplate/member-template-access-expr.cpp @@ -60,7 +60,7 @@ struct X1 { void test_X1(X1 x1) { float *fp1 = x1.f1<>(17); - float *fp2 = x1.f1<int>(3.14); + float *fp2 = x1.f1<int>(3.14); // expected-warning {{implicit conversion turns literal floating-point number into integer}} int *ip1 = x1.f1(17); float *ip2 = x1.f1(3.14); diff --git a/test/SemaTemplate/ms-if-exists.cpp b/test/SemaTemplate/ms-if-exists.cpp new file mode 100644 index 000000000000..04f4a6362361 --- /dev/null +++ b/test/SemaTemplate/ms-if-exists.cpp @@ -0,0 +1,68 @@ +// RUN: %clang_cc1 -fms-extensions -std=c++11 %s -verify + +struct Nontemplate { + typedef int type; +}; + +template<typename T> +struct X { + __if_exists(Nontemplate::type) { + typedef Nontemplate::type type; + } + + __if_exists(Nontemplate::value) { + typedef Nontemplate::value type2; + } + + __if_not_exists(Nontemplate::value) { + typedef int type3; + } + + __if_exists(T::X) { // expected-warning{{dependent __if_exists declarations are ignored}} + typedef T::X type4; + } +}; + +X<int>::type i1; +X<int>::type2 i2; // expected-error{{no type named 'type2' in 'X<int>'}} +X<int>::type3 i3; +X<int>::type4 i4; // expected-error{{no type named 'type4' in 'X<int>'}} + +struct HasFoo { + void foo(); +}; +struct HasBar { + void bar(int); + void bar(float); +}; + +template<typename T> +void f(T t) { + __if_exists(T::foo) { + { } + t.foo(); + } + + __if_not_exists(T::bar) { + int *i = t; // expected-error{{no viable conversion from 'HasFoo' to 'int *'}} + { } + } + + int array2[] = {
+ 0,
+ __if_exists(T::bar) {2, }// expected-warning{{dependent __if_exists declarations are ignored}}
+ 3
+ };
+} + +template void f(HasFoo); // expected-note{{in instantiation of function template specialization 'f<HasFoo>' requested here}} +template void f(HasBar); + +template<typename T, typename ...Ts> +void g(T, Ts...) { + __if_exists(T::operator Ts) { // expected-error{{__if_exists name contains unexpanded parameter pack 'Ts'}} + } + + __if_not_exists(Ts::operator T) { // expected-error{{__if_not_exists name contains unexpanded parameter pack 'Ts'}} + } +} diff --git a/test/SemaTemplate/ms-lookup-template-base-classes.cpp b/test/SemaTemplate/ms-lookup-template-base-classes.cpp index 910fa37e80d8..2c422dc7e3f7 100644 --- a/test/SemaTemplate/ms-lookup-template-base-classes.cpp +++ b/test/SemaTemplate/ms-lookup-template-base-classes.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fms-extensions -fsyntax-only -verify %s +// RUN: %clang_cc1 -fms-compatibility -fsyntax-only -verify %s template <class T> @@ -28,4 +28,118 @@ void test() b.z(3); } +namespace lookup_dependent_bases_id_expr { +template<class T> class A { +public: + int var; +}; + + +template<class T> +class B : public A<T> { +public: + void f() { + var = 3; + } +}; + +template class B<int>; + +} + + + +namespace lookup_dependent_base_class_static_function { + +template <class T> +class A { +public: + static void static_func();// expected-note {{must qualify identifier to find this declaration in dependent base class}} + void func();// expected-note {{must qualify identifier to find this declaration in dependent base class}} +}; + + +template <class T> +class B : public A<T> { +public: + static void z2(){ + static_func(); // expected-warning {{use of identifier 'static_func' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}} + func(); // expected-warning {{use of identifier 'func' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}} expected-error {{call to non-static member function without an object argument}} + } +}; +template class B<int>; // expected-note {{requested here}} + +} + + + +namespace lookup_dependent_base_class_default_argument { + +template<class T> +class A { +public: + static int f1(); // expected-note {{must qualify identifier to find this declaration in dependent base class}} + int f2(); // expected-note {{must qualify identifier to find this declaration in dependent base class}} +}; + +template<class T> +class B : public A<T> { +public: + void g1(int p = f1());// expected-warning {{use of identifier 'f1' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}} + void g2(int p = f2());// expected-warning {{use of identifier 'f2' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}} expected-error {{call to non-static member function without an object argument}} +}; + +void foo() +{ + B<int> b; + b.g1(); // expected-note {{required here}} + b.g2(); // expected-note {{required here}} +} + +} + + +namespace lookup_dependent_base_class_friend { + +template <class T> +class B { +public: + static void g(); // expected-note {{must qualify identifier to find this declaration in dependent base class}} +}; + +template <class T> +class A : public B<T> { +public: + friend void foo(A<T> p){ + g(); // expected-warning {{use of identifier 'g' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}} + } +}; + +int main2() +{ + A<int> a; + foo(a); // expected-note {{requested here}} +} + +} + + +namespace lookup_dependent_base_no_typo_correction { + +class C { +public: + int m_hWnd; +}; + +template <class T> +class A : public T { +public: + void f(int hWnd) { + m_hWnd = 1; + } +}; + +template class A<C>; + +} diff --git a/test/SemaTemplate/nested-incomplete-class.cpp b/test/SemaTemplate/nested-incomplete-class.cpp new file mode 100644 index 000000000000..a4bfccb8d279 --- /dev/null +++ b/test/SemaTemplate/nested-incomplete-class.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -fsyntax-only %s + +template <typename T> +struct foo { + struct bar; + + bar fn() { + // Should not get errors about bar being incomplete here. + bar b = bar(1, 2); + return b; + } +}; + +template <typename T> +struct foo<T>::bar { + bar(int, int); +}; + +void fn() { + foo<int>().fn(); +} diff --git a/test/SemaTemplate/nested-template.cpp b/test/SemaTemplate/nested-template.cpp index ab647aa22675..7849bae4d571 100644 --- a/test/SemaTemplate/nested-template.cpp +++ b/test/SemaTemplate/nested-template.cpp @@ -142,3 +142,16 @@ namespace PR10896 { f.foo(); } } + +namespace PR10924 { + template< class Topology, class ctype > + struct ReferenceElement + { + }; + + template< class Topology, class ctype > + template< int codim > + class ReferenceElement< Topology, ctype > :: BaryCenterArray // expected-error{{out-of-line definition of 'BaryCenterArray' does not match any declaration in 'ReferenceElement<Topology, ctype>'}} + { + }; +} diff --git a/test/SemaTemplate/pragma-ms_struct.cpp b/test/SemaTemplate/pragma-ms_struct.cpp new file mode 100644 index 000000000000..f04dc5ccae45 --- /dev/null +++ b/test/SemaTemplate/pragma-ms_struct.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -triple i686-apple-osx10.7.0 %s + +#pragma ms_struct on + +// <rdar://problem/10791194> +template<int x> struct foo { + long long a; + int b; +}; +extern int arr[sizeof(foo<0>) == 16 ? 1 : -1]; diff --git a/test/SemaTemplate/qualified-id.cpp b/test/SemaTemplate/qualified-id.cpp index 29eab89d84f5..64dff1ce2353 100644 --- a/test/SemaTemplate/qualified-id.cpp +++ b/test/SemaTemplate/qualified-id.cpp @@ -45,3 +45,12 @@ namespace PR6063 { detail::f(a, b); } } + +namespace PR12291 { + template <typename T> + class Outer2 { + template <typename V> + template <typename W> + class Outer2<V>::Inner; // expected-error{{nested name specifier 'Outer2<V>::' for declaration does not refer into a class, class template or class template partial specialization}} + }; +} diff --git a/test/SemaTemplate/resolve-single-template-id.cpp b/test/SemaTemplate/resolve-single-template-id.cpp index b9833d8609ef..0c9bacca3edd 100644 --- a/test/SemaTemplate/resolve-single-template-id.cpp +++ b/test/SemaTemplate/resolve-single-template-id.cpp @@ -41,7 +41,7 @@ int main() *oneT<int>; // expected-warning {{expression result unused}} *two; //expected-error {{reference to overloaded function could not be resolved; did you mean to call it with no arguments?}} expected-error {{indirection requires pointer operand}} *twoT<int>; //expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}} - !oneT<int>; // expected-warning {{expression result unused}} + !oneT<int>; // expected-warning {{expression result unused}} expected-warning {{address of function 'oneT<int>' will always evaluate to 'true'}} expected-note {{prefix with the address-of operator to silence this warning}} +oneT<int>; // expected-warning {{expression result unused}} -oneT<int>; //expected-error {{invalid argument type}} oneT<int> == 0; // expected-warning {{equality comparison result unused}} \ @@ -53,7 +53,7 @@ int main() int i = (int) (false ? (void (*)(int))twoT<int> : oneT<int>); //expected-error {{incompatible operand}} (twoT<int>) == oneT<int>; //expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}} {{cannot resolve overloaded function 'twoT' from context}} - bool b = oneT<int>; + bool b = oneT<int>; // expected-warning {{address of function 'oneT<int>' will always evaluate to 'true'}} expected-note {{prefix with the address-of operator to silence this warning}} void (*p)() = oneT<int>; test<oneT<int> > ti; void (*u)(int) = oneT<int>; diff --git a/test/SemaTemplate/temp_arg_template.cpp b/test/SemaTemplate/temp_arg_template.cpp index 9c34089e61f7..c9ce1b694363 100644 --- a/test/SemaTemplate/temp_arg_template.cpp +++ b/test/SemaTemplate/temp_arg_template.cpp @@ -54,3 +54,9 @@ namespace N { void f0( Y<int,1> y){ 1 << y; } // expected-note{{in instantiation of function template specialization 'N::operator<<<Y, int, 1>' requested here}} } + +// PR12179 +template <typename Primitive, template <Primitive...> class F> // expected-warning {{variadic templates are a C++11 extension}} +struct unbox_args { + typedef typename Primitive::template call<F> x; +}; diff --git a/test/SemaTemplate/temp_class_spec_neg.cpp b/test/SemaTemplate/temp_class_spec_neg.cpp index 6b129a5369fb..be5fbb154ea8 100644 --- a/test/SemaTemplate/temp_class_spec_neg.cpp +++ b/test/SemaTemplate/temp_class_spec_neg.cpp @@ -9,7 +9,7 @@ namespace N { } template<typename T> -struct N::M::A<T*> { }; // expected-warning{{originally}} +struct N::M::A<T*> { }; // expected-warning{{C++11 extension}} // C++ [temp.class.spec]p9 // bullet 1 diff --git a/test/SemaTemplate/temp_explicit.cpp b/test/SemaTemplate/temp_explicit.cpp index 76244c25e824..80c90d0cfcd2 100644 --- a/test/SemaTemplate/temp_explicit.cpp +++ b/test/SemaTemplate/temp_explicit.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -pedantic -Wc++0x-compat %s +// RUN: %clang_cc1 -fsyntax-only -verify -pedantic -Wc++11-compat %s // // Tests explicit instantiation of templates. template<typename T, typename U = T> class X0 { }; @@ -80,7 +80,7 @@ struct X5 { void f(T&); }; - struct Inner2 { + struct Inner2 { // expected-note {{here}} struct VeryInner { void g(T*); // expected-error 2{{pointer to a reference}} }; @@ -98,7 +98,7 @@ void f4(X5<float&>::Inner2); template struct X5<float&>::Inner2; // expected-note{{instantiation}} namespace N3 { - template struct N2::X5<int>::Inner2; + template struct N2::X5<int>::Inner2; // expected-warning {{explicit instantiation of 'Inner2' not in a namespace enclosing 'N2'}} } struct X6 { @@ -147,5 +147,5 @@ namespace N2 { template struct X7<double>; // expected-warning{{must occur in namespace}} - template struct X9<float>; // expected-warning{{must occur in the global}} + template struct X9<float>; // expected-warning{{must occur at global scope}} } diff --git a/test/SemaTemplate/temp_explicit_cxx0x.cpp b/test/SemaTemplate/temp_explicit_cxx0x.cpp index 9d6dc80b5b0a..e37fcd7c6a5d 100644 --- a/test/SemaTemplate/temp_explicit_cxx0x.cpp +++ b/test/SemaTemplate/temp_explicit_cxx0x.cpp @@ -18,7 +18,7 @@ template struct ::N1::Inner::X1<float>; namespace N2 { using namespace N1; - template struct X0<double>; // expected-error{{not in a namespace enclosing}} + template struct X0<double>; // expected-error{{must occur in namespace 'N1'}} template struct X2<float>; // expected-error{{at global scope}} } diff --git a/test/SemaTemplate/template-id-expr.cpp b/test/SemaTemplate/template-id-expr.cpp index de8d7f6c91a4..4416f92723ad 100644 --- a/test/SemaTemplate/template-id-expr.cpp +++ b/test/SemaTemplate/template-id-expr.cpp @@ -82,3 +82,17 @@ struct Y0 { x = this->template f4(0); // expected-error {{assigning to 'int' from incompatible type 'void'}} } }; + +struct A { + template<int I> + struct B { + static void b1(); + }; +}; + +template<int I> +void f5() { + A::template B<I>::template b1(); // expected-error {{'b1' following the 'template' keyword does not refer to a template}} +} + +template void f5<0>(); // expected-note {{in instantiation of function template specialization 'f5<0>' requested here}} diff --git a/test/SemaTemplate/template-id-printing.cpp b/test/SemaTemplate/template-id-printing.cpp index fcd4974a7611..047589b1ce43 100644 --- a/test/SemaTemplate/template-id-printing.cpp +++ b/test/SemaTemplate/template-id-printing.cpp @@ -11,3 +11,131 @@ void g() { // CHECK: N::f<double> void (*fp)(int) = N::f<double>; } + + +// (NNS qualified) DeclRefExpr. +namespace DRE { + +template <typename T> +void foo(); + +void test() { + // CHECK: DRE::foo<int>; + DRE::foo<int>; + // CHECK: DRE::template foo<int>; + DRE::template foo<int>; + // CHECK: DRE::foo<int>(); + DRE::foo<int>(); + // CHECK: DRE::template foo<int>(); + DRE::template foo<int>(); +} + +} // namespace DRE + + +// MemberExpr. +namespace ME { + +struct S { + template <typename T> + void mem(); +}; + +void test() { + S s; + // CHECK: s.mem<int>(); + s.mem<int>(); + // CHECK: s.template mem<int>(); + s.template mem<int>(); +} + +} // namespace ME + + +// UnresolvedLookupExpr. +namespace ULE { + +template <typename T> +int foo(); + +template <typename T> +void test() { + // CHECK: ULE::foo<T>; + ULE::foo<T>; + // CHECK: ULE::template foo<T>; + ULE::template foo<T>; +} + +} // namespace ULE + + +// UnresolvedMemberExpr. +namespace UME { + +struct S { + template <typename T> + void mem(); +}; + +template <typename U> +void test() { + S s; + // CHECK: s.mem<U>(); + s.mem<U>(); + // CHECK: s.template mem<U>(); + s.template mem<U>(); +} + +} // namespace UME + + +// DependentScopeDeclRefExpr. +namespace DSDRE { + +template <typename T> +struct S; + +template <typename T> +void test() { + // CHECK: S<T>::foo; + S<T>::foo; + // CHECK: S<T>::template foo; + S<T>::template foo; + // CHECK: S<T>::template foo<>; + S<T>::template foo<>; + // CHECK: S<T>::template foo<T>; + S<T>::template foo<T>; +} + +} // namespace DSDRE + + +// DependentScopeMemberExpr. +namespace DSME { + +template <typename T> +struct S; + +template <typename T> +void test() { + S<T> s; + // CHECK: s.foo; + s.foo; + // CHECK: s.template foo; + s.template foo; + // CHECK: s.template foo<>; + s.template foo<>; + // CHECK: s.template foo<T>; + s.template foo<T>; +} + +} // namespace DSME + +namespace DSDRE_withImplicitTemplateArgs { + +template <typename T> void foo() { + // CHECK: T::template bar(); + T::template bar(); +} + +} // namespace DSDRE_withImplicitTemplateArgs |