extend.texi (Attribute Syntax): Document that C++ labels on empty statements can...
authorIan Lance Taylor <iant@google.com>
Sun, 7 Jun 2009 06:39:04 +0000 (06:39 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Sun, 7 Jun 2009 06:39:04 +0000 (06:39 +0000)
./: * doc/extend.texi (Attribute Syntax): Document that C++ labels on
empty statements can now have attributes.
cp/:
* parser.c (cp_parser_label_for_labeled_statement): Support
attribute on labels if immediately followed by semicolon.
* semantics.c (finish_label_stmt): Return new label.
* pt.c (tsubst_expr): Handle attributes for LABEL_EXPR.
testsuite/:
* gcc.dg/Wunused-label-1.c: New test case.
* g++.dg/warn/Wunused-label-1.C: New test case.
* g++.dg/warn/Wunused-label-2.C: New test case.
* g++.dg/warn/Wunused-label-3.C: New test case.

From-SVN: r148242

gcc/ChangeLog
gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/doc/extend.texi
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/warn/Wunused-label-1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/warn/Wunused-label-2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/warn/Wunused-label-3.C [new file with mode: 0644]
gcc/testsuite/gcc.dg/Wunused-label-1.c [new file with mode: 0644]

index 7473556..c68945b 100644 (file)
@@ -1,3 +1,8 @@
+2009-06-06  Ian Lance Taylor  <iant@google.com>
+
+       * doc/extend.texi (Attribute Syntax): Document that C++ labels on
+       empty statements can now have attributes.
+
 2009-06-05  Shujing Zhao  <pearly.zhao@oracle.com>
 
        * config/mips/mips.c: Use REG_P and CONST_INT_P where applicable.
index bfd468b..200ce5a 100644 (file)
@@ -1,3 +1,10 @@
+2009-06-06  Ian Lance Taylor  <iant@google.com>
+
+       * parser.c (cp_parser_label_for_labeled_statement): Support
+       attribute on labels if immediately followed by semicolon.
+       * semantics.c (finish_label_stmt): Return new label.
+       * pt.c (tsubst_expr): Handle attributes for LABEL_EXPR.
+
 2009-06-03  Ian Lance Taylor  <iant@google.com>
 
        * Make-lang.in (cc1plus-checksum.o): Depend upon $(CONFIG_H) and
index e7d2e7d..00f2580 100644 (file)
@@ -7052,6 +7052,7 @@ static void
 cp_parser_label_for_labeled_statement (cp_parser* parser)
 {
   cp_token *token;
+  tree label = NULL_TREE;
 
   /* The next token should be an identifier.  */
   token = cp_lexer_peek_token (parser->lexer);
@@ -7111,12 +7112,34 @@ cp_parser_label_for_labeled_statement (cp_parser* parser)
 
     default:
       /* Anything else must be an ordinary label.  */
-      finish_label_stmt (cp_parser_identifier (parser));
+      label = finish_label_stmt (cp_parser_identifier (parser));
       break;
     }
 
   /* Require the `:' token.  */
   cp_parser_require (parser, CPP_COLON, "%<:%>");
+
+  /* An ordinary label may optionally be followed by attributes.
+     However, this is only permitted if the attributes are then
+     followed by a semicolon.  This is because, for backward
+     compatibility, when parsing
+       lab: __attribute__ ((unused)) int i;
+     we want the attribute to attach to "i", not "lab".  */
+  if (label != NULL_TREE
+      && cp_lexer_next_token_is_keyword (parser->lexer, RID_ATTRIBUTE))
+    {
+      tree attrs;
+
+      cp_parser_parse_tentatively (parser);
+      attrs = cp_parser_attributes_opt (parser);
+      if (attrs == NULL_TREE
+         || cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
+       cp_parser_abort_tentative_parse (parser);
+      else if (!cp_parser_parse_definitely (parser))
+       ;
+      else
+       cplus_decl_attributes (&label, attrs, 0);
+    }
 }
 
 /* Parse an expression-statement.
index 38e930b..91bd0d1 100644 (file)
@@ -10895,7 +10895,14 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
       break;
 
     case LABEL_EXPR:
-      finish_label_stmt (DECL_NAME (LABEL_EXPR_LABEL (t)));
+      {
+       tree decl = LABEL_EXPR_LABEL (t);
+       tree label;
+
+       label = finish_label_stmt (DECL_NAME (decl));
+       if (DECL_ATTRIBUTES (decl) != NULL_TREE)
+         cplus_decl_attributes (&label, DECL_ATTRIBUTES (decl), 0);
+      }
       break;
 
     case GOTO_EXPR:
index b37b322..adb6023 100644 (file)
@@ -1315,17 +1315,19 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands,
   return add_stmt (r);
 }
 
-/* Finish a label with the indicated NAME.  */
+/* Finish a label with the indicated NAME.  Returns the new label.  */
 
 tree
 finish_label_stmt (tree name)
 {
   tree decl = define_label (input_location, name);
 
-  if (decl  == error_mark_node)
+  if (decl == error_mark_node)
     return error_mark_node;
 
-  return add_stmt (build_stmt (LABEL_EXPR, decl));
+  add_stmt (build_stmt (LABEL_EXPR, decl));
+
+  return decl;
 }
 
 /* Finish a series of declarations for local labels.  G++ allows users
index 98df9d5..df900fd 100644 (file)
@@ -3440,11 +3440,13 @@ feature is intended for code generated by programs which contains labels
 that may be unused but which is compiled with @option{-Wall}.  It would
 not normally be appropriate to use in it human-written code, though it
 could be useful in cases where the code that jumps to the label is
-contained within an @code{#ifdef} conditional.  GNU C++ does not permit
-such placement of attribute lists, as it is permissible for a
-declaration, which could begin with an attribute list, to be labelled in
-C++.  Declarations cannot be labelled in C90 or C99, so the ambiguity
-does not arise there.
+contained within an @code{#ifdef} conditional.  GNU C++ only permits
+attributes on labels if the attribute specifier is immediately
+followed by a semicolon (i.e., the label applies to an empty
+statement).  If the semicolon is missing, C++ label attributes are
+ambiguous, as it is permissible for a declaration, which could begin
+with an attribute list, to be labelled in C++.  Declarations cannot be
+labelled in C90 or C99, so the ambiguity does not arise there.
 
 An attribute specifier list may appear as part of a @code{struct},
 @code{union} or @code{enum} specifier.  It may go either immediately
index 6b87e85..8f4a6d7 100644 (file)
@@ -1,3 +1,10 @@
+2009-06-06  Ian Lance Taylor  <iant@google.com>
+
+       * gcc.dg/Wunused-label-1.c: New test case.
+       * g++.dg/warn/Wunused-label-1.C: New test case.
+       * g++.dg/warn/Wunused-label-2.C: New test case.
+       * g++.dg/warn/Wunused-label-3.C: New test case.
+
 2009-06-06  Daniel Franke  <franke.daniel@gmail.com>
 
        PR fortran/37203
diff --git a/gcc/testsuite/g++.dg/warn/Wunused-label-1.C b/gcc/testsuite/g++.dg/warn/Wunused-label-1.C
new file mode 100644 (file)
index 0000000..96f49b3
--- /dev/null
@@ -0,0 +1,28 @@
+// { dg-do compile }
+// { dg-options "-Wunused-label" }
+
+extern void f9();
+
+void
+f1()
+{
+ l1: f9();                             // { dg-warning "not used" }
+ l3: ; f9();                           // { dg-warning "not used" }
+ l4: __attribute__ ((unused)) ; f9();
+}
+
+void
+f2()
+{
+ label: __attribute ((unused)) ;
+}
+
+void
+f3()
+{
+  // The next line would be OK in C but is a syntax error in C++.
+ l2: __attribute__ ((unused)) f9();    // { dg-error "expected" }
+               // We still get an unused label warning--this is
+               // optional and can be removed if it ever changes.
+               // { dg-warning "not used" "expected" { target *-*-* } 24 }
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wunused-label-2.C b/gcc/testsuite/g++.dg/warn/Wunused-label-2.C
new file mode 100644 (file)
index 0000000..a53fded
--- /dev/null
@@ -0,0 +1,13 @@
+// { dg-do compile }
+// { dg-options "-Wunused" }
+
+// If __attribute__ ((unused)) follows a label and precedes a
+// declaration, we should get a warning for the label, not the
+// declaration.
+
+void
+f1()
+{
+  int i1;                              // { dg-warning "unused variable" }
+ l1: __attribute__ ((unused)) int i2;  // { dg-warning "label \[^\n\]* not used" }
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wunused-label-3.C b/gcc/testsuite/g++.dg/warn/Wunused-label-3.C
new file mode 100644 (file)
index 0000000..7479ca2
--- /dev/null
@@ -0,0 +1,51 @@
+// { dg-do compile }
+// { dg-options "-Wunused-label" }
+
+extern void f9();
+
+template<int i>
+void
+f1()
+{
+  if (i)
+    return;
+
+ l1: f9();                             // { dg-warning "not used" }
+ l3: ; f9();                           // { dg-warning "not used" }
+ l4: __attribute__ ((unused)) ; f9();
+}
+
+template
+void f1<0>();
+
+template<int i>
+void
+f2()
+{
+  if (i)
+    return;
+
+ l1: f9();                             // { dg-warning "not used" }
+ l3: ; f9();                           // { dg-warning "not used" }
+ l4: __attribute__ ((unused)) ; f9();
+}
+
+template
+void f2<1>();
+
+template<int i>
+void
+f3()
+{
+  void* lab;
+ l1: f9();
+ l2: __attribute__ ((unused)) ; f9();
+  lab = i ? &&l1 : &&l2;
+  goto *lab;
+}
+
+template
+void f3<0>();
+
+template
+void f3<1>();
diff --git a/gcc/testsuite/gcc.dg/Wunused-label-1.c b/gcc/testsuite/gcc.dg/Wunused-label-1.c
new file mode 100644 (file)
index 0000000..1840a80
--- /dev/null
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-Wunused-label" } */
+
+extern void f2 ();
+
+void
+f1 ()
+{
+ l1: f2 ();                            /* { dg-warning "not used" } */
+ l2: __attribute__ ((unused)) f2 ();
+ l3: ; f2 ();                          /* { dg-warning "not used" } */
+ l4: __attribute__ ((unused)) ; f2 ();
+}