diff options
author | Ian Lance Taylor <iant@google.com> | 2009-06-07 06:39:04 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2009-06-07 06:39:04 +0000 |
commit | 5bca4e800bc5a61148a74c4656b274155275f9fc (patch) | |
tree | d6bdaa5091ac13eeb83382f918486bf5eb98b1f4 /gcc | |
parent | 712b30cf6f380ea918f78d4ec208093df3566982 (diff) | |
download | gcc-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/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/cp/parser.c | 25 | ||||
-rw-r--r-- | gcc/cp/pt.c | 9 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 8 | ||||
-rw-r--r-- | gcc/doc/extend.texi | 12 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/warn/Wunused-label-1.C | 28 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/warn/Wunused-label-2.C | 13 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/warn/Wunused-label-3.C | 51 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/Wunused-label-1.c | 13 |
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 (); +} |