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