Patchwork [C++] PR c++/45114 - Support alias templates

login
register
mail settings
Submitter Dodji Seketeli
Date Nov. 5, 2011, 11:36 p.m.
Message ID <m3wrbem9a4.fsf@redhat.com>
Download mbox | patch
Permalink /patch/123896/
State New
Headers show

Comments

Dodji Seketeli - Nov. 5, 2011, 11:36 p.m.
Jason Merrill <jason@redhat.com> writes:

> On 10/27/2011 03:10 PM, Dodji Seketeli wrote:
> > +/* Setter for the TYPE_DECL_ALIAS_P proprety above.  */
> > +#define SET_TYPE_DECL_ALIAS_P(NODE, VAL)               \
> > +  (DECL_LANG_FLAG_6 (TYPE_DECL_CHECK (NODE)) = (VAL))
> 
> This seems unnecessary.

Removed.

> 
> > +#define TYPE_DECL_NAMES_ALIAS_TEMPLATE_P(NODE)                         \
> > +  (TYPE_DECL_ALIAS_P (NODE)                                            \
> > +   && DECL_LANG_SPECIFIC (NODE)                                                \
> > +   && DECL_TI_TEMPLATE (NODE)                                          \
> > +   && same_type_p (TREE_TYPE (NODE), TREE_TYPE (DECL_TI_TEMPLATE (NODE))))
> 
> I don't think same_type_p is the test you want here, as it ignores
> typedefs.  How about
> 
>   DECL_TEMPLATE_RESULT (DECL_TI_TEMPLATE (NODE)) == (NODE)

Right.  Changed.

> ?
> 
> > +#define TYPE_ALIAS_P(NODE) \
> > +  (TYPE_P (NODE) \
> > +   && DECL_LANG_SPECIFIC (TYPE_NAME (NODE))    \
> > +   && TYPE_DECL_ALIAS_P (TYPE_NAME (NODE)))
> 
> Why check DECL_LANG_SPECIFIC?

I removed the check.

> 
> > +      /*If T is a specialization of an alias template, then we don't
> > +       want to take this 'if' branch; we want to print it as if it
> > +       was a specialization of class template.  */
> 
> I think we want to handle them specially within this if.

Done.

> 
> > -      else if (same_type_p (t, TREE_TYPE (decl)))
> > +      else if (same_type_p (t, TREE_TYPE (decl))
> > +              && /* If T is the type of an alias template then we
> > +                    want to let dump_decl print it like an alias
> > +                    template.  */
> > +              TYPE_DECL_NAMES_ALIAS_TEMPLATE_P (decl))
> 
> This change restricts the existing test to only apply to alias
> templates.

Removed.

> 
> Also, I would think we would want to handle the uninstantiated alias
> the same as instantiations.

In the updated patch below, uninstantiated aliase types follow the
same path as typedefs and are handled specifically by dump_decl,
whereas alias instantiations are handled by the new
dump_alias_template_specialization that knows how to handle class and
non-class alias template instantiations.  Is that bad?

> 
> You need some tests for printing of aliases in error messages.  Only
> one of the current tests prints an alias:
> 
> > /home/jason/gt/gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C:5:26: error: partial specialization of alias template 'using AA0 = struct A0<int, T>'
> 
> This should have the template header.  So here:
> 
> > +      if (DECL_ALIAS_TEMPLATE_P (TI_TEMPLATE (get_template_info 
> (type))))
> > +       {
> > +         error ("partial specialization of alias template %qD",
> > +                TYPE_NAME (type));
> > +         return error_mark_node;
> > +       }
> 
> We should pass the template to error, rather than the
> instantiation. But when I try that I see that it prints
> 
>  template<class T, class U> struct AA0<T, U>
> 
> instead, so more fixing is needed.

Right.  I tried to add more tests for that, and fixed many little
things here and there to get better printing.

> 
> > +  else if (DECL_ALIAS_TEMPLATE_P (t))
> > +    {
> > +      tree tmpl;
> > +      result = get_aliased_type (DECL_TEMPLATE_RESULT (t));
> > +      tmpl = TI_TEMPLATE (get_template_info (result));
> > +      /* If RESULT is just the naming of TMPL, return TMPL.  */
> > +      if (same_type_p (result,
> > +                      TREE_TYPE (DECL_TEMPLATE_RESULT (tmpl))))
> > +       result = tmpl;
> > +    }
> 
> What is this trying to achieve?  When we pass in a template, sometimes
> it returns a type and sometimes a template?  That seems odd.

This is gone now, as it was for stripping aliases and I removed it
now, see below.


> 
> > +      else
> > +       /* Strip template aliases from TEMPLATE_DECL nodes,
> > +          similarly to what is done by
> > +          canonicalize_type_argument for types above.  */
> > +       val = strip_alias (val);
> 
> I don't think this is right.  Alias templates are never deduced, but
> that doesn't seem to mean that they can't be used as template template
> arguments.  Both clang and EDG accept this testcase:
> 
> template <class T, class U> struct same;
> template <class T> struct same<T,T> {};
> 
> template <class T> using Ptr = T*;
> template <template <class> class T> struct A {
>   template <class U> using X = T<U>;
> };
> same<A<Ptr>::X<int>,int*> s;

I got confused by the fact that in the initial n2258 paper, the first
test case of gcc/testsuite/g++.dg/cpp0x/alias-decl-0.C was meant to
pass.  I didn't realize that it changed in the final draft.  And you
are right that the example above ought to pass.  Also that example
made me realize that I needed to do a bit more to support non-class
alias template instantiations as well.  I have added more test cases.

> 
> > +               if (ctx == DECL_CONTEXT (t)
> > +                   && (TREE_CODE (t) != TYPE_DECL
> > +                       /* ... unless T is an alias declaration; in
> > +                          which case our caller can be willing to
> > +                          create a specialization of the alias
> > +                          template represented by T.  If we hand her
> > +                          T, she is going to clobber it.  So we'll
> > +                          contruct a new T in this case, just like
> > +                          for the case where T is not a class
> > +                          member.  */
> > +                       || !TYPE_DECL_ALIAS_P (t)))
> 
> I'm guessing that what this is trying to solve is the case of an
> instantiation of a member alias template?

Correct.

> In that case the problem is
> that the member is a template, and this code is assuming a
> non-template member.  Let's check for that instead of
> alias-declarations, as the existing code ought to work fine for
> regular alias members.

Done, thanks.

> 
> > +      else if (TYPE_DECL_ALIAS_P (decl))
> > +       /* fall through.  */;
> 
> Why not set r here, as for the other cases?

Because I'd like to handle alias declarations even for cases handled
by the other cases where, r is end up being NULL.

>  It seems like this way you will lose cv-quals added to an alias.

Oops.  I think I have fixed this now, thanks.

Bootstrapped and tested on x86_64-unknown-linux-gnu.

From: Dodji Seketeli <dodji@redhat.com>
Date: Fri, 30 Sep 2011 12:52:52 +0200
Subject: [PATCH] PR c++/45114 - Support alias templates

gcc/cp/

	* cp-tree.h (TYPE_DECL_ALIAS_P)
	(TYPE_DECL_NAMES_ALIAS_TEMPLATE_P, TYPE_ALIAS_P)
	(DECL_TYPE_TEMPLATE_P, DECL_ALIAS_TEMPLATE_P): New accessor macros.
	(TYPE_TEMPLATE_INFO): Get template info of an alias template
	specializations from its TYPE_DECL.
	(SET_TYPE_TEMPLATE_INFO): Set template info of alias template
	specializations into its TYPE_DECL.
	(DECL_CLASS_TEMPLATE_P): Re-write using the new
	DECL_TYPE_TEMPLATE_P.
	(enum cp_decl_spec): Add new ds_alias enumerator.
	(alias_type_or_template_p, alias_template_specialization_p):
	Declare new functions.
	* parser.c (cp_parser_alias_declaration): New static function.
	(cp_parser_check_decl_spec): Add "using" name for the `alias'
	declspec.
	(cp_parser_type_name): Update comment.  Support simple-template-id
	representing alias template specializations in c++0x mode.
	(cp_parser_qualifying_entity): Update comment.  Use
	cp_parser_type_name.
	(cp_parser_block_declaration): Handle alias-declaration in c++11.
	Update comment.
	(cp_parser_template_id): Handle specializations of alias
	templates.
	(cp_parser_member_declaration): Add alias-declaration production
	to comment.  Support alias-declarations.
	(cp_parser_template_declaration_after_export): Handle alias
	templates in c++11.
	* decl.c (make_typename_type, make_unbound_class_template): Accept
	alias templates.
	(grokdeclarator): Set TYPE_DECL_ALIAS_P on alias
	declarations.
	* decl2.c (grokfield): Move template creation after setting up the
	TYPE_DECL of the alias, so that the TEMPLATE_DECL of the alias
	template actually carries the right type-id of the alias
	declaration.
	* pt.c (alias_type_or_template_p)
	(alias_template_specialization_p): Define new public functions.
	(maybe_process_partial_specialization): Reject partial
	specializations of alias templates.
	(primary_template_instantiation_p): Consider alias template
	instantiations.
	(push_template_decl_real): Assert that TYPE_DECLs of alias
	templates are different from those of class template.  Store
	template info onto the TYPE_DECL of the alias template.
	(convert_template_argument): Strip aliases from template
	arguments.
	(lookup_template_class_1): Handle the creation of the
	specialization of an alias template.
	(tsubst_decl): Create a substituted copy of the TYPE_DECL of an
	member alias template.
	(tsubst): Handle substituting into the type of an alias template.
	Handle substituting UNBOUND_CLASS_TEMPLATE into
	BOUND_TEMPLATE_TEMPLATE_PARM.
	(do_type_instantiation): Better diagnostics when trying to
	explicitely instantiate a non-class template.
	* search.c (lookup_field_1, lookup_field_r): Support looking up
	alias templates.
	* semantics.c (finish_template_type): For instantiations of alias
	templates, return the TYPE_DECL of the actual alias and not the
	one of the aliased type.
	* error.c (dump_alias_template_specialization): New static
	function.
	(dump_type): Handle specialization of alias templates.
	like we print specializations of class templates.  Also, handle
	the printing of alias templates.
	(dump_aggr_type): For specialization of alias templates, fetch
	arguments from the right place.
	(dump_decl): Print an alias-declaration like `using decl = type;'
	(dump_template_decl):  Support printing of alias templates.

gcc/testsuite/

	* g++.dg/cpp0x/alias-decl-0.C: New test case.
	* g++.dg/cpp0x/alias-decl-1.C: Likewise.
	* g++.dg/cpp0x/alias-decl-3.C: Likewise.
	* g++.dg/cpp0x/alias-decl-4.C: Likewise.
	* g++.dg/cpp0x/alias-decl-6.C: Likewise.
	* g++.dg/cpp0x/alias-decl-7.C: Likewise.
	* g++.dg/cpp0x/alias-decl-8.C: Likewise.
	* g++.dg/cpp0x/alias-decl-9.C: Likewise.
	* g++.dg/cpp0x/alias-decl-10.C: Likewise.
---
 gcc/cp/cp-tree.h                           |   66 ++++++++-
 gcc/cp/decl.c                              |    9 +-
 gcc/cp/decl2.c                             |    9 +-
 gcc/cp/error.c                             |   61 +++++++--
 gcc/cp/parser.c                            |  138 +++++++++++++++++--
 gcc/cp/pt.c                                |  203 ++++++++++++++++++++++++---
 gcc/cp/search.c                            |    6 +-
 gcc/cp/semantics.c                         |   14 +-
 gcc/testsuite/g++.dg/cpp0x/alias-decl-0.C  |   37 +++++
 gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C  |   15 ++
 gcc/testsuite/g++.dg/cpp0x/alias-decl-10.C |   18 +++
 gcc/testsuite/g++.dg/cpp0x/alias-decl-2.C  |   33 +++++
 gcc/testsuite/g++.dg/cpp0x/alias-decl-3.C  |   42 ++++++
 gcc/testsuite/g++.dg/cpp0x/alias-decl-4.C  |   14 ++
 gcc/testsuite/g++.dg/cpp0x/alias-decl-5.C  |   34 +++++
 gcc/testsuite/g++.dg/cpp0x/alias-decl-6.C  |   12 ++
 gcc/testsuite/g++.dg/cpp0x/alias-decl-7.C  |   23 +++
 gcc/testsuite/g++.dg/cpp0x/alias-decl-8.C  |   32 +++++
 gcc/testsuite/g++.dg/cpp0x/alias-decl-9.C  |    9 ++
 19 files changed, 708 insertions(+), 67 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/alias-decl-0.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/alias-decl-10.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/alias-decl-2.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/alias-decl-3.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/alias-decl-4.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/alias-decl-5.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/alias-decl-6.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/alias-decl-7.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/alias-decl-8.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/alias-decl-9.C
Jason Merrill - Nov. 6, 2011, 4:41 a.m.
On 11/05/2011 07:36 PM, Dodji Seketeli wrote:
> +#define TYPE_DECL_NAMES_ALIAS_TEMPLATE_P(NODE)                         \

This doesn't seem to be needed anymore.

> +dump_alias_template_specialization (tree t, int flags)
> +{
> +  gcc_assert (alias_template_specialization_p (t));
> +
> +  if (CLASS_TYPE_P (t))
> +    dump_aggr_type (t, flags);
> +  else
> +    {
> +      tree name;
> +      name = TYPE_IDENTIFIER (t);
> +      pp_cxx_tree_identifier (cxx_pp, name);
> +      dump_template_parms (TYPE_TEMPLATE_INFO (t),
> +                          /*primary=*/false,
> +                          flags & ~TFF_TEMPLATE_HEADER);
> +    }

Why do you treat class and non-class aliases differently?  In both cases 
I think we want alias specializations to be printed as 
scope::name<args>.  We don't want to print 'class' since such a 
specialization cannot be used in an elaborated-type-specifier. 
7.1.6.3/2: "If the identifier resolves to a typedef-name or
the simple-template-id resolves to an alias template specialization, the 
elaborated-type-specifier is ill-formed."

> +      if (alias_template_specialization_p (t))
> +       {
> +         dump_alias_template_specialization (t, flags);
> +         return;
> +       }
> +      else if ((flags & TFF_CHASE_TYPEDEF)
> +              || DECL_SELF_REFERENCE_P (decl)
> +              || (!flag_pretty_templates
> +                  && DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)))
>         t = strip_typedefs (t);

The order of these two should be reversed.  We want TFF_CHASE_TYPEDEF 
and -fno-pretty-templates to strip alias-templates as well as 
non-template typedefs.

> -  /* If the next keyword is `namespace', we have a
> +  /* If the next keyword is `namespace', we have either a
>       namespace-alias-definition.  */

This change seems unintended.

> +      if (!(type_decl != NULL_TREE
> +           && TREE_CODE (type_decl) == TYPE_DECL
> +           && TYPE_DECL_ALIAS_P (type_decl)
> +           && DECL_TEMPLATE_INSTANTIATION (type_decl)))
> +       cp_parser_simulate_error (parser);

I think the TYPE_DECL_ALIAS_P and DECL_TEMPLATE_INSTANTIATION checks 
should be an assert instead; at this point any TYPE_DECL we get should 
satisfy those.

> -         || (TYPE_P (t) && TYPE_DECL_ALIAS_P (TYPE_NAME (t)))
> +         || (TYPE_P (t)
> +             && TYPE_NAME (t)
> +             && TREE_CODE (TYPE_NAME (t)) == TYPE_DECL
> +             && TYPE_DECL_ALIAS_P (TYPE_NAME (t)))

In C++ I think a non-null TYPE_NAME is always a TYPE_DECL.

>> Why not set r here, as for the other cases?
> Because I'd like to handle alias declarations even for cases handled
> by the other cases where, r is end up being NULL.

Hmm.  With this code we end up substituting into a non-template alias 
declaration at file scope.  I think if you check 
alias_template_specialization_p before checking for class/function scope 
that should handle the cases you need.

Jason

Patch

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 7ff1491..9300947 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -139,6 +139,7 @@  c-common.h, not after.
    5: DECL_INTERFACE_KNOWN.
    6: DECL_THIS_STATIC (in VAR_DECL or FUNCTION_DECL).
       DECL_FIELD_IS_BASE (in FIELD_DECL)
+      TYPE_DECL_ALIAS_P (in TYPE_DECL)
    7: DECL_DEAD_FOR_LOCAL (in VAR_DECL).
       DECL_THUNK_P (in a member FUNCTION_DECL)
       DECL_NORMAL_CAPTURE_P (in FIELD_DECL)
@@ -2541,6 +2542,37 @@  extern void decl_shadowed_for_var_insert (tree, tree);
 #define DECL_PENDING_INLINE_INFO(NODE) \
   (LANG_DECL_FN_CHECK (NODE)->u.pending_inline_info)
 
+/* Nonzero for TYPE_DECL means that it was written 'using name = type'.  */
+#define TYPE_DECL_ALIAS_P(NODE) \
+  DECL_LANG_FLAG_6 (TYPE_DECL_CHECK (NODE))
+
+/* Nonzero if NODE is a TYPE_DECL for an instantiation that names an
+   alias template.  For instance:
+
+       template<class T, class U> struct S {};
+       template<class T> using A = S<T, int>;
+
+       template<class T>
+       struct C
+       {
+	 typedef A<T> name_of_A;
+       };
+  A<T> just "names A" because its list of argument is the
+  same a the list of parameters of the template A.  */
+#define TYPE_DECL_NAMES_ALIAS_TEMPLATE_P(NODE)				\
+  (TYPE_DECL_ALIAS_P (NODE)						\
+   && DECL_LANG_SPECIFIC (NODE)						\
+   && DECL_TEMPLATE_INFO (NODE)						\
+   && DECL_TI_TEMPLATE (NODE)						\
+   && (DECL_TEMPLATE_RESULT (DECL_TI_TEMPLATE (NODE)) == (NODE)))
+
+/* Nonzero for a type which is an alias for another type; i.e, a type
+   which declaration was written 'using name-of-type =
+   another-type'.  */
+#define TYPE_ALIAS_P(NODE) \
+  (TYPE_P (NODE) \
+   && TYPE_DECL_ALIAS_P (TYPE_NAME (NODE)))
+
 /* For a class type: if this structure has many fields, we'll sort them
    and put them into a TREE_VEC.  */
 #define CLASSTYPE_SORTED_FIELDS(NODE) \
@@ -2597,16 +2629,20 @@  extern void decl_shadowed_for_var_insert (tree, tree);
    ? ENUM_TEMPLATE_INFO (NODE) :			\
    (TREE_CODE (NODE) == BOUND_TEMPLATE_TEMPLATE_PARM	\
     ? TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (NODE) :	\
-    (TYPE_LANG_SPECIFIC (NODE)				\
+    ((CLASS_TYPE_P (NODE) && !TYPE_ALIAS_P (NODE))	\
      ? CLASSTYPE_TEMPLATE_INFO (NODE)			\
-     : NULL_TREE)))
+     : (DECL_LANG_SPECIFIC (TYPE_NAME (NODE))		\
+	? (DECL_TEMPLATE_INFO (TYPE_NAME (NODE)))	\
+	: NULL_TREE))))
 
 /* Set the template information for an ENUMERAL_, RECORD_, or
    UNION_TYPE to VAL.  */
-#define SET_TYPE_TEMPLATE_INFO(NODE, VAL)	\
-  (TREE_CODE (NODE) == ENUMERAL_TYPE		\
-   ? (ENUM_TEMPLATE_INFO (NODE) = (VAL))	\
-   : (CLASSTYPE_TEMPLATE_INFO (NODE) = (VAL)))
+#define SET_TYPE_TEMPLATE_INFO(NODE, VAL)				\
+  (TREE_CODE (NODE) == ENUMERAL_TYPE					\
+   ? (ENUM_TEMPLATE_INFO (NODE) = (VAL))				\
+   : ((CLASS_TYPE_P (NODE) && !TYPE_ALIAS_P (NODE))			\
+      ? (CLASSTYPE_TEMPLATE_INFO (NODE) = (VAL))			\
+      : (DECL_TEMPLATE_INFO (TYPE_NAME (NODE)) = (VAL))))
 
 #define TI_TEMPLATE(NODE) TREE_TYPE (TEMPLATE_INFO_CHECK (NODE))
 #define TI_ARGS(NODE) TREE_CHAIN (TEMPLATE_INFO_CHECK (NODE))
@@ -3619,12 +3655,23 @@  more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
    && !DECL_UNBOUND_CLASS_TEMPLATE_P (NODE) \
    && TREE_CODE (DECL_TEMPLATE_RESULT (NODE)) == FUNCTION_DECL)
 
-/* Nonzero for a DECL that represents a template class.  */
-#define DECL_CLASS_TEMPLATE_P(NODE)				\
+/* Nonzero for a DECL that represents a class template or alias
+   template.  */
+#define DECL_TYPE_TEMPLATE_P(NODE)				\
   (TREE_CODE (NODE) == TEMPLATE_DECL				\
    && DECL_TEMPLATE_RESULT (NODE) != NULL_TREE			\
+   && TREE_CODE (DECL_TEMPLATE_RESULT (NODE)) == TYPE_DECL)
+
+/* Nonzero for a DECL that represents a class template.  */
+#define DECL_CLASS_TEMPLATE_P(NODE)				\
+  (DECL_TYPE_TEMPLATE_P (NODE)					\
    && DECL_IMPLICIT_TYPEDEF_P (DECL_TEMPLATE_RESULT (NODE)))
 
+/* Nonzero for a TEMPLATE_DECL that represents an alias template.  */
+#define DECL_ALIAS_TEMPLATE_P(NODE)			\
+  (DECL_TYPE_TEMPLATE_P (NODE)				\
+   && !DECL_ARTIFICIAL (DECL_TEMPLATE_RESULT (NODE)))
+
 /* Nonzero for a NODE which declares a type.  */
 #define DECL_DECLARES_TYPE_P(NODE) \
   (TREE_CODE (NODE) == TYPE_DECL || DECL_CLASS_TEMPLATE_P (NODE))
