And here's a fix for the access7 failure, to be applied on top of your patch.

I notice that your patch changes the behavior of C++98/03 mode as well, which seems wrong to me; I think this is a big enough change that we should limit it to C++11 mode.

Jason

commit f60b940ab6bcbad60632ba085fa0a5cff2e963e3
Author: Jason Merrill <ja...@redhat.com>
Date:   Thu Jul 12 17:16:35 2012 +0200

    access7

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 8ce0f2a..12c688a 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -78,6 +78,7 @@ c-common.h, not after.
       CONVERT_EXPR_VBASE_PATH (in CONVERT_EXPR)
       OVL_ARG_DEPENDENT (in OVERLOAD)
       PACK_EXPANSION_LOCAL_P (in *_PACK_EXPANSION)
+      TINFO_RECHECK_ACCESS_P (in TEMPLATE_INFO)
    1: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE)
       TI_PENDING_TEMPLATE_FLAG.
       TEMPLATE_PARMS_FOR_INLINE.
@@ -725,6 +726,14 @@ typedef struct qualified_typedef_usage_s qualified_typedef_usage_t;
 DEF_VEC_O (qualified_typedef_usage_t);
 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) \
+  (TREE_LANG_FLAG_0 (TEMPLATE_INFO_CHECK (NODE)))
+#define FNDECL_RECHECK_ACCESS_P(NODE) \
+  (TINFO_RECHECK_ACCESS_P (DECL_TEMPLATE_INFO (NODE)))
+
 struct GTY(()) tree_template_info {
   struct tree_common common;
   VEC(qualified_typedef_usage_t,gc) *typedefs_needing_access_checking;
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 6a1780b..7eca5c7 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -9875,10 +9875,13 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
 	    hash = hash_tmpl_and_args (gen_tmpl, argvec);
 	    spec = retrieve_specialization (gen_tmpl, argvec, hash);
 
+	    r = spec;
 	    if (spec)
 	      {
-		r = spec;
-		break;
+		if (FNDECL_RECHECK_ACCESS_P (spec) && (complain & tf_error))
+		  /* Reinstantiate to get access errors.  */;
+		else
+		  break;
 	      }
 
 	    /* We can see more levels of arguments than parameters if
@@ -9954,6 +9957,13 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
 	if (type == error_mark_node)
 	  RETURN (error_mark_node);
 
+	if (r)
+	  {
+	    /* We're done reinstantiating for access errors.  */
+	    gcc_assert (FNDECL_RECHECK_ACCESS_P (r));
+	    break;
+	  }
+
 	/* We do NOT check for matching decls pushed separately at this
 	   point, as they may not represent instantiations of this
 	   template, and in any case are considered separate under the
@@ -14347,7 +14357,13 @@ instantiate_template_1 (tree tmpl, tree orig_args, tsubst_flags_t complain)
 	      || fndecl == NULL_TREE);
 
   if (spec != NULL_TREE)
-    return spec;
+    {
+      if (FNDECL_RECHECK_ACCESS_P (spec)
+	  && (complain & tf_error))
+	/* Do the instantiation again, we're out of SFINAE context.  */;
+      else
+	return spec;
+    }
 
   if (check_instantiated_args (gen_tmpl, INNERMOST_TEMPLATE_ARGS (targ_ptr),
 			       complain))
@@ -14398,7 +14414,17 @@ instantiate_template_1 (tree tmpl, tree orig_args, tsubst_flags_t complain)
   if (DECL_CHAIN (gen_tmpl) && DECL_CLONED_FUNCTION_P (DECL_CHAIN (gen_tmpl)))
     clone_function_decl (fndecl, /*update_method_vec_p=*/0);
 
-  return tmp ? error_mark_node : fndecl;
+  if (tmp)
+    {
+      if (!(complain & tf_error))
+	{
+	  /* Remember to reinstantiate when we're out of SFINAE so the user
+	     can see the errors.  */
+	  FNDECL_RECHECK_ACCESS_P (fndecl) = true;
+	}
+      return error_mark_node;
+    }
+  return fndecl;
 }
 
 /* Wrapper for instantiate_template_1.  */
diff --git a/gcc/testsuite/g++.dg/template/access7.C b/gcc/testsuite/g++.dg/template/access7.C
index bd38e4e..7d18127 100644
--- a/gcc/testsuite/g++.dg/template/access7.C
+++ b/gcc/testsuite/g++.dg/template/access7.C
@@ -14,5 +14,5 @@ typename A::T* f (A) {			// { dg-error "this context" }
 }
 
 void g () {
-  f (S<int> ());			// { dg-message "required" }
+  f (S<int> ());			// { dg-message "required|no match" }
 }

Reply via email to