From 07589ca2b2c84ec9609861ff5d119ed7413fd9c5 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Wed, 2 Dec 2020 12:53:23 -0800 Subject: [PATCH] c++: typename_type structural comparison For modules we need to compare structurally all the way down. This means inhibiting typename_type resolution, independent of comparing specializations. gcc/cp/ * cp-tree.h (comparing_typenames): Declare. * pt.c (comparing_typenames): Define. (spec_hasher::equal): Increment it around comparisons. * typeck.c (structural_comptypes): Adjust TYPENAME resolution check. --- gcc/cp/cp-tree.h | 4 ++++ gcc/cp/pt.c | 8 ++++++-- gcc/cp/typeck.c | 19 +++++++++---------- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 41ae13b3dbd..156bd6c8650 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5399,6 +5399,10 @@ extern int function_depth; in structrual_comptypes. */ extern int comparing_specializations; +/* Nonzero if we are inside eq_specializations, which affects + resolving of typenames in structural_comptypes. */ +extern int comparing_typenames; + /* In parser.c. */ /* Nonzero if we are parsing an unevaluated operand: an operand to diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 72d6cc3ad98..aa050f55fd6 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -1702,9 +1702,11 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend, return spec; } -/* Returns true iff two spec_entry nodes are equivalent. */ - +/* Restricts tree and type comparisons. */ int comparing_specializations; +int comparing_typenames; + +/* Returns true iff two spec_entry nodes are equivalent. */ bool spec_hasher::equal (spec_entry *e1, spec_entry *e2) @@ -1712,6 +1714,7 @@ spec_hasher::equal (spec_entry *e1, spec_entry *e2) int equal; ++comparing_specializations; + ++comparing_typenames; equal = (e1->tmpl == e2->tmpl && comp_template_args (e1->args, e2->args)); if (equal && flag_concepts @@ -1727,6 +1730,7 @@ spec_hasher::equal (spec_entry *e1, spec_entry *e2) equal = equivalent_constraints (c1, c2); } --comparing_specializations; + --comparing_typenames; return equal; } diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 267b284ea40..6294a787b5a 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -1256,16 +1256,15 @@ structural_comptypes (tree t1, tree t2, int strict) gcc_assert (TYPE_P (t1) && TYPE_P (t2)); - if (!comparing_specializations) - { - /* TYPENAME_TYPEs should be resolved if the qualifying scope is the - current instantiation. */ - if (TREE_CODE (t1) == TYPENAME_TYPE) - t1 = resolve_typename_type (t1, /*only_current_p=*/true); - - if (TREE_CODE (t2) == TYPENAME_TYPE) - t2 = resolve_typename_type (t2, /*only_current_p=*/true); - } + /* TYPENAME_TYPEs should be resolved if the qualifying scope is the + current instantiation, and we don't care about typename + structural equality. The comparing_typenames check is after the + code check, in order to early-out the common case. */ + if (TREE_CODE (t1) == TYPENAME_TYPE && !comparing_typenames) + t1 = resolve_typename_type (t1, /*only_current_p=*/true); + + if (TREE_CODE (t2) == TYPENAME_TYPE && !comparing_typenames) + t2 = resolve_typename_type (t2, /*only_current_p=*/true); if (TYPE_PTRMEMFUNC_P (t1)) t1 = TYPE_PTRMEMFUNC_FN_TYPE (t1); -- 2.30.2