[gcc/devel/ranger] c++: Template argument hashing [pr94454]
Aldy Hernandez
aldyh@gcc.gnu.org
Wed Jun 17 20:33:23 GMT 2020
https://gcc.gnu.org/g:aa576f2a860c8287cac6bbe6d37f5f37448bf06a
commit aa576f2a860c8287cac6bbe6d37f5f37448bf06a
Author: Nathan Sidwell <nathan@acm.org>
Date: Mon Apr 20 06:44:08 2020 -0700
c++: Template argument hashing [pr94454]
One of the problems hit by pr94454 was that the argument hasher was
not skipping nodes that template_args_equal would. Fixed by replacing
the STRIP_NOPS invocation by a bespoke loop. We also confuse the
canonical type machinery by treating tpl-tpl-parms as types. They're
not; bound-tpl-tpl-parms are. We can get away with them being
type-like. Unfortunately we give the original level==orig_level case
a canonical type, but the reduced cases of level<orig_level get
structural equality. That breaks the hasher because we'll use
TYPE_HASH (CANONICAL_TYPE ()) when we can. There's a note in
tsubst[TEMPLATE_TEMPLATE_PARM] about why the reduced ones cannot have
a canonical type. (I didn't feel like questioning that assertion at
this point.)
* pt.c (iterative_hash_template_arg): Strip nodes as
template_args_equal does.
[ARGUMENT_PACK_SELECT, TREE_VEC, CONSTRUCTOR]: Refactor.
[node_class:TEMPLATE_TEMPLATE_PARM]: Hash by level & index.
[node_class:default]: Refactor.
Diff:
---
gcc/cp/ChangeLog | 9 +++++++
gcc/cp/pt.c | 75 ++++++++++++++++++++++++++++++++++----------------------
2 files changed, 55 insertions(+), 29 deletions(-)
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 9533cca7137..5191db9580e 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,12 @@
+2020-04-20 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/94454 Template Argument Hashing
+ * pt.c (iterative_hash_template_arg): Strip nodes as
+ template_args_equal does.
+ [ARGUMENT_PACK_SELECT, TREE_VEC, CONSTRUCTOR]: Refactor.
+ [node_class:TEMPLATE_TEMPLATE_PARM]: Hash by level & index.
+ [node_class:default]: Refactor.
+
2020-04-18 Patrick Palka <ppalka@redhat.com>
PR c++/94632
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 9e39f46a090..4814b768c2c 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -195,6 +195,7 @@ static void set_current_access_from_decl (tree);
static enum template_base_result get_template_base (tree, tree, tree, tree,
bool , tree *);
static tree try_class_unification (tree, tree, tree, tree, bool);
+static bool class_nttp_const_wrapper_p (tree t);
static int coerce_template_template_parms (tree, tree, tsubst_flags_t,
tree, tree);
static bool template_template_parm_bindings_ok_p (tree, tree);
@@ -1737,31 +1738,32 @@ spec_hasher::hash (spec_entry *e)
}
/* Recursively calculate a hash value for a template argument ARG, for use
- in the hash tables of template specializations. */
+ in the hash tables of template specializations. We must be
+ careful to (at least) skip the same entities template_args_equal
+ does. */
hashval_t
iterative_hash_template_arg (tree arg, hashval_t val)
{
- unsigned HOST_WIDE_INT i;
- enum tree_code code;
- char tclass;
-
if (arg == NULL_TREE)
return iterative_hash_object (arg, val);
if (!TYPE_P (arg))
- STRIP_NOPS (arg);
-
- if (TREE_CODE (arg) == ARGUMENT_PACK_SELECT)
- gcc_unreachable ();
+ /* Strip nop-like things, but not the same as STRIP_NOPS. */
+ while (CONVERT_EXPR_P (arg)
+ || TREE_CODE (arg) == NON_LVALUE_EXPR
+ || class_nttp_const_wrapper_p (arg))
+ arg = TREE_OPERAND (arg, 0);
- code = TREE_CODE (arg);
- tclass = TREE_CODE_CLASS (code);
+ enum tree_code code = TREE_CODE (arg);
val = iterative_hash_object (code, val);
switch (code)
{
+ case ARGUMENT_PACK_SELECT:
+ gcc_unreachable ();
+
case ERROR_MARK:
return val;
@@ -1769,12 +1771,9 @@ iterative_hash_template_arg (tree arg, hashval_t val)
return iterative_hash_object (IDENTIFIER_HASH_VALUE (arg), val);
case TREE_VEC:
- {
- int i, len = TREE_VEC_LENGTH (arg);
- for (i = 0; i < len; ++i)
- val = iterative_hash_template_arg (TREE_VEC_ELT (arg, i), val);
- return val;
- }
+ for (int i = 0, len = TREE_VEC_LENGTH (arg); i < len; ++i)
+ val = iterative_hash_template_arg (TREE_VEC_ELT (arg, i), val);
+ return val;
case TYPE_PACK_EXPANSION:
case EXPR_PACK_EXPANSION:
@@ -1798,6 +1797,7 @@ iterative_hash_template_arg (tree arg, hashval_t val)
case CONSTRUCTOR:
{
tree field, value;
+ unsigned i;
iterative_hash_template_arg (TREE_TYPE (arg), val);
FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (arg), i, field, value)
{
@@ -1884,6 +1884,7 @@ iterative_hash_template_arg (tree arg, hashval_t val)
break;
}
+ char tclass = TREE_CODE_CLASS (code);
switch (tclass)
{
case tcc_type:
@@ -1899,12 +1900,30 @@ iterative_hash_template_arg (tree arg, hashval_t val)
tree ti = TYPE_ALIAS_TEMPLATE_INFO (ats);
return hash_tmpl_and_args (TI_TEMPLATE (ti), TI_ARGS (ti));
}
- if (TYPE_CANONICAL (arg))
- return iterative_hash_object (TYPE_HASH (TYPE_CANONICAL (arg)),
- val);
- else if (TREE_CODE (arg) == DECLTYPE_TYPE)
- return iterative_hash_template_arg (DECLTYPE_TYPE_EXPR (arg), val);
- /* Otherwise just compare the types during lookup. */
+
+ switch (TREE_CODE (arg))
+ {
+ case TEMPLATE_TEMPLATE_PARM:
+ {
+ tree tpi = TEMPLATE_TYPE_PARM_INDEX (arg);
+
+ /* Do not recurse with TPI directly, as that is unbounded
+ recursion. */
+ val = iterative_hash_object (TEMPLATE_PARM_LEVEL (tpi), val);
+ val = iterative_hash_object (TEMPLATE_PARM_IDX (tpi), val);
+ }
+ break;
+
+ case DECLTYPE_TYPE:
+ val = iterative_hash_template_arg (DECLTYPE_TYPE_EXPR (arg), val);
+ break;
+
+ default:
+ if (tree canonical = TYPE_CANONICAL (arg))
+ val = iterative_hash_object (TYPE_HASH (canonical), val);
+ break;
+ }
+
return val;
case tcc_declaration:
@@ -1913,13 +1932,11 @@ iterative_hash_template_arg (tree arg, hashval_t val)
default:
gcc_assert (IS_EXPR_CODE_CLASS (tclass));
- {
- unsigned n = cp_tree_operand_length (arg);
- for (i = 0; i < n; ++i)
- val = iterative_hash_template_arg (TREE_OPERAND (arg, i), val);
- return val;
- }
+ for (int i = 0, n = cp_tree_operand_length (arg); i < n; ++i)
+ val = iterative_hash_template_arg (TREE_OPERAND (arg, i), val);
+ return val;
}
+
gcc_unreachable ();
return 0;
}
More information about the Gcc-cvs
mailing list