mirror of git://gcc.gnu.org/git/gcc.git
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
This commit is contained in:
parent
d6d3f03341
commit
38b7bc7fc6
|
|
@ -1,3 +1,12 @@
|
|||
2013-11-13 Joseph Myers <joseph@codesourcery.com>
|
||||
|
||||
* 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.
|
||||
|
||||
2013-11-12 Jeff Law <law@redhat.com>
|
||||
|
||||
* tree-ssa-threadedge.c (thread_around_empty_blocks): New
|
||||
|
|
|
|||
|
|
@ -1,3 +1,9 @@
|
|||
2013-11-13 Joseph Myers <joseph@codesourcery.com>
|
||||
|
||||
* 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.
|
||||
|
||||
2013-11-12 Andrew MacLeod <amacleod@redhat.com>
|
||||
|
||||
* c-family/c-common.c: Include gimplify.h.
|
||||
|
|
|
|||
|
|
@ -434,6 +434,7 @@ const struct c_common_resword c_common_reswords[] =
|
|||
{ "__asm__", RID_ASM, 0 },
|
||||
{ "__attribute", RID_ATTRIBUTE, 0 },
|
||||
{ "__attribute__", RID_ATTRIBUTE, 0 },
|
||||
{ "__auto_type", RID_AUTO_TYPE, D_CONLY },
|
||||
{ "__bases", RID_BASES, D_CXXONLY },
|
||||
{ "__builtin_choose_expr", RID_CHOOSE_EXPR, D_CONLY },
|
||||
{ "__builtin_complex", RID_BUILTIN_COMPLEX, D_CONLY },
|
||||
|
|
@ -11551,6 +11552,7 @@ keyword_begins_type_specifier (enum rid keyword)
|
|||
{
|
||||
switch (keyword)
|
||||
{
|
||||
case RID_AUTO_TYPE:
|
||||
case RID_INT:
|
||||
case RID_CHAR:
|
||||
case RID_FLOAT:
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ enum rid
|
|||
RID_EXTENSION, RID_IMAGPART, RID_REALPART, RID_LABEL, RID_CHOOSE_EXPR,
|
||||
RID_TYPES_COMPATIBLE_P, RID_BUILTIN_COMPLEX, RID_BUILTIN_SHUFFLE,
|
||||
RID_DFLOAT32, RID_DFLOAT64, RID_DFLOAT128,
|
||||
RID_FRACT, RID_ACCUM,
|
||||
RID_FRACT, RID_ACCUM, RID_AUTO_TYPE,
|
||||
|
||||
/* C11 */
|
||||
RID_ALIGNAS, RID_GENERIC,
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
121
gcc/c/c-parser.c
121
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,6 +1680,58 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
|
|||
struct c_expr init;
|
||||
location_t init_loc;
|
||||
c_parser_consume_token (parser);
|
||||
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,
|
||||
|
|
@ -1680,6 +1745,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
|
|||
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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ the value of an enumeration constant, the width of a bit-field, or
|
|||
the initial value of a static variable.
|
||||
|
||||
If you don't know the type of the operand, you can still do this, but you
|
||||
must use @code{typeof} (@pxref{Typeof}).
|
||||
must use @code{typeof} or @code{__auto_type} (@pxref{Typeof}).
|
||||
|
||||
In G++, the result value of a statement expression undergoes array and
|
||||
function pointer decay, and is returned by value to the enclosing
|
||||
|
|
@ -755,6 +755,35 @@ Thus, @code{array (pointer (char), 4)} is the type of arrays of 4
|
|||
pointers to @code{char}.
|
||||
@end itemize
|
||||
|
||||
In GNU C, but not GNU C++, you may also declare the type of a variable
|
||||
as @code{__auto_type}. In that case, the declaration must declare
|
||||
only one variable, whose declarator must just be an identifier, the
|
||||
declaration must be initialized, and the type of the variable is
|
||||
determined by the initializer; the name of the variable is not in
|
||||
scope until after the initializer. (In C++, you should use C++11
|
||||
@code{auto} for this purpose.) Using @code{__auto_type}, the
|
||||
``maximum'' macro above could be written as:
|
||||
|
||||
@smallexample
|
||||
#define max(a,b) \
|
||||
(@{ __auto_type _a = (a); \
|
||||
__auto_type _b = (b); \
|
||||
_a > _b ? _a : _b; @})
|
||||
@end smallexample
|
||||
|
||||
Using @code{__auto_type} instead of @code{typeof} has two advantages:
|
||||
|
||||
@itemize @bullet
|
||||
@item Each argument to the macro appears only once in the expansion of
|
||||
the macro. This prevents the size of the macro expansion growing
|
||||
exponentially when calls to such macros are nested inside arguments of
|
||||
such macros.
|
||||
|
||||
@item If the argument to the macro has variably modified type, it is
|
||||
evaluated only once when using @code{__auto_type}, but twice if
|
||||
@code{typeof} is used.
|
||||
@end itemize
|
||||
|
||||
@emph{Compatibility Note:} In addition to @code{typeof}, GCC 2 supported
|
||||
a more limited extension that permitted one to write
|
||||
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ typedef _Atomic __UINTMAX_TYPE__ atomic_uintmax_t;
|
|||
#define kill_dependency(Y) \
|
||||
__extension__ \
|
||||
({ \
|
||||
__typeof__ (Y) __kill_dependency_tmp = (Y); \
|
||||
__auto_type __kill_dependency_tmp = (Y); \
|
||||
__kill_dependency_tmp; \
|
||||
})
|
||||
|
||||
|
|
@ -121,9 +121,9 @@ typedef _Atomic __UINTMAX_TYPE__ atomic_uintmax_t;
|
|||
__atomic_type_lock_free (void * _Atomic)
|
||||
|
||||
|
||||
/* Note that these macros require __typeof__ to remove _Atomic
|
||||
qualifiers (and const qualifiers, if those are valid on macro
|
||||
operands).
|
||||
/* Note that these macros require __typeof__ and __auto_type to remove
|
||||
_Atomic qualifiers (and const qualifiers, if those are valid on
|
||||
macro operands).
|
||||
|
||||
Also note that the header file uses the generic form of __atomic
|
||||
builtins, which requires the address to be taken of the value
|
||||
|
|
@ -135,8 +135,9 @@ typedef _Atomic __UINTMAX_TYPE__ atomic_uintmax_t;
|
|||
#define atomic_store_explicit(PTR, VAL, MO) \
|
||||
__extension__ \
|
||||
({ \
|
||||
__typeof__ (*(PTR)) __atomic_store_tmp = (VAL); \
|
||||
__atomic_store ((PTR), &__atomic_store_tmp, (MO)); \
|
||||
__auto_type __atomic_store_ptr = (PTR); \
|
||||
__typeof__ (*__atomic_store_ptr) __atomic_store_tmp = (VAL); \
|
||||
__atomic_store (__atomic_store_ptr, &__atomic_store_tmp, (MO)); \
|
||||
})
|
||||
|
||||
#define atomic_store(PTR, VAL) \
|
||||
|
|
@ -146,8 +147,9 @@ typedef _Atomic __UINTMAX_TYPE__ atomic_uintmax_t;
|
|||
#define atomic_load_explicit(PTR, MO) \
|
||||
__extension__ \
|
||||
({ \
|
||||
__typeof__ (*(PTR)) __atomic_load_tmp; \
|
||||
__atomic_load ((PTR), &__atomic_load_tmp, (MO)); \
|
||||
__auto_type __atomic_load_ptr = (PTR); \
|
||||
__typeof__ (*__atomic_load_ptr) __atomic_load_tmp; \
|
||||
__atomic_load (__atomic_load_ptr, &__atomic_load_tmp, (MO)); \
|
||||
__atomic_load_tmp; \
|
||||
})
|
||||
|
||||
|
|
@ -157,8 +159,10 @@ typedef _Atomic __UINTMAX_TYPE__ atomic_uintmax_t;
|
|||
#define atomic_exchange_explicit(PTR, VAL, MO) \
|
||||
__extension__ \
|
||||
({ \
|
||||
__typeof__ (*(PTR)) __atomic_exchange_val = (VAL), __atomic_exchange_tmp; \
|
||||
__atomic_exchange ((PTR), &__atomic_exchange_val, \
|
||||
__auto_type __atomic_exchange_ptr = (PTR); \
|
||||
__typeof__ (*__atomic_exchange_ptr) __atomic_exchange_val = (VAL); \
|
||||
__typeof__ (*__atomic_exchange_ptr) __atomic_exchange_tmp; \
|
||||
__atomic_exchange (__atomic_exchange_ptr, &__atomic_exchange_val, \
|
||||
&__atomic_exchange_tmp, (MO)); \
|
||||
__atomic_exchange_tmp; \
|
||||
})
|
||||
|
|
@ -170,8 +174,10 @@ typedef _Atomic __UINTMAX_TYPE__ atomic_uintmax_t;
|
|||
#define atomic_compare_exchange_strong_explicit(PTR, VAL, DES, SUC, FAIL) \
|
||||
__extension__ \
|
||||
({ \
|
||||
__typeof__ (*(PTR)) __atomic_compare_exchange_tmp = (DES); \
|
||||
__atomic_compare_exchange ((PTR), (VAL), \
|
||||
__auto_type __atomic_compare_exchange_ptr = (PTR); \
|
||||
__typeof__ (*__atomic_compare_exchange_ptr) __atomic_compare_exchange_tmp \
|
||||
= (DES); \
|
||||
__atomic_compare_exchange (__atomic_compare_exchange_ptr, (VAL), \
|
||||
&__atomic_compare_exchange_tmp, 0, \
|
||||
(SUC), (FAIL)); \
|
||||
})
|
||||
|
|
@ -183,8 +189,10 @@ typedef _Atomic __UINTMAX_TYPE__ atomic_uintmax_t;
|
|||
#define atomic_compare_exchange_weak_explicit(PTR, VAL, DES, SUC, FAIL) \
|
||||
__extension__ \
|
||||
({ \
|
||||
__typeof__ (*(PTR)) __atomic_compare_exchange_tmp = (DES); \
|
||||
__atomic_compare_exchange ((PTR), (VAL), \
|
||||
__auto_type __atomic_compare_exchange_ptr = (PTR); \
|
||||
__typeof__ (*__atomic_compare_exchange_ptr) __atomic_compare_exchange_tmp \
|
||||
= (DES); \
|
||||
__atomic_compare_exchange (__atomic_compare_exchange_ptr, (VAL), \
|
||||
&__atomic_compare_exchange_tmp, 1, \
|
||||
(SUC), (FAIL)); \
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,3 +1,8 @@
|
|||
2013-11-13 Joseph Myers <joseph@codesourcery.com>
|
||||
|
||||
* gcc.dg/atomic/stdatomic-vm.c, gcc.dg/auto-type-1.c,
|
||||
gcc.dg/auto-type-2.c: New tests.
|
||||
|
||||
2013-11-12 Balaji V. Iyer <balaji.v.iyer@intel.com>
|
||||
|
||||
* gcc.dg/cilk-plus/cilk-plus.exp: Added a check for LTO before running
|
||||
|
|
|
|||
|
|
@ -0,0 +1,68 @@
|
|||
/* Test atomic operations on expressions of variably modified type
|
||||
with side effects. */
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-std=c11 -pedantic-errors" } */
|
||||
|
||||
#include <stdatomic.h>
|
||||
|
||||
extern void abort (void);
|
||||
|
||||
int s = 5;
|
||||
|
||||
int count = 0;
|
||||
|
||||
int
|
||||
func (void)
|
||||
{
|
||||
count++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
int vla[s][s];
|
||||
int (*_Atomic p)[s] = &vla[0];
|
||||
int (*b)[s] = kill_dependency (++p);
|
||||
if (b != &vla[1] || p != &vla[1])
|
||||
abort ();
|
||||
int (*_Atomic *q)[s] = &p;
|
||||
atomic_store_explicit (q + func (), &vla[0], memory_order_seq_cst);
|
||||
if (count != 1)
|
||||
abort ();
|
||||
atomic_store (q + func (), &vla[0]);
|
||||
if (count != 2)
|
||||
abort ();
|
||||
(void) atomic_load_explicit (q + func (), memory_order_seq_cst);
|
||||
if (count != 3)
|
||||
abort ();
|
||||
(void) atomic_load (q + func ());
|
||||
if (count != 4)
|
||||
abort ();
|
||||
(void) atomic_exchange_explicit (q + func (), &vla[0], memory_order_seq_cst);
|
||||
if (count != 5)
|
||||
abort ();
|
||||
(void) atomic_exchange (q + func (), &vla[0]);
|
||||
if (count != 6)
|
||||
abort ();
|
||||
int vla2[s][s];
|
||||
int (*p2)[s] = &vla2[0];
|
||||
int (**qna)[s] = &p2;
|
||||
(void) atomic_compare_exchange_strong_explicit (q + func (), qna, &vla[0],
|
||||
memory_order_seq_cst,
|
||||
memory_order_seq_cst);
|
||||
if (count != 7)
|
||||
abort ();
|
||||
(void) atomic_compare_exchange_strong (q + func (), qna, &vla[0]);
|
||||
if (count != 8)
|
||||
abort ();
|
||||
(void) atomic_compare_exchange_weak_explicit (q + func (), qna, &vla[0],
|
||||
memory_order_seq_cst,
|
||||
memory_order_seq_cst);
|
||||
if (count != 9)
|
||||
abort ();
|
||||
(void) atomic_compare_exchange_weak (q + func (), qna, &vla[0]);
|
||||
if (count != 10)
|
||||
abort ();
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
/* Test __auto_type. Test correct uses. */
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "" } */
|
||||
|
||||
extern void abort (void);
|
||||
extern void exit (int);
|
||||
|
||||
__auto_type i = 1;
|
||||
extern int i;
|
||||
__auto_type c = (char) 1;
|
||||
extern char c;
|
||||
static __auto_type u = 10U;
|
||||
extern unsigned int u;
|
||||
const __auto_type ll = 1LL;
|
||||
extern const long long ll;
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
if (i != 1 || c != 1 || u != 10U)
|
||||
abort ();
|
||||
__auto_type ai = i;
|
||||
int *aip = &ai;
|
||||
if (ai != 1)
|
||||
abort ();
|
||||
__auto_type p = (int (*) [++i]) 0;
|
||||
if (i != 2)
|
||||
abort ();
|
||||
if (sizeof (*p) != 2 * sizeof (int))
|
||||
abort ();
|
||||
int vla[u][u];
|
||||
int (*vp)[u] = &vla[0];
|
||||
__auto_type vpp = ++vp;
|
||||
if (vp != &vla[1])
|
||||
abort ();
|
||||
exit (0);
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
/* Test __auto_type. Test invalid uses. */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "" } */
|
||||
|
||||
__auto_type; /* { dg-error "empty declaration" } */
|
||||
__auto_type *p = (int *) 0; /* { dg-error "plain identifier" } */
|
||||
struct s0 { int i : 1; } x;
|
||||
void f (void) { __auto_type v = x.i; } /* { dg-error "bit-field initializer" } */
|
||||
__auto_type i; /* { dg-error "initialized data declaration" } */
|
||||
__auto_type g { } /* { dg-error "initialized data declaration" } */
|
||||
__auto_type a = 1, b = 2; /* { dg-error "single declarator" } */
|
||||
__auto_type long e0 = 0; /* { dg-error "__auto_type" } */
|
||||
__auto_type short e1 = 0; /* { dg-error "__auto_type" } */
|
||||
__auto_type signed e2 = 0; /* { dg-error "__auto_type" } */
|
||||
__auto_type unsigned e3 = 0; /* { dg-error "__auto_type" } */
|
||||
__auto_type _Complex e4 = 0; /* { dg-error "__auto_type" } */
|
||||
long __auto_type e5 = 0; /* { dg-error "__auto_type" } */
|
||||
short __auto_type e6 = 0; /* { dg-error "__auto_type" } */
|
||||
signed __auto_type e7 = 0; /* { dg-error "__auto_type" } */
|
||||
unsigned __auto_type e8 = 0; /* { dg-error "__auto_type" } */
|
||||
_Complex __auto_type e9 = 0; /* { dg-error "__auto_type" } */
|
||||
int __auto_type e10 = 0; /* { dg-error "two or more data types" } */
|
||||
__auto_type _Bool e11 = 0; /* { dg-error "two or more data types" } */
|
||||
Loading…
Reference in New Issue