]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
cp-tree.def (UNBOUND_CLASS_TEMPLATE): New tree node.
authorKriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
Tue, 23 Oct 2001 09:14:15 +0000 (09:14 +0000)
committerKriang Lerdsuwanakij <lerdsuwa@gcc.gnu.org>
Tue, 23 Oct 2001 09:14:15 +0000 (09:14 +0000)
* cp-tree.def (UNBOUND_CLASS_TEMPLATE): New tree node.
* cp-tree.h (make_unbound_class_template): Prototype new function.
* decl.c (make_unbound_class_template): New function.
* decl2.c (arg_assoc_template_arg): Handle UNBOUND_CLASS_TEMPLATE.
* error.c (dump_type): Likewise.
* mangle.c (write_type): Likewise.
* parse.y (template_parm): Likewise.
(template_argument): Use make_unbound_class_template.
* pt.c (convert_template_argument): Handle UNBOUND_CLASS_TEMPLATE.
(tsubst): Likewise.
(tsubst_copy): Likewise.
(unify): Likewise.
* tree.c (walk_tree): Likewise.
* typeck.c (comptypes): Likewise.

From-SVN: r46430

29 files changed:
gcc/cp/ChangeLog
gcc/cp/cp-tree.def
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/error.c
gcc/cp/mangle.c
gcc/cp/parse.y
gcc/cp/pt.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/testsuite/g++.dg/template/qualttp1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/qualttp10.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/qualttp11.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/qualttp12.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/qualttp13.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/qualttp14.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/qualttp15.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/qualttp16.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/qualttp17.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/qualttp18.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/qualttp2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/qualttp3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/qualttp4.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/qualttp5.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/qualttp6.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/qualttp7.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/qualttp8.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/qualttp9.C [new file with mode: 0644]

index a8bff6cdfad2f69922f373aa9505a5925d91991d..34abbc4fbb59b7d861a693ad0155ffde870a5010 100644 (file)
@@ -1,3 +1,20 @@
+2001-10-24  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>
+
+       * cp-tree.def (UNBOUND_CLASS_TEMPLATE): New tree node.
+       * cp-tree.h (make_unbound_class_template): Prototype new function.
+       * decl.c (make_unbound_class_template): New function.
+       * decl2.c (arg_assoc_template_arg): Handle UNBOUND_CLASS_TEMPLATE.
+       * error.c (dump_type): Likewise.
+       * mangle.c (write_type): Likewise.
+       * parse.y (template_parm): Likewise.
+       (template_argument): Use make_unbound_class_template.
+       * pt.c (convert_template_argument): Handle UNBOUND_CLASS_TEMPLATE.
+       (tsubst): Likewise.
+       (tsubst_copy): Likewise.
+       (unify): Likewise.
+       * tree.c (walk_tree): Likewise.
+       * typeck.c (comptypes): Likewise.
+
 2001-10-21  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
        * xref.c (GNU_xref_member): Use safe-ctype macros and/or fold
