aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2009-06-07 06:39:04 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2009-06-07 06:39:04 +0000
commit5bca4e800bc5a61148a74c4656b274155275f9fc (patch)
treed6bdaa5091ac13eeb83382f918486bf5eb98b1f4 /gcc
parent712b30cf6f380ea918f78d4ec208093df3566982 (diff)
downloadgcc-5bca4e800bc5a61148a74c4656b274155275f9fc.zip
gcc-5bca4e800bc5a61148a74c4656b274155275f9fc.tar.gz
gcc-5bca4e800bc5a61148a74c4656b274155275f9fc.tar.bz2
extend.texi (Attribute Syntax): Document that C++ labels on empty statements can now have attributes.
./: * 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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/parser.c25
-rw-r--r--gcc/cp/pt.c9
-rw-r--r--gcc/cp/semantics.c8
-rw-r--r--gcc/doc/extend.texi12
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/g++.dg/warn/Wunused-label-1.C28
-rw-r--r--gcc/testsuite/g++.dg/warn/Wunused-label-2.C13
-rw-r--r--gcc/testsuite/g++.dg/warn/Wunused-label-3.C51
-rw-r--r--gcc/testsuite/gcc.dg/Wunused-label-1.c13
11 files changed, 168 insertions, 10 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7473556..c68945b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index bfd468b..200ce5a 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index e7d2e7d..00f2580 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -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.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 38e930b..91bd0d1 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -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:
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index b37b322..adb6023 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -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
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 98df9d5..df900fd 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 6b87e85..8f4a6d7 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..96f49b3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wunused-label-1.C
@@ -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
index 0000000..a53fded
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wunused-label-2.C
@@ -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
index 0000000..7479ca2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wunused-label-3.C
@@ -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
index 0000000..1840a80
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wunused-label-1.c
@@ -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 ();
+}