OSDN Git Service

PR preprocessor/6521
[pf3gnuchains/gcc-fork.git] / gcc / c-parse.in
index 9434a2f..679d42d 100644 (file)
@@ -43,7 +43,7 @@ end ifc
 #include "cpplib.h"
 #include "intl.h"
 #include "timevar.h"
-#include "c-lex.h"
+#include "c-lex.h"             /* Gets YYDEBUG macro.  */
 #include "c-tree.h"
 #include "c-pragma.h"
 #include "flags.h"
@@ -62,11 +62,48 @@ end ifobjc
 /* Like YYERROR but do call yyerror.  */
 #define YYERROR1 { yyerror ("syntax error"); YYERROR; }
 
-/* Cause the "yydebug" variable to be defined.  */
-#define YYDEBUG 1
-
-/* Rename the "yyparse" function so that we can override it elsewhere.  */
-#define yyparse yyparse_1
+/* Like the default stack expander, except (1) use realloc when possible,
+   (2) impose no hard maxiumum on stack size, (3) REALLY do not use alloca.
+
+   Irritatingly, YYSTYPE is defined after this %{ %} block, so we cannot
+   give malloced_yyvs its proper type.  This is ok since all we need from
+   it is to be able to free it.  */
+
+static short *malloced_yyss;
+static void *malloced_yyvs;
+
+#define yyoverflow(MSG, SS, SSSIZE, VS, VSSIZE, YYSSZ)                 \
+do {                                                                   \
+  size_t newsize;                                                      \
+  short *newss;                                                                \
+  YYSTYPE *newvs;                                                      \
+  newsize = *(YYSSZ) *= 2;                                             \
+  if (malloced_yyss)                                                   \
+    {                                                                  \
+      newss = (short *)                                                        \
+       really_call_realloc (*(SS), newsize * sizeof (short));          \
+      newvs = (YYSTYPE *)                                              \
+       really_call_realloc (*(VS), newsize * sizeof (YYSTYPE));        \
+    }                                                                  \
+  else                                                                 \
+    {                                                                  \
+      newss = (short *) really_call_malloc (newsize * sizeof (short)); \
+      newvs = (YYSTYPE *) really_call_malloc (newsize * sizeof (YYSTYPE)); \
+      if (newss)                                                       \
+        memcpy (newss, *(SS), (SSSIZE));                               \
+      if (newvs)                                                       \
+        memcpy (newvs, *(VS), (VSSIZE));                               \
+    }                                                                  \
+  if (!newss || !newvs)                                                        \
+    {                                                                  \
+      yyerror (MSG);                                                   \
+      return 2;                                                                \
+    }                                                                  \
+  *(SS) = newss;                                                       \
+  *(VS) = newvs;                                                       \
+  malloced_yyss = newss;                                               \
+  malloced_yyvs = (void *) newvs;                                      \
+} while (0)
 %}
 
 %start program
@@ -85,7 +122,8 @@ end ifobjc
 
 /* Reserved words that specify storage class.
    yylval contains an IDENTIFIER_NODE which indicates which one.  */
-%token SCSPEC
+%token SCSPEC                  /* Storage class other than static.  */
+%token STATIC                  /* Static storage class.  */
 
 /* Reserved words that specify type.
    yylval contains an IDENTIFIER_NODE which indicates which one.  */
@@ -151,7 +189,7 @@ end ifobjc
 %type <ttype> BREAK CONTINUE RETURN GOTO ASM_KEYWORD SIZEOF TYPEOF ALIGNOF
 
 %type <ttype> identifier IDENTIFIER TYPENAME CONSTANT expr nonnull_exprlist exprlist
-%type <ttype> expr_no_commas cast_expr unary_expr primary string STRING
+%type <ttype> expr_no_commas cast_expr unary_expr primary STRING
 %type <ttype> declspecs_nosc_nots_nosa_noea declspecs_nosc_nots_nosa_ea
 %type <ttype> declspecs_nosc_nots_sa_noea declspecs_nosc_nots_sa_ea
 %type <ttype> declspecs_nosc_ts_nosa_noea declspecs_nosc_ts_nosa_ea
@@ -167,7 +205,7 @@ end ifobjc
 %type <ttype> typespec_reserved_nonattr typespec_reserved_attr
 %type <ttype> typespec_nonreserved_nonattr
 
