Since duplicate_decls throws away the new decl before returning 1, we
need to make sure that we don't have anything pointing to it. In a
TYPE_DECL, the type points back to the decl via TYPE_NAME, so we always
need to choose the type from the olddecl.
Tested x86_64-pc-linux-gnu, applying to trunk and 4.8.
commit 9dd7f9667b090b7e8c045eecb8b16db6930204eb
Author: Jason Merrill <ja...@redhat.com>
Date: Mon Jan 27 14:16:36 2014 -0500
PR c++/54652
* decl.c (duplicate_decls): Always use oldtype for TYPE_DECL.
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 7ebb05d..c93c783 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -1926,9 +1926,9 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
/* Merge the data types specified in the two decls. */
newtype = merge_types (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
- /* If merge_types produces a non-typedef type, just use the old type. */
- if (TREE_CODE (newdecl) == TYPE_DECL
- && newtype == DECL_ORIGINAL_TYPE (newdecl))
+ /* For typedefs use the old type, as the new type's DECL_NAME points
+ at newdecl, which will be ggc_freed. */
+ if (TREE_CODE (newdecl) == TYPE_DECL)
newtype = oldtype;
if (VAR_P (newdecl))
diff --git a/gcc/testsuite/g++.dg/ext/attrib48.C b/gcc/testsuite/g++.dg/ext/attrib48.C
new file mode 100644
index 0000000..19a9959
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/attrib48.C
@@ -0,0 +1,6 @@
+// PR c++/54652
+
+typedef unsigned L __attribute__ ((aligned));
+typedef unsigned L __attribute__ ((aligned));
+
+L l;