Commit 38b7bc7f by Joseph Myers Committed by Joseph Myers

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
parent d6d3f033
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
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,
......
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
......
......@@ -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
......@@ -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)); \
})
......
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
......
/* 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;
}
/* 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);
}
/* 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" } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment