As presented in the cover message, this patch replaces the
BOUND_TEMPLATE_TEMPLATE_PARM tree with a TEMPLATE_ID_TYPE tree that
represents a template-id whose arguments haven't yet been applied to
its template.  The template itself might have not been resolved to a
TEMPLATE_DECL yet, in which case it's just an IDENTIFIER_NODE.

The functionality of representing BOUND_TEMPLATE_TEMPLATE_PARM then
gets expressed by using a TEMPLATE_ID_TYPE in which the template
validates the DECL_TEMPLATE_TEMPLATE_PARAMETER_P predicate.

Additionally, the TYPENAME_TYPE_FULLNAME of a TYPENAME_TYPE is also
represented using a TEMPLATE_ID_TYPE, rather than a TEMPLATE_ID_EXPR -
even when make_typename_type is passed a TEMPLATE_ID_EXPR.  Note that
the TEMPLATE_ID_TYPE yielded by TYPENAME_TYPE_FULLNAME can either have
a TEMPLATE_DECL or just an IDENTIFIER_NODE, depending on if the
template name of the template-id could be resolved to a template at
the point where the typename was formed or not.

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

gcc/cp/

        PR c++/51239
        * cp_tree.def (TEMPLATE_TYPE_PARM): Rename
        BOUND_TEMPLATE_TEMPLATE_PARM into TEMPLATE_ID_TYPE in comments.
        (TEMPLATE_ID_TYPE): Renamed BOUND_TEMPLATE_TEMPLATE_PARM into
        this.  Update comments.
        * cp-tree.h (build_template_id_type):
        (TEMPLATE_ID_TYPE_TYPE_CHECK): Turn
        BOUND_TEMPLATE_TEMPLATE_PARM_TYPE_CHECK into this.
        (BOUND_TEMPLATE_TEMPLATE_PARM_P): New predicate macro.
        (MAYBE_CLASS_TYPE_P): Rename BOUND_TEMPLATE_TEMPLATE_PARM into
        TEMPLATE_ID_TYPE.
        (TEMPLATE_ID_TYPE_TEMPLATE_INFO): Turn
        TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO into this.
        (TYPE_TEMPLATE_INFO): Support TEMPLATE_ID_TYPE.
        (SET_TYPE_TEMPLATE_INFO): Update to support TEMPLATE_ID_TYPE, and
        to better support type aliases.
        (TYPENAME_TYPE_FULLNAME): Replace TEMPLATE_ID_EXPR with
        TEMPLATE_ID_TYPE in comments.
        (TEMPLATE_TYPE_PARM_INDEX): Rename BOUND_TEMPLATE_TEMPLATE_PARM
        into TEMPLATE_ID_TYPE in the definition of this macro.
        (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL): Use
        BOUND_TEMPLATE_TEMPLATE_PARM_P instead of
        BOUND_TEMPLATE_TEMPLATE_PARM.
        * cp-objcp-common.c (cp_common_init_ts): Rename
        BOUND_TEMPLATE_TEMPLATE_PARM into TEMPLATE_ID_TYPE.
        * cxx-pretty-print.c (pp_cxx_unqualified_id)<TEMPLATE_ID_TYPE>:
        Renamed BOUND_TEMPLATE_TEMPLATE_PARM into this.
        (pp_cxx_type_specifier_seq)<TEMPLATE_ID_TYPE>: Likewise.
        (pp_cxx_direct_abstract_declarator)<TEMPLATE_ID_TYPE>>: Likewise.
        (pp_cxx_type_id)<TEMPLATE_ID_TYPE>: Likewise.
        (pp_cxx_canonical_template_parameter): Use
        BOUND_TEMPLATE_TEMPLATE_PARM_P instead of
        BOUND_TEMPLATE_TEMPLATE_PARM.
        * decl.c (make_typename_type): Store unbound template-id in a
        TEMPLATE_ID_TYPE instead of in a TEMPLATE_ID_EXPR.
        (check_elaborated_type_specifier): Use
        BOUND_TEMPLATE_TEMPLATE_PARM_P instead of
        BOUND_TEMPLATE_TEMPLATE_PARM.
        * decl2.c (is_late_template_attribute): Use
        BOUND_TEMPLATE_TEMPLATE_PARM_P instead of
        BOUND_TEMPLATE_TEMPLATE_PARM.
        * error.c (dump_type)<TEMPLATE_ID_TYPE>: Replace
        BOUND_TEMPLATE_TEMPLATE_PARM with this.
        (dump_typename): Use dump_type on  TYPENAME_TYPE_FULLNAME rather
        than dump_decl.
        (dump_type_prefix, dump_type_suffix, dump_expr)<TEMPLATE_ID_TYPE>:
        Replace BOUND_TEMPLATE_TEMPLATE_PARM with this.
        * lex.c (cxx_make_type): Replace BOUND_TEMPLATE_TEMPLATE_PARM with
        TEMPLATE_ID_TYPE.
        * mangle.c (CLASSTYPE_TEMPLATE_ID_P): Replace use of
        BOUND_TEMPLATE_TEMPLATE_PARM with BOUND_TEMPLATE_TEMPLATE_PARM_P.
        (write_nested_name, write_prefix): Replace use of TEMPLATE_ID_EXPR
        with TEMPLATE_ID_TYPE.  Use TYPE_TI_ARGS on the
        TYPENAME_TYPE_FULLNAME rather than TREE_OPERAND.
        (write_type)<TEMPLATE_ID_TYPE>: Replace
        BOUND_TEMPLATE_TEMPLATE_PARM with this.  Use TYPE_TI_ARGS rather
        than TI_ARGS of TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO.
        (write_expression): USe BOUND_TEMPLATE_TEMPLATE_PARM_P instead of
        BOUND_TEMPLATE_TEMPLATE_PARM.
        (write_template_param)<TEMPLATE_ID_TYPE>: Replace
        BOUND_TEMPLATE_TEMPLATE_PARM with this.
        (write_template_template_param): Use
        BOUND_TEMPLATE_TEMPLATE_PARM_P instead of
        BOUND_TEMPLATE_TEMPLATE_PARM, TYPE_TEMPLATE_INFO instead of
        TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO.
        * name-lookup.c (arg_assoc_type)<TEMPLATE_ID_TYPE>: Rename
        BOUND_TEMPLATE_TEMPLATE_PARM into this.
        * parser.c (cp_parser_nested_name_specifier_opt): Replace
        TEMPLATE_ID_EXPR with TEMPLATE_ID_TYPE.
        * pt.c (get_template_info): Use TYPE_TEMPLATE_INFO to get
        TEMPLATE_INFO from types in general.
        (maybe_process_partial_specialization): Use
        BOUND_TEMPLATE_TEMPLATE_PARM_P instead of
        BOUND_TEMPLATE_TEMPLATE_PARM.
        (find_parameter_packs_r): Replaced case
        BOUND_TEMPLATE_TEMPLATE_PARM with case TEMPLATE_ID_TYPE.  Check
        for TYPE_TI_TEMPLATE before walking it.
        (lookup_template_class_1): Propagate error if arglist is
        erroneous.
        (for_each_template_parm_r)<TEMPLATE_ID_TYPE>: Replaced
        BOUND_TEMPLATE_TEMPLATE_PARM with this.  Use
        BOUND_TEMPLATE_TEMPLATE_PARM_P.
        (for_each_template_parm): Replace BOUND_TEMPLATE_TEMPLATE_PARM
        with TEMPLATE_ID_TYPE in comments.
        (tsubst)<TEMPLATE_ID_TYPE>: Replace BOUND_TEMPLATE_TEMPLATE_PARM
        with this.  Handle TEMPLATE_ID_TYPE.  Replace use of
        TEMPLATE_ID_EXPR in make_typename_type with
        build_template_id_type.  Use BOUND_TEMPLATE_TEMPLATE_PARM_P.
        (tsubst_copy)<TEMPLATE_ID_TYPE>: Replace use of
        BOUND_TEMPLATE_TEMPLATE_PARM with this.
        (template_parm_level_and_index): Replace use of
        BOUND_TEMPLATE_TEMPLATE_PARM with BOUND_TEMPLATE_TEMPLATE_PARM_P.
        (unify)<TEMPLATE_ID_TYPE>: Replace use of
        BOUND_TEMPLATE_TEMPLATE_PARM with this.  Use
        BOUND_TEMPLATE_TEMPLATE_PARM_P.
        (dependent_type_p_r): Replace use of BOUND_TEMPLATE_TEMPLATE_PARM
        with BOUND_TEMPLATE_TEMPLATE_PARM_P.
        (resolve_typename_type): TYPENAME_TYPE_FULLNAME now yields
        TEMPLATE_ID_TYPE, no more TEMPLATE_ID_EXPR.
        * ptree.c (cxx_print_type)<TEMPLATE_ID_TYPE>: Replace
        BOUND_TEMPLATE_TEMPLATE_PARM with this.
        * search.c (lookup_field_1): Replace use of
        BOUND_TEMPLATE_TEMPLATE_PARM with BOUND_TEMPLATE_TEMPLATE_PARM_P.
        * tree.c (build_template_id_type): Define new function.
        (bind_template_template_parm): Use the new build_template_id_type.
        (cp_walk_tree)<TEMPLATE_ID_TYPE>: Replace
        BOUND_TEMPLATE_TEMPLATE_PARM with this.
        * typeck.c (comp_template_parms_position): Replace use of
        BOUND_TEMPLATE_TEMPLATE_PARM with BOUND_TEMPLATE_TEMPLATE_PARM_P.
        (structural_comptypes): Compare TEMPLATE_ID_TYPE nodes not
        BOUND_TEMPLATE_TEMPLATE_PARM.
        * typeck2.c (cxx_incomplete_type_diagnostic)<TEMPLATE_ID_TYPE>: Replace
        BOUND_TEMPLATE_TEMPLATE_PARM with this.  Adjust diagnostic.
