This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C1X static assertions patch


This patch adds support for C1X _Static_assert to GCC.  (The C1X
static assertions changes also include a macro static_assert in
<assert.h>, but that's the responsibility of the library not of GCC.)

As with other cases where integer constant expressions are required,
this implementation will pedwarn-if-pedantic for something this is not
an integer constant expression but folds to an integer constant.

Unlike C++0x, it appears that C1X allows a static assertion as the
declaration in a "for" loop, so that is allowed by this
implementation.

Bootstrapped with no regressions on x86_64-unknown-linux-gnu.  Applied
to mainline.

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.

testsuite:
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.

Index: gcc/testsuite/gcc.dg/c1x-static-assert-1.c
===================================================================
--- gcc/testsuite/gcc.dg/c1x-static-assert-1.c	(revision 0)
+++ gcc/testsuite/gcc.dg/c1x-static-assert-1.c	(revision 0)
@@ -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++)
+    ;
+}
Index: gcc/testsuite/gcc.dg/c90-static-assert-1.c
===================================================================
--- gcc/testsuite/gcc.dg/c90-static-assert-1.c	(revision 0)
+++ gcc/testsuite/gcc.dg/c90-static-assert-1.c	(revision 0)
@@ -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'" } */
Index: gcc/testsuite/gcc.dg/c1x-static-assert-5.c
===================================================================
--- gcc/testsuite/gcc.dg/c1x-static-assert-5.c	(revision 0)
+++ gcc/testsuite/gcc.dg/c1x-static-assert-5.c	(revision 0)
@@ -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");
Index: gcc/testsuite/gcc.dg/c1x-static-assert-2.c
===================================================================
--- gcc/testsuite/gcc.dg/c1x-static-assert-2.c	(revision 0)
+++ gcc/testsuite/gcc.dg/c1x-static-assert-2.c	(revision 0)
@@ -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\"" } */
+    ;
+}
Index: gcc/testsuite/gcc.dg/c1x-static-assert-6.c
===================================================================
--- gcc/testsuite/gcc.dg/c1x-static-assert-6.c	(revision 0)
+++ gcc/testsuite/gcc.dg/c1x-static-assert-6.c	(revision 0)
@@ -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" } */
Index: gcc/testsuite/gcc.dg/c1x-static-assert-3.c
===================================================================
--- gcc/testsuite/gcc.dg/c1x-static-assert-3.c	(revision 0)
+++ gcc/testsuite/gcc.dg/c1x-static-assert-3.c	(revision 0)
@@ -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" } */
Index: gcc/testsuite/gcc.dg/c99-static-assert-1.c
===================================================================
--- gcc/testsuite/gcc.dg/c99-static-assert-1.c	(revision 0)
+++ gcc/testsuite/gcc.dg/c99-static-assert-1.c	(revision 0)
@@ -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'" } */
Index: gcc/testsuite/gcc.dg/c1x-static-assert-4.c
===================================================================
--- gcc/testsuite/gcc.dg/c1x-static-assert-4.c	(revision 0)
+++ gcc/testsuite/gcc.dg/c1x-static-assert-4.c	(revision 0)
@@ -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" } */
+{
+}
Index: gcc/c-common.c
===================================================================
--- gcc/c-common.c	(revision 159439)
+++ gcc/c-common.c	(working copy)
@@ -564,6 +564,7 @@ const struct c_common_resword c_common_r
   { "_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 },
Index: gcc/c-parser.c
===================================================================
--- gcc/c-parser.c	(revision 159439)
+++ gcc/c-parser.c	(working copy)
@@ -495,6 +495,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
@@ -504,6 +517,15 @@ c_parser_next_token_starts_declspecs (c_
   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.  */
 
@@ -884,7 +906,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 *);
@@ -1102,7 +1127,7 @@ c_parser_external_declaration (c_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;
     }
 }
@@ -1111,18 +1136,21 @@ c_parser_external_declaration (c_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]
@@ -1166,7 +1194,8 @@ c_parser_external_declaration (c_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;
@@ -1175,6 +1204,12 @@ c_parser_declaration_or_fndef (c_parser 
   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)
@@ -1333,7 +1368,8 @@ c_parser_declaration_or_fndef (c_parser 
 	 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;
@@ -1376,6 +1412,97 @@ c_parser_asm_definition (c_parser *parse
   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
@@ -1974,6 +2101,7 @@ c_parser_struct_or_union_specifier (c_pa
 
    struct-declaration:
      specifier-qualifier-list struct-declarator-list
+     static_assert-declaration-no-semi
 
    specifier-qualifier-list:
      type-specifier specifier-qualifier-list[opt]
@@ -2018,6 +2146,11 @@ c_parser_struct_declaration (c_parser *p
       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);
@@ -3506,11 +3639,11 @@ c_parser_compound_statement_nostart (c_p
 	  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)
@@ -3530,14 +3663,15 @@ c_parser_compound_statement_nostart (c_p
 		 && (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);
@@ -3667,7 +3801,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))
 	{
@@ -3675,6 +3809,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);
 	}
@@ -4211,9 +4346,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))
@@ -4226,12 +4361,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);
 	    }
@@ -6519,7 +6655,8 @@ c_parser_objc_methodprotolist (c_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;
 	}
     }
@@ -8040,12 +8177,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;

-- 
Joseph S. Myers
joseph@codesourcery.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]