+ type = build_nonstandard_integer_type (wider_precision, unsigned_p);
+
+ if (!type)
+ {
+ gloog_error = true;
+ return integer_type_node;
+ }
+
+ return type;
+}
+
+/* Return a type that could represent the integer value VAL, or
+ otherwise return NULL_TREE. */
+
+static tree
+type_for_value (mpz_t val)
+{
+ return type_for_interval (val, val);
+}
+
+/* Return the type for the clast_term T. Initializes BOUND_ONE and
+ BOUND_TWO to the bounds of the term. */
+
+static tree
+type_for_clast_term (struct clast_term *t, ivs_params_p ip, mpz_t bound_one,
+ mpz_t bound_two)
+{
+ clast_name_p name = t->var;
+ bool found = false;
+
+ gcc_assert (t->expr.type == clast_expr_term);
+
+ if (!name)
+ {
+ mpz_set (bound_one, t->val);
+ mpz_set (bound_two, t->val);
+ return type_for_value (t->val);
+ }
+
+ if (ip->params && ip->params_index)
+ found = clast_name_to_lb_ub (name, ip->params_index, bound_one, bound_two);
+
+ if (!found)
+ {
+ gcc_assert (*(ip->newivs) && ip->newivs_index);
+ found = clast_name_to_lb_ub (name, ip->newivs_index,
+ bound_one, bound_two);
+ gcc_assert (found);
+ }
+
+ mpz_mul (bound_one, bound_one, t->val);
+ mpz_mul (bound_two, bound_two, t->val);
+
+ return TREE_TYPE (clast_name_to_gcc (name, ip));
+}
+
+static tree
+type_for_clast_expr (struct clast_expr *, ivs_params_p, mpz_t, mpz_t);
+
+/* Return the type for the clast_reduction R. Initializes BOUND_ONE
+ and BOUND_TWO to the bounds of the reduction expression. */
+
+static tree
+type_for_clast_red (struct clast_reduction *r, ivs_params_p ip,
+ mpz_t bound_one, mpz_t bound_two)
+{
+ int i;
+ tree type = type_for_clast_expr (r->elts[0], ip, bound_one, bound_two);
+ mpz_t b1, b2, m1, m2;
+
+ if (r->n == 1)
+ return type;
+
+ mpz_init (b1);
+ mpz_init (b2);
+ mpz_init (m1);
+ mpz_init (m2);
+
+ for (i = 1; i < r->n; i++)
+ {
+ tree t = type_for_clast_expr (r->elts[i], ip, b1, b2);
+ type = max_precision_type (type, t);
+
+ switch (r->type)
+ {
+ case clast_red_sum:
+ value_min (m1, bound_one, bound_two);
+ value_min (m2, b1, b2);
+ mpz_add (bound_one, m1, m2);
+
+ value_max (m1, bound_one, bound_two);
+ value_max (m2, b1, b2);
+ mpz_add (bound_two, m1, m2);
+ break;
+
+ case clast_red_min:
+ value_min (bound_one, bound_one, bound_two);
+ value_min (bound_two, b1, b2);
+ break;
+
+ case clast_red_max:
+ value_max (bound_one, bound_one, bound_two);
+ value_max (bound_two, b1, b2);
+ break;
+
+ default:
+ gcc_unreachable ();
+ break;
+ }
+ }
+
+ mpz_clear (b1);
+ mpz_clear (b2);
+ mpz_clear (m1);
+ mpz_clear (m2);
+
+ /* Return a type that can represent the result of the reduction. */
+ return max_precision_type (type, type_for_interval (bound_one, bound_two));
+}
+
+/* Return the type for the clast_binary B used in STMT. */
+
+static tree
+type_for_clast_bin (struct clast_binary *b, ivs_params_p ip, mpz_t bound_one,
+ mpz_t bound_two)
+{
+ mpz_t one;
+ tree l = type_for_clast_expr ((struct clast_expr *) b->LHS, ip,
+ bound_one, bound_two);
+ tree r = type_for_value (b->RHS);
+ tree type = max_precision_type (l, r);
+
+ switch (b->type)
+ {
+ case clast_bin_fdiv:
+ mpz_mdiv (bound_one, bound_one, b->RHS);
+ mpz_mdiv (bound_two, bound_two, b->RHS);
+ break;
+
+ case clast_bin_cdiv:
+ mpz_mdiv (bound_one, bound_one, b->RHS);
+ mpz_mdiv (bound_two, bound_two, b->RHS);
+ mpz_init (one);
+ mpz_add (bound_one, bound_one, one);
+ mpz_add (bound_two, bound_two, one);
+ mpz_clear (one);
+ break;
+
+ case clast_bin_div:
+ mpz_div (bound_one, bound_one, b->RHS);
+ mpz_div (bound_two, bound_two, b->RHS);
+ break;
+
+ case clast_bin_mod:
+ mpz_mod (bound_one, bound_one, b->RHS);
+ mpz_mod (bound_two, bound_two, b->RHS);
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ /* Return a type that can represent the result of the reduction. */
+ return max_precision_type (type, type_for_interval (bound_one, bound_two));
+}
+
+/* Returns the type for the CLAST expression E when used in statement
+ STMT. */
+
+static tree
+type_for_clast_expr (struct clast_expr *e, ivs_params_p ip, mpz_t bound_one,
+ mpz_t bound_two)
+{
+ switch (e->type)
+ {
+ case clast_expr_term:
+ return type_for_clast_term ((struct clast_term *) e, ip,
+ bound_one, bound_two);
+
+ case clast_expr_red:
+ return type_for_clast_red ((struct clast_reduction *) e, ip,
+ bound_one, bound_two);
+
+ case clast_expr_bin:
+ return type_for_clast_bin ((struct clast_binary *) e, ip,
+ bound_one, bound_two);