PR c++/7347, c++/7348
authorKriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
Mon, 22 Jul 2002 14:23:37 +0000 (14:23 +0000)
committerKriang Lerdsuwanakij <lerdsuwa@gcc.gnu.org>
Mon, 22 Jul 2002 14:23:37 +0000 (14:23 +0000)
PR c++/7347, c++/7348
* cp-tree.h (tsubst_flags_t): Add tf_parsing.
* decl.c (make_typename_type): Use it.
(make_unbound_class_template): Likewise.
(lookup_name_real): Don't call type_access_control if scope is
template parameter dependent.
* parse.y (template_arg): Call make_unbound_class_template with
tf_parsing set.
(nest_name_specifier): Call make_typename_type with tf_parsing set.
(typename_sub0): Likewise.
(typename_sub1): Likewise.
(instantiate_decl): Push class scope.
* pt.c (regenerate_decl_from_template): Call pushclass and popclass
for both static variable and member function template.
(instantiate_decl) Call pushclass and popclass when tsubst'ing type
and arguments.
* search.c (type_access_control): Do type access for TEMPLATE_DECL
too.

* g++.dg/template/access4.C: New test.
* g++.dg/template/access5.C: New test.
* g++.old-deja/g++.pt/memtemp85.C: Fix access problem.
* g++.old-deja/g++.pt/memtemp86.C: Likewise.
* g++.old-deja/g++.pt/ttp58.C: Likewise.
* g++.old-deja/g++.pt/memtemp89.C: Remove XFAIL.

From-SVN: r55649

13 files changed:
gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/parse.y
gcc/cp/pt.c
gcc/cp/search.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/access4.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/access5.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.pt/memtemp85.C
gcc/testsuite/g++.old-deja/g++.pt/memtemp86.C
gcc/testsuite/g++.old-deja/g++.pt/memtemp89.C
gcc/testsuite/g++.old-deja/g++.pt/ttp58.C

index 57effa988c2d2fadfbc2340ea3c06fadb431fe68..fc5418070fd243e75375b6a9af59b6b7356c2f81 100644 (file)
@@ -1,3 +1,24 @@
+2002-07-22  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>
+
+       PR c++/7347, c++/7348
+       * cp-tree.h (tsubst_flags_t): Add tf_parsing.
+       * decl.c (make_typename_type): Use it.
+       (make_unbound_class_template): Likewise.
+       (lookup_name_real): Don't call type_access_control if scope is
+       template parameter dependent.
+       * parse.y (template_arg): Call make_unbound_class_template with
+       tf_parsing set.
+       (nest_name_specifier): Call make_typename_type with tf_parsing set.
+       (typename_sub0): Likewise.
+       (typename_sub1): Likewise.
+       (instantiate_decl): Push class scope.
+       * pt.c (regenerate_decl_from_template): Call pushclass and popclass
+       for both static variable and member function template.
+       (instantiate_decl) Call pushclass and popclass when tsubst'ing type
+       and arguments.
+       * search.c (type_access_control): Do type access for TEMPLATE_DECL
+       too.
+
 2002-07-20  Roger Sayle  <roger@eyesopen.com>
 
        * decl2.c (cxx_decode_option): Simplify -fhandle-exceptions
index 15a5aff2cedd3684398143f6d647a15bc04db661..0f4bf9081cf3db86b110887d85ac9512eadc071c 100644 (file)
@@ -3187,8 +3187,10 @@ typedef enum tsubst_flags_t {
   tf_ignore_bad_quals = 1 << 3, /* ignore bad cvr qualifiers */
   tf_keep_type_decl = 1 << 4,  /* retain typedef type decls
                                   (make_typename_type use) */
-  tf_ptrmem_ok = 1 << 5      /* pointers to member ok (internal
+  tf_ptrmem_ok = 1 << 5,     /* pointers to member ok (internal
                                instantiate_type use) */
+  tf_parsing = 1 << 6       /* called from parser
+                               (make_typename_type use) */
 } tsubst_flags_t;
 
 /* The kind of checking we can do looking in a class hierarchy. */
index f280384d98f14c669eba8c5001d253741607326f..e4897953e3e9effe5a0edc74b7758a8be961754d 100644 (file)
@@ -5659,8 +5659,10 @@ make_typename_type (context, name, complain)
              return error_mark_node;
            }
 
