Implement support for C++0x alias templates.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130953 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp
new file mode 100644
index 0000000..5fc0fe0
--- /dev/null
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+struct A { };
+template<typename T> using X = A; // expected-note {{declared here}}
+struct X<int>* p2; // expected-error {{elaborated type refers to a type alias template}}
+
+
+template<typename T> using Id = T; // expected-note {{declared here}}
+template<template<typename> class F>
+struct Y {
+  struct F<int> i; // expected-error {{elaborated type refers to a type alias template}}
+};
+template struct Y<Id>; // expected-note {{requested here}}
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp
index 10184a0..8b278bf 100644
--- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp
@@ -1,10 +1,9 @@
 // RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
 
-// FIXME: when clang supports alias-declarations.
-#if 0
 using X = struct { // ok
 };
-#endif
+template<typename T> using Y = struct { // expected-error {{can not be defined in a type alias template}}
+};
 
 class K {
   virtual ~K();
diff --git a/test/CXX/temp/temp.decls/p3.cpp b/test/CXX/temp/temp.decls/p3.cpp
new file mode 100644
index 0000000..21c82e6
--- /dev/null
+++ b/test/CXX/temp/temp.decls/p3.cpp
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+template<typename T> using A = int;
+template<typename T> using A<T*> = char; // expected-error {{partial specialization of alias templates is not permitted}}
+template<> using A<char> = char; // expected-error {{explicit specialization of alias templates is not permitted}}
+template using A<char> = char; // expected-error {{explicit instantiation of alias templates is not permitted}}
+// Best guess as to what the user was trying to do: missing template<>.
+using A<char> = char; // expected-error {{partial specialization of alias templates is not permitted}}
diff --git a/test/CXX/temp/temp.decls/temp.alias/p1.cpp b/test/CXX/temp/temp.decls/temp.alias/p1.cpp
new file mode 100644
index 0000000..80079b3
--- /dev/null
+++ b/test/CXX/temp/temp.decls/temp.alias/p1.cpp
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+template<typename T> using U = T;
+
+// The name of the alias template is a template-name.
+U<char> x;
+void f(U<int>);
+typedef U<U<U<U<int>>>> I;
diff --git a/test/CXX/temp/temp.decls/temp.alias/p2.cpp b/test/CXX/temp/temp.decls/temp.alias/p2.cpp
new file mode 100644
index 0000000..e145727
--- /dev/null
+++ b/test/CXX/temp/temp.decls/temp.alias/p2.cpp
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+template<typename T> using U = T;
+
+using I = U<U<U<U<int>>>>;
+using I = int;
+
+template<typename A, typename B> using Fst = A;
+template<typename A, typename B> using Snd = B;
+
+using I = Fst<Snd<char,int>,double>;
+
+namespace StdExample {
+  // Prerequisites for example.
+  template<class T, class A> struct vector { /* ... */ };
+
+
+  template<class T> struct Alloc {};
+  template<class T> using Vec = vector<T, Alloc<T>>;
+  Vec<int> v;
+
+  template<class T>
+    void process(Vec<T>& v) // expected-note {{previous definition is here}}
+    { /* ... */ }
+
+  template<class T>
+    void process(vector<T, Alloc<T>>& w) // expected-error {{redefinition of 'process'}}
+    { /* ... */ }
+
+  template<template<class> class TT>
+    void f(TT<int>); // expected-note {{candidate template ignored}}
+
+  template<template<class,class> class TT>
+    void g(TT<int, Alloc<int>>);
+
+  int h() {
+    f(v); // expected-error {{no matching function for call to 'f'}}
+    g(v); // OK: TT = vector
+  }
+
+
+  // v's type is same as vector<int, Alloc<int>>.
+  using VTest = vector<int, Alloc<int>>;
+  using VTest = decltype(v);
+}
diff --git a/test/CXX/temp/temp.decls/temp.alias/p3.cpp b/test/CXX/temp/temp.decls/temp.alias/p3.cpp
new file mode 100644
index 0000000..2e9e55c
--- /dev/null
+++ b/test/CXX/temp/temp.decls/temp.alias/p3.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+// The example given in the standard (this is rejected for other reasons anyway).
+template<class T> struct A;
+template<class T> using B = typename A<T>::U; // expected-error {{no type named 'U' in 'A<T>'}}
+template<class T> struct A {
+  typedef B<T> U; // expected-note {{in instantiation of template type alias 'B' requested here}}
+};
+B<short> b;
+
+template<typename T> using U = int;
+// FIXME: This is illegal, but probably only because CWG1044 missed this paragraph.
+template<typename T> using U = U<T>;
diff --git a/test/CXX/temp/temp.param/p10-0x.cpp b/test/CXX/temp/temp.param/p10-0x.cpp
new file mode 100644
index 0000000..bc7e616
--- /dev/null
+++ b/test/CXX/temp/temp.param/p10-0x.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s 
+
+template<typename> struct Y1;
+template<typename, int> struct Y2;
+
+template<class T1, class T2 = int> using B2 = T1;
+template<class T1 = int, class T2> using B2 = T1;
+
+template<template<class> class F, template<class> class G = Y1> using B2t = F<G<int>>;
+template<template<class> class F = Y2, template<class> class G> using B2t = F<G<int>>;
+
+template<int N, int M = 5> using B2n = Y2<int, N + M>;
+template<int N = 5, int M> using B2n = Y2<int, N + M>;
diff --git a/test/CXX/temp/temp.param/p11-0x.cpp b/test/CXX/temp/temp.param/p11-0x.cpp
index 0bf4341..10a4438 100644
--- a/test/CXX/temp/temp.param/p11-0x.cpp
+++ b/test/CXX/temp/temp.param/p11-0x.cpp
@@ -1,29 +1,48 @@
 // RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
 
-// If a template-parameter of a class template has a default
-// template-argument, each subsequent template-parameter shall either
-// have a default template-argument supplied or be a template
-// parameter pack.
+// If a template-parameter of a class template or alias template has a default
+// template-argument, each subsequent template-parameter shall either have a
+// default template-argument supplied or be a template parameter pack.
 template<typename> struct vector;
 
+template<typename T = int, typename> struct X3t; // expected-error{{template parameter missing a default argument}} expected-note{{previous default template argument defined here}}
+template<typename T = int, typename> using A3t = int; // expected-error{{template parameter missing a default argument}} expected-note{{previous default template argument defined here}}
+template<int V = 0, int> struct X3nt; // expected-error{{template parameter missing a default argument}} expected-note{{previous default template argument defined here}}
+template<int V = 0, int> using A3nt = int; // expected-error{{template parameter missing a default argument}} expected-note{{previous default template argument defined here}}
+template<template<class> class M = vector, template<class> class> struct X3tt; // expected-error{{template parameter missing a default argument}} expected-note{{previous default template argument defined here}}
+template<template<class> class M = vector, template<class> class> using A3tt = int; // expected-error{{template parameter missing a default argument}} expected-note{{previous default template argument defined here}}
+
 template<typename T = int, typename ...Types> struct X2t;
+template<typename T = int, typename ...Types> using A2t = X2t<T, Types...>;
 template<int V = 0, int ...Values> struct X2nt;
+template<int V = 0, int ...Values> using A2nt = X2nt<V, Values...>;
 template<template<class> class M = vector, template<class> class... Metas>
   struct X2tt;
+template<template<class> class M = vector, template<class> class... Metas>
+  using A2tt = X2tt<M, Metas...>;
 
-// If a template-parameter of a primary class template is a template
-// parameter pack, it shall be the last template-parameter .
+// If a template-parameter of a primary class template or alias template is a
+// template parameter pack, it shall be the last template-parameter.
 template<typename ...Types, // expected-error{{template parameter pack must be the last template parameter}}
          int After>
 struct X0t;
+template<typename ...Types, // expected-error{{template parameter pack must be the last template parameter}}
+         int After>
+using A0t = int;
 
 template<int ...Values, // expected-error{{template parameter pack must be the last template parameter}}
          int After>
 struct X0nt;
+template<int ...Values, // expected-error{{template parameter pack must be the last template parameter}}
+         int After>
+using A0nt = int;
 
 template<template<typename> class ...Templates, // expected-error{{template parameter pack must be the last template parameter}}
          int After>
 struct X0tt;
+template<template<typename> class ...Templates, // expected-error{{template parameter pack must be the last template parameter}}
+         int After>
+using A0tt = int;
 
 // [ Note: These are not requirements for function templates or class
 // template partial specializations because template arguments can be
diff --git a/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p1.cpp b/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p1.cpp
new file mode 100644
index 0000000..1d1d350
--- /dev/null
+++ b/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p1.cpp
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s 
+
+// Examples from CWG1056.
+namespace Example1 {
+  template<class T> struct A;
+  template<class T> using B = A<T>;
+
+  template<class T> struct A {
+    struct C {};
+    B<T>::C bc; // ok, B<T> is the current instantiation.
+  };
+
+  template<class T> struct A<A<T>> {
+    struct C {};
+    B<B<T>>::C bc; // ok, B<B<T>> is the current instantiation.
+  };
+
+  template<class T> struct A<A<A<T>>> {
+    struct C {};
+    B<B<T>>::C bc; // expected-error {{missing 'typename'}}
+  };
+}
+
+namespace Example2 {
+  template<class T> struct A {
+    void g();
+  };
+  template<class T> using B = A<T>;
+  template<class T> void B<T>::g() {} // ok.
+}
diff --git a/test/CXX/temp/temp.type/p1-0x.cpp b/test/CXX/temp/temp.type/p1-0x.cpp
new file mode 100644
index 0000000..c22af22
--- /dev/null
+++ b/test/CXX/temp/temp.type/p1-0x.cpp
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s
+
+namespace Old {
+  template<template<class> class TT> struct X { };
+  template<class> struct Y { };
+  template<class T> using Z = Y<T>;
+  X<Y> y;
+  X<Z> z;
+
+  using SameType = decltype(y); // expected-note {{here}}
+  using SameType = decltype(z); // expected-error {{different types}}
+}
+
+namespace New {
+  template<class T> struct X { };
+  template<class> struct Y { };
+  template<class T> using Z = Y<T>;
+  X<Y<int>> y;
+  X<Z<int>> z;
+
+  using SameType = decltype(y);
+  using SameType = decltype(z); // ok
+}
diff --git a/test/CodeGenCXX/mangle-alias-template.cpp b/test/CodeGenCXX/mangle-alias-template.cpp
new file mode 100644
index 0000000..2020a0a
--- /dev/null
+++ b/test/CodeGenCXX/mangle-alias-template.cpp
@@ -0,0 +1,41 @@
+// RUN: %clang_cc1 -std=c++0x -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s
+
+template<typename T> struct alloc {};
+template<typename T> using Alloc = alloc<T>;
+template<typename T, typename A = Alloc<T>> struct vector {};
+
+template<typename T> using Vec = vector<T>;
+
+template<typename T> void f(Vec<T> v);
+template<typename T> void g(T);
+
+template<template<typename> class F> void h(F<int>);
+
+// CHECK: define void @_Z1zv(
+void z() {
+  vector<int> VI;
+  f(VI);
+  // CHECK: call void @_Z1fIiEv6vectorIT_5allocIS1_EE(
+
+  Vec<double> VD;
+  g(VD);
+  // CHECK: call void @_Z1gI6vectorId5allocIdEEEvT_(
+
+  h<Vec>(VI);
+  // CHECK: call void @_Z1hI3VecEvT_IiE(
+
+  Alloc<int> AC;
+  h(AC);
+  // CHECK: call void @_Z1hI5allocEvT_IiE(
+
+  h<Alloc>(AC);
+  // CHECK: call void @_Z1hI5AllocEvT_IiE(
+
+  Vec<char> VC;
+  g<Vec<char>>(VC);
+  // CHECK: call void @_Z1gI6vectorIc5allocIcEEEvT_(
+
+  Vec<Vec<int>> VVI;
+  g(VVI);
+  // CHECK: call void @_Z1gI6vectorIS0_Ii5allocIiEES1_IS3_EEEvT_(
+}
diff --git a/test/CodeGenCXX/mangle-unnameable-conversions.cpp b/test/CodeGenCXX/mangle-unnameable-conversions.cpp
new file mode 100644
index 0000000..2132eff
--- /dev/null
+++ b/test/CodeGenCXX/mangle-unnameable-conversions.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -std=c++0x -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s
+
+template<typename T> using id = T;
+struct S {
+  template<typename T, int N>
+    operator id<T[N]>&();
+  template<typename T, typename U>
+    operator id<T (U::*)()>() const;
+};
+
+void f() {
+  int (&a)[42] = S(); // CHECK: @_ZN1ScvRAT0__T_IiLi42EEEv(
+  char (S::*fp)() = S(); // CHECK: @_ZNK1ScvMT0_FT_vEIcS_EEv(
+};
diff --git a/test/Lexer/has_feature_cxx0x.cpp b/test/Lexer/has_feature_cxx0x.cpp
index 57949e3..57354f8 100644
--- a/test/Lexer/has_feature_cxx0x.cpp
+++ b/test/Lexer/has_feature_cxx0x.cpp
@@ -155,3 +155,12 @@
 
 // CHECK-0X: has_override_control
 // CHECK-NO-0X: no_override_control
+
+#if __has_feature(cxx_alias_templates)
+int has_alias_templates();
+#else
+int no_alias_templates();
+#endif
+
+// CHECK-0X: has_alias_templates
+// CHECK-NO-0X: no_alias_templates
diff --git a/test/PCH/cxx-alias-decl.cpp b/test/PCH/cxx-alias-decl.cpp
new file mode 100644
index 0000000..e30311c
--- /dev/null
+++ b/test/PCH/cxx-alias-decl.cpp
@@ -0,0 +1,20 @@
+// Test this without pch.
+// RUN: %clang_cc1 -x c++ -std=c++0x -include %S/cxx-alias-decl.h -fsyntax-only -emit-llvm -o - %s
+
+// Test with pch.
+// RUN: %clang_cc1 -x c++ -std=c++0x -emit-pch -o %t %S/cxx-alias-decl.h
+// RUN: %clang_cc1 -x c++ -std=c++0x -include-pch %t -fsyntax-only -emit-llvm -o - %s 
+
+template struct T<S>;
+C<A>::A<char> a;
+
+using T1 = decltype(a);
+using T1 = D<int, char>;
+
+using T2 = B<A>;
+using T2 = S;
+
+using A = int;
+template<typename U> using B = S;
+template<typename U> using C = T<U>;
+template<typename U, typename V> using D = typename T<U>::template A<V>;
diff --git a/test/PCH/cxx-alias-decl.h b/test/PCH/cxx-alias-decl.h
new file mode 100644
index 0000000..26bc716
--- /dev/null
+++ b/test/PCH/cxx-alias-decl.h
@@ -0,0 +1,11 @@
+// Header for PCH test cxx-alias-decl.cpp
+
+struct S {};
+template<typename U> struct T {
+  template<typename V> using A = T<V>;
+};
+
+using A = int;
+template<typename U> using B = S;
+template<typename U> using C = T<U>;
+template<typename U, typename V> using D = typename T<U>::template A<V>;
diff --git a/test/SemaCXX/alias-template.cpp b/test/SemaCXX/alias-template.cpp
new file mode 100644
index 0000000..f29a932
--- /dev/null
+++ b/test/SemaCXX/alias-template.cpp
@@ -0,0 +1,147 @@
+// RUN: %clang_cc1 -verify -std=c++0x %s
+
+namespace RedeclAliasTypedef {
+  template<typename U> using T = int;
+  template<typename U> using T = int;
+  template<typename U> using T = T<U>;
+}
+
+namespace IllegalTypeIds {
+  template<typename U> using A = void(int n = 0); // expected-error {{default arguments can only be specified for parameters in a function declaration}}
+  template<typename U> using B = inline void(int n); // expected-error {{type name does not allow function specifier}}
+  template<typename U> using C = virtual void(int n); // expected-error {{type name does not allow function specifier}}
+  template<typename U> using D = explicit void(int n); // expected-error {{type name does not allow function specifier}}
+  template<typename U> using E = void(int n) throw(); // expected-error {{exception specifications are not allowed in type aliases}}
+  // FIXME: this is illegal; we incorrectly accept it for typedefs too.
+  template<typename U> using F = void(*)(int n) &&; // expected-err
+  template<typename U> using G = __thread void(int n); // expected-error {{type name does not allow storage class to be specified}}
+
+  template<typename U> using H = void(int n); // ok
+  template<typename U> using I = void(int n) &&; // ok
+}
+
+namespace IllegalSyntax {
+  template<typename Z> using ::T = void(int n); // expected-error {{name defined in alias declaration must be an identifier}}
+  template<typename Z> using operator int = void(int n); // expected-error {{name defined in alias declaration must be an identifier}}
+  template<typename Z> using typename U = void; // expected-error {{name defined in alias declaration must be an identifier}}
+  template<typename Z> using typename ::V = void(int n); // expected-error {{name defined in alias declaration must be an identifier}}
+  template<typename Z> using typename ::operator bool = void(int n); // expected-error {{name defined in alias declaration must be an identifier}}
+}
+
+namespace VariableLengthArrays {
+  template<typename Z> using T = int[42]; // ok
+
+  int n = 32;
+  template<typename Z> using T = int[n]; // expected-error {{variable length array declaration not allowed at file scope}}
+
+  const int m = 42;
+  template<typename Z> using U = int[m]; // expected-note {{previous definition}}
+  template<typename Z> using U = int[42]; // ok
+  template<typename Z> using U = int; // expected-error {{type alias template redefinition with different types ('int' vs 'int [42]')}}
+}
+
+namespace RedeclFunc {
+  int f(int, char**);
+  template<typename Z> using T = int;
+  T<char> f(int, char **); // ok
+}
+
+namespace LookupFilter {
+  namespace N { template<typename U> using S = int; }
+  using namespace N;
+  template<typename U> using S = S<U>*; // ok
+}
+
+namespace InFunctions {
+  template<typename...T> struct S0 {
+    template<typename Z> using U = T*; // expected-error {{declaration type contains unexpanded parameter pack 'T'}}
+    U<char> u;
+  };
+
+  template<typename Z> using T1 = int;
+  template<typename Z> using T2 = int[-1]; // expected-error {{array size is negative}}
+  template<typename...T> struct S3 { // expected-note {{template parameter is declared here}}
+    template<typename Z> using T = int; // expected-error {{declaration of 'T' shadows template parameter}}
+  };
+  template<typename Z> using Z = Z;
+}
+
+namespace ClassNameRedecl {
+  class C0 {
+    // FIXME: this diagnostic is pretty poor
+    template<typename U> using C0 = int; // expected-error {{name defined in alias declaration must be an identifier}}
+  };
+  class C1 {
+    // FIXME: this diagnostic is pretty poor
+    template<typename U> using C1 = C1; // expected-error {{name defined in alias declaration must be an identifier}}
+  };
+  class C2 {
+    template<typename U> using C0 = C1; // ok
+  };
+  template<typename...T> class C3 {
+    template<typename U> using f = T; // expected-error {{declaration type contains unexpanded parameter pack 'T'}}
+  };
+  template<typename T> class C4 { // expected-note {{template parameter is declared here}}
+    template<typename U> using T = int; // expected-error {{declaration of 'T' shadows template parameter}}
+  };
+  class C5 {
+    class c; // expected-note {{previous definition}}
+    template<typename U> using c = int; // expected-error {{redefinition of 'c' as different kind of symbol}}
+    class d; // expected-note {{previous definition}}
+    template<typename U> using d = d; // expected-error {{redefinition of 'd' as different kind of symbol}}
+  };
+  class C6 {
+    class c { template<typename U> using C6 = int; }; // ok
+  };
+}
+
+class CtorDtorName {
+  template<typename T> using X = CtorDtorName;
+  X<int>(); // expected-error {{expected member name}}
+  ~X<int>(); // expected-error {{destructor cannot be declared using a type alias}}
+};
+
+namespace TagName {
+  template<typename Z> using S = struct { int n; }; // expected-error {{can not be defined}}
+  template<typename Z> using T = class { int n; }; // expected-error {{can not be defined}}
+  template<typename Z> using U = enum { a, b, c }; // expected-error {{can not be defined}}
+  template<typename Z> using V = struct V { int n; }; // expected-error {{redefinition of 'V' as different kind of symbol}} \
+                                                         expected-error {{'TagName::V' can not be defined in a type alias template}} \
+                                                         expected-note {{previous definition is here}}
+}
+
+namespace StdExample {
+  template<typename T, typename U> struct pair;
+
+  template<typename T> using handler_t = void (*)(T);
+  extern handler_t<int> ignore;
+  extern void (*ignore)(int);
+  // FIXME: we recover as if cell is an undeclared variable. the diagnostics are terrible!
+  template<typename T> using cell = pair<T*, cell<T>*>; // expected-error {{use of undeclared identifier 'cell'}} \
+                                                           expected-error {{'T' does not refer to a value}} \
+                                                           expected-note {{declared here}} \
+                                                           expected-error {{expected ';' after alias declaration}}
+}
+
+namespace Access {
+  class C0 {
+    template<typename Z> using U = int; // expected-note {{declared private here}}
+  };
+  C0::U<int> v; // expected-error {{'U' is a private member}}
+  class C1 {
+  public:
+    template<typename Z> using U = int;
+  };
+  C1::U<int> w; // ok
+}
+
+namespace VoidArg {
+  template<typename Z> using V = void;
+  V<int> f(int); // ok
+  V<char> g(V<double>); // expected-error {{empty parameter list defined with a type alias of 'void' not allowed}}
+}
+
+namespace Curried {
+  template<typename T, typename U> struct S;
+  template<typename T> template<typename U> using SS = S<T, U>; // expected-error {{extraneous template parameter list in alias template declaration}}
+}
diff --git a/test/SemaCXX/attr-cxx0x.cpp b/test/SemaCXX/attr-cxx0x.cpp
index 40fe0e0..725f018 100644
--- a/test/SemaCXX/attr-cxx0x.cpp
+++ b/test/SemaCXX/attr-cxx0x.cpp
@@ -9,8 +9,13 @@
   int member [[align(8)]];
 };
 