-%type <ttype> SCSPEC TYPESPEC TYPE_QUAL maybe_type_qual
+%type <ttype> scspec SCSPEC STATIC TYPESPEC TYPE_QUAL maybe_type_qual
 %type <ttype> initdecls notype_initdecls initdcl notype_initdcl
 %type <ttype> init maybeasm
 %type <ttype> asm_operands nonnull_asm_operands asm_operand asm_clobbers
@@ -299,6 +337,7 @@ end ifc
 static void yyprint      PARAMS ((FILE *, int, YYSTYPE));
 static void yyerror      PARAMS ((const char *));
 static int yylexname     PARAMS ((void));
+static int yylexstring   PARAMS ((void));
 static inline int _yylex  PARAMS ((void));
 static int  yylex        PARAMS ((void));
 static void init_reswords PARAMS ((void));
@@ -329,9 +368,10 @@ program: /* empty */
                     get us back to the global binding level.  */
                  while (! global_bindings_p ())
                    poplevel (0, 0, 0);
-ifc
+                 /* __FUNCTION__ is defined at file scope ("").  This
+                    call may not be necessary as my tests indicate it
+                    still works without it.  */
                  finish_fname_decls ();
-end ifc
                   finish_file ();
                }
        ;
@@ -367,7 +407,7 @@ datadef:
          setspecs notype_initdecls ';'
                { if (pedantic)
                    error ("ISO C forbids data definition with no type or storage class");
-                 else if (!flag_traditional)
+                 else
                    warning ("data definition has no type or storage class"); 
 
                  POP_DECLSPEC_STACK; }
@@ -395,7 +435,7 @@ fndef:
          save_filename save_lineno compstmt_or_error
                { DECL_SOURCE_FILE (current_function_decl) = $7;
                  DECL_SOURCE_LINE (current_function_decl) = $8;
-                 finish_function (0); 
+                 finish_function (0, 1); 
                  POP_DECLSPEC_STACK; }
        | declspecs_ts setspecs declarator error
                { POP_DECLSPEC_STACK; }
@@ -409,7 +449,7 @@ fndef:
          save_filename save_lineno compstmt_or_error
                { DECL_SOURCE_FILE (current_function_decl) = $7;
                  DECL_SOURCE_LINE (current_function_decl) = $8;
-                 finish_function (0); 
+                 finish_function (0, 1); 
                  POP_DECLSPEC_STACK; }
        | declspecs_nots setspecs notype_declarator error
                { POP_DECLSPEC_STACK; }
@@ -423,7 +463,7 @@ fndef:
          save_filename save_lineno compstmt_or_error
                { DECL_SOURCE_FILE (current_function_decl) = $6;
                  DECL_SOURCE_LINE (current_function_decl) = $7;
-                 finish_function (0); 
+                 finish_function (0, 1); 
                  POP_DECLSPEC_STACK; }
        | setspecs notype_declarator error
                { POP_DECLSPEC_STACK; }
@@ -567,19 +607,22 @@ expr_no_commas:
        | expr_no_commas '^' expr_no_commas
                { $$ = parser_build_binary_op ($2, $1, $3); }
        | expr_no_commas ANDAND
