diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 21 | ||||
-rw-r--r-- | gcc/c-common.c | 1 | ||||
-rw-r--r-- | gcc/c-parser.c | 187 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/c1x-static-assert-1.c | 41 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/c1x-static-assert-2.c | 41 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/c1x-static-assert-3.c | 28 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/c1x-static-assert-4.c | 13 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/c1x-static-assert-5.c | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/c1x-static-assert-6.c | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/c90-static-assert-1.c | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/c99-static-assert-1.c | 5 |
12 files changed, 335 insertions, 25 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f3e8312..94cb08b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,24 @@ +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, diff --git a/gcc/c-common.c b/gcc/c-common.c index 720569f..942961d 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -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 }, diff --git a/gcc/c-parser.c b/gcc/c-parser.c index ea97778..dc3f26e 100644 --- a/gcc/c-parser.c +++ b/gcc/c-parser.c @@ -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; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8b25528..64242be 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +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. diff --git a/gcc/testsuite/gcc.dg/c1x-static-assert-1.c b/gcc/testsuite/gcc.dg/c1x-static-assert-1.c new file mode 100644 index 0000000..bf7aa59 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c1x-static-assert-1.c @@ -0,0 +1,41 @@ +/* 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++) + ; +} diff --git a/gcc/testsuite/gcc.dg/c1x-static-assert-2.c b/gcc/testsuite/gcc.dg/c1x-static-assert-2.c new file mode 100644 index 0000000..9a48ca7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c1x-static-assert-2.c @@ -0,0 +1,41 @@ +/* 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\"" } */ + ; +} diff --git a/gcc/testsuite/gcc.dg/c1x-static-assert-3.c b/gcc/testsuite/gcc.dg/c1x-static-assert-3.c new file mode 100644 index 0000000..81b504e --- /dev/null +++ b/gcc/testsuite/gcc.dg/c1x-static-assert-3.c @@ -0,0 +1,28 @@ +/* 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" } */ diff --git a/gcc/testsuite/gcc.dg/c1x-static-assert-4.c b/gcc/testsuite/gcc.dg/c1x-static-assert-4.c new file mode 100644 index 0000000..ebc95f5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c1x-static-assert-4.c @@ -0,0 +1,13 @@ +/* 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" } */ +{ +} diff --git a/gcc/testsuite/gcc.dg/c1x-static-assert-5.c b/gcc/testsuite/gcc.dg/c1x-static-assert-5.c new file mode 100644 index 0000000..d4d0821 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c1x-static-assert-5.c @@ -0,0 +1,5 @@ +/* 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"); diff --git a/gcc/testsuite/gcc.dg/c1x-static-assert-6.c b/gcc/testsuite/gcc.dg/c1x-static-assert-6.c new file mode 100644 index 0000000..c544cad --- /dev/null +++ b/gcc/testsuite/gcc.dg/c1x-static-assert-6.c @@ -0,0 +1,5 @@ +/* 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" } */ diff --git a/gcc/testsuite/gcc.dg/c90-static-assert-1.c b/gcc/testsuite/gcc.dg/c90-static-assert-1.c new file mode 100644 index 0000000..d174ec9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c90-static-assert-1.c @@ -0,0 +1,5 @@ +/* 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'" } */ diff --git a/gcc/testsuite/gcc.dg/c99-static-assert-1.c b/gcc/testsuite/gcc.dg/c99-static-assert-1.c new file mode 100644 index 0000000..2347736 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c99-static-assert-1.c @@ -0,0 +1,5 @@ +/* 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'" } */ |