aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2017-03-09 08:35:37 +0000
committerMarek Polacek <mpolacek@gcc.gnu.org>2017-03-09 08:35:37 +0000
commit423aec8b5756c73681dadd10aec25e28dc18eb99 (patch)
tree6f5ceb49588acca1f4f4d463e536488ff47b8073
parentdd01cd0ca29b687337661abd9870c32a287de94b (diff)
downloadgcc-423aec8b5756c73681dadd10aec25e28dc18eb99.zip
gcc-423aec8b5756c73681dadd10aec25e28dc18eb99.tar.gz
gcc-423aec8b5756c73681dadd10aec25e28dc18eb99.tar.bz2
PR c++/79900 - ICE in strip_typedefs
PR c++/79900 - ICE in strip_typedefs * tree.c (strip_typedefs): Skip the attribute handling if T is a variant type which hasn't been updated yet. * g++.dg/warn/Wpadded-1.C: New test. From-SVN: r245988
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/tree.c47
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/warn/Wpadded-1.C22
4 files changed, 62 insertions, 18 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 5bd8322..caf0322 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2017-03-09 Marek Polacek <polacek@redhat.com>
+
+ PR c++/79900 - ICE in strip_typedefs
+ * tree.c (strip_typedefs): Skip the attribute handling if T is
+ a variant type which hasn't been updated yet.
+
2017-03-08 Jason Merrill <jason@redhat.com>
PR c++/79797 - ICE with self-reference in array DMI.
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index d3c63b8..2757af6 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1548,29 +1548,40 @@ strip_typedefs (tree t, bool *remove_attributes)
result = TYPE_MAIN_VARIANT (t);
}
gcc_assert (!typedef_variant_p (result));
- if (TYPE_USER_ALIGN (t) != TYPE_USER_ALIGN (result)
- || TYPE_ALIGN (t) != TYPE_ALIGN (result))
+
+ if (COMPLETE_TYPE_P (result) && !COMPLETE_TYPE_P (t))
+ /* If RESULT is complete and T isn't, it's likely the case that T
+ is a variant of RESULT which hasn't been updated yet. Skip the
+ attribute handling. */;
+ else
{
- gcc_assert (TYPE_USER_ALIGN (t));
- if (remove_attributes)
- *remove_attributes = true;
- else
+ if (TYPE_USER_ALIGN (t) != TYPE_USER_ALIGN (result)
+ || TYPE_ALIGN (t) != TYPE_ALIGN (result))
{
- if (TYPE_ALIGN (t) == TYPE_ALIGN (result))
- result = build_variant_type_copy (result);
+ gcc_assert (TYPE_USER_ALIGN (t));
+ if (remove_attributes)
+ *remove_attributes = true;
else
- result = build_aligned_type (result, TYPE_ALIGN (t));
- TYPE_USER_ALIGN (result) = true;
+ {
+ if (TYPE_ALIGN (t) == TYPE_ALIGN (result))
+ result = build_variant_type_copy (result);
+ else
+ result = build_aligned_type (result, TYPE_ALIGN (t));
+ TYPE_USER_ALIGN (result) = true;
+ }
+ }
+
+ if (TYPE_ATTRIBUTES (t))
+ {
+ if (remove_attributes)
+ result = apply_identity_attributes (result, TYPE_ATTRIBUTES (t),
+ remove_attributes);
+ else
+ result = cp_build_type_attribute_variant (result,
+ TYPE_ATTRIBUTES (t));
}
}
- if (TYPE_ATTRIBUTES (t))
- {
- if (remove_attributes)
- result = apply_identity_attributes (result, TYPE_ATTRIBUTES (t),
- remove_attributes);
- else
- result = cp_build_type_attribute_variant (result, TYPE_ATTRIBUTES (t));
- }
+
return cp_build_qualified_type (result, cp_type_quals (t));
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 396ab3a..6c8ab1d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2017-03-09 Marek Polacek <polacek@redhat.com>
+
+ PR c++/79900 - ICE in strip_typedefs
+ * g++.dg/warn/Wpadded-1.C: New test.
+
2017-03-08 Marek Polacek <polacek@redhat.com>
* g++.dg/Walloca1.C: Adjust dg-warning.
diff --git a/gcc/testsuite/g++.dg/warn/Wpadded-1.C b/gcc/testsuite/g++.dg/warn/Wpadded-1.C
new file mode 100644
index 0000000..b3f0581
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wpadded-1.C
@@ -0,0 +1,22 @@
+// PR c++/79900 - ICE in strip_typedefs
+// { dg-do compile }
+// { dg-options "-Wpadded" }
+
+template <class> struct A;
+template <typename> struct B { // { dg-warning "padding struct size to alignment boundary" }
+ long _M_off;
+ int _M_state;
+};
+template <> struct A<char> { typedef B<int> pos_type; };
+enum _Ios_Openmode {};
+struct C {
+ typedef _Ios_Openmode openmode;
+};
+template <typename, typename _Traits> struct D {
+ typedef typename _Traits::pos_type pos_type;
+ pos_type m_fn1(pos_type, C::openmode);
+};
+template class D<char, A<char> >;
+template <typename _CharT, typename _Traits>
+typename D<_CharT, _Traits>::pos_type D<_CharT, _Traits>::m_fn1(pos_type x,
+ C::openmode) { return x; }