public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [C++ PATCH] PR c++/45114 - Support alias templates
@ 2011-10-27 19:26 Dodji Seketeli
  2011-10-27 22:16 ` Gabriel Dos Reis
  2011-10-27 22:40 ` Jason Merrill
  0 siblings, 2 replies; 10+ messages in thread
From: Dodji Seketeli @ 2011-10-27 19:26 UTC (permalink / raw)
  To: GCC Patches; +Cc: Jason Merrill, Benjamin De Kosnik

Hello,

This patch adds support for the alias-declaration feature of the c++11
specification, introduced by the paper N2258[1] and voted into in the
standard.  It's a derivative work of a preliminary patch attached by
Jason Merrill to PR C++/45114[2].

alias-declaration introduces a new syntax for declaring an alias for a
type.  Exactly like a typedef.  E.g:

    template<class T> struct Vector {};
    using IntVect = Vector<int>;

The concept generalizes to families of types as well.  That is, you
can define an alias for a family of types -- dubbed alias template.
E.g:

    template<class Elements, class Allocator> struct Vector {};
    template<class T> struct MyAllocactor {};
    template<class T> using Vec = Vector<T, MyAllocator<T> >;

    Vec<int> v; // <-- this is equivalent to
		// Vector<int, MyAllocator<int> > v; Neat heh? :-)

The approach taken by the patch is to represent the alias of a type the
same way we represent a typedef today and mark it as type alias using a
flag.  An alias for a type T is thus a variant of T with a new type
name.

By extension an alias template is represented almost like a class
template except that its pattern is a variant of the type at the right
hand side of the '=' of the alias template declaration.

To represent a specialization of an alias template it's important to
notice that there are two "template info" at stake, unlike with normal
template specializations.  There is the template info of the alias
specialization itself and the one of the underlying type we are
aliasing.  The latter has been historically stored in
CLASSTYPE_TEMPLATE_INFO; now we hang the former off of the type name
of the alias.  Using the right template info helps here.  :-)

Substituting into an alias template means substituting for the
parameters of the alias template itself, but also for the parameters
of the type it aliases.  This part was easy as it's already mostly
handled by the typedef handling code we are based on.

Instantiating an alias template means just instantiating the type it
aliases.  This part is also taken care of by construction as the
alias*ed* type is the main variant of the alias type.  And we already
instantiate only the main variant type of a given type.

[1]: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2258.pdf
[2]: http://gcc.gnu.org/PR45114

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

gcc/cp/

	* cp-tree.h (TYPE_DECL_ALIAS_P, SET_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_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.
	(cp_parser_template_declaration_after_export): Handle alias
	templates in c++11.
	* decl.c (grokdeclarator): Set TYPE_DECL_ALIAS_P on alias
	declarations.
	(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 (get_aliased_type, strip_alias): New static functions.
	(alias_type_or_template_p)
	(alias_template_specialization_p): Define new public functions.
	(maybe_process_partial_specialization): Reject partial
	specializations of alias template.
	(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.
	* semantics.c (finish_template_type): For alias templates, return
	the TYPE_DECL of the actual alias and not the one of the aliased
	type.
	* error.c (dump_type):  Print 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;'

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-5.C: Likewise.
---
 gcc/cp/cp-tree.h                          |   70 ++++++++++++--
 gcc/cp/decl.c                             |    5 +
 gcc/cp/decl2.c                            |    9 +-
 gcc/cp/error.c                            |   31 +++++-
 gcc/cp/parser.c                           |   71 +++++++++++++-
 gcc/cp/pt.c                               |  153 +++++++++++++++++++++++++++--
 gcc/cp/semantics.c                        |   14 ++-
 gcc/testsuite/g++.dg/cpp0x/alias-decl-0.C |   33 ++++++
 gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C |    5 +
 gcc/testsuite/g++.dg/cpp0x/alias-decl-2.C |   33 ++++++
 gcc/testsuite/g++.dg/cpp0x/alias-decl-3.C |   29 ++++++
 gcc/testsuite/g++.dg/cpp0x/alias-decl-4.C |   14 +++
 gcc/testsuite/g++.dg/cpp0x/alias-decl-5.C |   34 +++++++
 13 files changed, 470 insertions(+), 31 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-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

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 7ff1491..98971a5 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,41 @@ 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))
+
+/* 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))
+
+/* 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> is 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_TI_TEMPLATE (NODE)						\
+   && same_type_p (TREE_TYPE (NODE), TREE_TYPE (DECL_TI_TEMPLATE (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) \
+   && DECL_LANG_SPECIFIC (TYPE_NAME (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 +2633,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 +3659,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 +4630,7 @@ typedef enum cp_decl_spec {
   ds_explicit,
   ds_friend,
   ds_typedef,
+  ds_alias,
   ds_constexpr,
   ds_complex,
   ds_thread,
@@ -5282,6 +5334,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..8e84f3d 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -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;'.  */
+	SET_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..1e8f2e4 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -340,7 +340,11 @@ dump_type (tree t, int flags)
     return;
 
   /* Don't print e.g. "struct mytypedef".  */
-  if (TYPE_P (t) && typedef_variant_p (t))
+  if (TYPE_P (t) && typedef_variant_p (t)
+      /*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.  */
+      && !alias_template_specialization_p (t))
     {
       tree decl = TYPE_NAME (t);
       if ((flags & TFF_CHASE_TYPEDEF)
@@ -348,7 +352,11 @@ dump_type (tree t, int flags)
 	  || (!flag_pretty_templates
 	      && DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)))
 	t = strip_typedefs (t);
-      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))
 	t = decl;
       else
 	{
@@ -588,7 +596,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 +624,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 +963,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");
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 090482c..cb8c188 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"
@@ -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,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;
@@ -14831,6 +14840,58 @@ 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_LANG_SPECIFIC (decl)
+      && DECL_TI_TEMPLATE (decl))
+    decl = DECL_TI_TEMPLATE (decl);
+  return decl;
+}
+
 /* Parse a using-directive.
 
    using-directive:
@@ -18528,6 +18589,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
@@ -20889,6 +20951,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..01b65fb 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -841,6 +841,13 @@ maybe_process_partial_specialization (tree type)
 	}
       else if (CLASSTYPE_TEMPLATE_INSTANTIATION (type))
 	error ("specialization of %qT after instantiation", type);
+
+      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;
+	}
     }
   else if (CLASS_TYPE_P (type)
 	   && !CLASSTYPE_USE_TEMPLATE (type)
@@ -4831,6 +4838,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 +5106,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 +5275,30 @@ 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_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,
@@ -5979,6 +6019,45 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
   return expr;
 }
 
+/* If T represents an alias declaration, return its underlying aliased
+   type.  */
+
+static tree
+get_aliased_type (tree t)
+{
+  tree result = t;
+
+  if (t == NULL_TREE)
+    /* return t */;
+  else if (TREE_CODE (t) == TYPE_DECL && TYPE_DECL_ALIAS_P (t))
+    result = DECL_ORIGINAL_TYPE (t);
+  else if (TYPE_P (t) && TYPE_DECL_ALIAS_P (TYPE_NAME (t)))
+    result = DECL_ORIGINAL_TYPE (TYPE_NAME (t));
+  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;
+    }
+
+  return result;
+}
+
+/* Return the most underlying type of a type alias or alias
+   template.  */
+
+static tree
+strip_alias (tree t)
+{
+  while (alias_type_or_template_p (t))
+    t = get_aliased_type (t);
+  return t;
+}
+
 /* Subroutine of coerce_template_template_parms, which returns 1 if
    PARM_PARM and ARG_PARM match using the rule for the template
    parameters of template template parameters. Both PARM and ARG are
@@ -6433,6 +6512,11 @@ convert_template_argument (tree parm,
 	 themselves also use the typedef.  */
       if (TYPE_P (val))
 	val = canonicalize_type_argument (val, complain);
