Commit 5bca4e80 by Ian Lance Taylor Committed by Ian Lance Taylor

extend.texi (Attribute Syntax): Document that C++ labels on empty statements can…

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
parent 712b30cf
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.
......
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
......
......@@ -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.
......
......@@ -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:
......
......@@ -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
......
......@@ -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
......
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
......
// { 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 }
}
// { 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" }
}
// { 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>();
/* { 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 ();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment