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

login
register
mail settings
Submitter Dodji Seketeli
Date Nov. 7, 2011, 3:54 p.m.
Message ID <m3y5vskjx1.fsf@redhat.com>
Download mbox | patch
Permalink /patch/124119/
State New
Headers show

Comments

Dodji Seketeli - Nov. 7, 2011, 3:54 p.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.

Removed, thanks.

> 
> > +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.

I didn't realize the elaborated-type-specifier case.  Fixed now.

> 
> > +      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.

Fixed.

> 
> > -  /* 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.

Oops, fixed.  Thanks.

> 
> > +      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.

I did that initially and it revealed that the assertion can be
violated by erroneous input code, e.g (in the test
g++.dg/cpp0x/vt-34055.C):

    template<typename...> struct B;
    template<typename...T> struct B<T&> // { dg-error "parameter packs|T" }
    {
      void foo();
    };

Hence the recoverable error approach here.  So I am now just asserting
the DECL_TEMPLATE_INSTANTIATION when the TYPE_DECL is for an alias
declaration.  Is that better?

> 
> > -         || (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.

I wonder why I added that check there.  Removed now.

> 
> >> 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.

Ah, I see.

> I think if you check alias_template_specialization_p before checking
> for class/function scope that should handle the cases you need.

alias_template_specialization_p wouldn't work as we'd miss the case
where we precisely want to build an instantiation from an alias
template.  So maybe the below is better?

Thinking about that part of the code, I realized that the former patch
didn't support (GNU extension) attributes so that part of the code
wasn't tested enough.  I have thus added new tests that are a slight
modification of the g++.dg/cpp0x/ext/tmplattr*.C tests to use the
alias-template syntax and exercise that part of the code.

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

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_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 printing of alias templates and their
	specializations.  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.
	* g++.dg/ext/alias-decl-attr1.C: Likewise.
	* g++.dg/ext/alias-decl-attr2.C: Likewise.
	* g++.dg/ext/alias-decl-attr3.C: Likewise.
	* g++.dg/ext/alias-decl-attr4.C: Likewise.
---
 gcc/cp/cp-tree.h                            |   46 +++++-
 gcc/cp/decl.c                               |    9 +-
 gcc/cp/decl2.c                              |    9 +-
 gcc/cp/error.c                              |   55 ++++++-
 gcc/cp/parser.c                             |  141 ++++++++++++++++--
 gcc/cp/pt.c                                 |  210 +++++++++++++++++++++++----
 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 +
 gcc/testsuite/g++.dg/ext/alias-decl-attr1.C |   19 +++
 gcc/testsuite/g++.dg/ext/alias-decl-attr2.C |   42 ++++++
 gcc/testsuite/g++.dg/ext/alias-decl-attr3.C |   21 +++
 gcc/testsuite/g++.dg/ext/alias-decl-attr4.C |   34 +++++
 23 files changed, 806 insertions(+), 69 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
 create mode 100644 gcc/testsuite/g++.dg/ext/alias-decl-attr1.C
 create mode 100644 gcc/testsuite/g++.dg/ext/alias-decl-attr2.C
 create mode 100644 gcc/testsuite/g++.dg/ext/alias-decl-attr3.C
 create mode 100644 gcc/testsuite/g++.dg/ext/alias-decl-attr4.C
Jason Merrill - Nov. 7, 2011, 6:27 p.m.
On 11/07/2011 10:54 AM, Dodji Seketeli wrote:
> I didn't realize the elaborated-type-specifier case.  Fixed now.

There still seem to be problems printing the scope:

namespace N
{
   template <class T> using U = T*;
};

void f(N::U<int>) { blah; }

------------
wa.C: In function ‘void N::f(U<int>)’:
wa.C:6:21: error: ‘blah’ was not declared in this scope

Note how the N:: is attached to the function rather than the parameter 
type.  I wonder how that happens...

But this patch is close enough; go ahead and check it in as is and fix 
this issue afterwards.

Jason
H.J. Lu - Nov. 8, 2011, 7:48 p.m.
On Mon, Nov 7, 2011 at 7:54 AM, Dodji Seketeli <dodji@redhat.com> wrote:
>> 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.
>
> Removed, thanks.
>
>>
>> > +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.
>
> I didn't realize the elaborated-type-specifier case.  Fixed now.
>
>>
>> > +      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.
>
> Fixed.
>
>>
>> > -  /* 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.
>
> Oops, fixed.  Thanks.
>
>>
>> > +      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.
>
> I did that initially and it revealed that the assertion can be
> violated by erroneous input code, e.g (in the test
> g++.dg/cpp0x/vt-34055.C):
>
>    template<typename...> struct B;
>    template<typename...T> struct B<T&> // { dg-error "parameter packs|T" }
>    {
>      void foo();
>    };
>
> Hence the recoverable error approach here.  So I am now just asserting
> the DECL_TEMPLATE_INSTANTIATION when the TYPE_DECL is for an alias
> declaration.  Is that better?
>
>>
>> > -         || (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.
>
> I wonder why I added that check there.  Removed now.
>
>>
>> >> 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.
>
> Ah, I see.
>
>> I think if you check alias_template_specialization_p before checking
>> for class/function scope that should handle the cases you need.
>
> alias_template_specialization_p wouldn't work as we'd miss the case
> where we precisely want to build an instantiation from an alias
> template.  So maybe the below is better?
>
> Thinking about that part of the code, I realized that the former patch
> didn't support (GNU extension) attributes so that part of the code
> wasn't tested enough.  I have thus added new tests that are a slight
> modification of the g++.dg/cpp0x/ext/tmplattr*.C tests to use the
> alias-template syntax and exercise that part of the code.
>
> Bootstrapped and tested on x86_64-unknown-linux-gnu against trunk.
>
> 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_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 printing of alias templates and their
>        specializations.  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.
>

This caused:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51036

Patch

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 7ff1491..02ee289 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,17 @@  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 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 +2609,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 +3635,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 +4606,7 @@  typedef enum cp_decl_spec {
   ds_explicit,
   ds_friend,
   ds_typedef,
+  ds_alias,
   ds_constexpr,
   ds_complex,
   ds_thread,
@@ -5282,6 +5310,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..b592daa 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,23 @@  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)
+{
+  tree name;
+
+  gcc_assert (alias_template_specialization_p (t));
+
+  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.  */
 