index e7ef2b9dca779b78e46a3d0d8a2f59c0b99918f3..1395301d1d929857968f32e14e9dbbb0bbf82ba9 100644 (file)
@@ -163,6 +163,11 @@ DEFTREECODE (BOUND_TEMPLATE_TEMPLATE_PARM, "bound_template_template_parm", 't',
    of `T'.  */
 DEFTREECODE (TYPENAME_TYPE, "typename_type", 't', 0)
 
+/* For template template argument of the form `T::template C'.
+   TYPE_CONTEXT is `T', the template parameter dependent object.
+   TYPE_NAME is an IDENTIFIER_NODE for `C', the member class template.  */
+DEFTREECODE (UNBOUND_CLASS_TEMPLATE, "unbound_class_template", 't', 0)
+
 /* A type designated by `__typeof (expr)'.  TYPE_FIELDS is the
    expression in question.  */
 DEFTREECODE (TYPEOF_TYPE, "typeof_type", 't', 0)
index 290f8edb987e02f62b9c83361874273aa3b4fe88..f58e21547cbe657ba68c2d65a8f231cbb1c23244 100644 (file)
@@ -3617,6 +3617,7 @@ extern void set_namespace_binding               PARAMS ((tree, tree, tree));
 extern tree lookup_namespace_name              PARAMS ((tree, tree));
 extern tree build_typename_type                 PARAMS ((tree, tree, tree, tree));
 extern tree make_typename_type                 PARAMS ((tree, tree, int));
+extern tree make_unbound_class_template                PARAMS ((tree, tree, int));
 extern tree lookup_name_nonclass               PARAMS ((tree));
 extern tree lookup_function_nonclass            PARAMS ((tree, tree));
 extern tree lookup_name                                PARAMS ((tree, int));
index bd64bc49101309fc45eceb1a57b703d9fb1494ce..1b3fc9e83f494162d47203047c642359031eb18c 100644 (file)
@@ -5696,6 +5696,61 @@ make_typename_type (context, name, complain)
   return build_typename_type (context, name, fullname,  NULL_TREE);
 }
 
+/* Resolve `CONTEXT::template NAME'.  Returns an appropriate type,
+   unless an error occurs, in which case error_mark_node is returned.
+   If COMPLAIN zero, don't complain about any errors that occur.  */
+
+tree
+make_unbound_class_template (context, name, complain)
+     tree context, name;
+     int complain;
+{
+  tree t;
+  tree d;
+
+  if (TYPE_P (name))
+    name = TYPE_IDENTIFIER (name);
+  else if (DECL_P (name))
+    name = DECL_NAME (name);
+  if (TREE_CODE (name) != IDENTIFIER_NODE)
+    my_friendly_abort (20010902);
+
+  if (!uses_template_parms (context)
+      || currently_open_class (context))
+    {
+      tree tmpl = NULL_TREE;
+
+      if (IS_AGGR_TYPE (context))
+       tmpl = lookup_field (context, name, 0, 0);
+
+      if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
+       {
+         if (complain)
+           cp_error ("no class template named `%#T' in `%#T'", name, context);
+         return error_mark_node;
+       }
+      
+      if (!enforce_access (context, tmpl))
+       return error_mark_node;
+
+      return tmpl;
+    }
+
+  /* Build the UNBOUND_CLASS_TEMPLATE.  */
+  t = make_aggr_type (UNBOUND_CLASS_TEMPLATE);
+  TYPE_CONTEXT (t) = FROB_CONTEXT (context);
+  TREE_TYPE (t) = NULL_TREE;
+
+  /* Build the corresponding TEMPLATE_DECL.  */
+  d = build_decl (TEMPLATE_DECL, name, t);
+  TYPE_NAME (TREE_TYPE (d)) = d;
+  TYPE_STUB_DECL (TREE_TYPE (d)) = d;
+  DECL_CONTEXT (d) = FROB_CONTEXT (context);
+  DECL_ARTIFICIAL (d) = 1;
+
+  return t;
+}
+
 /* Select the right _DECL from multiple choices. */
 
 static tree
index 8c5dba175073d340c08c063c882631c4b2e63dcc..f384f0a64d3690fe250fc1be0563a4defc451d74 100644 (file)
@@ -4559,7 +4559,8 @@ arg_assoc_template_arg (k, arg)
      contribute to the set of associated namespaces.  ]  */
 
   /* Consider first template template arguments.  */
