From 97ca3d0d59208beb76920dcfe33aeb921e396042 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Thu, 21 Jan 2016 15:26:02 -0500 Subject: [PATCH] re PR c++/43407 (Specifying visibility attribute of C++0x enum class emits warning) PR c++/43407 * decl.c (start_enum): Add attributes parameter. * parser.c (cp_parser_enum_specifier): Pass it. * pt.c (lookup_template_class_1): Pass it. * cp-tree.h: Adjust. From-SVN: r232701 --- gcc/cp/ChangeLog | 8 ++ gcc/cp/cp-tree.h | 2 +- gcc/cp/decl.c | 6 +- gcc/cp/parser.c | 3 +- gcc/cp/pt.c | 165 ++++++++++++++++++--------- gcc/testsuite/g++.dg/abi/abi-tag15.C | 2 +- gcc/testsuite/g++.dg/cpp0x/enum31.C | 7 ++ 7 files changed, 133 insertions(+), 60 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/enum31.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 45cb0e72a4c..f516216ab6f 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2016-01-21 Jason Merrill + + PR c++/43407 + * decl.c (start_enum): Add attributes parameter. + * parser.c (cp_parser_enum_specifier): Pass it. + * pt.c (lookup_template_class_1): Pass it. + * cp-tree.h: Adjust. + 2016-01-19 Jason Merrill PR c++/59759 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 51589c3311b..0aeee578f7e 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5788,7 +5788,7 @@ extern bool grok_op_properties (tree, bool); extern tree xref_tag (enum tag_types, tree, tag_scope, bool); extern tree xref_tag_from_type (tree, tree, tag_scope); extern bool xref_basetypes (tree, tree); -extern tree start_enum (tree, tree, tree, bool, bool *); +extern tree start_enum (tree, tree, tree, tree, bool, bool *); extern void finish_enum_value_list (tree); extern void finish_enum (tree); extern void build_enumerator (tree, tree, tree, tree, location_t); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index ceeef606117..d995654a3d8 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -13045,6 +13045,8 @@ copy_type_enum (tree dst, tree src) the enumeration type. This should be NULL_TREE if no storage type was specified. + ATTRIBUTES are any attributes specified after the enum-key. + SCOPED_ENUM_P is true if this is a scoped enumeration type. if IS_NEW is not NULL, gets TRUE iff a new type is created. @@ -13055,7 +13057,7 @@ copy_type_enum (tree dst, tree src) tree start_enum (tree name, tree enumtype, tree underlying_type, - bool scoped_enum_p, bool *is_new) + tree attributes, bool scoped_enum_p, bool *is_new) { tree prevtype = NULL_TREE; gcc_assert (identifier_p (name)); @@ -13163,6 +13165,8 @@ start_enum (tree name, tree enumtype, tree underlying_type, SET_SCOPED_ENUM_P (enumtype, scoped_enum_p); + cplus_decl_attributes (&enumtype, attributes, (int)ATTR_FLAG_TYPE_IN_PLACE); + if (underlying_type) { if (CP_INTEGRAL_TYPE_P (underlying_type)) diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 8dd7e498f7f..33f1df3ca02 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -17132,7 +17132,7 @@ cp_parser_enum_specifier (cp_parser* parser) brace so the enum will be recorded as being on the line of its tag (or the 'enum' keyword, if there is no tag). */ type = start_enum (identifier, type, underlying_type, - scoped_enum_p, &is_new_type); + attributes, scoped_enum_p, &is_new_type); /* If the next token is not '{' it is an opaque-enum-specifier or an elaborated-type-specifier. */ @@ -17248,7 +17248,6 @@ cp_parser_enum_specifier (cp_parser* parser) if (cp_parser_allow_gnu_extensions_p (parser)) { tree trailing_attr = cp_parser_gnu_attributes_opt (parser); - trailing_attr = chainon (trailing_attr, attributes); cplus_decl_attributes (&type, trailing_attr, (int) ATTR_FLAG_TYPE_IN_PLACE); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index ae60f1c2d0a..7985198d46c 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -214,6 +214,7 @@ static tree listify_autos (tree, tree); static tree tsubst_template_parm (tree, tree, tsubst_flags_t); static tree instantiate_alias_template (tree, tree, tsubst_flags_t); static bool complex_alias_template_p (const_tree tmpl); +static tree tsubst_attributes (tree, tree, tsubst_flags_t, tree); /* Make the current scope suitable for access checking when we are processing T. T can be FUNCTION_DECL for instantiated function @@ -8398,6 +8399,8 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context, t = start_enum (TYPE_IDENTIFIER (template_type), NULL_TREE, tsubst (ENUM_UNDERLYING_TYPE (template_type), arglist, complain, in_decl), + tsubst_attributes (TYPE_ATTRIBUTES (template_type), + arglist, complain, in_decl), SCOPED_ENUM_P (template_type), NULL); if (t == error_mark_node) @@ -9540,6 +9543,109 @@ can_complete_type_without_circularity (tree type) static tree tsubst_omp_clauses (tree, bool, bool, tree, tsubst_flags_t, tree); +/* Instantiate a single dependent attribute T (a TREE_LIST), and return either + T or a new TREE_LIST, possibly a chain in the case of a pack expansion. */ + +static tree +tsubst_attribute (tree t, tree *decl_p, tree args, + tsubst_flags_t complain, tree in_decl) +{ + gcc_assert (ATTR_IS_DEPENDENT (t)); + + tree val = TREE_VALUE (t); + if (val == NULL_TREE) + /* Nothing to do. */; + else if ((flag_openmp || flag_openmp_simd || flag_cilkplus) + && is_attribute_p ("omp declare simd", + get_attribute_name (t))) + { + tree clauses = TREE_VALUE (val); + clauses = tsubst_omp_clauses (clauses, true, false, args, + complain, in_decl); + c_omp_declare_simd_clauses_to_decls (*decl_p, clauses); + clauses = finish_omp_clauses (clauses, false, true); + tree parms = DECL_ARGUMENTS (*decl_p); + clauses + = c_omp_declare_simd_clauses_to_numbers (parms, clauses); + if (clauses) + val = build_tree_list (NULL_TREE, clauses); + else + val = NULL_TREE; + } + /* If the first attribute argument is an identifier, don't + pass it through tsubst. Attributes like mode, format, + cleanup and several target specific attributes expect it + unmodified. */ + else if (attribute_takes_identifier_p (get_attribute_name (t))) + { + tree chain + = tsubst_expr (TREE_CHAIN (val), args, complain, in_decl, + /*integral_constant_expression_p=*/false); + if (chain != TREE_CHAIN (val)) + val = tree_cons (NULL_TREE, TREE_VALUE (val), chain); + } + else if (PACK_EXPANSION_P (val)) + { + /* An attribute pack expansion. */ + tree purp = TREE_PURPOSE (t); + tree pack = tsubst_pack_expansion (val, args, complain, in_decl); + int len = TREE_VEC_LENGTH (pack); + tree list = NULL_TREE; + tree *q = &list; + for (int i = 0; i < len; ++i) + { + tree elt = TREE_VEC_ELT (pack, i); + *q = build_tree_list (purp, elt); + q = &TREE_CHAIN (*q); + } + return list; + } + else + val = tsubst_expr (val, args, complain, in_decl, + /*integral_constant_expression_p=*/false); + + if (val != TREE_VALUE (t)) + return build_tree_list (TREE_PURPOSE (t), val); + return t; +} + +/* Instantiate any dependent attributes in ATTRIBUTES, returning either it + unchanged or a new TREE_LIST chain. */ + +static tree +tsubst_attributes (tree attributes, tree args, + tsubst_flags_t complain, tree in_decl) +{ + tree last_dep = NULL_TREE; + + for (tree t = attributes; t; t = TREE_CHAIN (t)) + if (ATTR_IS_DEPENDENT (t)) + { + last_dep = t; + attributes = copy_list (attributes); + break; + } + + if (last_dep) + for (tree *p = &attributes; *p; p = &TREE_CHAIN (*p)) + { + tree t = *p; + if (ATTR_IS_DEPENDENT (t)) + { + tree subst = tsubst_attribute (t, NULL, args, complain, in_decl); + if (subst == t) + continue; + *p = subst; + do + p = &TREE_CHAIN (*p); + while (*p); + *p = TREE_CHAIN (t); + } + } + + return attributes; +} + /* Apply any attributes which had to be deferred until instantiation time. DECL_P, ATTRIBUTES and ATTR_FLAGS are as cplus_decl_attributes; ARGS, COMPLAIN, IN_DECL are as tsubst. */ @@ -9581,61 +9687,10 @@ apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags, { *p = TREE_CHAIN (t); TREE_CHAIN (t) = NULL_TREE; - if ((flag_openmp || flag_openmp_simd || flag_cilkplus) - && is_attribute_p ("omp declare simd", - get_attribute_name (t)) - && TREE_VALUE (t)) - { - tree clauses = TREE_VALUE (TREE_VALUE (t)); - clauses = tsubst_omp_clauses (clauses, true, false, args, - complain, in_decl); - c_omp_declare_simd_clauses_to_decls (*decl_p, clauses); - clauses = finish_omp_clauses (clauses, false, true); - tree parms = DECL_ARGUMENTS (*decl_p); - clauses - = c_omp_declare_simd_clauses_to_numbers (parms, clauses); - if (clauses) - TREE_VALUE (TREE_VALUE (t)) = clauses; - else - TREE_VALUE (t) = NULL_TREE; - } - /* If the first attribute argument is an identifier, don't - pass it through tsubst. Attributes like mode, format, - cleanup and several target specific attributes expect it - unmodified. */ - else if (attribute_takes_identifier_p (get_attribute_name (t)) - && TREE_VALUE (t)) - { - tree chain - = tsubst_expr (TREE_CHAIN (TREE_VALUE (t)), args, complain, - in_decl, - /*integral_constant_expression_p=*/false); - if (chain != TREE_CHAIN (TREE_VALUE (t))) - TREE_VALUE (t) - = 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, - /*integral_constant_expression_p=*/false); - *q = t; - q = &TREE_CHAIN (t); + *q = tsubst_attribute (t, decl_p, args, complain, in_decl); + do + q = &TREE_CHAIN (*q); + while (*q); } else p = &TREE_CHAIN (t); diff --git a/gcc/testsuite/g++.dg/abi/abi-tag15.C b/gcc/testsuite/g++.dg/abi/abi-tag15.C index bfda3a279ef..cf9e32fb817 100644 --- a/gcc/testsuite/g++.dg/abi/abi-tag15.C +++ b/gcc/testsuite/g++.dg/abi/abi-tag15.C @@ -1,3 +1,3 @@ // PR c++/66748 -enum __attribute__((abi_tag("foo"))) E {}; // { dg-error "redeclaration of" } +enum __attribute__((abi_tag("foo"))) E {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/enum31.C b/gcc/testsuite/g++.dg/cpp0x/enum31.C new file mode 100644 index 00000000000..62d65b46f0a --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/enum31.C @@ -0,0 +1,7 @@ +// { dg-do compile { target c++11 } } + +enum class __attribute__((__visibility__("default"))) Foobar +{ + fratz, + nabble +}; -- 2.30.2