Support for C++11 (non-template) alias declarations.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@129567 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/CXX/basic/basic.scope/basic.scope.pdecl/p3.cpp b/test/CXX/basic/basic.scope/basic.scope.pdecl/p3.cpp
new file mode 100644
index 0000000..751c0df
--- /dev/null
+++ b/test/CXX/basic/basic.scope/basic.scope.pdecl/p3.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s
+
+// Classes.
+namespace Class {
+  namespace NS {
+    class C {}; // expected-note {{candidate}}
+  }
+  using namespace NS;
+  class C : C {}; // expected-error {{reference to 'C' is ambiguous}} \
+                     expected-note {{candidate}}
+}
+
+// Enumerations.
+enum E {
+  EPtrSize = sizeof((E*)0) // ok, E is already declared
+};
+
+// Alias declarations. clang implements the proposed resolution to N1044.
+namespace Alias {
+  namespace NS {
+    class C;
+  }
+  using namespace NS;
+  using C = C; // ok, C = B::C
+  using C = NS::C; // ok, same type
+}
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp
index 6482771..c00d4b7 100644
--- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp
@@ -63,7 +63,7 @@
 struct F : auto {}; // expected-error{{expected class name}}
 template<typename T = auto> struct G { }; // expected-error{{'auto' not allowed here}}
 
