PR c++/72764 - ICE with invalid template typename.
authorJason Merrill <jason@redhat.com>
Wed, 28 Jun 2017 21:06:35 +0000 (17:06 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 28 Jun 2017 21:06:35 +0000 (17:06 -0400)
* decl.c (build_typename_type): No longer static.
* tree.c (strip_typedefs): Use it instead of make_typename_type.

From-SVN: r249760

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/tree.c
gcc/testsuite/g++.dg/cpp0x/alias-decl-60.C [new file with mode: 0644]

index 2245ca9060c23550b84f93ef80a62c89ec292c9b..4b05c7efbacad4efe081700d8209b97f23a9efb5 100644 (file)
@@ -1,5 +1,9 @@
 2017-06-28  Jason Merrill  <jason@redhat.com>
 
+       PR c++/72764 - ICE with invalid template typename.
+       * decl.c (build_typename_type): No longer static.
+       * tree.c (strip_typedefs): Use it instead of make_typename_type.
+
        PR c++/69300 - ICE with self-referential noexcept
        * pt.c (maybe_instantiate_noexcept): Check for recursion.
 
index f82b1b6ae10fe5726415e672d4429d03079a084e..946a916799240ec837d5964e96dbf934126ef341 100644 (file)
@@ -6087,6 +6087,7 @@ extern tree define_label                  (location_t, tree);
 extern void check_goto                         (tree);
 extern bool check_omp_return                   (void);
 extern tree make_typename_type                 (tree, tree, enum tag_types, tsubst_flags_t);
+extern tree build_typename_type                        (tree, tree, tree, tag_types);
 extern tree make_unbound_class_template                (tree, tree, tree, tsubst_flags_t);
 extern tree build_library_fn_ptr               (const char *, tree, int);
 extern tree build_cp_library_fn_ptr            (const char *, tree, int);
index 93e24fc8984473b5ff6bd9988d729104658c613f..3d96a3ea0fd80de92e2510f081feb90bef9dc103 100644 (file)
@@ -3594,7 +3594,7 @@ struct typename_hasher : ggc_ptr_hash<tree_node>
 
 static GTY (()) hash_table<typename_hasher> *typename_htab;
 
-static tree
+tree
 build_typename_type (tree context, tree name, tree fullname,
                     enum tag_types tag_type)
 {
index bb17278c611ca12e546cf03c24895be640de4efc..4535af64dc6551bcab42dbf1ec07f03cf4735503 100644 (file)
@@ -1503,13 +1503,13 @@ strip_typedefs (tree t, bool *remove_attributes)
       break;
     case TYPENAME_TYPE:
       {
+       bool changed = false;
        tree fullname = TYPENAME_TYPE_FULLNAME (t);
        if (TREE_CODE (fullname) == TEMPLATE_ID_EXPR
            && TREE_OPERAND (fullname, 1))
          {
            tree args = TREE_OPERAND (fullname, 1);
            tree new_args = copy_node (args);
-           bool changed = false;
            for (int i = 0; i < TREE_VEC_LENGTH (args); ++i)
              {
                tree arg = TREE_VEC_ELT (args, i);
@@ -1533,12 +1533,15 @@ strip_typedefs (tree t, bool *remove_attributes)
            else
              ggc_free (new_args);
          }
-       result = make_typename_type (strip_typedefs (TYPE_CONTEXT (t),
-                                                    remove_attributes),
-                                    fullname, typename_type, tf_none);
-       /* Handle 'typedef typename A::N N;'  */
-       if (typedef_variant_p (result))
-         result = TYPE_MAIN_VARIANT (DECL_ORIGINAL_TYPE (TYPE_NAME (result)));
+       tree ctx = strip_typedefs (TYPE_CONTEXT (t), remove_attributes);
+       if (!changed && ctx == TYPE_CONTEXT (t) && !typedef_variant_p (t))
+         return t;
+       tree name = fullname;
+       if (TREE_CODE (fullname) == TEMPLATE_ID_EXPR)
+         name = TREE_OPERAND (fullname, 0);
+       /* Use build_typename_type rather than make_typename_type because we
+          don't want to resolve it here, just strip typedefs.  */
+       result = build_typename_type (ctx, name, fullname, typename_type);
       }
       break;
     case DECLTYPE_TYPE:
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-60.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-60.C
new file mode 100644 (file)
index 0000000..6bf9b7b
--- /dev/null
@@ -0,0 +1,16 @@
+// PR c++/72764
+// { dg-do compile { target c++11 } }
+
+template < typename > struct A;
+template < typename > struct B {};
+
+template < typename T >
+using C = typename A < T >::template D < T >;
+
+template < typename T > struct A
+{ 
+  // should be: template < typename > struct D : B < C < T > > {};
+  struct D : B < C < T > > {}; // { dg-error "not a class template" }
+};
+
+A < int >::D a;                        // { dg-message "required" }