From 3e77df37511c9d48c749f7d677ba5fab6e35089e Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Fri, 8 May 2015 04:42:06 +0000 Subject: PR c++/59012 * parser.c (cp_parser_std_attribute_list): Handle attribute expansion. (cp_parser_std_attribute_spec): Handle alignas pack expansion. * decl2.c (is_late_template_attribute): An attribute exp is dependent. * pt.c (make_pack_expansion): Allow TREE_LIST for attribute expansion. (apply_late_template_attributes): Handle attribute pack expansion. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@222902 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cp/ChangeLog | 9 +++++++++ gcc/cp/decl2.c | 4 ++++ gcc/cp/parser.c | 20 +++++++++++++++++--- gcc/cp/pt.c | 19 +++++++++++++++++-- gcc/testsuite/g++.dg/cpp0x/alignas4.C | 19 +++++++++++++++++++ 5 files changed, 66 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/alignas4.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 3c32e6f77dd..8427e9d2782 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2015-05-07 Jason Merrill + + PR c++/59012 + * parser.c (cp_parser_std_attribute_list): Handle attribute expansion. + (cp_parser_std_attribute_spec): Handle alignas pack expansion. + * decl2.c (is_late_template_attribute): An attribute exp is dependent. + * pt.c (make_pack_expansion): Allow TREE_LIST for attribute expansion. + (apply_late_template_attributes): Handle attribute pack expansion. + 2015-05-07 Marek Polacek PR c/65179 diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 0d478471925..2276bd67ace 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -1175,6 +1175,10 @@ is_late_template_attribute (tree attr, tree decl) && is_attribute_p ("omp declare simd", name)) return true; + /* An attribute pack is clearly dependent. */ + if (args && PACK_EXPANSION_P (args)) + return true; + /* If any of the arguments are dependent expressions, we can't evaluate the attribute until instantiation time. */ for (arg = args; arg; arg = TREE_CHAIN (arg)) diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 30a3fabbb98..3d165da708f 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -22486,6 +22486,13 @@ cp_parser_std_attribute_list (cp_parser *parser) attributes = attribute; } token = cp_lexer_peek_token (parser->lexer); + if (token->type == CPP_ELLIPSIS) + { + cp_lexer_consume_token (parser->lexer); + TREE_VALUE (attribute) + = make_pack_expansion (TREE_VALUE (attribute)); + token = cp_lexer_peek_token (parser->lexer); + } if (token->type != CPP_COMMA) break; cp_lexer_consume_token (parser->lexer); @@ -22564,20 +22571,27 @@ cp_parser_std_attribute_spec (cp_parser *parser) return alignas_expr; } + alignas_expr = cxx_alignas_expr (alignas_expr); + alignas_expr = build_tree_list (NULL_TREE, alignas_expr); + + if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS)) + { + cp_lexer_consume_token (parser->lexer); + alignas_expr = make_pack_expansion (alignas_expr); + } + if (cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN) == NULL) { cp_parser_error (parser, "expected %<)%>"); return error_mark_node; } - alignas_expr = cxx_alignas_expr (alignas_expr); - /* Build the C++-11 representation of an 'aligned' attribute. */ attributes = build_tree_list (build_tree_list (get_identifier ("gnu"), get_identifier ("aligned")), - build_tree_list (NULL_TREE, alignas_expr)); + alignas_expr); } return attributes; diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 8e0e789916b..78714745452 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -3338,9 +3338,9 @@ make_pack_expansion (tree arg) if (!arg || arg == error_mark_node) return arg; - if (TREE_CODE (arg) == TREE_LIST) + if (TREE_CODE (arg) == TREE_LIST && TREE_PURPOSE (arg)) { - /* The only time we will see a TREE_LIST here is for a base + /* A TREE_LIST with a non-null TREE_PURPOSE is for a base class initializer. In this case, the TREE_PURPOSE will be a _TYPE node (representing the base class expansion we're initializing) and the TREE_VALUE will be a TREE_LIST @@ -9012,6 +9012,21 @@ apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags, = tree_cons (NULL_TREE, TREE_VALUE (TREE_VALUE (t)), chain); } + else if (TREE_VALUE (t) && PACK_EXPANSION_P (TREE_VALUE (t))) + { + /* An attribute pack expansion. */ + tree purp = TREE_PURPOSE (t); + tree pack = (tsubst_pack_expansion + (TREE_VALUE (t), args, complain, in_decl)); + int len = TREE_VEC_LENGTH (pack); + for (int i = 0; i < len; ++i) + { + tree elt = TREE_VEC_ELT (pack, i); + *q = build_tree_list (purp, elt); + q = &TREE_CHAIN (*q); + } + continue; + } else TREE_VALUE (t) = tsubst_expr (TREE_VALUE (t), args, complain, in_decl, diff --git a/gcc/testsuite/g++.dg/cpp0x/alignas4.C b/gcc/testsuite/g++.dg/cpp0x/alignas4.C new file mode 100644 index 00000000000..871aaefed1f --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/alignas4.C @@ -0,0 +1,19 @@ +// PR c++/59012 +// { dg-do compile { target c++11 } } +// { dg-final { scan-assembler "align 8" { target x86_64-*-*-gnu } } } + +template +struct A +{ + alignas(T...) char t; +}; + +A a; + +template +struct A2 +{ + [[gnu::aligned (alignof (T))...]] char t; +}; + +A2 a2; -- cgit v1.2.3