re PR c++/69481 (ICE with C++11 alias using with templates)
authorNathan Sidwell <nathan@acm.org>
Tue, 13 Dec 2016 20:43:08 +0000 (20:43 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Tue, 13 Dec 2016 20:43:08 +0000 (20:43 +0000)
cp/
PR c++/69481
* cp-tree.h (TYPE_TEMPLATE_INFO): Remove alias type checking.
(TYPE_ALIAS_TEMPLATE_INFO): New.
(TYPE_TEMPLATE_INFO_MAYBE_ALIAS): New.  Use those macros.
* error.c (dump_alias_template_specialization): Adjust.
* pt.c (maybe_process_partial_specialization)
iterative_has_template_arg, find_parameter_packs_r,
alias_template_specialization_p, dependent_alias_template_spec_p,
get_underlying_template, lookup_template_class_1, unify): Adjust
template using decl access.

testsuite/
PR c++/69481
* g++.dg/cpp0x/pr69481.C: New.
(--This line, and those below, will be ignored--

M    gcc/testsuite/ChangeLog
A    gcc/testsuite/g++.dg/cpp0x/pr69481.C
M    gcc/cp/cp-tree.h
M    gcc/cp/error.c
M    gcc/cp/ChangeLog
M    gcc/cp/pt.c

From-SVN: r243624

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/error.c
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/pr69481.C [new file with mode: 0644]

index 56803bf..24ceb04 100644 (file)
@@ -1,3 +1,16 @@
+2016-12-13  Nathan Sidwell  <nathan@acm.org>
+
+       PR c++/69481
+       * cp-tree.h (TYPE_TEMPLATE_INFO): Remove alias type checking.
+       (TYPE_ALIAS_TEMPLATE_INFO): New.
+       (TYPE_TEMPLATE_INFO_MAYBE_ALIAS): New.  Use those macros.
+       * error.c (dump_alias_template_specialization): Adjust.
+       * pt.c (maybe_process_partial_specialization,
+       iterative_has_template_arg, find_parameter_packs_r,
+       alias_template_specialization_p, dependent_alias_template_spec_p,
+       get_underlying_template, lookup_template_class_1, unify): Adjust
+       template using decl access.
+
 2016-12-11  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/78637
index f7da76a..cc7ca87 100644 (file)
@@ -3038,23 +3038,30 @@ extern void decl_shadowed_for_var_insert (tree, tree);
    ->template_info)
 
 /* Template information for an ENUMERAL_, RECORD_, UNION_TYPE, or
-   BOUND_TEMPLATE_TEMPLATE_PARM type.  Note that if NODE is a
-   specialization of an alias template, this accessor returns the
-   template info for the alias template, not the one (if any) for the
-   template of the underlying type.  */
+   BOUND_TEMPLATE_TEMPLATE_PARM type.  This ignores any alias
+   templateness of NODE.  */
 #define TYPE_TEMPLATE_INFO(NODE)                                       \
-  ((TYPE_ALIAS_P (NODE) && DECL_LANG_SPECIFIC (TYPE_NAME (NODE)))      \
-   ? (DECL_LANG_SPECIFIC (TYPE_NAME (NODE))                            \
-      ? DECL_TEMPLATE_INFO (TYPE_NAME (NODE))                          \
-      : NULL_TREE)                                                     \
-   : ((TREE_CODE (NODE) == ENUMERAL_TYPE)                              \
-      ? ENUM_TEMPLATE_INFO (NODE)                                      \
-      : ((TREE_CODE (NODE) == BOUND_TEMPLATE_TEMPLATE_PARM)            \
-        ? TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (NODE)                  \
-        : (CLASS_TYPE_P (NODE)                                         \
-           ? CLASSTYPE_TEMPLATE_INFO (NODE)                            \
-           : NULL_TREE))))
+  (TREE_CODE (NODE) == ENUMERAL_TYPE                                   \
+   ? ENUM_TEMPLATE_INFO (NODE)                                         \
+   : (TREE_CODE (NODE) == BOUND_TEMPLATE_TEMPLATE_PARM                 \
+      ? TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (NODE)                    \
+      : (CLASS_TYPE_P (NODE)                                           \
+        ? CLASSTYPE_TEMPLATE_INFO (NODE)                               \
+        : NULL_TREE)))
+
+/* Template information for an alias template type.  */
+#define TYPE_ALIAS_TEMPLATE_INFO(NODE)                                 \
+  (DECL_LANG_SPECIFIC (TYPE_NAME (NODE))                               \
+   ? DECL_TEMPLATE_INFO (TYPE_NAME (NODE))                             \
+   : NULL_TREE)
 
+/* If NODE is a specialization of an alias template, this accessor
+   returns the template info for the alias template.  Otherwise behave
+   as TYPE_TEMPLATE_INFO.  */
+#define TYPE_TEMPLATE_INFO_MAYBE_ALIAS(NODE)                           \
+  (TYPE_ALIAS_P (NODE) && DECL_LANG_SPECIFIC (TYPE_NAME (NODE))                \
+   ? DECL_TEMPLATE_INFO (TYPE_NAME (NODE))                             \
+   : TYPE_TEMPLATE_INFO (NODE))
 
 /* Set the template information for an ENUMERAL_, RECORD_, or
    UNION_TYPE to VAL.  */
index 5f8fb2a..d025fcb 100644 (file)
@@ -365,15 +365,13 @@ dump_template_bindings (cxx_pretty_printer *pp, tree parms, tree args,
 static void
 dump_alias_template_specialization (cxx_pretty_printer *pp, tree t, int flags)
 {
-  tree name;
-
   gcc_assert (alias_template_specialization_p (t));
 
+  tree decl = TYPE_NAME (t);
   if (!(flags & TFF_UNQUALIFIED_NAME))
-    dump_scope (pp, CP_DECL_CONTEXT (TYPE_NAME (t)), flags);
-  name = TYPE_IDENTIFIER (t);
-  pp_cxx_tree_identifier (pp, name);
-  dump_template_parms (pp, TYPE_TEMPLATE_INFO (t),
+    dump_scope (pp, CP_DECL_CONTEXT (decl), flags);
+  pp_cxx_tree_identifier (pp, DECL_NAME (decl));
+  dump_template_parms (pp, DECL_TEMPLATE_INFO (decl),
                       /*primary=*/false,
                       flags & ~TFF_TEMPLATE_HEADER);
 }
index 97d0b48..bae96ec 100644 (file)
@@ -940,10 +940,11 @@ maybe_process_partial_specialization (tree type)
 
   if (TYPE_ALIAS_P (type))
     {
-      if (TYPE_TEMPLATE_INFO (type)
-         && DECL_ALIAS_TEMPLATE_P (TYPE_TI_TEMPLATE (type)))
+      tree tinfo = TYPE_ALIAS_TEMPLATE_INFO (type);
+
+      if (tinfo && DECL_ALIAS_TEMPLATE_P (TI_TEMPLATE (tinfo)))
        error ("specialization of alias template %qD",
-              TYPE_TI_TEMPLATE (type));
+              TI_TEMPLATE (tinfo));
       else
        error ("explicit specialization of non-template %qT", type);
       return error_mark_node;
@@ -1829,7 +1830,7 @@ iterative_hash_template_arg (tree arg, hashval_t val)
          // left alone, or untouched specializations because
          // coerce_template_parms returns the unconverted template
          // arguments if it sees incomplete argument packs.
-         tree ti = TYPE_TEMPLATE_INFO (arg);
+         tree ti = TYPE_ALIAS_TEMPLATE_INFO (arg);
          return hash_tmpl_and_args (TI_TEMPLATE (ti), TI_ARGS (ti));
        }
       if (TYPE_CANONICAL (arg))
@@ -3459,8 +3460,8 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
   /* Handle type aliases/typedefs.  */
   if (TYPE_ALIAS_P (t))
     {
-      if (TYPE_TEMPLATE_INFO (t))
-       cp_walk_tree (&TYPE_TI_ARGS (t),
+      if (tree tinfo = TYPE_ALIAS_TEMPLATE_INFO (t))
+       cp_walk_tree (&TI_ARGS (tinfo),
                      &find_parameter_packs_r,
                      ppd, ppd->visited);
       *walk_subtrees = 0;
@@ -5794,15 +5795,9 @@ alias_template_specialization_p (const_tree t)
   /* It's an alias template specialization if it's an alias and its
      TYPE_NAME is a specialization of a primary template.  */
   if (TYPE_ALIAS_P (t))
-    {
-      tree name = TYPE_NAME (t);
-      if (DECL_LANG_SPECIFIC (name))
-       if (tree ti = DECL_TEMPLATE_INFO (name))
-         {
-           tree tmpl = TI_TEMPLATE (ti);
-           return PRIMARY_TEMPLATE_P (tmpl);
-         }
-    }
+    if (tree tinfo = TYPE_ALIAS_TEMPLATE_INFO (t))
+      return PRIMARY_TEMPLATE_P (TI_TEMPLATE (tinfo));
+
   return false;
 }
 
@@ -5854,10 +5849,18 @@ complex_alias_template_p (const_tree tmpl)
 bool
 dependent_alias_template_spec_p (const_tree t)
 {
-  return (alias_template_specialization_p (t)
-         && TEMPLATE_DECL_COMPLEX_ALIAS_P (DECL_TI_TEMPLATE (TYPE_NAME (t)))
-         && (any_dependent_template_arguments_p
-             (INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (t)))));
+  if (!alias_template_specialization_p (t))
+    return false;
+
+  tree tinfo = TYPE_ALIAS_TEMPLATE_INFO (t);
+  if (!TEMPLATE_DECL_COMPLEX_ALIAS_P (TI_TEMPLATE (tinfo)))
+    return false;
+
+  tree args = INNERMOST_TEMPLATE_ARGS (TI_ARGS (tinfo));
+  if (!any_dependent_template_arguments_p (args))
+    return false;
+
+  return true;
 }
 
 /* Return the number of innermost template parameters in TMPL.  */
@@ -5879,26 +5882,27 @@ get_underlying_template (tree tmpl)
   gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL);
   while (DECL_ALIAS_TEMPLATE_P (tmpl))
     {
-      tree result = DECL_ORIGINAL_TYPE (DECL_TEMPLATE_RESULT (tmpl));
-      if (TYPE_TEMPLATE_INFO (result))
-       {
-         tree sub = TYPE_TI_TEMPLATE (result);
-         if (PRIMARY_TEMPLATE_P (sub)
-             && (num_innermost_template_parms (tmpl)
-                 == num_innermost_template_parms (sub)))
-           {
-             tree alias_args = INNERMOST_TEMPLATE_ARGS
-               (template_parms_to_args (DECL_TEMPLATE_PARMS (tmpl)));
-             if (!comp_template_args (TYPE_TI_ARGS (result), alias_args))
-               break;
-             /* The alias type is equivalent to the pattern of the
-                underlying template, so strip the alias.  */
-             tmpl = sub;
-             continue;
-           }
-       }
-      break;
+      /* Determine if the alias is equivalent to an underlying template.  */
+      tree orig_type = DECL_ORIGINAL_TYPE (DECL_TEMPLATE_RESULT (tmpl));
+      tree tinfo = TYPE_TEMPLATE_INFO_MAYBE_ALIAS (orig_type);
+      if (!tinfo)
+       break;
+
+      tree underlying = TI_TEMPLATE (tinfo);
+      if (!PRIMARY_TEMPLATE_P (underlying)
+         || (num_innermost_template_parms (tmpl)
+             != num_innermost_template_parms (underlying)))
+       break;
+
+      tree alias_args = INNERMOST_TEMPLATE_ARGS
+       (template_parms_to_args (DECL_TEMPLATE_PARMS (tmpl)));
+      if (!comp_template_args (TI_ARGS (tinfo), alias_args))
+       break;
+
+      /* Alias is equivalent.  Strip it and repeat.  */
+      tmpl = underlying;
     }
+
   return tmpl;
 }
 
@@ -8375,9 +8379,8 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
             TEMPLATE will be `template <class T> template
             <class U> struct S1<T>::S2'.  We must fill in the missing
             arguments.  */
-         arglist
-           = add_outermost_template_args (TYPE_TI_ARGS (TREE_TYPE (templ)),
-                                          arglist);
+         tree ti = TYPE_TEMPLATE_INFO_MAYBE_ALIAS (TREE_TYPE (templ));
+         arglist = add_outermost_template_args (TI_ARGS (ti), arglist);
          arg_depth = TMPL_ARGS_DEPTH (arglist);
        }
 
@@ -8407,13 +8410,15 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
 
         the `C<T>' is just the same as `C'.  Outside of the
         class, however, such a reference is an instantiation.  */
-      if ((entering_scope
-          || !PRIMARY_TEMPLATE_P (gen_tmpl)
-          || currently_open_class (template_type))
-         /* comp_template_args is expensive, check it last.  */
-         && comp_template_args (TYPE_TI_ARGS (template_type),
-                                arglist))
-       return template_type;
+      if (entering_scope
+         || !PRIMARY_TEMPLATE_P (gen_tmpl)
+         || currently_open_class (template_type))
+       {
+         tree tinfo = TYPE_TEMPLATE_INFO_MAYBE_ALIAS (template_type);
+
+         if (comp_template_args (TI_ARGS (tinfo), arglist))
+           return template_type;
+       }
 
       /* If we already have this specialization, return it.  */
       elt.tmpl = gen_tmpl;
