isl_ast_build_expr_from_set: return valid result on empty set
authorSven Verdoolaege <skimo@kotnet.org>
Thu, 1 May 2014 10:11:27 +0000 (1 12:11 +0200)
committerSven Verdoolaege <skimo@kotnet.org>
Thu, 1 May 2014 10:11:27 +0000 (1 12:11 +0200)
When presented with an empty set, isl_ast_build_expr_from_set would
simply return the value NULL, indicating a failure.
Although there should be no need to call isl_ast_build_expr_from_set
on an empty set, we should not fail silently.
We choose to return a valid expression rather than requiring
a non-empty input.

Although it is currently possible for the isl_ast_build_expr_from_set
to get called on an empty set, the only known test cases that reach
this point only do so due to another bug that will be fixed in the
next commit.  We therefore test the low-level function instead
just in case it ever gets exported.

Signed-off-by: Sven Verdoolaege <skimo@kotnet.org>
isl_ast_build_expr.c
isl_test.c

index b0fdbb9..f8ee07f 100644 (file)
@@ -1201,6 +1201,8 @@ static int expr_from_set(__isl_take isl_basic_set *bset, void *user)
 
 /* Construct an isl_ast_expr that evaluates the conditions defining "set".
  * The result is simplified in terms of build->domain.
+ *
+ * If "set" is an (obviously) empty set, then return the expression "0".
  */
 __isl_give isl_ast_expr *isl_ast_build_expr_from_set(
        __isl_keep isl_ast_build *build, __isl_take isl_set *set)
@@ -1209,6 +1211,10 @@ __isl_give isl_ast_expr *isl_ast_build_expr_from_set(
 
        if (isl_set_foreach_basic_set(set, &expr_from_set, &data) < 0)
                data.res = isl_ast_expr_free(data.res);
+       else if (data.first) {
+               isl_ctx *ctx = isl_ast_build_get_ctx(build);
+               data.res = isl_ast_expr_from_val(isl_val_zero(ctx));
+       }
 
        isl_set_free(set);
        return data.res;
index f96d546..dd5ce59 100644 (file)
@@ -30,6 +30,7 @@
 #include <isl/ast_build.h>
 #include <isl/val.h>
 #include <isl/ilp.h>
+#include <isl_ast_build_expr.h>
 
 #define ARRAY_SIZE(array) (sizeof(array)/sizeof(*array))
 
@@ -4331,6 +4332,31 @@ static int test_ast(isl_ctx *ctx)
        return 0;
 }
 
+/* Check that isl_ast_build_expr_from_set returns a valid expression
+ * for an empty set.  Note that isl_ast_build_expr_from_set getting
+ * called on an empty set probably indicates a bug in the caller.
+ */
+static int test_ast_build(isl_ctx *ctx)
+{
+       isl_set *set;
+       isl_ast_build *build;
+       isl_ast_expr *expr;
+
+       set = isl_set_universe(isl_space_params_alloc(ctx, 0));
+       build = isl_ast_build_from_context(set);
+
+       set = isl_set_empty(isl_space_params_alloc(ctx, 0));
+       expr = isl_ast_build_expr_from_set(build, set);
+
+       isl_ast_expr_free(expr);
+       isl_ast_build_free(build);
+
+       if (!expr)
+               return -1;
+
+       return 0;
+}
+
 /* Internal data structure for before_for and after_for callbacks.
  *
  * depth is the current depth
@@ -4881,6 +4907,7 @@ struct {
        { "preimage", &test_preimage },
        { "pullback", &test_pullback },
        { "AST", &test_ast },
+       { "AST build", &test_ast_build },
        { "AST generation", &test_ast_gen },
        { "eliminate", &test_eliminate },
        { "residue class", &test_residue_class },