From ecbcf7b3198489daee27a8dd913314a69e947c11 Mon Sep 17 00:00:00 2001 From: Aldy Hernandez Date: Sat, 8 Dec 2001 22:34:54 +0000 Subject: [PATCH] c-common.h (rid): Add RID_CHOOSE_EXPR and RID_TYPES_COMPATIBLE_P. * c-common.h (rid): Add RID_CHOOSE_EXPR and RID_TYPES_COMPATIBLE_P. * c-parse.in (reswords): Add __builtin_choose_expr. Add __builtin_types_compatible_p. Add CHOOSE_EXPR token. Add TYPES_COMPATIBLE_P token. Add production for CHOOSE_EXPR. Add production for TYPES_COMPATIBLE_P. * doc/extend.texi (__builtin_choose_expr): Add documentation. (__builtin_types_compatible_p): Likewise. From-SVN: r47798 --- gcc/ChangeLog | 15 ++++++++ gcc/c-common.h | 2 +- gcc/c-parse.in | 27 +++++++++++++- gcc/doc/extend.texi | 90 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 132 insertions(+), 2 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 799f445cfc6..5155954714b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2001-10-08 Aldy Hernandez + + * c-common.h (rid): Add RID_CHOOSE_EXPR and + RID_TYPES_COMPATIBLE_P. + + * c-parse.in (reswords): Add __builtin_choose_expr. + Add __builtin_types_compatible_p. + Add CHOOSE_EXPR token. + Add TYPES_COMPATIBLE_P token. + Add production for CHOOSE_EXPR. + Add production for TYPES_COMPATIBLE_P. + + * doc/extend.texi (__builtin_choose_expr): Add documentation. + (__builtin_types_compatible_p): Likewise. + 2001-12-08 David Edelsohn * stor-layout.c (place_union_field): Apply ADJUST_FIELD_ALIGN diff --git a/gcc/c-common.h b/gcc/c-common.h index 33835f653db..59525d5dc53 100644 --- a/gcc/c-common.h +++ b/gcc/c-common.h @@ -74,7 +74,7 @@ enum rid /* C extensions */ RID_ASM, RID_TYPEOF, RID_ALIGNOF, RID_ATTRIBUTE, RID_VA_ARG, RID_EXTENSION, RID_IMAGPART, RID_REALPART, RID_LABEL, RID_PTRBASE, - RID_PTREXTENT, RID_PTRVALUE, + RID_PTREXTENT, RID_PTRVALUE, RID_CHOOSE_EXPR, RID_TYPES_COMPATIBLE_P, /* Too many ways of getting the name of a function as a string */ RID_FUNCTION_NAME, RID_PRETTY_FUNCTION_NAME, RID_C99_FUNCTION_NAME, diff --git a/gcc/c-parse.in b/gcc/c-parse.in index 324300d00e8..84d1c0214b3 100644 --- a/gcc/c-parse.in +++ b/gcc/c-parse.in @@ -110,7 +110,7 @@ end ifobjc %token SIZEOF ENUM STRUCT UNION IF ELSE WHILE DO FOR SWITCH CASE DEFAULT %token BREAK CONTINUE RETURN GOTO ASM_KEYWORD TYPEOF ALIGNOF %token ATTRIBUTE EXTENSION LABEL -%token REALPART IMAGPART VA_ARG +%token REALPART IMAGPART VA_ARG CHOOSE_EXPR TYPES_COMPATIBLE_P %token PTR_VALUE PTR_BASE PTR_EXTENT /* function name can be a string const or a var decl. */ @@ -664,6 +664,26 @@ primary: { $$ = build_function_call ($1, $3); } | VA_ARG '(' expr_no_commas ',' typename ')' { $$ = build_va_arg ($3, groktypename ($5)); } + | CHOOSE_EXPR '(' expr_no_commas ',' expr_no_commas ',' expr_no_commas ')' + { + tree c; + + c = fold ($3); + STRIP_NOPS (c); + if (TREE_CODE (c) != INTEGER_CST) + error ("first argument to __builtin_choose_expr not a constant"); + $$ = integer_zerop (c) ? $7 : $5; + } + | TYPES_COMPATIBLE_P '(' typename ',' typename ')' + { + tree e1, e2; + + e1 = TYPE_MAIN_VARIANT (groktypename ($3)); + e2 = TYPE_MAIN_VARIANT (groktypename ($5)); + + $$ = comptypes (e1, e2) + ? build_int_2 (1, 0) : build_int_2 (0, 0); + } | primary '[' expr ']' %prec '.' { $$ = build_array_ref ($1, $3); } | primary '.' identifier @@ -3218,6 +3238,8 @@ static const struct resword reswords[] = { "__attribute__", RID_ATTRIBUTE, 0 }, { "__bounded", RID_BOUNDED, 0 }, { "__bounded__", RID_BOUNDED, 0 }, + { "__builtin_choose_expr", RID_CHOOSE_EXPR, 0 }, + { "__builtin_types_compatible_p", RID_TYPES_COMPATIBLE_P, 0 }, { "__builtin_va_arg", RID_VA_ARG, 0 }, { "__complex", RID_COMPLEX, 0 }, { "__complex__", RID_COMPLEX, 0 }, @@ -3390,6 +3412,9 @@ static const short rid_to_yy[RID_MAX] = /* RID_PTREXTENT */ PTR_EXTENT, /* RID_PTRVALUE */ PTR_VALUE, + /* RID_CHOOSE_EXPR */ CHOOSE_EXPR, + /* RID_TYPES_COMPATIBLE_P */ TYPES_COMPATIBLE_P, + /* RID_FUNCTION_NAME */ STRING_FUNC_NAME, /* RID_PRETTY_FUNCTION_NAME */ STRING_FUNC_NAME, /* RID_C99_FUNCTION_NAME */ VAR_FUNC_NAME, diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 5e800108803..1a4ff5814df 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -4388,6 +4388,96 @@ the same names as the standard macros ( @code{isgreater}, prefixed. We intend for a library implementor to be able to simply @code{#define} each standard macro to its built-in equivalent. +@deftypefn {Built-in Function} int __builtin_types_compatible_p (@var{type1}, @var{type2}) + +You can use the built-in function @code{__builtin_types_compatible_p} to +determine whether two types are the same. + +This built-in function returns 1 if the unqualified versions of the +types @var{type1} and @var{type2} (which are types, not expressions) are +compatible, 0 otherwise. The result of this built-in function can be +used in integer constant expressions. + +This built-in function ignores top level qualifiers (e.g., @code{const}, +@code{volatile}). For example, @code{int} is equivalent to @code{const +int}. + +The type @code{int[]} and @code{int[5]} are compatible. On the other +hand, @code{int} and @code{char *} are not compatible, even if the size +of their types, on the particular architecture are the same. Also, the +amount of pointer indirection is taken into account when determining +similarity. Consequently, @code{short *} is not similar to +@code{short **}. Furthermore, two types that are typedefed are +considered compatible if their underlying types are compatible. + +An @code{enum} type is considered to be compatible with another +@code{enum} type. For example, @code{enum @{foo, bar@}} is similar to +@code{enum @{hot, dog@}}. + +You would typically use this function in code whose execution varies +depending on the arguments' types. For example: + +@smallexample +#define foo(x) \ + (@{ \ + typeof (x) tmp; \ + if (__builtin_types_compatible_p (typeof (x), long double)) \ + tmp = foo_long_double (tmp); \ + else if (__builtin_types_compatible_p (typeof (x), double)) \ + tmp = foo_double (tmp); \ + else if (__builtin_types_compatible_p (typeof (x), float)) \ + tmp = foo_float (tmp); \ + else \ + abort (); \ + tmp; \ + @}) +@end smallexample + +@emph{Note:} This construct is only available for C. + +@end deftypefn + +@deftypefn {Built-in Function} @var{type} __builtin_choose_expr (@var{const_exp}, @var{exp1}, @var{exp2}) + +You can use the built-in function @code{__builtin_choose_expr} to +evaluate code depending on the value of a constant expression. This +built-in function returns @var{exp1} if @var{const_exp}, which is a +constant expression that must be able to be determined at compile time, +is nonzero. Otherwise it returns 0. + +This built-in function is analogous to the @samp{? :} operator in C, +except that the expression returned has its type unaltered by promotion +rules. Also, the built-in function does not evaluate the expression +that was not chosen. For example, if @var{const_exp} evaluates to true, +@var{exp2} is not evaluated even if it has side-effects. + +This built-in function can return an lvalue if the chosen argument is an +lvalue. + +If @var{exp1} is returned, the return type is the same as @var{exp1}'s +type. Similarly, if @var{exp2} is returned, its return type is the same +as @var{exp2}. + +Example: + +@smallexample +#define foo(x) \ + __builtin_choose_expr (__builtin_types_compatible_p (typeof (x), double), \ + foo_double (x), \ + __builtin_choose_expr (__builtin_types_compatible_p (typeof (x), float), \ + foo_float (x), \ + /* @r{The void expression results in a compile-time error} \ + @r{when assigning the result to something.} */ \ + (void)0)) +@end smallexample + +@emph{Note:} This construct is only available for C. Furthermore, the +unused expression (@var{exp1} or @var{exp2} depending on the value of +@var{const_exp}) may still generate syntax errors. This may change in +future revisions. + +@end deftypefn + @deftypefn {Built-in Function} int __builtin_constant_p (@var{exp}) You can use the built-in function @code{__builtin_constant_p} to determine if a value is known to be constant at compile-time and hence -- 2.30.2