summaryrefslogtreecommitdiff
path: root/gcc/c/c-parser.c
diff options
context:
space:
mode:
authorjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>2013-11-13 00:38:49 +0000
committerjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>2013-11-13 00:38:49 +0000
commit4fba5eb95587cdfbbc183874bdc5b044f10b713c (patch)
treee843a9dc913b73d2b8924f2993e8aaeee0c8be4f /gcc/c/c-parser.c
parentded3d3f8abc23c9641c8a975da35e16b26ce432a (diff)
downloadgcc-4fba5eb95587cdfbbc183874bdc5b044f10b713c.tar.gz
* doc/extend.texi (Statement Exprs, Typeof): Discuss __auto_type.
* ginclude/stdatomic.h (kill_dependency, atomic_store_explicit) (atomic_load_explicit, atomic_exchange_explicit) (atomic_compare_exchange_strong_explicit) (atomic_compare_exchange_weak_explicit): Use __auto_type to declare variable initialized with PTR argument. c-family: * c-common.h (enum rid): Add RID_AUTO_TYPE. * c-common.c (c_common_reswords): Add __auto_type. (keyword_begins_type_specifier): Handle RID_AUTO_TYPE. c: * c-tree.h (c_typespec_keyword): Add cts_auto_type. * c-decl.c (declspecs_add_type, finish_declspecs): Handle __auto_type. * c-parser.c (c_token_starts_typename, c_token_starts_declspecs) (c_parser_attribute_any_word, c_parser_objc_selector): Handle RID_AUTO_TYPE. (c_parser_declspecs): Take argument AUTO_TYPE_OK. (c_parser_declaration_or_fndef, c_parser_struct_declaration) (c_parser_declarator, c_parser_direct_declarator_inner) (c_parser_parameter_declaration, c_parser_type_name): All callers changed. (c_parser_declaration_or_fndef): Handle declarations with type determined from the initializer. testsuite: * gcc.dg/atomic/stdatomic-vm.c, gcc.dg/auto-type-1.c, gcc.dg/auto-type-2.c: New tests. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@204731 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/c/c-parser.c')
-rw-r--r--gcc/c/c-parser.c147
1 files changed, 122 insertions, 25 deletions
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 5b4665a2a8d..ffbf3c41f93 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -501,6 +501,7 @@ c_token_starts_typename (c_token *token)
case RID_FRACT:
case RID_ACCUM:
case RID_SAT:
+ case RID_AUTO_TYPE:
return true;
default:
return false;
@@ -659,6 +660,7 @@ c_token_starts_declspecs (c_token *token)
case RID_SAT:
case RID_ALIGNAS:
case RID_ATOMIC:
+ case RID_AUTO_TYPE:
return true;
default:
return false;
@@ -1128,7 +1130,7 @@ static void c_parser_declaration_or_fndef (c_parser *, 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, bool, enum c_lookahead_kind);
+ bool, bool, bool, enum c_lookahead_kind);
static struct c_typespec c_parser_enum_specifier (c_parser *);
static struct c_typespec c_parser_struct_or_union_specifier (c_parser *);
static tree c_parser_struct_declaration (c_parser *);
@@ -1499,7 +1501,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
}
c_parser_declspecs (parser, specs, true, true, start_attr_ok,
- true, cla_nonabstract_decl);
+ true, true, cla_nonabstract_decl);
if (parser->error)
{
c_parser_skip_to_end_of_block_or_statement (parser);
@@ -1512,9 +1514,12 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
return;
}
finish_declspecs (specs);
+ bool auto_type_p = specs->typespec_word == cts_auto_type;
if (c_parser_next_token_is (parser, CPP_SEMICOLON))
{
- if (empty_ok)
+ if (auto_type_p)
+ error_at (here, "%<__auto_type%> in empty declaration");
+ else if (empty_ok)
shadow_tag (specs);
else
{
@@ -1537,7 +1542,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
shadow_tag_warned (specs, 1);
return;
}
- else if (c_dialect_objc ())
+ else if (c_dialect_objc () && !auto_type_p)
{
/* Prefix attributes are an error on method decls. */
switch (c_parser_peek_token (parser)->type)
@@ -1640,6 +1645,14 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
c_parser_skip_to_end_of_block_or_statement (parser);
return;
}
+ if (auto_type_p && declarator->kind != cdk_id)
+ {
+ error_at (here,
+ "%<__auto_type%> requires a plain identifier"
+ " as declarator");
+ c_parser_skip_to_end_of_block_or_statement (parser);
+ return;
+ }
if (c_parser_next_token_is (parser, CPP_EQ)
|| c_parser_next_token_is (parser, CPP_COMMA)
|| c_parser_next_token_is (parser, CPP_SEMICOLON)
@@ -1667,19 +1680,72 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
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. */
- d = start_decl (declarator, specs, true,
- chainon (postfix_attrs, all_prefix_attrs));
- if (!d)
- d = error_mark_node;
- if (omp_declare_simd_clauses.exists ())
- c_finish_omp_declare_simd (parser, d, NULL_TREE,
- omp_declare_simd_clauses);
- start_init (d, asm_name, global_bindings_p ());
- init_loc = c_parser_peek_token (parser)->location;
- init = c_parser_initializer (parser);
- finish_init ();
+ if (auto_type_p)
+ {
+ start_init (NULL_TREE, asm_name, global_bindings_p ());
+ init_loc = c_parser_peek_token (parser)->location;
+ init = c_parser_expr_no_commas (parser, NULL);
+ if (TREE_CODE (init.value) == COMPONENT_REF
+ && DECL_C_BIT_FIELD (TREE_OPERAND (init.value, 1)))
+ error_at (here,
+ "%<__auto_type%> used with a bit-field"
+ " initializer");
+ init = convert_lvalue_to_rvalue (init_loc, init, true, true);
+ tree init_type = TREE_TYPE (init.value);
+ /* As with typeof, remove _Atomic and const
+ qualifiers from atomic types. */
+ if (init_type != error_mark_node && TYPE_ATOMIC (init_type))
+ init_type
+ = c_build_qualified_type (init_type,
+ (TYPE_QUALS (init_type)
+ & ~(TYPE_QUAL_ATOMIC
+ | TYPE_QUAL_CONST)));
+ bool vm_type = variably_modified_type_p (init_type,
+ NULL_TREE);
+ if (vm_type)
+ init.value = c_save_expr (init.value);
+ finish_init ();
+ specs->typespec_kind = ctsk_typeof;
+ specs->locations[cdw_typedef] = init_loc;
+ specs->typedef_p = true;
+ specs->type = init_type;
+ if (vm_type)
+ {
+ bool maybe_const = true;
+ tree type_expr = c_fully_fold (init.value, false,
+ &maybe_const);
+ specs->expr_const_operands &= maybe_const;
+ if (specs->expr)
+ specs->expr = build2 (COMPOUND_EXPR,
+ TREE_TYPE (type_expr),
+ specs->expr, type_expr);
+ else
+ specs->expr = type_expr;
+ }
+ d = start_decl (declarator, specs, true,
+ chainon (postfix_attrs, all_prefix_attrs));
+ if (!d)
+ d = error_mark_node;
+ if (omp_declare_simd_clauses.exists ())
+ c_finish_omp_declare_simd (parser, d, NULL_TREE,
+ omp_declare_simd_clauses);
+ }
+ else
+ {
+ /* The declaration of the variable is in effect while
+ its initializer is parsed. */
+ d = start_decl (declarator, specs, true,
+ chainon (postfix_attrs, all_prefix_attrs));
+ if (!d)
+ d = error_mark_node;
+ if (omp_declare_simd_clauses.exists ())
+ c_finish_omp_declare_simd (parser, d, NULL_TREE,
+ omp_declare_simd_clauses);
+ 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);
@@ -1689,6 +1755,14 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
}
else
{
+ if (auto_type_p)
+ {
+ error_at (here,
+ "%<__auto_type%> requires an initialized "
+ "data declaration");
+ c_parser_skip_to_end_of_block_or_statement (parser);
+ return;
+ }
tree d = start_decl (declarator, specs, false,
chainon (postfix_attrs,
all_prefix_attrs));
@@ -1728,6 +1802,14 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
}
if (c_parser_next_token_is (parser, CPP_COMMA))
{
+ if (auto_type_p)
+ {
+ error_at (here,
+ "%<__auto_type%> may only be used with"
+ " a single declarator");
+ c_parser_skip_to_end_of_block_or_statement (parser);
+ return;
+ }
c_parser_consume_token (parser);
if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
all_prefix_attrs = chainon (c_parser_attributes (parser),
@@ -1757,6 +1839,13 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
return;
}
}
+ else if (auto_type_p)
+ {
+ error_at (here,
+ "%<__auto_type%> requires an initialized data declaration");
+ c_parser_skip_to_end_of_block_or_statement (parser);
+ return;
+ }
else if (!fndef_ok)
{
c_parser_error (parser, "expected %<=%>, %<,%>, %<;%>, "
@@ -1949,7 +2038,7 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser)
Storage class specifiers are accepted iff SCSPEC_OK; type
specifiers are accepted iff TYPESPEC_OK; alignment specifiers are
accepted iff ALIGNSPEC_OK; attributes are accepted at the start
- iff START_ATTR_OK.
+ iff START_ATTR_OK; __auto_type is accepted iff AUTO_TYPE_OK.
declaration-specifiers:
storage-class-specifier declaration-specifiers[opt]
@@ -2030,6 +2119,7 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser)
type-specifier:
typeof-specifier
+ __auto_type
__int128
_Decimal32
_Decimal64
@@ -2055,7 +2145,8 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser)
static void
c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
bool scspec_ok, bool typespec_ok, bool start_attr_ok,
- bool alignspec_ok, enum c_lookahead_kind la)
+ bool alignspec_ok, bool auto_type_ok,
+ enum c_lookahead_kind la)
{
bool attrs_ok = start_attr_ok;
bool seen_type = specs->typespec_kind != ctsk_none;
@@ -2177,6 +2268,10 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
c_parser_peek_token (parser)->value);
c_parser_consume_token (parser);
break;
+ case RID_AUTO_TYPE:
+ if (!auto_type_ok)
+ goto out;
+ /* Fall through. */
case RID_UNSIGNED:
case RID_LONG:
case RID_INT128:
@@ -2722,7 +2817,7 @@ c_parser_struct_declaration (c_parser *parser)
of N1731.
<http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1731.pdf> */
c_parser_declspecs (parser, specs, false, true, true,
- true, cla_nonabstract_decl);
+ true, false, cla_nonabstract_decl);
if (parser->error)
return NULL_TREE;
if (!specs->declspecs_seen_p)
@@ -3045,7 +3140,7 @@ c_parser_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
struct c_declarator *inner;
c_parser_consume_token (parser);
c_parser_declspecs (parser, quals_attrs, false, false, true,
- false, cla_prefer_id);
+ false, false, cla_prefer_id);
inner = c_parser_declarator (parser, type_seen_p, kind, seen_id);
if (inner == NULL)
return NULL;
@@ -3201,13 +3296,13 @@ c_parser_direct_declarator_inner (c_parser *parser, bool id_present,
dimen.original_type = NULL_TREE;
c_parser_consume_token (parser);
c_parser_declspecs (parser, quals_attrs, false, false, true,
- false, cla_prefer_id);
+ false, false, cla_prefer_id);
static_seen = c_parser_next_token_is_keyword (parser, RID_STATIC);
if (static_seen)
c_parser_consume_token (parser);
if (static_seen && !quals_attrs->declspecs_seen_p)
c_parser_declspecs (parser, quals_attrs, false, false, true,
- false, cla_prefer_id);
+ false, false, cla_prefer_id);
if (!quals_attrs->declspecs_seen_p)
quals_attrs = NULL;
/* If "static" is present, there must be an array dimension.
@@ -3510,7 +3605,7 @@ c_parser_parameter_declaration (c_parser *parser, tree attrs)
declspecs_add_attrs (input_location, specs, attrs);
attrs = NULL_TREE;
}
- c_parser_declspecs (parser, specs, true, true, true, true,
+ c_parser_declspecs (parser, specs, true, true, true, true, false,
cla_nonabstract_decl);
finish_declspecs (specs);
pending_xref_error ();
@@ -3643,6 +3738,7 @@ c_parser_attribute_any_word (c_parser *parser)
case RID_TRANSACTION_ATOMIC:
case RID_TRANSACTION_CANCEL:
case RID_ATOMIC:
+ case RID_AUTO_TYPE:
ok = true;
break;
default:
@@ -3821,7 +3917,7 @@ c_parser_type_name (c_parser *parser)
struct c_declarator *declarator;
struct c_type_name *ret;
bool dummy = false;
- c_parser_declspecs (parser, specs, false, true, true, false,
+ c_parser_declspecs (parser, specs, false, true, true, false, false,
cla_prefer_type);
if (!specs->declspecs_seen_p)
{
@@ -8702,6 +8798,7 @@ c_parser_objc_selector (c_parser *parser)
case RID_VOID:
case RID_BOOL:
case RID_ATOMIC:
+ case RID_AUTO_TYPE:
c_parser_consume_token (parser);
return value;
default: