/* 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, 2007, 2008
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Parser actions based on the old Bison parser; structure somewhat
#include "config.h"
#include "system.h"
#include "coretypes.h"
-#include "tm.h"
+#include "tm.h" /* For rtl.h: needs enum reg_class. */
#include "tree.h"
-#include "rtl.h"
#include "langhooks.h"
#include "input.h"
#include "cpplib.h"
#include "timevar.h"
-#include "c-pragma.h"
+#include "c-family/c-pragma.h"
#include "c-tree.h"
#include "flags.h"
#include "output.h"
#include "toplev.h"
#include "ggc.h"
-#include "c-common.h"
+#include "c-family/c-common.h"
#include "vec.h"
#include "target.h"
#include "cgraph.h"
+#include "plugin.h"
\f
/* Initialization routine for this file. */
tree id;
int mask = 0;
+ /* Make sure RID_MAX hasn't grown past the 8 bits used to hold the keyword in
+ the c_token structure. */
+ gcc_assert (RID_MAX <= 255);
+
mask |= D_CXXONLY;
if (!flag_isoc99)
mask |= D_C99;
if (!c_dialect_objc ())
mask |= D_OBJC | D_CXX_OBJC;
- ridpointers = GGC_CNEWVEC (tree, (int) RID_MAX);
+ ridpointers = ggc_alloc_cleared_vec_tree ((int) RID_MAX);
for (i = 0; i < num_c_common_reswords; i++)
{
/* If a keyword is disabled, do not enter it into the table
C_ID_TYPENAME,
/* An identifier declared as an Objective-C class name. */
C_ID_CLASSNAME,
+ /* An address space identifier. */
+ C_ID_ADDRSPACE,
/* Not an identifier. */
C_ID_NONE
} c_id_kind;
/* A single C token after string literal concatenation and conversion
of preprocessing tokens to tokens. */
-typedef struct c_token GTY (())
-{
+typedef struct GTY (()) c_token {
/* The kind of token. */
ENUM_BITFIELD (cpp_ttype) type : 8;
/* If this token is a CPP_NAME, this value indicates whether also
ENUM_BITFIELD (rid) keyword : 8;
/* If this token is a CPP_PRAGMA, this indicates the pragma that
was seen. Otherwise it is PRAGMA_NONE. */
- ENUM_BITFIELD (pragma_kind) pragma_kind : 7;
- /* The value associated with this token, if any. */
- tree value;
+ ENUM_BITFIELD (pragma_kind) pragma_kind : 8;
/* The location at which this token was found. */
location_t location;
+ /* The value associated with this token, if any. */
+ tree value;
} c_token;
/* A parser structure recording information about the state and
context of parsing. Includes lexer information with up to two
tokens of look-ahead; more are not needed for C. */
-typedef struct c_parser GTY(())
-{
+typedef struct GTY(()) c_parser {
/* The look-ahead tokens. */
c_token tokens[2];
/* How many look-ahead tokens are available (0, 1 or 2). */
if (rid_code == RID_CXX_COMPAT_WARN)
{
- warning (OPT_Wc___compat,
- "%Hidentifier %qs conflicts with C++ keyword",
- &token->location,
- IDENTIFIER_POINTER (token->value));
+ warning_at (token->location,
+ OPT_Wc___compat,
+ "identifier %qE conflicts with C++ keyword",
+ token->value);
+ }
+ else if (rid_code >= RID_FIRST_ADDR_SPACE
+ && rid_code <= RID_LAST_ADDR_SPACE)
+ {
+ token->id_kind = C_ID_ADDRSPACE;
+ token->keyword = rid_code;
+ break;
}
else if (c_dialect_objc ())
{
}
else
{
- /* Return the canonical spelling for this keyword. */
- token->value = ridpointers[(int) rid_code];
token->type = CPP_KEYWORD;
token->keyword = rid_code;
break;
{
case C_ID_ID:
return false;
+ case C_ID_ADDRSPACE:
+ return true;
case C_ID_TYPENAME:
return true;
case C_ID_CLASSNAME:
{
case RID_UNSIGNED:
case RID_LONG:
+ case RID_INT128:
case RID_SHORT:
case RID_SIGNED:
case RID_COMPLEX:
{
case C_ID_ID:
return false;
+ case C_ID_ADDRSPACE:
+ return true;
case C_ID_TYPENAME:
return true;
case C_ID_CLASSNAME:
case RID_THREAD:
case RID_UNSIGNED:
case RID_LONG:
+ case RID_INT128:
case RID_SHORT:
case RID_SIGNED:
case RID_COMPLEX:
}
}
+
+/* Return true if TOKEN can start declaration specifiers or a static
+ assertion, false otherwise. */
+static bool
+c_token_starts_declaration (c_token *token)
+{
+ if (c_token_starts_declspecs (token)
+ || token->keyword == RID_STATIC_ASSERT)
+ return true;
+ else
+ return false;
+}
+
/* Return true if the next token from PARSER can start declaration
specifiers, false otherwise. */
static inline bool
return c_token_starts_declspecs (token);
}
+/* Return true if the next token from PARSER can start declaration
+ specifiers or a static assertion, false otherwise. */
+static inline bool
+c_parser_next_token_starts_declaration (c_parser *parser)
+{
+ c_token *token = c_parser_peek_token (parser);
+ return c_token_starts_declaration (token);
+}
+
/* Return a pointer to the next-but-one token from PARSER, reading it
in if necessary. The next token is already read in. */
CPP_KEYWORD, keywords are treated like
identifiers. */
(token->type == CPP_KEYWORD ? CPP_NAME : token->type),
- token->value);
+ /* ??? The C parser does not save the cpp flags of a
+ token, we need to pass 0 here and we will not get
+ the source spelling of some tokens but rather the
+ canonical spelling. */
+ token->value, /*flags=*/0);
}
/* If the next token is of the indicated TYPE, consume it. Otherwise,
parser->error = false;
}
+/* CPP's options (initialized by c-opts.c). */
+extern cpp_options *cpp_opts;
+
/* Save the warning flags which are controlled by __extension__. */
static inline int
int ret = (pedantic
| (warn_pointer_arith << 1)
| (warn_traditional << 2)
- | (flag_iso << 3));
- pedantic = 0;
+ | (flag_iso << 3)
+ | (warn_long_long << 4)
+ | (warn_cxx_compat << 5));
+ cpp_opts->pedantic = pedantic = 0;
warn_pointer_arith = 0;
- warn_traditional = 0;
+ cpp_opts->warn_traditional = warn_traditional = 0;
flag_iso = 0;
+ cpp_opts->warn_long_long = warn_long_long = 0;
+ warn_cxx_compat = 0;
return ret;
}
static inline void
restore_extension_diagnostics (int flags)
{
- pedantic = flags & 1;
+ cpp_opts->pedantic = pedantic = flags & 1;
warn_pointer_arith = (flags >> 1) & 1;
- warn_traditional = (flags >> 2) & 1;
+ cpp_opts->warn_traditional = warn_traditional = (flags >> 2) & 1;
flag_iso = (flags >> 3) & 1;
+ cpp_opts->warn_long_long = warn_long_long = (flags >> 4) & 1;
+ warn_cxx_compat = (flags >> 5) & 1;
}
/* Possibly kinds of declarator to parse. */
static void c_parser_external_declaration (c_parser *);
static void c_parser_asm_definition (c_parser *);
-static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool, bool);
+static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool,
+ bool, bool);
+static void c_parser_static_assert_declaration_no_semi (c_parser *);
+static void c_parser_static_assert_declaration (c_parser *);
static void c_parser_declspecs (c_parser *, struct c_declspecs *, bool, bool,
bool);
static struct c_typespec c_parser_enum_specifier (c_parser *);
static struct c_type_name *c_parser_type_name (c_parser *);
static struct c_expr c_parser_initializer (c_parser *);
static struct c_expr c_parser_braced_init (c_parser *, tree, bool);
-static void c_parser_initelt (c_parser *);
-static void c_parser_initval (c_parser *, struct c_expr *);
+static void c_parser_initelt (c_parser *, struct obstack *);
+static void c_parser_initval (c_parser *, struct c_expr *,
+ struct obstack *);
static tree c_parser_compound_statement (c_parser *);
static void c_parser_compound_statement_nostart (c_parser *);
static void c_parser_label (c_parser *);
static void c_parser_for_statement (c_parser *);
static tree c_parser_asm_statement (c_parser *);
static tree c_parser_asm_operands (c_parser *, bool);
+static tree c_parser_asm_goto_operands (c_parser *);
static tree c_parser_asm_clobbers (c_parser *);
static struct c_expr c_parser_expr_no_commas (c_parser *, struct c_expr *);
static struct c_expr c_parser_conditional_expression (c_parser *,
static struct c_expr c_parser_alignof_expression (c_parser *);
static struct c_expr c_parser_postfix_expression (c_parser *);
static struct c_expr c_parser_postfix_expression_after_paren_type (c_parser *,
- struct c_type_name *);
+ struct c_type_name *,
+ location_t);
static struct c_expr c_parser_postfix_expression_after_primary (c_parser *,
+ location_t loc,
struct c_expr);
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 VEC(tree,gc) *c_parser_expr_list (c_parser *, bool, bool,
+ VEC(tree,gc) **);
static void c_parser_omp_construct (c_parser *);
static void c_parser_omp_threadprivate (c_parser *);
static void c_parser_omp_barrier (c_parser *);
{
if (c_parser_next_token_is (parser, CPP_EOF))
{
- pedwarn (OPT_pedantic, "%HISO C forbids an empty translation unit",
- &c_parser_peek_token (parser)->location);
+ pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic,
+ "ISO C forbids an empty translation unit");
}
else
{
void *obstack_position = obstack_alloc (&parser_obstack, 0);
+ mark_valid_location_for_stdc_pragma (false);
do
{
ggc_collect ();
}
break;
case CPP_SEMICOLON:
- pedwarn (OPT_pedantic,
- "%HISO C does not allow extra %<;%> outside of a function",
- &c_parser_peek_token (parser)->location);
+ pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic,
+ "ISO C does not allow extra %<;%> outside of a function");
c_parser_consume_token (parser);
break;
case CPP_PRAGMA:
+ mark_valid_location_for_stdc_pragma (true);
c_parser_pragma (parser, pragma_external);
+ mark_valid_location_for_stdc_pragma (false);
break;
case CPP_PLUS:
case CPP_MINUS:
/* A declaration or a function definition. We can only tell
which after parsing the declaration specifiers, if any, and
the first declarator. */
- c_parser_declaration_or_fndef (parser, true, true, false, true);
+ c_parser_declaration_or_fndef (parser, true, true, true, false, true);
break;
}
}
/* Parse a declaration or function definition (C90 6.5, 6.7.1, C99
6.7, 6.9.1). If FNDEF_OK is true, a function definition is
accepted; otherwise (old-style parameter declarations) only other
- declarations are accepted. If NESTED is true, we are inside a
- function or parsing old-style parameter declarations; any functions
- encountered are nested functions and declaration specifiers are
- required; otherwise we are at top level and functions are normal
- functions and declaration specifiers may be optional. If EMPTY_OK
- is true, empty declarations are OK (subject to all other
- constraints); otherwise (old-style parameter declarations) they are
- diagnosed. If START_ATTR_OK is true, the declaration specifiers
- may start with attributes; otherwise they may not.
+ declarations are accepted. If STATIC_ASSERT_OK is true, a static
+ assertion is accepted; otherwise (old-style parameter declarations)
+ it is not. If NESTED is true, we are inside a function or parsing
+ old-style parameter declarations; any functions encountered are
+ nested functions and declaration specifiers are required; otherwise
+ we are at top level and functions are normal functions and
+ declaration specifiers may be optional. If EMPTY_OK is true, empty
+ declarations are OK (subject to all other constraints); otherwise
+ (old-style parameter declarations) they are diagnosed. If
+ START_ATTR_OK is true, the declaration specifiers may start with
+ attributes; otherwise they may not.
declaration:
declaration-specifiers init-declarator-list[opt] ;
+ static_assert-declaration
function-definition:
declaration-specifiers[opt] declarator declaration-list[opt]
C we also allow but diagnose declarations without declaration
specifiers, but only at top level (elsewhere they conflict with
other syntax).
-
+
OpenMP:
-
+
declaration:
threadprivate-directive */
static void
-c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok,
+c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
+ bool static_assert_ok, bool empty_ok,
bool nested, bool start_attr_ok)
{
struct c_declspecs *specs;
bool diagnosed_no_specs = false;
location_t here = c_parser_peek_token (parser)->location;
+ if (static_assert_ok
+ && c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
+ {
+ c_parser_static_assert_declaration (parser);
+ return;
+ }
specs = build_null_declspecs ();
c_parser_declspecs (parser, specs, true, true, start_attr_ok);
if (parser->error)
else
{
shadow_tag_warned (specs, 1);
- pedwarn (0, "%Hempty declaration", &here);
+ pedwarn (here, 0, "empty declaration");
}
c_parser_consume_token (parser);
return;
if (!diagnosed_no_specs && !specs->declspecs_seen_p)
{
diagnosed_no_specs = true;
- pedwarn (0, "%Hdata definition has no type or storage class",
- &here);
+ pedwarn (here, 0, "data definition has no type or storage class");
}
/* Having seen a data definition, there cannot now be a
function definition. */
{
tree d;
struct c_expr init;
+ location_t init_loc;
c_parser_consume_token (parser);
/* The declaration of the variable is in effect while
its initializer is parsed. */
if (!d)
d = error_mark_node;
start_init (d, asm_name, global_bindings_p ());
+ init_loc = c_parser_peek_token (parser)->location;
init = c_parser_initializer (parser);
finish_init ();
if (d != error_mark_node)
{
maybe_warn_string_init (TREE_TYPE (d), init);
- finish_decl (d, init.value, asm_name);
+ finish_decl (d, init_loc, init.value,
+ init.original_type, asm_name);
}
}
else
chainon (postfix_attrs,
all_prefix_attrs));
if (d)
- finish_decl (d, NULL_TREE, asm_name);
+ finish_decl (d, UNKNOWN_LOCATION, NULL_TREE,
+ NULL_TREE, asm_name);
}
if (c_parser_next_token_is (parser, CPP_COMMA))
{
/* Function definition (nested or otherwise). */
if (nested)
{
- pedwarn (OPT_pedantic, "%HISO C forbids nested functions", &here);
+ pedwarn (here, OPT_pedantic, "ISO C forbids nested functions");
c_push_function_context ();
}
if (!start_function (specs, declarator, all_prefix_attrs))
function definitions either. */
while (c_parser_next_token_is_not (parser, CPP_EOF)
&& c_parser_next_token_is_not (parser, CPP_OPEN_BRACE))
- c_parser_declaration_or_fndef (parser, false, false, true, false);
- DECL_SOURCE_LOCATION (current_function_decl)
- = c_parser_peek_token (parser)->location;
+ c_parser_declaration_or_fndef (parser, false, false, false,
+ true, false);
store_parm_decls ();
+ DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus
+ = c_parser_peek_token (parser)->location;
fnbody = c_parser_compound_statement (parser);
if (nested)
{
tree decl = current_function_decl;
+ /* Mark nested functions as needing static-chain initially.
+ lower_nested_functions will recompute it but the
+ DECL_STATIC_CHAIN flag is also used before that happens,
+ by initializer_constant_valid_p. See gcc.dg/nested-fn-2.c. */
+ DECL_STATIC_CHAIN (decl) = 1;
add_stmt (fnbody);
finish_function ();
c_pop_function_context ();
- add_stmt (build_stmt (DECL_EXPR, decl));
+ add_stmt (build_stmt (DECL_SOURCE_LOCATION (decl), DECL_EXPR, decl));
}
else
{
c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
}
+/* Parse a static assertion (C1X N1425 6.7.10).
+
+ static_assert-declaration:
+ static_assert-declaration-no-semi ;
+*/
+
+static void
+c_parser_static_assert_declaration (c_parser *parser)
+{
+ c_parser_static_assert_declaration_no_semi (parser);
+ if (parser->error
+ || !c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+ c_parser_skip_to_end_of_block_or_statement (parser);
+}
+
+/* Parse a static assertion (C1X N1425 6.7.10), without the trailing
+ semicolon.
+
+ static_assert-declaration-no-semi:
+ _Static_assert ( constant-expression , string-literal )
+*/
+
+static void
+c_parser_static_assert_declaration_no_semi (c_parser *parser)
+{
+ location_t assert_loc, value_loc;
+ tree value;
+ tree string;
+
+ gcc_assert (c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT));
+ assert_loc = c_parser_peek_token (parser)->location;
+ if (!flag_isoc1x)
+ {
+ if (flag_isoc99)
+ pedwarn (assert_loc, OPT_pedantic,
+ "ISO C99 does not support %<_Static_assert%>");
+ else
+ pedwarn (assert_loc, OPT_pedantic,
+ "ISO C90 does not support %<_Static_assert%>");
+ }
+ c_parser_consume_token (parser);
+ if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ return;
+ value_loc = c_parser_peek_token (parser)->location;
+ value = c_parser_expr_no_commas (parser, NULL).value;
+ parser->lex_untranslated_string = true;
+ if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
+ {
+ parser->lex_untranslated_string = false;
+ return;
+ }
+ switch (c_parser_peek_token (parser)->type)
+ {
+ case CPP_STRING:
+ case CPP_STRING16:
+ case CPP_STRING32:
+ case CPP_WSTRING:
+ case CPP_UTF8STRING:
+ string = c_parser_peek_token (parser)->value;
+ c_parser_consume_token (parser);
+ parser->lex_untranslated_string = false;
+ break;
+ default:
+ c_parser_error (parser, "expected string literal");
+ parser->lex_untranslated_string = false;
+ return;
+ }
+ c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (value)))
+ {
+ error_at (value_loc, "expression in static assertion is not an integer");
+ return;
+ }
+ if (TREE_CODE (value) != INTEGER_CST)
+ {
+ value = c_fully_fold (value, false, NULL);
+ if (TREE_CODE (value) == INTEGER_CST)
+ pedwarn (value_loc, OPT_pedantic, "expression in static assertion "
+ "is not an integer constant expression");
+ }
+ if (TREE_CODE (value) != INTEGER_CST)
+ {
+ error_at (value_loc, "expression in static assertion is not constant");
+ return;
+ }
+ constant_expression_warning (value);
+ if (integer_zerop (value))
+ error_at (assert_loc, "static assertion failed: %E", string);
+}
+
/* Parse some declaration specifiers (possibly none) (C90 6.5, C99
6.7), adding them to SPECS (which may already include some).
Storage class specifiers are accepted iff SCSPEC_OK; type
const
restrict
volatile
+ address-space-qualifier
(restrict is new in C99.)
declaration-specifiers:
attributes declaration-specifiers[opt]
+ type-qualifier:
+ address-space
+
+ address-space:
+ identifier recognized by the target
+
storage-class-specifier:
__thread
type-specifier:
typeof-specifier
+ __int128
_Decimal32
_Decimal64
_Decimal128
{
struct c_typespec t;
tree attrs;
+ location_t loc = c_parser_peek_token (parser)->location;
if (c_parser_next_token_is (parser, CPP_NAME))
{
tree value = c_parser_peek_token (parser)->value;
c_id_kind kind = c_parser_peek_token (parser)->id_kind;
+
+ if (kind == C_ID_ADDRSPACE)
+ {
+ addr_space_t as
+ = c_parser_peek_token (parser)->keyword - RID_FIRST_ADDR_SPACE;
+ declspecs_add_addrspace (specs, as);
+ c_parser_consume_token (parser);
+ attrs_ok = true;
+ continue;
+ }
+
/* This finishes the specifiers unless a type name is OK, it
is declared as a type name and a type name hasn't yet
been seen. */
/* For a typedef name, record the meaning, not the name.
In case of 'foo foo, bar;'. */
t.spec = lookup_name (value);
+ t.expr = NULL_TREE;
+ t.expr_const_operands = true;
}
else
{
if (c_parser_next_token_is (parser, CPP_LESS))
proto = c_parser_objc_protocol_refs (parser);
t.spec = objc_get_protocol_qualified_type (value, proto);
+ t.expr = NULL_TREE;
+ t.expr_const_operands = true;
}
- declspecs_add_type (specs, t);
+ declspecs_add_type (loc, specs, t);
continue;
}
if (c_parser_next_token_is (parser, CPP_LESS))
proto = c_parser_objc_protocol_refs (parser);
t.kind = ctsk_objc;
t.spec = objc_get_protocol_qualified_type (NULL_TREE, proto);
- declspecs_add_type (specs, t);
+ t.expr = NULL_TREE;
+ t.expr_const_operands = true;
+ declspecs_add_type (loc, specs, t);
continue;
}
gcc_assert (c_parser_next_token_is (parser, CPP_KEYWORD));
break;
case RID_UNSIGNED:
case RID_LONG:
+ case RID_INT128:
case RID_SHORT:
case RID_SIGNED:
case RID_COMPLEX:
parser->objc_need_raw_identifier = true;
t.kind = ctsk_resword;
t.spec = c_parser_peek_token (parser)->value;
- declspecs_add_type (specs, t);
+ t.expr = NULL_TREE;
+ t.expr_const_operands = true;
+ declspecs_add_type (loc, specs, t);
c_parser_consume_token (parser);
break;
case RID_ENUM:
attrs_ok = true;
seen_type = true;
t = c_parser_enum_specifier (parser);
- declspecs_add_type (specs, t);
+ declspecs_add_type (loc, specs, t);
break;
case RID_STRUCT:
case RID_UNION:
attrs_ok = true;
seen_type = true;
t = c_parser_struct_or_union_specifier (parser);
- declspecs_add_type (specs, t);
+ invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, t.spec);
+ declspecs_add_type (loc, specs, t);
break;
case RID_TYPEOF:
/* ??? The old parser rejected typeof after other type
attrs_ok = true;
seen_type = true;
t = c_parser_typeof_specifier (parser);
- declspecs_add_type (specs, t);
+ declspecs_add_type (loc, specs, t);
break;
case RID_CONST:
case RID_VOLATILE:
struct c_typespec ret;
tree attrs;
tree ident = NULL_TREE;
- location_t ident_loc;
+ location_t enum_loc;
+ location_t ident_loc = UNKNOWN_LOCATION; /* Quiet warning. */
gcc_assert (c_parser_next_token_is_keyword (parser, RID_ENUM));
+ enum_loc = c_parser_peek_token (parser)->location;
c_parser_consume_token (parser);
attrs = c_parser_attributes (parser);
+ enum_loc = c_parser_peek_token (parser)->location;
/* Set the location in case we create a decl now. */
c_parser_set_source_position_from_token (c_parser_peek_token (parser));
if (c_parser_next_token_is (parser, CPP_NAME))
{
ident = c_parser_peek_token (parser)->value;
ident_loc = c_parser_peek_token (parser)->location;
+ enum_loc = ident_loc;
c_parser_consume_token (parser);
}
if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
{
/* Parse an enum definition. */
struct c_enum_contents the_enum;
- tree type = start_enum (&the_enum, ident);
+ tree type = start_enum (enum_loc, &the_enum, ident);
tree postfix_attrs;
/* We chain the enumerators in reverse order, then put them in
forward order at the end. */
tree enum_decl;
bool seen_comma;
c_token *token;
- location_t comma_loc;
+ location_t comma_loc = UNKNOWN_LOCATION; /* Quiet warning. */
+ location_t value_loc;
if (c_parser_next_token_is_not (parser, CPP_NAME))
{
c_parser_error (parser, "expected identifier");
enum_id = token->value;
/* Set the location in case we create a decl now. */
c_parser_set_source_position_from_token (token);
+ value_loc = token->location;
c_parser_consume_token (parser);
if (c_parser_next_token_is (parser, CPP_EQ))
{
c_parser_consume_token (parser);
+ value_loc = c_parser_peek_token (parser)->location;
enum_value = c_parser_expr_no_commas (parser, NULL).value;
}
else
enum_value = NULL_TREE;
- enum_decl = build_enumerator (&the_enum, enum_id, enum_value);
+ enum_decl = build_enumerator (value_loc,
+ &the_enum, enum_id, enum_value);
TREE_CHAIN (enum_decl) = values;
values = enum_decl;
seen_comma = false;
if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
{
if (seen_comma && !flag_isoc99)
- pedwarn (OPT_pedantic, "%Hcomma at end of enumerator list",
- &comma_loc);
+ pedwarn (comma_loc, OPT_pedantic, "comma at end of enumerator list");
c_parser_consume_token (parser);
break;
}
ret.spec = finish_enum (type, nreverse (values),
chainon (attrs, postfix_attrs));
ret.kind = ctsk_tagdef;
+ ret.expr = NULL_TREE;
+ ret.expr_const_operands = true;
return ret;
}
else if (!ident)
c_parser_error (parser, "expected %<{%>");
ret.spec = error_mark_node;
ret.kind = ctsk_tagref;
+ ret.expr = NULL_TREE;
+ ret.expr_const_operands = true;
return ret;
}
- ret = parser_xref_tag (ENUMERAL_TYPE, ident);
+ ret = parser_xref_tag (ident_loc, ENUMERAL_TYPE, ident);
/* In ISO C, enumerated types can be referred to only if already
defined. */
if (pedantic && !COMPLETE_TYPE_P (ret.spec))
{
gcc_assert (ident);
- pedwarn (OPT_pedantic,
- "%HISO C forbids forward references to %<enum%> types",
- &ident_loc);
+ pedwarn (enum_loc, OPT_pedantic,
+ "ISO C forbids forward references to %<enum%> types");
}
return ret;
}
struct c_typespec ret;
tree attrs;
tree ident = NULL_TREE;
+ location_t struct_loc;
+ location_t ident_loc = UNKNOWN_LOCATION;
enum tree_code code;
switch (c_parser_peek_token (parser)->keyword)
{
default:
gcc_unreachable ();
}
+ struct_loc = c_parser_peek_token (parser)->location;
c_parser_consume_token (parser);
attrs = c_parser_attributes (parser);
+
/* Set the location in case we create a decl now. */
c_parser_set_source_position_from_token (c_parser_peek_token (parser));
+
if (c_parser_next_token_is (parser, CPP_NAME))
{
ident = c_parser_peek_token (parser)->value;
+ ident_loc = c_parser_peek_token (parser)->location;
+ struct_loc = ident_loc;
c_parser_consume_token (parser);
}
if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
{
/* Parse a struct or union definition. Start the scope of the
tag before parsing components. */
- tree type = start_struct (code, ident);
+ struct c_struct_parse_info *struct_info;
+ tree type = start_struct (struct_loc, code, ident, &struct_info);
tree postfix_attrs;
/* We chain the components in reverse order, then put them in
forward order at the end. Each struct-declaration may
/* Parse any stray semicolon. */
if (c_parser_next_token_is (parser, CPP_SEMICOLON))
{
- pedwarn (OPT_pedantic,
- "%Hextra semicolon in struct or union specified",
- &c_parser_peek_token (parser)->location);
+ pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic,
+ "extra semicolon in struct or union specified");
c_parser_consume_token (parser);
continue;
}
else
{
if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
- pedwarn (0, "%Hno semicolon at end of struct or union",
- &c_parser_peek_token (parser)->location);
+ pedwarn (c_parser_peek_token (parser)->location, 0,
+ "no semicolon at end of struct or union");
else
{
c_parser_error (parser, "expected %<;%>");
}
}
postfix_attrs = c_parser_attributes (parser);
- ret.spec = finish_struct (type, nreverse (contents),
- chainon (attrs, postfix_attrs));
+ ret.spec = finish_struct (struct_loc, type, nreverse (contents),
+ chainon (attrs, postfix_attrs), struct_info);
ret.kind = ctsk_tagdef;
+ ret.expr = NULL_TREE;
+ ret.expr_const_operands = true;
return ret;
}
else if (!ident)
c_parser_error (parser, "expected %<{%>");
ret.spec = error_mark_node;
ret.kind = ctsk_tagref;
+ ret.expr = NULL_TREE;
+ ret.expr_const_operands = true;
return ret;
}
- ret = parser_xref_tag (code, ident);
+ ret = parser_xref_tag (ident_loc, code, ident);
return ret;
}
struct-declaration:
specifier-qualifier-list struct-declarator-list
+ static_assert-declaration-no-semi
specifier-qualifier-list:
type-specifier specifier-qualifier-list[opt]
restore_extension_diagnostics (ext);
return decl;
}
+ if (c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
+ {
+ c_parser_static_assert_declaration_no_semi (parser);
+ return NULL_TREE;
+ }
specs = build_null_declspecs ();
decl_loc = c_parser_peek_token (parser)->location;
c_parser_declspecs (parser, specs, false, true, true);
tree ret;
if (!specs->type_seen_p)
{
- pedwarn (OPT_pedantic,
- "%HISO C forbids member declarations with no members",
- &decl_loc);
+ pedwarn (decl_loc, OPT_pedantic,
+ "ISO C forbids member declarations with no members");
shadow_tag_warned (specs, pedantic);
ret = NULL_TREE;
}
structs or unions (which is [a] useful and [b] supports
MS P-SDK). */
tree attrs = NULL;
- ret = grokfield (build_id_declarator (NULL_TREE), specs,
+
+ ret = grokfield (c_parser_peek_token (parser)->location,
+ build_id_declarator (NULL_TREE), specs,
NULL_TREE, &attrs);
if (ret)
decl_attributes (&ret, attrs, 0);
}
if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
postfix_attrs = c_parser_attributes (parser);
- d = grokfield (declarator, specs, width, &all_prefix_attrs);
+ d = grokfield (c_parser_peek_token (parser)->location,
+ declarator, specs, width, &all_prefix_attrs);
decl_attributes (&d, chainon (postfix_attrs,
all_prefix_attrs), 0);
- TREE_CHAIN (d) = decls;
+ DECL_CHAIN (d) = decls;
decls = d;
if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
all_prefix_attrs = chainon (c_parser_attributes (parser),
struct c_typespec ret;
ret.kind = ctsk_typeof;
ret.spec = error_mark_node;
+ ret.expr = NULL_TREE;
+ ret.expr_const_operands = true;
gcc_assert (c_parser_next_token_is_keyword (parser, RID_TYPEOF));
c_parser_consume_token (parser);
- skip_evaluation++;
+ c_inhibit_evaluation_warnings++;
in_typeof++;
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
- skip_evaluation--;
+ c_inhibit_evaluation_warnings--;
in_typeof--;
return ret;
}
if (c_parser_next_token_starts_typename (parser))
{
struct c_type_name *type = c_parser_type_name (parser);
- skip_evaluation--;
+ c_inhibit_evaluation_warnings--;
in_typeof--;
if (type != NULL)
{
- ret.spec = groktypename (type);
+ ret.spec = groktypename (type, &ret.expr, &ret.expr_const_operands);
pop_maybe_used (variably_modified_type_p (ret.spec, NULL_TREE));
}
}
bool was_vm;
location_t here = c_parser_peek_token (parser)->location;
struct c_expr expr = c_parser_expression (parser);
- skip_evaluation--;
+ c_inhibit_evaluation_warnings--;
in_typeof--;
if (TREE_CODE (expr.value) == COMPONENT_REF
&& DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
- error ("%H%<typeof%> applied to a bit-field", &here);
+ error_at (here, "%<typeof%> applied to a bit-field");
+ mark_exp_read (expr.value);
ret.spec = TREE_TYPE (expr.value);
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);
- }
+ /* This is returned with the type so that when the type is
+ evaluated, this can be evaluated. */
+ if (was_vm)
+ ret.expr = c_fully_fold (expr.value, false, &ret.expr_const_operands);
pop_maybe_used (was_vm);
}
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
/* Parse a sequence of array declarators and parameter lists. */
if (c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
{
+ location_t brace_loc = c_parser_peek_token (parser)->location;
struct c_declarator *declarator;
struct c_declspecs *quals_attrs = build_null_declspecs ();
bool static_seen;
"expected %<]%>");
return NULL;
}
- declarator = build_array_declarator (dimen, quals_attrs, static_seen,
- star_seen);
+ if (dimen)
+ mark_exp_read (dimen);
+ declarator = build_array_declarator (brace_loc, dimen, quals_attrs,
+ static_seen, star_seen);
if (declarator == NULL)
return NULL;
inner = set_array_declarator_inner (declarator, inner);
static struct c_arg_info *
c_parser_parms_list_declarator (c_parser *parser, tree attrs)
{
- bool good_parm = false;
+ bool bad_parm = false;
/* ??? Following the old parser, forward parameter declarations may
use abstract declarators, and if no real parameter declarations
follow the forward declarations then this is not diagnosed. Also
ret->had_vla_unspec = 0;
/* Suppress -Wold-style-definition for this case. */
ret->types = error_mark_node;
- error ("%HISO C requires a named argument before %<...%>",
- &c_parser_peek_token (parser)->location);
+ error_at (c_parser_peek_token (parser)->location,
+ "ISO C requires a named argument before %<...%>");
c_parser_consume_token (parser);
if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
{
/* Parse a parameter. */
struct c_parm *parm = c_parser_parameter_declaration (parser, attrs);
attrs = NULL_TREE;
- if (parm != NULL)
- {
- good_parm = true;
- push_parm_decl (parm);
- }
+ if (parm == NULL)
+ bad_parm = true;
+ else
+ push_parm_decl (parm);
if (c_parser_next_token_is (parser, CPP_SEMICOLON))
{
tree new_attrs;
if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
{
c_parser_consume_token (parser);
- if (good_parm)
- return get_parm_info (false);
- else
+ if (bad_parm)
{
- struct c_arg_info *ret
- = XOBNEW (&parser_obstack, struct c_arg_info);
- ret->parms = 0;
- ret->tags = 0;
- ret->types = 0;
- ret->others = 0;
- ret->pending_sizes = 0;
- ret->had_vla_unspec = 0;
- return ret;
+ get_pending_sizes ();
+ return NULL;
}
+ else
+ return get_parm_info (false);
}
if (!c_parser_require (parser, CPP_COMMA,
"expected %<;%>, %<,%> or %<)%>"))
{
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+ get_pending_sizes ();
return NULL;
}
if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
{
c_parser_consume_token (parser);
- if (good_parm)
- return get_parm_info (true);
- else
+ if (bad_parm)
{
- struct c_arg_info *ret
- = XOBNEW (&parser_obstack, struct c_arg_info);
- ret->parms = 0;
- ret->tags = 0;
- ret->types = 0;
- ret->others = 0;
- ret->pending_sizes = 0;
- ret->had_vla_unspec = 0;
- return ret;
+ get_pending_sizes ();
+ return NULL;
}
+ else
+ return get_parm_info (true);
}
else
{
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
"expected %<)%>");
+ get_pending_sizes ();
return NULL;
}
}
bool dummy = false;
if (!c_parser_next_token_starts_declspecs (parser))
{
+ c_token *token = c_parser_peek_token (parser);
+ if (parser->error)
+ return NULL;
+ c_parser_set_source_position_from_token (token);
+ if (token->type == CPP_NAME
+ && c_parser_peek_2nd_token (parser)->type != CPP_COMMA
+ && c_parser_peek_2nd_token (parser)->type != CPP_CLOSE_PAREN)
+ {
+ error ("unknown type name %qE", token->value);
+ parser->error = true;
+ }
/* ??? In some Objective-C cases '...' isn't applicable so there
should be a different message. */
- c_parser_error (parser,
- "expected declaration specifiers or %<...%>");
+ else
+ c_parser_error (parser,
+ "expected declaration specifiers or %<...%>");
c_parser_skip_to_end_of_parameter (parser);
return NULL;
}
}
else if (c_parser_next_token_is (parser, CPP_WSTRING))
{
- error ("%Hwide string literal in %<asm%>",
- &c_parser_peek_token (parser)->location);
+ error_at (c_parser_peek_token (parser)->location,
+ "wide string literal in %<asm%>");
str = build_string (1, "");
c_parser_consume_token (parser);
}
|| c_parser_next_token_is (parser, CPP_KEYWORD))
{
tree attr, attr_name, attr_args;
+ VEC(tree,gc) *expr_list;
if (c_parser_next_token_is (parser, CPP_COMMA))
{
c_parser_consume_token (parser);
case RID_STATIC:
case RID_UNSIGNED:
case RID_LONG:
+ case RID_INT128:
case RID_CONST:
case RID_EXTERN:
case RID_REGISTER:
}
if (!ok)
break;
+ /* Accept __attribute__((__const)) as __attribute__((const))
+ etc. */
+ attr_name
+ = ridpointers[(int) c_parser_peek_token (parser)->keyword];
}
- attr_name = c_parser_peek_token (parser)->value;
+ else
+ attr_name = c_parser_peek_token (parser)->value;
c_parser_consume_token (parser);
if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
{
attr_args = build_tree_list (NULL_TREE, arg1);
else
{
+ tree tree_list;
c_parser_consume_token (parser);
- attr_args = tree_cons (NULL_TREE, arg1,
- c_parser_expr_list (parser, false));
+ expr_list = c_parser_expr_list (parser, false, true, NULL);
+ tree_list = build_tree_list_vec (expr_list);
+ attr_args = tree_cons (NULL_TREE, arg1, tree_list);
+ release_tree_vector (expr_list);
}
}
else
if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
attr_args = NULL_TREE;
else
- attr_args = c_parser_expr_list (parser, false);
+ {
+ expr_list = c_parser_expr_list (parser, false, true, NULL);
+ attr_args = build_tree_list_vec (expr_list);
+ release_tree_vector (expr_list);
+ }
}
attr = build_tree_list (attr_name, attr_args);
if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
else
{
struct c_expr ret;
+ location_t loc = c_parser_peek_token (parser)->location;
ret = c_parser_expr_no_commas (parser, NULL);
if (TREE_CODE (ret.value) != STRING_CST
&& TREE_CODE (ret.value) != COMPOUND_LITERAL_EXPR)
- ret = default_function_array_conversion (ret);
+ ret = default_function_array_read_conversion (loc, ret);
return ret;
}
}
static struct c_expr
c_parser_braced_init (c_parser *parser, tree type, bool nested_p)
{
+ struct c_expr ret;
+ struct obstack braced_init_obstack;
location_t brace_loc = c_parser_peek_token (parser)->location;
+ gcc_obstack_init (&braced_init_obstack);
gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE));
c_parser_consume_token (parser);
if (nested_p)
- push_init_level (0);
+ push_init_level (0, &braced_init_obstack);
else
really_start_incremental_init (type);
if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
{
- pedwarn (OPT_pedantic, "%HISO C forbids empty initializer braces",
- &brace_loc);
+ pedwarn (brace_loc, OPT_pedantic, "ISO C forbids empty initializer braces");
}
else
{
comma. */
while (true)
{
- c_parser_initelt (parser);
+ c_parser_initelt (parser, &braced_init_obstack);
if (parser->error)
break;
if (c_parser_next_token_is (parser, CPP_COMMA))
}
if (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
{
- struct c_expr ret;
ret.value = error_mark_node;
ret.original_code = ERROR_MARK;
+ ret.original_type = NULL;
c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, "expected %<}%>");
+ pop_init_level (0, &braced_init_obstack);
+ obstack_free (&braced_init_obstack, NULL);
return ret;
}
c_parser_consume_token (parser);
- return pop_init_level (0);
+ ret = pop_init_level (0, &braced_init_obstack);
+ obstack_free (&braced_init_obstack, NULL);
+ return ret;
}
/* Parse a nested initializer, including designators. */
static void
-c_parser_initelt (c_parser *parser)
+c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack)
{
/* Parse any designator or designator list. A single array
designator may have the subsequent "=" omitted in GNU C, but a
&& c_parser_peek_2nd_token (parser)->type == CPP_COLON)
{
/* Old-style structure member designator. */
- set_init_label (c_parser_peek_token (parser)->value);
+ set_init_label (c_parser_peek_token (parser)->value,
+ braced_init_obstack);
/* Use the colon as the error location. */
- pedwarn (OPT_pedantic,
- "%Hobsolete use of designated initializer with %<:%>",
- &c_parser_peek_2nd_token (parser)->location);
+ pedwarn (c_parser_peek_2nd_token (parser)->location, OPT_pedantic,
+ "obsolete use of designated initializer with %<:%>");
c_parser_consume_token (parser);
c_parser_consume_token (parser);
}
has been a single array designator and 2 otherwise. */
int des_seen = 0;
/* Location of a designator. */
- location_t des_loc;
+ location_t des_loc = UNKNOWN_LOCATION; /* Quiet warning. */
while (c_parser_next_token_is (parser, CPP_OPEN_SQUARE)
|| c_parser_next_token_is (parser, CPP_DOT))
{
c_parser_consume_token (parser);
if (c_parser_next_token_is (parser, CPP_NAME))
{
- set_init_label (c_parser_peek_token (parser)->value);
+ set_init_label (c_parser_peek_token (parser)->value,
+ braced_init_obstack);
c_parser_consume_token (parser);
}
else
struct c_expr init;
init.value = error_mark_node;
init.original_code = ERROR_MARK;
+ init.original_type = NULL;
c_parser_error (parser, "expected identifier");
c_parser_skip_until_found (parser, CPP_COMMA, NULL);
- process_init_element (init);
+ process_init_element (init, false, braced_init_obstack);
return;
}
}
else
{
tree first, second;
- location_t ellipsis_loc;
+ location_t ellipsis_loc = UNKNOWN_LOCATION; /* Quiet warning. */
/* ??? Following the old parser, [ objc-receiver
objc-message-args ] is accepted as an initializer,
being distinguished from a designator by what follows
goto parse_message_args;
}
first = c_parser_expr_no_commas (parser, NULL).value;
+ mark_exp_read (first);
if (c_parser_next_token_is (parser, CPP_ELLIPSIS)
|| c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
goto array_desig_after_first;
while (c_parser_next_token_is (parser, CPP_COMMA))
{
struct c_expr next;
+ location_t comma_loc, exp_loc;
+ comma_loc = c_parser_peek_token (parser)->location;
c_parser_consume_token (parser);
+ exp_loc = c_parser_peek_token (parser)->location;
next = c_parser_expr_no_commas (parser, NULL);
- next = default_function_array_conversion (next);
- rec = build_compound_expr (rec, next.value);
+ next = default_function_array_read_conversion (exp_loc,
+ next);
+ rec = build_compound_expr (comma_loc, rec, next.value);
}
parse_message_args:
/* Now parse the objc-message-args. */
mexpr.value
= objc_build_message_expr (build_tree_list (rec, args));
mexpr.original_code = ERROR_MARK;
+ mexpr.original_type = NULL;
/* Now parse and process the remainder of the
initializer, starting with this message
expression as a primary-expression. */
- c_parser_initval (parser, &mexpr);
+ c_parser_initval (parser, &mexpr, braced_init_obstack);
return;
}
c_parser_consume_token (parser);
first = c_parser_expr_no_commas (parser, NULL).value;
+ mark_exp_read (first);
array_desig_after_first:
if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
{
ellipsis_loc = c_parser_peek_token (parser)->location;
c_parser_consume_token (parser);
second = c_parser_expr_no_commas (parser, NULL).value;
+ mark_exp_read (second);
}
else
second = NULL_TREE;
if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
{
c_parser_consume_token (parser);
- set_init_index (first, second);
+ set_init_index (first, second, braced_init_obstack);
if (second)
- pedwarn (OPT_pedantic,
- "%HISO C forbids specifying range of "
- "elements to initialize", &ellipsis_loc);
+ pedwarn (ellipsis_loc, OPT_pedantic,
+ "ISO C forbids specifying range of elements to initialize");
}
else
c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
if (c_parser_next_token_is (parser, CPP_EQ))
{
if (!flag_isoc99)
- pedwarn (OPT_pedantic,
- "%HISO C90 forbids specifying subobject "
- "to initialize", &des_loc);
+ pedwarn (des_loc, OPT_pedantic,
+ "ISO C90 forbids specifying subobject to initialize");
c_parser_consume_token (parser);
}
else
{
if (des_seen == 1)
- {
- pedwarn (OPT_pedantic,
- "%Hobsolete use of designated initializer "
- "without %<=%>",
- &c_parser_peek_token (parser)->location);
- }
+ pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic,
+ "obsolete use of designated initializer without %<=%>");
else
{
struct c_expr init;
init.value = error_mark_node;
init.original_code = ERROR_MARK;
+ init.original_type = NULL;
c_parser_error (parser, "expected %<=%>");
c_parser_skip_until_found (parser, CPP_COMMA, NULL);
- process_init_element (init);
+ process_init_element (init, false, braced_init_obstack);
return;
}
}
}
}
- c_parser_initval (parser, NULL);
+ c_parser_initval (parser, NULL, braced_init_obstack);
}
/* Parse a nested initializer; as c_parser_initializer but parses
initializer. */
static void
-c_parser_initval (c_parser *parser, struct c_expr *after)
+c_parser_initval (c_parser *parser, struct c_expr *after,
+ struct obstack * braced_init_obstack)
{
struct c_expr init;
gcc_assert (!after || c_dialect_objc ());
init = c_parser_braced_init (parser, NULL_TREE, true);
else
{
+ location_t loc = c_parser_peek_token (parser)->location;
init = c_parser_expr_no_commas (parser, after);
if (init.value != NULL_TREE
&& TREE_CODE (init.value) != STRING_CST
&& TREE_CODE (init.value) != COMPOUND_LITERAL_EXPR)
- init = default_function_array_conversion (init);
+ init = default_function_array_read_conversion (loc, init);
}
- process_init_element (init);
+ process_init_element (init, false, braced_init_obstack);
}
/* Parse a compound statement (possibly a function body) (C90 6.6.2,
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?
-
+
OpenMP:
-
+
block-item:
openmp-directive
c_parser_compound_statement (c_parser *parser)
{
tree stmt;
+ location_t brace_loc;
+ brace_loc = c_parser_peek_token (parser)->location;
if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
- return error_mark_node;
+ {
+ /* Ensure a scope is entered and left anyway to avoid confusion
+ if we have just prepared to enter a function body. */
+ stmt = c_begin_compound_stmt (true);
+ c_end_compound_stmt (brace_loc, stmt, true);
+ return error_mark_node;
+ }
stmt = c_begin_compound_stmt (true);
c_parser_compound_statement_nostart (parser);
- return c_end_compound_stmt (stmt, true);
+ return c_end_compound_stmt (brace_loc, stmt, true);
}
/* Parse a compound statement except for the opening brace. This is
{
bool last_stmt = false;
bool last_label = false;
- location_t label_loc;
+ bool save_valid_for_pragma = valid_location_for_stdc_pragma_p ();
+ location_t label_loc = UNKNOWN_LOCATION; /* Quiet warning. */
if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
{
c_parser_consume_token (parser);
return;
}
+ mark_valid_location_for_stdc_pragma (true);
if (c_parser_next_token_is_keyword (parser, RID_LABEL))
{
- location_t err_loc = c_parser_peek_token (parser)->location;
/* Read zero or more forward-declarations for labels that nested
functions can jump to. */
+ mark_valid_location_for_stdc_pragma (false);
while (c_parser_next_token_is_keyword (parser, RID_LABEL))
{
+ label_loc = c_parser_peek_token (parser)->location;
c_parser_consume_token (parser);
/* Any identifiers, including those declared as type names,
are OK here. */
label
= declare_label (c_parser_peek_token (parser)->value);
C_DECLARED_LABEL_FLAG (label) = 1;
- add_stmt (build_stmt (DECL_EXPR, label));
+ add_stmt (build_stmt (label_loc, DECL_EXPR, label));
c_parser_consume_token (parser);
if (c_parser_next_token_is (parser, CPP_COMMA))
c_parser_consume_token (parser);
}
c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
}
- pedwarn (OPT_pedantic, "%HISO C forbids label declarations", &err_loc);
+ pedwarn (label_loc, OPT_pedantic, "ISO C forbids label declarations");
}
/* We must now have at least one statement, label or declaration. */
if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
{
+ mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
c_parser_error (parser, "expected declaration or statement");
c_parser_consume_token (parser);
return;
label_loc = c_parser_peek_token (parser)->location;
last_label = true;
last_stmt = false;
+ mark_valid_location_for_stdc_pragma (false);
c_parser_label (parser);
}
else if (!last_label
- && c_parser_next_token_starts_declspecs (parser))
+ && c_parser_next_token_starts_declaration (parser))
{
last_label = false;
- c_parser_declaration_or_fndef (parser, true, true, true, true);
+ mark_valid_location_for_stdc_pragma (false);
+ c_parser_declaration_or_fndef (parser, true, true, true, true, true);
if (last_stmt)
- pedwarn_c90 ((pedantic && !flag_isoc99)
+ pedwarn_c90 (loc,
+ (pedantic && !flag_isoc99)
? OPT_pedantic
: OPT_Wdeclaration_after_statement,
- "%HISO C90 forbids mixed declarations and code",
- &loc);
+ "ISO C90 forbids mixed declarations and code");
last_stmt = false;
}
else if (!last_label
&& (c_parser_peek_2nd_token (parser)->keyword
== RID_EXTENSION))
c_parser_consume_token (parser);
- if (c_token_starts_declspecs (c_parser_peek_2nd_token (parser)))
+ if (c_token_starts_declaration (c_parser_peek_2nd_token (parser)))
{
int ext;
ext = disable_extension_diagnostics ();
c_parser_consume_token (parser);
last_label = false;
- c_parser_declaration_or_fndef (parser, true, true, true, true);
+ mark_valid_location_for_stdc_pragma (false);
+ c_parser_declaration_or_fndef (parser, true, true, true, true,
+ true);
/* Following the old parser, __extension__ does not
disable this diagnostic. */
restore_extension_diagnostics (ext);
if (last_stmt)
- pedwarn_c90 ((pedantic && !flag_isoc99)
+ pedwarn_c90 (loc, (pedantic && !flag_isoc99)
? OPT_pedantic
: OPT_Wdeclaration_after_statement,
- "%HISO C90 forbids mixed declarations and code",
- &loc);
+ "ISO C90 forbids mixed declarations and code");
last_stmt = false;
}
else
}
else if (c_parser_next_token_is (parser, CPP_EOF))
{
+ mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
c_parser_error (parser, "expected declaration or statement");
return;
}
else if (c_parser_next_token_is_keyword (parser, RID_ELSE))
{
- if (parser->in_if_block)
+ if (parser->in_if_block)
{
- error ("%H""expected %<}%> before %<else%>", &loc);
+ mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
+ error_at (loc, """expected %<}%> before %<else%>");
return;
}
- else
+ else
{
- error ("%H%<else%> without a previous %<if%>", &loc);
+ error_at (loc, "%<else%> without a previous %<if%>");
c_parser_consume_token (parser);
continue;
}
statement:
last_label = false;
last_stmt = true;
+ mark_valid_location_for_stdc_pragma (false);
c_parser_statement_after_labels (parser);
}
parser->error = false;
}
if (last_label)
- error ("%Hlabel at end of compound statement", &label_loc);
+ error_at (label_loc, "label at end of compound statement");
c_parser_consume_token (parser);
+ /* Restore the value we started with. */
+ mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
}
/* Parse a label (C90 6.6.1, C99 6.8.1).
if (c_parser_next_token_is (parser, CPP_COLON))
{
c_parser_consume_token (parser);
- label = do_case (exp1, NULL_TREE);
+ label = do_case (loc1, exp1, NULL_TREE);
}
else if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
{
c_parser_consume_token (parser);
exp2 = c_parser_expr_no_commas (parser, NULL).value;
if (c_parser_require (parser, CPP_COLON, "expected %<:%>"))
- label = do_case (exp1, exp2);
+ label = do_case (loc1, exp1, exp2);
}
else
c_parser_error (parser, "expected %<:%> or %<...%>");
{
c_parser_consume_token (parser);
if (c_parser_require (parser, CPP_COLON, "expected %<:%>"))
- label = do_case (NULL_TREE, NULL_TREE);
+ label = do_case (loc1, NULL_TREE, NULL_TREE);
}
else
{
if (tlab)
{
decl_attributes (&tlab, attrs, 0);
- label = add_stmt (build_stmt (LABEL_EXPR, tlab));
+ label = add_stmt (build_stmt (loc1, LABEL_EXPR, tlab));
}
}
if (label)
{
- SET_EXPR_LOCATION (label, loc1);
- if (c_parser_next_token_starts_declspecs (parser)
+ if (c_parser_next_token_starts_declaration (parser)
&& !(c_parser_next_token_is (parser, CPP_NAME)
&& c_parser_peek_2nd_token (parser)->type == CPP_COLON))
{
- error ("%Ha label can only be part of a statement and "
- "a declaration is not a statement",
- &c_parser_peek_token (parser)->location);
- c_parser_declaration_or_fndef (parser, /*fndef_ok*/ false,
+ error_at (c_parser_peek_token (parser)->location,
+ "a label can only be part of a statement and "
+ "a declaration is not a statement");
+ c_parser_declaration_or_fndef (parser, /*fndef_ok*/ false,
+ /*static_assert_ok*/ true,
/*nested*/ true, /*empty_ok*/ false,
/*start_attr_ok*/ true);
}
c_parser_consume_token (parser);
if (c_parser_next_token_is (parser, CPP_NAME))
{
- stmt = c_finish_goto_label (c_parser_peek_token (parser)->value);
+ stmt = c_finish_goto_label (loc,
+ c_parser_peek_token (parser)->value);
c_parser_consume_token (parser);
}
else if (c_parser_next_token_is (parser, CPP_MULT))
{
c_parser_consume_token (parser);
- stmt = c_finish_goto_ptr (c_parser_expression (parser).value);
+ stmt = c_finish_goto_ptr (loc,
+ c_parser_expression (parser).value);
}
else
c_parser_error (parser, "expected identifier or %<*%>");
goto expect_semicolon;
case RID_CONTINUE:
c_parser_consume_token (parser);
- stmt = c_finish_bc_stmt (&c_cont_label, false);
+ stmt = c_finish_bc_stmt (loc, &c_cont_label, false);
goto expect_semicolon;
case RID_BREAK:
c_parser_consume_token (parser);
- stmt = c_finish_bc_stmt (&c_break_label, true);
+ stmt = c_finish_bc_stmt (loc, &c_break_label, true);
goto expect_semicolon;
case RID_RETURN:
c_parser_consume_token (parser);
if (c_parser_next_token_is (parser, CPP_SEMICOLON))
{
- stmt = c_finish_return (NULL_TREE);
+ stmt = c_finish_return (loc, NULL_TREE, NULL_TREE);
c_parser_consume_token (parser);
}
else
{
- stmt = c_finish_return (c_parser_expression_conv (parser).value);
+ struct c_expr expr = c_parser_expression_conv (parser);
+ mark_exp_read (expr.value);
+ stmt = c_finish_return (loc, expr.value, expr.original_type);
goto expect_semicolon;
}
break;
c_parser_consume_token (parser);
if (c_parser_next_token_is (parser, CPP_SEMICOLON))
{
- stmt = objc_build_throw_stmt (NULL_TREE);
+ stmt = objc_build_throw_stmt (loc, NULL_TREE);
c_parser_consume_token (parser);
}
else
{
- stmt
- = objc_build_throw_stmt (c_parser_expression (parser).value);
+ tree expr = c_parser_expression (parser).value;
+ expr = c_fully_fold (expr, false, NULL);
+ stmt = objc_build_throw_stmt (loc, expr);
goto expect_semicolon;
}
break;
break;
default:
expr_stmt:
- stmt = c_finish_expr_stmt (c_parser_expression_conv (parser).value);
+ stmt = c_finish_expr_stmt (loc, c_parser_expression_conv (parser).value);
expect_semicolon:
c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
break;
(recursively) all of the component statements should already have
line numbers assigned. ??? Can we discard no-op statements
earlier? */
- if (stmt && CAN_HAVE_LOCATION_P (stmt))
+ if (CAN_HAVE_LOCATION_P (stmt)
+ && EXPR_LOCATION (stmt) == UNKNOWN_LOCATION)
SET_EXPR_LOCATION (stmt, loc);
parser->in_if_block = in_if_block;
static tree
c_parser_condition (c_parser *parser)
{
- location_t loc;
+ location_t loc = c_parser_peek_token (parser)->location;
tree cond;
- loc = c_parser_peek_token (parser)->location;
- cond = c_objc_common_truthvalue_conversion
- (c_parser_expression_conv (parser).value);
- if (CAN_HAVE_LOCATION_P (cond))
- SET_EXPR_LOCATION (cond, loc);
+ cond = c_parser_expression_conv (parser).value;
+ cond = c_objc_common_truthvalue_conversion (loc, cond);
+ cond = c_fully_fold (cond, false, NULL);
if (warn_sequence_point)
verify_sequence_points (cond);
return cond;
c_parser_c99_block_statement (c_parser *parser)
{
tree block = c_begin_compound_stmt (flag_isoc99);
+ location_t loc = c_parser_peek_token (parser)->location;
c_parser_statement (parser);
- return c_end_compound_stmt (block, flag_isoc99);
+ return c_end_compound_stmt (loc, block, flag_isoc99);
}
/* Parse the body of an if statement. This is just parsing a
c_parser_if_body (c_parser *parser, bool *if_p)
{
tree block = c_begin_compound_stmt (flag_isoc99);
+ location_t body_loc = c_parser_peek_token (parser)->location;
while (c_parser_next_token_is_keyword (parser, RID_CASE)
|| c_parser_next_token_is_keyword (parser, RID_DEFAULT)
|| (c_parser_next_token_is (parser, CPP_NAME)
*if_p = c_parser_next_token_is_keyword (parser, RID_IF);
if (c_parser_next_token_is (parser, CPP_SEMICOLON))
{
- add_stmt (build_empty_stmt ());
+ location_t loc = c_parser_peek_token (parser)->location;
+ add_stmt (build_empty_stmt (loc));
c_parser_consume_token (parser);
+ if (!c_parser_next_token_is_keyword (parser, RID_ELSE))
+ warning_at (loc, OPT_Wempty_body,
+ "suggest braces around empty body in an %<if%> statement");
}
else if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
add_stmt (c_parser_compound_statement (parser));
else
c_parser_statement_after_labels (parser);
- return c_end_compound_stmt (block, flag_isoc99);
+ return c_end_compound_stmt (body_loc, block, flag_isoc99);
}
/* Parse the else body of an if statement. This is just parsing a
static tree
c_parser_else_body (c_parser *parser)
{
+ location_t else_loc = c_parser_peek_token (parser)->location;
tree block = c_begin_compound_stmt (flag_isoc99);
while (c_parser_next_token_is_keyword (parser, RID_CASE)
|| c_parser_next_token_is_keyword (parser, RID_DEFAULT)
c_parser_label (parser);
if (c_parser_next_token_is (parser, CPP_SEMICOLON))
{
- add_stmt (build_empty_stmt ());
+ location_t loc = c_parser_peek_token (parser)->location;
+ warning_at (loc,
+ OPT_Wempty_body,
+ "suggest braces around empty body in an %<else%> statement");
+ add_stmt (build_empty_stmt (loc));
c_parser_consume_token (parser);
}
- else
+ else
c_parser_statement_after_labels (parser);
- return c_end_compound_stmt (block, flag_isoc99);
+ return c_end_compound_stmt (else_loc, block, flag_isoc99);
}
/* Parse an if statement (C90 6.6.4, C99 6.8.4).
else
second_body = NULL_TREE;
c_finish_if_stmt (loc, cond, first_body, second_body, first_if);
- add_stmt (c_end_compound_stmt (block, flag_isoc99));
+ add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
}
/* Parse a switch statement (C90 6.6.4, C99 6.8.4).
c_parser_switch_statement (c_parser *parser)
{
tree block, expr, body, save_break;
+ location_t switch_loc = c_parser_peek_token (parser)->location;
+ location_t switch_cond_loc;
gcc_assert (c_parser_next_token_is_keyword (parser, RID_SWITCH));
c_parser_consume_token (parser);
block = c_begin_compound_stmt (flag_isoc99);
if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
+ switch_cond_loc = c_parser_peek_token (parser)->location;
expr = c_parser_expression (parser).value;
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
}
else
- expr = error_mark_node;
- c_start_case (expr);
+ {
+ switch_cond_loc = UNKNOWN_LOCATION;
+ expr = error_mark_node;
+ }
+ c_start_case (switch_loc, switch_cond_loc, expr);
save_break = c_break_label;
c_break_label = NULL_TREE;
body = c_parser_c99_block_statement (parser);
c_finish_case (body);
if (c_break_label)
- add_stmt (build1 (LABEL_EXPR, void_type_node, c_break_label));
+ {
+ location_t here = c_parser_peek_token (parser)->location;
+ tree t = build1 (LABEL_EXPR, void_type_node, c_break_label);
+ SET_EXPR_LOCATION (t, here);
+ add_stmt (t);
+ }
c_break_label = save_break;
- add_stmt (c_end_compound_stmt (block, flag_isoc99));
+ add_stmt (c_end_compound_stmt (switch_loc, block, flag_isoc99));
}
/* Parse a while statement (C90 6.6.5, C99 6.8.5).
c_cont_label = NULL_TREE;
body = c_parser_c99_block_statement (parser);
c_finish_loop (loc, cond, NULL, body, c_break_label, c_cont_label, true);
- add_stmt (c_end_compound_stmt (block, flag_isoc99));
+ add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
c_break_label = save_break;
c_cont_label = save_cont;
}
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,
- "%Hsuggest braces around empty body in %<do%> statement",
- &c_parser_peek_token (parser)->location);
+ warning_at (c_parser_peek_token (parser)->location,
+ OPT_Wempty_body,
+ "suggest braces around empty body in %<do%> statement");
block = c_begin_compound_stmt (flag_isoc99);
loc = c_parser_peek_token (parser)->location;
save_break = c_break_label;
if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
c_parser_skip_to_end_of_block_or_statement (parser);
c_finish_loop (loc, cond, NULL, body, new_break, new_cont, false);
- add_stmt (c_end_compound_stmt (block, flag_isoc99));
+ add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
}
/* Parse a for statement (C90 6.6.5, C99 6.8.5).
c_parser_for_statement (c_parser *parser)
{
tree block, cond, incr, save_break, save_cont, body;
- location_t loc;
+ location_t loc = c_parser_peek_token (parser)->location;
+ location_t for_loc = c_parser_peek_token (parser)->location;
gcc_assert (c_parser_next_token_is_keyword (parser, RID_FOR));
- loc = c_parser_peek_token (parser)->location;
c_parser_consume_token (parser);
block = c_begin_compound_stmt (flag_isoc99);
if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
if (c_parser_next_token_is (parser, CPP_SEMICOLON))
{
c_parser_consume_token (parser);
- c_finish_expr_stmt (NULL_TREE);
+ c_finish_expr_stmt (loc, NULL_TREE);
}
- else if (c_parser_next_token_starts_declspecs (parser))
+ else if (c_parser_next_token_starts_declaration (parser))
{
- c_parser_declaration_or_fndef (parser, true, true, true, true);
- check_for_loop_decls ();
+ c_parser_declaration_or_fndef (parser, true, true, true, true, true);
+ check_for_loop_decls (for_loc);
}
else if (c_parser_next_token_is_keyword (parser, RID_EXTENSION))
{
&& (c_parser_peek_2nd_token (parser)->keyword
== RID_EXTENSION))
c_parser_consume_token (parser);
- if (c_token_starts_declspecs (c_parser_peek_2nd_token (parser)))
+ if (c_token_starts_declaration (c_parser_peek_2nd_token (parser)))
{
int ext;
ext = disable_extension_diagnostics ();
c_parser_consume_token (parser);
- c_parser_declaration_or_fndef (parser, true, true, true, true);
+ c_parser_declaration_or_fndef (parser, true, true, true, true,
+ true);
restore_extension_diagnostics (ext);
- check_for_loop_decls ();
+ check_for_loop_decls (for_loc);
}
else
goto init_expr;
else
{
init_expr:
- c_finish_expr_stmt (c_parser_expression (parser).value);
+ c_finish_expr_stmt (loc, c_parser_expression (parser).value);
c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
}
/* Parse the loop condition. */
}
/* Parse the increment expression. */
if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
- incr = c_process_expr_stmt (NULL_TREE);
+ incr = c_process_expr_stmt (loc, NULL_TREE);
else
- incr = c_process_expr_stmt (c_parser_expression (parser).value);
+ incr = c_process_expr_stmt (loc, c_parser_expression (parser).value);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
}
else
c_cont_label = NULL_TREE;
body = c_parser_c99_block_statement (parser);
c_finish_loop (loc, cond, incr, body, c_break_label, c_cont_label, true);
- add_stmt (c_end_compound_stmt (block, flag_isoc99));
+ add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
c_break_label = save_break;
c_cont_label = save_cont;
}
asm-statement:
asm type-qualifier[opt] ( asm-argument ) ;
+ asm type-qualifier[opt] goto ( asm-goto-argument ) ;
asm-argument:
asm-string-literal
asm-string-literal : asm-operands[opt]
asm-string-literal : asm-operands[opt] : asm-operands[opt]
- asm-string-literal : asm-operands[opt] : asm-operands[opt] : asm-clobbers
+ asm-string-literal : asm-operands[opt] : asm-operands[opt] : asm-clobbers[opt]
+
+ asm-goto-argument:
+ asm-string-literal : : asm-operands[opt] : asm-clobbers[opt] \
+ : asm-goto-operands
Qualifiers other than volatile are accepted in the syntax but
warned for. */
static tree
c_parser_asm_statement (c_parser *parser)
{
- tree quals, str, outputs, inputs, clobbers, ret;
- bool simple;
+ tree quals, str, outputs, inputs, clobbers, labels, ret;
+ bool simple, is_goto;
+ location_t asm_loc = c_parser_peek_token (parser)->location;
+ int section, nsections;
+
gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
c_parser_consume_token (parser);
if (c_parser_next_token_is_keyword (parser, RID_VOLATILE))
else if (c_parser_next_token_is_keyword (parser, RID_CONST)
|| c_parser_next_token_is_keyword (parser, RID_RESTRICT))
{
- warning (0, "%H%E qualifier ignored on asm",
- &c_parser_peek_token (parser)->location,
- c_parser_peek_token (parser)->value);
+ warning_at (c_parser_peek_token (parser)->location,
+ 0,
+ "%E qualifier ignored on asm",
+ c_parser_peek_token (parser)->value);
quals = NULL_TREE;
c_parser_consume_token (parser);
}
else
quals = NULL_TREE;
+
+ is_goto = false;
+ if (c_parser_next_token_is_keyword (parser, RID_GOTO))
+ {
+ c_parser_consume_token (parser);
+ is_goto = true;
+ }
+
/* ??? Follow the C++ parser rather than using the
lex_untranslated_string kludge. */
parser->lex_untranslated_string = true;
+ ret = NULL;
+
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
- {
- parser->lex_untranslated_string = false;
- return NULL_TREE;
- }
+ goto error;
+
str = c_parser_asm_string_literal (parser);
- if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
- {
- simple = true;
- outputs = NULL_TREE;
- inputs = NULL_TREE;
- clobbers = NULL_TREE;
- goto done_asm;
- }
- if (!c_parser_require (parser, CPP_COLON, "expected %<:%> or %<)%>"))
- {
- parser->lex_untranslated_string = false;
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
- return NULL_TREE;
- }
- simple = false;
- /* Parse outputs. */
- if (c_parser_next_token_is (parser, CPP_COLON)
- || c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
- outputs = NULL_TREE;
- else
- outputs = c_parser_asm_operands (parser, false);
- if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
- {
- inputs = NULL_TREE;
- clobbers = NULL_TREE;
- goto done_asm;
- }
- if (!c_parser_require (parser, CPP_COLON, "expected %<:%> or %<)%>"))
- {
- parser->lex_untranslated_string = false;
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
- return NULL_TREE;
- }
- /* Parse inputs. */
- if (c_parser_next_token_is (parser, CPP_COLON)
- || c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
- inputs = NULL_TREE;
- else
- inputs = c_parser_asm_operands (parser, true);
- if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
- {
- clobbers = NULL_TREE;
- goto done_asm;
- }
- if (!c_parser_require (parser, CPP_COLON, "expected %<:%> or %<)%>"))
- {
- parser->lex_untranslated_string = false;
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
- return NULL_TREE;
+ if (str == NULL_TREE)
+ goto error_close_paren;
+
+ simple = true;
+ outputs = NULL_TREE;
+ inputs = NULL_TREE;
+ clobbers = NULL_TREE;
+ labels = NULL_TREE;
+
+ if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN) && !is_goto)
+ goto done_asm;
+
+ /* Parse each colon-delimited section of operands. */
+ nsections = 3 + is_goto;
+ for (section = 0; section < nsections; ++section)
+ {
+ if (!c_parser_require (parser, CPP_COLON,
+ is_goto
+ ? "expected %<:%>"
+ : "expected %<:%> or %<)%>"))
+ goto error_close_paren;
+
+ /* Once past any colon, we're no longer a simple asm. */
+ simple = false;
+
+ if ((!c_parser_next_token_is (parser, CPP_COLON)
+ && !c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+ || section == 3)
+ switch (section)
+ {
+ case 0:
+ /* For asm goto, we don't allow output operands, but reserve
+ the slot for a future extension that does allow them. */
+ if (!is_goto)
+ outputs = c_parser_asm_operands (parser, false);
+ break;
+ case 1:
+ inputs = c_parser_asm_operands (parser, true);
+ break;
+ case 2:
+ clobbers = c_parser_asm_clobbers (parser);
+ break;
+ case 3:
+ labels = c_parser_asm_goto_operands (parser);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN) && !is_goto)
+ goto done_asm;
}
- /* Parse clobbers. */
- clobbers = c_parser_asm_clobbers (parser);
+
done_asm:
- parser->lex_untranslated_string = false;
if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
{
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
- return NULL_TREE;
+ goto error;
}
+
if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
c_parser_skip_to_end_of_block_or_statement (parser);
- ret = build_asm_stmt (quals, build_asm_expr (str, outputs, inputs,
- clobbers, simple));
+
+ ret = build_asm_stmt (quals, build_asm_expr (asm_loc, str, outputs, inputs,
+ clobbers, labels, simple));
+
+ error:
+ parser->lex_untranslated_string = false;
return ret;
+
+ error_close_paren:
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
+ goto error;
}
/* Parse asm operands, a GNU extension. If CONVERT_P (for inputs but
c_parser_asm_operands (c_parser *parser, bool convert_p)
{
tree list = NULL_TREE;
+ location_t loc;
while (true)
{
tree name, str;
parser->lex_untranslated_string = true;
return NULL_TREE;
}
+ loc = c_parser_peek_token (parser)->location;
expr = c_parser_expression (parser);
+ mark_exp_read (expr.value);
if (convert_p)
- expr = default_function_array_conversion (expr);
+ expr = default_function_array_conversion (loc, expr);
+ expr.value = c_fully_fold (expr.value, false, NULL);
parser->lex_untranslated_string = true;
if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
{
return list;
}
+/* Parse asm goto labels, a GNU extension.
+
+ asm-goto-operands:
+ identifier
+ asm-goto-operands , identifier
+*/
+
+static tree
+c_parser_asm_goto_operands (c_parser *parser)
+{
+ tree list = NULL_TREE;
+ while (true)
+ {
+ tree name, label;
+
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ c_token *tok = c_parser_peek_token (parser);
+ name = tok->value;
+ label = lookup_label_for_goto (tok->location, name);
+ c_parser_consume_token (parser);
+ TREE_USED (label) = 1;
+ }
+ else
+ {
+ c_parser_error (parser, "expected identifier");
+ return NULL_TREE;
+ }
+
+ name = build_string (IDENTIFIER_LENGTH (name),
+ IDENTIFIER_POINTER (name));
+ list = tree_cons (name, label, list);
+ if (c_parser_next_token_is (parser, CPP_COMMA))
+ c_parser_consume_token (parser);
+ else
+ return nreverse (list);
+ }
+}
+
/* Parse an expression other than a compound expression; that is, an
assignment expression (C90 6.3.16, C99 6.5.16). If AFTER is not
NULL then it is an Objective-C message expression which is the
{
struct c_expr lhs, rhs, ret;
enum tree_code code;
+ location_t op_location, exp_location;
gcc_assert (!after || c_dialect_objc ());
lhs = c_parser_conditional_expression (parser, after);
+ op_location = c_parser_peek_token (parser)->location;
switch (c_parser_peek_token (parser)->type)
{
case CPP_EQ:
return lhs;
}
c_parser_consume_token (parser);
+ exp_location = c_parser_peek_token (parser)->location;
rhs = c_parser_expr_no_commas (parser, NULL);
- rhs = default_function_array_conversion (rhs);
- ret.value = build_modify_expr (lhs.value, code, rhs.value);
+ rhs = default_function_array_read_conversion (exp_location, rhs);
+ ret.value = build_modify_expr (op_location, lhs.value, lhs.original_type,
+ code, exp_location, rhs.value,
+ rhs.original_type);
if (code == NOP_EXPR)
ret.original_code = MODIFY_EXPR;
else
TREE_NO_WARNING (ret.value) = 1;
ret.original_code = ERROR_MARK;
}
+ ret.original_type = NULL;
return ret;
}
c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
{
struct c_expr cond, exp1, exp2, ret;
+ location_t cond_loc, colon_loc, middle_loc;
+
gcc_assert (!after || c_dialect_objc ());
+
cond = c_parser_binary_expression (parser, after);
+
if (c_parser_next_token_is_not (parser, CPP_QUERY))
return cond;
- cond = default_function_array_conversion (cond);
+ cond_loc = c_parser_peek_token (parser)->location;
+ cond = default_function_array_read_conversion (cond_loc, cond);
c_parser_consume_token (parser);
if (c_parser_next_token_is (parser, CPP_COLON))
{
- pedwarn (OPT_pedantic,
- "%HISO C forbids omitting the middle term of a ?: expression",
- &c_parser_peek_token (parser)->location);
+ tree eptype = NULL_TREE;
+
+ middle_loc = c_parser_peek_token (parser)->location;
+ pedwarn (middle_loc, OPT_pedantic,
+ "ISO C forbids omitting the middle term of a ?: expression");
+ warn_for_omitted_condop (middle_loc, cond.value);
+ if (TREE_CODE (cond.value) == EXCESS_PRECISION_EXPR)
+ {
+ eptype = TREE_TYPE (cond.value);
+ cond.value = TREE_OPERAND (cond.value, 0);
+ }
/* Make sure first operand is calculated only once. */
- exp1.value = save_expr (default_conversion (cond.value));
- cond.value = c_objc_common_truthvalue_conversion (exp1.value);
- skip_evaluation += cond.value == truthvalue_true_node;
+ exp1.value = c_save_expr (default_conversion (cond.value));
+ if (eptype)
+ exp1.value = build1 (EXCESS_PRECISION_EXPR, eptype, exp1.value);
+ exp1.original_type = NULL;
+ cond.value = c_objc_common_truthvalue_conversion (cond_loc, exp1.value);
+ c_inhibit_evaluation_warnings += cond.value == truthvalue_true_node;
}
else
{
cond.value
= c_objc_common_truthvalue_conversion
- (default_conversion (cond.value));
- skip_evaluation += cond.value == truthvalue_false_node;
+ (cond_loc, default_conversion (cond.value));
+ c_inhibit_evaluation_warnings += cond.value == truthvalue_false_node;
exp1 = c_parser_expression_conv (parser);
- skip_evaluation += ((cond.value == truthvalue_true_node)
- - (cond.value == truthvalue_false_node));
+ mark_exp_read (exp1.value);
+ c_inhibit_evaluation_warnings +=
+ ((cond.value == truthvalue_true_node)
+ - (cond.value == truthvalue_false_node));
}
+
+ colon_loc = c_parser_peek_token (parser)->location;
if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
{
- skip_evaluation -= cond.value == truthvalue_true_node;
+ c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node;
ret.value = error_mark_node;
ret.original_code = ERROR_MARK;
+ ret.original_type = NULL;
return ret;
}
- exp2 = c_parser_conditional_expression (parser, NULL);
- exp2 = default_function_array_conversion (exp2);
- skip_evaluation -= cond.value == truthvalue_true_node;
- ret.value = build_conditional_expr (cond.value, exp1.value, exp2.value);
+ {
+ location_t exp2_loc = c_parser_peek_token (parser)->location;
+ exp2 = c_parser_conditional_expression (parser, NULL);
+ exp2 = default_function_array_read_conversion (exp2_loc, exp2);
+ }
+ c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node;
+ ret.value = build_conditional_expr (colon_loc, cond.value,
+ cond.original_code == C_MAYBE_CONST_EXPR,
+ exp1.value, exp1.original_type,
+ exp2.value, exp2.original_type);
ret.original_code = ERROR_MARK;
+ if (exp1.value == error_mark_node || exp2.value == error_mark_node)
+ ret.original_type = NULL;
+ else
+ {
+ tree t1, t2;
+
+ /* If both sides are enum type, the default conversion will have
+ made the type of the result be an integer type. We want to
+ remember the enum types we started with. */
+ t1 = exp1.original_type ? exp1.original_type : TREE_TYPE (exp1.value);
+ t2 = exp2.original_type ? exp2.original_type : TREE_TYPE (exp2.value);
+ ret.original_type = ((t1 != error_mark_node
+ && t2 != error_mark_node
+ && (TYPE_MAIN_VARIANT (t1)
+ == TYPE_MAIN_VARIANT (t2)))
+ ? t1
+ : NULL);
+ }
return ret;
}
the stack has lower precedence than the new operator or there is
only one element on the stack; then the top expression is the LHS
of the new operator. In the case of logical AND and OR
- expressions, we also need to adjust skip_evaluation as
- appropriate when the operators are pushed and popped. */
+ expressions, we also need to adjust c_inhibit_evaluation_warnings
+ as appropriate when the operators are pushed and popped. */
/* The precedence levels, where 0 is a dummy lowest level used for
the bottom of the stack. */
enum prec prec;
/* The operation on its left. */
enum tree_code op;
+ /* The source location of this operation. */
+ location_t loc;
} stack[NUM_PRECS];
int sp;
+ /* Location of the binary operator. */
+ location_t binary_loc = UNKNOWN_LOCATION; /* Quiet warning. */
#define POP \
do { \
switch (stack[sp].op) \
{ \
case TRUTH_ANDIF_EXPR: \
- skip_evaluation -= stack[sp - 1].expr.value == truthvalue_false_node; \
+ c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value \
+ == truthvalue_false_node); \
break; \
case TRUTH_ORIF_EXPR: \
- skip_evaluation -= stack[sp - 1].expr.value == truthvalue_true_node; \
+ c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value \
+ == truthvalue_true_node); \
break; \
default: \
break; \
} \
stack[sp - 1].expr \
- = default_function_array_conversion (stack[sp - 1].expr); \
+ = default_function_array_read_conversion (stack[sp - 1].loc, \
+ stack[sp - 1].expr); \
stack[sp].expr \
- = default_function_array_conversion (stack[sp].expr); \
- stack[sp - 1].expr = parser_build_binary_op (stack[sp].op, \
+ = default_function_array_read_conversion (stack[sp].loc, \
+ stack[sp].expr); \
+ stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc, \
+ stack[sp].op, \
stack[sp - 1].expr, \
stack[sp].expr); \
sp--; \
} while (0)
gcc_assert (!after || c_dialect_objc ());
+ stack[0].loc = c_parser_peek_token (parser)->location;
stack[0].expr = c_parser_cast_expression (parser, after);
stack[0].prec = PREC_NONE;
sp = 0;
expression. */
goto out;
}
+ binary_loc = c_parser_peek_token (parser)->location;
c_parser_consume_token (parser);
while (oprec <= stack[sp].prec)
POP;
{
case TRUTH_ANDIF_EXPR:
stack[sp].expr
- = default_function_array_conversion (stack[sp].expr);
+ = default_function_array_read_conversion (stack[sp].loc,
+ stack[sp].expr);
stack[sp].expr.value = c_objc_common_truthvalue_conversion
- (default_conversion (stack[sp].expr.value));
- skip_evaluation += stack[sp].expr.value == truthvalue_false_node;
+ (stack[sp].loc, default_conversion (stack[sp].expr.value));
+ c_inhibit_evaluation_warnings += (stack[sp].expr.value
+ == truthvalue_false_node);
break;
case TRUTH_ORIF_EXPR:
stack[sp].expr
- = default_function_array_conversion (stack[sp].expr);
+ = default_function_array_read_conversion (stack[sp].loc,
+ stack[sp].expr);
stack[sp].expr.value = c_objc_common_truthvalue_conversion
- (default_conversion (stack[sp].expr.value));
- skip_evaluation += stack[sp].expr.value == truthvalue_true_node;
+ (stack[sp].loc, default_conversion (stack[sp].expr.value));
+ c_inhibit_evaluation_warnings += (stack[sp].expr.value
+ == truthvalue_true_node);
break;
default:
break;
}
sp++;
+ stack[sp].loc = binary_loc;
stack[sp].expr = c_parser_cast_expression (parser, NULL);
stack[sp].prec = oprec;
stack[sp].op = ocode;
+ stack[sp].loc = binary_loc;
}
out:
while (sp > 0)
static struct c_expr
c_parser_cast_expression (c_parser *parser, struct c_expr *after)
{
+ location_t cast_loc = c_parser_peek_token (parser)->location;
gcc_assert (!after || c_dialect_objc ());
if (after)
- return c_parser_postfix_expression_after_primary (parser, *after);
+ return c_parser_postfix_expression_after_primary (parser,
+ cast_loc, *after);
/* If the expression begins with a parenthesized type name, it may
be either a cast or a compound literal; we need to see whether
the next character is '{' to tell the difference. If not, it is
{
ret.value = error_mark_node;
ret.original_code = ERROR_MARK;
+ ret.original_type = NULL;
return ret;
}
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);
- expr = c_parser_cast_expression (parser, NULL);
- expr = default_function_array_conversion (expr);
- ret.value = c_cast_expr (type_name, expr.value);
+ return c_parser_postfix_expression_after_paren_type (parser, type_name,
+ cast_loc);
+ {
+ location_t expr_loc = c_parser_peek_token (parser)->location;
+ expr = c_parser_cast_expression (parser, NULL);
+ expr = default_function_array_read_conversion (expr_loc, expr);
+ }
+ ret.value = c_cast_expr (cast_loc, type_name, expr.value);
ret.original_code = ERROR_MARK;
+ ret.original_type = NULL;
return ret;
}
else
{
int ext;
struct c_expr ret, op;
+ location_t op_loc = c_parser_peek_token (parser)->location;
+ location_t exp_loc;
+ ret.original_code = ERROR_MARK;
+ ret.original_type = NULL;
switch (c_parser_peek_token (parser)->type)
{
case CPP_PLUS_PLUS:
c_parser_consume_token (parser);
+ exp_loc = c_parser_peek_token (parser)->location;
op = c_parser_cast_expression (parser, NULL);
- op = default_function_array_conversion (op);
- return parser_build_unary_op (PREINCREMENT_EXPR, op);
+ op = default_function_array_read_conversion (exp_loc, op);
+ return parser_build_unary_op (op_loc, PREINCREMENT_EXPR, op);
case CPP_MINUS_MINUS:
c_parser_consume_token (parser);
+ exp_loc = c_parser_peek_token (parser)->location;
op = c_parser_cast_expression (parser, NULL);
- op = default_function_array_conversion (op);
- return parser_build_unary_op (PREDECREMENT_EXPR, op);
+ op = default_function_array_read_conversion (exp_loc, op);
+ return parser_build_unary_op (op_loc, PREDECREMENT_EXPR, op);
case CPP_AND:
c_parser_consume_token (parser);
- return parser_build_unary_op (ADDR_EXPR,
- c_parser_cast_expression (parser, NULL));
+ op = c_parser_cast_expression (parser, NULL);
+ mark_exp_read (op.value);
+ return parser_build_unary_op (op_loc, ADDR_EXPR, op);
case CPP_MULT:
c_parser_consume_token (parser);
+ exp_loc = c_parser_peek_token (parser)->location;
op = c_parser_cast_expression (parser, NULL);
- op = default_function_array_conversion (op);
- ret.value = build_indirect_ref (op.value, "unary *");
- ret.original_code = ERROR_MARK;
+ op = default_function_array_read_conversion (exp_loc, op);
+ ret.value = build_indirect_ref (op_loc, op.value, RO_UNARY_STAR);
return ret;
case CPP_PLUS:
if (!c_dialect_objc () && !in_system_header)
- warning (OPT_Wtraditional,
- "%Htraditional C rejects the unary plus operator",
- &c_parser_peek_token (parser)->location);
+ warning_at (op_loc,
+ OPT_Wtraditional,
+ "traditional C rejects the unary plus operator");
c_parser_consume_token (parser);
+ exp_loc = c_parser_peek_token (parser)->location;
op = c_parser_cast_expression (parser, NULL);
- op = default_function_array_conversion (op);
- return parser_build_unary_op (CONVERT_EXPR, op);
+ op = default_function_array_read_conversion (exp_loc, op);
+ return parser_build_unary_op (op_loc, CONVERT_EXPR, op);
case CPP_MINUS:
c_parser_consume_token (parser);
+ exp_loc = c_parser_peek_token (parser)->location;
op = c_parser_cast_expression (parser, NULL);
- op = default_function_array_conversion (op);
- return parser_build_unary_op (NEGATE_EXPR, op);
+ op = default_function_array_read_conversion (exp_loc, op);
+ return parser_build_unary_op (op_loc, NEGATE_EXPR, op);
case CPP_COMPL:
c_parser_consume_token (parser);
+ exp_loc = c_parser_peek_token (parser)->location;
op = c_parser_cast_expression (parser, NULL);
- op = default_function_array_conversion (op);
- return parser_build_unary_op (BIT_NOT_EXPR, op);
+ op = default_function_array_read_conversion (exp_loc, op);
+ return parser_build_unary_op (op_loc, BIT_NOT_EXPR, op);
case CPP_NOT:
c_parser_consume_token (parser);
+ exp_loc = c_parser_peek_token (parser)->location;
op = c_parser_cast_expression (parser, NULL);
- op = default_function_array_conversion (op);
- return parser_build_unary_op (TRUTH_NOT_EXPR, op);
+ op = default_function_array_read_conversion (exp_loc, op);
+ return parser_build_unary_op (op_loc, TRUTH_NOT_EXPR, op);
case CPP_AND_AND:
/* Refer to the address of a label as a pointer. */
c_parser_consume_token (parser);
if (c_parser_next_token_is (parser, CPP_NAME))
{
ret.value = finish_label_address_expr
- (c_parser_peek_token (parser)->value);
+ (c_parser_peek_token (parser)->value, op_loc);
c_parser_consume_token (parser);
}
else
c_parser_error (parser, "expected identifier");
ret.value = error_mark_node;
}
- ret.original_code = ERROR_MARK;
return ret;
case CPP_KEYWORD:
switch (c_parser_peek_token (parser)->keyword)
return ret;
case RID_REALPART:
c_parser_consume_token (parser);
+ exp_loc = c_parser_peek_token (parser)->location;
op = c_parser_cast_expression (parser, NULL);
- op = default_function_array_conversion (op);
- return parser_build_unary_op (REALPART_EXPR, op);
+ op = default_function_array_conversion (exp_loc, op);
+ return parser_build_unary_op (op_loc, REALPART_EXPR, op);
case RID_IMAGPART:
c_parser_consume_token (parser);
+ exp_loc = c_parser_peek_token (parser)->location;
op = c_parser_cast_expression (parser, NULL);
- op = default_function_array_conversion (op);
- return parser_build_unary_op (IMAGPART_EXPR, op);
+ op = default_function_array_conversion (exp_loc, op);
+ return parser_build_unary_op (op_loc, IMAGPART_EXPR, op);
default:
return c_parser_postfix_expression (parser);
}
location_t expr_loc;
gcc_assert (c_parser_next_token_is_keyword (parser, RID_SIZEOF));
c_parser_consume_token (parser);
- skip_evaluation++;
+ c_inhibit_evaluation_warnings++;
in_sizeof++;
if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
&& c_token_starts_typename (c_parser_peek_2nd_token (parser)))
if (type_name == NULL)
{
struct c_expr ret;
- skip_evaluation--;
+ c_inhibit_evaluation_warnings--;
in_sizeof--;
ret.value = error_mark_node;
ret.original_code = ERROR_MARK;
+ ret.original_type = NULL;
return ret;
}
if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
{
expr = c_parser_postfix_expression_after_paren_type (parser,
- type_name);
+ type_name,
+ expr_loc);
goto sizeof_expr;
}
/* sizeof ( type-name ). */
- skip_evaluation--;
+ c_inhibit_evaluation_warnings--;
in_sizeof--;
- if (type_name->declarator->kind == cdk_array
- && type_name->declarator->u.array.vla_unspec_p)
- {
- /* C99 6.7.5.2p4 */
- error ("%H%<[*]%> not allowed in other than a declaration",
- &expr_loc);
- }
- return c_expr_sizeof_type (type_name);
+ return c_expr_sizeof_type (expr_loc, type_name);
}
else
{
expr_loc = c_parser_peek_token (parser)->location;
expr = c_parser_unary_expression (parser);
sizeof_expr:
- skip_evaluation--;
+ c_inhibit_evaluation_warnings--;
in_sizeof--;
+ mark_exp_read (expr.value);
if (TREE_CODE (expr.value) == COMPONENT_REF
&& DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
- error ("%H%<sizeof%> applied to a bit-field", &expr_loc);
- return c_expr_sizeof_expr (expr);
+ error_at (expr_loc, "%<sizeof%> applied to a bit-field");
+ return c_expr_sizeof_expr (expr_loc, expr);
}
}
c_parser_alignof_expression (c_parser *parser)
{
struct c_expr expr;
+ location_t loc = c_parser_peek_token (parser)->location;
gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNOF));
c_parser_consume_token (parser);
- skip_evaluation++;
+ c_inhibit_evaluation_warnings++;
in_alignof++;
if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
&& c_token_starts_typename (c_parser_peek_2nd_token (parser)))
{
/* Either __alignof__ ( type-name ) or __alignof__
unary-expression starting with a compound literal. */
+ location_t loc;
struct c_type_name *type_name;
struct c_expr ret;
c_parser_consume_token (parser);
+ loc = c_parser_peek_token (parser)->location;
type_name = c_parser_type_name (parser);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
if (type_name == NULL)
{
struct c_expr ret;
- skip_evaluation--;
+ c_inhibit_evaluation_warnings--;
in_alignof--;
ret.value = error_mark_node;
ret.original_code = ERROR_MARK;
+ ret.original_type = NULL;
return ret;
}
if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
{
expr = c_parser_postfix_expression_after_paren_type (parser,
- type_name);
+ type_name,
+ loc);
goto alignof_expr;
}
/* alignof ( type-name ). */
- skip_evaluation--;
+ c_inhibit_evaluation_warnings--;
in_alignof--;
- ret.value = c_alignof (groktypename (type_name));
+ ret.value = c_alignof (loc, groktypename (type_name, NULL, NULL));
ret.original_code = ERROR_MARK;
+ ret.original_type = NULL;
return ret;
}
else
struct c_expr ret;
expr = c_parser_unary_expression (parser);
alignof_expr:
- skip_evaluation--;
+ mark_exp_read (expr.value);
+ c_inhibit_evaluation_warnings--;
in_alignof--;
- ret.value = c_alignof_expr (expr.value);
+ ret.value = c_alignof_expr (loc, expr.value);
ret.original_code = ERROR_MARK;
+ ret.original_type = NULL;
return ret;
}
}
{
struct c_expr expr, e1, e2, e3;
struct c_type_name *t1, *t2;
- location_t loc;
+ location_t loc = c_parser_peek_token (parser)->location;;
+ expr.original_code = ERROR_MARK;
+ expr.original_type = NULL;
switch (c_parser_peek_token (parser)->type)
{
case CPP_NUMBER:
+ expr.value = c_parser_peek_token (parser)->value;
+ loc = c_parser_peek_token (parser)->location;
+ c_parser_consume_token (parser);
+ if (TREE_CODE (expr.value) == FIXED_CST
+ && !targetm.fixed_point_supported_p ())
+ {
+ error_at (loc, "fixed-point types not supported for this target");
+ expr.value = error_mark_node;
+ }
+ break;
case CPP_CHAR:
case CPP_CHAR16:
case CPP_CHAR32:
case CPP_WCHAR:
expr.value = c_parser_peek_token (parser)->value;
- expr.original_code = ERROR_MARK;
c_parser_consume_token (parser);
break;
case CPP_STRING:
case CPP_STRING16:
case CPP_STRING32:
case CPP_WSTRING:
+ case CPP_UTF8STRING:
expr.value = c_parser_peek_token (parser)->value;
expr.original_code = STRING_CST;
c_parser_consume_token (parser);
gcc_assert (c_dialect_objc ());
expr.value
= objc_build_string_object (c_parser_peek_token (parser)->value);
- expr.original_code = ERROR_MARK;
c_parser_consume_token (parser);
break;
case CPP_NAME:
{
c_parser_error (parser, "expected expression");
expr.value = error_mark_node;
- expr.original_code = ERROR_MARK;
break;
}
{
tree id = c_parser_peek_token (parser)->value;
- location_t loc = c_parser_peek_token (parser)->location;
c_parser_consume_token (parser);
- expr.value = build_external_ref (id,
+ expr.value = build_external_ref (loc, id,
(c_parser_peek_token (parser)->type
- == CPP_OPEN_PAREN), loc);
- expr.original_code = ERROR_MARK;
+ == CPP_OPEN_PAREN),
+ &expr.original_type);
}
break;
case CPP_OPEN_PAREN:
{
/* A statement expression. */
tree stmt;
- location_t here = c_parser_peek_token (parser)->location;
+ location_t brace_loc;
c_parser_consume_token (parser);
+ brace_loc = c_parser_peek_token (parser)->location;
c_parser_consume_token (parser);
if (cur_stmt_list == NULL)
{
- error ("%Hbraced-group within expression allowed "
- "only inside a function", &here);
+ error_at (loc, "braced-group within expression allowed "
+ "only inside a function");
parser->error = true;
c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
expr.value = error_mark_node;
- expr.original_code = ERROR_MARK;
break;
}
stmt = c_begin_stmt_expr ();
c_parser_compound_statement_nostart (parser);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
"expected %<)%>");
- pedwarn (OPT_pedantic,
- "%HISO C forbids braced-groups within expressions", &here);
- expr.value = c_finish_stmt_expr (stmt);
- expr.original_code = ERROR_MARK;
+ pedwarn (loc, OPT_pedantic,
+ "ISO C forbids braced-groups within expressions");
+ expr.value = c_finish_stmt_expr (brace_loc, stmt);
+ mark_exp_read (expr.value);
}
else if (c_token_starts_typename (c_parser_peek_2nd_token (parser)))
{
than going directly to
c_parser_postfix_expression_after_paren_type from
elsewhere? */
+ location_t loc;
struct c_type_name *type_name;
c_parser_consume_token (parser);
+ loc = c_parser_peek_token (parser)->location;
type_name = c_parser_type_name (parser);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
"expected %<)%>");
if (type_name == NULL)
{
expr.value = error_mark_node;
- expr.original_code = ERROR_MARK;
}
else
expr = c_parser_postfix_expression_after_paren_type (parser,
- type_name);
+ type_name,
+ loc);
}
else
{
expr = c_parser_expression (parser);
if (TREE_CODE (expr.value) == MODIFY_EXPR)
TREE_NO_WARNING (expr.value) = 1;
- expr.original_code = ERROR_MARK;
+ if (expr.original_code != C_MAYBE_CONST_EXPR)
+ expr.original_code = ERROR_MARK;
+ /* Don't change EXPR.ORIGINAL_TYPE. */
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
"expected %<)%>");
}
case RID_FUNCTION_NAME:
case RID_PRETTY_FUNCTION_NAME:
case RID_C99_FUNCTION_NAME:
- expr.value = fname_decl (c_parser_peek_token (parser)->keyword,
+ expr.value = fname_decl (loc,
+ c_parser_peek_token (parser)->keyword,
c_parser_peek_token (parser)->value);
- expr.original_code = ERROR_MARK;
c_parser_consume_token (parser);
break;
case RID_VA_ARG:
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
expr.value = error_mark_node;
- expr.original_code = ERROR_MARK;
break;
}
e1 = c_parser_expr_no_commas (parser, NULL);
+ mark_exp_read (e1.value);
+ e1.value = c_fully_fold (e1.value, false, NULL);
if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
{
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
expr.value = error_mark_node;
- expr.original_code = ERROR_MARK;
break;
}
+ loc = c_parser_peek_token (parser)->location;
t1 = c_parser_type_name (parser);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
"expected %<)%>");
if (t1 == NULL)
{
expr.value = error_mark_node;
- expr.original_code = ERROR_MARK;
}
else
{
- expr.value = build_va_arg (e1.value, groktypename (t1));
- expr.original_code = ERROR_MARK;
+ tree type_expr = NULL_TREE;
+ expr.value = c_build_va_arg (loc, e1.value,
+ groktypename (t1, &type_expr, NULL));
+ if (type_expr)
+ {
+ expr.value = build2 (C_MAYBE_CONST_EXPR,
+ TREE_TYPE (expr.value), type_expr,
+ expr.value);
+ C_MAYBE_CONST_EXPR_NON_CONST (expr.value) = true;
+ }
}
break;
case RID_OFFSETOF:
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
expr.value = error_mark_node;
- expr.original_code = ERROR_MARK;
break;
}
t1 = c_parser_type_name (parser);
if (t1 == NULL)
{
expr.value = error_mark_node;
- expr.original_code = ERROR_MARK;
break;
}
if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
{
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
expr.value = error_mark_node;
- expr.original_code = ERROR_MARK;
break;
}
{
- tree type = groktypename (t1);
+ tree type = groktypename (t1, NULL, NULL);
tree offsetof_ref;
if (type == error_mark_node)
offsetof_ref = error_mark_node;
else
- offsetof_ref = build1 (INDIRECT_REF, type, null_pointer_node);
+ {
+ offsetof_ref = build1 (INDIRECT_REF, type, null_pointer_node);
+ SET_EXPR_LOCATION (offsetof_ref, loc);
+ }
/* 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. */
if (c_parser_next_token_is (parser, CPP_NAME))
{
offsetof_ref = build_component_ref
- (offsetof_ref, c_parser_peek_token (parser)->value);
+ (loc, offsetof_ref, c_parser_peek_token (parser)->value);
c_parser_consume_token (parser);
while (c_parser_next_token_is (parser, CPP_DOT)
|| c_parser_next_token_is (parser,
- CPP_OPEN_SQUARE))
+ CPP_OPEN_SQUARE)
+ || c_parser_next_token_is (parser,
+ CPP_DEREF))
{
- if (c_parser_next_token_is (parser, CPP_DOT))
+ if (c_parser_next_token_is (parser, CPP_DEREF))
+ {
+ loc = c_parser_peek_token (parser)->location;
+ offsetof_ref = build_array_ref (loc,
+ offsetof_ref,
+ integer_zero_node);
+ goto do_dot;
+ }
+ else if (c_parser_next_token_is (parser, CPP_DOT))
{
+ do_dot:
c_parser_consume_token (parser);
if (c_parser_next_token_is_not (parser,
CPP_NAME))
break;
}
offsetof_ref = build_component_ref
- (offsetof_ref,
+ (loc, offsetof_ref,
c_parser_peek_token (parser)->value);
c_parser_consume_token (parser);
}
else
{
tree idx;
+ loc = c_parser_peek_token (parser)->location;
c_parser_consume_token (parser);
idx = c_parser_expression (parser).value;
+ idx = c_fully_fold (idx, false, NULL);
c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
"expected %<]%>");
- offsetof_ref = build_array_ref (offsetof_ref, idx);
+ offsetof_ref = build_array_ref (loc, offsetof_ref, idx);
}
}
}
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
"expected %<)%>");
expr.value = fold_offsetof (offsetof_ref, NULL_TREE);
- expr.original_code = ERROR_MARK;
}
break;
case RID_CHOOSE_EXPR:
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
expr.value = error_mark_node;
- expr.original_code = ERROR_MARK;
break;
}
loc = c_parser_peek_token (parser)->location;
{
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
expr.value = error_mark_node;
- expr.original_code = ERROR_MARK;
break;
}
e2 = c_parser_expr_no_commas (parser, NULL);
{
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
expr.value = error_mark_node;
- expr.original_code = ERROR_MARK;
break;
}
e3 = c_parser_expr_no_commas (parser, NULL);
{
tree c;
- c = fold (e1.value);
- if (TREE_CODE (c) != INTEGER_CST)
- error ("%Hfirst argument to %<__builtin_choose_expr%> not"
- " a constant", &loc);
+ c = e1.value;
+ mark_exp_read (e2.value);
+ mark_exp_read (e3.value);
+ if (TREE_CODE (c) != INTEGER_CST
+ || !INTEGRAL_TYPE_P (TREE_TYPE (c)))
+ error_at (loc,
+ "first argument to %<__builtin_choose_expr%> not"
+ " a constant");
+ constant_expression_warning (c);
expr = integer_zerop (c) ? e3 : e2;
}
break;
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
expr.value = error_mark_node;
- expr.original_code = ERROR_MARK;
break;
}
t1 = c_parser_type_name (parser);
if (t1 == NULL)
{
expr.value = error_mark_node;
- expr.original_code = ERROR_MARK;
break;
}
if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
{
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
expr.value = error_mark_node;
- expr.original_code = ERROR_MARK;
break;
}
t2 = c_parser_type_name (parser);
if (t2 == NULL)
{
expr.value = error_mark_node;
- expr.original_code = ERROR_MARK;
break;
}
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
{
tree e1, e2;
- e1 = TYPE_MAIN_VARIANT (groktypename (t1));
- e2 = TYPE_MAIN_VARIANT (groktypename (t2));
+ e1 = TYPE_MAIN_VARIANT (groktypename (t1, NULL, NULL));
+ e2 = TYPE_MAIN_VARIANT (groktypename (t2, NULL, NULL));
- expr.value = comptypes (e1, e2)
- ? build_int_cst (NULL_TREE, 1)
- : build_int_cst (NULL_TREE, 0);
- expr.original_code = ERROR_MARK;
+ expr.value
+ = comptypes (e1, e2) ? integer_one_node : integer_zero_node;
}
break;
case RID_AT_SELECTOR:
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
expr.value = error_mark_node;
- expr.original_code = ERROR_MARK;
break;
}
{
tree sel = c_parser_objc_selector_arg (parser);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
"expected %<)%>");
- expr.value = objc_build_selector_expr (sel);
- expr.original_code = ERROR_MARK;
+ expr.value = objc_build_selector_expr (loc, sel);
}
break;
case RID_AT_PROTOCOL:
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
expr.value = error_mark_node;
- expr.original_code = ERROR_MARK;
break;
}
if (c_parser_next_token_is_not (parser, CPP_NAME))
c_parser_error (parser, "expected identifier");
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
expr.value = error_mark_node;
- expr.original_code = ERROR_MARK;
break;
}
{
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
"expected %<)%>");
expr.value = objc_build_protocol_expr (id);
- expr.original_code = ERROR_MARK;
}
break;
case RID_AT_ENCODE:
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
expr.value = error_mark_node;
- expr.original_code = ERROR_MARK;
break;
}
t1 = c_parser_type_name (parser);
if (t1 == NULL)
{
expr.value = error_mark_node;
- expr.original_code = ERROR_MARK;
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
break;
}
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
"expected %<)%>");
{
- tree type = groktypename (t1);
+ tree type = groktypename (t1, NULL, NULL);
expr.value = objc_build_encode_expr (type);
- expr.original_code = ERROR_MARK;
}
break;
default:
c_parser_error (parser, "expected expression");
expr.value = error_mark_node;
- expr.original_code = ERROR_MARK;
break;
}
break;
"expected %<]%>");
expr.value = objc_build_message_expr (build_tree_list (receiver,
args));
- expr.original_code = ERROR_MARK;
break;
}
/* Else fall through to report error. */
default:
c_parser_error (parser, "expected expression");
expr.value = error_mark_node;
- expr.original_code = ERROR_MARK;
break;
}
- return c_parser_postfix_expression_after_primary (parser, expr);
+ return c_parser_postfix_expression_after_primary (parser, loc, expr);
}
/* Parse a postfix expression after a parenthesized type name: the
possible to tell until after the type name whether a cast
expression has a cast or a compound literal, or whether the operand
of sizeof is a parenthesized type name or starts with a compound
- literal. */
+ literal. TYPE_LOC is the location where TYPE_NAME starts--the
+ location of the first token after the parentheses around the type
+ name. */
static struct c_expr
c_parser_postfix_expression_after_paren_type (c_parser *parser,
- struct c_type_name *type_name)
+ struct c_type_name *type_name,
+ location_t type_loc)
{
tree type;
struct c_expr init;
+ bool non_const;
struct c_expr expr;
location_t start_loc;
+ tree type_expr = NULL_TREE;
+ bool type_expr_const = true;
+ check_compound_literal_type (type_loc, type_name);
start_init (NULL_TREE, NULL, 0);
- type = groktypename (type_name);
+ type = groktypename (type_name, &type_expr, &type_expr_const);
start_loc = c_parser_peek_token (parser)->location;
if (type != error_mark_node && C_TYPE_VARIABLE_SIZE (type))
{
- error ("%Hcompound literal has variable size", &start_loc);
+ error_at (type_loc, "compound literal has variable size");
type = error_mark_node;
}
init = c_parser_braced_init (parser, type, false);
finish_init ();
maybe_warn_string_init (type, init);
+ if (type != error_mark_node
+ && !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (type))
+ && current_function_decl)
+ {
+ error ("compound literal qualified by address-space qualifier");
+ type = error_mark_node;
+ }
+
if (!flag_isoc99)
- pedwarn (OPT_pedantic, "%HISO C90 forbids compound literals",
- &start_loc);
- expr.value = build_compound_literal (type, init.value);
+ pedwarn (start_loc, OPT_pedantic, "ISO C90 forbids compound literals");
+ non_const = ((init.value && TREE_CODE (init.value) == CONSTRUCTOR)
+ ? CONSTRUCTOR_NON_CONST (init.value)
+ : init.original_code == C_MAYBE_CONST_EXPR);
+ non_const |= !type_expr_const;
+ expr.value = build_compound_literal (start_loc, type, init.value, non_const);
expr.original_code = ERROR_MARK;
- return c_parser_postfix_expression_after_primary (parser, expr);
+ expr.original_type = NULL;
+ if (type_expr)
+ {
+ if (TREE_CODE (expr.value) == C_MAYBE_CONST_EXPR)
+ {
+ gcc_assert (C_MAYBE_CONST_EXPR_PRE (expr.value) == NULL_TREE);
+ C_MAYBE_CONST_EXPR_PRE (expr.value) = type_expr;
+ }
+ else
+ {
+ gcc_assert (!non_const);
+ expr.value = build2 (C_MAYBE_CONST_EXPR, type,
+ type_expr, expr.value);
+ }
+ }
+ return c_parser_postfix_expression_after_primary (parser, start_loc, expr);
}
/* Parse a postfix expression after the initial primary or compound
- literal; that is, parse a series of postfix operators. */
+ literal; that is, parse a series of postfix operators.
+
+ EXPR_LOC is the location of the primary expression. */
static struct c_expr
c_parser_postfix_expression_after_primary (c_parser *parser,
+ location_t expr_loc,
struct c_expr expr)
{
- tree ident, idx, exprlist;
+ struct c_expr orig_expr;
+ tree ident, idx;
+ VEC(tree,gc) *exprlist;
+ VEC(tree,gc) *origtypes;
while (true)
{
+ location_t op_loc = c_parser_peek_token (parser)->location;
switch (c_parser_peek_token (parser)->type)
{
case CPP_OPEN_SQUARE:
idx = c_parser_expression (parser).value;
c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
"expected %<]%>");
- expr.value = build_array_ref (expr.value, idx);
+ expr.value = build_array_ref (op_loc, expr.value, idx);
expr.original_code = ERROR_MARK;
+ expr.original_type = NULL;
break;
case CPP_OPEN_PAREN:
/* Function call. */
c_parser_consume_token (parser);
if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
- exprlist = NULL_TREE;
+ exprlist = NULL;
else
- exprlist = c_parser_expr_list (parser, true);
+ exprlist = c_parser_expr_list (parser, true, false, &origtypes);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
"expected %<)%>");
- expr.value = build_function_call (expr.value, exprlist);
+ orig_expr = expr;
+ mark_exp_read (expr.value);
+ /* FIXME diagnostics: Ideally we want the FUNCNAME, not the
+ "(" after the FUNCNAME, which is what we have now. */
+ expr.value = build_function_call_vec (op_loc, expr.value, exprlist,
+ origtypes);
expr.original_code = ERROR_MARK;
- if (warn_disallowed_functions)
- warn_if_disallowed_function_p (expr.value);
+ if (TREE_CODE (expr.value) == INTEGER_CST
+ && TREE_CODE (orig_expr.value) == FUNCTION_DECL
+ && DECL_BUILT_IN_CLASS (orig_expr.value) == BUILT_IN_NORMAL
+ && DECL_FUNCTION_CODE (orig_expr.value) == BUILT_IN_CONSTANT_P)
+ expr.original_code = C_MAYBE_CONST_EXPR;
+ expr.original_type = NULL;
+ if (exprlist != NULL)
+ {
+ release_tree_vector (exprlist);
+ release_tree_vector (origtypes);
+ }
break;
case CPP_DOT:
/* Structure element reference. */
c_parser_consume_token (parser);
- expr = default_function_array_conversion (expr);
+ expr = default_function_array_conversion (expr_loc, expr);
if (c_parser_next_token_is (parser, CPP_NAME))
ident = c_parser_peek_token (parser)->value;
else
c_parser_error (parser, "expected identifier");
expr.value = error_mark_node;
expr.original_code = ERROR_MARK;
+ expr.original_type = NULL;
return expr;
}
c_parser_consume_token (parser);
- expr.value = build_component_ref (expr.value, ident);
+ expr.value = build_component_ref (op_loc, expr.value, ident);
expr.original_code = ERROR_MARK;
+ if (TREE_CODE (expr.value) != COMPONENT_REF)
+ expr.original_type = NULL;
+ else
+ {
+ /* Remember the original type of a bitfield. */
+ tree field = TREE_OPERAND (expr.value, 1);
+ if (TREE_CODE (field) != FIELD_DECL)
+ expr.original_type = NULL;
+ else
+ expr.original_type = DECL_BIT_FIELD_TYPE (field);
+ }
break;
case CPP_DEREF:
/* Structure element reference. */
c_parser_consume_token (parser);
- expr = default_function_array_conversion (expr);
+ expr = default_function_array_conversion (expr_loc, expr);
if (c_parser_next_token_is (parser, CPP_NAME))
ident = c_parser_peek_token (parser)->value;
else
c_parser_error (parser, "expected identifier");
expr.value = error_mark_node;
expr.original_code = ERROR_MARK;
+ expr.original_type = NULL;
return expr;
}
c_parser_consume_token (parser);
- expr.value = build_component_ref (build_indirect_ref (expr.value,
- "->"), ident);
+ expr.value = build_component_ref (op_loc,
+ build_indirect_ref (op_loc,
+ expr.value,
+ RO_ARROW),
+ ident);
expr.original_code = ERROR_MARK;
+ if (TREE_CODE (expr.value) != COMPONENT_REF)
+ expr.original_type = NULL;
+ else
+ {
+ /* Remember the original type of a bitfield. */
+ tree field = TREE_OPERAND (expr.value, 1);
+ if (TREE_CODE (field) != FIELD_DECL)
+ expr.original_type = NULL;
+ else
+ expr.original_type = DECL_BIT_FIELD_TYPE (field);
+ }
break;
case CPP_PLUS_PLUS:
/* Postincrement. */
c_parser_consume_token (parser);
- expr = default_function_array_conversion (expr);
- expr.value = build_unary_op (POSTINCREMENT_EXPR, expr.value, 0);
+ expr = default_function_array_read_conversion (expr_loc, expr);
+ expr.value = build_unary_op (op_loc,
+ POSTINCREMENT_EXPR, expr.value, 0);
expr.original_code = ERROR_MARK;
+ expr.original_type = NULL;
break;
case CPP_MINUS_MINUS:
/* Postdecrement. */
c_parser_consume_token (parser);
- expr = default_function_array_conversion (expr);
- expr.value = build_unary_op (POSTDECREMENT_EXPR, expr.value, 0);
+ expr = default_function_array_read_conversion (expr_loc, expr);
+ expr.value = build_unary_op (op_loc,
+ POSTDECREMENT_EXPR, expr.value, 0);
expr.original_code = ERROR_MARK;
+ expr.original_type = NULL;
break;
default:
return expr;
while (c_parser_next_token_is (parser, CPP_COMMA))
{
struct c_expr next;
+ tree lhsval;
+ location_t loc = c_parser_peek_token (parser)->location;
+ location_t expr_loc;
c_parser_consume_token (parser);
+ expr_loc = c_parser_peek_token (parser)->location;
+ lhsval = expr.value;
+ while (TREE_CODE (lhsval) == COMPOUND_EXPR)
+ lhsval = TREE_OPERAND (lhsval, 1);
+ if (DECL_P (lhsval) || handled_component_p (lhsval))
+ mark_exp_read (lhsval);
next = c_parser_expr_no_commas (parser, NULL);
- next = default_function_array_conversion (next);
- expr.value = build_compound_expr (expr.value, next.value);
+ next = default_function_array_conversion (expr_loc, next);
+ expr.value = build_compound_expr (loc, expr.value, next.value);
expr.original_code = COMPOUND_EXPR;
+ expr.original_type = next.original_type;
}
return expr;
}
c_parser_expression_conv (c_parser *parser)
{
struct c_expr expr;
+ location_t loc = c_parser_peek_token (parser)->location;
expr = c_parser_expression (parser);
- expr = default_function_array_conversion (expr);
+ expr = default_function_array_conversion (loc, expr);
return expr;
}
/* Parse a non-empty list of expressions. If CONVERT_P, convert
- functions and arrays to pointers.
+ functions and arrays to pointers. If FOLD_P, fold the expressions.
nonempty-expr-list:
assignment-expression
nonempty-expr-list , assignment-expression
*/
-static tree
-c_parser_expr_list (c_parser *parser, bool convert_p)
+static VEC(tree,gc) *
+c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p,
+ VEC(tree,gc) **p_orig_types)
{
+ VEC(tree,gc) *ret;
+ VEC(tree,gc) *orig_types;
struct c_expr expr;
- tree ret, cur;
+ location_t loc = c_parser_peek_token (parser)->location;
+
+ ret = make_tree_vector ();
+ if (p_orig_types == NULL)
+ orig_types = NULL;
+ else
+ orig_types = make_tree_vector ();
+
expr = c_parser_expr_no_commas (parser, NULL);
if (convert_p)
- expr = default_function_array_conversion (expr);
- ret = cur = build_tree_list (NULL_TREE, expr.value);
+ expr = default_function_array_read_conversion (loc, expr);
+ if (fold_p)
+ expr.value = c_fully_fold (expr.value, false, NULL);
+ VEC_quick_push (tree, ret, expr.value);
+ if (orig_types != NULL)
+ VEC_quick_push (tree, orig_types, expr.original_type);
while (c_parser_next_token_is (parser, CPP_COMMA))
{
c_parser_consume_token (parser);
+ loc = c_parser_peek_token (parser)->location;
expr = c_parser_expr_no_commas (parser, NULL);
if (convert_p)
- expr = default_function_array_conversion (expr);
- cur = TREE_CHAIN (cur) = build_tree_list (NULL_TREE, expr.value);
- }
+ expr = default_function_array_read_conversion (loc, expr);
+ if (fold_p)
+ expr.value = c_fully_fold (expr.value, false, NULL);
+ VEC_safe_push (tree, gc, ret, expr.value);
+ if (orig_types != NULL)
+ VEC_safe_push (tree, gc, orig_types, expr.original_type);
+ }
+ if (orig_types != NULL)
+ *p_orig_types = orig_types;
return ret;
}
-
\f
/* Parse Objective-C-specific constructs. */
/* Parse any stray semicolon. */
if (c_parser_next_token_is (parser, CPP_SEMICOLON))
{
- pedwarn (OPT_pedantic,
- "%Hextra semicolon in struct or union specified",
- &c_parser_peek_token (parser)->location);
+ pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic,
+ "extra semicolon in struct or union specified");
c_parser_consume_token (parser);
continue;
}
/* Comma-separated instance variables are chained together in
reverse order; add them one by one. */
tree ivar = nreverse (decls);
- for (; ivar; ivar = TREE_CHAIN (ivar))
+ for (; ivar; ivar = DECL_CHAIN (ivar))
objc_add_instance_variable (copy_node (ivar));
}
c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
if (c_parser_next_token_is (parser, CPP_SEMICOLON))
{
c_parser_consume_token (parser);
- pedwarn (OPT_pedantic,
- "%Hextra semicolon in method definition specified",
- &c_parser_peek_token (parser)->location);
+ pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic,
+ "extra semicolon in method definition specified");
}
if (!c_parser_next_token_is (parser, CPP_OPEN_BRACE))
{
switch (c_parser_peek_token (parser)->type)
{
case CPP_SEMICOLON:
- pedwarn (OPT_pedantic, "%HISO C does not allow extra %<;%> "
- "outside of a function",
- &c_parser_peek_token (parser)->location);
+ pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic,
+ "ISO C does not allow extra %<;%> outside of a function");
c_parser_consume_token (parser);
break;
case CPP_PLUS:
default:
if (c_parser_next_token_is_keyword (parser, RID_AT_END))
return;
- c_parser_declaration_or_fndef (parser, false, true, false, true);
+ c_parser_declaration_or_fndef (parser, false, false, true,
+ false, true);
break;
}
}
if (c_parser_next_token_starts_typename (parser))
type_name = c_parser_type_name (parser);
if (type_name)
- type = groktypename (type_name);
+ type = groktypename (type_name, NULL, NULL);
return build_tree_list (quals, type);
}
if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
expr = c_parser_expression (parser).value;
+ expr = c_fully_fold (expr, false, NULL);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
}
else
case RID_ALIGNOF:
case RID_UNSIGNED:
case RID_LONG:
+ case RID_INT128:
case RID_CONST:
case RID_SHORT:
case RID_VOLATILE:
c_parser_consume_token (parser);
return objc_get_class_reference (id);
}
- return c_parser_expression (parser).value;
+ return c_fully_fold (c_parser_expression (parser).value, false, NULL);
}
/* Parse objc-message-args.
{
tree keywordexpr;
if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
- return list;
+ return error_mark_node;
keywordexpr = c_parser_objc_keywordexpr (parser);
list = chainon (list, build_tree_list (sel, keywordexpr));
sel = c_parser_objc_selector (parser);
static tree
c_parser_objc_keywordexpr (c_parser *parser)
{
- tree list = c_parser_expr_list (parser, true);
- if (TREE_CHAIN (list) == NULL_TREE)
+ tree ret;
+ VEC(tree,gc) *expr_list = c_parser_expr_list (parser, true, true, NULL);
+ if (VEC_length (tree, expr_list) == 1)
{
/* Just return the expression, remove a level of
indirection. */
- return TREE_VALUE (list);
+ ret = VEC_index (tree, expr_list, 0);
}
else
{
/* We have a comma expression, we will collapse later. */
- return list;
+ ret = build_tree_list_vec (expr_list);
}
+ release_tree_vector (expr_list);
+ return ret;
}
\f
return false;
case PRAGMA_OMP_SECTION:
- error ("%H%<#pragma omp section%> may only be used in "
- "%<#pragma omp sections%> construct",
- &c_parser_peek_token (parser)->location);
+ error_at (c_parser_peek_token (parser)->location,
+ "%<#pragma omp section%> may only be used in "
+ "%<#pragma omp sections%> construct");
c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
return false;
c_parser_consume_pragma (parser);
c_invoke_pragma_handler (id);
- /* Skip to EOL, but suppress any error message. Those will have been
+ /* Skip to EOL, but suppress any error message. Those will have been
generated by the handler routine through calling error, as opposed
to calling c_parser_error. */
parser->error = true;
for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
if (OMP_CLAUSE_CODE (c) == code)
{
- error ("too many %qs clauses", name);
+ location_t loc = OMP_CLAUSE_LOCATION (c);
+ error_at (loc, "too many %qs clauses", name);
break;
}
}
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 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 nonzero, CLAUSE_LOC is the location of the clause.
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,
+c_parser_omp_variable_list (c_parser *parser,
+ location_t clause_loc,
+ enum omp_clause_code kind,
tree list)
{
if (c_parser_next_token_is_not (parser, CPP_NAME)
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);
+ undeclared_variable (c_parser_peek_token (parser)->location,
+ c_parser_peek_token (parser)->value);
else if (t == error_mark_node)
;
else if (kind != 0)
{
- tree u = build_omp_clause (kind);
+ tree u = build_omp_clause (clause_loc, kind);
OMP_CLAUSE_DECL (u) = t;
OMP_CLAUSE_CHAIN (u) = list;
list = u;
c_parser_omp_var_list_parens (c_parser *parser, enum omp_clause_code kind,
tree list)
{
+ /* The clauses location. */
+ location_t loc = c_parser_peek_token (parser)->location;
+
if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
- list = c_parser_omp_variable_list (parser, kind, list);
+ list = c_parser_omp_variable_list (parser, loc, kind, list);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
}
return list;
|| (n = tree_low_cst (num, 0)) <= 0
|| (int) n != n)
{
- error ("%Hcollapse argument needs positive constant integer expression",
- &loc);
+ error_at (loc,
+ "collapse argument needs positive constant integer expression");
return list;
}
- c = build_omp_clause (OMP_CLAUSE_COLLAPSE);
+ c = build_omp_clause (loc, OMP_CLAUSE_COLLAPSE);
OMP_CLAUSE_COLLAPSE_EXPR (c) = num;
OMP_CLAUSE_CHAIN (c) = list;
return c;
c_parser_omp_clause_default (c_parser *parser, tree list)
{
enum omp_clause_default_kind kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED;
+ location_t loc = c_parser_peek_token (parser)->location;
tree c;
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
return list;
check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULT, "default");
- c = build_omp_clause (OMP_CLAUSE_DEFAULT);
+ c = build_omp_clause (loc, OMP_CLAUSE_DEFAULT);
OMP_CLAUSE_CHAIN (c) = list;
OMP_CLAUSE_DEFAULT_KIND (c) = kind;
static tree
c_parser_omp_clause_if (c_parser *parser, tree list)
{
+ location_t loc = c_parser_peek_token (parser)->location;
if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
{
tree t = c_parser_paren_condition (parser);
check_no_duplicate_clause (list, OMP_CLAUSE_IF, "if");
- c = build_omp_clause (OMP_CLAUSE_IF);
+ c = build_omp_clause (loc, OMP_CLAUSE_IF);
OMP_CLAUSE_IF_EXPR (c) = t;
OMP_CLAUSE_CHAIN (c) = list;
list = c;
c_parser_omp_clause_nowait (c_parser *parser ATTRIBUTE_UNUSED, tree list)
{
tree c;
+ location_t loc = c_parser_peek_token (parser)->location;
check_no_duplicate_clause (list, OMP_CLAUSE_NOWAIT, "nowait");
- c = build_omp_clause (OMP_CLAUSE_NOWAIT);
+ c = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
OMP_CLAUSE_CHAIN (c) = list;
return c;
}
static tree
c_parser_omp_clause_num_threads (c_parser *parser, tree list)
{
+ location_t num_threads_loc = c_parser_peek_token (parser)->location;
if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
location_t expr_loc = c_parser_peek_token (parser)->location;
tree c, t = c_parser_expression (parser).value;
+ t = c_fully_fold (t, false, NULL);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
}
/* Attempt to statically determine when the number isn't positive. */
- c = fold_build2 (LE_EXPR, boolean_type_node, t,
+ c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
build_int_cst (TREE_TYPE (t), 0));
+ if (CAN_HAVE_LOCATION_P (c))
+ SET_EXPR_LOCATION (c, expr_loc);
if (c == boolean_true_node)
{
- warning (0, "%H%<num_threads%> value must be positive", &expr_loc);
+ warning_at (expr_loc, 0,
+ "%<num_threads%> 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);
+ c = build_omp_clause (num_threads_loc, OMP_CLAUSE_NUM_THREADS);
OMP_CLAUSE_NUM_THREADS_EXPR (c) = t;
OMP_CLAUSE_CHAIN (c) = list;
list = c;
ordered */
static tree
-c_parser_omp_clause_ordered (c_parser *parser ATTRIBUTE_UNUSED, tree list)
+c_parser_omp_clause_ordered (c_parser *parser, tree list)
{
tree c;
check_no_duplicate_clause (list, OMP_CLAUSE_ORDERED, "ordered");
- c = build_omp_clause (OMP_CLAUSE_ORDERED);
+ c = build_omp_clause (c_parser_peek_token (parser)->location,
+ OMP_CLAUSE_ORDERED);
OMP_CLAUSE_CHAIN (c) = list;
+
return c;
}
static tree
c_parser_omp_clause_reduction (c_parser *parser, tree list)
{
+ location_t clause_loc = c_parser_peek_token (parser)->location;
if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
enum tree_code code;
{
tree nl, c;
- nl = c_parser_omp_variable_list (parser, OMP_CLAUSE_REDUCTION, list);
+ nl = c_parser_omp_variable_list (parser, clause_loc,
+ OMP_CLAUSE_REDUCTION, list);
for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
OMP_CLAUSE_REDUCTION_CODE (c) = code;
c_parser_omp_clause_schedule (c_parser *parser, tree list)
{
tree c, t;
+ location_t loc = c_parser_peek_token (parser)->location;
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
return list;
- c = build_omp_clause (OMP_CLAUSE_SCHEDULE);
+ c = build_omp_clause (loc, OMP_CLAUSE_SCHEDULE);
if (c_parser_next_token_is (parser, CPP_NAME))
{
here = c_parser_peek_token (parser)->location;
t = c_parser_expr_no_commas (parser, NULL).value;
+ t = c_fully_fold (t, false, NULL);
if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME)
- error ("%Hschedule %<runtime%> does not take "
- "a %<chunk_size%> parameter", &here);
+ error_at (here, "schedule %<runtime%> does not take "
+ "a %<chunk_size%> parameter");
else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_AUTO)
- error ("%Hschedule %<auto%> does not take "
- "a %<chunk_size%> parameter", &here);
+ error_at (here,
+ "schedule %<auto%> does not take "
+ "a %<chunk_size%> parameter");
else if (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE)
OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
else
/* FIXME: Should we allow duplicates? */
check_no_duplicate_clause (list, OMP_CLAUSE_UNTIED, "untied");
- c = build_omp_clause (OMP_CLAUSE_UNTIED);
+ c = build_omp_clause (c_parser_peek_token (parser)->location,
+ OMP_CLAUSE_UNTIED);
OMP_CLAUSE_CHAIN (c) = list;
+
return c;
}
/* Remove the invalid clause(s) from the list to avoid
confusing the rest of the compiler. */
clauses = prev;
- error ("%H%qs is not valid for %qs", &here, c_name, where);
+ error_at (here, "%qs is not valid for %qs", c_name, where);
}
}
binop:
+, *, -, /, &, ^, |, <<, >>
- where x is an lvalue expression with scalar type. */
+ where x is an lvalue expression with scalar type.
+
+ LOC is the location of the #pragma token. */
static void
-c_parser_omp_atomic (c_parser *parser)
+c_parser_omp_atomic (location_t loc, c_parser *parser)
{
tree lhs, rhs;
tree stmt;
c_parser_skip_to_pragma_eol (parser);
lhs = c_parser_unary_expression (parser).value;
+ lhs = c_fully_fold (lhs, false, NULL);
switch (TREE_CODE (lhs))
{
case ERROR_MARK:
}
c_parser_consume_token (parser);
- rhs_expr = c_parser_expression (parser);
- rhs_expr = default_function_array_conversion (rhs_expr);
+ {
+ location_t rhs_loc = c_parser_peek_token (parser)->location;
+ rhs_expr = c_parser_expression (parser);
+ rhs_expr = default_function_array_read_conversion (rhs_loc, rhs_expr);
+ }
rhs = rhs_expr.value;
+ rhs = c_fully_fold (rhs, false, NULL);
break;
}
- stmt = c_finish_omp_atomic (code, lhs, rhs);
+ stmt = c_finish_omp_atomic (loc, code, lhs, rhs);
if (stmt != error_mark_node)
add_stmt (stmt);
c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
static void
c_parser_omp_barrier (c_parser *parser)
{
+ location_t loc = c_parser_peek_token (parser)->location;
c_parser_consume_pragma (parser);
c_parser_skip_to_pragma_eol (parser);
- c_finish_omp_barrier ();
+ c_finish_omp_barrier (loc);
}
/* OpenMP 2.5:
# pragma omp critical [(name)] new-line
structured-block
-*/
+
+ LOC is the location of the #pragma itself. */
static tree
-c_parser_omp_critical (c_parser *parser)
+c_parser_omp_critical (location_t loc, c_parser *parser)
{
tree stmt, name = NULL;
c_parser_skip_to_pragma_eol (parser);
stmt = c_parser_omp_structured_block (parser);
- return c_finish_omp_critical (stmt, name);
+ return c_finish_omp_critical (loc, stmt, name);
}
/* OpenMP 2.5:
static void
c_parser_omp_flush (c_parser *parser)
{
+ location_t loc = c_parser_peek_token (parser)->location;
c_parser_consume_pragma (parser);
if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL);
c_parser_error (parser, "expected %<(%> or end of line");
c_parser_skip_to_pragma_eol (parser);
- c_finish_omp_flush ();
+ c_finish_omp_flush (loc);
}
/* Parse the restricted form of the for statement 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. */
+ so that we can push a new decl if necessary to make it private.
+ LOC is the location of the OMP in "#pragma omp". */
static tree
-c_parser_omp_for_loop (c_parser *parser, tree clauses, tree *par_clauses)
+c_parser_omp_for_loop (location_t loc,
+ c_parser *parser, tree clauses, tree *par_clauses)
{
tree decl, cond, incr, save_break, save_cont, body, init, stmt, cl;
- tree declv, condv, incrv, initv, for_block = NULL, ret = NULL;
- location_t loc;
+ tree declv, condv, incrv, initv, ret = NULL;
bool fail = false, open_brace_parsed = false;
int i, collapse = 1, nbraces = 0;
+ location_t for_loc;
+ VEC(tree,gc) *for_block = make_tree_vector ();
for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl))
if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_COLLAPSE)
c_parser_error (parser, "for statement expected");
return NULL;
}
- loc = c_parser_peek_token (parser)->location;
+ for_loc = c_parser_peek_token (parser)->location;
c_parser_consume_token (parser);
for (i = 0; i < collapse; i++)
goto pop_scopes;
/* Parse the initialization declaration or expression. */
- if (c_parser_next_token_starts_declspecs (parser))
+ if (c_parser_next_token_starts_declaration (parser))
{
if (i > 0)
- for_block
- = tree_cons (NULL, c_begin_compound_stmt (true), for_block);
- c_parser_declaration_or_fndef (parser, true, true, true, true);
- decl = check_for_loop_decls ();
+ VEC_safe_push (tree, gc, for_block, c_begin_compound_stmt (true));
+ c_parser_declaration_or_fndef (parser, true, true, true, true, true);
+ decl = check_for_loop_decls (for_loc);
if (decl == NULL)
goto error_init;
if (DECL_INITIAL (decl) == error_mark_node)
else if (c_parser_next_token_is (parser, CPP_NAME)
&& c_parser_peek_2nd_token (parser)->type == CPP_EQ)
{
+ struct c_expr decl_exp;
struct c_expr init_exp;
+ location_t init_loc;
- decl = c_parser_postfix_expression (parser).value;
+ decl_exp = c_parser_postfix_expression (parser);
+ decl = decl_exp.value;
c_parser_require (parser, CPP_EQ, "expected %<=%>");
+ init_loc = c_parser_peek_token (parser)->location;
init_exp = c_parser_expr_no_commas (parser, NULL);
- init_exp = default_function_array_conversion (init_exp);
- init = build_modify_expr (decl, NOP_EXPR, init_exp.value);
- init = c_process_expr_stmt (init);
+ init_exp = default_function_array_read_conversion (init_loc,
+ init_exp);
+ init = build_modify_expr (init_loc, decl, decl_exp.original_type,
+ NOP_EXPR, init_loc, init_exp.value,
+ init_exp.original_type);
+ init = c_process_expr_stmt (init_loc, init);
c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
}
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);
+ location_t cond_loc = c_parser_peek_token (parser)->location;
+ struct c_expr cond_expr = c_parser_binary_expression (parser, NULL);
+
+ cond = cond_expr.value;
+ cond = c_objc_common_truthvalue_conversion (cond_loc, cond);
+ cond = c_fully_fold (cond, false, NULL);
+ switch (cond_expr.original_code)
+ {
+ case GT_EXPR:
+ case GE_EXPR:
+ case LT_EXPR:
+ case LE_EXPR:
+ break;
+ default:
+ /* Can't be cond = error_mark_node, because we want to preserve
+ the location until c_finish_omp_for. */
+ cond = build1 (NOP_EXPR, boolean_type_node, error_mark_node);
+ break;
+ }
+ protected_set_expr_location (cond, cond_loc);
}
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);
+ {
+ location_t incr_loc = c_parser_peek_token (parser)->location;
+
+ incr = c_process_expr_stmt (incr_loc,
+ c_parser_expression (parser).value);
+ }
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
if (decl == NULL || decl == error_mark_node || init == error_mark_node)
if (open_brace_parsed)
{
+ location_t here = c_parser_peek_token (parser)->location;
stmt = c_begin_compound_stmt (true);
c_parser_compound_statement_nostart (parser);
- add_stmt (c_end_compound_stmt (stmt, true));
+ add_stmt (c_end_compound_stmt (here, stmt, true));
}
else
add_stmt (c_parser_c99_block_statement (parser));
if (c_cont_label)
- add_stmt (build1 (LABEL_EXPR, void_type_node, c_cont_label));
+ {
+ tree t = build1 (LABEL_EXPR, void_type_node, c_cont_label);
+ SET_EXPR_LOCATION (t, loc);
+ add_stmt (t);
+ }
body = pop_stmt_list (body);
c_break_label = save_break;
c_parser_error (parser, "collapsed loops not perfectly nested");
while (nbraces)
{
+ location_t here = c_parser_peek_token (parser)->location;
stmt = c_begin_compound_stmt (true);
add_stmt (body);
c_parser_compound_statement_nostart (parser);
- body = c_end_compound_stmt (stmt, true);
+ body = c_end_compound_stmt (here, stmt, true);
nbraces--;
}
goto pop_scopes;
c = &OMP_CLAUSE_CHAIN (*c);
else if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_FIRSTPRIVATE)
{
- error ("%Hiteration variable %qD should not be firstprivate",
- &loc, OMP_CLAUSE_DECL (*c));
+ error_at (loc,
+ "iteration variable %qD should not be firstprivate",
+ OMP_CLAUSE_DECL (*c));
*c = OMP_CLAUSE_CHAIN (*c);
}
else
/* Copy lastprivate (decl) clause to OMP_FOR_CLAUSES,
change it to shared (decl) in
OMP_PARALLEL_CLAUSES. */
- tree l = build_omp_clause (OMP_CLAUSE_LASTPRIVATE);
+ tree l = build_omp_clause (OMP_CLAUSE_LOCATION (*c),
+ OMP_CLAUSE_LASTPRIVATE);
OMP_CLAUSE_DECL (l) = OMP_CLAUSE_DECL (*c);
OMP_CLAUSE_CHAIN (l) = clauses;
clauses = l;
ret = stmt;
}
pop_scopes:
- while (for_block)
+ while (!VEC_empty (tree, for_block))
{
- stmt = c_end_compound_stmt (TREE_VALUE (for_block), true);
+ /* FIXME diagnostics: LOC below should be the actual location of
+ this particular for block. We need to build a list of
+ locations to go along with FOR_BLOCK. */
+ stmt = c_end_compound_stmt (loc, VEC_pop (tree, for_block), true);
add_stmt (stmt);
- for_block = TREE_CHAIN (for_block);
}
+ release_tree_vector (for_block);
return ret;
}
/* OpenMP 2.5:
#pragma omp for for-clause[optseq] new-line
for-loop
+
+ LOC is the location of the #pragma token.
*/
#define OMP_FOR_CLAUSE_MASK \
| (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
static tree
-c_parser_omp_for (c_parser *parser)
+c_parser_omp_for (location_t loc, c_parser *parser)
{
tree block, clauses, ret;
"#pragma omp for");
block = c_begin_compound_stmt (true);
- ret = c_parser_omp_for_loop (parser, clauses, NULL);
- block = c_end_compound_stmt (block, true);
+ ret = c_parser_omp_for_loop (loc, parser, clauses, NULL);
+ block = c_end_compound_stmt (loc, block, true);
add_stmt (block);
return ret;
/* OpenMP 2.5:
# pragma omp master new-line
structured-block
+
+ LOC is the location of the #pragma token.
*/
static tree
-c_parser_omp_master (c_parser *parser)
+c_parser_omp_master (location_t loc, c_parser *parser)
{
c_parser_skip_to_pragma_eol (parser);
- return c_finish_omp_master (c_parser_omp_structured_block (parser));
+ return c_finish_omp_master (loc, c_parser_omp_structured_block (parser));
}
/* OpenMP 2.5:
# pragma omp ordered new-line
structured-block
+
+ LOC is the location of the #pragma itself.
*/
static tree
-c_parser_omp_ordered (c_parser *parser)
+c_parser_omp_ordered (location_t loc, c_parser *parser)
{
c_parser_skip_to_pragma_eol (parser);
- return c_finish_omp_ordered (c_parser_omp_structured_block (parser));
+ return c_finish_omp_ordered (loc, c_parser_omp_structured_block (parser));
}
/* OpenMP 2.5:
section-sequence:
section-directive[opt] structured-block
- section-sequence section-directive structured-block */
+ section-sequence section-directive structured-block
+
+ SECTIONS_LOC is the location of the #pragma omp sections. */
static tree
-c_parser_omp_sections_scope (c_parser *parser)
+c_parser_omp_sections_scope (location_t sections_loc, c_parser *parser)
{
tree stmt, substmt;
bool error_suppress = false;
location_t loc;
+ loc = c_parser_peek_token (parser)->location;
if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
{
/* Avoid skipping until the end of the block. */
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 ();
}
else if (!error_suppress)
{
- error ("%Hexpected %<#pragma omp section%> or %<}%>",
- &loc);
+ error_at (loc, "expected %<#pragma omp section%> or %<}%>");
error_suppress = true;
}
substmt = pop_stmt_list (stmt);
stmt = make_node (OMP_SECTIONS);
+ SET_EXPR_LOCATION (stmt, sections_loc);
TREE_TYPE (stmt) = void_type_node;
OMP_SECTIONS_BODY (stmt) = substmt;
/* OpenMP 2.5:
# pragma omp sections sections-clause[optseq] newline
sections-scope
+
+ LOC is the location of the #pragma token.
*/
#define OMP_SECTIONS_CLAUSE_MASK \
| (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
static tree
-c_parser_omp_sections (c_parser *parser)
+c_parser_omp_sections (location_t loc, c_parser *parser)
{
tree block, clauses, ret;
"#pragma omp sections");
block = c_begin_compound_stmt (true);
- ret = c_parser_omp_sections_scope (parser);
+ ret = c_parser_omp_sections_scope (loc, parser);
if (ret)
OMP_SECTIONS_CLAUSES (ret) = clauses;
- block = c_end_compound_stmt (block, true);
+ block = c_end_compound_stmt (loc, block, true);
add_stmt (block);
return ret;
# pragma parallel parallel-clause new-line
# pragma parallel for parallel-for-clause new-line
# pragma parallel sections parallel-sections-clause new-line
+
+ LOC is the location of the #pragma token.
*/
#define OMP_PARALLEL_CLAUSE_MASK \
| (1u << PRAGMA_OMP_CLAUSE_NUM_THREADS))
static tree
-c_parser_omp_parallel (c_parser *parser)
+c_parser_omp_parallel (location_t loc, c_parser *parser)
{
enum pragma_kind p_kind = PRAGMA_OMP_PARALLEL;
const char *p_name = "#pragma omp parallel";
case PRAGMA_OMP_PARALLEL:
block = c_begin_omp_parallel ();
c_parser_statement (parser);
- stmt = c_finish_omp_parallel (clauses, block);
+ stmt = c_finish_omp_parallel (loc, clauses, block);
break;
case PRAGMA_OMP_PARALLEL_FOR:
block = c_begin_omp_parallel ();
- c_split_parallel_clauses (clauses, &par_clause, &ws_clause);
- c_parser_omp_for_loop (parser, ws_clause, &par_clause);
- stmt = c_finish_omp_parallel (par_clause, block);
+ c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause);
+ c_parser_omp_for_loop (loc, parser, ws_clause, &par_clause);
+ stmt = c_finish_omp_parallel (loc, 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);
+ c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause);
+ stmt = c_parser_omp_sections_scope (loc, parser);
if (stmt)
OMP_SECTIONS_CLAUSES (stmt) = ws_clause;
- stmt = c_finish_omp_parallel (par_clause, block);
+ stmt = c_finish_omp_parallel (loc, par_clause, block);
OMP_PARALLEL_COMBINED (stmt) = 1;
break;
/* OpenMP 2.5:
# pragma omp single single-clause[optseq] new-line
structured-block
+
+ LOC is the location of the #pragma.
*/
#define OMP_SINGLE_CLAUSE_MASK \
| (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
static tree
-c_parser_omp_single (c_parser *parser)
+c_parser_omp_single (location_t loc, c_parser *parser)
{
tree stmt = make_node (OMP_SINGLE);
+ SET_EXPR_LOCATION (stmt, loc);
TREE_TYPE (stmt) = void_type_node;
OMP_SINGLE_CLAUSES (stmt)
/* OpenMP 3.0:
# pragma omp task task-clause[optseq] new-line
+
+ LOC is the location of the #pragma.
*/
#define OMP_TASK_CLAUSE_MASK \
| (1u << PRAGMA_OMP_CLAUSE_SHARED))
static tree
-c_parser_omp_task (c_parser *parser)
+c_parser_omp_task (location_t loc, c_parser *parser)
{
tree clauses, block;
block = c_begin_omp_task ();
c_parser_statement (parser);
- return c_finish_omp_task (clauses, block);
+ return c_finish_omp_task (loc, clauses, block);
}
/* OpenMP 3.0:
static void
c_parser_omp_taskwait (c_parser *parser)
{
+ location_t loc = c_parser_peek_token (parser)->location;
c_parser_consume_pragma (parser);
c_parser_skip_to_pragma_eol (parser);
- c_finish_omp_taskwait ();
+ c_finish_omp_taskwait (loc);
}
/* Main entry point to parsing most OpenMP pragmas. */
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);
+ c_parser_omp_atomic (loc, parser);
return;
case PRAGMA_OMP_CRITICAL:
- stmt = c_parser_omp_critical (parser);
+ stmt = c_parser_omp_critical (loc, parser);
break;
case PRAGMA_OMP_FOR:
- stmt = c_parser_omp_for (parser);
+ stmt = c_parser_omp_for (loc, parser);
break;
case PRAGMA_OMP_MASTER:
- stmt = c_parser_omp_master (parser);
+ stmt = c_parser_omp_master (loc, parser);
break;
case PRAGMA_OMP_ORDERED:
- stmt = c_parser_omp_ordered (parser);
+ stmt = c_parser_omp_ordered (loc, parser);
break;
case PRAGMA_OMP_PARALLEL:
- stmt = c_parser_omp_parallel (parser);
+ stmt = c_parser_omp_parallel (loc, parser);
break;
case PRAGMA_OMP_SECTIONS:
- stmt = c_parser_omp_sections (parser);
+ stmt = c_parser_omp_sections (loc, parser);
break;
case PRAGMA_OMP_SINGLE:
- stmt = c_parser_omp_single (parser);
+ stmt = c_parser_omp_single (loc, parser);
break;
case PRAGMA_OMP_TASK:
- stmt = c_parser_omp_task (parser);
+ stmt = c_parser_omp_task (loc, parser);
break;
default:
gcc_unreachable ();
}
if (stmt)
- SET_EXPR_LOCATION (stmt, loc);
+ gcc_assert (EXPR_LOCATION (stmt) != UNKNOWN_LOCATION);
}
c_parser_omp_threadprivate (c_parser *parser)
{
tree vars, t;
+ location_t loc;
c_parser_consume_pragma (parser);
+ loc = c_parser_peek_token (parser)->location;
vars = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL);
/* Mark every variable in VARS to be assigned thread local storage. */
{
tree v = TREE_PURPOSE (t);
+ /* FIXME diagnostics: Ideally we should keep individual
+ locations for all the variables in the var list to make the
+ following errors more precise. Perhaps
+ c_parser_omp_var_list_parens() should construct a list of
+ locations to go along with the var list. */
+
/* If V had already been marked threadprivate, it doesn't matter
whether it had been used prior to this point. */
if (TREE_CODE (v) != VAR_DECL)
- error ("%qD is not a variable", v);
+ error_at (loc, "%qD is not a variable", v);
else if (TREE_USED (v) && !C_DECL_THREADPRIVATE_P (v))
- error ("%qE declared %<threadprivate%> after first use", v);
+ error_at (loc, "%qE declared %<threadprivate%> after first use", v);
else if (! TREE_STATIC (v) && ! DECL_EXTERNAL (v))
- error ("automatic variable %qE cannot be %<threadprivate%>", v);
+ error_at (loc, "automatic variable %qE cannot be %<threadprivate%>", v);
else if (TREE_TYPE (v) == error_mark_node)
;
else if (! COMPLETE_TYPE_P (TREE_TYPE (v)))
- error ("%<threadprivate%> %qE has incomplete type", v);
+ error_at (loc, "%<threadprivate%> %qE has incomplete type", v);
else
{
if (! DECL_THREAD_LOCAL_P (v))
if (c_parser_peek_token (&tparser)->pragma_kind == PRAGMA_GCC_PCH_PREPROCESS)
c_parser_pragma_pch_preprocess (&tparser);
- the_parser = GGC_NEW (c_parser);
+ the_parser = ggc_alloc_c_parser ();
*the_parser = tparser;
+ /* Initialize EH, if we've been told to do so. */
+ if (flag_exceptions)
+ using_eh_for_cleanups ();
+
c_parser_translation_unit (the_parser);
the_parser = NULL;
}