diff options
author | Jason Merrill <jason@redhat.com> | 2023-05-02 14:54:46 -0400 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2023-05-02 18:53:06 -0400 |
commit | c912fe765a1378f1b09d1095ab4e093d5205122a (patch) | |
tree | 3a318562d74fe869684247b630226e3a16d5c51c | |
parent | 33020780a9699f1146eeed61783cec89fde337a0 (diff) | |
download | gcc-c912fe765a1378f1b09d1095ab4e093d5205122a.zip gcc-c912fe765a1378f1b09d1095ab4e093d5205122a.tar.gz gcc-c912fe765a1378f1b09d1095ab4e093d5205122a.tar.bz2 |
c++: simplify member template substitution
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.
-rw-r--r-- | gcc/cp/pt.cc | 38 |
1 files changed, 10 insertions, 28 deletions
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 3f1cf13..471fc20 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -12285,21 +12285,13 @@ 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; @@ -12307,19 +12299,6 @@ instantiate_class_template (tree 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. */ @@ -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); |