Patchwork [C++,RFC,/] PR 51213 ("access control under SFINAE")

login
register
mail settings
Submitter Jason Merrill
Date July 12, 2012, 10:55 p.m.
Message ID <4FFF55EF.3090508@redhat.com>
Download mbox | patch
Permalink /patch/170760/
State New
Headers show

Comments

Jason Merrill - July 12, 2012, 10:55 p.m.
These patches fix the typedef11.C and friend13/15.C failures.  Each 
fixes a latent bug in the compiler.

1) We shouldn't do access control checking for typedefs used in the body 
of a function when the declaration is instantiated; we should wait until 
the body is instantiated.

2) We shouldn't try to do any access checking when deducing template 
arguments, that can wait until we call instantiate_template later in 
add_template_candidate_real, when we actually have a FUNCTION_DECL to 
compare to any friend declarations.

Tested x86_64-pc-linux-gnu, applying to trunk.
Paolo Carlini - July 14, 2012, 9:54 a.m.
Hi,

and, first, thanks a lot for all the nice work and help on these issues!

On 07/13/2012 12:55 AM, Jason Merrill wrote:
> diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
> index fec88eb..95c6464 100644
> --- a/gcc/cp/pt.c
> +++ b/gcc/cp/pt.c
> @@ -8334,7 +8334,7 @@ apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags,
>   
>   /* Perform (or defer) access check for typedefs that were referenced
>      from within the template TMPL code.
> -   This is a subroutine of instantiate_template and instantiate_class_template.
> +   This is a subroutine of instantiate_decl and instantiate_class_template.
>      TMPL is the template to consider and TARGS is the list of arguments of
>      that template.  */
>   
> @@ -14380,12 +14380,6 @@ instantiate_template_1 (tree tmpl, tree orig_args, tsubst_flags_t complain)
>     /* Now we know the specialization, compute access previously
>        deferred.  */
>     push_access_scope (fndecl);
> -
> -  /* Some typedefs referenced from within the template code need to be access
> -     checked at template instantiation time, i.e now. These types were
> -     added to the template at parsing time. Let's get those and perfom
> -     the acces checks then.  */
> -  perform_typedefs_access_check (DECL_TEMPLATE_RESULT (tmpl), targ_ptr);
>     perform_deferred_access_checks ();
>     pop_access_scope (fndecl);
>     pop_deferring_access_checks ();
> @@ -18395,6 +18389,13 @@ instantiate_decl (tree d, int defer_ok,
>         /* Set up context.  */
>         start_preparsed_function (d, NULL_TREE, SF_PRE_PARSED);
>   
> +      /* Some typedefs referenced from within the template code need to be
> +	 access checked at template instantiation time, i.e now. These
> +	 types were added to the template at parsing time. Let's get those
> +	 and perform the access checks then.  */
> +      perform_typedefs_access_check (DECL_TEMPLATE_RESULT (gen_tmpl),
> +				     gen_args);
> +
I'm working on integrating again my work.

The above change of yours appear to imply that, at variance with what I 
had in my first draft, perform_typedefs_access_check shouldn't really 
gain a tsubst_flags_t argument, because now it's called by 
instantiate_decl and instantiate_class_template_1 (from which I was 
passing a true / tf_error). Makes sense?

Thanks!
Paolo.
Jason Merrill - July 16, 2012, 5:39 p.m.
On 07/14/2012 05:54 AM, Paolo Carlini wrote:
> The above change of yours appear to imply that, at variance with what I
> had in my first draft, perform_typedefs_access_check shouldn't really
> gain a tsubst_flags_t argument, because now it's called by
> instantiate_decl and instantiate_class_template_1 (from which I was
> passing a true / tf_error). Makes sense?

That makes sense to me.

Jason

Patch

commit 56a4aeb321d97093da7ac7b0cc4a4783adc83494
Author: Jason Merrill <jason@redhat.com>
Date:   Thu Jul 12 12:20:36 2012 +0200

    	* pt.c (deduction_tsubst_fntype): Just suppress access checking.
    	(instantiate_template_1): Set DECL_TI_TEMPLATE before access checking.
    	(push_deduction_access_scope, pop_deduction_access_scope): Remove.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 72b0c4f..fec88eb 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -116,8 +116,6 @@  enum template_base_result {
 
 static void push_access_scope (tree);
 static void pop_access_scope (tree);
-static void push_deduction_access_scope (tree);
-static void pop_deduction_access_scope (tree);
 static bool resolve_overloaded_unification (tree, tree, tree, tree,
 					    unification_kind_t, int,
 					    bool);
@@ -14263,9 +14261,10 @@  deduction_tsubst_fntype (tree fn, tree targs, tsubst_flags_t complain)
 
   input_location = DECL_SOURCE_LOCATION (fn);
   ++deduction_depth;
-  push_deduction_access_scope (fn);
+  /* We will do access checks in instantiate_template.  */
+  push_deferring_access_checks (dk_deferred);
   r = tsubst (fntype, targs, complain, NULL_TREE);
-  pop_deduction_access_scope (fn);
+  pop_deferring_access_checks ();
   --deduction_depth;
 
   if (excessive_deduction_depth)
@@ -14374,6 +14373,10 @@  instantiate_template_1 (tree tmpl, tree orig_args, tsubst_flags_t complain)
   if (fndecl == error_mark_node)
     return error_mark_node;
 
+  /* The DECL_TI_TEMPLATE should always be the immediate parent
+     template, not the most general template.  */
+  DECL_TI_TEMPLATE (fndecl) = tmpl;
+
   /* Now we know the specialization, compute access previously
      deferred.  */
   push_access_scope (fndecl);
@@ -14387,10 +14390,6 @@  instantiate_template_1 (tree tmpl, tree orig_args, tsubst_flags_t complain)
   pop_access_scope (fndecl);
   pop_deferring_access_checks ();
 
-  /* The DECL_TI_TEMPLATE should always be the immediate parent
-     template, not the most general template.  */
-  DECL_TI_TEMPLATE (fndecl) = tmpl;
-
   /* If we've just instantiated the main entry point for a function,
      instantiate all the alternate entry points as well.  We do this
      by cloning the instantiation of the main entry point, not by
@@ -14413,36 +14412,6 @@  instantiate_template (tree tmpl, tree orig_args, tsubst_flags_t complain)
   return ret;
 }
 
-/* We're going to do deduction substitution on the type of TMPL, a function
-   template.  In C++11 mode, push into that access scope.  In C++03 mode,
-   disable access checking.  */
-
-static void
-push_deduction_access_scope (tree tmpl)
-{
-  if (cxx_dialect >= cxx0x)
-    {
-      int ptd = processing_template_decl;
-      push_access_scope (DECL_TEMPLATE_RESULT (tmpl));
-      /* Preserve processing_template_decl across push_to_top_level.  */
-      if (ptd && !processing_template_decl)
-	++processing_template_decl;
-    }
-  else
-    push_deferring_access_checks (dk_no_check);
-}
-
-/* And pop back out.  */
-
-static void
-pop_deduction_access_scope (tree tmpl)
-{
-  if (cxx_dialect >= cxx0x)
-    pop_access_scope (DECL_TEMPLATE_RESULT (tmpl));
-  else
-    pop_deferring_access_checks ();
-}
-
 /* PARM is a template parameter pack for FN.  Returns true iff
    PARM is used in a deducible way in the argument list of FN.  */
 
diff --git a/gcc/testsuite/g++.dg/template/sfinae6_neg.C b/gcc/testsuite/g++.dg/template/sfinae6_neg.C
index 9b7bdfd1..c238222 100644
--- a/gcc/testsuite/g++.dg/template/sfinae6_neg.C
+++ b/gcc/testsuite/g++.dg/template/sfinae6_neg.C
@@ -14,7 +14,7 @@  template<typename T> struct enable_if<false, T> { };
 template<typename F, typename T1, typename T2>
   typename enable_if<sizeof(create_a<F>()(create_a<T1>(), create_a<T2>()), 1),
 		     yes_type>::type
-  check_is_callable2(type<F>, type<T1>, type<T2>); // { dg-error "within this context" "" { target c++11 } }
+  check_is_callable2(type<F>, type<T1>, type<T2>);
 
 no_type check_is_callable2(...);