-using A = auto; // expected-error{{expected ';'}} expected-error{{requires a qualified name}}
+using A = auto; // expected-error{{'auto' not allowed in type alias}}
 
 // FIXME: don't issue the second diagnostic for this error.
 auto k() -> auto; // expected-error{{'auto' not allowed here}} unexpected-error{{without trailing return type}}
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp
new file mode 100644
index 0000000..a51cfbf
--- /dev/null
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp
@@ -0,0 +1,161 @@
+// RUN: %clang_cc1 -verify -std=c++0x %s
+
+namespace RedeclAliasTypedef {
+  typedef int T;
+  using T = int;
+  using T = int;
+  typedef T T;
+  using T = T;
+  typedef int T;
+}
+
+namespace IllegalTypeIds {
+  using A = void(int n = 0); // expected-error {{default arguments can only be specified for parameters in a function declaration}}
+  using B = inline void(int n); // expected-error {{type name does not allow function specifier}}
+  using C = virtual void(int n); // expected-error {{type name does not allow function specifier}}
+  using D = explicit void(int n); // expected-error {{type name does not allow function specifier}}
+  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.
+  using F = void(*)(int n) &&; // expected-err
+  using G = __thread void(int n); // expected-error {{type name does not allow storage class to be specified}}
+
+  using H = void(int n); // ok
+  using I = void(int n) &&; // ok
+}
+
+namespace IllegalSyntax {
+  using ::T = void(int n); // expected-error {{name defined in alias declaration must be an identifier}}
+  using operator int = void(int n); // expected-error {{name defined in alias declaration must be an identifier}}
+  using typename U = void; // expected-error {{name defined in alias declaration must be an identifier}}
+  using typename ::V = void(int n); // expected-error {{name defined in alias declaration must be an identifier}}
+  using typename ::operator bool = void(int n); // expected-error {{name defined in alias declaration must be an identifier}}
+}
+
+namespace VariableLengthArrays {
+  using T = int[42]; // ok
+
+  int n = 32;
+  using T = int[n]; // expected-error {{variable length array declaration not allowed at file scope}}
+
+  const int m = 42;
+  using U = int[m]; // expected-note {{previous definition}}
+  using U = int[42]; // ok
+  using U = int; // expected-error {{type alias redefinition with different types ('int' vs 'int [42]')}}
+
+  void f() {
+    int n = 42;
+    goto foo; // expected-error {{goto into protected scope}}
+    using T = int[n]; // expected-note {{bypasses initialization of VLA type alias}}
+  foo: ;
+  }
+}
+
+namespace RedeclFunc {
+  int f(int, char**);
+  using T = int;
+  T f(int, char **); // ok
+}
+
+namespace LookupFilter {
+  namespace N { struct S; }
+  using namespace N;
+  using S = S*; // ok
+}
+
+namespace InFunctions {
+  template<typename...T> void f0() {
+    using U = T*; // expected-error {{declaration type contains unexpanded parameter pack 'T'}}
+    U u;
+  }
+  template void f0<int, char>();
+
+  void f1() {
+    using T = int;
+  }
+  void f2() {
+    using T = int[-1]; // expected-error {{array size is negative}}
+  }
+
+  template<typename...T> void f3() { // expected-note {{template parameter is declared here}}
+    using T = int; // expected-error {{declaration of 'T' shadows template parameter}}
+  }
+}
+
+namespace ClassNameRedecl {
+  class C0 {
+    // FIXME: this diagnostic is pretty poor
+    using C0 = int; // expected-error {{name defined in alias declaration must be an identifier}}
+  };
+  class C1 {
+    // FIXME: this diagnostic is pretty poor
+    using C1 = C1; // expected-error {{name defined in alias declaration must be an identifier}}
+  };
+  class C2 {
+    using C0 = C1; // ok
+  };
+  template<typename...T> class C3 {
+    using f = T; // expected-error {{declaration type contains unexpanded parameter pack 'T'}}
+  };
+  template<typename T> class C4 { // expected-note {{template parameter is declared here}}
+    using T = int; // expected-error {{declaration of 'T' shadows template parameter}}
+  };
+  class C5 {
+    class c; // expected-note {{previous definition}}
+    using c = int; // expected-error {{typedef redefinition with different types}}
+    class d;
+    using d = d; // ok
+  };
+  class C6 {
+    class c { using C6 = int; }; // ok
+  };
+}
+
+class CtorDtorName {
+  using X = CtorDtorName;
+  X(); // expected-error {{expected member name}}
+  ~X(); // expected-error {{destructor cannot be declared using a type alias}}
+};
+
+namespace TagName {
+  using S = struct { int n; };
+  using T = class { int n; };
+  using U = enum { a, b, c };
+  using V = struct V { int n; };
+}
+
+namespace CWG1044 {
+  // FIXME: this is terrible. one error is plenty.
+  using T = T; // expected-error {{type name requires a specifier}} \
+                  expected-error {{C++ requires a type specifier}} \
+                  expected-error {{expected ';' after alias declaration}}
+}
+
+namespace StdExample {
+  template<typename T, typename U> struct pair;
+
+  using handler_t = void (*)(int);
+  extern handler_t ignore;
+  extern void (*ignore)(int);
+  // FIXME: we know we're parsing a type here; don't recover as if we were
+  // using operator*.
+  using cell = pair<void*, cell*>; // expected-error {{use of undeclared identifier 'cell'}} \
+                                      expected-error {{expected expression}}
+}
+
+namespace Access {
+  class C0 {
+    using U = int; // expected-note {{declared private here}}
+  };
+  C0::U v; // expected-error {{'U' is a private member}}
+  class C1 {
+  public:
+    using U = int;
+  };
+  C1::U w; // ok
+}
+
+namespace VoidArg {
+  using V = void;
+  V f(int); // ok
+  V g(V); // expected-error {{empty parameter list defined with a type alias of 'void' not allowed}}
+}
diff --git a/test/FixIt/fixit-cxx0x.cpp b/test/FixIt/fixit-cxx0x.cpp
index d8a858d..90bf9f5 100644
--- a/test/FixIt/fixit-cxx0x.cpp
+++ b/test/FixIt/fixit-cxx0x.cpp
@@ -14,3 +14,6 @@
   }
 }
 
+using ::T = void; // expected-error {{name defined in alias declaration must be an identifier}}
+using typename U = void; // expected-error {{name defined in alias declaration must be an identifier}}
+using typename ::V = void; // expected-error {{name defined in alias declaration must be an identifier}}