18fbe78f6SDaniel Dunbar // RUN: %clang_cc1 -fsyntax-only -verify %s
2f98d9b60SDouglas Gregor namespace N {
3f98d9b60SDouglas Gregor   struct Outer {
4f98d9b60SDouglas Gregor     struct Inner {
5f98d9b60SDouglas Gregor       template<typename T>
6f98d9b60SDouglas Gregor       struct InnerTemplate {
7f98d9b60SDouglas Gregor         struct VeryInner {
8f98d9b60SDouglas Gregor           typedef T type;
9f98d9b60SDouglas Gregor 
10f98d9b60SDouglas Gregor           static enum K1 { K1Val = sizeof(T) } Kind1;
117a74938fSDouglas Gregor           static enum { K2Val = sizeof(T)*2 } Kind2;
12b8006fafSDouglas Gregor           enum { K3Val = sizeof(T)*2 } Kind3;
13f98d9b60SDouglas Gregor 
fooN::Outer::Inner::InnerTemplate::VeryInner14f98d9b60SDouglas Gregor           void foo() {
15f98d9b60SDouglas Gregor             K1 k1 = K1Val;
16f98d9b60SDouglas Gregor             Kind1 = K1Val;
17f98d9b60SDouglas Gregor             Outer::Inner::InnerTemplate<type>::VeryInner::Kind2 = K2Val;
18b8006fafSDouglas Gregor             Kind3 = K3Val;
19b8006fafSDouglas Gregor           }
20b8006fafSDouglas Gregor 
21b8006fafSDouglas Gregor           struct UeberInner {
barN::Outer::Inner::InnerTemplate::VeryInner::UeberInner22b8006fafSDouglas Gregor             void bar() {
23b8006fafSDouglas Gregor               K1 k1 = K1Val;
24b8006fafSDouglas Gregor               Kind1 = K1Val;
25b8006fafSDouglas Gregor               Outer::Inner::InnerTemplate<type>::VeryInner::Kind2 = K2Val;
26cd3a0979SDouglas Gregor 
27cd3a0979SDouglas Gregor               InnerTemplate t;
28cd3a0979SDouglas Gregor               InnerTemplate<type> t2;
29f98d9b60SDouglas Gregor             }
30f98d9b60SDouglas Gregor           };
31f98d9b60SDouglas Gregor         };
32f98d9b60SDouglas Gregor       };
33f98d9b60SDouglas Gregor     };
34b8006fafSDouglas Gregor   };
35f98d9b60SDouglas Gregor }
36f98d9b60SDouglas Gregor 
37f98d9b60SDouglas Gregor typedef int INT;
38f98d9b60SDouglas Gregor template struct N::Outer::Inner::InnerTemplate<INT>::VeryInner;
39f5af3584SDouglas Gregor template struct N::Outer::Inner::InnerTemplate<INT>::UeberInner; // expected-error{{no struct named 'UeberInner' in 'N::Outer::Inner::InnerTemplate<int>'}}
40e44a2adfSDouglas Gregor 
41e44a2adfSDouglas Gregor namespace N2 {
42e44a2adfSDouglas Gregor   struct Outer2 {
438157b07cSDouglas Gregor     template<typename T, typename U = T>
44e44a2adfSDouglas Gregor     struct Inner {
fooN2::Outer2::Inner45e44a2adfSDouglas Gregor       void foo() {
46e44a2adfSDouglas Gregor         enum { K1Val = sizeof(T) } k1;
478157b07cSDouglas Gregor         enum K2 { K2Val = sizeof(T)*2 } k2a;
48e44a2adfSDouglas Gregor 
498157b07cSDouglas Gregor         K2 k2b = K2Val;
508157b07cSDouglas Gregor 
518157b07cSDouglas Gregor         struct S { T x, y; } s1;
528157b07cSDouglas Gregor         struct { U x, y; } s2;
538157b07cSDouglas Gregor         s1.x = s2.x; // expected-error{{incompatible}}
548157b07cSDouglas Gregor 
558157b07cSDouglas Gregor         typedef T type;
568157b07cSDouglas Gregor         type t2 = s1.x;
57e44a2adfSDouglas Gregor 
5805580944SDouglas Gregor         typedef struct { T z; } type2;
5905580944SDouglas Gregor         type2 t3 = { s1.x };
6005580944SDouglas Gregor 
61e44a2adfSDouglas Gregor         Inner i1;
62e44a2adfSDouglas Gregor         i1.foo();
63e44a2adfSDouglas Gregor         Inner<T> i2;
64e44a2adfSDouglas Gregor         i2.foo();
65e44a2adfSDouglas Gregor       }
66e44a2adfSDouglas Gregor     };
67e44a2adfSDouglas Gregor   };
68e44a2adfSDouglas Gregor }
69e44a2adfSDouglas Gregor 
708157b07cSDouglas Gregor template struct N2::Outer2::Inner<float>;
718157b07cSDouglas Gregor template struct N2::Outer2::Inner<int*, float*>; // expected-note{{instantiation}}
72c95a1fa7SDouglas Gregor 
73c95a1fa7SDouglas Gregor // Test dependent pointer-to-member expressions.
74c95a1fa7SDouglas Gregor template<typename T>
75c95a1fa7SDouglas Gregor struct smart_ptr {
76c95a1fa7SDouglas Gregor   struct safe_bool {
77c95a1fa7SDouglas Gregor     int member;
78c95a1fa7SDouglas Gregor   };
79c95a1fa7SDouglas Gregor 
operator int safe_bool::*smart_ptr80c95a1fa7SDouglas Gregor   operator int safe_bool::*() const {
81c95a1fa7SDouglas Gregor     return ptr? &safe_bool::member : 0;
82c95a1fa7SDouglas Gregor   }
83c95a1fa7SDouglas Gregor 
84c95a1fa7SDouglas Gregor   T* ptr;
85c95a1fa7SDouglas Gregor };
86c95a1fa7SDouglas Gregor 
test_smart_ptr(smart_ptr<int> p)87c95a1fa7SDouglas Gregor void test_smart_ptr(smart_ptr<int> p) {
88c95a1fa7SDouglas Gregor   if (p) { }
89c95a1fa7SDouglas Gregor }
90ce410662SJohn McCall 
91ce410662SJohn McCall // PR5517
92ce410662SJohn McCall namespace test0 {
93ce410662SJohn McCall   template <int K> struct X {
Xtest0::X94ce410662SJohn McCall     X() { extern void x(); }
95ce410662SJohn McCall   };
g()96ce410662SJohn McCall   void g() { X<2>(); }
97ce410662SJohn McCall }
98815039afSJohn McCall 
99815039afSJohn McCall // <rdar://problem/8302161>
100815039afSJohn McCall namespace test1 {
f(T const & t)101815039afSJohn McCall   template <typename T> void f(T const &t) {
102815039afSJohn McCall     union { char c; T t_; };
103815039afSJohn McCall     c = 'a'; // <- this shouldn't silently fail to instantiate
104815039afSJohn McCall     T::foo(); // expected-error {{has no members}}
105815039afSJohn McCall   }
106815039afSJohn McCall   template void f(int const &); // expected-note {{requested here}}
107815039afSJohn McCall }
108*f623c962SRichard Smith 
109*f623c962SRichard Smith namespace test2 {
f()110*f623c962SRichard Smith   template<typename T> void f() {
111*f623c962SRichard Smith     T::error; // expected-error {{no member}}
112*f623c962SRichard Smith   }
g()113*f623c962SRichard Smith   void g() {
114*f623c962SRichard Smith     // This counts as an odr-use, so should trigger the instantiation of f<int>.
115*f623c962SRichard Smith     (void)&f<int>; // expected-note {{here}}
116*f623c962SRichard Smith   }
117*f623c962SRichard Smith }
118