c++: reusing typedefs in template for [PR124229]
This is a crash on code like:
template for (constexpr auto val : define_static_array (enumerators_of (^^E)))
{
constexpr auto a = annotations_of(val)[0];
using U = [:type_of(a):];
constexpr auto m1 = extract<U>(a);
}
because the template arg to extract wasn't substituted to "info".
Once I dug deeper I realized this problem isn't tied to Reflection:
we also crash here:
template for (constexpr auto val : { 42 })
{
using U = decltype(val);
foo<U>();
}
because we emit code for foo() that still has a DECLTYPE_TYPE in it.
The problem is in tsubst and reusing typedefs. Normally, for code like
template<typename T> void foo () {
using U = T;
U u;
}
we do the DECL_FUNCTION_SCOPE_P -> retrieve_local_specialization call.
This call only happens in function templates (that are not explicit
specializations), but the "template for" above are both in non-template
functions. So we end up returning the original tree:
/* The typedef is from a non-template context. */
return t;
It seems clear that this is the wrong thing to do, and that the
DECL_FUNCTION_SCOPE_P code should happen in this scenario as well.
[temp.decls.general] tells me that "For the purpose of name lookup and
instantiation, the compound-statement of an expansion-statement is
considered a template definition." so I'm guessing that we want to
check for an expansion-statement as well. As decl_dependent_p says,
in_expansion_stmt is false when instantiating, so I'm looking for
sk_template_for.
PR c++/124229
gcc/cp/ChangeLog:
* pt.cc (in_expansion_stmt_p): New.
(tsubst): When reusing typedefs, do retrieve_local_specialization also
when in_expansion_stmt_p is true.
gcc/testsuite/ChangeLog:
* g++.dg/cpp26/expansion-stmt32.C: New test.
* g++.dg/reflect/expansion-stmt2.C: New test.
Reviewed-by: Jason Merrill <jason@redhat.com>
3 files changed