@@ -4579,6 +4626,7 @@  typedef enum cp_decl_spec {
   ds_explicit,
   ds_friend,
   ds_typedef,
+  ds_alias,
   ds_constexpr,
   ds_complex,
   ds_thread,
@@ -5282,6 +5330,8 @@  extern tree build_non_dependent_expr		(tree);
 extern void make_args_non_dependent		(VEC(tree,gc) *);
 extern bool reregister_specialization		(tree, tree, tree);
 extern tree fold_non_dependent_expr		(tree);
+extern bool alias_type_or_template_p            (tree);
+extern bool alias_template_specialization_p     (tree);
 extern bool explicit_class_specialization_p     (tree);
 extern int push_tinst_level                     (tree);
 extern void pop_tinst_level                     (void);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 860556c..dac6670 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -3270,7 +3270,7 @@  make_typename_type (tree context, tree name, enum tag_types tag_type,
       return error_mark_node;
     }
 
-  if (want_template && !DECL_CLASS_TEMPLATE_P (t))
+  if (want_template && !DECL_TYPE_TEMPLATE_P (t))
     {
       if (complain & tf_error)
 	error ("%<typename %T::%D%> names %q#T, which is not a class template",
@@ -3338,7 +3338,7 @@  make_unbound_class_template (tree context, tree name, tree parm_list,
       if (tmpl && TREE_CODE (tmpl) == TYPE_DECL)
 	tmpl = maybe_get_template_decl_from_type_decl (tmpl);
 
-      if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
+      if (!tmpl || !DECL_TYPE_TEMPLATE_P (tmpl))
 	{
 	  if (complain & tf_error)
 	    error ("no class template named %q#T in %q#T", name, context);
@@ -9790,6 +9790,11 @@  grokdeclarator (const cp_declarator *declarator,
 		      memfn_quals != TYPE_UNQUALIFIED,
 		      inlinep, friendp, raises != NULL_TREE);
 
+      if (declspecs->specs[(int)ds_alias])
+	/* Acknowledge that this was written:
+	     `using analias = atype;'.  */
+	TYPE_DECL_ALIAS_P (decl) = 1;
+
       return decl;
     }
 
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 9851ece..b230d95 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -847,9 +847,6 @@  grokfield (const cp_declarator *declarator,
       DECL_NONLOCAL (value) = 1;
       DECL_CONTEXT (value) = current_class_type;
 
-      if (processing_template_decl)
-	value = push_template_decl (value);
-
       if (attrlist)
 	{
 	  int attrflags = 0;
@@ -868,6 +865,12 @@  grokfield (const cp_declarator *declarator,
           && TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (value))) != value)
 	set_underlying_type (value);
 
+      /* It's important that push_template_decl below follows
+	 set_underlying_type above so that the created template
+	 carries the properly set type of VALUE.  */
+      if (processing_template_decl)
+	value = push_template_decl (value);
+
       record_locally_defined_typedef (value);
       return value;
     }
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 544c4d1..a27154e 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -61,6 +61,7 @@  static const char *op_to_string	(enum tree_code);
 static const char *parm_to_string (int);
 static const char *type_to_string (tree, int);
 
+static void dump_alias_template_specialization (tree, int);
 static void dump_type (tree, int);
 static void dump_typename (tree, int);
 static void dump_simple_decl (tree, tree, int);
@@ -330,6 +331,27 @@  dump_template_bindings (tree parms, tree args, VEC(tree,gc)* typenames)
     }
 }
 
+/* Dump a human-readable equivalent of the alias template
+   specialization of T.  */
+
+static void
+dump_alias_template_specialization (tree t, int flags)
+{
+  gcc_assert (alias_template_specialization_p (t));
+
+  if (CLASS_TYPE_P (t))
+    dump_aggr_type (t, flags);
+  else
+    {
+      tree name;
+      name = TYPE_IDENTIFIER (t);
+      pp_cxx_tree_identifier (cxx_pp, name);
+      dump_template_parms (TYPE_TEMPLATE_INFO (t),
+			   /*primary=*/false,
+			   flags & ~TFF_TEMPLATE_HEADER);
+    }
+}
+
 /* Dump a human-readable equivalent of TYPE.  FLAGS controls the
    format.  */
 
@@ -343,10 +365,15 @@  dump_type (tree t, int flags)
   if (TYPE_P (t) && typedef_variant_p (t))
     {
       tree decl = TYPE_NAME (t);
-      if ((flags & TFF_CHASE_TYPEDEF)
-	  || DECL_SELF_REFERENCE_P (decl)
-	  || (!flag_pretty_templates
-	      && DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)))
+      if (alias_template_specialization_p (t))
+	{
+	  dump_alias_template_specialization (t, flags);
+	  return;
+	}
+      else if ((flags & TFF_CHASE_TYPEDEF)
+	       || DECL_SELF_REFERENCE_P (decl)
+	       || (!flag_pretty_templates
+		   && DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)))
 	t = strip_typedefs (t);
       else if (same_type_p (t, TREE_TYPE (decl)))
 	t = decl;