-         if (!enforce_access (context, tmpl))
-           return error_mark_node;
+         if (complain & tf_parsing)
+           type_access_control (context, tmpl);
+         else
+           enforce_access (context, tmpl);
 
          return lookup_template_class (tmpl,
                                        TREE_OPERAND (fullname, 1),
@@ -5682,8 +5684,10 @@ make_typename_type (context, name, complain)
          t = lookup_field (context, name, 0, 1);
          if (t)
            {
-             if (!enforce_access (context, t))
-               return error_mark_node;
+             if (complain & tf_parsing)
+               type_access_control (context, t);
+             else
+               enforce_access (context, t);
 
              if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl))
                t = TREE_TYPE (t);
@@ -5712,7 +5716,6 @@ make_typename_type (context, name, complain)
       return error_mark_node;
     }
 
-
   return build_typename_type (context, name, fullname,  NULL_TREE);
 }
 
@@ -5752,8 +5755,10 @@ make_unbound_class_template (context, name, complain)
          return error_mark_node;
        }
       
-      if (!enforce_access (context, tmpl))
-       return error_mark_node;
+      if (complain & tf_parsing)
+       type_access_control (context, tmpl);
+      else
+       enforce_access (context, tmpl);
 
       return tmpl;
     }
@@ -6078,7 +6083,8 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
          else
            {
              val = lookup_member (type, name, 0, prefer_type);
-             type_access_control (type, val);
+             if (!uses_template_parms (type))
+               type_access_control (type, val);
 
              /* Restore the containing TYPENAME_TYPE if we looked
                 through it before.  */
index 386c808aca4b2386f42f2f58668cbc2b69911cde..94314e5564b85649ffc1e9f3f816722c0690f677 100644 (file)
@@ -1159,7 +1159,7 @@ template_arg:
                      $$ = error_mark_node;
                    }
                  else
-                   $$ = make_unbound_class_template ($1, $3, 1);
+                   $$ = make_unbound_class_template ($1, $3, tf_error | tf_parsing);
                }
        ;
 
@@ -3071,14 +3071,14 @@ nested_name_specifier:
                { $$ = $2; }
        | nested_name_specifier TEMPLATE explicit_template_type SCOPE
                 { got_scope = $$
-                   = make_typename_type ($1, $3, tf_error); }
+                   = make_typename_type ($1, $3, tf_error | tf_parsing); }
        /* Error handling per Core 125.  */
        | nested_name_specifier IDENTIFIER SCOPE
                 { got_scope = $$
-                   = make_typename_type ($1, $2, tf_error); }
+                   = make_typename_type ($1, $2, tf_error | tf_parsing); }
        | nested_name_specifier PTYPENAME SCOPE
                 { got_scope = $$
-                   = make_typename_type ($1, $2, tf_error); }
+                   = make_typename_type ($1, $2, tf_error | tf_parsing); }
        ;
 
 /* Why the @#$%^& do type_name and notype_identifier need to be expanded
@@ -3120,7 +3120,7 @@ typename_sub0:
          typename_sub1 identifier %prec EMPTY
                {
                  if (TYPE_P ($1))
-                   $$ = make_typename_type ($1, $2, tf_error);
+                   $$ = make_typename_type ($1, $2, tf_error | tf_parsing);
                  else if (TREE_CODE ($2) == IDENTIFIER_NODE)
                    error ("`%T' is not a class or namespace", $2);
                  else
@@ -3133,9 +3133,9 @@ typename_sub0:
        | typename_sub1 template_type %prec EMPTY
                { $$ = TREE_TYPE ($2); }
        | typename_sub1 explicit_template_type %prec EMPTY
-                { $$ = make_typename_type ($1, $2, tf_error); }
+                { $$ = make_typename_type ($1, $2, tf_error | tf_parsing); }
        | typename_sub1 TEMPLATE explicit_template_type %prec EMPTY
-                { $$ = make_typename_type ($1, $3, tf_error); }
+                { $$ = make_typename_type ($1, $3, tf_error | tf_parsing); }
        ;
 
 typename_sub1:
@@ -3149,7 +3149,7 @@ typename_sub1:
        | typename_sub1 typename_sub2
                {
                  if (TYPE_P ($1))
-                   $$ = make_typename_type ($1, $2, tf_error);
+                   $$ = make_typename_type ($1, $2, tf_error | tf_parsing);
                  else if (TREE_CODE ($2) == IDENTIFIER_NODE)
                    error ("`%T' is not a class or namespace", $2);
                  else
@@ -3161,10 +3161,10 @@ typename_sub1:
                }
        | typename_sub1 explicit_template_type SCOPE
                 { got_scope = $$
-                   = make_typename_type ($1, $2, tf_error); }
+                   = make_typename_type ($1, $2, tf_error | tf_parsing); }
        | typename_sub1 TEMPLATE explicit_template_type SCOPE
                 { got_scope = $$
-                   = make_typename_type ($1, $3, tf_error); }
+                   = make_typename_type ($1, $3, tf_error | tf_parsing); }
        ;
 
 /* This needs to return a TYPE_DECL for simple names so that we don't
index 8caf0a04a4f861dfba222930a685a2125a4bdd90..52554a9dcbcf21eaf779a5a9a0281c4fd3e14011 100644 (file)
@@ -9844,10 +9844,10 @@ regenerate_decl_from_template (decl, tmpl)
      register_specialization for it.  */
   my_friendly_assert (unregistered, 0);
 
