Skip to content

Commit

Permalink
c++: simplify member template substitution
Browse files Browse the repository at this point in the history
I noticed that for member class templates of a class template we were
unnecessarily substituting both the template and its type.  Avoiding that
duplication speeds compilation of this silly testcase from ~12s to ~9s on my
laptop.  It's unlikely to make a difference on any real code, but the
simplification is also nice.

We still need to clear CLASSTYPE_USE_TEMPLATE on the partial instantiation
of the template class, but it makes more sense to do that in
tsubst_template_decl anyway.

  #define NC(X)					\
    template <class U> struct X##1;		\
    template <class U> struct X##2;		\
    template <class U> struct X##3;		\
    template <class U> struct X##4;		\
    template <class U> struct X##5;		\
    template <class U> struct X##6;
  #define NC2(X) NC(X##a) NC(X##b) NC(X##c) NC(X##d) NC(X##e) NC(X##f)
  #define NC3(X) NC2(X##A) NC2(X##B) NC2(X##C) NC2(X##D) NC2(X##E)
  template <int I> struct A
  {
    NC3(am)
  };
  template <class...Ts> void sink(Ts...);
  template <int...Is> void g()
  {
    sink(A<Is>()...);
  }
  template <int I> void f()
  {
    g<__integer_pack(I)...>();
  }
  int main()
  {
    f<1000>();
  }

gcc/cp/ChangeLog:

	* pt.cc (instantiate_class_template): Skip the RECORD_TYPE
	of a class template.
	(tsubst_template_decl): Clear CLASSTYPE_USE_TEMPLATE.
  • Loading branch information
jicama committed May 2, 2023
1 parent 3302078 commit c912fe7
Showing 1 changed file with 10 additions and 28 deletions.
38 changes: 10 additions & 28 deletions gcc/cp/pt.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12285,41 +12285,20 @@ instantiate_class_template (tree type)
Ignore it; it will be regenerated when needed. */
continue;

bool class_template_p = (TREE_CODE (t) != ENUMERAL_TYPE
&& TYPE_LANG_SPECIFIC (t)
&& CLASSTYPE_IS_TEMPLATE (t));

/* If the member is a class template, then -- even after
substitution -- there may be dependent types in the
template argument list for the class. We increment
PROCESSING_TEMPLATE_DECL so that dependent_type_p, as
that function will assume that no types are dependent
when outside of a template. */
if (class_template_p)
++processing_template_decl;
/* If the member is a class template, we've
already substituted its type. */
if (CLASS_TYPE_P (t)
&& CLASSTYPE_IS_TEMPLATE (t))
continue;

tree newtag = tsubst (t, args, tf_error, NULL_TREE);
if (class_template_p)
--processing_template_decl;
if (newtag == error_mark_node)
continue;

if (TREE_CODE (newtag) != ENUMERAL_TYPE)
{
tree name = TYPE_IDENTIFIER (t);

if (class_template_p)
/* Unfortunately, lookup_template_class sets
CLASSTYPE_IMPLICIT_INSTANTIATION for a partial
instantiation (i.e., for the type of a member
template class nested within a template class.)
This behavior is required for
maybe_process_partial_specialization to work
correctly, but is not accurate in this case;
the TAG is not an instantiation of anything.
(The corresponding TEMPLATE_DECL is an
instantiation, but the TYPE is not.) */
CLASSTYPE_USE_TEMPLATE (newtag) = 0;

/* Now, install the tag. We don't use pushtag
because that does too much work -- creating an
implicit typedef, which we've already done. */
Expand Down Expand Up @@ -14750,7 +14729,10 @@ tsubst_template_decl (tree t, tree args, tsubst_flags_t complain,
/* For a partial specialization, we need to keep pointing to
the primary template. */
if (!DECL_TEMPLATE_SPECIALIZATION (t))
CLASSTYPE_TI_TEMPLATE (inner) = r;
{
CLASSTYPE_TI_TEMPLATE (inner) = r;
CLASSTYPE_USE_TEMPLATE (inner) = 0;
}

DECL_TI_ARGS (r) = CLASSTYPE_TI_ARGS (inner);
inner = TYPE_MAIN_DECL (inner);
Expand Down

0 comments on commit c912fe7

Please sign in to comment.