Commit 32912286 by Joseph Myers Committed by Joseph Myers

c-common.c (c_common_reswords): Add _Static_assert for C.

	* c-common.c (c_common_reswords): Add _Static_assert for C.
	* c-parser.c (c_token_starts_declaration,
	c_parser_next_token_starts_declaration,
	c_parser_static_assert_declaration_no_semi,
	c_parser_static_assert_declaration): New.
	(c_parser_declaration_or_fndef): Add parameter static_assert_ok.
	Handle static assertions if static_assert_ok.
	(c_parser_external_declaration, c_parser_declaration_or_fndef,
	c_parser_compound_statement_nostart, c_parser_label,
	c_parser_for_statement, c_parser_objc_methodprotolist,
	c_parser_omp_for_loop): All callers of
	c_parser_declaration_or_fndef changed.
	(c_parser_struct_declaration): Handle static assertions.
	(c_parser_compound_statement_nostart): Use
	c_parser_next_token_starts_declaration and
	c_token_starts_declaration to detect start of declarations.
	(c_parser_label, c_parser_for_statement, c_parser_omp_for_loop):
	Likewise.

testsuite:
	* gcc.dg/c1x-static-assert-1.c, gcc.dg/c1x-static-assert-2.c,
	gcc.dg/c1x-static-assert-3.c, gcc.dg/c1x-static-assert-4.c,
	gcc.dg/c1x-static-assert-5.c, gcc.dg/c1x-static-assert-6.c,
	gcc.dg/c90-static-assert-1.c, gcc.dg/c99-static-assert-1.c: New
	tests.

