X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fc-parser.c;h=bdf96ca6d920781e5f99adc33cacc342cafaecec;hp=522f2d2e4a547740f997d7460623c752e5e7f526;hb=8115b8bebfeb4eb90663a7fd5865993ce7f10121;hpb=56af936e3ca66383f712b664648142ed9fed1bca
diff --git a/gcc/c-parser.c b/gcc/c-parser.c
index 522f2d2e4a5..bdf96ca6d92 100644
--- a/gcc/c-parser.c
+++ b/gcc/c-parser.c
@@ -1,6 +1,6 @@
/* Parser for C and Objective-C.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
Parser actions based on the old Bison parser; structure somewhat
influenced by and fragments based on the C++ parser.
@@ -9,7 +9,7 @@ This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -18,9 +18,8 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+. */
/* TODO:
@@ -59,25 +58,6 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
#include "cgraph.h"
-/* Miscellaneous data and functions needed for the parser. */
-
-int yydebug;
-
-/* Objective-C specific parser/lexer information. */
-
-static int objc_pq_context = 0;
-
-/* The following flag is needed to contextualize Objective-C lexical
- analysis. In some cases (e.g., 'int NSObject;'), it is undesirable
- to bind an identifier to an Objective-C class, even if a class with
- that name exists. */
-static int objc_need_raw_identifier = 0;
-#define OBJC_NEED_RAW_IDENTIFIER(VAL) \
- do { \
- if (c_dialect_objc ()) \
- objc_need_raw_identifier = VAL; \
- } while (0)
-
/* The reserved keyword table. */
struct resword
{
@@ -100,6 +80,9 @@ static const struct resword reswords[] =
{ "_Decimal32", RID_DFLOAT32, D_EXT },
{ "_Decimal64", RID_DFLOAT64, D_EXT },
{ "_Decimal128", RID_DFLOAT128, D_EXT },
+ { "_Fract", RID_FRACT, D_EXT },
+ { "_Accum", RID_ACCUM, D_EXT },
+ { "_Sat", RID_SAT, D_EXT },
{ "__FUNCTION__", RID_FUNCTION_NAME, 0 },
{ "__PRETTY_FUNCTION__", RID_PRETTY_FUNCTION_NAME, 0 },
{ "__alignof", RID_ALIGNOF, 0 },
@@ -297,6 +280,15 @@ typedef struct c_parser GTY(())
/* True if we're processing a pragma, and shouldn't automatically
consume CPP_PRAGMA_EOL. */
BOOL_BITFIELD in_pragma : 1;
+ /* True if we want to lex an untranslated string. */
+ BOOL_BITFIELD lex_untranslated_string : 1;
+ /* Objective-C specific parser/lexer information. */
+ BOOL_BITFIELD objc_pq_context : 1;
+ /* The following flag is needed to contextualize Objective-C lexical
+ analysis. In some cases (e.g., 'int NSObject;'), it is
+ undesirable to bind an identifier to an Objective-C class, even
+ if a class with that name exists. */
+ BOOL_BITFIELD objc_need_raw_identifier : 1;
} c_parser;
@@ -309,11 +301,13 @@ static GTY (()) c_parser *the_parser;
/* Read in and lex a single token, storing it in *TOKEN. */
static void
-c_lex_one_token (c_token *token)
+c_lex_one_token (c_parser *parser, c_token *token)
{
timevar_push (TV_LEX);
- token->type = c_lex_with_flags (&token->value, &token->location, NULL);
+ token->type = c_lex_with_flags (&token->value, &token->location, NULL,
+ (parser->lex_untranslated_string
+ ? C_LEX_STRING_NO_TRANSLATE : 0));
token->id_kind = C_ID_NONE;
token->keyword = RID_MAX;
token->pragma_kind = PRAGMA_NONE;
@@ -325,8 +319,9 @@ c_lex_one_token (c_token *token)
{
tree decl;
- int objc_force_identifier = objc_need_raw_identifier;
- OBJC_NEED_RAW_IDENTIFIER (0);
+ bool objc_force_identifier = parser->objc_need_raw_identifier;
+ if (c_dialect_objc ())
+ parser->objc_need_raw_identifier = false;
if (C_IS_RESERVED_WORD (token->value))
{
@@ -335,7 +330,8 @@ c_lex_one_token (c_token *token)
if (c_dialect_objc ())
{
if (!OBJC_IS_AT_KEYWORD (rid_code)
- && (!OBJC_IS_PQ_KEYWORD (rid_code) || objc_pq_context))
+ && (!OBJC_IS_PQ_KEYWORD (rid_code)
+ || parser->objc_pq_context))
{
/* Return the canonical spelling for this keyword. */
token->value = ridpointers[(int) rid_code];
@@ -392,7 +388,8 @@ c_lex_one_token (c_token *token)
case CPP_SEMICOLON:
/* These tokens may affect the interpretation of any identifiers
following, if doing Objective-C. */
- OBJC_NEED_RAW_IDENTIFIER (0);
+ if (c_dialect_objc ())
+ parser->objc_need_raw_identifier = false;
break;
case CPP_PRAGMA:
/* We smuggled the cpp_token->u.pragma value in an INTEGER_CST. */
@@ -413,7 +410,7 @@ c_parser_peek_token (c_parser *parser)
{
if (parser->tokens_avail == 0)
{
- c_lex_one_token (&parser->tokens[0]);
+ c_lex_one_token (parser, &parser->tokens[0]);
parser->tokens_avail = 1;
}
return &parser->tokens[0];
@@ -496,6 +493,9 @@ c_token_starts_typename (c_token *token)
case RID_VOLATILE:
case RID_RESTRICT:
case RID_ATTRIBUTE:
+ case RID_FRACT:
+ case RID_ACCUM:
+ case RID_SAT:
return true;
default:
return false;
@@ -570,6 +570,9 @@ c_token_starts_declspecs (c_token *token)
case RID_VOLATILE:
case RID_RESTRICT:
case RID_ATTRIBUTE:
+ case RID_FRACT:
+ case RID_ACCUM:
+ case RID_SAT:
return true;
default:
return false;
@@ -603,7 +606,7 @@ c_parser_peek_2nd_token (c_parser *parser)
gcc_assert (parser->tokens_avail == 1);
gcc_assert (parser->tokens[0].type != CPP_EOF);
gcc_assert (parser->tokens[0].type != CPP_PRAGMA_EOL);
- c_lex_one_token (&parser->tokens[1]);
+ c_lex_one_token (parser, &parser->tokens[1]);
parser->tokens_avail = 2;
return &parser->tokens[1];
}
@@ -809,50 +812,6 @@ c_parser_skip_to_end_of_parameter (c_parser *parser)
parser->error = false;
}
-/* Skip tokens until we have consumed an entire block, or until we
- have consumed a non-nested ';'. */
-
-static void
-c_parser_skip_to_end_of_block_or_statement (c_parser *parser)
-{
- unsigned nesting_depth = 0;
-
- while (true)
- {
- c_token *token;
-
- /* Peek at the next token. */
- token = c_parser_peek_token (parser);
- /* If we've run out of tokens, stop. */
- if (token->type == CPP_EOF)
- return;
- if (token->type == CPP_PRAGMA_EOL && parser->in_pragma)
- return;
- /* If the next token is a ';', we have reached the end of the
- statement. */
- if (token->type == CPP_SEMICOLON && !nesting_depth)
- {
- /* Consume the ';'. */
- c_parser_consume_token (parser);
- break;
- }
- /* If the next token is a non-nested '}', then we have reached
- the end of the current block. */
- if (token->type == CPP_CLOSE_BRACE
- && (nesting_depth == 0 || --nesting_depth == 0))
- {
- c_parser_consume_token (parser);
- break;
- }
- /* If it the next token is a '{', then we are entering a new
- block. Consume the entire block. */
- if (token->type == CPP_OPEN_BRACE)
- ++nesting_depth;
- c_parser_consume_token (parser);
- }
- parser->error = false;
-}
-
/* Expect to be at the end of the pragma directive and consume an
end of line marker. */
@@ -879,6 +838,82 @@ c_parser_skip_to_pragma_eol (c_parser *parser)
parser->error = false;
}
+/* Skip tokens until we have consumed an entire block, or until we
+ have consumed a non-nested ';'. */
+
+static void
+c_parser_skip_to_end_of_block_or_statement (c_parser *parser)
+{
+ unsigned nesting_depth = 0;
+ bool save_error = parser->error;
+
+ while (true)
+ {
+ c_token *token;
+
+ /* Peek at the next token. */
+ token = c_parser_peek_token (parser);
+
+ switch (token->type)
+ {
+ case CPP_EOF:
+ return;
+
+ case CPP_PRAGMA_EOL:
+ if (parser->in_pragma)
+ return;
+ break;
+
+ case CPP_SEMICOLON:
+ /* If the next token is a ';', we have reached the
+ end of the statement. */
+ if (!nesting_depth)
+ {
+ /* Consume the ';'. */
+ c_parser_consume_token (parser);
+ goto finished;
+ }
+ break;
+
+ case CPP_CLOSE_BRACE:
+ /* If the next token is a non-nested '}', then we have
+ reached the end of the current block. */
+ if (nesting_depth == 0 || --nesting_depth == 0)
+ {
+ c_parser_consume_token (parser);
+ goto finished;
+ }
+ break;
+
+ case CPP_OPEN_BRACE:
+ /* If it the next token is a '{', then we are entering a new
+ block. Consume the entire block. */
+ ++nesting_depth;
+ break;
+
+ case CPP_PRAGMA:
+ /* If we see a pragma, consume the whole thing at once. We
+ have some safeguards against consuming pragmas willy-nilly.
+ Normally, we'd expect to be here with parser->error set,
+ which disables these safeguards. But it's possible to get
+ here for secondary error recovery, after parser->error has
+ been cleared. */
+ c_parser_consume_pragma (parser);
+ c_parser_skip_to_pragma_eol (parser);
+ parser->error = save_error;
+ continue;
+
+ default:
+ break;
+ }
+
+ c_parser_consume_token (parser);
+ }
+
+ finished:
+ parser->error = false;
+}
+
/* Save the warning flags which are controlled by __extension__. */
static inline int
@@ -981,6 +1016,10 @@ static struct c_expr c_parser_postfix_expression_after_primary (c_parser *,
static struct c_expr c_parser_expression (c_parser *);
static struct c_expr c_parser_expression_conv (c_parser *);
static tree c_parser_expr_list (c_parser *, bool);
+static void c_parser_omp_construct (c_parser *);
+static void c_parser_omp_threadprivate (c_parser *);
+static void c_parser_omp_barrier (c_parser *);
+static void c_parser_omp_flush (c_parser *);
enum pragma_context { pragma_external, pragma_stmt, pragma_compound };
static bool c_parser_pragma (c_parser *, enum pragma_context);
@@ -1189,7 +1228,12 @@ c_parser_external_declaration (c_parser *parser)
absence is diagnosed through the diagnosis of implicit int. In GNU
C we also allow but diagnose declarations without declaration
specifiers, but only at top level (elsewhere they conflict with
- other syntax). */
+ other syntax).
+
+ OpenMP:
+
+ declaration:
+ threadprivate-directive */
static void
c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
@@ -1462,6 +1506,12 @@ c_parser_asm_definition (c_parser *parser)
_Decimal32
_Decimal64
_Decimal128
+ _Fract
+ _Accum
+ _Sat
+
+ (_Fract, _Accum, and _Sat are new from ISO/IEC DTR 18037:
+ http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1169.pdf)
Objective-C:
@@ -1564,11 +1614,15 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
case RID_DFLOAT64:
case RID_DFLOAT128:
case RID_BOOL:
+ case RID_FRACT:
+ case RID_ACCUM:
+ case RID_SAT:
if (!typespec_ok)
goto out;
attrs_ok = true;
seen_type = true;
- OBJC_NEED_RAW_IDENTIFIER (1);
+ if (c_dialect_objc ())
+ parser->objc_need_raw_identifier = true;
t.kind = ctsk_resword;
t.spec = c_parser_peek_token (parser)->value;
declspecs_add_type (specs, t);
@@ -1661,7 +1715,8 @@ c_parser_enum_specifier (c_parser *parser)
if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
{
/* Parse an enum definition. */
- tree type = start_enum (ident);
+ struct c_enum_contents the_enum;
+ tree type = start_enum (&the_enum, ident);
tree postfix_attrs;
/* We chain the enumerators in reverse order, then put them in
forward order at the end. */
@@ -1689,7 +1744,7 @@ c_parser_enum_specifier (c_parser *parser)
}
else
enum_value = NULL_TREE;
- enum_decl = build_enumerator (enum_id, enum_value);
+ enum_decl = build_enumerator (&the_enum, enum_id, enum_value);
TREE_CHAIN (enum_decl) = values;
values = enum_decl;
seen_comma = false;
@@ -1979,7 +2034,11 @@ c_parser_struct_declaration (c_parser *parser)
/* Support for unnamed structs or unions as members of
structs or unions (which is [a] useful and [b] supports
MS P-SDK). */
- ret = grokfield (build_id_declarator (NULL_TREE), specs, NULL_TREE);
+ tree attrs = NULL;
+ ret = grokfield (build_id_declarator (NULL_TREE), specs,
+ NULL_TREE, &attrs);
+ if (ret)
+ decl_attributes (&ret, attrs, 0);
}
return ret;
}
@@ -2019,7 +2078,7 @@ c_parser_struct_declaration (c_parser *parser)
}
if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
postfix_attrs = c_parser_attributes (parser);
- d = grokfield (declarator, specs, width);
+ d = grokfield (declarator, specs, width, &all_prefix_attrs);
decl_attributes (&d, chainon (postfix_attrs,
all_prefix_attrs), 0);
TREE_CHAIN (d) = decls;
@@ -2090,6 +2149,7 @@ c_parser_typeof_specifier (c_parser *parser)
}
else
{
+ bool was_vm;
struct c_expr expr = c_parser_expression (parser);
skip_evaluation--;
in_typeof--;
@@ -2097,7 +2157,25 @@ c_parser_typeof_specifier (c_parser *parser)
&& DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
error ("% applied to a bit-field");
ret.spec = TREE_TYPE (expr.value);
- pop_maybe_used (variably_modified_type_p (ret.spec, NULL_TREE));
+ was_vm = variably_modified_type_p (ret.spec, NULL_TREE);
+ /* This should be returned with the type so that when the type
+ is evaluated, this can be evaluated. For now, we avoid
+ evaluation when the context might. */
+ if (!skip_evaluation && was_vm)
+ {
+ tree e = expr.value;
+
+ /* If the expression is not of a type to which we cannot assign a line
+ number, wrap the thing in a no-op NOP_EXPR. */
+ if (DECL_P (e) || CONSTANT_CLASS_P (e))
+ e = build1 (NOP_EXPR, void_type_node, e);
+
+ if (CAN_HAVE_LOCATION_P (e))
+ SET_EXPR_LOCATION (e, input_location);
+
+ add_stmt (e);
+ }
+ pop_maybe_used (was_vm);
}
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
return ret;
@@ -2164,7 +2242,7 @@ c_parser_typeof_specifier (c_parser *parser)
parameter-type-list[opt] )
direct-abstract-declarator:
- direct-abstract-declarator[opt] ( parameter-forward-declarations
+ direct-abstract-declarator[opt] ( parameter-forward-declarations
parameter-type-list[opt] )
parameter-forward-declarations:
@@ -2393,6 +2471,8 @@ c_parser_direct_declarator_inner (c_parser *parser, bool id_present,
}
declarator = build_array_declarator (dimen, quals_attrs, static_seen,
star_seen);
+ if (declarator == NULL)
+ return NULL;
inner = set_array_declarator_inner (declarator, inner, !id_present);
return c_parser_direct_declarator_inner (parser, id_present, inner);
}
@@ -2455,6 +2535,8 @@ c_parser_parms_declarator (c_parser *parser, bool id_list_ok, tree attrs)
ret->tags = 0;
ret->types = list;
ret->others = 0;
+ ret->pending_sizes = 0;
+ ret->had_vla_unspec = 0;
c_parser_consume_token (parser);
pop_scope ();
return ret;
@@ -2496,6 +2578,8 @@ c_parser_parms_list_declarator (c_parser *parser, tree attrs)
ret->tags = 0;
ret->types = 0;
ret->others = 0;
+ ret->pending_sizes = 0;
+ ret->had_vla_unspec = 0;
c_parser_consume_token (parser);
return ret;
}
@@ -2505,6 +2589,8 @@ c_parser_parms_list_declarator (c_parser *parser, tree attrs)
ret->parms = 0;
ret->tags = 0;
ret->others = 0;
+ ret->pending_sizes = 0;
+ ret->had_vla_unspec = 0;
/* Suppress -Wold-style-definition for this case. */
ret->types = error_mark_node;
error ("ISO C requires a named argument before %<...%>");
@@ -2555,6 +2641,8 @@ c_parser_parms_list_declarator (c_parser *parser, tree attrs)
ret->tags = 0;
ret->types = 0;
ret->others = 0;
+ ret->pending_sizes = 0;
+ ret->had_vla_unspec = 0;
return ret;
}
}
@@ -2580,6 +2668,8 @@ c_parser_parms_list_declarator (c_parser *parser, tree attrs)
ret->tags = 0;
ret->types = 0;
ret->others = 0;
+ ret->pending_sizes = 0;
+ ret->had_vla_unspec = 0;
return ret;
}
}
@@ -2645,8 +2735,8 @@ c_parser_parameter_declaration (c_parser *parser, tree attrs)
string-literal
??? At present, following the old parser, the caller needs to have
- set c_lex_string_translate to 0. It would be better to follow the
- C++ parser rather than using the c_lex_string_translate kludge. */
+ set lex_untranslated_string to 1. It would be better to follow the
+ C++ parser rather than using this kludge. */
static tree
c_parser_asm_string_literal (c_parser *parser)
@@ -2685,16 +2775,16 @@ c_parser_simple_asm_expr (c_parser *parser)
tree str;
gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
/* ??? Follow the C++ parser rather than using the
- c_lex_string_translate kludge. */
- c_lex_string_translate = 0;
+ lex_untranslated_string kludge. */
+ parser->lex_untranslated_string = true;
c_parser_consume_token (parser);
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
- c_lex_string_translate = 1;
+ parser->lex_untranslated_string = false;
return NULL_TREE;
}
str = c_parser_asm_string_literal (parser);
- c_lex_string_translate = 1;
+ parser->lex_untranslated_string = false;
if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
{
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
@@ -2737,17 +2827,17 @@ c_parser_attributes (c_parser *parser)
while (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
{
/* ??? Follow the C++ parser rather than using the
- c_lex_string_translate kludge. */
- c_lex_string_translate = 0;
+ lex_untranslated_string kludge. */
+ parser->lex_untranslated_string = true;
c_parser_consume_token (parser);
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
- c_lex_string_translate = 1;
+ parser->lex_untranslated_string = false;
return attrs;
}
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
- c_lex_string_translate = 1;
+ parser->lex_untranslated_string = false;
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
return attrs;
}
@@ -2793,6 +2883,9 @@ c_parser_attributes (c_parser *parser)
case RID_DFLOAT64:
case RID_DFLOAT128:
case RID_BOOL:
+ case RID_FRACT:
+ case RID_ACCUM:
+ case RID_SAT:
ok = true;
break;
default:
@@ -2844,7 +2937,7 @@ c_parser_attributes (c_parser *parser)
c_parser_consume_token (parser);
else
{
- c_lex_string_translate = 1;
+ parser->lex_untranslated_string = false;
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
"expected %<)%>");
return attrs;
@@ -2855,7 +2948,7 @@ c_parser_attributes (c_parser *parser)
c_parser_consume_token (parser);
else
{
- c_lex_string_translate = 1;
+ parser->lex_untranslated_string = false;
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
"expected %<)%>");
return attrs;
@@ -2864,12 +2957,12 @@ c_parser_attributes (c_parser *parser)
c_parser_consume_token (parser);
else
{
- c_lex_string_translate = 1;
+ parser->lex_untranslated_string = false;
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
"expected %<)%>");
return attrs;
}
- c_lex_string_translate = 1;
+ parser->lex_untranslated_string = false;
}
return attrs;
}
@@ -3256,7 +3349,16 @@ c_parser_initval (c_parser *parser, struct c_expr *after)
prefix attributes on the declaration. ??? The syntax follows the
old parser in requiring something after label declarations.
Although they are erroneous if the labels declared aren't defined,
- is it useful for the syntax to be this way? */
+ is it useful for the syntax to be this way?
+
+ OpenMP:
+
+ block-item:
+ openmp-directive
+
+ openmp-directive:
+ barrier-directive
+ flush-directive */
static tree
c_parser_compound_statement (c_parser *parser)
@@ -3402,6 +3504,8 @@ c_parser_compound_statement_nostart (c_parser *parser)
last_stmt = true;
c_parser_statement_after_labels (parser);
}
+
+ parser->error = false;
}
if (last_label)
error ("label at end of compound statement");
@@ -3527,7 +3631,53 @@ c_parser_label (c_parser *parser)
objc-throw-statement:
@throw expression ;
@throw ;
-*/
+
+ OpenMP:
+
+ statement:
+ openmp-construct
+
+ openmp-construct:
+ parallel-construct
+ for-construct
+ sections-construct
+ single-construct
+ parallel-for-construct
+ parallel-sections-construct
+ master-construct
+ critical-construct
+ atomic-construct
+ ordered-construct
+
+ parallel-construct:
+ parallel-directive structured-block
+
+ for-construct:
+ for-directive iteration-statement
+
+ sections-construct:
+ sections-directive section-scope
+
+ single-construct:
+ single-directive structured-block
+
+ parallel-for-construct:
+ parallel-for-directive iteration-statement
+
+ parallel-sections-construct:
+ parallel-sections-directive section-scope
+
+ master-construct:
+ master-directive structured-block
+
+ critical-construct:
+ critical-directive structured-block
+
+ atomic-construct:
+ atomic-directive expression-statement
+
+ ordered-construct:
+ ordered-directive structured-block */
static void
c_parser_statement (c_parser *parser)
@@ -3668,7 +3818,7 @@ c_parser_statement_after_labels (c_parser *parser)
(recursively) all of the component statements should already have
line numbers assigned. ??? Can we discard no-op statements
earlier? */
- if (stmt && EXPR_P (stmt))
+ if (stmt && CAN_HAVE_LOCATION_P (stmt))
SET_EXPR_LOCATION (stmt, loc);
}
@@ -3687,7 +3837,7 @@ c_parser_paren_condition (c_parser *parser)
loc = c_parser_peek_token (parser)->location;
cond = c_objc_common_truthvalue_conversion
(c_parser_expression_conv (parser).value);
- if (EXPR_P (cond))
+ if (CAN_HAVE_LOCATION_P (cond))
SET_EXPR_LOCATION (cond, loc);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
return cond;
@@ -3707,7 +3857,7 @@ c_parser_c99_block_statement (c_parser *parser)
is just parsing a statement but (a) it is a block in C99, (b) we
track whether the body is an if statement for the sake of
-Wparentheses warnings, (c) we handle an empty body specially for
- the sake of -Wextra warnings. */
+ the sake of -Wempty-body warnings. */
static tree
c_parser_if_body (c_parser *parser, bool *if_p)
@@ -3719,8 +3869,8 @@ c_parser_if_body (c_parser *parser, bool *if_p)
&& c_parser_peek_2nd_token (parser)->type == CPP_COLON))
c_parser_label (parser);
*if_p = c_parser_next_token_is_keyword (parser, RID_IF);
- if (extra_warnings && c_parser_next_token_is (parser, CPP_SEMICOLON))
- add_stmt (build1 (NOP_EXPR, NULL_TREE, NULL_TREE));
+ if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+ add_stmt (build_empty_stmt ());
c_parser_statement_after_labels (parser);
return c_end_compound_stmt (block, flag_isoc99);
}
@@ -3828,6 +3978,9 @@ c_parser_do_statement (c_parser *parser)
location_t loc;
gcc_assert (c_parser_next_token_is_keyword (parser, RID_DO));
c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+ warning (OPT_Wempty_body,
+ "suggest braces around empty body in % statement");
block = c_begin_compound_stmt (flag_isoc99);
loc = c_parser_peek_token (parser)->location;
save_break = c_break_label;
@@ -3924,7 +4077,7 @@ c_parser_for_statement (c_parser *parser)
{
tree ocond = c_parser_expression_conv (parser).value;
cond = c_objc_common_truthvalue_conversion (ocond);
- if (EXPR_P (cond))
+ if (CAN_HAVE_LOCATION_P (cond))
SET_EXPR_LOCATION (cond, loc);
c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
}
@@ -3990,11 +4143,11 @@ c_parser_asm_statement (c_parser *parser)
else
quals = NULL_TREE;
/* ??? Follow the C++ parser rather than using the
- c_lex_string_translate kludge. */
- c_lex_string_translate = 0;
+ lex_untranslated_string kludge. */
+ parser->lex_untranslated_string = true;
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
- c_lex_string_translate = 1;
+ parser->lex_untranslated_string = false;
return NULL_TREE;
}
str = c_parser_asm_string_literal (parser);
@@ -4008,7 +4161,7 @@ c_parser_asm_statement (c_parser *parser)
}
if (!c_parser_require (parser, CPP_COLON, "expected %<:%> or %<)%>"))
{
- c_lex_string_translate = 1;
+ parser->lex_untranslated_string = false;
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
return NULL_TREE;
}
@@ -4027,7 +4180,7 @@ c_parser_asm_statement (c_parser *parser)
}
if (!c_parser_require (parser, CPP_COLON, "expected %<:%> or %<)%>"))
{
- c_lex_string_translate = 1;
+ parser->lex_untranslated_string = false;
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
return NULL_TREE;
}
@@ -4044,14 +4197,14 @@ c_parser_asm_statement (c_parser *parser)
}
if (!c_parser_require (parser, CPP_COLON, "expected %<:%> or %<)%>"))
{
- c_lex_string_translate = 1;
+ parser->lex_untranslated_string = false;
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
return NULL_TREE;
}
/* Parse clobbers. */
clobbers = c_parser_asm_clobbers (parser);
done_asm:
- c_lex_string_translate = 1;
+ parser->lex_untranslated_string = false;
if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
{
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
@@ -4109,16 +4262,16 @@ c_parser_asm_operands (c_parser *parser, bool convert_p)
str = c_parser_asm_string_literal (parser);
if (str == NULL_TREE)
return NULL_TREE;
- c_lex_string_translate = 1;
+ parser->lex_untranslated_string = false;
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
- c_lex_string_translate = 0;
+ parser->lex_untranslated_string = true;
return NULL_TREE;
}
expr = c_parser_expression (parser);
if (convert_p)
expr = default_function_array_conversion (expr);
- c_lex_string_translate = 0;
+ parser->lex_untranslated_string = true;
if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
{
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
@@ -4576,6 +4729,10 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after)
ret.original_code = ERROR_MARK;
return ret;
}
+
+ /* Save casted types in the function's used types hash table. */
+ used_types_insert (type_name->specs->type);
+
if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
return c_parser_postfix_expression_after_paren_type (parser,
type_name);
@@ -4751,6 +4908,12 @@ c_parser_sizeof_expression (c_parser *parser)
/* sizeof ( type-name ). */
skip_evaluation--;
in_sizeof--;
+ if (type_name->declarator->kind == cdk_array
+ && type_name->declarator->u.array.vla_unspec_p)
+ {
+ /* C99 6.7.5.2p4 */
+ error ("%<[*]%> not allowed in other than a declaration");
+ }
return c_expr_sizeof_type (type_name);
}
else
@@ -5049,7 +5212,7 @@ c_parser_postfix_expression (c_parser *parser)
if (type == error_mark_node)
offsetof_ref = error_mark_node;
else
- offsetof_ref = build1 (INDIRECT_REF, type, NULL);
+ offsetof_ref = build1 (INDIRECT_REF, type, null_pointer_node);
/* Parse the second argument to __builtin_offsetof. We
must have one identifier, and beyond that we want to
accept sub structure and sub array references. */
@@ -5091,7 +5254,7 @@ c_parser_postfix_expression (c_parser *parser)
c_parser_error (parser, "expected identifier");
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
"expected %<)%>");
- expr.value = fold_offsetof (offsetof_ref);
+ expr.value = fold_offsetof (offsetof_ref, NULL_TREE);
expr.original_code = ERROR_MARK;
}
break;
@@ -5292,7 +5455,7 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser,
struct c_expr expr;
start_init (NULL_TREE, NULL, 0);
type = groktypename (type_name);
- if (C_TYPE_VARIABLE_SIZE (type))
+ if (type != error_mark_node && C_TYPE_VARIABLE_SIZE (type))
{
error ("compound literal has variable size");
type = error_mark_node;
@@ -5769,11 +5932,11 @@ c_parser_objc_protocol_definition (c_parser *parser)
c_parser_consume_token (parser);
if (c_parser_next_token_is (parser, CPP_LESS))
proto = c_parser_objc_protocol_refs (parser);
- objc_pq_context = 1;
+ parser->objc_pq_context = true;
objc_start_protocol (id, proto);
c_parser_objc_methodprotolist (parser);
c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>");
- objc_pq_context = 0;
+ parser->objc_pq_context = false;
objc_finish_interface ();
}
}
@@ -5813,7 +5976,7 @@ c_parser_objc_method_definition (c_parser *parser)
enum tree_code type = c_parser_objc_method_type (parser);
tree decl;
objc_set_method_type (type);
- objc_pq_context = 1;
+ parser->objc_pq_context = true;
decl = c_parser_objc_method_decl (parser);
if (c_parser_next_token_is (parser, CPP_SEMICOLON))
{
@@ -5826,7 +5989,7 @@ c_parser_objc_method_definition (c_parser *parser)
c_parser_error (parser, "expected %<{%>");
return;
}
- objc_pq_context = 0;
+ parser->objc_pq_context = false;
objc_start_method_definition (decl);
add_stmt (c_parser_compound_statement (parser));
objc_finish_method_definition (current_function_decl);
@@ -5890,10 +6053,10 @@ c_parser_objc_methodproto (c_parser *parser)
tree decl;
objc_set_method_type (type);
/* Remember protocol qualifiers in prototypes. */
- objc_pq_context = 1;
+ parser->objc_pq_context = true;
decl = c_parser_objc_method_decl (parser);
/* Forget protocol qualifiers here. */
- objc_pq_context = 0;
+ parser->objc_pq_context = false;
objc_add_method_declaration (decl);
c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
}
@@ -6344,12 +6507,13 @@ c_parser_objc_keywordexpr (c_parser *parser)
}
-/* Handle pragmas. ALLOW_STMT is true if we're within the context of
- a function and such pragmas are to be allowed. Returns true if we
- actually parsed such a pragma. */
+/* Handle pragmas. Some OpenMP pragmas are associated with, and therefore
+ should be considered, statements. ALLOW_STMT is true if we're within
+ the context of a function and such pragmas are to be allowed. Returns
+ true if we actually parsed such a pragma. */
static bool
-c_parser_pragma (c_parser *parser, enum pragma_context context ATTRIBUTE_UNUSED)
+c_parser_pragma (c_parser *parser, enum pragma_context context)
{
unsigned int id;
@@ -6358,13 +6522,56 @@ c_parser_pragma (c_parser *parser, enum pragma_context context ATTRIBUTE_UNUSED)
switch (id)
{
+ case PRAGMA_OMP_BARRIER:
+ if (context != pragma_compound)
+ {
+ if (context == pragma_stmt)
+ c_parser_error (parser, "%<#pragma omp barrier%> may only be "
+ "used in compound statements");
+ goto bad_stmt;
+ }
+ c_parser_omp_barrier (parser);
+ return false;
+
+ case PRAGMA_OMP_FLUSH:
+ if (context != pragma_compound)
+ {
+ if (context == pragma_stmt)
+ c_parser_error (parser, "%<#pragma omp flush%> may only be "
+ "used in compound statements");
+ goto bad_stmt;
+ }
+ c_parser_omp_flush (parser);
+ return false;
+
+ case PRAGMA_OMP_THREADPRIVATE:
+ c_parser_omp_threadprivate (parser);
+ return false;
+
+ case PRAGMA_OMP_SECTION:
+ error ("%<#pragma omp section%> may only be used in "
+ "%<#pragma omp sections%> construct");
+ c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
+ return false;
+
case PRAGMA_GCC_PCH_PREPROCESS:
c_parser_error (parser, "%<#pragma GCC pch_preprocess%> must be first");
c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
return false;
default:
- gcc_assert (id >= PRAGMA_FIRST_EXTERNAL);
+ if (id < PRAGMA_FIRST_EXTERNAL)
+ {
+ if (context == pragma_external)
+ {
+ bad_stmt:
+ c_parser_error (parser, "expected declaration specifiers");
+ c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
+ return false;
+ }
+ c_parser_omp_construct (parser);
+ return true;
+ }
break;
}
@@ -6420,6 +6627,1222 @@ c_parser_pragma_pch_preprocess (c_parser *parser)
c_common_pch_pragma (parse_in, TREE_STRING_POINTER (name));
}
+/* OpenMP 2.5 parsing routines. */
+
+/* Returns name of the next clause.
+ If the clause is not recognized PRAGMA_OMP_CLAUSE_NONE is returned and
+ the token is not consumed. Otherwise appropriate pragma_omp_clause is
+ returned and the token is consumed. */
+
+static pragma_omp_clause
+c_parser_omp_clause_name (c_parser *parser)
+{
+ pragma_omp_clause result = PRAGMA_OMP_CLAUSE_NONE;
+
+ if (c_parser_next_token_is_keyword (parser, RID_IF))
+ result = PRAGMA_OMP_CLAUSE_IF;
+ else if (c_parser_next_token_is_keyword (parser, RID_DEFAULT))
+ result = PRAGMA_OMP_CLAUSE_DEFAULT;
+ else if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+
+ switch (p[0])
+ {
+ case 'c':
+ if (!strcmp ("copyin", p))
+ result = PRAGMA_OMP_CLAUSE_COPYIN;
+ else if (!strcmp ("copyprivate", p))
+ result = PRAGMA_OMP_CLAUSE_COPYPRIVATE;
+ break;
+ case 'f':
+ if (!strcmp ("firstprivate", p))
+ result = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE;
+ break;
+ case 'l':
+ if (!strcmp ("lastprivate", p))
+ result = PRAGMA_OMP_CLAUSE_LASTPRIVATE;
+ break;
+ case 'n':
+ if (!strcmp ("nowait", p))
+ result = PRAGMA_OMP_CLAUSE_NOWAIT;
+ else if (!strcmp ("num_threads", p))
+ result = PRAGMA_OMP_CLAUSE_NUM_THREADS;
+ break;
+ case 'o':
+ if (!strcmp ("ordered", p))
+ result = PRAGMA_OMP_CLAUSE_ORDERED;
+ break;
+ case 'p':
+ if (!strcmp ("private", p))
+ result = PRAGMA_OMP_CLAUSE_PRIVATE;
+ break;
+ case 'r':
+ if (!strcmp ("reduction", p))
+ result = PRAGMA_OMP_CLAUSE_REDUCTION;
+ break;
+ case 's':
+ if (!strcmp ("schedule", p))
+ result = PRAGMA_OMP_CLAUSE_SCHEDULE;
+ else if (!strcmp ("shared", p))
+ result = PRAGMA_OMP_CLAUSE_SHARED;
+ break;
+ }
+ }
+
+ if (result != PRAGMA_OMP_CLAUSE_NONE)
+ c_parser_consume_token (parser);
+
+ return result;
+}
+
+/* Validate that a clause of the given type does not already exist. */
+
+static void
+check_no_duplicate_clause (tree clauses, enum tree_code code, const char *name)
+{
+ tree c;
+
+ for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) == code)
+ {
+ error ("too many %qs clauses", name);
+ break;
+ }
+}
+
+/* OpenMP 2.5:
+ variable-list:
+ identifier
+ variable-list , identifier
+
+ If KIND is nonzero, create the appropriate node and install the decl
+ in OMP_CLAUSE_DECL and add the node to the head of the list.
+
+ If KIND is zero, create a TREE_LIST with the decl in TREE_PURPOSE;
+ return the list created. */
+
+static tree
+c_parser_omp_variable_list (c_parser *parser, enum omp_clause_code kind,
+ tree list)
+{
+ if (c_parser_next_token_is_not (parser, CPP_NAME)
+ || c_parser_peek_token (parser)->id_kind != C_ID_ID)
+ c_parser_error (parser, "expected identifier");
+
+ while (c_parser_next_token_is (parser, CPP_NAME)
+ && c_parser_peek_token (parser)->id_kind == C_ID_ID)
+ {
+ tree t = lookup_name (c_parser_peek_token (parser)->value);
+
+ if (t == NULL_TREE)
+ undeclared_variable (c_parser_peek_token (parser)->value,
+ c_parser_peek_token (parser)->location);
+ else if (t == error_mark_node)
+ ;
+ else if (kind != 0)
+ {
+ tree u = build_omp_clause (kind);
+ OMP_CLAUSE_DECL (u) = t;
+ OMP_CLAUSE_CHAIN (u) = list;
+ list = u;
+ }
+ else
+ list = tree_cons (t, NULL_TREE, list);
+
+ c_parser_consume_token (parser);
+
+ if (c_parser_next_token_is_not (parser, CPP_COMMA))
+ break;
+
+ c_parser_consume_token (parser);
+ }
+
+ return list;
+}
+
+/* Similarly, but expect leading and trailing parenthesis. This is a very
+ common case for omp clauses. */
+
+static tree
+c_parser_omp_var_list_parens (c_parser *parser, enum tree_code kind, tree list)
+{
+ if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ {
+ list = c_parser_omp_variable_list (parser, kind, list);
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+ }
+ return list;
+}
+
+/* OpenMP 2.5:
+ copyin ( variable-list ) */
+
+static tree
+c_parser_omp_clause_copyin (c_parser *parser, tree list)
+{
+ return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_COPYIN, list);
+}
+
+/* OpenMP 2.5:
+ copyprivate ( variable-list ) */
+
+static tree
+c_parser_omp_clause_copyprivate (c_parser *parser, tree list)
+{
+ return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_COPYPRIVATE, list);
+}
+
+/* OpenMP 2.5:
+ default ( shared | none ) */
+
+static tree
+c_parser_omp_clause_default (c_parser *parser, tree list)
+{
+ enum omp_clause_default_kind kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED;
+ tree c;
+
+ if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ return list;
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+
+ switch (p[0])
+ {
+ case 'n':
+ if (strcmp ("none", p) != 0)
+ goto invalid_kind;
+ kind = OMP_CLAUSE_DEFAULT_NONE;
+ break;
+
+ case 's':
+ if (strcmp ("shared", p) != 0)
+ goto invalid_kind;
+ kind = OMP_CLAUSE_DEFAULT_SHARED;
+ break;
+
+ default:
+ goto invalid_kind;
+ }
+
+ c_parser_consume_token (parser);
+ }
+ else
+ {
+ invalid_kind:
+ c_parser_error (parser, "expected % or %");
+ }
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+
+ if (kind == OMP_CLAUSE_DEFAULT_UNSPECIFIED)
+ return list;
+
+ check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULT, "default");
+ c = build_omp_clause (OMP_CLAUSE_DEFAULT);
+ OMP_CLAUSE_CHAIN (c) = list;
+ OMP_CLAUSE_DEFAULT_KIND (c) = kind;
+
+ return c;
+}
+
+/* OpenMP 2.5:
+ firstprivate ( variable-list ) */
+
+static tree
+c_parser_omp_clause_firstprivate (c_parser *parser, tree list)
+{
+ return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_FIRSTPRIVATE, list);
+}
+
+/* OpenMP 2.5:
+ if ( expression ) */
+
+static tree
+c_parser_omp_clause_if (c_parser *parser, tree list)
+{
+ if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+ {
+ tree t = c_parser_paren_condition (parser);
+ tree c;
+
+ check_no_duplicate_clause (list, OMP_CLAUSE_IF, "if");
+
+ c = build_omp_clause (OMP_CLAUSE_IF);
+ OMP_CLAUSE_IF_EXPR (c) = t;
+ OMP_CLAUSE_CHAIN (c) = list;
+ list = c;
+ }
+ else
+ c_parser_error (parser, "expected %<(%>");
+
+ return list;
+}
+
+/* OpenMP 2.5:
+ lastprivate ( variable-list ) */
+
+static tree
+c_parser_omp_clause_lastprivate (c_parser *parser, tree list)
+{
+ return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_LASTPRIVATE, list);
+}
+
+/* OpenMP 2.5:
+ nowait */
+
+static tree
+c_parser_omp_clause_nowait (c_parser *parser ATTRIBUTE_UNUSED, tree list)
+{
+ tree c;
+
+ check_no_duplicate_clause (list, OMP_CLAUSE_NOWAIT, "nowait");
+
+ c = build_omp_clause (OMP_CLAUSE_NOWAIT);
+ OMP_CLAUSE_CHAIN (c) = list;
+ return c;
+}
+
+/* OpenMP 2.5:
+ num_threads ( expression ) */
+
+static tree
+c_parser_omp_clause_num_threads (c_parser *parser, tree list)
+{
+ if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ {
+ tree c, t = c_parser_expression (parser).value;
+
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
+ {
+ c_parser_error (parser, "expected integer expression");
+ return list;
+ }
+
+ /* Attempt to statically determine when the number isn't positive. */
+ c = fold_build2 (LE_EXPR, boolean_type_node, t,
+ build_int_cst (TREE_TYPE (t), 0));
+ if (c == boolean_true_node)
+ {
+ warning (0, "% value must be positive");
+ t = integer_one_node;
+ }
+
+ check_no_duplicate_clause (list, OMP_CLAUSE_NUM_THREADS, "num_threads");
+
+ c = build_omp_clause (OMP_CLAUSE_NUM_THREADS);
+ OMP_CLAUSE_NUM_THREADS_EXPR (c) = t;
+ OMP_CLAUSE_CHAIN (c) = list;
+ list = c;
+ }
+
+ return list;
+}
+
+/* OpenMP 2.5:
+ ordered */
+
+static tree
+c_parser_omp_clause_ordered (c_parser *parser ATTRIBUTE_UNUSED, tree list)
+{
+ tree c;
+
+ check_no_duplicate_clause (list, OMP_CLAUSE_ORDERED, "ordered");
+
+ c = build_omp_clause (OMP_CLAUSE_ORDERED);
+ OMP_CLAUSE_CHAIN (c) = list;
+ return c;
+}
+
+/* OpenMP 2.5:
+ private ( variable-list ) */
+
+static tree
+c_parser_omp_clause_private (c_parser *parser, tree list)
+{
+ return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_PRIVATE, list);
+}
+
+/* OpenMP 2.5:
+ reduction ( reduction-operator : variable-list )
+
+ reduction-operator:
+ One of: + * - & ^ | && || */
+
+static tree
+c_parser_omp_clause_reduction (c_parser *parser, tree list)
+{
+ if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ {
+ enum tree_code code;
+
+ switch (c_parser_peek_token (parser)->type)
+ {
+ case CPP_PLUS:
+ code = PLUS_EXPR;
+ break;
+ case CPP_MULT:
+ code = MULT_EXPR;
+ break;
+ case CPP_MINUS:
+ code = MINUS_EXPR;
+ break;
+ case CPP_AND:
+ code = BIT_AND_EXPR;
+ break;
+ case CPP_XOR:
+ code = BIT_XOR_EXPR;
+ break;
+ case CPP_OR:
+ code = BIT_IOR_EXPR;
+ break;
+ case CPP_AND_AND:
+ code = TRUTH_ANDIF_EXPR;
+ break;
+ case CPP_OR_OR:
+ code = TRUTH_ORIF_EXPR;
+ break;
+ default:
+ c_parser_error (parser,
+ "expected %<+%>, %<*%>, %<-%>, %<&%>, "
+ "%<^%>, %<|%>, %<&&%>, or %<||%>");
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, 0);
+ return list;
+ }
+ c_parser_consume_token (parser);
+ if (c_parser_require (parser, CPP_COLON, "expected %<:%>"))
+ {
+ tree nl, c;
+
+ nl = c_parser_omp_variable_list (parser, OMP_CLAUSE_REDUCTION, list);
+ for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
+ OMP_CLAUSE_REDUCTION_CODE (c) = code;
+
+ list = nl;
+ }
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+ }
+ return list;
+}
+
+/* OpenMP 2.5:
+ schedule ( schedule-kind )
+ schedule ( schedule-kind , expression )
+
+ schedule-kind:
+ static | dynamic | guided | runtime
+*/
+
+static tree
+c_parser_omp_clause_schedule (c_parser *parser, tree list)
+{
+ tree c, t;
+
+ if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ return list;
+
+ c = build_omp_clause (OMP_CLAUSE_SCHEDULE);
+
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ tree kind = c_parser_peek_token (parser)->value;
+ const char *p = IDENTIFIER_POINTER (kind);
+
+ switch (p[0])
+ {
+ case 'd':
+ if (strcmp ("dynamic", p) != 0)
+ goto invalid_kind;
+ OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_DYNAMIC;
+ break;
+
+ case 'g':
+ if (strcmp ("guided", p) != 0)
+ goto invalid_kind;
+ OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_GUIDED;
+ break;
+
+ case 'r':
+ if (strcmp ("runtime", p) != 0)
+ goto invalid_kind;
+ OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_RUNTIME;
+ break;
+
+ default:
+ goto invalid_kind;
+ }
+ }
+ else if (c_parser_next_token_is_keyword (parser, RID_STATIC))
+ OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_STATIC;
+ else
+ goto invalid_kind;
+
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_COMMA))
+ {
+ c_parser_consume_token (parser);
+
+ t = c_parser_expr_no_commas (parser, NULL).value;
+
+ if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME)
+ error ("schedule % does not take "
+ "a % parameter");
+ else if (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE)
+ OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
+ else
+ c_parser_error (parser, "expected integer expression");
+
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+ }
+ else
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+ "expected %<,%> or %<)%>");
+
+ check_no_duplicate_clause (list, OMP_CLAUSE_SCHEDULE, "schedule");
+ OMP_CLAUSE_CHAIN (c) = list;
+ return c;
+
+ invalid_kind:
+ c_parser_error (parser, "invalid schedule kind");
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, 0);
+ return list;
+}
+
+/* OpenMP 2.5:
+ shared ( variable-list ) */
+
+static tree
+c_parser_omp_clause_shared (c_parser *parser, tree list)
+{
+ return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_SHARED, list);
+}
+
+/* Parse all OpenMP clauses. The set clauses allowed by the directive
+ is a bitmask in MASK. Return the list of clauses found; the result
+ of clause default goes in *pdefault. */
+
+static tree
+c_parser_omp_all_clauses (c_parser *parser, unsigned int mask,
+ const char *where)
+{
+ tree clauses = NULL;
+
+ while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
+ {
+ const pragma_omp_clause c_kind = c_parser_omp_clause_name (parser);
+ const char *c_name;
+ tree prev = clauses;
+
+ switch (c_kind)
+ {
+ case PRAGMA_OMP_CLAUSE_COPYIN:
+ clauses = c_parser_omp_clause_copyin (parser, clauses);
+ c_name = "copyin";
+ break;
+ case PRAGMA_OMP_CLAUSE_COPYPRIVATE:
+ clauses = c_parser_omp_clause_copyprivate (parser, clauses);
+ c_name = "copyprivate";
+ break;
+ case PRAGMA_OMP_CLAUSE_DEFAULT:
+ clauses = c_parser_omp_clause_default (parser, clauses);
+ c_name = "default";
+ break;
+ case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE:
+ clauses = c_parser_omp_clause_firstprivate (parser, clauses);
+ c_name = "firstprivate";
+ break;
+ case PRAGMA_OMP_CLAUSE_IF:
+ clauses = c_parser_omp_clause_if (parser, clauses);
+ c_name = "if";
+ break;
+ case PRAGMA_OMP_CLAUSE_LASTPRIVATE:
+ clauses = c_parser_omp_clause_lastprivate (parser, clauses);
+ c_name = "lastprivate";
+ break;
+ case PRAGMA_OMP_CLAUSE_NOWAIT:
+ clauses = c_parser_omp_clause_nowait (parser, clauses);
+ c_name = "nowait";
+ break;
+ case PRAGMA_OMP_CLAUSE_NUM_THREADS:
+ clauses = c_parser_omp_clause_num_threads (parser, clauses);
+ c_name = "num_threads";
+ break;
+ case PRAGMA_OMP_CLAUSE_ORDERED:
+ clauses = c_parser_omp_clause_ordered (parser, clauses);
+ c_name = "ordered";
+ break;
+ case PRAGMA_OMP_CLAUSE_PRIVATE:
+ clauses = c_parser_omp_clause_private (parser, clauses);
+ c_name = "private";
+ break;
+ case PRAGMA_OMP_CLAUSE_REDUCTION:
+ clauses = c_parser_omp_clause_reduction (parser, clauses);
+ c_name = "reduction";
+ break;
+ case PRAGMA_OMP_CLAUSE_SCHEDULE:
+ clauses = c_parser_omp_clause_schedule (parser, clauses);
+ c_name = "schedule";
+ break;
+ case PRAGMA_OMP_CLAUSE_SHARED:
+ clauses = c_parser_omp_clause_shared (parser, clauses);
+ c_name = "shared";
+ break;
+ default:
+ c_parser_error (parser, "expected %<#pragma omp%> clause");
+ goto saw_error;
+ }
+
+ if (((mask >> c_kind) & 1) == 0 && !parser->error)
+ {
+ /* Remove the invalid clause(s) from the list to avoid
+ confusing the rest of the compiler. */
+ clauses = prev;
+ error ("%qs is not valid for %qs", c_name, where);
+ }
+ }
+
+ saw_error:
+ c_parser_skip_to_pragma_eol (parser);
+
+ return c_finish_omp_clauses (clauses);
+}
+
+/* OpenMP 2.5:
+ structured-block:
+ statement
+
+ In practice, we're also interested in adding the statement to an
+ outer node. So it is convenient if we work around the fact that
+ c_parser_statement calls add_stmt. */
+
+static tree
+c_parser_omp_structured_block (c_parser *parser)
+{
+ tree stmt = push_stmt_list ();
+ c_parser_statement (parser);
+ return pop_stmt_list (stmt);
+}
+
+/* OpenMP 2.5:
+ # pragma omp atomic new-line
+ expression-stmt
+
+ expression-stmt:
+ x binop= expr | x++ | ++x | x-- | --x
+ binop:
+ +, *, -, /, &, ^, |, <<, >>
+
+ where x is an lvalue expression with scalar type. */
+
+static void
+c_parser_omp_atomic (c_parser *parser)
+{
+ tree lhs, rhs;
+ tree stmt;
+ enum tree_code code;
+
+ c_parser_skip_to_pragma_eol (parser);
+
+ lhs = c_parser_unary_expression (parser).value;
+ switch (TREE_CODE (lhs))
+ {
+ case ERROR_MARK:
+ saw_error:
+ c_parser_skip_to_end_of_block_or_statement (parser);
+ return;
+
+ case PREINCREMENT_EXPR:
+ case POSTINCREMENT_EXPR:
+ lhs = TREE_OPERAND (lhs, 0);
+ code = PLUS_EXPR;
+ rhs = integer_one_node;
+ break;
+
+ case PREDECREMENT_EXPR:
+ case POSTDECREMENT_EXPR:
+ lhs = TREE_OPERAND (lhs, 0);
+ code = MINUS_EXPR;
+ rhs = integer_one_node;
+ break;
+
+ default:
+ switch (c_parser_peek_token (parser)->type)
+ {
+ case CPP_MULT_EQ:
+ code = MULT_EXPR;
+ break;
+ case CPP_DIV_EQ:
+ code = TRUNC_DIV_EXPR;
+ break;
+ case CPP_PLUS_EQ:
+ code = PLUS_EXPR;
+ break;
+ case CPP_MINUS_EQ:
+ code = MINUS_EXPR;
+ break;
+ case CPP_LSHIFT_EQ:
+ code = LSHIFT_EXPR;
+ break;
+ case CPP_RSHIFT_EQ:
+ code = RSHIFT_EXPR;
+ break;
+ case CPP_AND_EQ:
+ code = BIT_AND_EXPR;
+ break;
+ case CPP_OR_EQ:
+ code = BIT_IOR_EXPR;
+ break;
+ case CPP_XOR_EQ:
+ code = BIT_XOR_EXPR;
+ break;
+ default:
+ c_parser_error (parser,
+ "invalid operator for %<#pragma omp atomic%>");
+ goto saw_error;
+ }
+
+ c_parser_consume_token (parser);
+ rhs = c_parser_expression (parser).value;
+ break;
+ }
+ stmt = c_finish_omp_atomic (code, lhs, rhs);
+ if (stmt != error_mark_node)
+ add_stmt (stmt);
+ c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+}
+
+
+/* OpenMP 2.5:
+ # pragma omp barrier new-line
+*/
+
+static void
+c_parser_omp_barrier (c_parser *parser)
+{
+ c_parser_consume_pragma (parser);
+ c_parser_skip_to_pragma_eol (parser);
+
+ c_finish_omp_barrier ();
+}
+
+/* OpenMP 2.5:
+ # pragma omp critical [(name)] new-line
+ structured-block
+*/
+
+static tree
+c_parser_omp_critical (c_parser *parser)
+{
+ tree stmt, name = NULL;
+
+ if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+ {
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ name = c_parser_peek_token (parser)->value;
+ c_parser_consume_token (parser);
+ c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+ }
+ else
+ c_parser_error (parser, "expected identifier");
+ }
+ else if (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
+ c_parser_error (parser, "expected %<(%> or end of line");
+ c_parser_skip_to_pragma_eol (parser);
+
+ stmt = c_parser_omp_structured_block (parser);
+ return c_finish_omp_critical (stmt, name);
+}
+
+/* OpenMP 2.5:
+ # pragma omp flush flush-vars[opt] new-line
+
+ flush-vars:
+ ( variable-list ) */
+
+static void
+c_parser_omp_flush (c_parser *parser)
+{
+ c_parser_consume_pragma (parser);
+ if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+ c_parser_omp_var_list_parens (parser, 0, NULL);
+ else if (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
+ c_parser_error (parser, "expected %<(%> or end of line");
+ c_parser_skip_to_pragma_eol (parser);
+
+ c_finish_omp_flush ();
+}
+
+/* Parse the restricted form of the for statment allowed by OpenMP.
+ The real trick here is to determine the loop control variable early
+ so that we can push a new decl if necessary to make it private. */
+
+static tree
+c_parser_omp_for_loop (c_parser *parser)
+{
+ tree decl, cond, incr, save_break, save_cont, body, init;
+ location_t loc;
+
+ if (!c_parser_next_token_is_keyword (parser, RID_FOR))
+ {
+ c_parser_error (parser, "for statement expected");
+ return NULL;
+ }
+ loc = c_parser_peek_token (parser)->location;
+ c_parser_consume_token (parser);
+
+ if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ return NULL;
+
+ /* Parse the initialization declaration or expression. */
+ if (c_parser_next_token_starts_declspecs (parser))
+ {
+ c_parser_declaration_or_fndef (parser, true, true, true, true);
+ decl = check_for_loop_decls ();
+ if (decl == NULL)
+ goto error_init;
+ init = decl;
+ }
+ else if (c_parser_next_token_is (parser, CPP_NAME)
+ && c_parser_peek_2nd_token (parser)->type == CPP_EQ)
+ {
+ decl = c_parser_postfix_expression (parser).value;
+
+ c_parser_require (parser, CPP_EQ, "expected %<=%>");
+
+ init = c_parser_expr_no_commas (parser, NULL).value;
+ init = build_modify_expr (decl, NOP_EXPR, init);
+ init = c_process_expr_stmt (init);
+
+ c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+ }
+ else
+ goto error_init;
+
+ /* Parse the loop condition. */
+ cond = NULL_TREE;
+ if (c_parser_next_token_is_not (parser, CPP_SEMICOLON))
+ {
+ cond = c_parser_expression_conv (parser).value;
+ cond = c_objc_common_truthvalue_conversion (cond);
+ if (CAN_HAVE_LOCATION_P (cond))
+ SET_EXPR_LOCATION (cond, input_location);
+ }
+ c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+
+ /* Parse the increment expression. */
+ incr = NULL_TREE;
+ if (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
+ incr = c_process_expr_stmt (c_parser_expression (parser).value);
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+
+ parse_body:
+ save_break = c_break_label;
+ c_break_label = size_one_node;
+ save_cont = c_cont_label;
+ c_cont_label = NULL_TREE;
+ body = push_stmt_list ();
+
+ add_stmt (c_parser_c99_block_statement (parser));
+ if (c_cont_label)
+ add_stmt (build1 (LABEL_EXPR, void_type_node, c_cont_label));
+
+ body = pop_stmt_list (body);
+ c_break_label = save_break;
+ c_cont_label = save_cont;
+
+ /* Only bother calling c_finish_omp_for if we havn't already generated
+ an error from the initialization parsing. */
+ if (decl != NULL && decl != error_mark_node && init != error_mark_node)
+ return c_finish_omp_for (loc, decl, init, cond, incr, body, NULL);
+ return NULL;
+
+ error_init:
+ c_parser_error (parser, "expected iteration declaration or initialization");
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+ decl = init = cond = incr = NULL_TREE;
+ goto parse_body;
+}
+
+/* OpenMP 2.5:
+ #pragma omp for for-clause[optseq] new-line
+ for-loop
+*/
+
+#define OMP_FOR_CLAUSE_MASK \
+ ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \
+ | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
+ | (1u << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
+ | (1u << PRAGMA_OMP_CLAUSE_REDUCTION) \
+ | (1u << PRAGMA_OMP_CLAUSE_ORDERED) \
+ | (1u << PRAGMA_OMP_CLAUSE_SCHEDULE) \
+ | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
+
+static tree
+c_parser_omp_for (c_parser *parser)
+{
+ tree block, clauses, ret;
+
+ clauses = c_parser_omp_all_clauses (parser, OMP_FOR_CLAUSE_MASK,
+ "#pragma omp for");
+
+ block = c_begin_compound_stmt (true);
+ ret = c_parser_omp_for_loop (parser);
+ if (ret)
+ OMP_FOR_CLAUSES (ret) = clauses;
+ block = c_end_compound_stmt (block, true);
+ add_stmt (block);
+
+ return ret;
+}
+
+/* OpenMP 2.5:
+ # pragma omp master new-line
+ structured-block
+*/
+
+static tree
+c_parser_omp_master (c_parser *parser)
+{
+ c_parser_skip_to_pragma_eol (parser);
+ return c_finish_omp_master (c_parser_omp_structured_block (parser));
+}
+
+/* OpenMP 2.5:
+ # pragma omp ordered new-line
+ structured-block
+*/
+
+static tree
+c_parser_omp_ordered (c_parser *parser)
+{
+ c_parser_skip_to_pragma_eol (parser);
+ return c_finish_omp_ordered (c_parser_omp_structured_block (parser));
+}
+
+/* OpenMP 2.5:
+
+ section-scope:
+ { section-sequence }
+
+ section-sequence:
+ section-directive[opt] structured-block
+ section-sequence section-directive structured-block */
+
+static tree
+c_parser_omp_sections_scope (c_parser *parser)
+{
+ tree stmt, substmt;
+ bool error_suppress = false;
+ location_t loc;
+
+ if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
+ {
+ /* Avoid skipping until the end of the block. */
+ parser->error = false;
+ return NULL_TREE;
+ }
+
+ stmt = push_stmt_list ();
+
+ loc = c_parser_peek_token (parser)->location;
+ if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_SECTION)
+ {
+ substmt = push_stmt_list ();
+
+ while (1)
+ {
+ c_parser_statement (parser);
+
+ if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_OMP_SECTION)
+ break;
+ if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+ break;
+ if (c_parser_next_token_is (parser, CPP_EOF))
+ break;
+ }
+
+ substmt = pop_stmt_list (substmt);
+ substmt = build1 (OMP_SECTION, void_type_node, substmt);
+ SET_EXPR_LOCATION (substmt, loc);
+ add_stmt (substmt);
+ }
+
+ while (1)
+ {
+ if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+ break;
+ if (c_parser_next_token_is (parser, CPP_EOF))
+ break;
+
+ loc = c_parser_peek_token (parser)->location;
+ if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_OMP_SECTION)
+ {
+ c_parser_consume_pragma (parser);
+ c_parser_skip_to_pragma_eol (parser);
+ error_suppress = false;
+ }
+ else if (!error_suppress)
+ {
+ error ("expected %<#pragma omp section%> or %<}%>");
+ error_suppress = true;
+ }
+
+ substmt = c_parser_omp_structured_block (parser);
+ substmt = build1 (OMP_SECTION, void_type_node, substmt);
+ SET_EXPR_LOCATION (substmt, loc);
+ add_stmt (substmt);
+ }
+ c_parser_skip_until_found (parser, CPP_CLOSE_BRACE,
+ "expected %<#pragma omp section%> or %<}%>");
+
+ substmt = pop_stmt_list (stmt);
+
+ stmt = make_node (OMP_SECTIONS);
+ TREE_TYPE (stmt) = void_type_node;
+ OMP_SECTIONS_BODY (stmt) = substmt;
+
+ return add_stmt (stmt);
+}
+
+/* OpenMP 2.5:
+ # pragma omp sections sections-clause[optseq] newline
+ sections-scope
+*/
+
+#define OMP_SECTIONS_CLAUSE_MASK \
+ ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \
+ | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
+ | (1u << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
+ | (1u << PRAGMA_OMP_CLAUSE_REDUCTION) \
+ | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
+
+static tree
+c_parser_omp_sections (c_parser *parser)
+{
+ tree block, clauses, ret;
+
+ clauses = c_parser_omp_all_clauses (parser, OMP_SECTIONS_CLAUSE_MASK,
+ "#pragma omp sections");
+
+ block = c_begin_compound_stmt (true);
+ ret = c_parser_omp_sections_scope (parser);
+ if (ret)
+ OMP_SECTIONS_CLAUSES (ret) = clauses;
+ block = c_end_compound_stmt (block, true);
+ add_stmt (block);
+
+ return ret;
+}
+
+/* OpenMP 2.5:
+ # pragma parallel parallel-clause new-line
+ # pragma parallel for parallel-for-clause new-line
+ # pragma parallel sections parallel-sections-clause new-line
+*/
+
+#define OMP_PARALLEL_CLAUSE_MASK \
+ ( (1u << PRAGMA_OMP_CLAUSE_IF) \
+ | (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \
+ | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
+ | (1u << PRAGMA_OMP_CLAUSE_DEFAULT) \
+ | (1u << PRAGMA_OMP_CLAUSE_SHARED) \
+ | (1u << PRAGMA_OMP_CLAUSE_COPYIN) \
+ | (1u << PRAGMA_OMP_CLAUSE_REDUCTION) \
+ | (1u << PRAGMA_OMP_CLAUSE_NUM_THREADS))
+
+static tree
+c_parser_omp_parallel (c_parser *parser)
+{
+ enum pragma_kind p_kind = PRAGMA_OMP_PARALLEL;
+ const char *p_name = "#pragma omp parallel";
+ tree stmt, clauses, par_clause, ws_clause, block;
+ unsigned int mask = OMP_PARALLEL_CLAUSE_MASK;
+
+ if (c_parser_next_token_is_keyword (parser, RID_FOR))
+ {
+ c_parser_consume_token (parser);
+ p_kind = PRAGMA_OMP_PARALLEL_FOR;
+ p_name = "#pragma omp parallel for";
+ mask |= OMP_FOR_CLAUSE_MASK;
+ mask &= ~(1u << PRAGMA_OMP_CLAUSE_NOWAIT);
+ }
+ else if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ if (strcmp (p, "sections") == 0)
+ {
+ c_parser_consume_token (parser);
+ p_kind = PRAGMA_OMP_PARALLEL_SECTIONS;
+ p_name = "#pragma omp parallel sections";
+ mask |= OMP_SECTIONS_CLAUSE_MASK;
+ mask &= ~(1u << PRAGMA_OMP_CLAUSE_NOWAIT);
+ }
+ }
+
+ clauses = c_parser_omp_all_clauses (parser, mask, p_name);
+
+ switch (p_kind)
+ {
+ case PRAGMA_OMP_PARALLEL:
+ block = c_begin_omp_parallel ();
+ c_parser_statement (parser);
+ stmt = c_finish_omp_parallel (clauses, block);
+ break;
+
+ case PRAGMA_OMP_PARALLEL_FOR:
+ block = c_begin_omp_parallel ();
+ c_split_parallel_clauses (clauses, &par_clause, &ws_clause);
+ stmt = c_parser_omp_for_loop (parser);
+ if (stmt)
+ OMP_FOR_CLAUSES (stmt) = ws_clause;
+ stmt = c_finish_omp_parallel (par_clause, block);
+ OMP_PARALLEL_COMBINED (stmt) = 1;
+ break;
+
+ case PRAGMA_OMP_PARALLEL_SECTIONS:
+ block = c_begin_omp_parallel ();
+ c_split_parallel_clauses (clauses, &par_clause, &ws_clause);
+ stmt = c_parser_omp_sections_scope (parser);
+ if (stmt)
+ OMP_SECTIONS_CLAUSES (stmt) = ws_clause;
+ stmt = c_finish_omp_parallel (par_clause, block);
+ OMP_PARALLEL_COMBINED (stmt) = 1;
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ return stmt;
+}
+
+/* OpenMP 2.5:
+ # pragma omp single single-clause[optseq] new-line
+ structured-block
+*/
+
+#define OMP_SINGLE_CLAUSE_MASK \
+ ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \
+ | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
+ | (1u << PRAGMA_OMP_CLAUSE_COPYPRIVATE) \
+ | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
+
+static tree
+c_parser_omp_single (c_parser *parser)
+{
+ tree stmt = make_node (OMP_SINGLE);
+ TREE_TYPE (stmt) = void_type_node;
+
+ OMP_SINGLE_CLAUSES (stmt)
+ = c_parser_omp_all_clauses (parser, OMP_SINGLE_CLAUSE_MASK,
+ "#pragma omp single");
+ OMP_SINGLE_BODY (stmt) = c_parser_omp_structured_block (parser);
+
+ return add_stmt (stmt);
+}
+
+
+/* Main entry point to parsing most OpenMP pragmas. */
+
+static void
+c_parser_omp_construct (c_parser *parser)
+{
+ enum pragma_kind p_kind;
+ location_t loc;
+ tree stmt;
+
+ loc = c_parser_peek_token (parser)->location;
+ p_kind = c_parser_peek_token (parser)->pragma_kind;
+ c_parser_consume_pragma (parser);
+
+ /* For all constructs below except #pragma omp atomic
+ MUST_NOT_THROW catch handlers are needed when exceptions
+ are enabled. */
+ if (p_kind != PRAGMA_OMP_ATOMIC)
+ c_maybe_initialize_eh ();
+
+ switch (p_kind)
+ {
+ case PRAGMA_OMP_ATOMIC:
+ c_parser_omp_atomic (parser);
+ return;
+ case PRAGMA_OMP_CRITICAL:
+ stmt = c_parser_omp_critical (parser);
+ break;
+ case PRAGMA_OMP_FOR:
+ stmt = c_parser_omp_for (parser);
+ break;
+ case PRAGMA_OMP_MASTER:
+ stmt = c_parser_omp_master (parser);
+ break;
+ case PRAGMA_OMP_ORDERED:
+ stmt = c_parser_omp_ordered (parser);
+ break;
+ case PRAGMA_OMP_PARALLEL:
+ stmt = c_parser_omp_parallel (parser);
+ break;
+ case PRAGMA_OMP_SECTIONS:
+ stmt = c_parser_omp_sections (parser);
+ break;
+ case PRAGMA_OMP_SINGLE:
+ stmt = c_parser_omp_single (parser);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ if (stmt)
+ SET_EXPR_LOCATION (stmt, loc);
+}
+
+
+/* OpenMP 2.5:
+ # pragma omp threadprivate (variable-list) */
+
+static void
+c_parser_omp_threadprivate (c_parser *parser)
+{
+ tree vars, t;
+
+ c_parser_consume_pragma (parser);
+ vars = c_parser_omp_var_list_parens (parser, 0, NULL);
+
+ /* Mark every variable in VARS to be assigned thread local storage. */
+ for (t = vars; t; t = TREE_CHAIN (t))
+ {
+ tree v = TREE_PURPOSE (t);
+
+ /* If V had already been marked threadprivate, it doesn't matter
+ whether it had been used prior to this point. */
+ if (TREE_USED (v) && !C_DECL_THREADPRIVATE_P (v))
+ error ("%qE declared % after first use", v);
+ else if (! TREE_STATIC (v) && ! DECL_EXTERNAL (v))
+ error ("automatic variable %qE cannot be %", v);
+ else if (! COMPLETE_TYPE_P (TREE_TYPE (v)))
+ error ("% %qE has incomplete type", v);
+ else
+ {
+ if (! DECL_THREAD_LOCAL_P (v))
+ {
+ DECL_TLS_MODEL (v) = decl_default_tls_model (v);
+ /* If rtl has been already set for this var, call
+ make_decl_rtl once again, so that encode_section_info
+ has a chance to look at the new decl flags. */
+ if (DECL_RTL_SET_P (v))
+ make_decl_rtl (v);
+ }
+ C_DECL_THREADPRIVATE_P (v) = 1;
+ }
+ }
+
+ c_parser_skip_to_pragma_eol (parser);
+}
+
+
/* Parse a single source file. */
void