aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2006-09-30 13:46:53 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2006-09-30 16:27:02 -0400
commit3425388b0c9f3ec4807bc4f6a61d5083a99fa506 (patch)
tree081fd621c40902a109dc6c136b5938c35a8a7536 /symbol.c
parent[PATCH] fix duplicate initializer detection (diff)
downloadsparse-3425388b0c9f3ec4807bc4f6a61d5083a99fa506.tar.gz
sparse-3425388b0c9f3ec4807bc4f6a61d5083a99fa506.tar.bz2
sparse-3425388b0c9f3ec4807bc4f6a61d5083a99fa506.zip
[PATCH] add support for __builtin_choose_expr()
that bugger is weird; _no_ type modifications are done to arguments (no promotions, no degeration, void accepted, etc.). Implemented, testcase added. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'symbol.c')
-rw-r--r--symbol.c45
1 files changed, 45 insertions, 0 deletions
diff --git a/symbol.c b/symbol.c
index 1ebfd56..7d64f7f 100644
--- a/symbol.c
+++ b/symbol.c
@@ -515,6 +515,45 @@ static int evaluate_expect(struct expression *expr)
return 1;
}
+static int arguments_choose(struct expression *expr)
+{
+ struct expression_list *arglist = expr->args;
+ struct expression *arg;
+ int i = 0;
+
+ FOR_EACH_PTR (arglist, arg) {
+ if (!evaluate_expression(arg))
+ return 0;
+ i++;
+ } END_FOR_EACH_PTR(arg);
+ if (i < 3) {
+ sparse_error(expr->pos,
+ "not enough arguments for __builtin_choose_expr");
+ return 0;
+ } if (i > 3) {
+ sparse_error(expr->pos,
+ "too many arguments for __builtin_choose_expr");
+ return 0;
+ }
+ return 1;
+}
+
+static int evaluate_choose(struct expression *expr)
+{
+ struct expression_list *list = expr->args;
+ struct expression *arg, *args[3];
+ int n = 0;
+
+ /* there will be exactly 3; we'd already verified that */
+ FOR_EACH_PTR(list, arg) {
+ args[n++] = arg;
+ } END_FOR_EACH_PTR(arg);
+
+ *expr = get_expression_value(args[0]) ? *args[1] : *args[2];
+
+ return 1;
+}
+
static int expand_expect(struct expression *expr, int cost)
{
struct expression *arg = first_ptr_list((struct ptr_list *) expr->args);
@@ -662,6 +701,11 @@ static struct symbol_op expect_op = {
.expand = expand_expect
};
+static struct symbol_op choose_op = {
+ .evaluate = evaluate_choose,
+ .args = arguments_choose,
+};
+
/*
* Builtin functions
*/
@@ -671,6 +715,7 @@ static struct sym_init eval_init_table[] = {
{ "__builtin_safe_p", &builtin_fn_type, MOD_TOPLEVEL, &safe_p_op },
{ "__builtin_warning", &builtin_fn_type, MOD_TOPLEVEL, &warning_op },
{ "__builtin_expect", &builtin_fn_type, MOD_TOPLEVEL, &expect_op },
+ { "__builtin_choose_expr", &builtin_fn_type, MOD_TOPLEVEL, &choose_op },
{ NULL, NULL, 0 }
};