PR c++/57550
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 9 Jul 2013 03:19:36 +0000 (03:19 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 9 Jul 2013 03:19:36 +0000 (03:19 +0000)
* pt.c (fn_type_unification): Only defer during substitution.
(type_unification_real): Defer during defarg substitution,
add checks parm to pass back deferred checks.
(unify, do_auto_deduction): Adjust.
* semantics.c (reopen_deferring_access_checks): New.
* cp-tree.h: Declare it.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@200808 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/testsuite/g++.dg/template/access27.C [new file with mode: 0644]

index 333249a..33f6562 100644 (file)
@@ -1,3 +1,13 @@
+2013-07-08  Jason Merrill  <jason@redhat.com>
+
+       PR c++/57550
+       * pt.c (fn_type_unification): Only defer during substitution.
+       (type_unification_real): Defer during defarg substitution,
+       add checks parm to pass back deferred checks.
+       (unify, do_auto_deduction): Adjust.
+       * semantics.c (reopen_deferring_access_checks): New.
+       * cp-tree.h: Declare it.
+
 2013-07-06  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/28262
index 1b0b243..1971bc5 100644 (file)
@@ -5637,6 +5637,7 @@ extern void resume_deferring_access_checks        (void);
 extern void stop_deferring_access_checks       (void);
 extern void pop_deferring_access_checks                (void);
 extern vec<deferred_access_check, va_gc> *get_deferred_access_checks (void);
+extern void reopen_deferring_access_checks (vec<deferred_access_check, va_gc> *);
 extern void pop_to_parent_deferring_access_checks (void);
 extern bool perform_access_checks (vec<deferred_access_check, va_gc> *,
                                   tsubst_flags_t);
index 3847a1d..26d5a1c 100644 (file)
@@ -138,6 +138,7 @@ static int maybe_adjust_types_for_deduction (unification_kind_t, tree*, tree*,
                                             tree);
 static int type_unification_real (tree, tree, tree, const tree *,
                                  unsigned int, int, unification_kind_t, int,
+                                 vec<deferred_access_check, va_gc> **,
                                  bool);
 static void note_template_header (int);
 static tree convert_nontype_argument_function (tree, tree);
@@ -15052,7 +15053,6 @@ fn_type_unification (tree fn,
     return error_mark_node;
   tinst = build_tree_list (fn, NULL_TREE);
   ++deduction_depth;
-  push_deferring_access_checks (dk_deferred);
 
   gcc_assert (TREE_CODE (fn) == TEMPLATE_DECL);
 
@@ -15144,8 +15144,13 @@ fn_type_unification (tree fn,
        }
       processing_template_decl += incomplete;
       input_location = DECL_SOURCE_LOCATION (fn);
+      /* Ignore any access checks; we'll see them again in
+        instantiate_template and they might have the wrong
+        access path at this point.  */
+      push_deferring_access_checks (dk_deferred);
       fntype = tsubst (TREE_TYPE (fn), explicit_targs,
                       complain | tf_partial, NULL_TREE);
+      pop_deferring_access_checks ();
       input_location = loc;
       processing_template_decl -= incomplete;
       pop_tinst_level ();
@@ -15153,12 +15158,6 @@ fn_type_unification (tree fn,
       if (fntype == error_mark_node)
        goto fail;
 
-      /* Throw away these access checks; we'll see them again in
-        instantiate_template and they might have the wrong
-        access path at this point.  */
-      pop_deferring_access_checks ();
-      push_deferring_access_checks (dk_deferred);
-
       /* Place the explicitly specified arguments in TARGS.  */
       for (i = NUM_TMPL_ARGS (explicit_targs); i--;)
        TREE_VEC_ELT (targs, i) = TREE_VEC_ELT (explicit_targs, i);
@@ -15194,9 +15193,15 @@ fn_type_unification (tree fn,
       excessive_deduction_depth = true;
       goto fail;
     }
+
+  /* type_unification_real will pass back any access checks from default
+     template argument substitution.  */
+  vec<deferred_access_check, va_gc> *checks;
+  checks = NULL;
+
   ok = !type_unification_real (DECL_INNERMOST_TEMPLATE_PARMS (fn),
                               targs, parms, args, nargs, /*subr=*/0,
-                              strict, flags, explain_p);
+                              strict, flags, &checks, explain_p);
   if (!explain_p)
     pop_tinst_level ();
   if (!ok)
@@ -15245,16 +15250,23 @@ fn_type_unification (tree fn,
       excessive_deduction_depth = true;
       goto fail;
     }
+
+  /* Also collect access checks from the instantiation.  */
+  reopen_deferring_access_checks (checks);
+
   decl = instantiate_template (fn, targs, complain);
+
+  checks = get_deferred_access_checks ();
+  pop_deferring_access_checks ();
+
   pop_tinst_level ();
 
   if (decl == error_mark_node)
     goto fail;
 
-  /* Now perform any access checks encountered during deduction, such as
-     for default template arguments.  */
+  /* Now perform any access checks encountered during substitution.  */
   push_access_scope (decl);
-  ok = perform_deferred_access_checks (complain);
+  ok = perform_access_checks (checks, complain);
   pop_access_scope (decl);
   if (!ok)
     goto fail;
@@ -15283,7 +15295,6 @@ fn_type_unification (tree fn,
   r = decl;
 
  fail:
-  pop_deferring_access_checks ();
   --deduction_depth;
   if (excessive_deduction_depth)
     {
@@ -15684,7 +15695,10 @@ unify_one_argument (tree tparms, tree targs, tree parm, tree arg,
 
    If SUBR is 1, we're being called recursively (to unify the
    arguments of a function or method parameter of a function
-   template). */
+   template).
+
+   CHECKS is a pointer to a vector of access checks encountered while
+   substituting default template arguments.  */
 
 static int
 type_unification_real (tree tparms,
@@ -15695,6 +15709,7 @@ type_unification_real (tree tparms,
                       int subr,
                       unification_kind_t strict,
                       int flags,
+                      vec<deferred_access_check, va_gc> **checks,
                       bool explain_p)
 {
   tree parm, arg;
@@ -15834,6 +15849,7 @@ type_unification_real (tree tparms,
            {
              tree parm = TREE_VALUE (TREE_VEC_ELT (tparms, i));
              tree arg = TREE_PURPOSE (TREE_VEC_ELT (tparms, i));
+             reopen_deferring_access_checks (*checks);
              location_t save_loc = input_location;
              if (DECL_P (parm))
                input_location = DECL_SOURCE_LOCATION (parm);
@@ -15841,6 +15857,8 @@ type_unification_real (tree tparms,
              arg = convert_template_argument (parm, arg, targs, complain,
                                               i, NULL_TREE);
              input_location = save_loc;
+             *checks = get_deferred_access_checks ();
+             pop_deferring_access_checks ();
              if (arg == error_mark_node)
                return 1;
              else
@@ -17307,7 +17325,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
 
        return type_unification_real (tparms, targs, TYPE_ARG_TYPES (parm),
                                      args, nargs, 1, DEDUCE_EXACT,
-                                     LOOKUP_NORMAL, explain_p);
+                                     LOOKUP_NORMAL, NULL, explain_p);
       }
 
     case OFFSET_TYPE:
@@ -20914,7 +20932,7 @@ do_auto_deduction (tree type, tree init, tree auto_node)
        = build_tree_list (NULL_TREE, TYPE_NAME (auto_node));
       val = type_unification_real (tparms, targs, parms, &init, 1, 0,
                                   DEDUCE_CALL, LOOKUP_NORMAL,
-                                  /*explain_p=*/false);
+                                  NULL, /*explain_p=*/false);
       if (val > 0)
        {
          if (processing_template_decl)
index f821754..0a6c775 100644 (file)
@@ -155,6 +155,17 @@ push_deferring_access_checks (deferring_kind deferring)
     }
 }
 
+/* Save the current deferred access states and start deferred access
+   checking, continuing the set of deferred checks in CHECKS.  */
+
+void
+reopen_deferring_access_checks (vec<deferred_access_check, va_gc> * checks)
+{
+  push_deferring_access_checks (dk_deferred);
+  if (!deferred_access_no_check)
+    deferred_access_stack->last().deferred_access_checks = checks;
+}
+
 /* Resume deferring access checks again after we stopped doing
    this previously.  */
 
diff --git a/gcc/testsuite/g++.dg/template/access27.C b/gcc/testsuite/g++.dg/template/access27.C
new file mode 100644 (file)
index 0000000..967e10f
--- /dev/null
@@ -0,0 +1,17 @@
+// PR c++/57550
+
+template <bool (double)> bool Wrapper(double);
+template <class T> void MakeHandler(bool (T));
+
+class Handler
+{
+public:
+  template <typename T> static void SetPrimitiveHandlers()
+  {
+    MakeHandler(Wrapper<Append<T> >);
+  }
+private :
+  template <typename T> static bool Append(T);
+};
+
+template void Handler::SetPrimitiveHandlers<double>();