167714230a191bc3c01f33378f34f34ef377991a6Douglas Gregor// RUN: %clang_cc1 -fsyntax-only -verify %s
28e8fb3be5bd78f0564444eca02b404566a5f3b5dAndy Gibbs// expected-no-diagnostics
367714230a191bc3c01f33378f34f34ef377991a6Douglas Gregor
467714230a191bc3c01f33378f34f34ef377991a6Douglas Gregor// Core issue 150: Template template parameters and default arguments
567714230a191bc3c01f33378f34f34ef377991a6Douglas Gregor
69a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregortemplate<typename T, typename U>
79a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregorstruct is_same {
89a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor  static const bool value = false;
99a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor};
109a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor
119a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregortemplate<typename T>
129a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregorstruct is_same<T, T> {
139a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor  static const bool value = true;
149a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor};
159a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor
1667714230a191bc3c01f33378f34f34ef377991a6Douglas Gregornamespace PR9353 {
1767714230a191bc3c01f33378f34f34ef377991a6Douglas Gregor  template<class _T, class Traits> class IM;
1867714230a191bc3c01f33378f34f34ef377991a6Douglas Gregor
1967714230a191bc3c01f33378f34f34ef377991a6Douglas Gregor  template <class T, class Trt,
2067714230a191bc3c01f33378f34f34ef377991a6Douglas Gregor            template<class _T, class Traits = int> class IntervalMap>
2167714230a191bc3c01f33378f34f34ef377991a6Douglas Gregor  void foo(IntervalMap<T,Trt>* m) { typedef IntervalMap<int> type; }
2267714230a191bc3c01f33378f34f34ef377991a6Douglas Gregor
2367714230a191bc3c01f33378f34f34ef377991a6Douglas Gregor  void f(IM<int, int>* m) { foo(m); }
2467714230a191bc3c01f33378f34f34ef377991a6Douglas Gregor}
259a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor
269a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregornamespace PR9400 {
279a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor  template<template <typename T, typename = T > class U> struct A
289a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor  {
299a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor    template<int> U<int> foo();
309a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor  };
319a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor
329a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor  template <typename T, typename = T>
339a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor  struct s {
349a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor  };
359a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor
369a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor  void f() {
379a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor    A<s> x;
389a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor    x.foo<2>();
399a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor  }
409a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor}
419a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor
429a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregornamespace MultiReplace {
439a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor  template<typename Z,
449a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor           template<typename T, typename U = T *, typename V = U const> class TT>
459a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor  struct X {
469a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor    typedef TT<Z> type;
479a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor  };
489a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor
499a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor  template<typename T, typename = int, typename = float>
509a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor  struct Y { };
519a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor
529a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor  int check0[is_same<X<int, Y>::type, Y<int, int*, int* const> >::value? 1 : -1];
539a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor}
549a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor
559a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregornamespace MultiReplacePartial {
569a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor  template<typename First, typename Z,
579a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor           template<typename T, typename U = T *, typename V = U const> class TT>
589a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor  struct X {
599a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor    typedef TT<Z> type;
609a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor  };
619a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor
629a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor  template<typename Z,
639a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor           template<typename T, typename U = T *, typename V = U const> class TT>
649a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor  struct X<int, Z, TT> {
659a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor    typedef TT<Z> type;
669a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor  };
679a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor
689a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor  template<typename T, typename = int, typename = float>
699a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor  struct Y { };
709a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor
719a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor  int check0[is_same<X<int, int, Y>::type, Y<int, int*, int* const> >::value? 1 : -1];
729a299e0575ce235f491014627c7267e2d2cd73deDouglas Gregor}
730b4bcb639a9aab9c466a9e6d6e61b3bd1bb36d68Douglas Gregor
740b4bcb639a9aab9c466a9e6d6e61b3bd1bb36d68Douglas Gregornamespace PR9016 {
750b4bcb639a9aab9c466a9e6d6e61b3bd1bb36d68Douglas Gregor  template<typename > struct allocator ;
760b4bcb639a9aab9c466a9e6d6e61b3bd1bb36d68Douglas Gregor  template<typename > struct less ;
770b4bcb639a9aab9c466a9e6d6e61b3bd1bb36d68Douglas Gregor
780b4bcb639a9aab9c466a9e6d6e61b3bd1bb36d68Douglas Gregor  template<class T, template<class> class Compare, class Default,
790b4bcb639a9aab9c466a9e6d6e61b3bd1bb36d68Douglas Gregor           template<class> class Alloc>
800b4bcb639a9aab9c466a9e6d6e61b3bd1bb36d68Douglas Gregor  struct interval_set { };
810b4bcb639a9aab9c466a9e6d6e61b3bd1bb36d68Douglas Gregor
820b4bcb639a9aab9c466a9e6d6e61b3bd1bb36d68Douglas Gregor  template <class X, template<class> class = less> struct interval_type_default {
830b4bcb639a9aab9c466a9e6d6e61b3bd1bb36d68Douglas Gregor    typedef X type;
840b4bcb639a9aab9c466a9e6d6e61b3bd1bb36d68Douglas Gregor  };
850b4bcb639a9aab9c466a9e6d6e61b3bd1bb36d68Douglas Gregor
860b4bcb639a9aab9c466a9e6d6e61b3bd1bb36d68Douglas Gregor  template <class T,
875875038f5c333b8bd013f62950281618d08e36a8Douglas Gregor            template<class _T, template<class> class Compare = PR9016::less,
880b4bcb639a9aab9c466a9e6d6e61b3bd1bb36d68Douglas Gregor                     class = typename interval_type_default<_T,Compare>::type,
890b4bcb639a9aab9c466a9e6d6e61b3bd1bb36d68Douglas Gregor                     template<class> class = allocator> class IntervalSet>
900b4bcb639a9aab9c466a9e6d6e61b3bd1bb36d68Douglas Gregor  struct ZZZ
910b4bcb639a9aab9c466a9e6d6e61b3bd1bb36d68Douglas Gregor  {
920b4bcb639a9aab9c466a9e6d6e61b3bd1bb36d68Douglas Gregor    IntervalSet<T> IntervalSetT;
930b4bcb639a9aab9c466a9e6d6e61b3bd1bb36d68Douglas Gregor  };
940b4bcb639a9aab9c466a9e6d6e61b3bd1bb36d68Douglas Gregor
95c494f77363f057dd8619fec4e885c4f80e3d1b66Douglas Gregor  template <class T,
965875038f5c333b8bd013f62950281618d08e36a8Douglas Gregor            template<class _T, template<class> class Compare = PR9016::less,
97c494f77363f057dd8619fec4e885c4f80e3d1b66Douglas Gregor                     class = typename interval_type_default<_T,Compare>::type,
98c494f77363f057dd8619fec4e885c4f80e3d1b66Douglas Gregor                     template<class> class = allocator> class IntervalSet>
99c494f77363f057dd8619fec4e885c4f80e3d1b66Douglas Gregor  void int40()
100c494f77363f057dd8619fec4e885c4f80e3d1b66Douglas Gregor  {
101c494f77363f057dd8619fec4e885c4f80e3d1b66Douglas Gregor    IntervalSet<T> IntervalSetT;
102c494f77363f057dd8619fec4e885c4f80e3d1b66Douglas Gregor  }
103c494f77363f057dd8619fec4e885c4f80e3d1b66Douglas Gregor
1040b4bcb639a9aab9c466a9e6d6e61b3bd1bb36d68Douglas Gregor  void test() {
1050b4bcb639a9aab9c466a9e6d6e61b3bd1bb36d68Douglas Gregor    ZZZ<int, interval_set> zzz;
106c494f77363f057dd8619fec4e885c4f80e3d1b66Douglas Gregor    int40<int, interval_set>();
1070b4bcb639a9aab9c466a9e6d6e61b3bd1bb36d68Douglas Gregor  }
1080b4bcb639a9aab9c466a9e6d6e61b3bd1bb36d68Douglas Gregor}
109