]> gcc.gnu.org Git - gcc.git/commitdiff
re PR c++/27339 (out-of-class definition of value template parameter with private...
authorMark Mitchell <mark@codesourcery.com>
Tue, 16 May 2006 05:39:49 +0000 (05:39 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Tue, 16 May 2006 05:39:49 +0000 (05:39 +0000)
PR c++/27339
* cp-tree.h (perform_access_checks): New function.
* semantics.c (perform_access_checks): New function.
(perform_deferred_access_checks): Use it.
* parser.c (cp_parser_simple_declaration): Adjust call to
cp_parser_init_declarator.
(cp_parser_type_parameter): Do not defer checks in default
arguments.
(cp_parser_explicit_specialization): Adjust call to
cp_parser_single_declaration.
(cp_parser_init_declarator): Perform template-parameter access
checks.
(cp_parser_parameter_declaration): Do not defer checks for
template parameter default arguments.
(cp_parser_template_declaration_after_export): Gather access
checks for template parameters, and pass them to
cp_parser_single_declaration.
(cp_parser_template_parameter_access_checks): New function.
(cp_parser_single_declaration): Add checks parameter.
PR c++/27339
* g++.dg/parser/access8.C: Adjust error marker.
* g++.dg/template/access17.C: New test.
* g++.dg/template/access18.C: Likewise.

From-SVN: r113819

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/parser.c
gcc/cp/semantics.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/parse/access8.C
gcc/testsuite/g++.dg/template/access17.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/access18.C [new file with mode: 0644]

index 3bdf214a310b45c7779f960ddae46160f06e1b8f..42af5fd3d02f1aca0d288788c184c60c4ceff5cf 100644 (file)
@@ -1,5 +1,25 @@
 2006-05-15  Mark Mitchell  <mark@codesourcery.com>
 
+       PR c++/27339
+       * cp-tree.h (perform_access_checks): New function.
+       * semantics.c (perform_access_checks): New function.
+       (perform_deferred_access_checks): Use it.
+       * parser.c (cp_parser_simple_declaration): Adjust call to
+       cp_parser_init_declarator.
+       (cp_parser_type_parameter): Do not defer checks in default
+       arguments.
+       (cp_parser_explicit_specialization): Adjust call to
+       cp_parser_single_declaration.
+       (cp_parser_init_declarator): Perform template-parameter access
+       checks. 
+       (cp_parser_parameter_declaration): Do not defer checks for
+       template parameter default arguments.
+       (cp_parser_template_declaration_after_export): Gather access
+       checks for template parameters, and pass them to
+       cp_parser_single_declaration.
+       (cp_parser_template_parameter_access_checks): New function.
+       (cp_parser_single_declaration): Add checks parameter.
+
        PR c++/27505
        * call.c (convert_like_real): Convert bitfields to their declared
        types when forming an rvalue.
index 8e56a9fc528efc5f22c7881ce401097908e126ab..38376288ef9af3cac1c5bec23cf0e33eb56b8794 100644 (file)
@@ -4153,6 +4153,7 @@ extern void stop_deferring_access_checks  (void);
 extern void pop_deferring_access_checks                (void);
 extern tree get_deferred_access_checks         (void);
 extern void pop_to_parent_deferring_access_checks (void);
+extern void perform_access_checks               (tree);
 extern void perform_deferred_access_checks     (void);
 extern void perform_or_defer_access_check      (tree, tree);
 extern int stmts_are_full_exprs_p              (void);
index bee7e9af61ec5e79275dcaacc5bcfafa22eaeb42..c89c357e200cc98368e28e39fc89c028b4a68bf7 100644 (file)
@@ -1527,7 +1527,7 @@ static void cp_parser_linkage_specification
 /* Declarators [gram.dcl.decl] */
 
 static tree cp_parser_init_declarator
-  (cp_parser *, cp_decl_specifier_seq *, bool, bool, int, bool *);
+  (cp_parser *, cp_decl_specifier_seq *, tree, bool, bool, int, bool *);
 static cp_declarator *cp_parser_declarator
   (cp_parser *, cp_parser_declarator_kind, int *, bool *, bool);
 static cp_declarator *cp_parser_direct_declarator
@@ -1726,8 +1726,10 @@ static tree cp_parser_function_definition_after_declarator
   (cp_parser *, bool);
 static void cp_parser_template_declaration_after_export
   (cp_parser *, bool);
+static void cp_parser_perform_template_parameter_access_checks
+  (tree);
 static tree cp_parser_single_declaration
-  (cp_parser *, bool, bool *);
+  (cp_parser *, tree, bool, bool *);
 static tree cp_parser_functional_cast
   (cp_parser *, tree);
 static tree cp_parser_save_member_function_body
@@ -7271,6 +7273,7 @@ cp_parser_simple_declaration (cp_parser* parser,
 
       /* Parse the init-declarator.  */
       decl = cp_parser_init_declarator (parser, &decl_specifiers,
+                                       /*checks=*/NULL_TREE,
                                        function_definition_allowed_p,
                                        /*member_p=*/false,
                                        declares_class_or_enum,
@@ -8574,7 +8577,9 @@ cp_parser_type_parameter (cp_parser* parser)
            /* Consume the `=' token.  */
            cp_lexer_consume_token (parser->lexer);
            /* Parse the default-argument.  */
+           push_deferring_access_checks (dk_no_deferred);
            default_argument = cp_parser_type_id (parser);
+           pop_deferring_access_checks ();
          }
        else
          default_argument = NULL_TREE;
@@ -8628,6 +8633,7 @@ cp_parser_type_parameter (cp_parser* parser)
            /* Consume the `='.  */
            cp_lexer_consume_token (parser->lexer);
            /* Parse the id-expression.  */
+           push_deferring_access_checks (dk_no_deferred);
            default_argument
              = cp_parser_id_expression (parser,
                                         /*template_keyword_p=*/false,
@@ -8652,6 +8658,7 @@ cp_parser_type_parameter (cp_parser* parser)
            /* See if the default argument is valid.  */
            default_argument
              = check_template_template_default_arg (default_argument);
+           pop_deferring_access_checks ();
          }
        else
          default_argument = NULL_TREE;
@@ -9500,6 +9507,7 @@ cp_parser_explicit_specialization (cp_parser* parser)
   else
     /* Parse the dependent declaration.  */
     cp_parser_single_declaration (parser,
+                                 /*checks=*/NULL_TREE,
                                  /*member_p=*/false,
                                  /*friend_p=*/NULL);
   /* We're done with the specialization.  */
@@ -10870,10 +10878,14 @@ cp_parser_asm_definition (cp_parser* parser)
    function-definition:
      __extension__ function-definition
 
-   The DECL_SPECIFIERS and PREFIX_ATTRIBUTES apply to this declarator.
-   Returns a representation of the entity declared.  If MEMBER_P is TRUE,
-   then this declarator appears in a class scope.  The new DECL created
-   by this declarator is returned.
+   The DECL_SPECIFIERS apply to this declarator.  Returns a
+   representation of the entity declared.  If MEMBER_P is TRUE, then
+   this declarator appears in a class scope.  The new DECL created by
+   this declarator is returned.
+
+   The CHECKS are access checks that should be performed once we know
+   what entity is being declared (and, therefore, what classes have
+   befriended it).
 
    If FUNCTION_DEFINITION_ALLOWED_P then we handle the declarator and
    for a function-definition here as well.  If the declarator is a
@@ -10887,6 +10899,7 @@ cp_parser_asm_definition (cp_parser* parser)
 static tree
 cp_parser_init_declarator (cp_parser* parser,
                           cp_decl_specifier_seq *decl_specifiers,
+                          tree checks,
                           bool function_definition_allowed_p,
                           bool member_p,
                           int declares_class_or_enum,
@@ -11096,6 +11109,9 @@ cp_parser_init_declarator (cp_parser* parser,
          current_function_decl = decl;
        }
 
+      /* Perform access checks for template parameters.  */
+      cp_parser_perform_template_parameter_access_checks (checks);
+
       /* Perform the access control checks for the declarator and the
         the decl-specifiers.  */
       perform_deferred_access_checks ();
@@ -12438,8 +12454,12 @@ cp_parser_parameter_declaration (cp_parser *parser,
             to avoid collecting live data on the stack.  */
          ++function_depth;
          /* Parse the assignment-expression.  */
+         if (template_parm_p)
+           push_deferring_access_checks (dk_no_deferred);
          default_argument
            = cp_parser_assignment_expression (parser, /*cast_p=*/false);
+         if (template_parm_p)
+           pop_deferring_access_checks ();
          /* Restore saved state.  */
          --function_depth;
          parser->greater_than_is_operator_p
@@ -15418,6 +15438,7 @@ static void
 cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
 {
   tree decl = NULL_TREE;
+  tree checks;
   tree parameter_list;
   bool friend_p = false;
   bool need_lang_pop;
@@ -15442,6 +15463,12 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
     }
   else
     need_lang_pop = false;
+
+  /* We cannot perform access checks on the template parameter
+     declarations until we know what is being declared, just as we
+     cannot check the decl-specifier list.  */
+  push_deferring_access_checks (dk_deferred);
+
   /* If the next token is `>', then we have an invalid
      specialization.  Rather than complain about an invalid template
      parameter, issue an error message here.  */
@@ -15455,6 +15482,12 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
     /* Parse the template parameters.  */
     parameter_list = cp_parser_template_parameter_list (parser);
 
+  /* Get the deferred access checks from the parameter list.  These
+     will be checked once we know what is being declared, as for a
+     member template the checks must be performed in the scope of the
+     class containing the member.  */
+  checks = get_deferred_access_checks ();
+
   /* Look for the `>'.  */
   cp_parser_skip_until_found (parser, CPP_GREATER, "`>'");
   /* We just processed one more parameter list.  */
@@ -15469,11 +15502,10 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
       /* There are no access checks when parsing a template, as we do not
         know if a specialization will be a friend.  */
       push_deferring_access_checks (dk_no_check);
-
       decl = cp_parser_single_declaration (parser,
+                                          checks,
                                           member_p,
                                           &friend_p);
-
       pop_deferring_access_checks ();
 
       /* If this is a member template declaration, let the front
@@ -15492,6 +15524,8 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
   /* We are done with the current parameter list.  */
   --parser->num_template_parameter_lists;
 
+  pop_deferring_access_checks ();
+
   /* Finish up.  */
   finish_template_decl (parameter_list);
 
@@ -15513,6 +15547,18 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
                   TREE_VALUE (parser->unparsed_functions_queues));
 }
 
+/* Perform the deferred access checks from a template-parameter-list.
+   CHECKS is a TREE_LIST of access checks, as returned by
+   get_deferred_access_checks.  */
+
+static void
+cp_parser_perform_template_parameter_access_checks (tree checks)
+{
+  ++processing_template_parmlist;
+  perform_access_checks (checks);
+  --processing_template_parmlist;
+}
+
 /* Parse a `decl-specifier-seq [opt] init-declarator [opt] ;' or
    `function-definition' sequence.  MEMBER_P is true, this declaration
    appears in a class scope.
@@ -15522,6 +15568,7 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
 
 static tree
 cp_parser_single_declaration (cp_parser* parser,
+                             tree checks,
                              bool member_p,
                              bool* friend_p)
 {
@@ -15583,6 +15630,9 @@ cp_parser_single_declaration (cp_parser* parser,
            decl = TYPE_NAME (decl);
          else
            decl = error_mark_node;
+
+         /* Perform access checks for template parameters.  */
+         cp_parser_perform_template_parameter_access_checks (checks);
        }
     }
   /* If it's not a template class, try for a template function.  If
@@ -15595,6 +15645,7 @@ cp_parser_single_declaration (cp_parser* parser,
          || decl_specifiers.type != error_mark_node))
     decl = cp_parser_init_declarator (parser,
                                      &decl_specifiers,
+                                     checks,
                                      /*function_definition_allowed_p=*/true,
                                      member_p,
                                      declares_class_or_enum,
index 23ab2d8a132da86a7aa1aa1f91dee2aef2bed90f..1e315e2d1233de6d43575ab269dc4e9a8bf2018d 100644 (file)
@@ -261,6 +261,21 @@ pop_to_parent_deferring_access_checks (void)
     }
 }
 
