This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] PR c++/26693


Dodji Seketeli wrote:
In this code example:
     1  template<typename> struct A
     2  {
     3    typedef int X;
     4    static const int i = 0;
     5  };
     6
     7  template<typename> struct B
     8  {
     9    B(const B&); // { dg-message "candidate" }
    10    typedef typename A<char[A<B>::i]>::X Y;
    11    template<typename T> B(T, Y); // { dg-error "call" }
    12  };
    13
    14  B<int> b(0,0);
[...]
The second set of error g++ should give us is:
:11: error: no matching function for call to 'B<int>::B(int, int)'
:9: note: candidates are: B< <template-parameter-1-1> >::B(const B< <template-parameter-1-1> >&) [with <template-parameter-1-1> = int]


This second set of error is missing if I don't handle the particular case of typedef variants of TYPENAME_TYPE as was talking about in 2/.

I believe this is one is generated because during instantiation of the last parameter (namely the Y typedef) of B<int>::B(int, int), the function tsubst() receives a typedef variant of a TYPENAME_TYPE.

Right, because Y is a typedef of a typename type.


Before this patch, the condition:
 if (TYPE_P (t)
      && TYPE_NAME (t)
      && TYPE_NAME (t) != TYPE_MAIN_DECL (t))
    {

was not true, because t was not a typedef variant. So t was handled by the TYPENAME_TYPE case that comes later in that function and an error was raised.

But after the patch, this condition becomes true and later this if:

if (DECL_CLASS_SCOPE_P (decl)
&& CLASSTYPE_TEMPLATE_INFO (DECL_CONTEXT (decl))
&& uses_template_parms (DECL_CONTEXT (decl)))
{
tree tmpl = most_general_template (DECL_TI_TEMPLATE (decl));
tree gen_args = tsubst (DECL_TI_ARGS (decl), args, complain, in_decl);
r = retrieve_specialization (tmpl, gen_args, false);
}


becomes true as well, and later r is returned.

Yes, that's how I would expect it to work. The declaration of the template constructor uses B<unnamed template parm>::Y, so tsubsting it should use B<int>::Y.


This code path doesn't raise the error that was raised previously.

But that isn't the code path that produces the error. That error comes from the overload resolution code.


So my understanding is the typedef variant of TYPENAME_TYPE triggered a different code path that lead to some errors not being raised. I might be missing something at this point, but I can't see what :-(.

Here's what's happening: if you use the underlying TYPENAME_TYPE directly, you create a zero-length array, which results in a deduction failure. If you use the typedef instead, you get a fully resolved type because as an extension G++ allows zero-length arrays outside of the argument deduction context.


I think this is the behavior we want; if as an extension we allow B<int> to be instantiated at all, we should also allow the use of the Y typedef in this situation. The zero-length array is not coming from argument deduction in this case, so it isn't a substitution failure.

Pedantically, the testcase is ill-formed because B<int>::Y is ill-formed. If we allow B<int>::Y, we should also allow it to be used.

This is wrong: if DECL_IS_BUILTIN (x) we don't want to create a typedef variant, we just want to set TYPE_NAME (type) to x.

Ah. I did this because clone_underlying_type handles that case of DECL_IS_BUILTIN (x).

Ah, I see.


Jason


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]