From: Nathan Sidwell Date: Mon, 15 Mar 2021 18:25:46 +0000 (-0700) Subject: c++: Incorrect type equivalence [PR 99496] X-Git-Tag: basepoints/gcc-12~570 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7b900dca607dceaae2db372365f682a4979c7826;p=thirdparty%2Fgcc.git 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. --- diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index 19bdfc7cb218..6dbdc926cb4e 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); diff --git a/gcc/testsuite/g++.dg/modules/pr99496_a.H b/gcc/testsuite/g++.dg/modules/pr99496_a.H new file mode 100644 index 000000000000..71b77fbb49cd --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/pr99496_a.H @@ -0,0 +1,17 @@ +// PR 99496 different types with same canonical +// (requires spec hasher to be a constant, so we get collisions) +// { dg-additional-options -fmodule-header } +// { dg-module-cmi {} } + +template using __void_t = void; + +template +struct __is_referenceable +{ }; + +template +struct __is_referenceable<_Tp, __void_t<_Tp&>> +{ }; + +template::value> +struct __is_copy_constructible_impl; diff --git a/gcc/testsuite/g++.dg/modules/pr99496_b.C b/gcc/testsuite/g++.dg/modules/pr99496_b.C new file mode 100644 index 000000000000..57b71d13f542 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/pr99496_b.C @@ -0,0 +1,3 @@ +// { dg-additional-options {-fmodules-ts -fno-module-lazy} } + +import "pr99496_a.H";