+/* Perform the access checks in CHECKS.  The TREE_PURPOSE of each node
+   is the BINFO indicating the qualifying scope used to access the
+   DECL node stored in the TREE_VALUE of the node.  */
+
+void
+perform_access_checks (tree checks)
+{
+  while (checks)
+    {
+      enforce_access (TREE_PURPOSE (checks),
+                     TREE_VALUE (checks));
+      checks = TREE_CHAIN (checks);
+    }
+}
+
 /* Perform the deferred access checks.
 
    After performing the checks, we still have to keep the list
@@ -280,14 +295,7 @@ pop_to_parent_deferring_access_checks (void)
 void
 perform_deferred_access_checks (void)
 {
-  tree deferred_check;
-
-  for (deferred_check = get_deferred_access_checks ();
-       deferred_check;
-       deferred_check = TREE_CHAIN (deferred_check))
-    /* Check access.  */
-    enforce_access (TREE_PURPOSE (deferred_check),
-                   TREE_VALUE (deferred_check));
+  perform_access_checks (get_deferred_access_checks ());
 }
 
 /* Defer checking the accessibility of DECL, when looked up in
index 9f65c93f1af487fbae259cd695c3aabe0dc93140..ce8b924392dfe6908ee14bd345a0f8061b6e50af 100644 (file)
@@ -1,3 +1,10 @@
+2006-05-15  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/27339
+       * g++.dg/parser/access8.C: Adjust error marker.
+       * g++.dg/template/access17.C: New test.
+       * g++.dg/template/access18.C: Likewise.
+
 2006-05-15  Roger Sayle  <roger@eyesopen.com>
 
        PR target/26600
index badea1c98b73d32badd26352adeb74ce5c26537b..45f4be70288aaaad7a8a472e2adf62083c030f3b 100644 (file)
@@ -5,8 +5,8 @@ class foo
   typedef int memfun;  // { dg-error "private" }
 };
 
-template<foo::memfun> // { dg-error "context" } 
-struct fm_obj { };
+template<foo::memfun>
+struct fm_obj { }; // { dg-error "context" } 
 
 template <typename T = foo::memfun> // { dg-error "context" }
 struct S {};
diff --git a/gcc/testsuite/g++.dg/template/access17.C b/gcc/testsuite/g++.dg/template/access17.C
new file mode 100644 (file)
index 0000000..0c45100
--- /dev/null
@@ -0,0 +1,23 @@
+// PR c++/27339
+
+class A 
+{
+private: 
+  enum private_enum {a};
+
+  template<A::private_enum v>  // OK 
+  struct B
+  {
+    void bm();
+  }; 
+public: 
+  void am() 
+  { 
+    B<a> instance; //OK
+    instance.bm();
+  }
+};
+
+template<A::private_enum v>  // FAIL
+void
+A::B<v>::bm(){}
diff --git a/gcc/testsuite/g++.dg/template/access18.C b/gcc/testsuite/g++.dg/template/access18.C
new file mode 100644 (file)
index 0000000..3338bc9
--- /dev/null
@@ -0,0 +1,19 @@
+// DR 401
+
+class X {
+  typedef int a; // { dg-error "private" }
+  static const int b = 5; // { dg-error "private" }
+  template <typename>
+  struct c; // { dg-error "private" }
+};
+
+template <typename = X::a> // { dg-error "context" }
+struct A;
+
+template <int = X::b> // { dg-error "context" }
+struct B;
+
+template <template <typename> class T = X::c> // { dg-error "context" }
+struct C;
+  
+  
This page took 0.106194 seconds and 5 git commands to generate.