-  if (TREE_CODE (decl) == VAR_DECL)
+  if (DECL_CLASS_SCOPE_P (decl))
     /* Make sure that we can see identifiers, and compute access
        correctly, for the class members used in the declaration of
-       this static variable.  */
+       this static variable or function.  */
     pushclass (DECL_CONTEXT (decl), 2);
 
   /* Do the substitution to get the new declaration.  */
@@ -9859,8 +9859,6 @@ regenerate_decl_from_template (decl, tmpl)
       DECL_INITIAL (new_decl) = 
        tsubst_expr (DECL_INITIAL (code_pattern), args, 
                     tf_error, DECL_TI_TEMPLATE (decl));
-      /* Pop the class context we pushed above.  */
-      popclass ();
     }
   else if (TREE_CODE (decl) == FUNCTION_DECL)
     {
@@ -9871,6 +9869,10 @@ regenerate_decl_from_template (decl, tmpl)
       DECL_INITIAL (decl) = NULL_TREE;
     }
 
+  /* Pop the class context we pushed above.  */
+  if (DECL_CLASS_SCOPE_P (decl))
+    popclass ();
+
   /* The immediate parent of the new template is still whatever it was
      before, even though tsubst sets DECL_TI_TEMPLATE up as the most
      general template.  We also reset the DECL_ASSEMBLER_NAME since
@@ -10052,6 +10054,11 @@ instantiate_decl (d, defer_ok)
       tree gen = DECL_TEMPLATE_RESULT (gen_tmpl);
       tree type = TREE_TYPE (gen);
 
+      /* Make sure that we can see identifiers, and compute access
+        correctly.  */
+      if (DECL_CLASS_SCOPE_P (d))
+       pushclass (DECL_CONTEXT (d), 1);
+
       if (TREE_CODE (gen) == FUNCTION_DECL)
        {
          tsubst (DECL_ARGUMENTS (gen), args, tf_error | tf_warning, d);
@@ -10064,6 +10071,9 @@ instantiate_decl (d, defer_ok)
          type = TREE_TYPE (type);
        }
       tsubst (type, args, tf_error | tf_warning, d);
+
+      if (DECL_CLASS_SCOPE_P (d))
+       popclass ();
     }
   
   if (TREE_CODE (d) == VAR_DECL && DECL_INITIALIZED_IN_CLASS_P (d)
index b7ba0bc4daec234144508a0530b61fd8ef23e927..95d5dde8cf095d1255c476d0e037fac2c08c0a5d 100644 (file)
@@ -971,8 +971,8 @@ friend_accessible_p (scope, decl, binfo)
   return 0;
 }
 
