13573b2c84372d9484296fa658f5276f6c09acb92Daniel Dunbar// RUN: %clang_cc1 -fsyntax-only -verify %s
2d909756aa3da61a79dbaf3592e565278b12041c3Douglas Gregor
3c55a11bb31cf885afdc8e62f560f356bc0fdd4a9Douglas Gregor// Test class template partial specializations of member templates.
4d909756aa3da61a79dbaf3592e565278b12041c3Douglas Gregortemplate<typename T>
5d909756aa3da61a79dbaf3592e565278b12041c3Douglas Gregorstruct X0 {
6d909756aa3da61a79dbaf3592e565278b12041c3Douglas Gregor  template<typename U> struct Inner0 {
7d909756aa3da61a79dbaf3592e565278b12041c3Douglas Gregor    static const unsigned value = 0;
8d909756aa3da61a79dbaf3592e565278b12041c3Douglas Gregor  };
9d909756aa3da61a79dbaf3592e565278b12041c3Douglas Gregor
10d909756aa3da61a79dbaf3592e565278b12041c3Douglas Gregor  template<typename U> struct Inner0<U*> {
11d909756aa3da61a79dbaf3592e565278b12041c3Douglas Gregor    static const unsigned value = 1;
12d909756aa3da61a79dbaf3592e565278b12041c3Douglas Gregor  };
13d909756aa3da61a79dbaf3592e565278b12041c3Douglas Gregor};
14d909756aa3da61a79dbaf3592e565278b12041c3Douglas Gregor
15d909756aa3da61a79dbaf3592e565278b12041c3Douglas Gregortemplate<typename T> template<typename U>
16d909756aa3da61a79dbaf3592e565278b12041c3Douglas Gregorstruct X0<T>::Inner0<const U*> {
17d909756aa3da61a79dbaf3592e565278b12041c3Douglas Gregor  static const unsigned value = 2;
18d909756aa3da61a79dbaf3592e565278b12041c3Douglas Gregor};
19d909756aa3da61a79dbaf3592e565278b12041c3Douglas Gregor
20c55a11bb31cf885afdc8e62f560f356bc0fdd4a9Douglas Gregorint array0[X0<int>::Inner0<int>::value == 0? 1 : -1];
21c55a11bb31cf885afdc8e62f560f356bc0fdd4a9Douglas Gregorint array1[X0<int>::Inner0<int*>::value == 1? 1 : -1];
22c55a11bb31cf885afdc8e62f560f356bc0fdd4a9Douglas Gregorint array2[X0<int>::Inner0<const int*>::value == 2? 1 : -1];
23c55a11bb31cf885afdc8e62f560f356bc0fdd4a9Douglas Gregor
24c55a11bb31cf885afdc8e62f560f356bc0fdd4a9Douglas Gregor// Make sure we can provide out-of-line class template partial specializations
25c55a11bb31cf885afdc8e62f560f356bc0fdd4a9Douglas Gregor// for member templates (and instantiate them).
26c55a11bb31cf885afdc8e62f560f356bc0fdd4a9Douglas Gregortemplate<class T> struct A {
27c55a11bb31cf885afdc8e62f560f356bc0fdd4a9Douglas Gregor  struct C {
28c55a11bb31cf885afdc8e62f560f356bc0fdd4a9Douglas Gregor    template<class T2> struct B;
29c55a11bb31cf885afdc8e62f560f356bc0fdd4a9Douglas Gregor  };
30c55a11bb31cf885afdc8e62f560f356bc0fdd4a9Douglas Gregor};
31c55a11bb31cf885afdc8e62f560f356bc0fdd4a9Douglas Gregor
32c55a11bb31cf885afdc8e62f560f356bc0fdd4a9Douglas Gregor// partial specialization of A<T>::C::B<T2>
33c55a11bb31cf885afdc8e62f560f356bc0fdd4a9Douglas Gregortemplate<class T> template<class T2> struct A<T>::C::B<T2*> { };
34c55a11bb31cf885afdc8e62f560f356bc0fdd4a9Douglas Gregor
35c55a11bb31cf885afdc8e62f560f356bc0fdd4a9Douglas GregorA<short>::C::B<int*> absip;
36c55a11bb31cf885afdc8e62f560f356bc0fdd4a9Douglas Gregor
37c55a11bb31cf885afdc8e62f560f356bc0fdd4a9Douglas Gregor// Check for conflicts during template instantiation.
38c55a11bb31cf885afdc8e62f560f356bc0fdd4a9Douglas Gregortemplate<typename T, typename U>
39c55a11bb31cf885afdc8e62f560f356bc0fdd4a9Douglas Gregorstruct Outer {
40c55a11bb31cf885afdc8e62f560f356bc0fdd4a9Douglas Gregor  template<typename X, typename Y> struct Inner;
41c55a11bb31cf885afdc8e62f560f356bc0fdd4a9Douglas Gregor  template<typename Y> struct Inner<T, Y> {}; // expected-note{{previous}}
42c55a11bb31cf885afdc8e62f560f356bc0fdd4a9Douglas Gregor  template<typename Y> struct Inner<U, Y> {}; // expected-error{{cannot be redeclared}}
43c55a11bb31cf885afdc8e62f560f356bc0fdd4a9Douglas Gregor};
44c55a11bb31cf885afdc8e62f560f356bc0fdd4a9Douglas Gregor
45c55a11bb31cf885afdc8e62f560f356bc0fdd4a9Douglas GregorOuter<int, int> outer; // expected-note{{instantiation}}
46c55a11bb31cf885afdc8e62f560f356bc0fdd4a9Douglas Gregor
47c55a11bb31cf885afdc8e62f560f356bc0fdd4a9Douglas Gregor// Test specialization of class template partial specialization members.
48c55a11bb31cf885afdc8e62f560f356bc0fdd4a9Douglas Gregortemplate<> template<typename Z>
49c55a11bb31cf885afdc8e62f560f356bc0fdd4a9Douglas Gregorstruct X0<float>::Inner0<Z*> {
50c55a11bb31cf885afdc8e62f560f356bc0fdd4a9Douglas Gregor  static const unsigned value = 3;
51c55a11bb31cf885afdc8e62f560f356bc0fdd4a9Douglas Gregor};
52c55a11bb31cf885afdc8e62f560f356bc0fdd4a9Douglas Gregor
53c55a11bb31cf885afdc8e62f560f356bc0fdd4a9Douglas Gregorint array3[X0<float>::Inner0<int>::value == 0? 1 : -1];
54c55a11bb31cf885afdc8e62f560f356bc0fdd4a9Douglas Gregorint array4[X0<float>::Inner0<int*>::value == 3? 1 : -1];
55c55a11bb31cf885afdc8e62f560f356bc0fdd4a9Douglas Gregorint array5[X0<float>::Inner0<const int*>::value == 2? 1 : -1];
565e2891651c53c2a313b7d6f6321c405ed5a7d1e3Douglas Gregor
575e2891651c53c2a313b7d6f6321c405ed5a7d1e3Douglas Gregornamespace rdar8651930 {
585e2891651c53c2a313b7d6f6321c405ed5a7d1e3Douglas Gregor  template<typename OuterT>
595e2891651c53c2a313b7d6f6321c405ed5a7d1e3Douglas Gregor  struct Outer {
605e2891651c53c2a313b7d6f6321c405ed5a7d1e3Douglas Gregor    template<typename T, typename U>
615e2891651c53c2a313b7d6f6321c405ed5a7d1e3Douglas Gregor    struct Inner;
625e2891651c53c2a313b7d6f6321c405ed5a7d1e3Douglas Gregor
635e2891651c53c2a313b7d6f6321c405ed5a7d1e3Douglas Gregor    template<typename T>
645e2891651c53c2a313b7d6f6321c405ed5a7d1e3Douglas Gregor    struct Inner<T, T> {
655e2891651c53c2a313b7d6f6321c405ed5a7d1e3Douglas Gregor      static const bool value = true;
665e2891651c53c2a313b7d6f6321c405ed5a7d1e3Douglas Gregor    };
675e2891651c53c2a313b7d6f6321c405ed5a7d1e3Douglas Gregor
685e2891651c53c2a313b7d6f6321c405ed5a7d1e3Douglas Gregor    template<typename T, typename U>
695e2891651c53c2a313b7d6f6321c405ed5a7d1e3Douglas Gregor    struct Inner {
705e2891651c53c2a313b7d6f6321c405ed5a7d1e3Douglas Gregor      static const bool value = false;
715e2891651c53c2a313b7d6f6321c405ed5a7d1e3Douglas Gregor    };
725e2891651c53c2a313b7d6f6321c405ed5a7d1e3Douglas Gregor  };
735e2891651c53c2a313b7d6f6321c405ed5a7d1e3Douglas Gregor
745e2891651c53c2a313b7d6f6321c405ed5a7d1e3Douglas Gregor  int array0[Outer<int>::Inner<int, int>::value? 1 : -1];
755e2891651c53c2a313b7d6f6321c405ed5a7d1e3Douglas Gregor  int array1[Outer<int>::Inner<int, float>::value? -1 : 1];
765e2891651c53c2a313b7d6f6321c405ed5a7d1e3Douglas Gregor}
77