From-SVN: r159459
parent a3ca07e3
2010-05-16 Joseph Myers <joseph@codesourcery.com>
* c-common.c (c_common_reswords): Add _Static_assert for C.
* c-parser.c (c_token_starts_declaration,
c_parser_next_token_starts_declaration,
c_parser_static_assert_declaration_no_semi,
c_parser_static_assert_declaration): New.
(c_parser_declaration_or_fndef): Add parameter static_assert_ok.
Handle static assertions if static_assert_ok.
(c_parser_external_declaration, c_parser_declaration_or_fndef,
c_parser_compound_statement_nostart, c_parser_label,
c_parser_for_statement, c_parser_objc_methodprotolist,
c_parser_omp_for_loop): All callers of
c_parser_declaration_or_fndef changed.
(c_parser_struct_declaration): Handle static assertions.
(c_parser_compound_statement_nostart): Use
c_parser_next_token_starts_declaration and
c_token_starts_declaration to detect start of declarations.
(c_parser_label, c_parser_for_statement, c_parser_omp_for_loop):
Likewise.
2010-05-16 Anatoly Sokolov <aesok@post.ru>
* config/mmix/mmix.h (FUNCTION_VALUE, FUNCTION_OUTGOING_VALUE,
......
......@@ -563,6 +563,7 @@ const struct c_common_resword c_common_reswords[] =
{ "_Fract", RID_FRACT, D_CONLY | D_EXT },
{ "_Accum", RID_ACCUM, D_CONLY | D_EXT },
{ "_Sat", RID_SAT, D_CONLY | D_EXT },
{ "_Static_assert", RID_STATIC_ASSERT, D_CONLY },
{ "__FUNCTION__", RID_FUNCTION_NAME, 0 },
{ "__PRETTY_FUNCTION__", RID_PRETTY_FUNCTION_NAME, 0 },
{ "__alignof", RID_ALIGNOF, 0 },
......
......@@ -494,6 +494,19 @@ c_token_starts_declspecs (c_token *token)
}
}
/* Return true if TOKEN can start declaration specifiers or a static
assertion, false otherwise. */
static bool
c_token_starts_declaration (c_token *token)
{
if (c_token_starts_declspecs (token)
|| token->keyword == RID_STATIC_ASSERT)
return true;
else
return false;
}
/* Return true if the next token from PARSER can start declaration
specifiers, false otherwise. */
static inline bool
......@@ -503,6 +516,15 @@ c_parser_next_token_starts_declspecs (c_parser *parser)
return c_token_starts_declspecs (token);
}
/* Return true if the next token from PARSER can start declaration
specifiers or a static assertion, false otherwise. */
static inline bool
c_parser_next_token_starts_declaration (c_parser *parser)
{
c_token *token = c_parser_peek_token (parser);
return c_token_starts_declaration (token);
}
/* Return a pointer to the next-but-one token from PARSER, reading it
in if necessary. The next token is already read in. */
......@@ -883,7 +905,10 @@ typedef enum c_dtr_syn {
static void c_parser_external_declaration (c_parser *);
static void c_parser_asm_definition (c_parser *);
static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool, bool);
static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool,
bool, bool);
static void c_parser_static_assert_declaration_no_semi (c_parser *);
static void c_parser_static_assert_declaration (c_parser *);
static void c_parser_declspecs (c_parser *, struct c_declspecs *, bool, bool,
bool);
static struct c_typespec c_parser_enum_specifier (c_parser *);
......@@ -1101,7 +1126,7 @@ c_parser_external_declaration (c_parser *parser)
/* A declaration or a function definition. We can only tell
which after parsing the declaration specifiers, if any, and
the first declarator. */
c_parser_declaration_or_fndef (parser, true, true, false, true);
c_parser_declaration_or_fndef (parser, true, true, true, false, true);
break;
}
}
......@@ -1110,18 +1135,21 @@ c_parser_external_declaration (c_parser *parser)
/* Parse a declaration or function definition (C90 6.5, 6.7.1, C99
6.7, 6.9.1). If FNDEF_OK is true, a function definition is
accepted; otherwise (old-style parameter declarations) only other
declarations are accepted. If NESTED is true, we are inside a
function or parsing old-style parameter declarations; any functions
encountered are nested functions and declaration specifiers are
required; otherwise we are at top level and functions are normal
functions and declaration specifiers may be optional. If EMPTY_OK
is true, empty declarations are OK (subject to all other
constraints); otherwise (old-style parameter declarations) they are
diagnosed. If START_ATTR_OK is true, the declaration specifiers
may start with attributes; otherwise they may not.
declarations are accepted. If STATIC_ASSERT_OK is true, a static
assertion is accepted; otherwise (old-style parameter declarations)
it is not. If NESTED is true, we are inside a function or parsing
old-style parameter declarations; any functions encountered are
nested functions and declaration specifiers are required; otherwise
we are at top level and functions are normal functions and
declaration specifiers may be optional. If EMPTY_OK is true, empty
declarations are OK (subject to all other constraints); otherwise
(old-style parameter declarations) they are diagnosed. If
START_ATTR_OK is true, the declaration specifiers may start with
attributes; otherwise they may not.
declaration:
declaration-specifiers init-declarator-list[opt] ;
static_assert-declaration
function-definition:
declaration-specifiers[opt] declarator declaration-list[opt]
......@@ -1165,7 +1193,8 @@ c_parser_external_declaration (c_parser *parser)
threadprivate-directive */
static void
c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
bool static_assert_ok, bool empty_ok,
bool nested, bool start_attr_ok)
{
struct c_declspecs *specs;
......@@ -1174,6 +1203,12 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
bool diagnosed_no_specs = false;
location_t here = c_parser_peek_token (parser)->location;
if (static_assert_ok
&& c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
{
c_parser_static_assert_declaration (parser);
return;
}
specs = build_null_declspecs ();
c_parser_declspecs (parser, specs, true, true, start_attr_ok);
if (parser->error)
......@@ -1332,7 +1367,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
function definitions either. */
while (c_parser_next_token_is_not (parser, CPP_EOF)
&& c_parser_next_token_is_not (parser, CPP_OPEN_BRACE))
c_parser_declaration_or_fndef (parser, false, false, true, false);
c_parser_declaration_or_fndef (parser, false, false, false,
true, false);
store_parm_decls ();
DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus
= c_parser_peek_token (parser)->location;
......@@ -1375,6 +1411,97 @@ c_parser_asm_definition (c_parser *parser)
c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
}
/* Parse a static assertion (C1X N1425 6.7.10).
static_assert-declaration:
static_assert-declaration-no-semi ;
*/
static void
c_parser_static_assert_declaration (c_parser *parser)
{
c_parser_static_assert_declaration_no_semi (parser);
if (parser->error
|| !c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
c_parser_skip_to_end_of_block_or_statement (parser);
}
/* Parse a static assertion (C1X N1425 6.7.10), without the trailing
semicolon.
static_assert-declaration-no-semi:
_Static_assert ( constant-expression , string-literal )
*/
static void
c_parser_static_assert_declaration_no_semi (c_parser *parser)
{
location_t assert_loc, value_loc;
tree value;
tree string;
gcc_assert (c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT));
assert_loc = c_parser_peek_token (parser)->location;
if (!flag_isoc1x)
{
if (flag_isoc99)
pedwarn (assert_loc, OPT_pedantic,
"ISO C99 does not support %<_Static_assert%>");
else
pedwarn (assert_loc, OPT_pedantic,
"ISO C90 does not support %<_Static_assert%>");
}
c_parser_consume_token (parser);
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
return;
value_loc = c_parser_peek_token (parser)->location;
value = c_parser_expr_no_commas (parser, NULL).value;
parser->lex_untranslated_string = true;
if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
{
parser->lex_untranslated_string = false;
return;
}
switch (c_parser_peek_token (parser)->type)
{
case CPP_STRING:
case CPP_STRING16:
case CPP_STRING32:
case CPP_WSTRING:
case CPP_UTF8STRING:
string = c_parser_peek_token (parser)->value;
c_parser_consume_token (parser);
parser->lex_untranslated_string = false;
break;
default:
c_parser_error (parser, "expected string literal");
parser->lex_untranslated_string = false;
return;
}
c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>");
if (!INTEGRAL_TYPE_P (TREE_TYPE (value)))
{
error_at (value_loc, "expression in static assertion is not an integer");
return;
}
if (TREE_CODE (value) != INTEGER_CST)
{
value = c_fully_fold (value, false, NULL);
if (TREE_CODE (value) == INTEGER_CST)
pedwarn (value_loc, OPT_pedantic, "expression in static assertion "
"is not an integer constant expression");
}
if (TREE_CODE (value) != INTEGER_CST)
{
error_at (value_loc, "expression in static assertion is not constant");
return;
}
constant_expression_warning (value);
if (integer_zerop (value))
error_at (assert_loc, "static assertion failed: %E", string);
}
/* Parse some declaration specifiers (possibly none) (C90 6.5, C99
6.7), adding them to SPECS (which may already include some).
Storage class specifiers are accepted iff SCSPEC_OK; type
......@@ -1973,6 +2100,7 @@ c_parser_struct_or_union_specifier (c_parser *parser)
struct-declaration:
specifier-qualifier-list struct-declarator-list
static_assert-declaration-no-semi
specifier-qualifier-list:
type-specifier specifier-qualifier-list[opt]
......@@ -2017,6 +2145,11 @@ c_parser_struct_declaration (c_parser *parser)
restore_extension_diagnostics (ext);
return decl;
}
if (c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
{
c_parser_static_assert_declaration_no_semi (parser);
return NULL_TREE;
}
specs = build_null_declspecs ();
decl_loc = c_parser_peek_token (parser)->location;
c_parser_declspecs (parser, specs, false, true, true);
......@@ -3505,11 +3638,11 @@ c_parser_compound_statement_nostart (c_parser *parser)
c_parser_label (parser);
}
else if (!last_label
&& c_parser_next_token_starts_declspecs (parser))
&& c_parser_next_token_starts_declaration (parser))
{
last_label = false;
mark_valid_location_for_stdc_pragma (false);
c_parser_declaration_or_fndef (parser, true, true, true, true);
c_parser_declaration_or_fndef (parser, true, true, true, true, true);
if (last_stmt)
pedwarn_c90 (loc,
(pedantic && !flag_isoc99)
......@@ -3529,14 +3662,15 @@ c_parser_compound_statement_nostart (c_parser *parser)
&& (c_parser_peek_2nd_token (parser)->keyword
== RID_EXTENSION))
c_parser_consume_token (parser);
if (c_token_starts_declspecs (c_parser_peek_2nd_token (parser)))
if (c_token_starts_declaration (c_parser_peek_2nd_token (parser)))
{
int ext;
ext = disable_extension_diagnostics ();
c_parser_consume_token (parser);
last_label = false;
mark_valid_location_for_stdc_pragma (false);
c_parser_declaration_or_fndef (parser, true, true, true, true);
c_parser_declaration_or_fndef (parser, true, true, true, true,
true);
/* Following the old parser, __extension__ does not
disable this diagnostic. */
restore_extension_diagnostics (ext);
......@@ -3666,7 +3800,7 @@ c_parser_label (c_parser *parser)
}
if (label)
{
if (c_parser_next_token_starts_declspecs (parser)
if (c_parser_next_token_starts_declaration (parser)
&& !(c_parser_next_token_is (parser, CPP_NAME)
&& c_parser_peek_2nd_token (parser)->type == CPP_COLON))
{
......@@ -3674,6 +3808,7 @@ c_parser_label (c_parser *parser)
"a label can only be part of a statement and "
"a declaration is not a statement");
c_parser_declaration_or_fndef (parser, /*fndef_ok*/ false,
/*static_assert_ok*/ true,
/*nested*/ true, /*empty_ok*/ false,
/*start_attr_ok*/ true);
}
......@@ -4210,9 +4345,9 @@ c_parser_for_statement (c_parser *parser)
c_parser_consume_token (parser);
c_finish_expr_stmt (loc, NULL_TREE);
}
else if (c_parser_next_token_starts_declspecs (parser))
else if (c_parser_next_token_starts_declaration (parser))
{
c_parser_declaration_or_fndef (parser, true, true, true, true);
c_parser_declaration_or_fndef (parser, true, true, true, true, true);
check_for_loop_decls (for_loc);
}
else if (c_parser_next_token_is_keyword (parser, RID_EXTENSION))
......@@ -4225,12 +4360,13 @@ c_parser_for_statement (c_parser *parser)
&& (c_parser_peek_2nd_token (parser)->keyword
== RID_EXTENSION))
c_parser_consume_token (parser);
if (c_token_starts_declspecs (c_parser_peek_2nd_token (parser)))
if (c_token_starts_declaration (c_parser_peek_2nd_token (parser)))
{
int ext;
ext = disable_extension_diagnostics ();
c_parser_consume_token (parser);
c_parser_declaration_or_fndef (parser, true, true, true, true);
c_parser_declaration_or_fndef (parser, true, true, true, true,
true);
restore_extension_diagnostics (ext);
check_for_loop_decls (for_loc);
}
......@@ -6518,7 +6654,8 @@ c_parser_objc_methodprotolist (c_parser *parser)
default:
if (c_parser_next_token_is_keyword (parser, RID_AT_END))
return;
c_parser_declaration_or_fndef (parser, false, true, false, true);
c_parser_declaration_or_fndef (parser, false, false, true,
false, true);
break;
}
}
......@@ -8039,12 +8176,12 @@ c_parser_omp_for_loop (location_t loc,
goto pop_scopes;
/* Parse the initialization declaration or expression. */
if (c_parser_next_token_starts_declspecs (parser))
if (c_parser_next_token_starts_declaration (parser))
{
if (i > 0)
for_block
= tree_cons (NULL, c_begin_compound_stmt (true), for_block);
c_parser_declaration_or_fndef (parser, true, true, true, true);
c_parser_declaration_or_fndef (parser, true, true, true, true, true);
decl = check_for_loop_decls (for_loc);
if (decl == NULL)
goto error_init;
......
2010-05-16 Joseph Myers <joseph@codesourcery.com>
* gcc.dg/c1x-static-assert-1.c, gcc.dg/c1x-static-assert-2.c,
gcc.dg/c1x-static-assert-3.c, gcc.dg/c1x-static-assert-4.c,
gcc.dg/c1x-static-assert-5.c, gcc.dg/c1x-static-assert-6.c,
gcc.dg/c90-static-assert-1.c, gcc.dg/c99-static-assert-1.c: New
tests.
2010-05-15 Jason Merrill <jason@redhat.com>
* g++.dg/eh/spec10.C: New.
......
/* Test C1X static assertions. Valid assertions. */
/* { dg-do compile } */
/* { dg-options "-std=c1x -pedantic-errors" } */
_Static_assert (1, "foo");
enum e { E0, E1 };
_Static_assert (E1, L"bar");
_Static_assert (-1, "foo" L"bar");
struct s
{
int a;
_Static_assert (3, "s");
int b;
};
union u
{
int i;
_Static_assert ((int)1.0, L"");
};
void
f (void)
{
int i;
i = 1;
_Static_assert (0 + 1, "f");
i = 2;
}
void
g (void)
{
int i = 0;
for (_Static_assert (1, ""); i < 10; i++)
;
}
/* Test C1X static assertions. Failed assertions. */
/* { dg-do compile } */
/* { dg-options "-std=c1x -pedantic-errors" } */
_Static_assert (0, "assert1"); /* { dg-error "static assertion failed: \"assert1\"" } */
enum e { E0, E1 };
_Static_assert (E0, L"assert2"); /* { dg-error "static assertion failed: \"assert2\"" } */
_Static_assert (-0, "ass" L"ert3"); /* { dg-error "static assertion failed: \"assert3\"" } */
struct s
{
int a;
_Static_assert (0, "assert4"); /* { dg-error "static assertion failed: \"assert4\"" } */
int b;
};
union u
{
int i;
_Static_assert ((int)0.0, L"assert5"); /* { dg-error "static assertion failed: \"assert5\"" } */
};
void
f (void)
{
int i;
i = 1;
_Static_assert (0 + 0, "assert6"); /* { dg-error "static assertion failed: \"assert6\"" } */
i = 2;
}
void
g (void)
{
int i = 0;
for (_Static_assert (0, "assert7"); i < 10; i++) /* { dg-error "static assertion failed: \"assert7\"" } */
;
}
/* Test C1X static assertions. Invalid assertions. */
/* { dg-do compile } */
/* { dg-options "-std=c1x -pedantic-errors" } */
_Static_assert (__INT_MAX__ * 2, "overflow"); /* { dg-warning "integer overflow in expression" } */
/* { dg-error "overflow in constant expression" "error" { target *-*-* } 5 } */
_Static_assert ((void *)(__SIZE_TYPE__)16, "non-integer"); /* { dg-error "not an integer" } */
_Static_assert (1.0, "non-integer"); /* { dg-error "not an integer" } */
_Static_assert ((int)(1.0 + 1.0), "non-constant-expression"); /* { dg-error "not an integer constant expression" } */
int i;
_Static_assert (i, "non-constant"); /* { dg-error "not constant" } */
void
f (void)
{
int j = 0;
for (_Static_assert (sizeof (struct s { int k; }), ""); j < 10; j++) /* { dg-error "loop initial declaration" } */
;
}
_Static_assert (1, 1); /* { dg-error "expected" } */
_Static_assert (1, ("")); /* { dg-error "expected" } */
/* Test C1X static assertions. More invalid assertions. */
/* { dg-do compile } */
/* { dg-options "-std=c1x -pedantic-errors" } */
/* Static assertions not valid in old-style parameter declarations
because declarations there must have declarators. */
void
f (i)
int i;
_Static_assert (1, ""); /* { dg-error "expected" } */
{
}
/* Test C1X static assertions. Non-constant-expression without -pedantic. */
/* { dg-do compile } */
/* { dg-options "-std=c1x" } */
_Static_assert ((int)(1.0 + 1.0), "non-constant-expression");
/* Test C1X static assertions. Non-constant-expression with -pedantic. */
/* { dg-do compile } */
/* { dg-options "-std=c1x -pedantic" } */
_Static_assert ((int)(1.0 + 1.0), "non-constant-expression"); /* { dg-warning "not an integer constant expression" } */
/* Test for static assertions not in C90. */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1990 -pedantic-errors" } */
_Static_assert (1, ""); /* { dg-error "ISO C90 does not support '_Static_assert'" } */
/* Test for static assertions not in C99. */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1999 -pedantic-errors" } */
_Static_assert (1, ""); /* { dg-error "ISO C99 does not support '_Static_assert'" } */
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