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" }
}