From e3c888eb0e3923981bcb914f818c29a054843d9e Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Sat, 2 Jun 2012 00:03:51 -0400 Subject: [PATCH] re PR c++/52973 (visibility attribute for class is not passed to its members) PR c++/52973 * parser.c (cp_parser_class_head): Apply attributes here. * semantics.c (begin_class_definition): Not here. * cp-tree.h: Adjust. From-SVN: r188137 --- gcc/cp/ChangeLog | 5 +++++ gcc/cp/cp-tree.h | 2 +- gcc/cp/parser.c | 15 ++++++++++----- gcc/cp/semantics.c | 7 ++----- gcc/objcp/ChangeLog | 5 +++++ gcc/objcp/objcp-decl.c | 2 +- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/g++.dg/ext/attrib14.C | 4 ++-- gcc/testsuite/g++.dg/ext/visibility/template12.C | 13 +++++++++++++ 9 files changed, 43 insertions(+), 14 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ext/visibility/template12.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ba5937acb451..b094504fae89 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,10 @@ 2012-06-01 Jason Merrill + PR c++/52973 + * parser.c (cp_parser_class_head): Apply attributes here. + * semantics.c (begin_class_definition): Not here. + * cp-tree.h: Adjust. + PR c++/52725 * parser.c (cp_parser_binary_expression): Bail early if we're parsing tentatively and the LHS has a parse error. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 626c61f995ac..d21c2bfee246 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5585,7 +5585,7 @@ extern tree finish_fname (tree); extern void finish_translation_unit (void); extern tree finish_template_type_parm (tree, tree); extern tree finish_template_template_parm (tree, tree); -extern tree begin_class_definition (tree, tree); +extern tree begin_class_definition (tree); extern void finish_template_decl (tree); extern tree finish_template_type (tree, tree, int); extern tree finish_base_specifier (tree, tree, bool); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 7f9a94b5c061..16139d619aa7 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -2008,7 +2008,7 @@ static tree cp_parser_class_name static tree cp_parser_class_specifier (cp_parser *); static tree cp_parser_class_head - (cp_parser *, bool *, tree *, tree *); + (cp_parser *, bool *, tree *); static enum tag_types cp_parser_class_key (cp_parser *); static void cp_parser_member_specification_opt @@ -17908,7 +17908,6 @@ cp_parser_class_specifier_1 (cp_parser* parser) /* Parse the class-head. */ type = cp_parser_class_head (parser, &nested_name_specifier_p, - &attributes, &bases); /* If the class-head was a semantic disaster, skip the entire body of the class. */ @@ -17967,7 +17966,7 @@ cp_parser_class_specifier_1 (cp_parser* parser) scope = CP_DECL_CONTEXT (TYPE_MAIN_DECL (type)); old_scope = push_inner_scope (scope); } - type = begin_class_definition (type, attributes); + type = begin_class_definition (type); if (type == error_mark_node) /* If the type is erroneous, skip the entire body of the class. */ @@ -18224,7 +18223,6 @@ cp_parser_class_specifier (cp_parser* parser) static tree cp_parser_class_head (cp_parser* parser, bool* nested_name_specifier_p, - tree *attributes_p, tree *bases) { tree nested_name_specifier; @@ -18592,6 +18590,14 @@ cp_parser_class_head (cp_parser* parser, else if (type == error_mark_node) type = NULL_TREE; + if (type) + { + /* Apply attributes now, before any use of the class as a template + argument in its base list. */ + cplus_decl_attributes (&type, attributes, (int)ATTR_FLAG_TYPE_IN_PLACE); + fixup_attribute_variants (type); + } + /* We will have entered the scope containing the class; the names of base classes should be looked up in that context. For example: @@ -18618,7 +18624,6 @@ cp_parser_class_head (cp_parser* parser, if (type) DECL_SOURCE_LOCATION (TYPE_NAME (type)) = type_start_token->location; - *attributes_p = attributes; if (type && (virt_specifiers & VIRT_SPEC_FINAL)) CLASSTYPE_FINAL (type) = 1; out: diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 263ebc27668b..8fefce0d5abc 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2516,7 +2516,7 @@ check_template_template_default_arg (tree argument) /* Begin a class definition, as indicated by T. */ tree -begin_class_definition (tree t, tree attributes) +begin_class_definition (tree t) { if (error_operand_p (t) || error_operand_p (TYPE_MAIN_DECL (t))) return error_mark_node; @@ -2573,9 +2573,6 @@ begin_class_definition (tree t, tree attributes) pushclass (t); TYPE_BEING_DEFINED (t) = 1; - cplus_decl_attributes (&t, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE); - fixup_attribute_variants (t); - if (flag_pack_struct) { tree v; @@ -8696,7 +8693,7 @@ begin_lambda_type (tree lambda) xref_basetypes (type, /*bases=*/NULL_TREE); /* Start the class. */ - type = begin_class_definition (type, /*attributes=*/NULL_TREE); + type = begin_class_definition (type); if (type == error_mark_node) return error_mark_node; diff --git a/gcc/objcp/ChangeLog b/gcc/objcp/ChangeLog index bed3b9dcd25e..28b52e81237e 100644 --- a/gcc/objcp/ChangeLog +++ b/gcc/objcp/ChangeLog @@ -1,3 +1,8 @@ +2012-06-02 Jason Merrill + + * objcp-decl.c (objcp_start_struct): Adjust for change in + begin_class_definition prototype. + 2011-10-14 Nicola Pero * Make-lang.in (OBJCXX_OBJS): Added objc-map.o. diff --git a/gcc/objcp/objcp-decl.c b/gcc/objcp/objcp-decl.c index ecc2b2b3cbbd..80404695f99d 100644 --- a/gcc/objcp/objcp-decl.c +++ b/gcc/objcp/objcp-decl.c @@ -49,7 +49,7 @@ objcp_start_struct (location_t loc ATTRIBUTE_UNUSED, CLASSTYPE_DECLARED_CLASS (s) = 0; /* this is a 'struct', not a 'class'. */ xref_basetypes (s, NULL_TREE); /* no base classes here! */ - return begin_class_definition (s, NULL_TREE); + return begin_class_definition (s); } tree diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index dd1c651a3572..3d0b2497405b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2012-06-01 Jason Merrill + PR c++/52973 + * g++.dg/ext/visibility/template12.C: New. + * g++.dg/ext/attrib14.C: Adjust warning line. + PR c++/52725 * g++.dg/parse/new6.C: New. * g++.dg/template/sizeof-template-argument.C: Adjust error message. diff --git a/gcc/testsuite/g++.dg/ext/attrib14.C b/gcc/testsuite/g++.dg/ext/attrib14.C index c7e5f7a9fd97..ebe0456d04a8 100644 --- a/gcc/testsuite/g++.dg/ext/attrib14.C +++ b/gcc/testsuite/g++.dg/ext/attrib14.C @@ -2,8 +2,8 @@ // The bogus attribute is ignored, but was in TYPE_ATTRIBUTES during // parsing of the class, causing some variants to have it and some not. -struct __attribute__((bogus)) A -{ // { dg-warning "ignored" "" } +struct __attribute__((bogus)) A // { dg-warning "ignored" "" } +{ virtual ~A(); void foo(const A&); void bar(const A&); diff --git a/gcc/testsuite/g++.dg/ext/visibility/template12.C b/gcc/testsuite/g++.dg/ext/visibility/template12.C new file mode 100644 index 000000000000..b9219d528f98 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/visibility/template12.C @@ -0,0 +1,13 @@ +// { dg-require-visibility "" } +// { dg-options "-fvisibility=hidden" } +// { dg-final { scan-not-hidden "_ZN1aI1bE1cE" } } + +template class __attribute__((visibility("default"))) a +{ +public: + /* A */ static int c; +}; + +class __attribute__((visibility("default"))) b : a {}; + +template<> /* B */ int a::c = 0;