public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r11-5824] c++: check alias match for specializations [PR98116]
@ 2020-12-07 16:49 Nathan Sidwell
0 siblings, 0 replies; only message in thread
From: Nathan Sidwell @ 2020-12-07 16:49 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:9d0eb0ae948f0fbee208cfb9a86133abea650f81
commit r11-5824-g9d0eb0ae948f0fbee208cfb9a86133abea650f81
Author: Nathan Sidwell <nathan@acm.org>
Date: Mon Dec 7 07:02:58 2020 -0800
c++: check alias match for specializations [PR98116]
This fixes the underlying problem my recent (backedout) changes to
array type creation uncovered. We had paths through
structural_comptypes that ignored alias templates, even when
significant. This adds the necessary checks.
PR c++/98116
gcc/cp/
* typeck.c (structural_comptypes): Move early outs to comptype.
Always check template-alias match when comparing_specializations.
(comptypes): Do early out checking here.
gcc/testsuite/
* g++.dg/template/pr98116.C: Remove dg-ice.
* g++.dg/template/pr98116-2.C: New.
Diff:
---
gcc/cp/typeck.c | 61 ++++++++++++++++---------------
gcc/testsuite/g++.dg/template/pr98116-2.C | 34 +++++++++++++++++
gcc/testsuite/g++.dg/template/pr98116.C | 5 +--
3 files changed, 68 insertions(+), 32 deletions(-)
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 267b284ea40..4d499af5ccb 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1247,14 +1247,8 @@ cxx_safe_function_type_cast_p (tree t1, tree t2)
static bool
structural_comptypes (tree t1, tree t2, int strict)
{
- if (t1 == t2)
- return true;
-
- /* Suppress errors caused by previously reported errors. */
- if (t1 == error_mark_node || t2 == error_mark_node)
- return false;
-
- gcc_assert (TYPE_P (t1) && TYPE_P (t2));
+ /* Both should be types that are not obviously the same. */
+ gcc_checking_assert (t1 != t2 && TYPE_P (t1) && TYPE_P (t2));
if (!comparing_specializations)
{
@@ -1300,13 +1294,13 @@ structural_comptypes (tree t1, tree t2, int strict)
/* Allow for two different type nodes which have essentially the same
definition. Note that we already checked for equality of the type
qualifiers (just above). */
-
if (TREE_CODE (t1) != ARRAY_TYPE
&& TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
- return true;
-
+ goto check_alias;
- /* Compare the types. Break out if they could be the same. */
+ /* Compare the types. Return false on known not-same. Break on not
+ known. Never return true from this switch -- you'll break
+ specialization comparison. */
switch (TREE_CODE (t1))
{
case VOID_TYPE:
@@ -1332,7 +1326,11 @@ structural_comptypes (tree t1, tree t2, int strict)
have identical properties, different TYPE_MAIN_VARIANTs, but
represent the same type. The canonical type system keeps
track of equivalence in this case, so we fall back on it. */
- return TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2);
+ if (TYPE_CANONICAL (t1) != TYPE_CANONICAL (t2))
+ return false;
+
+ /* We don't need or want the attribute comparison. */
+ goto check_alias;
case TEMPLATE_TEMPLATE_PARM:
case BOUND_TEMPLATE_TEMPLATE_PARM:
@@ -1477,24 +1475,28 @@ structural_comptypes (tree t1, tree t2, int strict)
return false;
}
- /* Don't treat an alias template specialization with dependent
- arguments as equivalent to its underlying type when used as a
- template argument; we need them to be distinct so that we
- substitute into the specialization arguments at instantiation
- time. And aliases can't be equivalent without being ==, so
- we don't need to look any deeper. */
+ /* If we get here, we know that from a target independent POV the
+ types are the same. Make sure the target attributes are also
+ the same. */
+ if (!comp_type_attributes (t1, t2))
+ return false;
+
+ check_alias:
if (comparing_specializations)
{
+ /* Don't treat an alias template specialization with dependent
+ arguments as equivalent to its underlying type when used as a
+ template argument; we need them to be distinct so that we
+ substitute into the specialization arguments at instantiation
+ time. And aliases can't be equivalent without being ==, so
+ we don't need to look any deeper. */
tree dep1 = dependent_alias_template_spec_p (t1, nt_transparent);
tree dep2 = dependent_alias_template_spec_p (t2, nt_transparent);
if ((dep1 || dep2) && dep1 != dep2)
return false;
}
- /* If we get here, we know that from a target independent POV the
- types are the same. Make sure the target attributes are also
- the same. */
- return comp_type_attributes (t1, t2);
+ return true;
}
/* Return true if T1 and T2 are related as allowed by STRICT. STRICT
@@ -1509,6 +1511,13 @@ comptypes (tree t1, tree t2, int strict)
gcc_checking_assert (TREE_CODE (t1) != TYPE_ARGUMENT_PACK
&& TREE_CODE (t2) != TYPE_ARGUMENT_PACK);
+ if (t1 == t2)
+ return true;
+
+ /* Suppress errors caused by previously reported errors. */
+ if (t1 == error_mark_node || t2 == error_mark_node)
+ return false;
+
if (strict == COMPARE_STRICT && comparing_specializations
&& (t1 != TYPE_CANONICAL (t1) || t2 != TYPE_CANONICAL (t2)))
/* If comparing_specializations, treat dependent aliases as distinct. */
@@ -1516,12 +1525,6 @@ comptypes (tree t1, tree t2, int strict)
if (strict == COMPARE_STRICT)
{
- if (t1 == t2)
- return true;
-
- if (t1 == error_mark_node || t2 == error_mark_node)
- return false;
-
if (TYPE_STRUCTURAL_EQUALITY_P (t1) || TYPE_STRUCTURAL_EQUALITY_P (t2))
/* At least one of the types requires structural equality, so
perform a deep check. */
diff --git a/gcc/testsuite/g++.dg/template/pr98116-2.C b/gcc/testsuite/g++.dg/template/pr98116-2.C
new file mode 100644
index 00000000000..fd12bb19be0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/pr98116-2.C
@@ -0,0 +1,34 @@
+// PR 98116, ICE with stripping typedef array type
+// { dg-do compile { target c++11 } }
+// { dg-additional-options {--param=hash-table-verification-limit=10000000 -fchecking=2} }
+
+// We got confused by alias templates that alias the same type. Their
+// hashes were different (good), but they compared equal (bad)
+
+namespace std {
+typedef int is_convertible;
+template <typename _Tp> using remove_pointer_t = typename _Tp ::type;
+template <bool> struct enable_if;
+template <typename> void declval();
+template <bool _Cond> using enable_if_t = typename enable_if<_Cond>::type;
+template <typename, typename> class Trans_NS___cxx11_basic_string {
+ long _M_string_length;
+};
+} // namespace std
+struct string16_char_traits;
+template class std::Trans_NS___cxx11_basic_string<unsigned short,
+ string16_char_traits>;
+template <typename, typename> using IsLegalDataConversion = std::is_convertible;
+template <typename Container, typename T>
+using ContainerHasConvertibleData = IsLegalDataConversion<
+ std::remove_pointer_t<decltype(std::declval<Container>)>, T>;
+template <typename Array, typename T, long>
+using EnableIfSpanCompatibleArray =
+ std::enable_if_t<!!sizeof (ContainerHasConvertibleData<Array, T>)>;
+template <int Extent> class span {
+ template <long N, EnableIfSpanCompatibleArray<
+ const std::Trans_NS___cxx11_basic_string<
+ unsigned short, string16_char_traits>[N],
+ std::Trans_NS___cxx11_basic_string<short, int>, Extent>>
+ span();
+};
diff --git a/gcc/testsuite/g++.dg/template/pr98116.C b/gcc/testsuite/g++.dg/template/pr98116.C
index 874c590f9d2..7d54314b26b 100644
--- a/gcc/testsuite/g++.dg/template/pr98116.C
+++ b/gcc/testsuite/g++.dg/template/pr98116.C
@@ -1,10 +1,9 @@
// PR 98116, ICE with stripping typedef array type
// { dg-do compile { target c++11 } }
// { dg-additional-options {--param=hash-table-verification-limit=10000000 -fchecking=2} }
-// { dg-ice "spec_hasher::equal" }
-// We get confused by alias templates that alias the same type.
-// { dg-prune-output "hash table checking failed" }
+// We got confused by alias templates that alias the same type. Their
+// hashes were different (good), but they compared equal (bad)
namespace std {
struct is_convertible;
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2020-12-07 16:49 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-07 16:49 [gcc r11-5824] c++: check alias match for specializations [PR98116] Nathan Sidwell
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).