diff options
author | Jason Merrill <jason@redhat.com> | 2020-01-27 05:45:01 -0500 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2020-04-27 17:21:56 -0400 |
commit | 5f1cd1da1a805c3d00332da45c3ab78a3931af63 (patch) | |
tree | 4b729b83f175414d577724f14267b6c8fafbacc5 /gcc | |
parent | bb7ed17aa1102de9f99fb9608f1119eb4df613fe (diff) | |
download | gcc-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.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 1 | ||||
-rw-r--r-- | gcc/cp/decl.c | 4 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/attr-type1.C | 19 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/warn/Wunused-var-26.C | 4 |
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" } |