Hi,
On 08/01/2012 04:32 PM, Jason Merrill wrote:
I think the problem is that we're deferring access control due to
tentative parsing on line 11, and not on line 13. I guess we need a
push_deferring_access_checks (dk_no_deferred);
pop_deferring_access_checks ();
around the substitution of default template args in
type_unification_real.
Great, thanks. Thus, I have been testing the attached and it definitely
works for the testcases I discussed so far. Testsuite seems also Ok
(lightly tested so far).
However, something weird is going on for this variant, using decltype
(wanted to consistently extend sfinae37.C):
class C {
typedef int type;
};
template<class T>
auto g(int) -> decltype(typename T::type(), char());
template<class>
auto g(...) -> char (&)[2];
static_assert(sizeof(g<C>(0)) == 2, "Ouch"); // line 11
typedef int testg[sizeof(g<C>(0)) == 2 ? 1 : -1]; // line 13
what happens is that line 13 is mishandled:
sfinae37_red.C:13:48: error: size of array testg is negative
However, *if I comment out line 11*, things work for line 13! If I swap
line 11 and line 13 then the declaration of testg is accepted and the
static_assert triggers. In any case, only the first evaluation of the
sizeof is correct, the next are incorrect. The issue seems so weird that
it should be easy to fix... ;)
Final important observation: in fact, this variant with decltype is
handled in the same way with or without the push_deferring_access_checks
/ pop_deferring_access_checks calls.
Paolo.
////////////////////////
Index: pt.c
===================================================================
--- pt.c (revision 190031)
+++ pt.c (working copy)
@@ -15122,9 +15122,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;