aboutsummaryrefslogtreecommitdiff
path: root/gcc/c
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2013-11-13 00:38:49 +0000
committerJoseph Myers <jsm28@gcc.gnu.org>2013-11-13 00:38:49 +0000
commit38b7bc7fc6a883b7ed12f27c798496fceef28ba2 (patch)
treee843a9dc913b73d2b8924f2993e8aaeee0c8be4f /gcc/c
parentd6d3f03341138d3918c71ce9fc6f05b81ebe004e (diff)
downloadgcc-38b7bc7fc6a883b7ed12f27c798496fceef28ba2.zip
gcc-38b7bc7fc6a883b7ed12f27c798496fceef28ba2.tar.gz
gcc-38b7bc7fc6a883b7ed12f27c798496fceef28ba2.tar.bz2
extend.texi (Statement Exprs, Typeof): Discuss __auto_type.
* 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. From-SVN: r204731
Diffstat (limited to 'gcc/c')
-rw-r--r--gcc/c/ChangeLog16
-rw-r--r--gcc/c/c-decl.c66
-rw-r--r--gcc/c/c-parser.c147
-rw-r--r--gcc/c/c-tree.h3
4 files changed, 204 insertions, 28 deletions
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index e95c54d..b9b9dc9 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,19 @@
+2013-11-13 Joseph Myers <joseph@codesourcery.com>
+
+ * 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.
+
2013-11-12 Andrew MacLeod <amacleod@redhat.com>
* c/c-typeck.c: Include gimplify.h.
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 6fe418e..92fc68f 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -9115,6 +9115,10 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
error_at (loc,
("both %<long%> and %<short%> in "
"declaration specifiers"));
+ else if (specs->typespec_word == cts_auto_type)
+ error_at (loc,
+ ("both %<long%> and %<__auto_type%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_void)
error_at (loc,
("both %<long%> and %<void%> in "
@@ -9159,6 +9163,10 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
error_at (loc,
("both %<long%> and %<short%> in "
"declaration specifiers"));
+ else if (specs->typespec_word == cts_auto_type)
+ error_at (loc,
+ ("both %<short%> and %<__auto_type%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_void)
error_at (loc,
("both %<short%> and %<void%> in "
@@ -9207,6 +9215,10 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
error_at (loc,
("both %<signed%> and %<unsigned%> in "
"declaration specifiers"));
+ else if (specs->typespec_word == cts_auto_type)
+ error_at (loc,
+ ("both %<signed%> and %<__auto_type%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_void)
error_at (loc,
("both %<signed%> and %<void%> in "
@@ -9247,6 +9259,10 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
error_at (loc,
("both %<signed%> and %<unsigned%> in "
"declaration specifiers"));
+ else if (specs->typespec_word == cts_auto_type)
+ error_at (loc,
+ ("both %<unsigned%> and %<__auto_type%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_void)
error_at (loc,
("both %<unsigned%> and %<void%> in "
@@ -9286,7 +9302,11 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
if (!flag_isoc99 && !in_system_header_at (loc))
pedwarn (loc, OPT_Wpedantic,
"ISO C90 does not support complex types");
- if (specs->typespec_word == cts_void)
+ if (specs->typespec_word == cts_auto_type)
+ error_at (loc,
+ ("both %<complex%> and %<__auto_type%> in "
+ "declaration specifiers"));
+ else if (specs->typespec_word == cts_void)
error_at (loc,
("both %<complex%> and %<void%> in "
"declaration specifiers"));
@@ -9334,6 +9354,10 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
("both %<_Sat%> and %<__int128%> in "
"declaration specifiers"));
}
+ else if (specs->typespec_word == cts_auto_type)
+ error_at (loc,
+ ("both %<_Sat%> and %<__auto_type%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_void)
error_at (loc,
("both %<_Sat%> and %<void%> in "
@@ -9392,7 +9416,8 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
else
{
/* "void", "_Bool", "char", "int", "float", "double", "_Decimal32",
- "__int128", "_Decimal64", "_Decimal128", "_Fract" or "_Accum". */
+ "__int128", "_Decimal64", "_Decimal128", "_Fract", "_Accum" or
+ "__auto_type". */
if (specs->typespec_word != cts_none)
{
error_at (loc,
@@ -9401,6 +9426,37 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
}
switch (i)
{
+ case RID_AUTO_TYPE:
+ if (specs->long_p)
+ error_at (loc,
+ ("both %<long%> and %<__auto_type%> in "
+ "declaration specifiers"));
+ else if (specs->short_p)
+ error_at (loc,
+ ("both %<short%> and %<__auto_type%> in "
+ "declaration specifiers"));
+ else if (specs->signed_p)
+ error_at (loc,
+ ("both %<signed%> and %<__auto_type%> in "
+ "declaration specifiers"));
+ else if (specs->unsigned_p)
+ error_at (loc,
+ ("both %<unsigned%> and %<__auto_type%> in "
+ "declaration specifiers"));
+ else if (specs->complex_p)
+ error_at (loc,
+ ("both %<complex%> and %<__auto_type%> in "
+ "declaration specifiers"));
+ else if (specs->saturating_p)
+ error_at (loc,
+ ("both %<_Sat%> and %<__auto_type%> in "
+ "declaration specifiers"));
+ else
+ {
+ specs->typespec_word = cts_auto_type;
+ specs->locations[cdw_typespec] = loc;
+ }
+ return specs;
case RID_INT128:
if (int128_integer_type_node == NULL_TREE)
{
@@ -9956,6 +10012,12 @@ finish_declspecs (struct c_declspecs *specs)
/* Now compute the actual type. */
switch (specs->typespec_word)
{
+ case cts_auto_type:
+ gcc_assert (!specs->long_p && !specs->short_p
+ && !specs->signed_p && !specs->unsigned_p
+ && !specs->complex_p);
+ /* Type to be filled in later. */
+ break;
case cts_void:
gcc_assert (!specs->long_p && !specs->short_p
&& !specs->signed_p && !specs->unsigned_p
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 5b4665a..ffbf3c4 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:
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index 502fdca..c4dfc3b 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -214,7 +214,8 @@ enum c_typespec_keyword {
cts_dfloat64,
cts_dfloat128,
cts_fract,
- cts_accum
+ cts_accum,
+ cts_auto_type
};
/* This enum lists all the possible declarator specifiers, storage