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:
Joseph Myers 2013-11-13 00:38:49 +00:00 committed by Joseph Myers
parent d6d3f03341
commit 38b7bc7fc6
14 changed files with 410 additions and 47 deletions

View File

@ -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

View File

@ -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.

View File

@ -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:

View File

@ -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,

View File

@ -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.

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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
@ -132,11 +132,12 @@ typedef _Atomic __UINTMAX_TYPE__ atomic_uintmax_t;
these to lock-free _N variants if possible, and throw away the
temps. */
#define atomic_store_explicit(PTR, VAL, MO) \
__extension__ \
({ \
__typeof__ (*(PTR)) __atomic_store_tmp = (VAL); \
__atomic_store ((PTR), &__atomic_store_tmp, (MO)); \
#define atomic_store_explicit(PTR, VAL, MO) \
__extension__ \
({ \
__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)); \
})

View File

@ -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

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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" } */