---
 gcc/cp/cp-objcp-common.c  |    2 +-
 gcc/cp/cp-tree.def        |   17 ++++---
 gcc/cp/cp-tree.h          |   55 ++++++++++++++--------
 gcc/cp/cxx-pretty-print.c |   10 ++--
 gcc/cp/decl.c             |   22 ++++++---
 gcc/cp/decl2.c            |    4 +-
 gcc/cp/error.c            |   10 ++--
 gcc/cp/lex.c              |    2 +-
 gcc/cp/mangle.c           |   26 +++++-----
 gcc/cp/name-lookup.c      |    2 +-
 gcc/cp/parser.c           |    2 +-
 gcc/cp/pt.c               |  114 ++++++++++++++++++++++++++++++---------------
 gcc/cp/ptree.c            |    6 ++-
 gcc/cp/search.c           |    2 +-
 gcc/cp/tree.c             |   64 +++++++++++++++++--------
 gcc/cp/typeck.c           |   18 ++++++-
 gcc/cp/typeck2.c          |   13 ++++--
 17 files changed, 237 insertions(+), 132 deletions(-)

diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c
index a957a03..719ec77 100644
--- a/gcc/cp/cp-objcp-common.c
+++ b/gcc/cp/cp-objcp-common.c
@@ -246,7 +246,7 @@ cp_common_init_ts (void)
   MARK_TS_COMMON (TYPE_PACK_EXPANSION);
   MARK_TS_COMMON (TYPE_ARGUMENT_PACK);
   MARK_TS_COMMON (DECLTYPE_TYPE);
-  MARK_TS_COMMON (BOUND_TEMPLATE_TEMPLATE_PARM);
+  MARK_TS_COMMON (TEMPLATE_ID_TYPE);
   MARK_TS_COMMON (UNBOUND_CLASS_TEMPLATE);
 
   MARK_TS_TYPED (EXPR_PACK_EXPANSION);
diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def
index 5fc5496..c68274c 100644
--- a/gcc/cp/cp-tree.def
+++ b/gcc/cp/cp-tree.def
@@ -172,7 +172,7 @@ DEFTREECODE (TEMPLATE_TEMPLATE_PARM, 
"template_template_parm", tcc_type, 0)
 /* The ordering of the following codes is optimized for the checking
    macros in tree.h.  Changing the order will degrade the speed of the
    compiler.  TEMPLATE_TYPE_PARM, TYPENAME_TYPE, TYPEOF_TYPE,
-   BOUND_TEMPLATE_TEMPLATE_PARM.  */
+   TEMPLATE_ID_TYPE.  */
 
 /* Index into a template parameter list.  This parameter must be a type.
    The type.values field will be a TEMPLATE_PARM_INDEX.  */
@@ -180,7 +180,7 @@ DEFTREECODE (TEMPLATE_TYPE_PARM, "template_type_parm", 
tcc_type, 0)
 
 /* A type designated by `typename T::t'.  TYPE_CONTEXT is `T',
    TYPE_NAME is an IDENTIFIER_NODE for `t'.  If the type was named via
-   template-id, TYPENAME_TYPE_FULLNAME will hold the TEMPLATE_ID_EXPR.
+   template-id, TYPENAME_TYPE_FULLNAME will hold the TEMPLATE_ID_TYPE.
    TREE_TYPE is always NULL.  */
 DEFTREECODE (TYPENAME_TYPE, "typename_type", tcc_type, 0)
 
@@ -188,12 +188,13 @@ DEFTREECODE (TYPENAME_TYPE, "typename_type", tcc_type, 0)
    expression in question.  */
 DEFTREECODE (TYPEOF_TYPE, "typeof_type", tcc_type, 0)
 
-/* Like TEMPLATE_TEMPLATE_PARM it is used with bound template arguments
-   like TT<int>.
-   In this case, TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO contains the
-   template name and its bound arguments.  TYPE_NAME is a TYPE_DECL.  */
-DEFTREECODE (BOUND_TEMPLATE_TEMPLATE_PARM, "bound_template_template_parm",
-            tcc_type, 0)
+/* A generic type for a template-id (templatename<arguments>) in which
+   the arguments have not yet been applied to the template.  The
+   TEMPLATE_ID_TYPE_TEMPLATE_INFO accessor returns the TEMPLATE_INFO
+   of the type, TYPE_TI_TEMPLATE returns the TEMPLATE_DECL of the
+   type, and TYPE_TI_ARGS returns the arguments.  TYPE_NAME is a
+   TYPE_DECL.  */
+DEFTREECODE (TEMPLATE_ID_TYPE, "template_id_type", tcc_type, 0)
 
 /* For template template argument of the form `T::template C'.
    TYPE_CONTEXT is `T', the template parameter dependent object.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 955d0eb..fa5bf7f 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -206,8 +206,8 @@ c-common.h, not after.
 #define VAR_TEMPL_TYPE_FIELD_OR_FUNCTION_DECL_CHECK(NODE) \
   TREE_CHECK5(NODE,VAR_DECL,FIELD_DECL,FUNCTION_DECL,TYPE_DECL,TEMPLATE_DECL)
 
-#define BOUND_TEMPLATE_TEMPLATE_PARM_TYPE_CHECK(NODE) \
-  TREE_CHECK(NODE,BOUND_TEMPLATE_TEMPLATE_PARM)
+#define TEMPLATE_ID_TYPE_TYPE_CHECK(NODE) \
+  TREE_CHECK(NODE,TEMPLATE_ID_TYPE)
 
 #if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
 #define THUNK_FUNCTION_CHECK(NODE) __extension__                       \
@@ -1191,11 +1191,11 @@ enum languages { lang_c, lang_cplusplus, lang_java };
    template template parameters.  Keep these checks in ascending code
    order.  */
 #define MAYBE_CLASS_TYPE_P(T)                                  \
