c++: template partial instantiation mismatch [PR 99528]
This turned out to be an existing problem, which had been hidden by other bugs. Templated members of templated classes can end up instantiating the template itself, and we were not handling the mergeableness of that correctly. PR c++/99528 gcc/cp/ * module.cc (enum merge_kind): Delete MK_type_tmpl_spec, MK_decl_tmpl_spec. (trees_in::decl_value): Adjust add_mergeable_specialization call. (trees_out::get_merge_kind): Adjust detecting a partial template instantiation. (trees_out::key_mergeable): Adjust handling same. (trees_in::key_mergeabvle): Likewise. gcc/testsuite/ * g++.dg/modules/pr99528.h: New. * g++.dg/modules/pr99528_a.H: New. * g++.dg/modules/pr99528_b.H: New. * g++.dg/modules/pr99528_c.C: New.
This commit is contained in:
parent
52db241345
commit
edc61d34eb
@ -2783,11 +2783,7 @@ enum merge_kind
|
||||
MK_tmpl_tmpl_mask = 0x1, /* We want TEMPLATE_DECL. */
|
||||
|
||||
MK_type_spec = MK_template_mask,
|
||||
MK_type_tmpl_spec = MK_type_spec | MK_tmpl_tmpl_mask,
|
||||
|
||||
MK_decl_spec = MK_template_mask | MK_tmpl_decl_mask,
|
||||
MK_decl_tmpl_spec = MK_decl_spec | MK_tmpl_tmpl_mask,
|
||||
|
||||
MK_alias_spec = MK_decl_spec | MK_tmpl_alias_mask,
|
||||
|
||||
MK_hwm = 0x20
|
||||
@ -8062,10 +8058,10 @@ trees_in::decl_value ()
|
||||
{
|
||||
/* Add to specialization tables now that constraints etc are
|
||||
added. */
|
||||
bool is_decl = (mk & MK_template_mask) && (mk & MK_tmpl_decl_mask);
|
||||
bool is_type = mk == MK_partial || !(mk & MK_tmpl_decl_mask);
|
||||
|
||||
spec.spec = is_decl ? inner : type;
|
||||
add_mergeable_specialization (is_decl, &spec, decl, spec_flags);
|
||||
spec.spec = is_type ? type : mk & MK_tmpl_tmpl_mask ? inner : decl;
|
||||
add_mergeable_specialization (!is_type, &spec, decl, spec_flags);
|
||||
}
|
||||
|
||||
if (TREE_CODE (decl) == INTEGER_CST && !TREE_OVERFLOW (decl))
|
||||
@ -10229,7 +10225,6 @@ trees_out::get_merge_kind (tree decl, depset *dep)
|
||||
case depset::EK_SPECIALIZATION:
|
||||
{
|
||||
gcc_checking_assert (dep->is_special ());
|
||||
spec_entry *entry = reinterpret_cast <spec_entry *> (dep->deps[0]);
|
||||
|
||||
if (TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL)
|
||||
/* An block-scope classes of templates are themselves
|
||||
@ -10247,13 +10242,8 @@ trees_out::get_merge_kind (tree decl, depset *dep)
|
||||
|
||||
if (TREE_CODE (decl) == TEMPLATE_DECL)
|
||||
{
|
||||
tree res = DECL_TEMPLATE_RESULT (decl);
|
||||
if (!(mk & MK_tmpl_decl_mask))
|
||||
res = TREE_TYPE (res);
|
||||
|
||||
if (res == entry->spec)
|
||||
/* We check we can get back to the template during
|
||||
streaming. */
|
||||
spec_entry *entry = reinterpret_cast <spec_entry *> (dep->deps[0]);
|
||||
if (TREE_CODE (entry->spec) != TEMPLATE_DECL)
|
||||
mk = merge_kind (mk | MK_tmpl_tmpl_mask);
|
||||
}
|
||||
}
|
||||
@ -10362,15 +10352,14 @@ trees_out::key_mergeable (int tag, merge_kind mk, tree decl, tree inner,
|
||||
gcc_assert (match_mergeable_specialization (false, entry)
|
||||
== TREE_TYPE (existing));
|
||||
else if (mk & MK_tmpl_tmpl_mask)
|
||||
if (tree ti = DECL_TEMPLATE_INFO (existing))
|
||||
existing = TI_TEMPLATE (ti);
|
||||
existing = DECL_TI_TEMPLATE (existing);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(mk & MK_tmpl_tmpl_mask))
|
||||
if (mk & MK_tmpl_tmpl_mask)
|
||||
existing = CLASSTYPE_TI_TEMPLATE (existing);
|
||||
else
|
||||
existing = TYPE_NAME (existing);
|
||||
else if (tree ti = CLASSTYPE_TEMPLATE_INFO (existing))
|
||||
existing = TI_TEMPLATE (ti);
|
||||
}
|
||||
|
||||
/* The walkabout should have found ourselves. */
|
||||
@ -10677,13 +10666,6 @@ trees_in::key_mergeable (int tag, merge_kind mk, tree decl, tree inner,
|
||||
DECL_NAME (inner) = DECL_NAME (decl);
|
||||
DECL_CONTEXT (inner) = DECL_CONTEXT (decl);
|
||||
|
||||
spec.spec = decl;
|
||||
if (mk & MK_tmpl_tmpl_mask)
|
||||
{
|
||||
if (inner == decl)
|
||||
return error_mark_node;
|
||||
spec.spec = inner;
|
||||
}
|
||||
tree constr = NULL_TREE;
|
||||
bool is_decl = mk & MK_tmpl_decl_mask;
|
||||
if (is_decl)
|
||||
@ -10694,13 +10676,10 @@ trees_in::key_mergeable (int tag, merge_kind mk, tree decl, tree inner,
|
||||
if (constr)
|
||||
set_constraints (inner, constr);
|
||||
}
|
||||
spec.spec = (mk & MK_tmpl_tmpl_mask) ? inner : decl;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mk == MK_type_spec && inner != decl)
|
||||
return error_mark_node;
|
||||
spec.spec = type;
|
||||
}
|
||||
spec.spec = type;
|
||||
existing = match_mergeable_specialization (is_decl, &spec);
|
||||
if (constr)
|
||||
/* We'll add these back later, if this is the new decl. */
|
||||
@ -10712,24 +10691,15 @@ trees_in::key_mergeable (int tag, merge_kind mk, tree decl, tree inner,
|
||||
{
|
||||
/* A declaration specialization. */
|
||||
if (mk & MK_tmpl_tmpl_mask)
|
||||
if (tree ti = DECL_TEMPLATE_INFO (existing))
|
||||
{
|
||||
tree tmpl = TI_TEMPLATE (ti);
|
||||
if (DECL_TEMPLATE_RESULT (tmpl) == existing)
|
||||
existing = tmpl;
|
||||
}
|
||||
existing = DECL_TI_TEMPLATE (existing);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* A type specialization. */
|
||||
if (!(mk & MK_tmpl_tmpl_mask))
|
||||
if (mk & MK_tmpl_tmpl_mask)
|
||||
existing = CLASSTYPE_TI_TEMPLATE (existing);
|
||||
else
|
||||
existing = TYPE_NAME (existing);
|
||||
else if (tree ti = CLASSTYPE_TEMPLATE_INFO (existing))
|
||||
{
|
||||
tree tmpl = TI_TEMPLATE (ti);
|
||||
if (DECL_TEMPLATE_RESULT (tmpl) == TYPE_NAME (existing))
|
||||
existing = tmpl;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mk == MK_unique)
|
||||
|
9
gcc/testsuite/g++.dg/modules/pr99528.h
Normal file
9
gcc/testsuite/g++.dg/modules/pr99528.h
Normal file
@ -0,0 +1,9 @@
|
||||
template<typename _Tp>
|
||||
class new_allocator
|
||||
{
|
||||
public:
|
||||
template<typename _Tp1>
|
||||
new_allocator(const new_allocator<_Tp1>&) noexcept { }
|
||||
};
|
||||
|
||||
extern template class new_allocator<char>;
|
4
gcc/testsuite/g++.dg/modules/pr99528_a.H
Normal file
4
gcc/testsuite/g++.dg/modules/pr99528_a.H
Normal file
@ -0,0 +1,4 @@
|
||||
// PR 99528, ICE with template/function mismatch
|
||||
// { dg-additional-options -fmodule-header }
|
||||
// { dg-module-cmi {} }
|
||||
#include "pr99528.h"
|
4
gcc/testsuite/g++.dg/modules/pr99528_b.H
Normal file
4
gcc/testsuite/g++.dg/modules/pr99528_b.H
Normal file
@ -0,0 +1,4 @@
|
||||
// { dg-additional-options -fmodule-header }
|
||||
// { dg-module-cmi {} }
|
||||
#include "pr99528.h"
|
||||
|
3
gcc/testsuite/g++.dg/modules/pr99528_c.C
Normal file
3
gcc/testsuite/g++.dg/modules/pr99528_c.C
Normal file
@ -0,0 +1,3 @@
|
||||
// { dg-additional-options {-fmodules-ts -fno-module-lazy} }
|
||||
import "pr99528_a.H";
|
||||
import "pr99528_b.H";
|
Loading…
Reference in New Issue
Block a user