This is the mail archive of the gcc-help@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

__builtin_choose_expr


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]