-  if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
+  if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
+      || TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE)
     return 0;
   else if (TREE_CODE (arg) == TEMPLATE_DECL)
     {
index 2e7118465751c65eb0fcc71df2bb3c9e65fc2a90..5cd3ee70c9b7e4a40c886b1abc5bb5cfd36d4db4 100644 (file)
@@ -458,6 +458,13 @@ dump_type (t, flags)
       dump_typename (t, flags);
       break;
 
+    case UNBOUND_CLASS_TEMPLATE:
+      dump_type (TYPE_CONTEXT (t), flags);
+      print_scope_operator (scratch_buffer);
+      print_identifier (scratch_buffer, "template ");
+      dump_type (DECL_NAME (TYPE_NAME (t)), flags);
+      break;
+
     case TYPEOF_TYPE:
       output_add_string (scratch_buffer, "__typeof (");
       dump_expr (TYPE_FIELDS (t), flags & ~TFF_EXPR_IN_PARENS);
index 6ad9ffa3f2607bb962aa0a763bc0c8efe743de1e..0f6500ee4688adb37ebc92097b30a2e935e688c9 100644 (file)
@@ -1393,7 +1393,9 @@ write_type (type)
          break;
 
        case TYPENAME_TYPE:
-         /* We handle TYPENAME_TYPEs like ordinary nested names.  */
+       case UNBOUND_CLASS_TEMPLATE:
+         /* We handle TYPENAME_TYPEs and UNBOUND_CLASS_TEMPLATEs like
+            ordinary nested names.  */
          write_nested_name (TYPE_STUB_DECL (type));
          break;
 
index f3e85ffe849e69089dbfdd182f945f4ff8ea1829..937e1c8e8177702432b9b7891250263499530b60 100644 (file)
@@ -669,7 +669,8 @@ template_parm:
                {
                  if (TREE_CODE ($3) != TEMPLATE_DECL
                      && TREE_CODE ($3) != TEMPLATE_TEMPLATE_PARM
-                     && TREE_CODE ($3) != TYPE_DECL)
+                     && TREE_CODE ($3) != TYPE_DECL
+                     && TREE_CODE ($3) != UNBOUND_CLASS_TEMPLATE)
                    {
                      error ("invalid default template argument");
                      $3 = error_mark_node;
@@ -1100,6 +1101,16 @@ template_arg:
                    $$ = TREE_TYPE ($$);
                }
        | expr_no_comma_rangle
+       | nested_name_specifier TEMPLATE identifier
+               {
+                 if (!processing_template_decl)
+                   {
+                     cp_error ("use of template qualifier outside template");
+                     $$ = error_mark_node;
+                   }
+                 else
+                   $$ = make_unbound_class_template ($1, $3, 1);
+               }
        ;
 
 unop:
index 5a5cf4dafe95cae073096ead0eae0ff6aaf3d7b4..a99b80d32ec8bbbb7468581cd1f8b0a9e7fc127f 100644 (file)
@@ -3301,13 +3301,16 @@ convert_template_argument (parm, arg, args, complain, i, in_decl)
     = ((TREE_CODE (arg) == TEMPLATE_DECL
        && TREE_CODE (DECL_TEMPLATE_RESULT (arg)) == TYPE_DECL)
        || TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
+       || TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE
        || (TREE_CODE (arg) == RECORD_TYPE
           && CLASSTYPE_TEMPLATE_INFO (arg)
           && TREE_CODE (TYPE_NAME (arg)) == TYPE_DECL
           && DECL_ARTIFICIAL (TYPE_NAME (arg))
           && requires_tmpl_type
           && is_base_of_enclosing_class (arg, current_class_type)));
-  if (is_tmpl_type && TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
+  if (is_tmpl_type
+      && (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
+         || TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE))
     arg = TYPE_STUB_DECL (arg);
   else if (is_tmpl_type && TREE_CODE (arg) == RECORD_TYPE)
     arg = CLASSTYPE_TI_TEMPLATE (arg);
@@ -3360,30 +3363,38 @@ convert_template_argument (parm, arg, args, complain, i, in_decl)
     {
       if (requires_tmpl_type)
        {
-         tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
-         tree argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
-
-         if (coerce_template_template_parms (parmparm, argparm, complain,
-                                             in_decl, inner_args))
-           {
-             val = arg;
-                 
-             /* TEMPLATE_TEMPLATE_PARM node is preferred over 
-                TEMPLATE_DECL.  */
-             if (val != error_mark_node 
-                 && DECL_TEMPLATE_TEMPLATE_PARM_P (val))
-               val = TREE_TYPE (val);
-           }
+         if (TREE_CODE (TREE_TYPE (arg)) == UNBOUND_CLASS_TEMPLATE)
+           /* The number of argument required is not known yet.
+              Just accept it for now.  */
+           val = TREE_TYPE (arg);
          else
            {
-             if (in_decl && complain)
+             tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
+             tree argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
+
+             if (coerce_template_template_parms (parmparm, argparm,
+                                                 complain, in_decl,
+                                                 inner_args))
                {
-                 cp_error ("type/value mismatch at argument %d in template parameter list for `%D'",
-                           i + 1, in_decl);
-                 cp_error ("  expected a template of type `%D', got `%D'", parm, arg);
+                 val = arg;
+                 
+                 /* TEMPLATE_TEMPLATE_PARM node is preferred over 
+                    TEMPLATE_DECL.  */
+                 if (val != error_mark_node 
+                     && DECL_TEMPLATE_TEMPLATE_PARM_P (val))
+                   val = TREE_TYPE (val);
                }
+             else
+               {
+                 if (in_decl && complain)
+                   {
+                     cp_error ("type/value mismatch at argument %d in template parameter list for `%D'",
+                               i + 1, in_decl);
+                     cp_error ("  expected a template of type `%D', got `%D'", parm, arg);
+                   }
                  
-             val = error_mark_node;
+                 val = error_mark_node;
+               }
            }
        }
       else
@@ -6750,6 +6761,18 @@ tsubst (t, args, complain, in_decl)
                                             complain);
       }
 
+    case UNBOUND_CLASS_TEMPLATE:
+      {
+       tree ctx = tsubst_aggr_type (TYPE_CONTEXT (t), args, complain,
+                                    in_decl, /*entering_scope=*/1);
+       tree name = TYPE_IDENTIFIER (t);
+
+       if (ctx == error_mark_node || name == error_mark_node)
+         return error_mark_node;
+
+       return make_unbound_class_template (ctx, name, complain);
+      }
+
     case INDIRECT_REF:
       {
        tree e = tsubst (TREE_OPERAND (t, 0), args, complain,
@@ -7150,6 +7173,7 @@ tsubst_copy (t, args, complain, in_decl)
     case METHOD_TYPE:
     case ARRAY_TYPE:
     case TYPENAME_TYPE:
+    case UNBOUND_CLASS_TEMPLATE:
     case TYPE_DECL:
       return tsubst (t, args, complain, in_decl);
 
@@ -8542,6 +8566,7 @@ unify (tparms, targs, parm, arg, strict)
   switch (TREE_CODE (parm))
     {
     case TYPENAME_TYPE:
+    case UNBOUND_CLASS_TEMPLATE:
       /* In a type which contains a nested-name-specifier, template
         argument values cannot be deduced for template parameters used
         within the nested-name-specifier.  */
index 2c4c7446424abde95f71d0a7898afcabeba7185a..6ae0a352d38417fa8551448028335277ac0d4de9 100644 (file)
@@ -2079,6 +2079,7 @@ cp_walk_subtrees (tp, walk_subtrees_p, func, data, htab)
     case DEFAULT_ARG:
     case TEMPLATE_TEMPLATE_PARM:
     case BOUND_TEMPLATE_TEMPLATE_PARM:
+    case UNBOUND_CLASS_TEMPLATE:
     case TEMPLATE_PARM_INDEX:
     case TEMPLATE_TYPE_PARM:
     case TYPENAME_TYPE:
index 850ce8be826c8a39a2ad8738ec2e7d8e6c8b57f8..dda76fe2fcdca2932ea1bf5fc35dd4668a3dc308 100644 (file)
@@ -1097,6 +1097,12 @@ comptypes (t1, t2, strict)
         return 0;
       return same_type_p (TYPE_CONTEXT (t1), TYPE_CONTEXT (t2));
 
+    case UNBOUND_CLASS_TEMPLATE:
+      if (cp_tree_equal (TYPE_IDENTIFIER (t1),
+                         TYPE_IDENTIFIER (t2)) < 1)
+        return 0;
+      return same_type_p (TYPE_CONTEXT (t1), TYPE_CONTEXT (t2));
+
     case COMPLEX_TYPE:
       return same_type_p (TREE_TYPE (t1), TREE_TYPE (t2));
 
diff --git a/gcc/testsuite/g++.dg/template/qualttp1.C b/gcc/testsuite/g++.dg/template/qualttp1.C
new file mode 100644 (file)
index 0000000..b97ef42
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright (C) 2001 Free Software Foundation
+// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+// { dg-do compile }
+
+struct A
+{
+       template <class T> class B {};
+};
+
+template <class T> struct X
+{
+};
+
+template <class T> struct C
+{
+       X<T::template B> x; // { dg-error "type" }
+};
+
+int main()
+{
+       C<A> c;
+}
diff --git a/gcc/testsuite/g++.dg/template/qualttp10.C b/gcc/testsuite/g++.dg/template/qualttp10.C
new file mode 100644 (file)
index 0000000..8734ddc
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright (C) 2001 Free Software Foundation
+// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+// { dg-do compile }
+
+template <template <class> class TT> class C {
+};
+
+template <class T> struct D {
+       template <class U> class B {};
+       C<D<T>::template B> c;
+};
+
+D<int> d;
diff --git a/gcc/testsuite/g++.dg/template/qualttp11.C b/gcc/testsuite/g++.dg/template/qualttp11.C
new file mode 100644 (file)
index 0000000..fa5c860
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright (C) 2001 Free Software Foundation
+// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+// { dg-do link }
+
+struct A
+{
+       template <class T> class B {};
+};
+
+template <template <class> class TT> struct X
+{
+       TT<int> y;
+};
+
+template <class T> struct C
+{
+       X<T::template B> x;
+};
+
+int main()
+{
+       C<A> c;
+}
diff --git a/gcc/testsuite/g++.dg/template/qualttp12.C b/gcc/testsuite/g++.dg/template/qualttp12.C
new file mode 100644 (file)
index 0000000..ebd4b64
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright (C) 2001 Free Software Foundation
+// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+// { dg-do link }
+
+struct A
+{
+       template <class T> class B {};
+};
+
+template <template <class> class TT> void f()
+{
+       TT<int> y;
+}
+
+template <class T> struct C
+{
+       void g() { f<T::template B>(); }
+};
+
+int main()
+{
+       C<A> c;
+       c.g();
+}
diff --git a/gcc/testsuite/g++.dg/template/qualttp13.C b/gcc/testsuite/g++.dg/template/qualttp13.C
new file mode 100644 (file)
index 0000000..eefc604
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright (C) 2001 Free Software Foundation
+// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+template <class U> struct A
+{
+       template <class V> struct AA {
+               template <class T> struct B {
+                       int i;
+                       B() : i(1) {}
+               };
+       };
+};
+
+template <template <class> class TT> struct X
+{
+       TT<int> y;
+};
+
+template <class T, class U> struct C
+{
+       X<T::template AA<U>::template B> x;
+};
+
+int main()
+{
+       C<A<char>, int> c;
+}
diff --git a/gcc/testsuite/g++.dg/template/qualttp14.C b/gcc/testsuite/g++.dg/template/qualttp14.C
new file mode 100644 (file)
index 0000000..0558557
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright (C) 2001 Free Software Foundation
+// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+// { dg-do link }
+
+struct A
+{
+       template <class T> class B {};
+};
+
+template <template <class> class TT, class T> struct X
+{
+       TT<int> y;
+       T z;
+};
+
+template <class T> struct X<T::template B, T>
+{
+       typename T::template B<int> y;
+       T z;
+};
+
+template <class T> struct C
+{
+       X<T::template B, A> x;
+};
+
+int main()
+{
+       C<A> c;
+}
diff --git a/gcc/testsuite/g++.dg/template/qualttp15.C b/gcc/testsuite/g++.dg/template/qualttp15.C
new file mode 100644 (file)
index 0000000..1b1f3bb
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright (C) 2001 Free Software Foundation
+// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+// { dg-do compile }
+
+struct A
+{
+       template <class T> class B {};
+};
+
+template <template <class> class TT> struct X
+{
+       TT<int> y;
+};
+
+template <class T> struct X<T::template B>
+{      // { dg-error "previous" }
+       T z;
+};
+
+template <class T> struct X<T::template B>
+{      // { dg-error "redefinition" }
+       T z;
+};
+
+template <class T> struct C
+{
+       X<T::template B> x;
+};
+
+int main()
+{
+       C<A> c;
+}
diff --git a/gcc/testsuite/g++.dg/template/qualttp16.C b/gcc/testsuite/g++.dg/template/qualttp16.C
new file mode 100644 (file)
index 0000000..1fd0e1f
--- /dev/null
@@ -0,0 +1,40 @@
+// Copyright (C) 2001 Free Software Foundation
+// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+// { dg-do run }
+
+extern "C" void abort();
+
+struct A
+{
+       template <class T> class B {};
+};
+
+template <template <class> class TT, class T> struct X
+{
+       TT<int> y;
+       T z;
+       int f() { return 0; }
+};
+
+template <class T> struct X<T::template B, T>
+{
+       typename T::template B<int> y;
+       T z;
+       int f() { return 1; }
+};
+
+template <class T> struct C
+{
+       X<T::template B, A> x;
+};
+
+int main()
+{
+       C<A> c;
+       X<A::B, A> x1;
+       X<A::B, int> x2;
+       if (x1.f() != 1)
+               abort();
+       if (x2.f() != 0)
+               abort();
+}
diff --git a/gcc/testsuite/g++.dg/template/qualttp17.C b/gcc/testsuite/g++.dg/template/qualttp17.C
new file mode 100644 (file)
index 0000000..4766c53
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright (C) 2001 Free Software Foundation
+// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+// { dg-do compile }
+// { dg-options "-fno-inline" }
+
+struct A
+{
+       template <class T> class B {};
+};
+
+template <template <class> class TT> struct X
+{
+};
+
+template <class T> void f(X<T::template B>)
+{
+}
+
+int main()
+{
+       X<A::B> x;
+       f<A>(x);
+}
+
+// { dg-final { scan-assembler "\n_?_Z1fI1AEv1XIN1T1BEE\[: \t\n\]" } }
diff --git a/gcc/testsuite/g++.dg/template/qualttp18.C b/gcc/testsuite/g++.dg/template/qualttp18.C
new file mode 100644 (file)
index 0000000..2c9cf06
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright (C) 2001 Free Software Foundation
+// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+// { dg-do compile }
+
+struct A
+{
+       template <class T> class B {};
+};
+
+template <template <class> class TT> struct X
+{
+       TT<int> y;
+};
+
+struct C
+{
+       X<A::template B> x; // { dg-error "template|forbid" }
+};
+
+int main()
+{
+       C c;
+}
diff --git a/gcc/testsuite/g++.dg/template/qualttp2.C b/gcc/testsuite/g++.dg/template/qualttp2.C
new file mode 100644 (file)
index 0000000..b25e15f
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright (C) 2001 Free Software Foundation
+// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+// { dg-do compile }
+
+struct A
+{
+       template <class T> class B {};
+};
+
+template <int i> struct X
+{
+};
+
+template <class T> struct C
+{
+       X<T::template B> x; // { dg-error "type" }
+};
+
+int main()
+{
+       C<A> c;
+}
diff --git a/gcc/testsuite/g++.dg/template/qualttp3.C b/gcc/testsuite/g++.dg/template/qualttp3.C
new file mode 100644 (file)
index 0000000..929fa62
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright (C) 2001 Free Software Foundation
+// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+// { dg-do compile }
+
+struct A
+{
+       template <class T, class U> class B {};
+};
+
+template <template <class> class TT> struct X
+{
+       TT<int> y;
+};
+
+template <class T> struct C
+{
+       X<T::template B> x; // { dg-error "type" "" }
+};
+
+int main()
+{
+       C<A> c; // { dg-error "instantiated" }
+}
diff --git a/gcc/testsuite/g++.dg/template/qualttp4.C b/gcc/testsuite/g++.dg/template/qualttp4.C
new file mode 100644 (file)
index 0000000..04335f1
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright (C) 2001 Free Software Foundation
+// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+// { dg-do compile }
+
+struct A
+{
+       template <class T> struct B {};
+};
+
+template <template <class, class> class TT> // { dg-error "provided" }
+struct X
+{
+       TT<int> y; // { dg-error "number|type" }
+};
+
+template <class T> struct C
+{
+       X<T::template B> x; // { dg-error "type" }
+};
+
+int main()
+{
+       C<A> c; // { dg-error "instantiated" }
+}
diff --git a/gcc/testsuite/g++.dg/template/qualttp5.C b/gcc/testsuite/g++.dg/template/qualttp5.C
new file mode 100644 (file)
index 0000000..7ac7a31
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright (C) 2001 Free Software Foundation
+// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+// { dg-do compile }
+
+template <class U> struct A
+{
+       template <class T> class B {}; // { dg-error "candidates" }
+};
+
+template <template <class> class TT> void f()
+{
+       TT<int> y;
+       y = 0; // { dg-error "no match" }
+}
+
+template <class T> struct C
+{
+       void g() { f<A<T>::template B>(); } // { dg-error "instantiated" }
+};
+
+int main()
+{
+       C<int> c;
+       c.g(); // { dg-error "instantiated" }
+}
diff --git a/gcc/testsuite/g++.dg/template/qualttp6.C b/gcc/testsuite/g++.dg/template/qualttp6.C
new file mode 100644 (file)
index 0000000..0468958
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright (C) 2001 Free Software Foundation
+// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+// { dg-do compile }
+
+template <template <class> class TT> class C {
+};
+
+template <class T> struct D {
+       C<T::template B> c; // { dg-error "no class template" }
+};
+
+struct E {
+};
+
+D<E> d; // { dg-error "instantiated" }
diff --git a/gcc/testsuite/g++.dg/template/qualttp7.C b/gcc/testsuite/g++.dg/template/qualttp7.C
new file mode 100644 (file)
index 0000000..f6573ac
--- /dev/null
@@ -0,0 +1,12 @@
+// Copyright (C) 2001 Free Software Foundation
+// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+// { dg-do compile }
+
+template <template <class> class TT> class C {
+};
+
+template <class T> struct D {
+       C<T::template B> c; // { dg-error "no class template" }
+};
+
+D<int> d; // { dg-error "instantiated" }
diff --git a/gcc/testsuite/g++.dg/template/qualttp8.C b/gcc/testsuite/g++.dg/template/qualttp8.C
new file mode 100644 (file)
index 0000000..da67a09
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright (C) 2001 Free Software Foundation
+// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+// { dg-do compile }
+
+template <template <class> class TT> class C {
+};
+
+template <class T> struct D {
+       C<T::template B> c; // { dg-error "context" }
+};
+
+struct E {
+       private:
+       template <class T> class B {}; // { dg-error "private" }
+};
+
+D<E> d; // { dg-error "instantiated" }
diff --git a/gcc/testsuite/g++.dg/template/qualttp9.C b/gcc/testsuite/g++.dg/template/qualttp9.C
new file mode 100644 (file)
index 0000000..8d90dab
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright (C) 2001 Free Software Foundation
+// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+// { dg-do compile }
+
+template <template <class> class TT> class C {
+};
+
+template <class T> struct D : T {
+       C<T::template B> c;
+};
+
+struct E {
+       protected:
+       template <class T> class B {};
+};
+
+D<E> d;