-  (TREE_CODE (T) == TEMPLATE_TYPE_PARM                 \
-   || TREE_CODE (T) == TYPENAME_TYPE                   \
-   || TREE_CODE (T) == TYPEOF_TYPE                     \
-   || TREE_CODE (T) == BOUND_TEMPLATE_TEMPLATE_PARM    \
-   || TREE_CODE (T) == DECLTYPE_TYPE                   \
+  (TREE_CODE (T) == TEMPLATE_TYPE_PARM                         \
+   || TREE_CODE (T) == TYPENAME_TYPE                           \
+   || TREE_CODE (T) == TYPEOF_TYPE                             \
+   || TREE_CODE (T) == TEMPLATE_ID_TYPE                                \
+   || TREE_CODE (T) == DECLTYPE_TYPE                           \
    || CLASS_TYPE_P (T))
 
 /* Set CLASS_TYPE_P for T to VAL.  T must be a class, struct, or
@@ -2604,8 +2604,8 @@ extern void decl_shadowed_for_var_insert (tree, tree);
   (TYPE_LANG_SLOT_1 (ENUMERAL_TYPE_CHECK (NODE)))
 
 /* Template information for a template template parameter.  */
-#define TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO(NODE) \
-  (LANG_TYPE_CLASS_CHECK (BOUND_TEMPLATE_TEMPLATE_PARM_TYPE_CHECK (NODE)) \
+#define TEMPLATE_ID_TYPE_TEMPLATE_INFO(NODE) \
+  (LANG_TYPE_CLASS_CHECK (TEMPLATE_ID_TYPE_TYPE_CHECK (NODE)) \
    ->template_info)
 
 /* Template information for an ENUMERAL_, RECORD_, UNION_TYPE, or
@@ -2620,21 +2620,26 @@ extern void decl_shadowed_for_var_insert (tree, tree);
       : NULL_TREE)                                                     \
    : ((TREE_CODE (NODE) == ENUMERAL_TYPE)                              \
       ? ENUM_TEMPLATE_INFO (NODE)                                      \
-      : ((TREE_CODE (NODE) == BOUND_TEMPLATE_TEMPLATE_PARM)            \
-        ? TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (NODE)                  \
+      : ((TREE_CODE (NODE) == TEMPLATE_ID_TYPE)                                
\
+        ? TEMPLATE_ID_TYPE_TEMPLATE_INFO (NODE)                        \
         : (CLASS_TYPE_P (NODE)                                         \
            ? CLASSTYPE_TEMPLATE_INFO (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))                               \
-   : ((CLASS_TYPE_P (NODE) && !TYPE_ALIAS_P (NODE))                    \
-      ? (CLASSTYPE_TEMPLATE_INFO (NODE) = (VAL))                       \
-      : (DECL_TEMPLATE_INFO (TYPE_NAME (NODE)) = (VAL))))
+  (TYPE_ALIAS_P (NODE)                                                 \
+   ? ((TYPE_NAME (NODE) && DECL_LANG_SPECIFIC (TYPE_NAME (NODE)))      \
+      ? DECL_TEMPLATE_INFO (TYPE_NAME (NODE)) = (VAL)                  \
+      : NULL_TREE)                                                     \
+   : ((TREE_CODE (NODE) == ENUMERAL_TYPE)                              \
+      ? ENUM_TEMPLATE_INFO (NODE) = (VAL)                              \
+      : ((TREE_CODE (NODE) == TEMPLATE_ID_TYPE)                                
\
+        ? TEMPLATE_ID_TYPE_TEMPLATE_INFO (NODE) = (VAL)                \
+        : (CLASS_TYPE_P (NODE)                                         \
+           ? CLASSTYPE_TEMPLATE_INFO (NODE) = (VAL)                    \
+           : NULL_TREE))))
 
 #define TI_TEMPLATE(NODE) TREE_TYPE (TEMPLATE_INFO_CHECK (NODE))
 #define TI_ARGS(NODE) TREE_CHAIN (TEMPLATE_INFO_CHECK (NODE))
@@ -3028,7 +3033,7 @@ more_aggr_init_expr_args_p (const 
aggr_init_expr_arg_iterator *iter)
 /* The name used by the user to name the typename type.  Typically,
    this is an IDENTIFIER_NODE, and the same as the DECL_NAME on the
    corresponding TYPE_DECL.  However, this may also be a
-   TEMPLATE_ID_EXPR if we had something like `typename X::Y<T>'.  */
+   TEMPLATE_ID_TYPE if we had something like `typename X::Y<T>'.  */
 #define TYPENAME_TYPE_FULLNAME(NODE) \
   (TYPE_VALUES_RAW (TYPENAME_TYPE_CHECK (NODE)))
 
@@ -3650,6 +3655,15 @@ more_aggr_init_expr_args_p (const 
aggr_init_expr_arg_iterator *iter)
 #define DECL_UNBOUND_CLASS_TEMPLATE_P(NODE) \
   (TREE_CODE (NODE) == TEMPLATE_DECL && !DECL_TEMPLATE_RESULT (NODE))
 
+/* Nonzero if NODE is a TEMPLATE_ID_TYPE representing a bound template
+   template parameter;  that is a template-id whose template is a
+   template template parameter.  */
+#define BOUND_TEMPLATE_TEMPLATE_PARM_P(NODE)                   \
+  ((NODE) != NULL_TREE                                         \
+   && TREE_CODE (NODE) == TEMPLATE_ID_TYPE                     \
+   && TYPE_TI_TEMPLATE (NODE) != NULL_TREE                     \
+   && DECL_TEMPLATE_TEMPLATE_PARM_P (TYPE_TI_TEMPLATE (NODE)))
+
 #define DECL_FUNCTION_TEMPLATE_P(NODE)  \
   (TREE_CODE (NODE) == TEMPLATE_DECL \
    && !DECL_UNBOUND_CLASS_TEMPLATE_P (NODE) \
@@ -4503,7 +4517,7 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, 
TYPENAME_FLAG };
 #define TEMPLATE_TYPE_PARM_INDEX(NODE)                                 \
   (TYPE_VALUES_RAW (TREE_CHECK3 ((NODE), TEMPLATE_TYPE_PARM,           \
                                 TEMPLATE_TEMPLATE_PARM,                \
-                                BOUND_TEMPLATE_TEMPLATE_PARM)))
+                                TEMPLATE_ID_TYPE)))
 #define TEMPLATE_TYPE_IDX(NODE) \
   (TEMPLATE_PARM_IDX (TEMPLATE_TYPE_PARM_INDEX (NODE)))
 #define TEMPLATE_TYPE_LEVEL(NODE) \
@@ -4554,7 +4568,7 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, 
TYPENAME_FLAG };
 /* Returns the TEMPLATE_DECL associated to a TEMPLATE_TEMPLATE_PARM
    node.  */
 #define TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL(NODE)     \
-  ((TREE_CODE (NODE) == BOUND_TEMPLATE_TEMPLATE_PARM)  \
+  (BOUND_TEMPLATE_TEMPLATE_PARM_P (NODE)               \
    ? TYPE_TI_TEMPLATE (NODE)                           \
    : TYPE_NAME (NODE))
 
@@ -5666,6 +5680,7 @@ extern bool non_static_member_function_p        (tree);
 extern const char *cxx_printable_name          (tree, int);
 extern const char *cxx_printable_name_translate        (tree, int);
 extern tree build_exception_variant            (tree, tree);
+extern tree build_template_id_type              (tree, tree);
 extern tree bind_template_template_parm                (tree, tree);
 extern tree array_type_nelts_total             (tree);
 extern tree array_type_nelts_top               (tree);
diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c
index 55cb64b..c71ca0e 100644
--- a/gcc/cp/cxx-pretty-print.c
+++ b/gcc/cp/cxx-pretty-print.c
@@ -225,7 +225,7 @@ pp_cxx_unqualified_id (cxx_pretty_printer *pp, tree t)
       pp_cxx_unqualified_id (pp, TEMPLATE_PARM_DECL (t));
       break;
 
-    case BOUND_TEMPLATE_TEMPLATE_PARM:
+    case TEMPLATE_ID_TYPE:
       pp_cxx_cv_qualifier_seq (pp, t);
       pp_cxx_unqualified_id (pp, TYPE_IDENTIFIER (t));
       pp_cxx_begin_template_argument_list (pp);
@@ -1295,7 +1295,7 @@ pp_cxx_type_specifier_seq (cxx_pretty_printer *pp, tree t)
     case TEMPLATE_TYPE_PARM:
     case TEMPLATE_TEMPLATE_PARM:
     case TYPE_DECL:
-    case BOUND_TEMPLATE_TEMPLATE_PARM:
+    case TEMPLATE_ID_TYPE:
       pp_cxx_cv_qualifier_seq (pp, t);
       pp_cxx_simple_type_specifier (pp, t);
       break;
@@ -1687,7 +1687,7 @@ pp_cxx_direct_abstract_declarator (cxx_pretty_printer 
*pp, tree t)
     case TYPENAME_TYPE:
     case TEMPLATE_TYPE_PARM:
     case TEMPLATE_TEMPLATE_PARM:
-    case BOUND_TEMPLATE_TEMPLATE_PARM:
+    case TEMPLATE_ID_TYPE:
     case UNBOUND_CLASS_TEMPLATE:
       break;
 
@@ -1713,7 +1713,7 @@ pp_cxx_type_id (cxx_pretty_printer *pp, tree t)
     case RECORD_TYPE:
     case ENUMERAL_TYPE:
     case TYPENAME_TYPE:
-    case BOUND_TEMPLATE_TEMPLATE_PARM:
+    case TEMPLATE_ID_TYPE:
     case UNBOUND_CLASS_TEMPLATE:
     case TEMPLATE_TEMPLATE_PARM:
     case TEMPLATE_TYPE_PARM:
@@ -2140,7 +2140,7 @@ pp_cxx_canonical_template_parameter (cxx_pretty_printer 
*pp, tree parm)
 
   /* Brings type template parameters to the canonical forms.  */
   if (code == TEMPLATE_TYPE_PARM || code == TEMPLATE_TEMPLATE_PARM
-      || code == BOUND_TEMPLATE_TEMPLATE_PARM)
+      || BOUND_TEMPLATE_TEMPLATE_PARM_P (parm))
     parm = TEMPLATE_TYPE_PARM_INDEX (parm);
 
   pp_cxx_begin_template_argument_list (pp);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 5a4e027..4b6e903 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -3190,15 +3190,16 @@ make_typename_type (tree context, tree name, enum 
tag_types tag_type,
 
   if (TYPE_P (name))
     {
-      if (!(TYPE_LANG_SPECIFIC (name)
+      if (TREE_CODE (name) == TEMPLATE_ID_TYPE)
+       /* We use instances of TEMPLATE_ID_TYPE as is.  */;
+      else if (!(TYPE_LANG_SPECIFIC (name)
            && (CLASSTYPE_IS_TEMPLATE (name)
                || CLASSTYPE_USE_TEMPLATE (name))))
        name = TYPE_IDENTIFIER (name);
       else
-       /* Create a TEMPLATE_ID_EXPR for the type.  */
-       name = build_nt (TEMPLATE_ID_EXPR,
-                        CLASSTYPE_TI_TEMPLATE (name),
-                        CLASSTYPE_TI_ARGS (name));
+       /* Create a TEMPLATE_ID_TYPE for the type.  */
+       name = build_template_id_type (CLASSTYPE_TI_TEMPLATE (name),
+                                      CLASSTYPE_TI_ARGS (name));
     }
   else if (TREE_CODE (name) == TYPE_DECL)
     name = DECL_NAME (name);
@@ -3215,12 +3216,17 @@ make_typename_type (tree context, tree name, enum 
tag_types tag_type,
          error ("%qD is not a type", name);
          return error_mark_node;
        }
+      fullname = build_template_id_type (TREE_OPERAND (fullname, 0),
+                                        TREE_OPERAND (fullname, 1));
     }
   if (TREE_CODE (name) == TEMPLATE_DECL)
     {
       error ("%qD used without template parameters", name);
       return error_mark_node;
     }
+  if (TREE_CODE (name) == TEMPLATE_ID_TYPE)
+    name = TYPE_IDENTIFIER (name);
+
   gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
   gcc_assert (TYPE_P (context));
 
@@ -3246,7 +3252,7 @@ make_typename_type (tree context, tree name, enum 
tag_types tag_type,
   if ((!t || TREE_CODE (t) == TREE_LIST) && dependent_type_p (context))
     return build_typename_type (context, name, fullname, tag_type);
 
-  want_template = TREE_CODE (fullname) == TEMPLATE_ID_EXPR;
+  want_template = TREE_CODE (fullname) == TEMPLATE_ID_TYPE;
   
   if (!t)
     {
@@ -3294,7 +3300,7 @@ make_typename_type (tree context, tree name, enum 
tag_types tag_type,
   add_typedef_to_current_template_for_access_check (t, context, 
input_location);
 
   if (want_template)
-    return lookup_template_class (t, TREE_OPERAND (fullname, 1),
+    return lookup_template_class (t, TYPE_TI_ARGS (fullname),
                                  NULL_TREE, context,
                                  /*entering_scope=*/0,
                                  tf_warning_or_error | tf_user);
@@ -11377,7 +11383,7 @@ check_elaborated_type_specifier (enum tag_types 
tag_code,
     }
   /* Accept bound template template parameters.  */
   else if (allow_template_p
-          && TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
+          && BOUND_TEMPLATE_TEMPLATE_PARM_P (type))
     ;
   /*   [dcl.type.elab]
 
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 05f4b42..b677104 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -1130,8 +1130,8 @@ is_late_template_attribute (tree attr, tree decl)
       /* We can't apply any attributes to a completely unknown type until
         instantiation time.  */
       enum tree_code code = TREE_CODE (type);
-      if (code == TEMPLATE_TYPE_PARM
-         || code == BOUND_TEMPLATE_TEMPLATE_PARM
+      if (BOUND_TEMPLATE_TEMPLATE_PARM_P (type)
+         ||code == TEMPLATE_TYPE_PARM
          || code == TYPENAME_TYPE)
        return true;
       /* Also defer most attributes on dependent types.  This is not
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 21d6781..20c158f 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -451,7 +451,7 @@ dump_type (tree t, int flags)
        pp_cxx_canonical_template_parameter (cxx_pp, t);
       break;
 
-    case BOUND_TEMPLATE_TEMPLATE_PARM:
+    case TEMPLATE_ID_TYPE:
       {
        tree args = TYPE_TI_ARGS (t);
        pp_cxx_cv_qualifier_seq (cxx_pp, t);
@@ -570,7 +570,7 @@ dump_typename (tree t, int flags)
   else
     dump_type (ctx, flags & ~TFF_CLASS_KEY_OR_ENUM);
   pp_cxx_colon_colon (cxx_pp);
-  dump_decl (TYPENAME_TYPE_FULLNAME (t), flags);
+  dump_type (TYPENAME_TYPE_FULLNAME (t), flags);
 }
 
 /* Return the name of the supplied aggregate, or enumeral type.  */
@@ -766,7 +766,7 @@ dump_type_prefix (tree t, int flags)
     case RECORD_TYPE:
     case TEMPLATE_TYPE_PARM:
     case TEMPLATE_TEMPLATE_PARM:
-    case BOUND_TEMPLATE_TEMPLATE_PARM:
+    case TEMPLATE_ID_TYPE:
     case TREE_LIST:
     case TYPE_DECL:
     case TREE_VEC:
@@ -869,7 +869,7 @@ dump_type_suffix (tree t, int flags)
     case RECORD_TYPE:
     case TEMPLATE_TYPE_PARM:
     case TEMPLATE_TEMPLATE_PARM:
-    case BOUND_TEMPLATE_TEMPLATE_PARM:
+    case TEMPLATE_ID_TYPE:
     case TREE_LIST:
     case TYPE_DECL:
     case TREE_VEC:
@@ -2407,7 +2407,7 @@ dump_expr (tree t, int flags)
 
     case TEMPLATE_TYPE_PARM:
     case TEMPLATE_TEMPLATE_PARM:
-    case BOUND_TEMPLATE_TEMPLATE_PARM:
+    case TEMPLATE_ID_TYPE:
       dump_type (t, flags);
       break;
 
diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c
index c11e3b3..4320e33 100644
--- a/gcc/cp/lex.c
+++ b/gcc/cp/lex.c
@@ -664,7 +664,7 @@ cxx_make_type (enum tree_code code)
 
   /* Create lang_type structure.  */
   if (RECORD_OR_UNION_CODE_P (code)
-      || code == BOUND_TEMPLATE_TEMPLATE_PARM)
+      || code == TEMPLATE_ID_TYPE)
     {
       struct lang_type *pi
           = ggc_alloc_cleared_lang_type (sizeof (struct lang_type));
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 548998a..7235660 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -83,7 +83,7 @@ along with GCC; see the file COPYING3.  If not see
    without parameters inside the template.  */
 #define CLASSTYPE_TEMPLATE_ID_P(NODE)                                  \
   (TYPE_LANG_SPECIFIC (NODE) != NULL                                   \
-   && (TREE_CODE (NODE) == BOUND_TEMPLATE_TEMPLATE_PARM                        
\
+   && (BOUND_TEMPLATE_TEMPLATE_PARM_P (NODE)                           \
        || (CLASSTYPE_TEMPLATE_INFO (NODE) != NULL                      \
           && (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (NODE))))))
 
@@ -935,10 +935,10 @@ write_nested_name (const tree decl)
   else if (TREE_CODE (TREE_TYPE (decl)) == TYPENAME_TYPE)
     {
       tree name = TYPENAME_TYPE_FULLNAME (TREE_TYPE (decl));
-      if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
+      if (TREE_CODE (name) == TEMPLATE_ID_TYPE)
        {
          write_template_prefix (decl);
-         write_template_args (TREE_OPERAND (name, 1));
+         write_template_args (TYPE_TI_ARGS (name));
        }
       else
        {
@@ -1023,10 +1023,10 @@ write_prefix (const tree node)
   else if (TREE_CODE (TREE_TYPE (decl)) == TYPENAME_TYPE)
     {
       tree name = TYPENAME_TYPE_FULLNAME (TREE_TYPE (decl));
-      if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
+      if (TREE_CODE (name) == TEMPLATE_ID_TYPE)
        {
          write_template_prefix (decl);
-         write_template_args (TREE_OPERAND (name, 1));
+         write_template_args (TYPE_TI_ARGS (name));
        }
       else
        {
@@ -1943,10 +1943,10 @@ write_type (tree type)
              write_template_template_param (type);
              break;
 
-           case BOUND_TEMPLATE_TEMPLATE_PARM:
+           case TEMPLATE_ID_TYPE:
+             gcc_assert (BOUND_TEMPLATE_TEMPLATE_PARM_P (type));
              write_template_template_param (type);
-             write_template_args
-               (TI_ARGS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (type)));
+             write_template_args (TYPE_TI_ARGS (type));
              break;
 
            case VECTOR_TYPE:
@@ -2521,7 +2521,7 @@ write_expression (tree expr)
   /* Handle template parameters.  */
   if (code == TEMPLATE_TYPE_PARM
       || code == TEMPLATE_TEMPLATE_PARM
-      || code == BOUND_TEMPLATE_TEMPLATE_PARM
+      || BOUND_TEMPLATE_TEMPLATE_PARM_P (expr)
       || code == TEMPLATE_PARM_INDEX)
     write_template_param (expr);
   /* Handle literals.  */
@@ -2995,9 +2995,10 @@ write_template_param (const tree parm)
 
   switch (TREE_CODE (parm))
     {
+    case TEMPLATE_ID_TYPE:
+      gcc_assert (BOUND_TEMPLATE_TEMPLATE_PARM_P (parm));
     case TEMPLATE_TYPE_PARM:
     case TEMPLATE_TEMPLATE_PARM:
-    case BOUND_TEMPLATE_TEMPLATE_PARM:
       parm_index = TEMPLATE_TYPE_IDX (parm);
       break;
 
@@ -3027,10 +3028,9 @@ write_template_template_param (const tree parm)
   /* PARM, a TEMPLATE_TEMPLATE_PARM, is an instantiation of the
      template template parameter.  The substitution candidate here is
      only the template.  */
-  if (TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM)
+  if (BOUND_TEMPLATE_TEMPLATE_PARM_P (parm))
     {
-      templ
-       = TI_TEMPLATE (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (parm));
+      templ = TI_TEMPLATE (TYPE_TEMPLATE_INFO (parm));
       if (find_substitution (templ))
        return;
     }
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index ceecdef..56ee569 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -5330,7 +5330,7 @@ arg_assoc_type (struct arg_lookup *k, tree type)
       /* Associate the return type.  */
       return arg_assoc_type (k, TREE_TYPE (type));
     case TEMPLATE_TYPE_PARM:
-    case BOUND_TEMPLATE_TEMPLATE_PARM:
+    case TEMPLATE_ID_TYPE:
       return false;
     case TYPENAME_TYPE:
       return false;
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 5952a0f..97de50f 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -5093,7 +5093,7 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
                   || CLASSTYPE_IS_TEMPLATE (new_scope)))
          && !(TREE_CODE (new_scope) == TYPENAME_TYPE
               && (TREE_CODE (TYPENAME_TYPE_FULLNAME (new_scope))
-                  == TEMPLATE_ID_EXPR)))
+                  == TEMPLATE_ID_TYPE)))
        permerror (input_location, TYPE_P (new_scope)
                   ? G_("%qT is not a template")
                   : G_("%qD is not a template"),
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index bb5aa0c..7d00770 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -328,10 +328,8 @@ get_template_info (const_tree t)
   if (!tinfo && DECL_IMPLICIT_TYPEDEF_P (t))
     t = TREE_TYPE (t);
 
-  if (TAGGED_TYPE_P (t))
+  if (TYPE_P (t))
     tinfo = TYPE_TEMPLATE_INFO (t);
-  else if (TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)
-    tinfo = TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t);
 
   return tinfo;
 }
@@ -805,7 +803,7 @@ maybe_process_partial_specialization (tree type)
   if (type == error_mark_node)
     return error_mark_node;
 
-  if (TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
+  if (BOUND_TEMPLATE_TEMPLATE_PARM_P (type))
     {
       error ("name of class shadows template template parameter %qD",
             TYPE_NAME (type));
@@ -3040,10 +3038,15 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, 
void* data)
     case TEMPLATE_PARM_INDEX:
       return NULL_TREE;
 
-    case BOUND_TEMPLATE_TEMPLATE_PARM:
+    case TEMPLATE_ID_TYPE:
       /* Check the template itself.  */
-      cp_walk_tree (&TREE_TYPE (TYPE_TI_TEMPLATE (t)), 
-                   &find_parameter_packs_r, ppd, ppd->visited);
+      if (TYPE_TI_TEMPLATE (t) == NULL_TREE)
+       /* This can happen when the name of the template can not yet
+          be resolved to a TEMPLATE_DECL.  So we don't have any
+          template tree to walk, yet.  */;
+      else
+       cp_walk_tree (&TREE_TYPE (TYPE_TI_TEMPLATE (t)), 
+                     &find_parameter_packs_r, ppd, ppd->visited);
       /* Check the template arguments.  */
       cp_walk_tree (&TYPE_TI_ARGS (t), &find_parameter_packs_r, ppd, 
                    ppd->visited);
@@ -7303,10 +7306,11 @@ lookup_template_class_1 (tree d1, tree arglist, tree 
in_decl, tree context,
       int is_dependent_type;
       int use_partial_inst_tmpl = false;
 
-      if (template_type == error_mark_node)
-       /* An error occured while building the template TEMPL, and a
-          diagnostic has most certainly been emitted for that
-          already.  Let's propagate that error.  */
+      if (template_type == error_mark_node
+         || arglist == error_mark_node)
+       /* An error occured while building the template TEMPL or its
+          argument list, and a diagnostic has most certainly been
+          emitted for that already.  Let's propagate that error.  */
        return error_mark_node;
 
       gen_tmpl = most_general_template (templ);
@@ -7812,11 +7816,15 @@ for_each_template_parm_r (tree *tp, int *walk_subtrees, 
void *d)
        return error_mark_node;
       break;
 
-    case BOUND_TEMPLATE_TEMPLATE_PARM:
+    case TEMPLATE_ID_TYPE:
       /* Record template parameters such as `T' inside `TT<T>'.  */
       if (for_each_template_parm (TYPE_TI_ARGS (t), fn, data, pfd->visited,
                                  pfd->include_nondeduced_p))
        return error_mark_node;
+
+      if (!BOUND_TEMPLATE_TEMPLATE_PARM_P (t))
+       break;
+
       /* Fall through.  */
 
     case TEMPLATE_TEMPLATE_PARM:
@@ -7888,7 +7896,7 @@ for_each_template_parm_r (tree *tp, int *walk_subtrees, 
void *d)
 }
 
 /* For each TEMPLATE_TYPE_PARM, TEMPLATE_TEMPLATE_PARM,
-   BOUND_TEMPLATE_TEMPLATE_PARM or TEMPLATE_PARM_INDEX in T,
+   TEMPLATE_ID_TYPE or TEMPLATE_PARM_INDEX in T,
    call FN with the parameter and the DATA.
    If FN returns nonzero, the iteration is terminated, and
    for_each_template_parm returns 1.  Otherwise, the iteration
@@ -11221,7 +11229,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, 
tree in_decl)
 
     case TEMPLATE_TYPE_PARM:
     case TEMPLATE_TEMPLATE_PARM:
-    case BOUND_TEMPLATE_TEMPLATE_PARM:
+    case TEMPLATE_ID_TYPE:
     case TEMPLATE_PARM_INDEX:
       {
        int idx;
@@ -11231,6 +11239,34 @@ tsubst (tree t, tree args, tsubst_flags_t complain, 
tree in_decl)
 
        r = NULL_TREE;
 
+       if (code == TEMPLATE_ID_TYPE
+           && !BOUND_TEMPLATE_TEMPLATE_PARM_P (t))
+         {
+           /* We are processing a type constructed from a
+              template-id.  Bound template template parameters are a
+              particular case of TEMPLATE_ID_TYPE, and they are
+              handled in an 'else' clause a bit later in this
+              function.  */
+           tree argvec = tsubst (TYPE_TI_ARGS (t),
+                                 args, complain, in_decl);
+
+           if (TYPE_TI_TEMPLATE (t) != NULL_TREE)
+             /* The template name of the TEMPLATE_ID_TYPE resolved to
+                a TEMPLATE_DECL, so we can try to build a class type
+                for it.  */
+             r = lookup_template_class (TYPE_TI_TEMPLATE (t),
+                                        argvec, in_decl, NULL_TREE,
+                                        /*entering_scope=*/0, complain);
+           else
+             /* The template name of the TEMPLATE_ID_TYPE hasn't yet
+                resolved to a TEMPLATE_DECL, so we can't build a
+                class type from it yet.  */
+             r = build_template_id_type (TYPE_IDENTIFIER (t),
+                                         argvec);
+           return cp_build_qualified_type_real
+             (r, cp_type_quals (t), complain);
+         }
+
        gcc_assert (TREE_VEC_LENGTH (args) > 0);
        template_parm_level_and_index (t, &level, &idx); 
 