+typedef char align_typedef [[align(8)]];
+template<typename T> using align_alias_template = align_typedef;
+
 static_assert(alignof(align_big) == alignof(int), "k's alignment is wrong");
 static_assert(alignof(align_small) == 1, "j's alignment is wrong");
 static_assert(alignof(align_multiple) == 8, "l's alignment is wrong");
 static_assert(alignof(align_member) == 8, "quuux's alignment is wrong");
 static_assert(sizeof(align_member) == 8, "quuux's size is wrong");
+static_assert(alignof(align_typedef) == 8, "typedef's alignment is wrong");
+static_assert(alignof(align_alias_template<int>) == 8, "alias template's alignment is wrong");
diff --git a/test/SemaCXX/dependent-types.cpp b/test/SemaCXX/dependent-types.cpp
index d9b5323..053e79b 100644
--- a/test/SemaCXX/dependent-types.cpp
+++ b/test/SemaCXX/dependent-types.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -fsyntax-only -pedantic -verify %s
+// RUN: %clang_cc1 -fsyntax-only -pedantic -verify -std=c++0x %s
+
+template<typename T> using U = int &;
 
 template<typename T, int Size> void f() {
   T x1;
@@ -7,4 +9,5 @@
   T x4[]; // expected-error{{needs an explicit size or an initializer}}
   T x5[Size];
   int x6[Size];
+  U<T> x7; // expected-error{{declaration of reference variable 'x7' requires an initializer}}
 }
