isl_basic_set_opt: avoid invalid access on error path
[platform/upstream/isl.git] / isl_space.c
index 539be86..e6f957c 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright 2008-2009 Katholieke Universiteit Leuven
  * Copyright 2010      INRIA Saclay
  *
- * Use of this software is governed by the GNU LGPLv2.1 license
+ * Use of this software is governed by the MIT license
  *
  * Written by Sven Verdoolaege, K.U.Leuven, Departement
  * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
@@ -292,6 +292,8 @@ __isl_take isl_space *isl_space_dup(__isl_keep isl_space *dim)
        if (!dim)
                return NULL;
        dup = isl_space_alloc(dim->ctx, dim->nparam, dim->n_in, dim->n_out);
+       if (!dup)
+               return NULL;
        if (dim->tuple_id[0] &&
            !(dup->tuple_id[0] = isl_id_copy(dim->tuple_id[0])))
                goto error;
@@ -333,15 +335,15 @@ __isl_give isl_space *isl_space_copy(__isl_keep isl_space *dim)
        return dim;
 }
 
-void isl_space_free(__isl_take isl_space *dim)
+void *isl_space_free(__isl_take isl_space *dim)
 {
        int i;
 
        if (!dim)
-               return;
+               return NULL;
 
        if (--dim->ref > 0)
-               return;
+               return NULL;
 
        isl_id_free(dim->tuple_id[0]);
        isl_id_free(dim->tuple_id[1]);
@@ -355,6 +357,8 @@ void isl_space_free(__isl_take isl_space *dim)
        isl_ctx_deref(dim->ctx);
        
        free(dim);
+
+       return NULL;
 }
 
 /* Check if "s" is a valid dimension or tuple name.
@@ -779,6 +783,8 @@ __isl_give isl_space *isl_space_extend(__isl_take isl_space *dim,
        isl_assert(dim->ctx, dim->n_out <= n_out, goto error);
 
        dim = isl_space_cow(dim);
+       if (!dim)
+               goto error;
 
        if (dim->ids) {
                ids = isl_calloc_array(dim->ctx, isl_id *,
@@ -1459,6 +1465,8 @@ __isl_give isl_space *isl_space_underlying(__isl_take isl_space *dim,
        return dim;
 }
 
+/* Are the two spaces the same, including positions and names of parameters?
+ */
 int isl_space_is_equal(__isl_keep isl_space *dim1, __isl_keep isl_space *dim2)
 {
        if (!dim1 || !dim2)
@@ -1471,8 +1479,11 @@ int isl_space_is_equal(__isl_keep isl_space *dim1, __isl_keep isl_space *dim2)
 }
 
 /* Is space1 equal to the domain of space2?
+ *
+ * In the internal version we also allow space2 to be the space of a set,
+ * provided space1 is a parameter space.
  */
-int isl_space_is_domain(__isl_keep isl_space *space1,
+int isl_space_is_domain_internal(__isl_keep isl_space *space1,
        __isl_keep isl_space *space2)
 {
        if (!space1 || !space2)
@@ -1483,6 +1494,46 @@ int isl_space_is_domain(__isl_keep isl_space *space1,
               isl_space_tuple_match(space1, isl_dim_set, space2, isl_dim_in);
 }
 
+/* Is space1 equal to the domain of space2?
+ */
+int isl_space_is_domain(__isl_keep isl_space *space1,
+       __isl_keep isl_space *space2)
+{
+       if (!space2)
+               return -1;
+       if (!isl_space_is_map(space2))
+               return 0;
+       return isl_space_is_domain_internal(space1, space2);
+}
+
+/* Is space1 equal to the range of space2?
+ *
+ * In the internal version, space2 is allowed to be the space of a set,
+ * in which case it should be equal to space1.
+ */
+int isl_space_is_range_internal(__isl_keep isl_space *space1,
+       __isl_keep isl_space *space2)
+{
+       if (!space1 || !space2)
+               return -1;
+       if (!isl_space_is_set(space1))
+               return 0;
+       return match(space1, isl_dim_param, space2, isl_dim_param) &&
+              isl_space_tuple_match(space1, isl_dim_set, space2, isl_dim_out);
+}
+
+/* Is space1 equal to the range of space2?
+ */
+int isl_space_is_range(__isl_keep isl_space *space1,
+       __isl_keep isl_space *space2)
+{
+       if (!space2)
+               return -1;
+       if (!isl_space_is_map(space2))
+               return 0;
+       return isl_space_is_range_internal(space1, space2);
+}
+
 int isl_space_compatible(__isl_keep isl_space *dim1,
        __isl_keep isl_space *dim2)
 {
@@ -1498,9 +1549,9 @@ static uint32_t isl_hash_dim(uint32_t hash, __isl_keep isl_space *dim)
        if (!dim)
                return hash;
 
-       hash = isl_hash_builtin(hash, dim->nparam);
-       hash = isl_hash_builtin(hash, dim->n_in);
-       hash = isl_hash_builtin(hash, dim->n_out);
+       isl_hash_byte(hash, dim->nparam % 256);
+       isl_hash_byte(hash, dim->n_in % 256);
+       isl_hash_byte(hash, dim->n_out % 256);
 
        for (i = 0; i < dim->nparam; ++i) {
                id = get_id(dim, isl_dim_param, i);
@@ -1797,6 +1848,43 @@ error:
        return NULL;
 }
 
+/* Can we apply isl_space_uncurry to "space"?
+ * That is, does it have a nested relation in its range?
+ */
+int isl_space_can_uncurry(__isl_keep isl_space *space)
+{
+       if (!space)
+               return -1;
+
+       return !!space->nested[1];
+}
+
+/* Given a space A -> (B -> C), return the corresponding space
+ * (A -> B) -> C.
+ */
+__isl_give isl_space *isl_space_uncurry(__isl_take isl_space *space)
+{
+       isl_space *dom, *ran;
+       isl_space *ran_dom, *ran_ran;
+
+       if (!space)
+               return NULL;
+
+       if (!isl_space_can_uncurry(space))
+               isl_die(space->ctx, isl_error_invalid,
+                       "space cannot be uncurried",
+                       return isl_space_free(space));
+
+       dom = isl_space_domain(isl_space_copy(space));
+       ran = isl_space_unwrap(isl_space_range(space));
+       ran_dom = isl_space_domain(isl_space_copy(ran));
+       ran_ran = isl_space_range(ran);
+       dom = isl_space_join(isl_space_from_domain(dom),
+                          isl_space_from_range(ran_dom));
+       return isl_space_join(isl_space_from_domain(isl_space_wrap(dom)),
+                           isl_space_from_range(ran_ran));
+}
+
 int isl_space_has_named_params(__isl_keep isl_space *dim)
 {
        int i;