-/* Perform access control on TYPE_DECL VAL, which was looked up in TYPE.
-   This is fairly complex, so here's the design:
+/* Perform access control on TYPE_DECL or TEMPLATE_DECL VAL, which was
+   looked up in TYPE.  This is fairly complex, so here's the design:
 
    The lang_extdef nonterminal sets type_lookups to NULL_TREE before we
      start to process a top-level declaration.
@@ -995,7 +995,8 @@ void
 type_access_control (type, val)
      tree type, val;
 {
-  if (val == NULL_TREE || TREE_CODE (val) != TYPE_DECL
+  if (val == NULL_TREE
+      || (TREE_CODE (val) != TEMPLATE_DECL && TREE_CODE (val) != TYPE_DECL)
       || ! DECL_CLASS_SCOPE_P (val))
     return;
 
index 37d9e47c2b20113c58b665bbe6e2840feaaea084..41b879c854ce502c46071c1eee4b510ae5f56190 100644 (file)
@@ -1,3 +1,13 @@
+2002-07-22  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>
+
+       PR c++/7347, c++/7348
+       * g++.dg/template/access4.C: New test.
+       * g++.dg/template/access5.C: New test.
+       * g++.old-deja/g++.pt/memtemp85.C: Fix access problem.
+       * g++.old-deja/g++.pt/memtemp86.C: Likewise.
+       * g++.old-deja/g++.pt/ttp58.C: Likewise.
+       * g++.old-deja/g++.pt/memtemp89.C: Remove XFAIL.
+
 2002-07-22  Jakub Jelinek  <jakub@redhat.com>
 
        * gcc.dg/gnu89-init-2.c: New test.
diff --git a/gcc/testsuite/g++.dg/template/access4.C b/gcc/testsuite/g++.dg/template/access4.C
new file mode 100644 (file)
index 0000000..9451ecc
--- /dev/null
@@ -0,0 +1,18 @@
+// { dg-do compile }
+// Origin: Wolfgang Bangerth <wolfgang.bangerth@iwr.uni-heidelberg.de>
+
+// PR c++/7347
+// Access control for typename during instantiation
+
+template <int dim> class Base {
+  protected:
+    typedef int T;
+};
+
+template <int dim> class D : public Base<dim> {
+  public:
+    typedef typename Base<dim>::T T1;
+    D (T1 t);
+};
+
+D<2> d(1);
diff --git a/gcc/testsuite/g++.dg/template/access5.C b/gcc/testsuite/g++.dg/template/access5.C
new file mode 100644 (file)
index 0000000..a9cb8a5
--- /dev/null
@@ -0,0 +1,21 @@
+// { dg-do compile }
+// Origin: Wolfgang Bangerth <wolfgang.bangerth@iwr.uni-heidelberg.de>
+
+// PR c++/7348
+// Access control for typename in function return type
+
+class Outer {
+    template <int dim> struct Inner {
+        typedef int T;
+        T foo ();
+    };
+  public:
+    Outer();
+};
+
+template <int dim>
+typename Outer::Inner<dim>::T  Outer::Inner<dim>::foo () {
+  return 1;
+};
+
+template Outer::Inner<2>;
index ef8f0480774ff042315c9abd7e3afdeb50f079b1..ab9b9f610a8cf6daa3a948134ed23be919d26471 100644 (file)
@@ -4,7 +4,7 @@
 // by Paul Burchard <burchard@pobox.com>, Level Set Systems, Inc.
 // Copyright (C) 1999 Free Software Foundation
 
-class Q {
+struct Q {
        template<class>
        class X {
        };
index 47a587f76b8f5f98b09e6c5b6506f2c4bc8ffc7c..fe06dae5b4026c2dbad831887f5f092f8fb126e8 100644 (file)
@@ -4,7 +4,7 @@
 // by Paul Burchard <burchard@pobox.com>, Level Set Systems, Inc.
 // Copyright (C) 1999 Free Software Foundation
 
-class Q {
+struct Q {
        template<class>
        class X {
        };
index 6db9b4bdaa73d68c69c130ceae29014b7e999dfe..8564221cfea5d9b28f023a1d354a2d2ea2a8c98d 100644 (file)
@@ -5,11 +5,11 @@
 
 class Q {
        template<class T>
-       class X {
+       class X {               // ERROR - Q::X private
        };
 };
 template<template<class> class XX>
 class Y {
-       XX<int> x_;             // ERROR - Q::X inaccessible XFAIL *-*-*
+       XX<int> x_;
 };
-Y<Q::X> y;                     // ERROR - instantiated from here XFAIL *-*-*
+Y<Q::X> y;                     // ERROR - instantiated from here
index 662058037b72e8cdb362a0d20503bb2deb06fd69..729996f1fea4ed5cb9aadb41c24252c1d41bbade 100644 (file)
@@ -15,7 +15,7 @@ struct Z
   const static int value_ = false;
 };
 
-class Outer
+struct Outer
 {
   template <class T>
   struct A :