aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/module.cc
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@acm.org>2021-03-15 11:25:46 -0700
committerNathan Sidwell <nathan@acm.org>2021-03-16 04:37:33 -0700
commit7b900dca607dceaae2db372365f682a4979c7826 (patch)
tree300281173235f3b7155cb9e01f3268be9090dcda /gcc/cp/module.cc
parent3c5b6d24e664f951c6b4e42738aa1ef5489e5f66 (diff)
downloadgcc-7b900dca607dceaae2db372365f682a4979c7826.zip
gcc-7b900dca607dceaae2db372365f682a4979c7826.tar.gz
gcc-7b900dca607dceaae2db372365f682a4979c7826.tar.bz2
c++: Incorrect type equivalence [PR 99496]
This bug was caused by not marking dependent template aliases correctly -- these things look like typedefs, but are not (necessarily) equivalent to the canonical type. We need to record that. PR c++/99496 gcc/cp/ * module.cc (trees_out::decl_value): Adjust typedef streaming, indicate whether it is a dependent alias. (trees_in::decl_value): Likewise. Set as dependent alias, if it is one. gcc/testsuite/ * g++.dg/modules/pr99496_a.H: New. * g++.dg/modules/pr99496_b.C: New.
Diffstat (limited to 'gcc/cp/module.cc')
-rw-r--r--gcc/cp/module.cc64
1 files changed, 48 insertions, 16 deletions
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 19bdfc7..6dbdc92 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -7719,18 +7719,35 @@ trees_out::decl_value (tree decl, depset *dep)
}
}
- bool is_typedef = (!type && inner
- && TREE_CODE (inner) == TYPE_DECL
- && DECL_ORIGINAL_TYPE (inner)
- && TYPE_NAME (TREE_TYPE (inner)) == inner);
- if (is_typedef)
+ bool is_typedef = false;
+ if (!type && inner && TREE_CODE (inner) == TYPE_DECL)
{
- /* A typedef type. */
- int type_tag = insert (TREE_TYPE (inner));
+ tree t = TREE_TYPE (inner);
+ unsigned tdef_flags = 0;
+ if (DECL_ORIGINAL_TYPE (inner)
+ && TYPE_NAME (TREE_TYPE (inner)) == inner)
+ {
+ tdef_flags |= 1;
+ if (TYPE_STRUCTURAL_EQUALITY_P (t)
+ && TYPE_DEPENDENT_P_VALID (t)
+ && TYPE_DEPENDENT_P (t))
+ tdef_flags |= 2;
+ }
if (streaming_p ())
- dump (dumper::TREE)
- && dump ("Cloned:%d typedef %C:%N", type_tag,
- TREE_CODE (TREE_TYPE (inner)), TREE_TYPE (inner));
+ u (tdef_flags);
+
+ if (tdef_flags & 1)
+ {
+ /* A typedef type. */
+ int type_tag = insert (t);
+ if (streaming_p ())
+ dump (dumper::TREE)
+ && dump ("Cloned:%d %s %C:%N", type_tag,
+ tdef_flags & 2 ? "depalias" : "typedef",
+ TREE_CODE (t), t);
+
+ is_typedef = true;
+ }
}
if (streaming_p () && DECL_MAYBE_IN_CHARGE_CDTOR_P (decl))
@@ -7993,12 +8010,6 @@ trees_in::decl_value ()
dump (dumper::TREE) && dump ("Read:%d %C:%N", tag, TREE_CODE (decl), decl);
- /* Regular typedefs will have a NULL TREE_TYPE at this point. */
- bool is_typedef = (!type && inner
- && TREE_CODE (inner) == TYPE_DECL
- && DECL_ORIGINAL_TYPE (inner)
- && !TREE_TYPE (inner));
-
existing = back_refs[~tag];
bool installed = install_entity (existing);
bool is_new = existing == decl;
@@ -8030,6 +8041,16 @@ trees_in::decl_value ()
}
}
+ /* Regular typedefs will have a NULL TREE_TYPE at this point. */
+ unsigned tdef_flags = 0;
+ bool is_typedef = false;
+ if (!type && inner && TREE_CODE (inner) == TYPE_DECL)
+ {
+ tdef_flags = u ();
+ if (tdef_flags & 1)
+ is_typedef = true;
+ }
+
if (is_new)
{
/* A newly discovered node. */
@@ -8076,6 +8097,14 @@ trees_in::decl_value ()
TREE_TYPE (inner) = DECL_ORIGINAL_TYPE (inner);
DECL_ORIGINAL_TYPE (inner) = NULL_TREE;
set_underlying_type (inner);
+ if (tdef_flags & 2)
+ {
+ /* Match instantiate_alias_template's handling. */
+ tree type = TREE_TYPE (inner);
+ TYPE_DEPENDENT_P (type) = true;
+ TYPE_DEPENDENT_P_VALID (type) = true;
+ SET_TYPE_STRUCTURAL_EQUALITY (type);
+ }
}
if (inner_tag)
@@ -10661,6 +10690,9 @@ trees_in::key_mergeable (int tag, merge_kind mk, tree decl, tree inner,
spec.tmpl = tree_node ();
spec.args = tree_node ();
+ if (get_overrun ())
+ return error_mark_node;
+
DECL_NAME (decl) = DECL_NAME (spec.tmpl);
DECL_CONTEXT (decl) = DECL_CONTEXT (spec.tmpl);
DECL_NAME (inner) = DECL_NAME (decl);