On 9/14/21 00:31, Barrett Adair wrote:
I reworked the fix today based on feedback from Jason and Jakub (thank you), and the subject line is now outdated. I added another test for a closely related bug that's also fixed here (dependent-expr11.C -- this one would even fail without the second declaration). All the new tests in the patch succeed with the change (only two of them succeed with trunk). On my box, the bootstrap succeeds, the g++ test suite passes (matching today's posted results anyway), and the libstdc++ test suite is looking good but is still running after a long time. I'll leave the full "make check" running overnight.

Some potentially controversial changes here:

1. Adding new bool member to cp_parser. I'd like to avoid this, any tips?
2. Relaxing an assert in tsubst_copy. This change feels correct to me, but maybe I'm missing something. 3. Pushing a function scope in PARM_DECL case in tsubst_copy_and_build to make process_outer_var_ref happy for trailing return types. I don't yet fully appreciate the consequences of these changes, so this needs some eyes.

These all are to support dependent-expr11.C, right? This seems like a separate issue, that should be a separate patch.

And I don't think there's anything special about a trailing return type. I am surprised to discover that I don't see anything prohibiting that use, but I similarly don't see anything prohibiting

template<class T> auto bar(T t, bool_c<t()>) -> bool_c<t()>;

or even

template <class T> using FP = void (*)(T t, int (*)[t()]);

So I guess the "use of parameter outside function body" code in finish_id_expression_1 is obsolete with constexpr; removing that should address #1.

One way to approach #2 might be to

  begin_scope (sk_function_parms, NULL_TREE);

in tsubst_function_type, so that parsing_function_declarator (which I'm about to check in) is true, and change the assert to also check that.

Maybe that will also help with #3. Really, outer_var_p should be false for t, so we shouldn't ever get to process_outer_var_ref.

-----

OK, now for the part of the patch that corresponds to the subject line:

4. Traversing each template arg's tree in any_template_arguments_need_structural_equality_p to identify dependent expressions in trailing return types. This could probably be done better. I check current_function_decl here as an optimization (since it's NULL in the only place that "needs" this), but that seems brittle.

I think that optimization makes sense; within a function we shouldn't need structural comparison, only for comparing two template declarations.

Also, the new find_dependent_parm_decl_r callback implementation may have the unintended consequence of forcing structural comparison on member function trailing return types that depend on class template parameters. I think I really only want to force structural comparison for "arg tree has a dependent parm decl and we're in a trailing return type" -- is there a better way to do this?

I don't think whether the parm is dependent is important: the case we want to catch is if the argument as a whole is dependent, and contains a mention of a parameter.

Also note that I found another related bug which I have not yet solved:

template<int i>
struct foo {
   constexpr operator int() { return i; }
};
void bar() {
   [](auto i) -> foo<i> {
     return {};
   }(foo<1>{});
}

With the attached patch, failure occurs at invocation, while trunk fails to parse the return type. This seems like a step in the right direction, but we should consider whether such an incomplete fix introduces more issues than it solves (e.g. unfriendlier error messages, or perhaps something more sinister).

This would also be related to the separate change under 1-3 above.

Jason

Reply via email to