Hi,
There is a very useful feature in gcc, namely __builtin_choose_expr, which
isn't available in g++. I expect that this is simply down to the fact that
it had a very obvious use relating to overloading functions in C which isn't
necessary in C++, and therefore it simply didn't get implemented.
Assuming that this was indeed the only reason, I thought rather than
whinging that this wasn't available in C++, I'd have a go at implementing
it.
Attached below, therefore, is a simple patch to GCC 4.6.1 which implements
__builtin_choose_expr for C++. From my testing, it "seems to work fine",
but I'm afraid this is my first time hacking GCC, so I would be very
grateful if someone much more knowledgeable than me could check over my
patch (it should be very easy to follow) to see whether my approach is valid
or not.
If it seems to people that this is a useful / suitable addition to GCC
generally, then I would be happy to supplement my patch with test-cases and
proper documentation and see whether it can be merged into the GCC trunk.
Obviously I have uses for this feature, but I don't know whether it has a
broader appeal! ;o)
Thanks
Andy
--- <snip> ---
--- gcc-4.6.1-orig/gcc/c-family/c-common.c
+++ gcc-4.6.1/gcc/c-family/c-common.c
@@ -420,7 +420,7 @@ const struct c_common_resword c_common_r
{ "__asm__", RID_ASM, 0 },
{ "__attribute", RID_ATTRIBUTE, 0 },
{ "__attribute__", RID_ATTRIBUTE, 0 },
- { "__builtin_choose_expr", RID_CHOOSE_EXPR, D_CONLY },
+ { "__builtin_choose_expr", RID_CHOOSE_EXPR, 0 },
{ "__builtin_offsetof", RID_OFFSETOF, 0 },
{ "__builtin_types_compatible_p", RID_TYPES_COMPATIBLE_P, D_CONLY },
{ "__builtin_va_arg", RID_VA_ARG, 0 },
--- gcc-4.6.1-orig/gcc/cp/parser.c
+++ gcc-4.6.1/gcc/cp/parser.c
@@ -1837,6 +1837,8 @@ static tree cp_parser_expression
(cp_parser *, bool, cp_id_kind *);
static tree cp_parser_constant_expression
(cp_parser *, bool, bool *);
+static tree cp_parser_builtin_choose_expr
+ (cp_parser *);
static tree cp_parser_builtin_offsetof
(cp_parser *);
static tree cp_parser_lambda_expression
@@ -3850,6 +3852,9 @@ cp_parser_primary_expression (cp_parser
case RID_OFFSETOF:
return cp_parser_builtin_offsetof (parser);
+ case RID_CHOOSE_EXPR:
+ return cp_parser_builtin_choose_expr (parser);
+
case RID_HAS_NOTHROW_ASSIGN:
case RID_HAS_NOTHROW_CONSTRUCTOR:
case RID_HAS_NOTHROW_COPY:
@@ -7403,6 +7408,43 @@ cp_parser_builtin_offsetof (cp_parser *p
return expr;
}
+/* Parse __builtin_choose_expr.
+
+ __builtin_choose_expr ( constant-expression ,
+ assignment-expression ,
+ assignment-expression ) */
+
+static tree
+cp_parser_builtin_choose_expr (cp_parser *parser)
+{
+ tree condition, expr_true, expr_false;
+
+ /* Consume the "__builtin_choose_expr" token. */
+ cp_lexer_consume_token (parser->lexer);
+
+ /* Parse expressions. */
+ cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
+ condition = cp_parser_constant_expression (parser, false, NULL);
+ cp_parser_require (parser, CPP_COMMA, RT_COMMA);
+ expr_true = cp_parser_assignment_expression (parser, false, NULL);
+ cp_parser_require (parser, CPP_COMMA, RT_COMMA);
+ expr_false = cp_parser_assignment_expression (parser, false, NULL);
+ if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ cp_parser_skip_to_closing_parenthesis (parser, true, false, true);
+
+ /* Fold the condition expression and convert it to a boolean value. */
+ condition = fold_non_dependent_expr (condition);
+ condition = cp_convert (boolean_type_node, condition);
+ condition = maybe_constant_value (condition);
+
+ if (TREE_CODE (condition) == INTEGER_CST)
+ return integer_zerop (condition) ? expr_false : expr_true;
+
+ error ("non-constant condition for %<__builtin_choose_expr%>");
+ cxx_constant_value (condition);
+ return error_mark_node;
+}
+
/* Parse a trait expression.
Returns a representation of the expression, the underlying type