diff options
author | Jason Merrill <jason@redhat.com> | 2016-01-21 15:26:02 -0500 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2016-01-21 15:26:02 -0500 |
commit | 97ca3d0d59208beb76920dcfe33aeb921e396042 (patch) | |
tree | e14478b90970df2620dd61b06cdf616e89318b4d /gcc | |
parent | ed478de1a4b9a313c4f162e214440bac948600f9 (diff) | |
download | gcc-97ca3d0d59208beb76920dcfe33aeb921e396042.zip gcc-97ca3d0d59208beb76920dcfe33aeb921e396042.tar.gz gcc-97ca3d0d59208beb76920dcfe33aeb921e396042.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 2 | ||||
-rw-r--r-- | gcc/cp/decl.c | 6 | ||||
-rw-r--r-- | gcc/cp/parser.c | 3 | ||||
-rw-r--r-- | gcc/cp/pt.c | 165 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/abi/abi-tag15.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/enum31.C | 7 |
7 files changed, 133 insertions, 60 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 45cb0e7..f516216 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2016-01-21 Jason Merrill <jason@redhat.com> + + 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 <jason@redhat.com> PR c++/59759 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 51589c3..0aeee57 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 ceeef60..d995654 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 8dd7e49..33f1df3 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 ae60f1c..7985198 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 bfda3a2..cf9e32f 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 0000000..62d65b4 --- /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 +}; |