diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 0cd642ba1e1..5ea0490684c 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2008-02-05 Douglas Gregor + + PR c++/35074 + * decl2.c (save_template_attributes): When we're modifying the + TYPE_MAIN_VARIANT to add new attributes, be sure to also modify + all of the other variants to add those same attributes. Otherwise, + the main variant will be inconsistent with those other variants. + 2008-02-04 Richard Guenther PR java/35035 diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 3b20586457c..d2d81feae44 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -1068,6 +1068,7 @@ save_template_attributes (tree *attr_p, tree *decl_p) { tree late_attrs = splice_template_attributes (attr_p, *decl_p); tree *q; + tree old_attrs = NULL_TREE; if (!late_attrs) return; @@ -1090,9 +1091,26 @@ save_template_attributes (tree *attr_p, tree *decl_p) else q = &TYPE_ATTRIBUTES (*decl_p); - if (*q) - q = &TREE_CHAIN (tree_last (*q)); + old_attrs = *q; + + /* Place the late attributes at the beginning of the attribute + list. */ + TREE_CHAIN (tree_last (late_attrs)) = *q; *q = late_attrs; + + if (!DECL_P (*decl_p) && *decl_p == TYPE_MAIN_VARIANT (*decl_p)) + { + /* We've added new attributes directly to the main variant, so + now we need to update all of the other variants to include + these new attributes. */ + tree variant; + for (variant = TYPE_NEXT_VARIANT (*decl_p); variant; + variant = TYPE_NEXT_VARIANT (variant)) + { + gcc_assert (TYPE_ATTRIBUTES (variant) == old_attrs); + TYPE_ATTRIBUTES (variant) = TYPE_ATTRIBUTES (*decl_p); + } + } } /* Like decl_attributes, but handle C++ complexity. */ diff --git a/gcc/testsuite/g++.dg/ext/attrib30.C b/gcc/testsuite/g++.dg/ext/attrib30.C new file mode 100644 index 00000000000..fd2826a6029 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/attrib30.C @@ -0,0 +1,8 @@ +// { dg-do compile } +// PR c++/35074 +template struct A +{ + void foo() const; +} __attribute((aligned(4))); + +template void A::foo() const {}