PR c++/52973
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 2 Jun 2012 04:03:51 +0000 (04:03 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 2 Jun 2012 04:03:51 +0000 (04:03 +0000)
* parser.c (cp_parser_class_head): Apply attributes here.
* semantics.c (begin_class_definition): Not here.
* cp-tree.h: Adjust.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@188137 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/parser.c
gcc/cp/semantics.c
gcc/objcp/ChangeLog
gcc/objcp/objcp-decl.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ext/attrib14.C
gcc/testsuite/g++.dg/ext/visibility/template12.C [new file with mode: 0644]

index ba5937a..b094504 100644 (file)
@@ -1,5 +1,10 @@
 2012-06-01  Jason Merrill  <jason@redhat.com>
 
+       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.
index 626c61f..d21c2bf 100644 (file)
@@ -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);
index 7f9a94b..16139d6 100644 (file)
@@ -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:
index 263ebc2..8fefce0 100644 (file)
@@ -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;
 
index bed3b9d..28b52e8 100644 (file)
@@ -1,3 +1,8 @@
+2012-06-02  Jason Merrill  <jason@redhat.com>
+
+       * objcp-decl.c (objcp_start_struct): Adjust for change in
+       begin_class_definition prototype.
+
 2011-10-14  Nicola Pero  <nicola.pero@meta-innovation.com>
 
        * Make-lang.in (OBJCXX_OBJS): Added objc-map.o.
index ecc2b2b..8040469 100644 (file)
@@ -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 
index dd1c651..3d0b249 100644 (file)
@@ -1,5 +1,9 @@
 2012-06-01  Jason Merrill  <jason@redhat.com>
 
+       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.
index c7e5f7a..ebe0456 100644 (file)
@@ -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 (file)
index 0000000..b9219d5
--- /dev/null
@@ -0,0 +1,13 @@
+// { dg-require-visibility "" }
+// { dg-options "-fvisibility=hidden" }
+// { dg-final { scan-not-hidden "_ZN1aI1bE1cE" } }
+
+template <class T> class __attribute__((visibility("default"))) a
+{
+public:
+  /* A */ static int c;
+};
+
+class __attribute__((visibility("default"))) b : a <b> {};
+
+template<> /* B */ int a<b>::c = 0;