@@ -8641,12 +8646,11 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
          && CLASS_TYPE_P (context)
          && !same_type_p (context, DECL_CONTEXT (gen_tmpl)))
        {
-         tree partial_inst_args;
          TREE_VEC_LENGTH (arglist)--;
          ++processing_template_decl;
-         partial_inst_args =
-           tsubst (INNERMOST_TEMPLATE_ARGS
-                       (TYPE_TI_ARGS (TREE_TYPE (gen_tmpl))),
+         tree tinfo = TYPE_TEMPLATE_INFO_MAYBE_ALIAS (TREE_TYPE (gen_tmpl));
+         tree partial_inst_args =
+           tsubst (INNERMOST_TEMPLATE_ARGS (TI_ARGS (tinfo)),
                    arglist, complain, NULL_TREE);
          --processing_template_decl;
          TREE_VEC_LENGTH (arglist)++;
@@ -8678,11 +8682,11 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
             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) == TEMPLATE_DECL
-           ? found
-           TREE_CODE (found) == TYPE_DECL
-           ? TYPE_TI_TEMPLATE (TREE_TYPE (found))
-           : CLASSTYPE_TI_TEMPLATE (found);
+         found = (TREE_CODE (found) == TEMPLATE_DECL
+                  ? found
+                  : (TREE_CODE (found) == TYPE_DECL
+                     ? DECL_TI_TEMPLATE (found)
+                     : CLASSTYPE_TI_TEMPLATE (found)));
        }
 
       // Build template info for the new specialization.
@@ -20035,9 +20039,6 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
            return unify_template_deduction_failure (explain_p, parm, arg);
          {
            tree parmvec = TYPE_TI_ARGS (parm);
-           /* An alias template name is never deduced.  */
-           if (TYPE_ALIAS_P (arg))
-             arg = strip_typedefs (arg);
            tree argvec = INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (arg));
            tree full_argvec = add_to_template_args (targs, argvec);
            tree parm_parms 
index 072e617..4378e36 100644 (file)
@@ -1,3 +1,8 @@
+2016-12-13  Nathan Sidwell  <nathan@acm.org>
+
+       PR c++/69481
+       * g++.dg/cpp0x/pr69481.C: New.
+
 2016-12-13  Uros Bizjak  <ubizjak@gmail.com>
 
        PR target/78794
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr69481.C b/gcc/testsuite/g++.dg/cpp0x/pr69481.C
new file mode 100644 (file)
index 0000000..bab166b
--- /dev/null
@@ -0,0 +1,26 @@
+// PR c++/69481
+// { dg-do compile { target c++11 } }
+
+// ICE with canonical type verification
+
+template <typename> struct Traits;
+
+template <typename T>
+struct Bob {
+  using Loc = Traits<T>;
+  using typename Loc::Thing;
+
+  Thing Foo (); 
+};
+
+template <class V> struct tt
+{
+  using ut = tt<V>;
+  ut Bob ();
+};
+
+template <class V>
+tt<V> tt<V>::Bob ()
+{
+  return tt();
+}