Patchwork [RFC,/,RFH] Re-opened C++/51213 (access control under SFINAE)

login
register
mail settings
Submitter Paolo Carlini
Date Aug. 2, 2012, 4:21 p.m.
Message ID <501AA926.60607@oracle.com>
Download mbox | patch
Permalink /patch/174782/
State New
Headers show

Comments

Paolo Carlini - Aug. 2, 2012, 4:21 p.m.
Hi,

On 08/02/2012 05:33 PM, Jason Merrill wrote:
> On 08/01/2012 02:57 PM, Paolo Carlini wrote:
>> So, it is possible that when spec != NULL_TREE and we are once more in a
>> SFINAE context, we have to actually call perform_deferred_access_checks
>> (complain) and either return error_mark_node or the spec depending on
>> the return value?
>
> I don't think we need to redo the access check in SFINAE context; we 
> know that there's an error, so we can just return error_mark_node in 
> that case.  I guess we should change the name of 
> FNDECL_RECHECK_ACCESS_P to something like FNDECL_HAS_ACCESS_ERRORS to 
> make it clearer.
Ah, very well, everything makes sense now. Thus I'm finishing testing 
the below (already past the C++ testsuite), Ok if it passes?

Thanks,
Paolo.

///////////////////////
/cp
2012-08-02  Jason Merrill  <jason@redhat.com>
	    Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/51213 (again)
	* pt.c (type_unification_real): Call push_deferring_access_checks /
	pop_deferring_access_checks around the substitution of default
	template args.
	(instantiate_template_1): When the specialization returned by
	retrieve_specialization has FNDECL_HAS_ACCESS_ERRORS set and we
	are in a SFINAE context, simply return error_mark_node.
	* cp-tree.h (FNDECL_RECHECK_ACCESS_P): Rename FNDECL_HAS_ACCESS_ERRORS.

/testsuite
2012-08-02  Jason Merrill  <jason@redhat.com>
	    Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/51213 (again)
	* g++.dg/cpp0x/sfinae37.C: Extend.
Jason Merrill - Aug. 2, 2012, 4:53 p.m.
On 08/02/2012 12:21 PM, Paolo Carlini wrote:
> +	  if (complain & tf_error)
> +	    recheck_decl_substitution (spec, gen_tmpl, targ_ptr);
> +	  else
> +	    return error_mark_node;

I think we want to be consistent with the end of the function about 
whether we return error_mark_node or the decl after giving access errors 
in non-SFINAE context; I don't have a strong opinion either way, but 
this returns the decl, and the end of the function returns error_mark_node.

Jason

Patch

Index: testsuite/g++.dg/cpp0x/sfinae37.C
===================================================================
--- testsuite/g++.dg/cpp0x/sfinae37.C	(revision 190071)
+++ testsuite/g++.dg/cpp0x/sfinae37.C	(working copy)
@@ -5,6 +5,12 @@  class C {
   typedef int type;
 };
 
+template<int>
+struct I;
+
+template<>
+struct I<2> { };
+
 template<class T, class = typename T::type>
 auto f(int) -> char;
 
@@ -13,6 +19,10 @@  auto f(...) -> char (&)[2];
 
 static_assert(sizeof(f<C>(0)) == 2, "Ouch");
 
+typedef int testf[sizeof(f<C>(0)) == 2 ? 1 : -1];
+
+I<sizeof(f<C>(0))> vf;
+
 template<class T>
 auto g(int) -> decltype(typename T::type(), char());
 
@@ -20,3 +30,7 @@  template<class>
 auto g(...) -> char (&)[2];
 
 static_assert(sizeof(g<C>(0)) == 2, "Ouch");
+
+typedef int testg[sizeof(g<C>(0)) == 2 ? 1 : -1];
+
+I<sizeof(g<C>(0))> vg;
Index: cp/pt.c
===================================================================
--- cp/pt.c	(revision 190071)
+++ cp/pt.c	(working copy)
@@ -14363,8 +14363,13 @@  instantiate_template_1 (tree tmpl, tree orig_args,
 
   if (spec != NULL_TREE)
     {
-      if (FNDECL_RECHECK_ACCESS_P (spec) && (complain & tf_error))
-	recheck_decl_substitution (spec, gen_tmpl, targ_ptr);
+      if (FNDECL_HAS_ACCESS_ERRORS (spec))
+	{
+	  if (complain & tf_error)
+	    recheck_decl_substitution (spec, gen_tmpl, targ_ptr);
+	  else
+	    return error_mark_node;
+	}
       return spec;
     }
 
@@ -14426,7 +14431,7 @@  instantiate_template_1 (tree tmpl, tree orig_args,
 	{
 	  /* Remember to reinstantiate when we're out of SFINAE so the user
 	     can see the errors.  */
-	  FNDECL_RECHECK_ACCESS_P (fndecl) = true;
+	  FNDECL_HAS_ACCESS_ERRORS (fndecl) = true;
 	}
       return error_mark_node;
     }
@@ -15122,9 +15127,11 @@  type_unification_real (tree tparms,
 	      location_t save_loc = input_location;
 	      if (DECL_P (parm))
 		input_location = DECL_SOURCE_LOCATION (parm);
+	      push_deferring_access_checks (dk_no_deferred);
 	      arg = tsubst_template_arg (arg, targs, complain, NULL_TREE);
 	      arg = convert_template_argument (parm, arg, targs, complain,
 					       i, NULL_TREE);
+	      pop_deferring_access_checks ();
 	      input_location = save_loc;
 	      if (arg == error_mark_node)
 		return 1;
Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h	(revision 190071)
+++ cp/cp-tree.h	(working copy)
@@ -729,10 +729,10 @@  DEF_VEC_ALLOC_O (qualified_typedef_usage_t,gc);
 /* Non-zero if this template specialization has access violations that
    should be rechecked when the function is instantiated outside argument
    deduction.  */
-#define TINFO_RECHECK_ACCESS_P(NODE) \
+#define TINFO_HAS_ACCESS_ERRORS(NODE) \
   (TREE_LANG_FLAG_0 (TEMPLATE_INFO_CHECK (NODE)))
-#define FNDECL_RECHECK_ACCESS_P(NODE) \
-  (TINFO_RECHECK_ACCESS_P (DECL_TEMPLATE_INFO (NODE)))
+#define FNDECL_HAS_ACCESS_ERRORS(NODE) \
+  (TINFO_HAS_ACCESS_ERRORS (DECL_TEMPLATE_INFO (NODE)))
 
 struct GTY(()) tree_template_info {
   struct tree_common common;