On Fri, Aug 10, 2018 at 8:59 AM, Marek Polacek <pola...@redhat.com> wrote:
> On Mon, Aug 06, 2018 at 12:02:31AM +1000, Jason Merrill wrote:
>> > OK -- see the patch below.  Now, I'm not crazy about adding another bit
>> > to struct conversion, but reusing any of the other bits didn't seem
>> > safe/possible.  Maybe it'll come in handy when dealing with this problem
>> > for function templates.
>>
>> Looks good.
>>
>> >> >> @@ -6669,9 +6669,12 @@ convert_nontype_argument (tree type, tree expr, 
>> >> >> tsubst_flags_t complain)
>> >> >>           /* C++17: A template-argument for a non-type 
>> >> >> template-parameter shall
>> >> >>              be a converted constant expression (8.20) of the type of 
>> >> >> the
>> >> >>              template-parameter.  */
>> >> >> +         int errs = errorcount;
>> >> >>           expr = build_converted_constant_expr (type, expr, complain);
>> >> >>           if (expr == error_mark_node)
>> >> >> -           return error_mark_node;
>> >> >> +           /* Make sure we return NULL_TREE only if we have really 
>> >> >> issued
>> >> >> +              an error, as described above.  */
>> >> >> +           return errorcount > errs ? NULL_TREE : error_mark_node;
>> >> >
>> >> > Is this still needed?
>> >>
>> >> Earlier you wrote,
>> >>
>> >> > Checking complain doesn't work because that doesn't
>> >> > say if we have really issued an error.  If we have not, and we return
>> >> > NULL_TREE anyway, we hit this assert:
>> >> >  8517       gcc_assert (!(complain & tf_error) || seen_error ());
>> >>
>> >> If (complain & tf_error), we shouldn't see error_mark_node without an
>> >> error having been issued.  Why is build_converted_constant_expr
>> >> returning error_mark_node without giving an error when (complain &
>> >> tf_error)?
>> >
>> > This can happen on invalid code; e.g. tests nontype13.C and crash87.C.
>> > What happens there is that we're trying to convert a METHOD_TYPE to bool,
>> > which doesn't work: in standard_conversion we go into the
>> >     else if (tcode == BOOLEAN_TYPE)
>> > block, which returns NULL, implicit_conversion also then returns NULL, yet
>> > no error has been issued.
>>
>> Yes, that's normal.  The problem is in build_converted_constant_expr:
>>
>>   if (conv)
>>     expr = convert_like (conv, expr, complain);
>>   else
>>     expr = error_mark_node;
>>
>> Here when setting expr to error_mark_node I forgot to give an error if
>> (complain & tf_error).
>
> Done.  A few testcases needed adjusting but nothing surprising.
>
>> >> >> +      /* If we're in a template and we know the constant value, we can
>> >> >> +        warn.  Otherwise wait for instantiation.  */
>> >> >> +      || (processing_template_decl && !TREE_CONSTANT (init)))
>> >> >
>> >> > I don't think we want this condition.  If the value is non-constant
>> >> > but also not dependent, it'll never be constant, so we can go ahead
>> >> > and complain.
>> >
>> > (This to be investigated later.)
>>
>> Why later?
>
> So this was this wrong error:
> https://gcc.gnu.org/ml/gcc-patches/2018-07/msg00159.html
> which was confusing.  But I noticed it's because we instantiate 'size' twice:
> in compute_array_index_type:
>   size = instantiate_non_dependent_expr_sfinae (size, complain);
>   size = build_converted_constant_expr (size_type_node, size, complain);
>   size = maybe_constant_value (size);
> and then in check_narrowing:
>   init = fold_non_dependent_expr (init, complain);
>
> (in this case, size is a call to constexpr user-defined conversion).
>
> But check_narrowing now returns early if instantiation_dependent_expression_p,
> so I thought perhaps we could simply call maybe_constant_value which fixes 
> this
> problem and doesn't regress anything.  Does that seem like a sensible thing
> to do?

Hmm, that'll have problems if we pass an unfolded template expression
to check_narrowing, but probably we don't want to do that anyway.  So
yes, it seems reasonable.

>> > --- gcc/cp/decl.c
>> > +++ gcc/cp/decl.c
>> > @@ -9581,7 +9581,7 @@ compute_array_index_type (tree name, tree size, 
>> > tsubst_flags_t complain)
>> >      {
>> >        tree folded = cp_fully_fold (size);
>> >        if (TREE_CODE (folded) == INTEGER_CST)
>> > -       pedwarn (location_of (size), OPT_Wpedantic,
>> > +       pedwarn (input_location, OPT_Wpedantic,
>>
>> It should work to use location_of (osize) here.
>
> I dropped this hunk altogether.  Because location_of will use
> DECL_SOURCE_LOCATION for DECLs, the error message will point to the 
> declaration
> itself, not the use.  I don't really care either way.

We want the message to point to the use, which location_of (osize)
will provide, since it should still have a location wrapper around a
DECL.

>           expr = build_converted_constant_expr (type, expr, complain);
>           if (expr == error_mark_node)
> -           return error_mark_node;
> +           /* Make sure we return NULL_TREE only if we have really issued
> +              an error, as described above.  */
> +           return (complain & tf_error) ? NULL_TREE : error_mark_node;

Now that you've fixed build_converted_constant_expr, we shouldn't need
this hunk.

Jason

Reply via email to