re PR c++/37971 (Rejects default argument that is a template via access failure)
authorMark Mitchell <mark@codesourcery.com>
Wed, 10 Dec 2008 01:23:28 +0000 (01:23 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Wed, 10 Dec 2008 01:23:28 +0000 (01:23 +0000)
PR c++/37971
* class.c (resolve_address_of_overloaded_function): Check
accessibility of member functions unless FLAGS indicates
otherwise.
* call.c (standard_conversion): Adjust flags passed to
instantiate_type.
(convert_default_arg): Do not perform access checks.
* cp-tree.h (tsubst_flags_t): Add tf_no_access_control.

PR c++/37971
* g++.dg/overload/defarg2.C: New test.
* g++.dg/overload/defarg3.C: Likewise.

From-SVN: r142628

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/overload/defarg2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/overload/defarg3.C [new file with mode: 0644]

index 98cb9d7..9c27cd0 100644 (file)
@@ -1,3 +1,14 @@
+2008-12-09  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/37971
+       * class.c (resolve_address_of_overloaded_function): Check
+       accessibility of member functions unless FLAGS indicates
+       otherwise.
+       * call.c (standard_conversion): Adjust flags passed to
+       instantiate_type.
+       (convert_default_arg): Do not perform access checks.
+       * cp-tree.h (tsubst_flags_t): Add tf_no_access_control.
+
 2008-12-08  Steve Ellcey  <sje@cup.hp.com>
 
        * decl2.c (mark_used): Remove assemble_external call.
index 273599e..952e151 100644 (file)
@@ -706,7 +706,10 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p,
   if ((TYPE_PTRFN_P (to) || TYPE_PTRMEMFUNC_P (to))
       && expr && type_unknown_p (expr))
     {
-      expr = instantiate_type (to, expr, tf_conv);
+      tsubst_flags_t tflags = tf_conv;
+      if (!(flags & LOOKUP_PROTECT))
+       tflags |= tf_no_access_control;
+      expr = instantiate_type (to, expr, tflags);
       if (expr == error_mark_node)
        return NULL;
       from = TREE_TYPE (expr);
@@ -1360,9 +1363,8 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags)
 
 /* Returns the implicit conversion sequence (see [over.ics]) from type
    FROM to type TO.  The optional expression EXPR may affect the
-   conversion.  FLAGS are the usual overloading flags.  Only
-   LOOKUP_NO_CONVERSION is significant.  If C_CAST_P is true, this
-   conversion is coming from a C-style cast.  */
+   conversion.  FLAGS are the usual overloading flags.  If C_CAST_P is
+   true, this conversion is coming from a C-style cast.  */
 
 static conversion *
 implicit_conversion (tree to, tree from, tree expr, bool c_cast_p,
@@ -4954,8 +4956,17 @@ convert_default_arg (tree type, tree arg, tree fn, int parmnum)
   if (fn && DECL_TEMPLATE_INFO (fn))
     arg = tsubst_default_argument (fn, type, arg);
 
-  arg = break_out_target_exprs (arg);
+  /* Due to:
+
+       [dcl.fct.default]
 
+       The names in the expression are bound, and the semantic
+       constraints are checked, at the point where the default
+       expressions appears.
+
+     we must not perform access checks here.  */
+  push_deferring_access_checks (dk_no_check);
+  arg = break_out_target_exprs (arg);
   if (TREE_CODE (arg) == CONSTRUCTOR)
     {
       arg = digest_init (type, arg);
@@ -4978,6 +4989,7 @@ convert_default_arg (tree type, tree arg, tree fn, int parmnum)
                                         tf_warning_or_error);
       arg = convert_for_arg_passing (type, arg);
     }
+  pop_deferring_access_checks();
 
   VEC_pop (tree, default_arg_context);
 
index 97ab9e3..805e513 100644 (file)
@@ -5923,9 +5923,13 @@ pop_lang_context (void)
    control of FLAGS.  Permit pointers to member function if FLAGS
    permits.  If TEMPLATE_ONLY, the name of the overloaded function was
    a template-id, and EXPLICIT_TARGS are the explicitly provided
-   template arguments.  If OVERLOAD is for one or more member
-   functions, then ACCESS_PATH is the base path used to reference
-   those member functions.  */
+   template arguments.  
+
+   If OVERLOAD is for one or more member functions, then ACCESS_PATH
+   is the base path used to reference those member functions.  If
+   TF_NO_ACCESS_CONTROL is not set in FLAGS, and the address is
+   resolved to a member function, access checks will be performed and
+   errors issued if appropriate.  */
 
 static tree
 resolve_address_of_overloaded_function (tree target_type,
@@ -6190,14 +6194,16 @@ resolve_address_of_overloaded_function (tree target_type,
        return error_mark_node;
       
       mark_used (fn);
-      /* We could not check access when this expression was originally
-        created since we did not know at that time to which function
-        the expression referred.  */
-      if (DECL_FUNCTION_MEMBER_P (fn))
-       {
-         gcc_assert (access_path);
-         perform_or_defer_access_check (access_path, fn, fn);
-       }
+    }
+
+  /* We could not check access to member functions when this
+     expression was originally created since we did not know at that
+     time to which function the expression referred.  */
+  if (!(flags & tf_no_access_control) 
+      && DECL_FUNCTION_MEMBER_P (fn))
+    {
+      gcc_assert (access_path);
+      perform_or_defer_access_check (access_path, fn, fn);
     }
 
   if (TYPE_PTRFN_P (target_type) || TYPE_PTRMEMFUNC_P (target_type))
index 7f33ff1..bf22eb4 100644 (file)
@@ -3560,20 +3560,22 @@ typedef enum linkage_kind {
 
 /* Bitmask flags to control type substitution.  */
 typedef enum tsubst_flags_t {
-  tf_none = 0,                 /* nothing special */
-  tf_error = 1 << 0,           /* give error messages  */
-  tf_warning = 1 << 1,         /* give warnings too  */
-  tf_ignore_bad_quals = 1 << 2,        /* ignore bad cvr qualifiers */
-  tf_keep_type_decl = 1 << 3,  /* retain typedef type decls
-                                  (make_typename_type use) */
-  tf_ptrmem_ok = 1 << 4,       /* pointers to member ok (internal
-                                  instantiate_type use) */
-  tf_user = 1 << 5,            /* found template must be a user template
-                                  (lookup_template_class use) */
-  tf_conv = 1 << 6,            /* We are determining what kind of
-                                  conversion might be permissible,
-                                  not actually performing the
-                                  conversion.  */
+  tf_none = 0,                  /* nothing special */
+  tf_error = 1 << 0,            /* give error messages  */
+  tf_warning = 1 << 1,          /* give warnings too  */
+  tf_ignore_bad_quals = 1 << 2,         /* ignore bad cvr qualifiers */
+  tf_keep_type_decl = 1 << 3,   /* retain typedef type decls
+                                   (make_typename_type use) */
+  tf_ptrmem_ok = 1 << 4,        /* pointers to member ok (internal
+                                   instantiate_type use) */
+  tf_user = 1 << 5,             /* found template must be a user template
+                                   (lookup_template_class use) */
+  tf_conv = 1 << 6,             /* We are determining what kind of
+                                   conversion might be permissible,
+                                   not actually performing the
+                                   conversion.  */
+  tf_no_access_control = 1 << 7, /* Do not perform access checks, even
+                                   when issuing other errors.   */
   /* Convenient substitution flags combinations.  */
   tf_warning_or_error = tf_warning | tf_error
 } tsubst_flags_t;
index 6f8449a..3a14097 100644 (file)
@@ -1,3 +1,9 @@
+2008-12-09  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/37971
+       * g++.dg/overload/defarg2.C: New test.
+       * g++.dg/overload/defarg3.C: Likewise.
+
 2008-12-09  Jakub Jelinek  <jakub@redhat.com>
 
        PR middle-end/38454
diff --git a/gcc/testsuite/g++.dg/overload/defarg2.C b/gcc/testsuite/g++.dg/overload/defarg2.C
new file mode 100644 (file)
index 0000000..6b1a423
--- /dev/null
@@ -0,0 +1,17 @@
+// PR c++/37391
+// { dg-do compile }
+
+class C {
+private:
+  static int f(int);
+  static int f(char);
+
+public:  
+  static void g(int (*)(int) = f);
+};
+
+void h() {
+  /* Although C::f is inaccessible here, it is accessible in the
+     context of C::g, so there is no error.  */
+  C::g();
+}
diff --git a/gcc/testsuite/g++.dg/overload/defarg3.C b/gcc/testsuite/g++.dg/overload/defarg3.C
new file mode 100644 (file)
index 0000000..83ee111
--- /dev/null
@@ -0,0 +1,15 @@
+// PR c++/37391
+// { dg-do compile }
+
+class C {
+private:
+  static int f(int); // { dg-error "private" }
+  static int f(char);
+};
+
+class D {
+public:
+  /* C::f is inaccessible, so this is an error, even if this function
+     is never called.  */
+  static void g(int (*)(int) = C::f); // { dg-error "context" }
+};