@@ -588,7 +615,10 @@  dump_aggr_type (tree t, int flags)
 
   if (name)
     {
-      typdef = !DECL_ARTIFICIAL (name);
+      typdef = (!DECL_ARTIFICIAL (name)
+		/* An alias specialization is not considered to be a
+		   typedef.  */
+		&& !alias_template_specialization_p (t));
 
       if ((typdef
 	   && ((flags & TFF_CHASE_TYPEDEF)
@@ -613,7 +643,7 @@  dump_aggr_type (tree t, int flags)
 	{
 	  /* Because the template names are mangled, we have to locate
 	     the most general template, and use that name.  */
-	  tree tpl = CLASSTYPE_TI_TEMPLATE (t);
+	  tree tpl = TYPE_TI_TEMPLATE (t);
 
 	  while (DECL_TEMPLATE_INFO (tpl))
 	    tpl = DECL_TI_TEMPLATE (tpl);
@@ -952,6 +982,18 @@  dump_decl (tree t, int flags)
 	  dump_type (TREE_TYPE (t), flags);
 	  break;
 	}
+      if (TYPE_DECL_ALIAS_P (t)
+	  && (flags & TFF_DECL_SPECIFIERS
+	      || flags & TFF_CLASS_KEY_OR_ENUM))
+	{
+	  pp_cxx_ws_string (cxx_pp, "using");
+	  dump_decl (DECL_NAME (t), flags);
+	  pp_cxx_whitespace (cxx_pp);
+	  pp_cxx_ws_string (cxx_pp, "=");
+	  pp_cxx_whitespace (cxx_pp);
+	  dump_type (DECL_ORIGINAL_TYPE (t), flags);
+	  break;
+	}
       if ((flags & TFF_DECL_SPECIFIERS)
 	  && !DECL_SELF_REFERENCE_P (t))
 	pp_cxx_ws_string (cxx_pp, "typedef");
@@ -1196,13 +1238,14 @@  dump_template_decl (tree t, int flags)
 	}
     }
 
-  if (DECL_TEMPLATE_RESULT (t)
-      && TREE_CODE (DECL_TEMPLATE_RESULT (t)) == TYPE_DECL)
+  if (DECL_CLASS_TEMPLATE_P (t))
     dump_type (TREE_TYPE (t),
 	       ((flags & ~TFF_CLASS_KEY_OR_ENUM) | TFF_TEMPLATE_NAME
 		| (flags & TFF_DECL_SPECIFIERS ? TFF_CLASS_KEY_OR_ENUM : 0)));
   else if (DECL_TEMPLATE_RESULT (t)
-           && TREE_CODE (DECL_TEMPLATE_RESULT (t)) == VAR_DECL)
+           && (TREE_CODE (DECL_TEMPLATE_RESULT (t)) == VAR_DECL
+	       /* Alias template.  */
+	       || DECL_TYPE_TEMPLATE_P (t)))
     dump_decl (DECL_TEMPLATE_RESULT (t), flags | TFF_TEMPLATE_NAME);
   else
     {
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 090482c..c12e8d5 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1935,6 +1935,8 @@  static bool cp_parser_using_declaration
   (cp_parser *, bool);
 static void cp_parser_using_directive
   (cp_parser *);
+static tree cp_parser_alias_declaration
+  (cp_parser *);
 static void cp_parser_asm_definition
   (cp_parser *);
 static void cp_parser_linkage_specification
@@ -2509,6 +2511,7 @@  cp_parser_check_decl_spec (cp_decl_specifier_seq *decl_specs,
 	    "explicit",
 	    "friend",
 	    "typedef",
+	    "using",
             "constexpr",
 	    "__complex",
 	    "__thread"
@@ -5135,7 +5138,7 @@  cp_parser_nested_name_specifier (cp_parser *parser,
    this is either a class-name or a namespace-name (which corresponds
    to the class-or-namespace-name production in the grammar). For
    C++0x, it can also be a type-name that refers to an enumeration
-   type.
+   type or a simple-template-id.
 
    TYPENAME_KEYWORD_P is TRUE iff the `typename' keyword is in effect.
    TEMPLATE_KEYWORD_P is TRUE iff the `template' keyword is in effect.
@@ -5211,8 +5214,8 @@  cp_parser_qualifying_entity (cp_parser *parser,
       /* Parse tentatively.  */
       cp_parser_parse_tentatively (parser);
      
-      /* Parse a typedef-name or enum-name.  */
-      scope = cp_parser_nonclass_name (parser);
+      /* Parse a type-name  */
+      scope = cp_parser_type_name (parser);
 
       /* "If the name found does not designate a namespace or a class,
 	 enumeration, or dependent type, the program is ill-formed."
@@ -10146,12 +10149,12 @@  cp_parser_block_declaration (cp_parser *parser,
 	cp_parser_commit_to_tentative_parse (parser);
       cp_parser_asm_definition (parser);
     }
-  /* If the next keyword is `namespace', we have a
+  /* If the next keyword is `namespace', we have either a
      namespace-alias-definition.  */
   else if (token1->keyword == RID_NAMESPACE)
     cp_parser_namespace_alias_definition (parser);
-  /* If the next keyword is `using', we have either a
-     using-declaration or a using-directive.  */
+  /* If the next keyword is `using', we have a
+     using-declaration, a using-directive, or an alias-declaration.  */
   else if (token1->keyword == RID_USING)
     {
       cp_token *token2;
@@ -10163,6 +10166,12 @@  cp_parser_block_declaration (cp_parser *parser,
       token2 = cp_lexer_peek_nth_token (parser->lexer, 2);
       if (token2->keyword == RID_NAMESPACE)
 	cp_parser_using_directive (parser);
+      /* If the second token after 'using' is '=', then we have an
+	 alias-declaration.  */
+      else if (cxx_dialect >= cxx0x
+	       && token2->type == CPP_NAME
+	       && cp_lexer_peek_nth_token (parser->lexer, 3)->type == CPP_EQ)
+	cp_parser_alias_declaration (parser);
       /* Otherwise, it's a using-declaration.  */
       else
 	cp_parser_using_declaration (parser,
@@ -12343,7 +12352,7 @@  cp_parser_template_id (cp_parser *parser,
   /* Build a representation of the specialization.  */
   if (TREE_CODE (templ) == IDENTIFIER_NODE)
     template_id = build_min_nt (TEMPLATE_ID_EXPR, templ, arguments);
-  else if (DECL_CLASS_TEMPLATE_P (templ)
+  else if (DECL_TYPE_TEMPLATE_P (templ)
 	   || DECL_TEMPLATE_TEMPLATE_PARM_P (templ))
     {
       bool entering_scope;
@@ -13611,6 +13620,7 @@  cp_parser_simple_type_specifier (cp_parser* parser,
      class-name
      enum-name
      typedef-name
+     simple-template-id [in c++0x]
 
    enum-name:
      identifier
@@ -13638,8 +13648,36 @@  cp_parser_type_name (cp_parser* parser)
   /* If it's not a class-name, keep looking.  */
   if (!cp_parser_parse_definitely (parser))
     {
-      /* It must be a typedef-name or an enum-name.  */
-      return cp_parser_nonclass_name (parser);
+      if (cxx_dialect < cxx0x)
+	/* It must be a typedef-name or an enum-name.  */
+	return cp_parser_nonclass_name (parser);
+
+      cp_parser_parse_tentatively (parser);
+      /* It is either a simple-template-id representing an
+	 instantiation of an alias template...  */
+      type_decl = cp_parser_template_id (parser,
+					 /*template_keyword_p=*/false,
+					 /*check_dependency_p=*/false,
+					 /*is_declaration=*/false);
+      /* Note that this must be an instantiation of an alias template
+	 because [temp.names]/6 says:
+	 
+	     A template-id that names an alias template specialization
+	     is a type-name.
+
+	 Whereas [temp.names]/7 says:
+	 
+	     A simple-template-id that names a class template
+	     specialization is a class-name.  */
+      if (!(type_decl != NULL_TREE
+	    && TREE_CODE (type_decl) == TYPE_DECL
+	    && TYPE_DECL_ALIAS_P (type_decl)
+	    && DECL_TEMPLATE_INSTANTIATION (type_decl)))
+	cp_parser_simulate_error (parser);
+
+      if (!cp_parser_parse_definitely (parser))
+	/* ... Or a typedef-name or an enum-name.  */
+	return cp_parser_nonclass_name (parser);
     }
 
   return type_decl;
@@ -14831,6 +14869,61 @@  cp_parser_using_declaration (cp_parser* parser,
   return true;
 }
 
+/* Parse an alias-declaration.
+
+   alias-declaration:
+     using identifier = type-id  */
+
+static tree
+cp_parser_alias_declaration (cp_parser* parser)
+{
+  tree id, type, decl, dummy;
+  location_t id_location;
+  cp_declarator *declarator;
+  cp_decl_specifier_seq decl_specs;
+
+  /* Look for the `using' keyword.  */
+  cp_parser_require_keyword (parser, RID_USING, RT_USING);
+  id_location = cp_lexer_peek_token (parser->lexer)->location;
+  id = cp_parser_identifier (parser);
+  cp_parser_require (parser, CPP_EQ, RT_EQ);
+
+  type = cp_parser_type_id (parser);
+
+  /* A typedef-name can also be introduced by an alias-declaration. The
+     identifier following the using keyword becomes a typedef-name. It has
+     the same semantics as if it were introduced by the typedef
+     specifier. In particular, it does not define a new type and it shall
+     not appear in the type-id.  */
+
+  clear_decl_specs (&decl_specs);
+  decl_specs.type = type;
+  ++decl_specs.specs[(int) ds_typedef];
+  ++decl_specs.specs[(int) ds_alias];
+
+  declarator = make_id_declarator (NULL_TREE, id, sfk_none);
+  declarator->id_loc = id_location;
+
+  if (at_class_scope_p ())
+    decl = grokfield (declarator, &decl_specs, NULL_TREE, false,
+		      NULL_TREE, NULL_TREE);
+  else
+    decl = start_decl (declarator, &decl_specs, 0,
+		       NULL_TREE, NULL_TREE, &dummy);
+  if (decl == error_mark_node)
+    return decl;
+
+  cp_finish_decl (decl, NULL_TREE, 0, NULL_TREE, 0);
+
+  /* If decl is a template, return its TEMPLATE_DECL so that it gets
+     added into the symbol table; otherwise, return the TYPE_DECL.  */
+  if (DECL_LANG_SPECIFIC (decl)
+      && DECL_TEMPLATE_INFO (decl)
+      && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl)))
+    decl = DECL_TI_TEMPLATE (decl);
+  return decl;
+}
+
 /* Parse a using-directive.
 
    using-directive:
@@ -18528,6 +18621,7 @@  cp_parser_member_specification_opt (cp_parser* parser)
      :: [opt] nested-name-specifier template [opt] unqualified-id ;
      using-declaration
      template-declaration
+     alias-declaration
 
    member-declarator-list:
      member-declarator
@@ -18595,10 +18689,25 @@  cp_parser_member_declaration (cp_parser* parser)
   /* Check for a using-declaration.  */
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_USING))
     {
-      /* Parse the using-declaration.  */
-      cp_parser_using_declaration (parser,
-				   /*access_declaration_p=*/false);
-      return;
+      if (cxx_dialect < cxx0x)
+	{
+	  /* Parse the using-declaration.  */
+	  cp_parser_using_declaration (parser,
+				       /*access_declaration_p=*/false);
+	  return;
+	}
+      else
+	{
+	  tree decl;
+	  cp_parser_parse_tentatively (parser);
+	  decl = cp_parser_alias_declaration (parser);
+	  if (cp_parser_parse_definitely (parser))
+	    finish_member_declaration (decl);
+	  else
+	    cp_parser_using_declaration (parser,
+					 /*access_declaration_p=*/false);
+	  return;
+	}
     }
 
   /* Check for @defs.  */
@@ -20889,6 +20998,9 @@  cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
   if (cp_lexer_next_token_is_keyword (parser->lexer,
 				      RID_TEMPLATE))
     cp_parser_template_declaration_after_export (parser, member_p);
+  else if (cxx_dialect >= cxx0x
+	   && cp_lexer_next_token_is_keyword (parser->lexer, RID_USING))
+    decl = cp_parser_alias_declaration (parser);
   else
     {
       /* There are no access checks when parsing a template, as we do not
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 7aea72d..3f9cbd3 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -814,7 +814,13 @@  maybe_process_partial_specialization (tree type)
 
   context = TYPE_CONTEXT (type);
 
-  if (CLASS_TYPE_P (type) && CLASSTYPE_USE_TEMPLATE (type))
+  if ((CLASS_TYPE_P (type) && CLASSTYPE_USE_TEMPLATE (type))
+      /* Consider non-class instantiations of alias templates as
+	 well.  */
+      || (TYPE_P (type)
+	  && TYPE_TEMPLATE_INFO (type)
+	  && DECL_LANG_SPECIFIC (TYPE_NAME (type))
+	  && DECL_USE_TEMPLATE (TYPE_NAME (type))))
     {
       /* This is for ordinary explicit specialization and partial
 	 specialization of a template class such as:
@@ -827,7 +833,8 @@  maybe_process_partial_specialization (tree type)
 
 	 Make sure that `C<int>' and `C<T*>' are implicit instantiations.  */
 
-      if (CLASSTYPE_IMPLICIT_INSTANTIATION (type)
+      if (CLASS_TYPE_P (type)
+	  && CLASSTYPE_IMPLICIT_INSTANTIATION (type)
 	  && !COMPLETE_TYPE_P (type))
 	{
 	  check_specialization_namespace (CLASSTYPE_TI_TEMPLATE (type));
@@ -839,8 +846,16 @@  maybe_process_partial_specialization (tree type)
 		return error_mark_node;
 	    }
 	}
-      else if (CLASSTYPE_TEMPLATE_INSTANTIATION (type))
+      else if (CLASS_TYPE_P (type)
+	       && CLASSTYPE_TEMPLATE_INSTANTIATION (type))
 	error ("specialization of %qT after instantiation", type);
+
+      if (DECL_ALIAS_TEMPLATE_P (TYPE_TI_TEMPLATE (type)))
+	{
+	  error ("partial specialization of alias template %qD",
+		 TYPE_TI_TEMPLATE (type));
+	  return error_mark_node;
+	}
     }
   else if (CLASS_TYPE_P (type)
 	   && !CLASSTYPE_USE_TEMPLATE (type)
@@ -2842,8 +2857,8 @@  make_ith_pack_parameter_name (tree name, int i)
   return get_identifier (newname);
 }
 
-/* Return true if T is a primary function
-   or class template instantiation.  */
+/* Return true if T is a primary function, class or alias template
+   instantiation.  */
 
 bool
 primary_template_instantiation_p (const_tree t)
@@ -2858,6 +2873,11 @@  primary_template_instantiation_p (const_tree t)
   else if (CLASS_TYPE_P (t))
     return CLASSTYPE_TEMPLATE_INSTANTIATION (t)
 	   && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t));
+  else if (TYPE_P (t)
+	   && TYPE_TEMPLATE_INFO (t)
+	   && PRIMARY_TEMPLATE_P (TYPE_TI_TEMPLATE (t))
+	   && DECL_TEMPLATE_INSTANTIATION (TYPE_NAME (t)))
+    return true;
   return false;
 }
 
@@ -4831,6 +4851,10 @@  push_template_decl_real (tree decl, bool is_friend)
       else if (DECL_IMPLICIT_TYPEDEF_P (decl)
 	       && CLASS_TYPE_P (TREE_TYPE (decl)))
 	/* OK */;
+      else if (TREE_CODE (decl) == TYPE_DECL
+	       && TYPE_DECL_ALIAS_P (decl))
+	/* alias-declaration */
+	gcc_assert (!DECL_ARTIFICIAL (decl));
       else
 	{
 	  error ("template declaration of %q#D", decl);
@@ -5095,8 +5119,13 @@  template arguments to %qD do not match original template %qD",
 
   if (DECL_IMPLICIT_TYPEDEF_P (decl))
     SET_TYPE_TEMPLATE_INFO (TREE_TYPE (tmpl), info);
-  else if (DECL_LANG_SPECIFIC (decl))
-    DECL_TEMPLATE_INFO (decl) = info;
+  else
+    {
+      if (primary && !DECL_LANG_SPECIFIC (decl))
+	retrofit_lang_decl (decl);
+      if (DECL_LANG_SPECIFIC (decl))
+	DECL_TEMPLATE_INFO (decl) = info;
+    }
 
   return DECL_TEMPLATE_RESULT (tmpl);
 }
@@ -5259,6 +5288,33 @@  fold_non_dependent_expr (tree expr)
   return fold_non_dependent_expr_sfinae (expr, tf_error);
 }
 
+/* Return TRUE iff T is a type alias, a TEMPLATE_DECL for an alias
+   template declaration, or a TYPE_DECL for an alias declaration.  */
+
+bool
+alias_type_or_template_p (tree t)
+{
+  if (t == NULL_TREE)
+    return false;
+  return ((TREE_CODE (t) == TYPE_DECL && TYPE_DECL_ALIAS_P (t))
+	  || (TYPE_P (t)
+	      && TYPE_NAME (t)
+	      && TREE_CODE (TYPE_NAME (t)) == TYPE_DECL
+	      && TYPE_DECL_ALIAS_P (TYPE_NAME (t)))
+	  || DECL_ALIAS_TEMPLATE_P (t));
+}
+
+/* Return TRUE iff is a specialization of an alias template.  */
+
+bool
+alias_template_specialization_p (tree t)
+{
+  if (t == NULL_TREE)
+    return false;
+  return (primary_template_instantiation_p (t)
+	  && DECL_ALIAS_TEMPLATE_P (TYPE_TI_TEMPLATE (t)));
+}
+
 /* Subroutine of convert_nontype_argument. Converts EXPR to TYPE, which
    must be a function or a pointer-to-function type, as specified
    in [temp.arg.nontype]: disambiguate EXPR if it is an overload set,
@@ -7355,7 +7411,31 @@  lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
 	  ENUM_FIXED_UNDERLYING_TYPE_P (t)
 	    = ENUM_FIXED_UNDERLYING_TYPE_P (template_type);
 	}
-      else
+      else if (DECL_ALIAS_TEMPLATE_P (gen_tmpl))
+	{
+	  /* The user referred to a specialization of an alias
+	    template represented by GEN_TMPL.
+
+	    [temp.alias]/2 says:
+
+	        When a template-id refers to the specialization of an
+		alias template, it is equivalent to the associated
+		type obtained by substitution of its
+		template-arguments for the template-parameters in the
+		type-id of the alias template.  */
+
+	  t = tsubst (TREE_TYPE (gen_tmpl), arglist, complain, in_decl);
+	  /* Note that the call above (by indirectly calling
+	     register_specialization in tsubst_decl) registers the
+	     TYPE_DECL representing the specialization of the alias
+	     template.  So next time someone substitutes ARGLIST for
+	     the template parms into the alias template (GEN_TMPL),
+	     she'll get that TYPE_DECL back.  */
+
+	  if (t == error_mark_node)
+	    return t;
+	}
+      else if (CLASS_TYPE_P (template_type))
 	{
 	  t = make_class_type (TREE_CODE (template_type));
 	  CLASSTYPE_DECLARED_CLASS (t)
@@ -7378,6 +7458,8 @@  lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
 	       structural equality testing. */
 	    SET_TYPE_STRUCTURAL_EQUALITY (t);
 	}
+      else
+	gcc_unreachable ();
 
       /* If we called start_enum or pushtag above, this information
 	 will already be set up.  */
@@ -7393,14 +7475,17 @@  lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
       else
 	type_decl = TYPE_NAME (t);
 
-      TREE_PRIVATE (type_decl)
-	= TREE_PRIVATE (TYPE_STUB_DECL (template_type));
-      TREE_PROTECTED (type_decl)
-	= TREE_PROTECTED (TYPE_STUB_DECL (template_type));
-      if (CLASSTYPE_VISIBILITY_SPECIFIED (template_type))
+      if (CLASS_TYPE_P (template_type))
 	{
-	  DECL_VISIBILITY_SPECIFIED (type_decl) = 1;
-	  DECL_VISIBILITY (type_decl) = CLASSTYPE_VISIBILITY (template_type);
+	  TREE_PRIVATE (type_decl)
+	    = TREE_PRIVATE (TYPE_STUB_DECL (template_type));
+	  TREE_PROTECTED (type_decl)
+	    = TREE_PROTECTED (TYPE_STUB_DECL (template_type));
+	  if (CLASSTYPE_VISIBILITY_SPECIFIED (template_type))
+	    {
+	      DECL_VISIBILITY_SPECIFIED (type_decl) = 1;
+	      DECL_VISIBILITY (type_decl) = CLASSTYPE_VISIBILITY (template_type);
+	    }
 	}
 
       /* Let's consider the explicit specialization of a member
@@ -7456,7 +7541,7 @@  lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
 	  ++processing_template_decl;
 	  partial_inst_args =
 	    tsubst (INNERMOST_TEMPLATE_ARGS
-			(CLASSTYPE_TI_ARGS (TREE_TYPE (gen_tmpl))),
+			(TYPE_TI_ARGS (TREE_TYPE (gen_tmpl))),
 		    arglist, complain, NULL_TREE);
 	  --processing_template_decl;
 	  TREE_VEC_LENGTH (arglist)++;
@@ -7480,7 +7565,15 @@  lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
 	  TREE_VEC_LENGTH (arglist)--;
 	  found = tsubst (gen_tmpl, arglist, complain, NULL_TREE);
 	  TREE_VEC_LENGTH (arglist)++;
-	  found = CLASSTYPE_TI_TEMPLATE (found);
+	  /* FOUND is either a proper class type, or an alias
+	     template specialization.  In the later case, it's a
+	     TYPE_DECL, resulting from the substituting of arguments
+	     for parameters in the TYPE_DECL of the alias template
+	     done earlier.  So be careful while getting the template
+	     of FOUND.  */
+	  found = TREE_CODE (found) == TYPE_DECL
+	    ? TYPE_TI_TEMPLATE (TREE_TYPE (found))
+	    : CLASSTYPE_TI_TEMPLATE (found);
 	}
 
       SET_TYPE_TEMPLATE_INFO (t, build_template_info (found, arglist));
@@ -7508,7 +7601,7 @@  lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
 	   the instantiation and exit above.  */
 	tsubst_enum (template_type, t, arglist);
 
-      if (is_dependent_type)
+      if (CLASS_TYPE_P (template_type) && is_dependent_type)
 	/* If the type makes use of template parameters, the
 	   code that generates debugging information will crash.  */
 	DECL_IGNORED_P (TYPE_STUB_DECL (t)) = 1;
@@ -9843,7 +9936,8 @@  tsubst_decl (tree t, tree args, tsubst_flags_t complain)
 
 	DECL_TEMPLATE_INFO (r) = build_template_info (t, args);
 
-	if (TREE_CODE (decl) == TYPE_DECL)
+	if (TREE_CODE (decl) == TYPE_DECL
+	    && !TYPE_DECL_ALIAS_P (decl))
 	  {
 	    tree new_type;
 	    ++processing_template_decl;
@@ -10376,8 +10470,15 @@  tsubst_decl (tree t, tree args, tsubst_flags_t complain)
 		   referencing a static data member within in its own
 		   class.  We can use pointer equality, rather than
 		   same_type_p, because DECL_CONTEXT is always
-		   canonical.  */
-		if (ctx == DECL_CONTEXT (t))
+		   canonical...  */
+		if (ctx == DECL_CONTEXT (t)
+		    && (TREE_CODE (t) != TYPE_DECL
+			/* ... unless T is a member template; in which
+			   case our caller can be willing to create a
+			   specialization of that template represented
+			   by T.  */
+			|| !(DECL_TI_TEMPLATE (t)
+			     && DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (t)))))
 		  spec = t;
 	      }
 
@@ -10858,7 +10959,7 @@  tree
 tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 {
   enum tree_code code;
-  tree type, r;
+  tree type, r = NULL_TREE;
 
   if (t == NULL_TREE || t == error_mark_node
       || t == integer_type_node
@@ -10903,10 +11004,21 @@  tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 	       && DECL_TEMPLATE_INFO (DECL_CONTEXT (decl))
 	       && uses_template_parms (DECL_TI_ARGS (DECL_CONTEXT (decl))))
 	r = retrieve_local_specialization (decl);
+      else if (TYPE_DECL_ALIAS_P (decl))
+	/* Fall through.  */;
       else
 	/* The typedef is from a non-template context.  */
 	return t;
 
+      if (r == NULL_TREE && TYPE_DECL_ALIAS_P (decl))
+	{
+	  /* DECL represents an alias declaration, possibly an alias
+	     template.  Let's substitute our arguments for the
+	     template parameters into the declaration and get the
+	     resulting type.  */
+	  r = tsubst (decl, args, complain, decl);
+	}
+
       if (r)
 	{
 	  r = TREE_TYPE (r);
@@ -11043,6 +11155,46 @@  tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 		if (argvec == error_mark_node)
 		  return error_mark_node;
 
+		gcc_assert (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
+			    || TREE_CODE (arg) == TEMPLATE_DECL
+			    || TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE);
+
+		if (TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE)
+		  /* Consider this code:
+
+			template <template <class> class Template>
+			struct Internal {
+			template <class Arg> using Bind = Template<Arg>;
+			};
+
+			template <template <class> class Template, class Arg>
+			using Instantiate = Template<Arg>; //#0
+
+			template <template <class> class Template,
+                                  class Argument>
+			using Bind =
+			  Instantiate<Internal<Template>::template Bind,
+				      Argument>; //#1
+
+		     When #1 is parsed, the
+		     BOUND_TEMPLATE_TEMPLATE_PARM representing the
+		     parameter `Template' in #0 matches the
+		     UNBOUND_CLASS_TEMPLATE representing the argument
+		     `Internal<Template>::template Bind'; We then want
+		     to assemble the type `Bind<Argument>' that can't
+		     be fully created right now, because
+		     `Internal<Template>' not being complete, the Bind
+		     template cannot be looked up in that context.  So
+		     we need to "store" `Bind<Argument>' for later
+		     when the context of Bind becomes complete.  Let's
+		     store that in a TYPENAME_TYPE.  */
+		  return make_typename_type (TYPE_CONTEXT (arg),
+					     build_nt (TEMPLATE_ID_EXPR,
+						       TYPE_IDENTIFIER (arg),
+						       argvec),
+					     typename_type,
+					     complain);
+
 		/* We can get a TEMPLATE_TEMPLATE_PARM here when we
 		   are resolving nested-types in the signature of a
 		   member function templates.  Otherwise ARG is a
@@ -17608,7 +17760,12 @@  do_type_instantiation (tree t, tree storage, tsubst_flags_t complain)
 
   if (! CLASS_TYPE_P (t) || ! CLASSTYPE_TEMPLATE_INFO (t))
     {
-      error ("explicit instantiation of non-template type %qT", t);
+      tree tmpl =
+	(TYPE_TEMPLATE_INFO (t)) ? TYPE_TI_TEMPLATE (t) : NULL;
+      if (tmpl)
+	error ("explicit instantiation of non-class template %qD", tmpl);
+      else
+	error ("explicit instantiation of non-template type %qT", t);
       return;
     }
 
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index 97f593c..a59cd07 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -427,7 +427,7 @@  lookup_field_1 (tree type, tree name, bool want_type)
 		    field = fields[i--];
 		  while (i >= lo && DECL_NAME (fields[i]) == name);
 		  if (TREE_CODE (field) != TYPE_DECL
-		      && !DECL_CLASS_TEMPLATE_P (field))
+		      && !DECL_TYPE_TEMPLATE_P (field))
 		    field = NULL_TREE;
 		}
 	      else
@@ -478,7 +478,7 @@  lookup_field_1 (tree type, tree name, bool want_type)
       if (DECL_NAME (field) == name
 	  && (!want_type
 	      || TREE_CODE (field) == TYPE_DECL
-	      || DECL_CLASS_TEMPLATE_P (field)))
+	      || DECL_TYPE_TEMPLATE_P (field)))
 	return field;
     }
   /* Not found.  */
@@ -1046,7 +1046,7 @@  lookup_field_r (tree binfo, void *data)
   /* If we're looking up a type (as with an elaborated type specifier)
      we ignore all non-types we find.  */
   if (lfi->want_type && TREE_CODE (nval) != TYPE_DECL
-      && !DECL_CLASS_TEMPLATE_P (nval))
+      && !DECL_TYPE_TEMPLATE_P (nval))
     {
       if (lfi->name == TYPE_IDENTIFIER (type))
 	{
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index fa8ab99..7be828e 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -2733,15 +2733,17 @@  finish_template_decl (tree parms)
 tree
 finish_template_type (tree name, tree args, int entering_scope)
 {
-  tree decl;
+  tree type;
 
-  decl = lookup_template_class (name, args,
+  type = lookup_template_class (name, args,
 				NULL_TREE, NULL_TREE, entering_scope,
 				tf_warning_or_error | tf_user);
-  if (decl != error_mark_node)
-    decl = TYPE_STUB_DECL (decl);
-
-  return decl;
+  if (type == error_mark_node)
+    return type;
+  else if (CLASS_TYPE_P (type) && !alias_type_or_template_p (type))
+    return TYPE_STUB_DECL (type);
+  else
+    return TYPE_NAME (type);
 }
 
 /* Finish processing a BASE_CLASS with the indicated ACCESS_SPECIFIER.
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-0.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-0.C
new file mode 100644
index 0000000..c5760cf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-0.C
@@ -0,0 +1,37 @@ 
+// { dg-options "-std=c++0x" }
+
+template<template<class> class TT> struct X { };
+template<class> struct Y { };
+template<class T> using Z = Y<T>;
+
+void f(X<Y>);
+void g(X<Z>);
+
+void
+foo()
+{
+    // Below x and y don't have the same type, because Y and Z don't
+    // designate the same template ...
+    X<Y> y; 
+    X<Z> z;
+
+    // ... So these must fail to compile.
+    f(z);   // { dg-error "" }
+    g(y);   // { dg-error "" }
+}
+
+template<class> struct A0 {};
+template<class T> using AA0 = A0<T>;
+template<class T> using AAA0 = AA0<T>;
+
+void f0(A0<int>);
+void
+g0()
+{
+  AA0<int> a;
+  AAA0<int> b;
+  f0(a);
+  f0(b);
+}
+
+
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C
new file mode 100644
index 0000000..d0eda5f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C
@@ -0,0 +1,15 @@ 
+// { dg-options "-std=c++0x" }
+
+// These also represent tests for printing alias declarations and
+// their instantiations.
+
+template<class T, class U> struct A0 {};
+template<class T, class U> using AA0 = A0<T, U>;
+template<class T> struct AA0<int, T> {}; // { dg-error "partial specialization" }
+
+template <class U> using Ptr = U*;
+template<class U> struct Ptr<U*> {}; // { dg-error "partial specialization" }
+
+struct A {
+    using A = int;//{ dg-error "nested|has|same name as|class|in which|declared" }
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-10.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-10.C
new file mode 100644
index 0000000..856e429
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-10.C
@@ -0,0 +1,18 @@ 
+// { dg-options "-std=c++0x" }
+
+template <class T> using Ptr = T*;
+Ptr<unsigned>; // { dg-error "does not declare anything" }
+Ptr<char><int>; // { dg-error "not a template|does not declare anything" }
+template class Ptr<int>;//{ dg-error "explicit instantiation|non-class templ|does not decl|anything" }
+
+template <class T> using Arg = T;
+struct A {};
+template class Arg<A>;// { dg-error "explicit instantiation|non-class templ" }
+
+template <template <class> class TT, class T> using Instantiate = TT<T>;
+template <class> struct Vector {};
+template class Instantiate<Vector, int>; // OK Vector<int> can be explicitely instantiated
+
+template <class T> struct S {};
+template<class T> using SFor = S<T>;
+template class SFor<int>; // OK, S<int> can be explicitely instantiated
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-2.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-2.C
new file mode 100644
index 0000000..2e03dd8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-2.C
@@ -0,0 +1,33 @@ 
+// { dg-options "-std=c++0x" }
+
+template<class T> struct S0 {};
+template<class T> using AS0 = S0<T>;
+
+template<template<class> class TT>
+void f(TT<int>);
+
+template class AS0<char>;
+
+void
+foo()
+{
+  AS0<int> a;
+  f(a);
+}
+
+template<class T, class U> struct Vector{};
+template<class T> struct Alloc {};
+
+template<class T> using Vec = Vector<T, Alloc<T> >;
+
+template<class T> void g(Vector<T, Alloc<T> >);
+
+template<template<class T> class TT> void h(TT<int>); // { dg-error "provided for" }
+
+void
+bar()
+{
+  Vec<int> a;
+  g(a);
+  h(a); // { dg-error "no matching function|wrong number of template arguments" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-3.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-3.C
new file mode 100644
index 0000000..5484efc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-3.C
@@ -0,0 +1,42 @@ 
+// { dg-options "-std=c++0x" }
+
+// Exercise some member alias templates ...
+
+template<class T, class U> class A0 {};
+
+template<class T>
+struct A1 {
+    template<class U> struct S {};
+    template<class U> using AA0 = A0<T, U>;
+
+  void f(A0<T, int>);
+
+  void
+  foo()
+  {
+    AA0<int> a;
+    const AA0<int> b;
+    f(a);
+    f(b);
+  }
+};
+
+void
+bar()
+{
+    A1<int> a1;
+    a1.foo();
+    A1<int>::AA0<int> a1aa0;
+    a1.f(a1aa0);
+}
+
+// ... some simple member alias ...
+struct B {
+    using A = int;
+};
+
+B::A a;
+
+// ... and some simple alias
+
+using Int = int;
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-4.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-4.C
new file mode 100644
index 0000000..876944e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-4.C
@@ -0,0 +1,14 @@ 
+// { dg-options "-std=c++0x" }
+
+// [temp.alias]/3:
+// The type-id in an alias template declaration shall not refer
+// to the alias template being declared. The type produced by an
+// alias template specialization shall not directly or indirectly
+// make use of that specialization.
+
+template <class T> struct A;
+template <class T> using B = typename A<T>::U; // { dg-error "type" }
+template <class T> struct A {
+    typedef B<T> U;
+};
+B<short> b; // { dg-error "invalid type" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-5.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-5.C
new file mode 100644
index 0000000..1a4cbd5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-5.C
@@ -0,0 +1,34 @@ 
+// { dg-options "-std=c++0x" }
+
+// alias template of a partial specialization
+
+template<class T, class U, class W> struct S0 {};
+template<class T, class U> struct S0<T, U, char> {};
+template<class T> using AS0 = S0<T, int, char>;
+void foo(S0<bool, int, char>);
+
+AS0<bool> a; // OK
+
+void
+f()
+{
+    foo(a); //OK
+}
+
+// alias template of an explicit specialization of a member template
+
+template<class T>
+struct S1 {
+    template<class U>
+    struct M {};
+};
+template<class T> using AM = S1<int>::M<T>;
+void bar(S1<int>::M<bool>);
+
+AM<bool> b; //OK.
+
+void
+g()
+{
+    bar(b); //OK
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-6.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-6.C
new file mode 100644
index 0000000..f60b2ea
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-6.C
@@ -0,0 +1,12 @@ 
+// { dg-options "-std=c++0x" }
+
+// Alias template of non-class types.
+
+template <class T, class U> struct same;
+template <class T> struct same<T,T> {};
+
+template <class T> using Ptr = T*;
+template <template <class> class T> struct A {
+  template <class U> using X = T<U>;
+};
+same<A<Ptr>::X<int>,int*> s;
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-7.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-7.C
new file mode 100644
index 0000000..96c349a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-7.C
@@ -0,0 +1,23 @@ 
+// { dg-options "-std=c++0x" }
+
+// Add arguments to unbound template template parameter.
+
+template <template <class> class Template>
+struct Internal {
+  template <class Arg> using Bind = Template<Arg>;
+};
+
+template <template <class> class Template, class Arg>
+using Instantiate = Template<Arg>; // After parsing #1, the
+                                   // BOUND_TEMPLATE_TEMPLATE_PARM
+                                   // parameter Template gets
+                                   // the UNBOUND_CLASS_TEMPLATE
+                                   // Internal<Template>::template Bind
+                                   // as an argument, and the
+                                   // parameter Arg gets Argument as
+                                   // an argument.  And we build
+                                   // 'Bind<Argument>'.
+
+template <template <class> class Template, class Argument>
+using Bind = Instantiate<Internal<Template>::template Bind, Argument>; //#1
+
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-8.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-8.C
new file mode 100644
index 0000000..c926df7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-8.C
@@ -0,0 +1,32 @@ 
+// { dg-options "-std=c++0x" }
+
+struct A {
+    template <class U> using C = U;
+};
+
+// The particularity of the below struct is to have more than 7
+// fields.  In this case, looking up a member here should exercise
+// cp/search.c:lookup_field_1 in such a way that it finds it in the
+// CLASSTYPE_SORTED_FIELDS of struct A7.
+struct A7 {
+  int f0;
+  int f1;
+  int f2;
+  int f3;
+  int f4;
+  int f5;
+  int f6;
+  int f7;
+  template <class U> using C = U;
+};
+
+template <class T>
+struct B {
+    typename T::template C<int> n;  //#0
+};
+
+// These should trigger the lookup
+// of template C inside class A or
+// A7, via #0.
+B<A> b;
+B<A7> c;
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-9.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-9.C
new file mode 100644
index 0000000..dcf642d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-9.C
@@ -0,0 +1,9 @@ 
+// { dg-options "-std=c++0x" }
+
+template <class T>
+struct A {
+    using Result = T;
+};
+template <class A> using Arg = typename A::Result;
+Arg<A<int>> b;
+