+      else
+	/* Strip template aliases from TEMPLATE_DECL nodes,
+	   similarly to what is done by
+	   canonicalize_type_argument for types above.  */
+	val = strip_alias (val);
     }
   else
     {
@@ -7355,7 +7439,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 +7486,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.  */
@@ -7480,7 +7590,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));
@@ -10376,8 +10494,18 @@ 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 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)))
 		  spec = t;
 	      }
 
@@ -10858,7 +10986,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,6 +11031,8 @@ 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;
@@ -10915,6 +11045,15 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 	     complain | tf_ignore_bad_quals);
 	  return r;
 	}
+      else if (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.  */
+	  tree type_decl = tsubst (decl, args, complain, decl);
+	  return TREE_TYPE (type_decl);
+	}
       /* Else we must be instantiating the typedef, so fall through.  */
     }
 
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..abc56ff
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-0.C
@@ -0,0 +1,33 @@
+// { 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()
+{
+  X<Y> y;
+  X<Z> z;
+  f(z);
+  g(y);
+}
+
+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..f1c4b94
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C
@@ -0,0 +1,5 @@
+// { dg-options "-std=c++0x" }
+
+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" }
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..b7460f3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-3.C
@@ -0,0 +1,29 @@
+// { dg-options "-std=c++0x" }
+
+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);
+}
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
+}
-- 
1.7.6.4


-- 
		Dodji

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [C++ PATCH] PR c++/45114 - Support alias templates
  2011-10-27 19:26 [C++ PATCH] PR c++/45114 - Support alias templates Dodji Seketeli
@ 2011-10-27 22:16 ` Gabriel Dos Reis
  2011-10-27 22:40 ` Jason Merrill
  1 sibling, 0 replies; 10+ messages in thread
From: Gabriel Dos Reis @ 2011-10-27 22:16 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: GCC Patches, Jason Merrill, Benjamin De Kosnik

On Thu, Oct 27, 2011 at 2:10 PM, Dodji Seketeli <dodji@redhat.com> wrote:
> Hello,
>
> This patch adds support for the alias-declaration feature of the c++11
> specification, introduced by the paper N2258[1] and voted into in the
> standard.  It's a derivative work of a preliminary patch attached by
> Jason Merrill to PR C++/45114[2].

Thanks for doing this.  Jason told me your were working on it.
As of this morning, I was wondering whether I should ping you :-).
The patch just printed; I will look over and give you my feedback.
There were a couple of things that were inadvertently changed
(at least that is what I was told when I spotted the change), and I would
like to make sure we have the specification as i was voted on.

Thanks,

-- Gaby

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [C++ PATCH] PR c++/45114 - Support alias templates
  2011-10-27 19:26 [C++ PATCH] PR c++/45114 - Support alias templates Dodji Seketeli
  2011-10-27 22:16 ` Gabriel Dos Reis
@ 2011-10-27 22:40 ` Jason Merrill
  2011-11-06  2:19   ` Dodji Seketeli
  1 sibling, 1 reply; 10+ messages in thread
From: Jason Merrill @ 2011-10-27 22:40 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: GCC Patches, Benjamin De Kosnik

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.

> +#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)

?

> +#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?

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

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

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

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.

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

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

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

> +      else if (TYPE_DECL_ALIAS_P (decl))
> +       /* fall through.  */;

Why not set r here, as for the other cases?  It seems like this way you 
will lose cv-quals added to an alias.

Jason

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [C++ PATCH] PR c++/45114 - Support alias templates
  2011-10-27 22:40 ` Jason Merrill
@ 2011-11-06  2:19   ` Dodji Seketeli
  2011-11-06 10:13     ` Jason Merrill
  0 siblings, 1 reply; 10+ messages in thread
From: Dodji Seketeli @ 2011-11-06  2:19 UTC (permalink / raw)
  To: Jason Merrill; +Cc: GCC Patches, Benjamin De Kosnik

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

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;
+
-- 
1.7.6.4