diff --git a/test/SemaCXX/redeclared-alias-template.cpp b/test/SemaCXX/redeclared-alias-template.cpp
new file mode 100644
index 0000000..b368fcf
--- /dev/null
+++ b/test/SemaCXX/redeclared-alias-template.cpp
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s
+
+template<typename T> using A = int; // expected-note 2{{previous}}
+template<typename T> using A = char; // expected-error {{type alias template redefinition with different types ('char' vs 'int')}}
+template<typename T1, typename T2> using A = T1; // expected-error {{too many template parameters in template redeclaration}}
+
+template<typename T1, typename T2> using B = T1; // expected-note {{previous}}
+template<typename T2, typename T1> using B = T1; // expected-error {{type alias template redefinition with different types}}
+
+
+template<typename> struct S;
+template<template<typename> class F> using FInt = F<int>;
+template<typename X> using SXRInt = FInt<S<X>::template R>;
+template<typename X> using SXRInt = typename S<X>::template R<int>; // ok, redeclaration.
+
+template<template<typename> class> struct TT;
+
+namespace FilterLookup {
+  TT<A> f(); // expected-note {{previous declaration is here}}
+
+  template<typename> using A = int;
+  TT<A> f(); // expected-error {{functions that differ only in their return type cannot be overloaded}}
+}
diff --git a/test/SemaTemplate/alias-church-numerals.cpp b/test/SemaTemplate/alias-church-numerals.cpp
new file mode 100644
index 0000000..751cac7
--- /dev/null
+++ b/test/SemaTemplate/alias-church-numerals.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+template<template<template<typename> class, typename> class T, template<typename> class V> struct PartialApply {
+  template<typename W> using R = T<V, W>;
+};
+
+template<typename T> using Id = T;
+template<template<typename> class, typename X> using Zero = X;
+template<template<template<typename> class, typename> class N, template<typename> class F, typename X> using Succ = F<N<F,X>>;
+
+template<template<typename> class F, typename X> using One = Succ<Zero, F, X>;
+template<template<typename> class F, typename X> using Two = Succ<One, F, X>;
+
+template<template<template<typename> class, typename> class A,
+         template<template<typename> class, typename> class B,
+         template<typename> class F,
+         typename X> using Add = A<F, B<F, X>>;
+
+template<template<template<typename> class, typename> class A,
+         template<template<typename> class, typename> class B,
+         template<typename> class F,
+         typename X> using Mul = A<PartialApply<B,F>::template R, X>;
+
+template<template<typename> class F, typename X> using Four = Add<Two, Two, F, X>;
+template<template<typename> class F, typename X> using Sixteen = Mul<Four, Four, F, X>;
+template<template<typename> class F, typename X> using TwoHundredAndFiftySix = Mul<Sixteen, Sixteen, F, X>;
+
+template<typename T, T N> struct Const { static const T value = N; };
+template<typename A> struct IncrementHelper;
+template<typename T, T N> struct IncrementHelper<Const<T, N>> { using Result = Const<T, N+1>; };
+template<typename A> using Increment = typename IncrementHelper<A>::Result;
+
+using Arr = int[TwoHundredAndFiftySix<Increment, Const<int, 0>>::value];
+using Arr = int[256];
diff --git a/test/SemaTemplate/alias-nested-nontag.cpp b/test/SemaTemplate/alias-nested-nontag.cpp
new file mode 100644
index 0000000..1bb5ce3
--- /dev/null
+++ b/test/SemaTemplate/alias-nested-nontag.cpp
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s
+
+template<typename T> using Id = T; // expected-note {{type alias template 'Id' declared here}}
+struct U { static Id<int> V; };
+Id<int> ::U::V; // expected-error {{type 'Id<int>' (aka 'int') cannot be used prior to '::' because it has no members}} \
+                   expected-error {{C++ requires a type specifier}}
diff --git a/test/SemaTemplate/alias-template-template-param.cpp b/test/SemaTemplate/alias-template-template-param.cpp
new file mode 100644
index 0000000..a847b06
--- /dev/null
+++ b/test/SemaTemplate/alias-template-template-param.cpp
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s
+
+template<template<typename> class D> using C = D<int>;
+
+// Substitution of the alias template transforms the TemplateSpecializationType
+// 'D<int>' into the DependentTemplateSpecializationType 'T::template U<int>'.
+template<typename T> void f(C<T::template U>);