c++: typename_type structural comparison
authorNathan Sidwell <nathan@acm.org>
Wed, 2 Dec 2020 20:53:23 +0000 (12:53 -0800)
committerNathan Sidwell <nathan@acm.org>
Wed, 2 Dec 2020 20:59:05 +0000 (12:59 -0800)
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
gcc/cp/pt.c
gcc/cp/typeck.c

index 41ae13b3dbdca712fb9067c2a24b8dd6d8ebfb6a..156bd6c8650afaf1906c84287ea633bd5dd312d0 100644 (file)
@@ -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
index 72d6cc3ad9854c920fc020b35423c19e198037da..aa050f55fd6ad48caeffa541c404c671894f5c7f 100644 (file)
@@ -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;
 }
index 267b284ea40fad3c985ed520e7f7eab91ea19fc8..6294a787b5a7c823e88403c03383979a38da5624 100644 (file)
@@ -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);