-- 
		Dodji

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [C++ PATCH] PR c++/45114 - Support alias templates
  2011-11-06  2:19   ` Dodji Seketeli
@ 2011-11-06 10:13     ` Jason Merrill
  2011-11-07 15:57       ` Dodji Seketeli
  0 siblings, 1 reply; 10+ messages in thread
From: Jason Merrill @ 2011-11-06 10:13 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: GCC Patches, Benjamin De Kosnik

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

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [C++ PATCH] PR c++/45114 - Support alias templates
  2011-11-06 10:13     ` Jason Merrill
@ 2011-11-07 15:57       ` Dodji Seketeli
  2011-11-07 18:39         ` Jason Merrill
  2011-11-08 20:15         ` [C++ PATCH] PR c++/45114 - Support alias templates H.J. Lu
  0 siblings, 2 replies; 10+ messages in thread
From: Dodji Seketeli @ 2011-11-07 15:57 UTC (permalink / raw)
  To: Jason Merrill; +Cc: GCC Patches, Benjamin De Kosnik

> 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

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;
+}
-- 
1.7.6.4


-- 
		Dodji

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [C++ PATCH] PR c++/45114 - Support alias templates
  2011-11-07 15:57       ` Dodji Seketeli
@ 2011-11-07 18:39         ` Jason Merrill
  2011-11-08  3:40           ` [C++ PATCH] Fix context handling of alias declaration Dodji Seketeli
  2011-11-08 20:15         ` [C++ PATCH] PR c++/45114 - Support alias templates H.J. Lu
  1 sibling, 1 reply; 10+ messages in thread
From: Jason Merrill @ 2011-11-07 18:39 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: GCC Patches, Benjamin De Kosnik

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

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [C++ PATCH] Fix context handling of alias declaration
  2011-11-07 18:39         ` Jason Merrill
@ 2011-11-08  3:40           ` Dodji Seketeli
  2011-11-08  5:13             ` Jason Merrill
  0 siblings, 1 reply; 10+ messages in thread
From: Dodji Seketeli @ 2011-11-08  3:40 UTC (permalink / raw)
  To: Jason Merrill; +Cc: GCC Patches, Benjamin De Kosnik

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

I think it is because start_decl (in cp_parser_alias_declaration)
needs to be matched with a call to pop_scoped on the scope it yields.

start_decl pushes the scope represented by the context of the DECL
that it builds (here the namespace N).  If that scope is not popped by
the caller of start_decl subsequent DECLs appear as if they are
members of that scope as well.

Also, while printing the alias specialization, I obviously don't print
the context.

The patch below addresses these two issues.

A bootstrap and testing is currently running on
x86_64-unknown-linux-gnu against trunk.

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

Thanks.  I have committed the patches you have accepted, FWIW.

From: Dodji Seketeli <dodji@redhat.com>
Date: Tue, 8 Nov 2011 02:41:06 +0100
Subject: [PATCH] Fix context handling of alias declaration

gcc/cp/

	* decl.c (start_decl): Update comment.
	* error.c (dump_alias_template_specialization): Dump the context
	of the specialization.
	* parser.c (cp_parser_alias_declaration): Call pop_scope on the
	pushed scope yielded by start_decl.

gcc/testsuite

	* g++.dg/cpp0x/alias-decl-11.C: New test.
---
 gcc/cp/decl.c                              |    7 +++++--
 gcc/cp/error.c                             |    2 ++
 gcc/cp/parser.c                            |    7 +++++--
 gcc/testsuite/g++.dg/cpp0x/alias-decl-11.C |    8 ++++++++
 4 files changed, 20 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/alias-decl-11.C

diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index e4b91cc..1c33776 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -4295,8 +4295,11 @@ groktypename (cp_decl_specifier_seq *type_specifiers,
    deleted function, but 0 (SD_UNINITIALIZED) if this is a variable
    implicitly initialized via a default constructor.  ATTRIBUTES and
    PREFIX_ATTRIBUTES are GNU attributes associated with this declaration.
-   *PUSHED_SCOPE_P is set to the scope entered in this function, if any; if
-   set, the caller is responsible for calling pop_scope.  */
+
+   The scope represented by the context of the returned DECL is pushed
+   (if it is not the global namespace) and is assigned to
+   *PUSHED_SCOPE_P.  The caller is then responsible for calling
+   pop_scope on *PUSHED_SCOPE_P if it is set.  */
 
 tree
 start_decl (const cp_declarator *declarator,
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 841366f..d2b6a62 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -341,6 +341,8 @@ dump_alias_template_specialization (tree t, int flags)
 
   gcc_assert (alias_template_specialization_p (t));
 
+  if (!(flags & TFF_UNQUALIFIED_NAME))
+    dump_scope (CP_DECL_CONTEXT (TYPE_NAME (t)), flags);
   name = TYPE_IDENTIFIER (t);
   pp_cxx_tree_identifier (cxx_pp, name);
   dump_template_parms (TYPE_TEMPLATE_INFO (t),
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index fa0117e..1f8d5d9 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -14884,7 +14884,7 @@ cp_parser_using_declaration (cp_parser* parser,
 static tree
 cp_parser_alias_declaration (cp_parser* parser)
 {
-  tree id, type, decl, dummy, attributes;
+  tree id, type, decl, pushed_scope = NULL_TREE, attributes;
   location_t id_location;
   cp_declarator *declarator;
   cp_decl_specifier_seq decl_specs;
@@ -14918,12 +14918,15 @@ cp_parser_alias_declaration (cp_parser* parser)
 		      NULL_TREE, attributes);
   else
     decl = start_decl (declarator, &decl_specs, 0,
-		       attributes, NULL_TREE, &dummy);
+		       attributes, NULL_TREE, &pushed_scope);
   if (decl == error_mark_node)
     return decl;
 
   cp_finish_decl (decl, NULL_TREE, 0, NULL_TREE, 0);
 
+  if (pushed_scope)
+    pop_scope (pushed_scope);
+
   /* 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)
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-11.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-11.C
new file mode 100644
index 0000000..43ef7ba
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-11.C
@@ -0,0 +1,8 @@
+// { dg-options "-std=c++0x" }
+
+namespace N
+{
+  template <class T> using U = T*;
+};
+
+void f(N::U<int>) { blah; } // { dg-error "void f(N::U<int>)|not declared" }
-- 
1.7.6.4


-- 
		Dodji

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [C++ PATCH] Fix context handling of alias declaration
  2011-11-08  3:40           ` [C++ PATCH] Fix context handling of alias declaration Dodji Seketeli
@ 2011-11-08  5:13             ` Jason Merrill
  0 siblings, 0 replies; 10+ messages in thread
From: Jason Merrill @ 2011-11-08  5:13 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: GCC Patches, Benjamin De Kosnik

OK.

Jason

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [C++ PATCH] PR c++/45114 - Support alias templates
  2011-11-07 15:57       ` Dodji Seketeli
  2011-11-07 18:39         ` Jason Merrill
@ 2011-11-08 20:15         ` H.J. Lu
  1 sibling, 0 replies; 10+ messages in thread
From: H.J. Lu @ 2011-11-08 20:15 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: Jason Merrill, GCC Patches, Benjamin De Kosnik

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

-- 
H.J.

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2011-11-08 19:48 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-10-27 19:26 [C++ PATCH] PR c++/45114 - Support alias templates Dodji Seketeli
2011-10-27 22:16 ` Gabriel Dos Reis
2011-10-27 22:40 ` Jason Merrill
2011-11-06  2:19   ` Dodji Seketeli
2011-11-06 10:13     ` Jason Merrill
2011-11-07 15:57       ` Dodji Seketeli
2011-11-07 18:39         ` Jason Merrill
2011-11-08  3:40           ` [C++ PATCH] Fix context handling of alias declaration Dodji Seketeli
2011-11-08  5:13             ` Jason Merrill
2011-11-08 20:15         ` [C++ PATCH] PR c++/45114 - Support alias templates H.J. Lu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).