From 5f1cd1da1a805c3d00332da45c3ab78a3931af63 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Mon, 27 Jan 2020 05:45:01 -0500 Subject: [PATCH] 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 PR c++/90750 PR c++/79585 * decl.c (grokdeclarator): Move dependent attribute to decl. * decl2.c (splice_template_attributes): No longer static. --- gcc/cp/ChangeLog | 7 +++++++ gcc/cp/cp-tree.h | 1 + gcc/cp/decl.c | 4 ++++ gcc/cp/decl2.c | 2 +- gcc/testsuite/g++.dg/ext/attr-type1.C | 19 +++++++++++++++++++ gcc/testsuite/g++.dg/warn/Wunused-var-26.C | 4 ++-- 6 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ext/attr-type1.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 8cb958f36fb..2b44b24461f 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2020-04-27 Jason Merrill + + 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 PR c++/94772 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 924c0b9c790..fff0016b3aa 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 31b5884ca3a..cf855dae909 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 293df990435..ac65529a01d 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 00000000000..6e84cccea1f --- /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 struct S +{ + static const int b = 64; +}; + +template struct T: S +{ + using A = S; + using A::b; + char* __attribute__((aligned(b))) c; +}; + +T t; + +#define SA(X) static_assert (X,#X) +SA (alignof(T) == S::b); diff --git a/gcc/testsuite/g++.dg/warn/Wunused-var-26.C b/gcc/testsuite/g++.dg/warn/Wunused-var-26.C index b3e020b6007..89c53de88a4 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 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" } -- 2.30.2