C++ PATCH: PR 37971

Mark Mitchell mitchell@codesourcery.com
Wed Dec 10 01:35:00 GMT 2008


This patch fixes PR c++/37971.  We were checking accessibility of
default arguments at the point of use, rather than at the point the
default argument itself was defined.  It was trivial to turn off the
checks at the point of use, but adding them at the point of definition
was a little bit more tricky.  

The change here is conservative in that it's possible that we now fail
to issue errors in some situation where we should.  That could occur
if something is calling standard_conversion without setting
LOOKUP_PROTECT, but should be.   I think that's unlikely, but I'll
keep my eye out for any new bug reports.

Tested on x86_64-linux-gnu, applied to mainline.

I'll look into backporting to older branches next.

--
Mark Mitchell
CodeSourcery
mark@codesourcery.com
(650) 331-3385 x713

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-09  Mark Mitchell  <mark@codesourcery.com>

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

Index: gcc/testsuite/g++.dg/overload/defarg2.C
===================================================================
--- gcc/testsuite/g++.dg/overload/defarg2.C	(revision 0)
+++ gcc/testsuite/g++.dg/overload/defarg2.C	(revision 0)
@@ -0,0 +1,17 @@
+// PR c++/37971
+// { 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();
+}
Index: gcc/testsuite/g++.dg/overload/defarg3.C
===================================================================
--- gcc/testsuite/g++.dg/overload/defarg3.C	(revision 0)
+++ gcc/testsuite/g++.dg/overload/defarg3.C	(revision 0)
@@ -0,0 +1,15 @@
+// PR c++/37971
+// { 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" }
+};
Index: gcc/cp/class.c
===================================================================
--- gcc/cp/class.c	(revision 142608)
+++ gcc/cp/class.c	(working copy)
@@ -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 (
 	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: gcc/cp/call.c
===================================================================
--- gcc/cp/call.c	(revision 142608)
+++ gcc/cp/call.c	(working copy)
@@ -706,7 +706,10 @@ standard_conversion (tree to, tree from,
   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,
 
 /* 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
   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
                                         tf_warning_or_error);
       arg = convert_for_arg_passing (type, arg);
     }
+  pop_deferring_access_checks();
 
   VEC_pop (tree, default_arg_context);
 
Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h	(revision 142608)
+++ gcc/cp/cp-tree.h	(working copy)
@@ -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;



More information about the Gcc-patches mailing list