@@ -11272,12 +11308,13 @@ tsubst (tree t, tree args, tsubst_flags_t complain, 
tree in_decl)
                return cp_build_qualified_type_real
                  (arg, quals, complain | tf_ignore_bad_quals);
              }
-           else if (code == BOUND_TEMPLATE_TEMPLATE_PARM)
+           else if (code == TEMPLATE_ID_TYPE)
              {
                /* We are processing a type constructed from a
                   template template parameter.  */
                tree argvec = tsubst (TYPE_TI_ARGS (t),
                                      args, complain, in_decl);
+
                if (argvec == error_mark_node)
                  return error_mark_node;
 
@@ -11302,10 +11339,10 @@ tsubst (tree t, tree args, tsubst_flags_t complain, 
tree in_decl)
                          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
+                    When #1 is parsed, the template of the
+                    TEMPLATE_ID_TYPE representing the `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
@@ -11315,9 +11352,9 @@ tsubst (tree t, tree args, tsubst_flags_t complain, 
tree in_decl)
                     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),
+                                            build_template_id_type
+                                            (TYPE_IDENTIFIER (arg),
+                                             argvec),
                                             typename_type,
                                             complain);
 
@@ -11353,9 +11390,12 @@ tsubst (tree t, tree args, tsubst_flags_t complain, 
tree in_decl)
           template parameter, but with a lower level.  */
        switch (code)
          {
+         case TEMPLATE_ID_TYPE:
+           /* This must be a bound template template parm, otherwise,
+              it would have been handled earlier.  */
+           gcc_assert (BOUND_TEMPLATE_TEMPLATE_PARM_P (t));
          case TEMPLATE_TYPE_PARM:
          case TEMPLATE_TEMPLATE_PARM:
-         case BOUND_TEMPLATE_TEMPLATE_PARM:
            if (cp_type_quals (t))
              {
                r = tsubst (TYPE_MAIN_VARIANT (t), args, complain, in_decl);
@@ -11389,14 +11429,14 @@ tsubst (tree t, tree args, tsubst_flags_t complain, 
tree in_decl)
                else
                  TYPE_CANONICAL (r) = canonical_type_parameter (r);
 
-               if (code == BOUND_TEMPLATE_TEMPLATE_PARM)
+               if (BOUND_TEMPLATE_TEMPLATE_PARM_P (t))
                  {
                    tree argvec = tsubst (TYPE_TI_ARGS (t), args,
                                          complain, in_decl);
                    if (argvec == error_mark_node)
                      return error_mark_node;
 
-                   TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (r)
+                   TEMPLATE_ID_TYPE_TEMPLATE_INFO (r)
                      = build_template_info (TYPE_TI_TEMPLATE (t), argvec);
                  }
              }
@@ -12424,7 +12464,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t 
complain, tree in_decl)
     case INTEGER_TYPE:
     case TEMPLATE_TYPE_PARM:
     case TEMPLATE_TEMPLATE_PARM:
-    case BOUND_TEMPLATE_TEMPLATE_PARM:
+    case TEMPLATE_ID_TYPE:
     case TEMPLATE_PARM_INDEX:
     case POINTER_TYPE:
     case REFERENCE_TYPE:
@@ -15851,7 +15891,7 @@ template_parm_level_and_index (tree parm, int* level, 
int* index)
 {
   if (TREE_CODE (parm) == TEMPLATE_TYPE_PARM
       || TREE_CODE (parm) == TEMPLATE_TEMPLATE_PARM
-      || TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM)
+      || BOUND_TEMPLATE_TEMPLATE_PARM_P (parm))
     {
       *index = TEMPLATE_TYPE_IDX (parm);
       *level = TEMPLATE_TYPE_LEVEL (parm);
@@ -16216,9 +16256,10 @@ unify (tree tparms, tree targs, tree parm, tree arg, 
int strict,
         within the nested-name-specifier.  */
       return unify_success (explain_p);
 
+    case TEMPLATE_ID_TYPE:
+      gcc_assert (BOUND_TEMPLATE_TEMPLATE_PARM_P (parm));
     case TEMPLATE_TYPE_PARM:
     case TEMPLATE_TEMPLATE_PARM:
-    case BOUND_TEMPLATE_TEMPLATE_PARM:
       tparm = TREE_VALUE (TREE_VEC_ELT (tparms, 0));
       if (tparm == error_mark_node)
        return unify_invalid (explain_p);
@@ -16245,11 +16286,11 @@ unify (tree tparms, tree targs, tree parm, tree arg, 
int strict,
              && TREE_CODE (tparm) != TEMPLATE_DECL))
        gcc_unreachable ();
 
-      if (TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM)
+      if (BOUND_TEMPLATE_TEMPLATE_PARM_P (parm))
        {
          /* ARG must be constructed from a template class or a template
             template parameter.  */
-         if (TREE_CODE (arg) != BOUND_TEMPLATE_TEMPLATE_PARM
+         if (!BOUND_TEMPLATE_TEMPLATE_PARM_P (arg)
              && !CLASSTYPE_SPECIALIZATION_OF_PRIMARY_TEMPLATE_P (arg))
            return unify_template_deduction_failure (explain_p, parm, arg);
 
@@ -16342,7 +16383,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, 
int strict,
        }
 
       if (TREE_CODE (parm) == TEMPLATE_TEMPLATE_PARM
-         || TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM)
+         || BOUND_TEMPLATE_TEMPLATE_PARM_P (parm))
        {
          /* Deduce template name TT from TT, TT<>, TT<T> and TT<i>.  */
 
@@ -19183,7 +19224,7 @@ dependent_type_p_r (tree type)
 
   /* -- a template-id in which either the template name is a template
      parameter ...  */
-  if (TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
+  if (BOUND_TEMPLATE_TEMPLATE_PARM_P (type))
     return true;
   /* ... or any of the template arguments is a dependent type or
        an expression that is type-dependent or value-dependent.  */
@@ -20030,15 +20071,14 @@ resolve_typename_type (tree type, bool only_current_p)
       if (result == error_mark_node)
        result = NULL_TREE;
     }
-  else if (TREE_CODE (TYPENAME_TYPE_FULLNAME (type)) == TEMPLATE_ID_EXPR
-          && DECL_CLASS_TEMPLATE_P (decl))
+  else if (TREE_CODE (TYPENAME_TYPE_FULLNAME (type)) == TEMPLATE_ID_TYPE)
     {
+      tree fullname = TYPENAME_TYPE_FULLNAME (type);
       tree tmpl;
       tree args;
       /* Obtain the template and the arguments.  */
-      tmpl = TREE_OPERAND (TYPENAME_TYPE_FULLNAME (type), 0);
-      args = TREE_OPERAND (TYPENAME_TYPE_FULLNAME (type), 1);
-      /* Instantiate the template.  */
+      tmpl = TYPE_IDENTIFIER (fullname);
+      args = TYPE_TI_ARGS (fullname);
       result = lookup_template_class (tmpl, args, NULL_TREE, NULL_TREE,
                                      /*entering_scope=*/0,
                                      tf_error | tf_user);
diff --git a/gcc/cp/ptree.c b/gcc/cp/ptree.c
index a66e695..4d0331a 100644
--- a/gcc/cp/ptree.c
+++ b/gcc/cp/ptree.c
@@ -76,9 +76,13 @@ cxx_print_type (FILE *file, tree node, int indent)
 {
   switch (TREE_CODE (node))
     {
+    case TEMPLATE_ID_TYPE:
+      if (BOUND_TEMPLATE_TEMPLATE_PARM_P (node))
+       /* Fall through.  */;
+      else
+       break;
     case TEMPLATE_TYPE_PARM:
     case TEMPLATE_TEMPLATE_PARM:
-    case BOUND_TEMPLATE_TEMPLATE_PARM:
       indent_to (file, indent + 3);
       fprintf (file, "index %d level %d orig_level %d",
               TEMPLATE_TYPE_IDX (node), TEMPLATE_TYPE_LEVEL (node),
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index 3894c68..431c935 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -385,7 +385,7 @@ lookup_field_1 (tree type, tree name, bool want_type)
   tree field;
 
   if (TREE_CODE (type) == TEMPLATE_TYPE_PARM
-      || TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM
+      || BOUND_TEMPLATE_TEMPLATE_PARM_P (type)
       || TREE_CODE (type) == TYPENAME_TYPE)
     /* The TYPE_FIELDS of a TEMPLATE_TYPE_PARM and
        BOUND_TEMPLATE_TEMPLATE_PARM are not fields at all;
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 8d179d8..250e616 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1624,32 +1624,54 @@ build_exception_variant (tree type, tree raises)
   return v;
 }
 
+/*  Given a TEMPLATE_DECL or an IDENTIFIER_NODE, create a
+    TEMPLATE_ID_TYPE with args as its arguments.
+
+    The TEMPLATE_INFO of the resulting TEMPLATE_ID_TYPE can be
+    retrieved using the TEMPLATE_ID_TYPE_TEMPLATE_INFO accessor.  The
+    template arguments ARGS can be retrieved from the TEMLATE_ID_TYPE by
+    using the TYPE_TI_ARGS accessor, and the TEMPLATE_DECL can be
+    retrieved using TYPE_TI_TEMPLATE.
+
+    Note that if TMPL is an IDENTIFIER_NODE (rather than a
+    TEMPLATE_DECL), the TYPE_TI_TEMPLATE accessor will yield
+    NULL_TREE.  That IDENTIFIER_NODE can be retrieved by using the
+    TYPE_IDENTIFIER accessor instead.  */
+
+tree
+build_template_id_type (tree tmpl, tree args)
+{
+  tree result, decl, name;
+
+  gcc_assert (tmpl && (TREE_CODE (tmpl) == TEMPLATE_DECL
+                      || TREE_CODE (tmpl) == IDENTIFIER_NODE));
+
+  name = (TREE_CODE (tmpl) == TEMPLATE_DECL )? DECL_NAME (tmpl) : tmpl;
+  if (TREE_CODE (tmpl) == IDENTIFIER_NODE)
+    tmpl = NULL_TREE;
+
+  result = cxx_make_type (TEMPLATE_ID_TYPE);
+  decl = build_decl (input_location, TYPE_DECL,
+                    name, NULL_TREE);
+  TREE_TYPE (decl) = result;
+  TYPE_NAME (result) = decl;
+  TYPE_STUB_DECL (result) = decl;
+  SET_TYPE_TEMPLATE_INFO (result, build_template_info (tmpl, args));
+  TYPE_SIZE (result) = 0;
+  SET_TYPE_STRUCTURAL_EQUALITY (result);
+  return result;
+}
+
 /* Given a TEMPLATE_TEMPLATE_PARM node T, create a new
-   BOUND_TEMPLATE_TEMPLATE_PARM bound with NEWARGS as its template
-   arguments.  */
+   TEMPLATE_ID_TYPE bound with NEWARGS as its template arguments.  */
 
 tree
 bind_template_template_parm (tree t, tree newargs)
 {
-  tree decl = TYPE_NAME (t);
-  tree t2;
-
-  t2 = cxx_make_type (BOUND_TEMPLATE_TEMPLATE_PARM);
-  decl = build_decl (input_location,
-                    TYPE_DECL, DECL_NAME (decl), NULL_TREE);
-
-  /* These nodes have to be created to reflect new TYPE_DECL and template
-     arguments.  */
+  tree t2 = build_template_id_type (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t),
+                                   newargs);
   TEMPLATE_TYPE_PARM_INDEX (t2) = copy_node (TEMPLATE_TYPE_PARM_INDEX (t));
-  TEMPLATE_PARM_DECL (TEMPLATE_TYPE_PARM_INDEX (t2)) = decl;
-  TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t2)
-    = build_template_info (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t), newargs);
-
-  TREE_TYPE (decl) = t2;
-  TYPE_NAME (t2) = decl;
-  TYPE_STUB_DECL (t2) = decl;
-  TYPE_SIZE (t2) = 0;
-  SET_TYPE_STRUCTURAL_EQUALITY (t2);
+  TEMPLATE_PARM_DECL (TEMPLATE_TYPE_PARM_INDEX (t2)) = TYPE_NAME (t2);
 
   return t2;
 }
@@ -2937,7 +2959,7 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, 
walk_tree_fn func,
     {
     case DEFAULT_ARG:
     case TEMPLATE_TEMPLATE_PARM:
-    case BOUND_TEMPLATE_TEMPLATE_PARM:
+    case TEMPLATE_ID_TYPE:
     case UNBOUND_CLASS_TEMPLATE:
     case TEMPLATE_PARM_INDEX:
     case TEMPLATE_TYPE_PARM:
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 4973d7d..9200cfe 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1129,7 +1129,7 @@ comp_template_parms_position (tree t1, tree t2)
   tree index1, index2;
   gcc_assert (t1 && t2
              && TREE_CODE (t1) == TREE_CODE (t2)
-             && (TREE_CODE (t1) == BOUND_TEMPLATE_TEMPLATE_PARM
+             && (BOUND_TEMPLATE_TEMPLATE_PARM_P (t1)
                  || TREE_CODE (t1) == TEMPLATE_TEMPLATE_PARM
                  || TREE_CODE (t1) == TEMPLATE_TYPE_PARM));
 
@@ -1230,8 +1230,20 @@ structural_comptypes (tree t1, tree t2, int strict)
         track of equivalence in this case, so we fall back on it.  */
       return TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2);
 
+    case TEMPLATE_ID_TYPE:
+      if (!BOUND_TEMPLATE_TEMPLATE_PARM_P (t1))
+       {
+         if (!cp_tree_equal (TYPE_TI_TEMPLATE (t1),
+                             TYPE_TI_TEMPLATE (t2)))
+           return false;
+         return comp_template_args (TYPE_TI_ARGS (t1),
+                                    TYPE_TI_ARGS (t2));
+       }
+      else
+       {
+         /* Fall through.  */;
+       }
     case TEMPLATE_TEMPLATE_PARM:
-    case BOUND_TEMPLATE_TEMPLATE_PARM:
       if (!comp_template_parms_position (t1, t2))
        return false;
       if (!comp_template_parms
@@ -1248,7 +1260,7 @@ structural_comptypes (tree t1, tree t2, int strict)
     case UNION_TYPE:
       if (TYPE_TEMPLATE_INFO (t1) && TYPE_TEMPLATE_INFO (t2)
          && (TYPE_TI_TEMPLATE (t1) == TYPE_TI_TEMPLATE (t2)
-             || TREE_CODE (t1) == BOUND_TEMPLATE_TEMPLATE_PARM)
+             || BOUND_TEMPLATE_TEMPLATE_PARM_P (t1))
          && comp_template_args (TYPE_TI_ARGS (t1), TYPE_TI_ARGS (t2)))
        break;
 
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 4648e75..61f0c4d 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -453,10 +453,15 @@ cxx_incomplete_type_diagnostic (const_tree value, 
const_tree type,
                         "invalid use of template type parameter %qT", type);
       break;
 
-    case BOUND_TEMPLATE_TEMPLATE_PARM:
-      emit_diagnostic (diag_kind, input_location, 0,
-                      "invalid use of template template parameter %qT",
-                      TYPE_NAME (type));
+    case TEMPLATE_ID_TYPE:
+      if (BOUND_TEMPLATE_TEMPLATE_PARM_P (type))
+       emit_diagnostic (diag_kind, input_location, 0,
+                        "invalid use of template template parameter %qT",
+                        TYPE_NAME (type));
+      else
+       emit_diagnostic (diag_kind, input_location, 0,
+                        "invalid use of template-id %qT",
+                        TYPE_NAME (type));
       break;
 
     case TYPENAME_TYPE:
-- 
1.7.6.4



-- 
                Dodji

Reply via email to