aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2020-01-27 05:45:01 -0500
committerJason Merrill <jason@redhat.com>2020-04-27 17:21:56 -0400
commit5f1cd1da1a805c3d00332da45c3ab78a3931af63 (patch)
tree4b729b83f175414d577724f14267b6c8fafbacc5
parentbb7ed17aa1102de9f99fb9608f1119eb4df613fe (diff)
downloadgcc-5f1cd1da1a805c3d00332da45c3ab78a3931af63.zip
gcc-5f1cd1da1a805c3d00332da45c3ab78a3931af63.tar.gz
gcc-5f1cd1da1a805c3d00332da45c3ab78a3931af63.tar.bz2
c++: Avoid ICE with dependent attribute on type.
We previously happened to accept this testcase, but never actually did anything useful with the attribute. The patch for PR86379 stopped using TREE_TYPE as USING_DECL_SCOPE, so 'using A::b' no longer had TREE_TYPE set, so the language-independent decl_attributes started crashing on it. GNU attributes are more flexible in their placement than C++11 attributes, so if we encounter a dependent GNU attribute that syntactically appertains to a type rather than the declaration as a whole, move it to the declaration; that's almost certainly what the user meant, anyway. gcc/cp/ChangeLog 2020-04-27 Jason Merrill <jason@redhat.com> PR c++/90750 PR c++/79585 * decl.c (grokdeclarator): Move dependent attribute to decl. * decl2.c (splice_template_attributes): No longer static.
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/decl.c4
-rw-r--r--gcc/cp/decl2.c2
-rw-r--r--gcc/testsuite/g++.dg/ext/attr-type1.C19
-rw-r--r--gcc/testsuite/g++.dg/warn/Wunused-var-26.C4
6 files changed, 34 insertions, 3 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 8cb958f..2b44b24 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+2020-04-27 Jason Merrill <jason@redhat.com>
+
+ PR c++/90750
+ PR c++/79585
+ * decl.c (grokdeclarator): Move dependent attribute to decl.
+ * decl2.c (splice_template_attributes): No longer static.
+
2020-04-27 Patrick Palka <ppalka@redhat.com>
PR c++/94772
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 924c0b9..fff0016 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6626,6 +6626,7 @@ extern tree grokfield (const cp_declarator *, cp_decl_specifier_seq *,
tree, bool, tree, tree);
extern tree grokbitfield (const cp_declarator *, cp_decl_specifier_seq *,
tree, tree, tree);
+extern tree splice_template_attributes (tree *, tree);
extern bool any_dependent_type_attributes_p (tree);
extern tree cp_reconstruct_complex_type (tree, tree);
extern bool attributes_naming_typedef_ok (tree);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 31b5884..cf855da 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -11937,9 +11937,13 @@ grokdeclarator (const cp_declarator *declarator,
attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT;
if (declarator->kind == cdk_array)
attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
+ /* Assume that any attributes that get applied late to templates will
+ DTRT when applied to the declaration as a whole. */
+ tree late_attrs = splice_template_attributes (&attrs, type);
returned_attrs = decl_attributes (&type,
chainon (returned_attrs, attrs),
attr_flags);
+ returned_attrs = chainon (late_attrs, returned_attrs);
}
inner_declarator = declarator->declarator;
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 293df99..ac65529 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -1228,7 +1228,7 @@ is_late_template_attribute (tree attr, tree decl)
the declaration itself is dependent, so all attributes should be applied
at instantiation time. */
-static tree
+tree
splice_template_attributes (tree *attr_p, tree decl)
{
tree *p = attr_p;
diff --git a/gcc/testsuite/g++.dg/ext/attr-type1.C b/gcc/testsuite/g++.dg/ext/attr-type1.C
new file mode 100644
index 0000000..6e84ccc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/attr-type1.C
@@ -0,0 +1,19 @@
+// PR c++/90750
+// { dg-do compile { target c++11 } }
+
+template <typename> struct S
+{
+ static const int b = 64;
+};
+
+template <typename a> struct T: S<a>
+{
+ using A = S<a>;
+ using A::b;
+ char* __attribute__((aligned(b))) c;
+};
+
+T<int> t;
+
+#define SA(X) static_assert (X,#X)
+SA (alignof(T<int>) == S<int>::b);
diff --git a/gcc/testsuite/g++.dg/warn/Wunused-var-26.C b/gcc/testsuite/g++.dg/warn/Wunused-var-26.C
index b3e020b..89c53de 100644
--- a/gcc/testsuite/g++.dg/warn/Wunused-var-26.C
+++ b/gcc/testsuite/g++.dg/warn/Wunused-var-26.C
@@ -47,10 +47,10 @@ template <class T>
void f_var_type_unused ()
{
// The variable's type is marked unused.
- T* UNUSED t = new T; // { dg-bogus "unused variable" "bug 79585" { xfail *-*-* } }
+ T* UNUSED t = new T; // { dg-bogus "unused variable" "bug 79585" }
typedef T U;
- U* UNUSED u = new U; // { dg-bogus "unused variable" "bug 79585" { xfail *-*-* } }
+ U* UNUSED u = new U; // { dg-bogus "unused variable" "bug 79585" }
typedef T UNUSED U;
U v = U (); // { dg-bogus "unused variable" "bug 79585" }