-               { $1 = truthvalue_conversion (default_conversion ($1));
+               { $1 = c_common_truthvalue_conversion
+                   (default_conversion ($1));
                  skip_evaluation += $1 == boolean_false_node; }
          expr_no_commas
                { skip_evaluation -= $1 == boolean_false_node;
                  $$ = parser_build_binary_op (TRUTH_ANDIF_EXPR, $1, $4); }
        | expr_no_commas OROR
-               { $1 = truthvalue_conversion (default_conversion ($1));
+               { $1 = c_common_truthvalue_conversion
+                   (default_conversion ($1));
                  skip_evaluation += $1 == boolean_true_node; }
          expr_no_commas
                { skip_evaluation -= $1 == boolean_true_node;
                  $$ = parser_build_binary_op (TRUTH_ORIF_EXPR, $1, $4); }
        | expr_no_commas '?'
-               { $1 = truthvalue_conversion (default_conversion ($1));
+               { $1 = c_common_truthvalue_conversion
+                   (default_conversion ($1));
                  skip_evaluation += $1 == boolean_false_node; }
           expr ':'
                { skip_evaluation += (($1 == boolean_true_node)
@@ -592,7 +635,8 @@ expr_no_commas:
                    pedwarn ("ISO C forbids omitting the middle term of a ?: expression");
                  /* Make sure first operand is calculated only once.  */
                  $<ttype>2 = save_expr ($1);
-                 $1 = truthvalue_conversion (default_conversion ($<ttype>2));
+                 $1 = c_common_truthvalue_conversion
+                   (default_conversion ($<ttype>2));
                  skip_evaluation += $1 == boolean_true_node; }
          ':' expr_no_commas
                { skip_evaluation -= $1 == boolean_true_node;
@@ -607,7 +651,8 @@ expr_no_commas:
        | expr_no_commas ASSIGN expr_no_commas
                { char class;
                  $$ = build_modify_expr ($1, $2, $3);
-                 /* This inhibits warnings in truthvalue_conversion.  */
+                 /* This inhibits warnings in
+                    c_common_truthvalue_conversion.  */
                  class = TREE_CODE_CLASS (TREE_CODE ($$));
                  if (IS_EXPR_CODE_CLASS (class))
                    C_SET_EXP_ORIGINAL_CODE ($$, ERROR_MARK);
@@ -622,8 +667,8 @@ primary:
                  $$ = build_external_ref ($1, yychar == '(');
                }
        | CONSTANT
-       | string
-               { $$ = combine_strings ($1); }
+       | STRING
+               { $$ = fix_string_type ($$); }
        | VAR_FUNC_NAME
                { $$ = fname_decl (C_RID_CODE ($$), $$); }
        | '(' typename ')' '{' 
@@ -734,29 +779,6 @@ ifobjc
 end ifobjc
        ;
 
-/* Produces a STRING_CST with perhaps more STRING_CSTs chained onto it.  */
-string:
-         STRING
-       | string STRING
-               {
-ifc
-                  static int last_lineno = 0;
-                  static const char *last_input_filename = 0;
-end ifc
-                  $$ = chainon ($1, $2);
-ifc
-                 if (warn_traditional && !in_system_header
-                     && (lineno != last_lineno || !last_input_filename ||
-                         strcmp (last_input_filename, input_filename)))
-                   {
-                     warning ("traditional C rejects string concatenation");
-                     last_lineno = lineno;
-                     last_input_filename = input_filename;
-                   }
-end ifc
-               }
-       ;
-
 ifobjc
 /* Produces an STRING_CST with perhaps more STRING_CSTs chained
    onto it, which is to be read as an ObjC string object.  */
@@ -854,7 +876,7 @@ decl:
 
 /* A list of declaration specifiers.  These are:
 
-   - Storage class specifiers (SCSPEC), which for GCC currently include
+   - Storage class specifiers (scspec), which for GCC currently includes
    function specifiers ("inline").
 
    - Type specifiers (typespec_*).
@@ -1025,7 +1047,7 @@ declspecs_nosc_ts_sa_ea:
        ;
 
 declspecs_sc_nots_nosa_noea:
-         SCSPEC
+         scspec
                { $$ = tree_cons (NULL_TREE, $1, NULL_TREE);
                  TREE_STATIC ($$) = 0; }
        | declspecs_sc_nots_nosa_noea TYPE_QUAL
@@ -1034,25 +1056,25 @@ declspecs_sc_nots_nosa_noea:
        | declspecs_sc_nots_nosa_ea TYPE_QUAL
                { $$ = tree_cons (NULL_TREE, $2, $1);
                  TREE_STATIC ($$) = 1; }
-       | declspecs_nosc_nots_nosa_noea SCSPEC
+       | declspecs_nosc_nots_nosa_noea scspec
                { if (extra_warnings && TREE_STATIC ($1))
                    warning ("`%s' is not at beginning of declaration",
                             IDENTIFIER_POINTER ($2));
                  $$ = tree_cons (NULL_TREE, $2, $1);
                  TREE_STATIC ($$) = TREE_STATIC ($1); }
-       | declspecs_nosc_nots_nosa_ea SCSPEC
+       | declspecs_nosc_nots_nosa_ea scspec
                { if (extra_warnings && TREE_STATIC ($1))
                    warning ("`%s' is not at beginning of declaration",
                             IDENTIFIER_POINTER ($2));
                  $$ = tree_cons (NULL_TREE, $2, $1);
                  TREE_STATIC ($$) = TREE_STATIC ($1); }
-       | declspecs_sc_nots_nosa_noea SCSPEC
+       | declspecs_sc_nots_nosa_noea scspec
                { if (extra_warnings && TREE_STATIC ($1))
                    warning ("`%s' is not at beginning of declaration",
                             IDENTIFIER_POINTER ($2));
                  $$ = tree_cons (NULL_TREE, $2, $1);
                  TREE_STATIC ($$) = TREE_STATIC ($1); }
-       | declspecs_sc_nots_nosa_ea SCSPEC
+       | declspecs_sc_nots_nosa_ea scspec
                { if (extra_warnings && TREE_STATIC ($1))
                    warning ("`%s' is not at beginning of declaration",
                             IDENTIFIER_POINTER ($2));
@@ -1073,25 +1095,25 @@ declspecs_sc_nots_sa_noea:
        | declspecs_sc_nots_sa_ea TYPE_QUAL
                { $$ = tree_cons (NULL_TREE, $2, $1);
                  TREE_STATIC ($$) = 1; }
-       | declspecs_nosc_nots_sa_noea SCSPEC
+       | declspecs_nosc_nots_sa_noea scspec
                { if (extra_warnings && TREE_STATIC ($1))
                    warning ("`%s' is not at beginning of declaration",
                             IDENTIFIER_POINTER ($2));
                  $$ = tree_cons (NULL_TREE, $2, $1);
                  TREE_STATIC ($$) = TREE_STATIC ($1); }
-       | declspecs_nosc_nots_sa_ea SCSPEC
+       | declspecs_nosc_nots_sa_ea scspec
                { if (extra_warnings && TREE_STATIC ($1))
                    warning ("`%s' is not at beginning of declaration",
                             IDENTIFIER_POINTER ($2));
                  $$ = tree_cons (NULL_TREE, $2, $1);
                  TREE_STATIC ($$) = TREE_STATIC ($1); }
-       | declspecs_sc_nots_sa_noea SCSPEC
+       | declspecs_sc_nots_sa_noea scspec
                { if (extra_warnings && TREE_STATIC ($1))
                    warning ("`%s' is not at beginning of declaration",
                             IDENTIFIER_POINTER ($2));
                  $$ = tree_cons (NULL_TREE, $2, $1);
                  TREE_STATIC ($$) = TREE_STATIC ($1); }
-       | declspecs_sc_nots_sa_ea SCSPEC
+       | declspecs_sc_nots_sa_ea scspec
                { if (extra_warnings && TREE_STATIC ($1))
                    warning ("`%s' is not at beginning of declaration",
                             IDENTIFIER_POINTER ($2));
@@ -1124,25 +1146,25 @@ declspecs_sc_ts_nosa_noea:
        | declspecs_sc_nots_nosa_ea typespec_nonattr
                { $$ = tree_cons (NULL_TREE, $2, $1);
                  TREE_STATIC ($$) = 1; }
-       | declspecs_nosc_ts_nosa_noea SCSPEC
+       | declspecs_nosc_ts_nosa_noea scspec
                { if (extra_warnings && TREE_STATIC ($1))
                    warning ("`%s' is not at beginning of declaration",
                             IDENTIFIER_POINTER ($2));
                  $$ = tree_cons (NULL_TREE, $2, $1);
                  TREE_STATIC ($$) = TREE_STATIC ($1); }
-       | declspecs_nosc_ts_nosa_ea SCSPEC
+       | declspecs_nosc_ts_nosa_ea scspec
                { if (extra_warnings && TREE_STATIC ($1))
                    warning ("`%s' is not at beginning of declaration",
                             IDENTIFIER_POINTER ($2));
                  $$ = tree_cons (NULL_TREE, $2, $1);
                  TREE_STATIC ($$) = TREE_STATIC ($1); }
-       | declspecs_sc_ts_nosa_noea SCSPEC
+       | declspecs_sc_ts_nosa_noea scspec
                { if (extra_warnings && TREE_STATIC ($1))
                    warning ("`%s' is not at beginning of declaration",
                             IDENTIFIER_POINTER ($2));
                  $$ = tree_cons (NULL_TREE, $2, $1);
                  TREE_STATIC ($$) = TREE_STATIC ($1); }
-       | declspecs_sc_ts_nosa_ea SCSPEC
+       | declspecs_sc_ts_nosa_ea scspec
                { if (extra_warnings && TREE_STATIC ($1))
                    warning ("`%s' is not at beginning of declaration",
                             IDENTIFIER_POINTER ($2));
@@ -1187,25 +1209,25 @@ declspecs_sc_ts_sa_noea:
        | declspecs_sc_nots_sa_ea typespec_nonattr
                { $$ = tree_cons (NULL_TREE, $2, $1);
                  TREE_STATIC ($$) = 1; }
-       | declspecs_nosc_ts_sa_noea SCSPEC
+       | declspecs_nosc_ts_sa_noea scspec
                { if (extra_warnings && TREE_STATIC ($1))
                    warning ("`%s' is not at beginning of declaration",
                             IDENTIFIER_POINTER ($2));
                  $$ = tree_cons (NULL_TREE, $2, $1);
                  TREE_STATIC ($$) = TREE_STATIC ($1); }
-       | declspecs_nosc_ts_sa_ea SCSPEC
+       | declspecs_nosc_ts_sa_ea scspec
                { if (extra_warnings && TREE_STATIC ($1))
                    warning ("`%s' is not at beginning of declaration",
                             IDENTIFIER_POINTER ($2));
                  $$ = tree_cons (NULL_TREE, $2, $1);
                  TREE_STATIC ($$) = TREE_STATIC ($1); }
-       | declspecs_sc_ts_sa_noea SCSPEC
+       | declspecs_sc_ts_sa_noea scspec
                { if (extra_warnings && TREE_STATIC ($1))
                    warning ("`%s' is not at beginning of declaration",
                             IDENTIFIER_POINTER ($2));
                  $$ = tree_cons (NULL_TREE, $2, $1);
                  TREE_STATIC ($$) = TREE_STATIC ($1); }
-       | declspecs_sc_ts_sa_ea SCSPEC
+       | declspecs_sc_ts_sa_ea scspec
                { if (extra_warnings && TREE_STATIC ($1))
                    warning ("`%s' is not at beginning of declaration",
                             IDENTIFIER_POINTER ($2));
@@ -1397,10 +1419,8 @@ notype_initdecls:
 maybeasm:
          /* empty */
                { $$ = NULL_TREE; }
-       | ASM_KEYWORD '(' string ')'
-               { if (TREE_CHAIN ($3)) $3 = combine_strings ($3);
-                 $$ = $3;
-               }
+       | ASM_KEYWORD '(' STRING ')'
+               { $$ = $3; }
        ;
 
 initdcl:
@@ -1479,10 +1499,15 @@ attrib:
 
 any_word:
          identifier
-       | SCSPEC
+       | scspec
        | TYPESPEC
        | TYPE_QUAL
        ;
+
+scspec:
+         STATIC
+       | SCSPEC
+       ;
 \f
 /* Initializers.  `init' is the entry point.  */
 
@@ -1582,7 +1607,7 @@ nested_function:
                { tree decl = current_function_decl;
                  DECL_SOURCE_FILE (decl) = $5;
                  DECL_SOURCE_LINE (decl) = $6;
-                 finish_function (1);
+                 finish_function (1, 1);
                  pop_function_context (); 
                  add_decl_stmt (decl); }
        ;
@@ -1612,7 +1637,7 @@ notype_nested_function:
                { tree decl = current_function_decl;
                  DECL_SOURCE_FILE (decl) = $5;
                  DECL_SOURCE_LINE (decl) = $6;
-                 finish_function (1);
+                 finish_function (1, 1);
                  pop_function_context (); 
                  add_decl_stmt (decl); }
        ;
@@ -1972,30 +1997,17 @@ direct_absdcl1:
 /* The [...] part of a declarator for an array type.  */
 
 array_declarator:
-         '[' expr ']'
-               { $$ = build_array_declarator ($2, NULL_TREE, 0, 0); }
-       | '[' declspecs_nosc expr ']'
+       '[' maybe_type_quals_attrs expr ']'
                { $$ = build_array_declarator ($3, $2, 0, 0); }
-       | '[' ']'
-               { $$ = build_array_declarator (NULL_TREE, NULL_TREE, 0, 0); }
-       | '[' declspecs_nosc ']'
+       | '[' maybe_type_quals_attrs ']'
                { $$ = build_array_declarator (NULL_TREE, $2, 0, 0); }
-       | '[' '*' ']'
-               { $$ = build_array_declarator (NULL_TREE, NULL_TREE, 0, 1); }
-       | '[' declspecs_nosc '*' ']'
+       | '[' maybe_type_quals_attrs '*' ']'
                { $$ = build_array_declarator (NULL_TREE, $2, 0, 1); }
-       | '[' SCSPEC expr ']'
-               { if (C_RID_CODE ($2) != RID_STATIC)
-                   error ("storage class specifier in array declarator");
-                 $$ = build_array_declarator ($3, NULL_TREE, 1, 0); }
-       | '[' SCSPEC declspecs_nosc expr ']'
-               { if (C_RID_CODE ($2) != RID_STATIC)
-                   error ("storage class specifier in array declarator");
-                 $$ = build_array_declarator ($4, $3, 1, 0); }
-       | '[' declspecs_nosc SCSPEC expr ']'
-               { if (C_RID_CODE ($3) != RID_STATIC)
-                   error ("storage class specifier in array declarator");
-                 $$ = build_array_declarator ($4, $2, 1, 0); }
+       | '[' STATIC maybe_type_quals_attrs expr ']'
+               { $$ = build_array_declarator ($4, $3, 1, 0); }
+       /* declspecs_nosc_nots is a synonym for type_quals_attrs.  */
+       | '[' declspecs_nosc_nots STATIC expr ']'
+               { $$ = build_array_declarator ($4, $2, 1, 0); }
        ;
 
 /* A nonempty series of declarations and statements (possibly followed by
@@ -2067,6 +2079,7 @@ end ifobjc
 
 poplevel:  /* empty */
                 { $$ = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0); }
+        ;
 
 /* Start and end blocks created for the new scopes of C99.  */
 c99_block_start: /* empty */
@@ -2137,7 +2150,8 @@ compstmt_or_error:
        ;
 
 compstmt_start: '{' { compstmt_count++;
-                      $$ = c_begin_compound_stmt (); } 
+                      $$ = c_begin_compound_stmt (); }
+        ;
 
 compstmt_nostart: '}'
                { $$ = convert (void_type_node, integer_zero_node); }
@@ -2169,9 +2183,11 @@ compstmt_primary_start:
                  compstmt_count++;
                  $$ = add_stmt (build_stmt (COMPOUND_STMT, last_tree));
                }
+        ;
 
 compstmt: compstmt_start compstmt_nostart
                { RECHAIN_STMTS ($1, COMPOUND_BODY ($1)); 
+                 last_expr_type = NULL_TREE;
                   $$ = $1; }
        ;
 
@@ -2197,7 +2213,7 @@ if_prefix:
           IF
                 { $<ttype>$ = c_begin_if_stmt (); }
             '(' expr ')'
-               { c_expand_start_cond (truthvalue_conversion ($4), 
+               { c_expand_start_cond (c_common_truthvalue_conversion ($4), 
                                       compstmt_count,$<ttype>2);
                  $<itype>$ = stmt_count;
                  if_stmt_file = $<filename>-2;
@@ -2309,15 +2325,15 @@ select_or_iter_stmt:
                 { stmt_count++; 
                  $<ttype>$ = c_begin_while_stmt (); }
          '(' expr ')'
-                { $4 = truthvalue_conversion ($4);
-                 c_finish_while_stmt_cond (truthvalue_conversion ($4),
-                                           $<ttype>2);
+                { $4 = c_common_truthvalue_conversion ($4);
+                 c_finish_while_stmt_cond
+                   (c_common_truthvalue_conversion ($4), $<ttype>2);
                  $<ttype>$ = add_stmt ($<ttype>2); }
          c99_block_lineno_labeled_stmt
                { RECHAIN_STMTS ($<ttype>6, WHILE_BODY ($<ttype>6)); }
        | do_stmt_start
          '(' expr ')' ';'
-                { DO_COND ($1) = truthvalue_conversion ($3); }
+                { DO_COND ($1) = c_common_truthvalue_conversion ($3); }
        | do_stmt_start error
                { }
        | FOR
@@ -2329,7 +2345,8 @@ select_or_iter_stmt:
                  RECHAIN_STMTS ($<ttype>2, FOR_INIT_STMT ($<ttype>2)); }
          xexpr ';'
                 { if ($6) 
-                   FOR_COND ($<ttype>2) = truthvalue_conversion ($6); }
+                   FOR_COND ($<ttype>2)
+                     = c_common_truthvalue_conversion ($6); }
          xexpr ')'
                { FOR_EXPR ($<ttype>2) = $9; }
          c99_block_lineno_labeled_stmt
@@ -2469,14 +2486,16 @@ asm_operand:
          STRING '(' expr ')'
                { $$ = build_tree_list (build_tree_list (NULL_TREE, $1), $3); }
        | '[' identifier ']' STRING '(' expr ')'
-               { $$ = build_tree_list (build_tree_list ($2, $4), $6); }
+               { $2 = build_string (IDENTIFIER_LENGTH ($2),
+                                    IDENTIFIER_POINTER ($2));
+                 $$ = build_tree_list (build_tree_list ($2, $4), $6); }
        ;
 
 asm_clobbers:
-         string
-               { $$ = tree_cons (NULL_TREE, combine_strings ($1), NULL_TREE); }
-       | asm_clobbers ',' string
-               { $$ = tree_cons (NULL_TREE, combine_strings ($3), $1); }
+         STRING
+               { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); }
+       | asm_clobbers ',' STRING
+               { $$ = tree_cons (NULL_TREE, $3, $1); }
        ;
 \f
 /* This is what appears inside the parens in a function declarator.
@@ -2605,11 +2624,12 @@ setspecs_fp:
    where either a parmlist or an identifier list is ok.
    Its value is a list of ..._TYPE nodes or a list of identifiers.  */
 parmlist_or_identifiers:
+         maybe_attribute
                { pushlevel (0);
                  clear_parm_order ();
                  declare_parm_level (1); }
          parmlist_or_identifiers_1
-               { $$ = $2;
+               { $$ = $3;
                  parmlist_tags_warning ();
                  poplevel (0, 0, 0); }
        ;
@@ -2621,7 +2641,15 @@ parmlist_or_identifiers_1:
                  for (t = $1; t; t = TREE_CHAIN (t))
                    if (TREE_VALUE (t) == NULL_TREE)
                      error ("`...' in old-style identifier list");
-                 $$ = tree_cons (NULL_TREE, NULL_TREE, $1); }
+                 $$ = tree_cons (NULL_TREE, NULL_TREE, $1);
+
+                 /* Make sure we have a parmlist after attributes.  */
+                 if ($<ttype>-1 != 0
+                     && (TREE_CODE ($$) != TREE_LIST
+                         || TREE_PURPOSE ($$) == 0
+                         || TREE_CODE (TREE_PURPOSE ($$)) != PARM_DECL))
+                   YYERROR1;
+               }
        ;
 
 /* A nonempty list of identifiers.  */
@@ -3270,11 +3298,10 @@ struct resword
 
 /* Disable mask.  Keywords are disabled if (reswords[i].disable & mask) is
    _true_.  */
-#define D_TRAD 0x01    /* not in traditional C */
-#define D_C89  0x02    /* not in C89 */
-#define D_EXT  0x04    /* GCC extension */
-#define D_EXT89        0x08    /* GCC extension incorporated in C99 */
-#define D_OBJC 0x10    /* Objective C only */
+#define D_C89  0x01    /* not in C89 */
+#define D_EXT  0x02    /* GCC extension */
+#define D_EXT89        0x04    /* GCC extension incorporated in C99 */
+#define D_OBJC 0x08    /* Objective C only */
 
 static const struct resword reswords[] =
 {
@@ -3327,7 +3354,7 @@ static const struct resword reswords[] =
   { "break",           RID_BREAK,      0 },
   { "case",            RID_CASE,       0 },
   { "char",            RID_CHAR,       0 },
-  { "const",           RID_CONST,      D_TRAD },
+  { "const",           RID_CONST,      0 },
   { "continue",                RID_CONTINUE,   0 },
   { "default",         RID_DEFAULT,    0 },
   { "do",              RID_DO,         0 },
@@ -3339,24 +3366,24 @@ static const struct resword reswords[] =
   { "for",             RID_FOR,        0 },
   { "goto",            RID_GOTO,       0 },
   { "if",              RID_IF,         0 },
-  { "inline",          RID_INLINE,     D_TRAD|D_EXT89 },
+  { "inline",          RID_INLINE,     D_EXT89 },
   { "int",             RID_INT,        0 },
   { "long",            RID_LONG,       0 },
   { "register",                RID_REGISTER,   0 },
-  { "restrict",                RID_RESTRICT,   D_TRAD|D_C89 },
+  { "restrict",                RID_RESTRICT,   D_C89 },
   { "return",          RID_RETURN,     0 },
   { "short",           RID_SHORT,      0 },
-  { "signed",          RID_SIGNED,     D_TRAD },
+  { "signed",          RID_SIGNED,     0 },
   { "sizeof",          RID_SIZEOF,     0 },
   { "static",          RID_STATIC,     0 },
   { "struct",          RID_STRUCT,     0 },
   { "switch",          RID_SWITCH,     0 },
   { "typedef",         RID_TYPEDEF,    0 },
-  { "typeof",          RID_TYPEOF,     D_TRAD|D_EXT },
+  { "typeof",          RID_TYPEOF,     D_EXT },
   { "union",           RID_UNION,      0 },
   { "unsigned",                RID_UNSIGNED,   0 },
   { "void",            RID_VOID,       0 },
-  { "volatile",                RID_VOLATILE,   D_TRAD },
+  { "volatile",                RID_VOLATILE,   0 },
   { "while",           RID_WHILE,      0 },
 ifobjc
   { "id",              RID_ID,                 D_OBJC },
@@ -3393,7 +3420,7 @@ end ifobjc
    three languages.  */
 static const short rid_to_yy[RID_MAX] =
 {
-  /* RID_STATIC */     SCSPEC,
+  /* RID_STATIC */     STATIC,
   /* RID_UNSIGNED */   TYPESPEC,
   /* RID_LONG */       TYPESPEC,
   /* RID_CONST */      TYPE_QUAL,
@@ -3535,7 +3562,6 @@ init_reswords ()
   unsigned int i;
   tree id;
   int mask = (flag_isoc99 ? 0 : D_C89)
-             | (flag_traditional ? D_TRAD : 0)
              | (flag_no_asm ? (flag_isoc99 ? D_EXT : D_EXT|D_EXT89) : 0);
 
   if (c_language != clk_objective_c)
@@ -3661,6 +3687,59 @@ end ifobjc
   return IDENTIFIER;
 }
 
+/* Concatenate strings before returning them to the parser.  This isn't quite
+   as good as having it done in the lexer, but it's better than nothing.  */
+
+static int
+yylexstring ()
+{
+  enum cpp_ttype next_type;
+  tree orig = yylval.ttype;
+
+  next_type = c_lex (&yylval.ttype);
+  if (next_type == CPP_STRING
+      || next_type == CPP_WSTRING
+      || (next_type == CPP_NAME && yylexname () == STRING))
+    {
+      varray_type strings;
+
+ifc
+      static int last_lineno = 0;
+      static const char *last_input_filename = 0;
+      if (warn_traditional && !in_system_header
+         && (lineno != last_lineno || !last_input_filename ||
+             strcmp (last_input_filename, input_filename)))
+       {
+         warning ("traditional C rejects string concatenation");
+         last_lineno = lineno;
+         last_input_filename = input_filename;
+       }
+end ifc
+
+      VARRAY_TREE_INIT (strings, 32, "strings");
+      VARRAY_PUSH_TREE (strings, orig);
+
+      do
+       {
+         VARRAY_PUSH_TREE (strings, yylval.ttype);
+         next_type = c_lex (&yylval.ttype);
+       }
+      while (next_type == CPP_STRING
+            || next_type == CPP_WSTRING
+            || (next_type == CPP_NAME && yylexname () == STRING));
+
+      yylval.ttype = combine_strings (strings);
+
+      VARRAY_FREE (strings);
+    }
+  else
+    yylval.ttype = orig;
+
+  /* We will have always read one token too many.  */
+  _cpp_backup_tokens (parse_in, 1);
+
+  return STRING;
+}
 
 static inline int
 _yylex ()
@@ -3727,7 +3806,13 @@ _yylex ()
       return 0;
 
     case CPP_NAME:
-      return yylexname ();
+      {
+       int ret = yylexname ();
+       if (ret == STRING)
+         return yylexstring ();
+       else
+         return ret;
+      }
 
     case CPP_NUMBER:
     case CPP_CHAR:
@@ -3736,7 +3821,7 @@ _yylex ()
 
     case CPP_STRING:
     case CPP_WSTRING:
-      return STRING;
+      return yylexstring ();
       
       /* This token is Objective-C specific.  It gives the next token
         special significance.  */
@@ -3792,21 +3877,6 @@ yylex()
   return r;
 }
 
-/* Sets the value of the 'yydebug' variable to VALUE.
-   This is a function so we don't have to have YYDEBUG defined
-   in order to build the compiler.  */
-
-void
-c_set_yydebug (value)
-     int value;
-{
-#if YYDEBUG != 0
-  yydebug = value;
-#else
-  warning ("YYDEBUG not defined");
-#endif
-}
-
 /* Function used when yydebug is set, to print a token in more detail.  */
 
 static void
@@ -3827,6 +3897,7 @@ yyprint (file, yychar, yyl)
     case TYPESPEC:
     case TYPE_QUAL:
     case SCSPEC:
+    case STATIC:
       if (IDENTIFIER_POINTER (t))
        fprintf (file, " `%s'", IDENTIFIER_POINTER (t));
       break;
@@ -3880,3 +3951,15 @@ make_pointer_declarator (type_quals_attrs, target)
     itarget = tree_cons (attrs, target, NULL_TREE);
   return build1 (INDIRECT_REF, quals, itarget);
 }
+
+/* Free malloced parser stacks if necessary.  */
+
+void
+free_parser_stacks ()
+{
+  if (malloced_yyss)
+    {
+      free (malloced_yyss);
+      free (malloced_yyvs);
+    }
+}