@@ -344,10 +362,15 @@  dump_type (tree t, int flags)
     {
       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)))
+	       || DECL_SELF_REFERENCE_P (decl)
+	       || (!flag_pretty_templates
+		   && DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)))
 	t = strip_typedefs (t);
+      else if (alias_template_specialization_p (t))
+	{
+	  dump_alias_template_specialization (t, flags);
+	  return;
+	}
       else if (same_type_p (t, TREE_TYPE (decl)))
 	t = decl;
       else
@@ -588,7 +611,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 +639,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 +978,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 +1234,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..00d6b02 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."
@@ -10150,8 +10153,8 @@  cp_parser_block_declaration (cp_parser *parser,
      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,14 @@  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_lexer_peek_nth_token (parser->lexer, 3)->keyword
+		       == RID_ATTRIBUTE)))
+	cp_parser_alias_declaration (parser);
       /* Otherwise, it's a using-declaration.  */
       else
 	cp_parser_using_declaration (parser,
@@ -12343,7 +12354,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 +13622,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 +13650,37 @@  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))
+	gcc_assert (DECL_TEMPLATE_INSTANTIATION (type_decl));
+      else
+	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 +14872,63 @@  cp_parser_using_declaration (cp_parser* parser,
   return true;
 }
 
+/* Parse an alias-declaration.
+
+   alias-declaration:
+     using identifier attribute-specifier-seq [opt] = type-id  */
+
+static tree
+cp_parser_alias_declaration (cp_parser* parser)
+{
+  tree id, type, decl, dummy, attributes;
+  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);
+  attributes = cp_parser_attributes_opt (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.attributes = attributes;
+  ++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, attributes);
+  else
+    decl = start_decl (declarator, &decl_specs, 0,
+		       attributes, 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 +18626,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 +18694,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 +21003,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..2576483 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,32 @@  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)
+	      && 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 +7410,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 +7457,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 +7474,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 +7540,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 +7564,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 +7600,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 +9935,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 +10469,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 +10958,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
@@ -10890,10 +10990,21 @@  tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
       && typedef_variant_p (t))
     {
       tree decl = TYPE_NAME (t);
-      
-      if (DECL_CLASS_SCOPE_P (decl)
-	  && CLASSTYPE_TEMPLATE_INFO (DECL_CONTEXT (decl))
-	  && uses_template_parms (DECL_CONTEXT (decl)))
+
+      if (TYPE_DECL_ALIAS_P (decl)
+	  && DECL_LANG_SPECIFIC (decl)
+	  && DECL_TEMPLATE_INFO (decl)
+	  && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl)))
+	{
+	  /* DECL represents an alias template and we want to
+	     instantiate it.  Let's substitute our arguments for the
+	     template parameters into the declaration and get the
+	     resulting type.  */
+	  r = tsubst (decl, args, complain, decl);
+	}
+      else if (DECL_CLASS_SCOPE_P (decl)
+	       && CLASSTYPE_TEMPLATE_INFO (DECL_CONTEXT (decl))
+	       && uses_template_parms (DECL_CONTEXT (decl)))
 	{
 	  tree tmpl = most_general_template (DECL_TI_TEMPLATE (decl));
 	  tree gen_args = tsubst (DECL_TI_ARGS (decl), args, complain, in_decl);
@@ -11043,6 +11154,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 +17759,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;
+
diff --git a/gcc/testsuite/g++.dg/ext/alias-decl-attr1.C b/gcc/testsuite/g++.dg/ext/alias-decl-attr1.C
new file mode 100644
index 0000000..e83fe44
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/alias-decl-attr1.C
@@ -0,0 +1,19 @@ 
+// { dg-options "-std=c++0x" }
+
+template <unsigned Len, unsigned Align>
+struct aligned_storage
+{
+    using type __attribute__((aligned((Align)))) =
+        char[Len];
+};
+
+template<typename T>
+struct X
+{
+  typename aligned_storage<sizeof(T),__alignof(T)>::type data;
+};
+
+template<bool> struct StaticAssert;
+template<> struct StaticAssert<true> {};
+
+StaticAssert<__alignof (X<double>) == __alignof (double)> dummy;
diff --git a/gcc/testsuite/g++.dg/ext/alias-decl-attr2.C b/gcc/testsuite/g++.dg/ext/alias-decl-attr2.C
new file mode 100644
index 0000000..83e557c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/alias-decl-attr2.C
@@ -0,0 +1,42 @@ 
+// { dg-options "-std=c++0x" }
+
+template<typename T>
+struct X {
+    using layout_type __attribute ((aligned(__alignof(double)))) =
+        char[sizeof(T)];
+    layout_type data;
+};
+
+template<typename T>
+struct Y {
+    using layout_type  __attribute ((aligned(__alignof(T)))) =
+        char[sizeof(T)];
+    layout_type data;
+};
+
+template<typename T>
+struct Z {
+    using layout_type __attribute ((aligned(__alignof(T)))) =
+        char[sizeof(T)];
+    struct Z2 {
+        layout_type data;
+    } in;
+};
+
+template<typename T>
+struct A;
+
+template <typename T>
+struct A<T*> {
+    using layout_type __attribute ((aligned(__alignof(T)))) =
+        char[sizeof(T)];
+  layout_type data;
+};
+
+template<bool> struct StaticAssert;
+template<> struct StaticAssert<true> {};
+
+StaticAssert<__alignof(X<double>) == __alignof(double)> d1;
+StaticAssert<__alignof(Y<double>) == __alignof(double)> d2;
+StaticAssert<__alignof(Z<double>) == __alignof(double)> d3;
+StaticAssert<__alignof(A<double*>) == __alignof(double)> d4;
diff --git a/gcc/testsuite/g++.dg/ext/alias-decl-attr3.C b/gcc/testsuite/g++.dg/ext/alias-decl-attr3.C
new file mode 100644
index 0000000..369aa10
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/alias-decl-attr3.C
@@ -0,0 +1,21 @@ 
+// { dg-options "-std=c++0x" }
+// { dg-do run }
+
+template <class T>
+int
+align_of_type_wide_array()
+{
+    using type_wide_array __attribute((aligned(__alignof(T))))
+        = unsigned char[sizeof (T)];
+
+    return __alignof(type_wide_array);
+}
+
+int
+main ()
+{
+    if (align_of_type_wide_array<int>() == __alignof(int))
+        return 0;
+    else
+        return 1;
+}
diff --git a/gcc/testsuite/g++.dg/ext/alias-decl-attr4.C b/gcc/testsuite/g++.dg/ext/alias-decl-attr4.C
new file mode 100644
index 0000000..c4dd048
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/alias-decl-attr4.C
@@ -0,0 +1,34 @@ 
+// { dg-options "-std=c++0x" }
+// { dg-do run }
+
+using global_vector_type  __attribute__((vector_size(16))) = float;
+
+template <class T> struct A
+{
+    using type = T;
+};
+
+template < typename Val > struct S
+{
+    using vector_type __attribute__((vector_size(16))) =
+        typename A<Val>::type
+        typedef Val vector_type2 __attribute__((vector_size(16)));
+    int pr_size() { return sizeof(vector_type); }
+    int pr_size2() { return sizeof(vector_type2); }
+};
+
+int main()
+{
+  if (sizeof (S<float>::vector_type) != sizeof (global_vector_type))
+    return 1;
+  if (sizeof (S<float>::vector_type2) != sizeof (global_vector_type))
+    return 2;
+
+  S<float> x;
+  if (x.pr_size() != sizeof (global_vector_type))
+    return 3;
+  if (x.pr_size2() != sizeof (global_vector_type))
+    return 4;
+  
+  return 0;
+}