Skip to content

Fix support for mathematical types #8324

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions regression/cbmc/real-assignments1/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
int main()
{
__CPROVER_real a, b;
a = 0;
b = a;
b++;
b *= 100;
__CPROVER_assert(0, "");
}
7 changes: 7 additions & 0 deletions regression/cbmc/real-assignments1/test.desc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
CORE smt-backend broken-cprover-smt-backend no-new-smt
main.c
--trace --smt2
^EXIT=10$
^SIGNAL=0$
^ b=100 \(0b1100100\)$
--
8 changes: 8 additions & 0 deletions regression/cbmc/real-assignments1/typecheck.desc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
CORE
main.c
--show-goto-functions
^[[:space:]]*ASSIGN main::1::b := main::1::b \* cast\(100, ℝ\)$
^EXIT=0$
^SIGNAL=0$
--
^[[:space:]]*ASSIGN main::1::b := main::1::b \* 100$
2 changes: 2 additions & 0 deletions src/ansi-c/ansi_c_internal_additions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,9 @@ void ansi_c_internal_additions(std::string &code, bool support_float16_type)
" " CPROVER_PREFIX "ssize_t;\n"
"const unsigned " CPROVER_PREFIX "constant_infinity_uint;\n"
"typedef void " CPROVER_PREFIX "integer;\n"
"typedef void " CPROVER_PREFIX "natural;\n"
"typedef void " CPROVER_PREFIX "rational;\n"
"typedef void " CPROVER_PREFIX "real;\n"
"extern unsigned char " CPROVER_PREFIX "memory["
CPROVER_PREFIX "constant_infinity_uint];\n"

Expand Down
48 changes: 23 additions & 25 deletions src/ansi-c/c_typecast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,29 +102,23 @@ bool check_c_implicit_typecast(

if(src_type_id==ID_natural)
{
if(dest_type.id()==ID_bool ||
dest_type.id()==ID_c_bool ||
dest_type.id()==ID_integer ||
dest_type.id()==ID_real ||
dest_type.id()==ID_complex ||
dest_type.id()==ID_unsignedbv ||
dest_type.id()==ID_signedbv ||
dest_type.id()==ID_floatbv ||
dest_type.id()==ID_complex)
if(
dest_type.id() == ID_bool || dest_type.id() == ID_c_bool ||
dest_type.id() == ID_integer || dest_type.id() == ID_rational ||
dest_type.id() == ID_real || dest_type.id() == ID_complex ||
dest_type.id() == ID_unsignedbv || dest_type.id() == ID_signedbv ||
dest_type.id() == ID_floatbv || dest_type.id() == ID_complex)
return false;
}
else if(src_type_id==ID_integer)
{
if(dest_type.id()==ID_bool ||
dest_type.id()==ID_c_bool ||
dest_type.id()==ID_real ||
dest_type.id()==ID_complex ||
dest_type.id()==ID_unsignedbv ||
dest_type.id()==ID_signedbv ||
dest_type.id()==ID_floatbv ||
dest_type.id()==ID_fixedbv ||
dest_type.id()==ID_pointer ||
dest_type.id()==ID_complex)
if(
dest_type.id() == ID_bool || dest_type.id() == ID_c_bool ||
dest_type.id() == ID_rational || dest_type.id() == ID_real ||
dest_type.id() == ID_complex || dest_type.id() == ID_unsignedbv ||
dest_type.id() == ID_signedbv || dest_type.id() == ID_floatbv ||
dest_type.id() == ID_fixedbv || dest_type.id() == ID_pointer ||
dest_type.id() == ID_complex)
return false;
}
else if(src_type_id==ID_real)
Expand All @@ -139,12 +133,11 @@ bool check_c_implicit_typecast(
}
else if(src_type_id==ID_rational)
{
if(dest_type.id()==ID_bool ||
dest_type.id()==ID_c_bool ||
dest_type.id()==ID_complex ||
dest_type.id()==ID_floatbv ||
dest_type.id()==ID_fixedbv ||
dest_type.id()==ID_complex)
if(
dest_type.id() == ID_bool || dest_type.id() == ID_c_bool ||
dest_type.id() == ID_real || dest_type.id() == ID_complex ||
dest_type.id() == ID_floatbv || dest_type.id() == ID_fixedbv ||
dest_type.id() == ID_complex)
return false;
}
else if(src_type_id==ID_bool)
Expand Down Expand Up @@ -415,6 +408,8 @@ c_typecastt::c_typet c_typecastt::get_c_type(
}
else if(type.id() == ID_integer)
return INTEGER;
else if(type.id() == ID_natural)
return NATURAL;

return OTHER;
}
Expand Down Expand Up @@ -454,6 +449,9 @@ void c_typecastt::implicit_typecast_arithmetic(
case RATIONAL: new_type=rational_typet(); break;
case REAL: new_type=real_typet(); break;
case INTEGER: new_type=integer_typet(); break;
case NATURAL:
new_type = natural_typet();
break;
case COMPLEX:
case OTHER:
case VOIDPTR:
Expand Down
42 changes: 29 additions & 13 deletions src/ansi-c/c_typecast.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,19 +75,35 @@ class c_typecastt

// these are in promotion order

enum c_typet { BOOL,
CHAR, UCHAR,
SHORT, USHORT,
INT, UINT,
LONG, ULONG,
LONGLONG, ULONGLONG,
LARGE_SIGNED_INT, LARGE_UNSIGNED_INT,
INTEGER, // these are unbounded integers, non-standard
FIXEDBV, // fixed-point, non-standard
SINGLE, DOUBLE, LONGDOUBLE, FLOAT128, // float
RATIONAL, REAL, // infinite precision, non-standard
COMPLEX,
VOIDPTR, PTR, OTHER };
enum c_typet
{
BOOL,
CHAR,
UCHAR,
SHORT,
USHORT,
INT,
UINT,
LONG,
ULONG,
LONGLONG,
ULONGLONG,
LARGE_SIGNED_INT,
LARGE_UNSIGNED_INT,
INTEGER, // these are unbounded integers, non-standard
NATURAL, // these are unbounded natural numbers, non-standard
FIXEDBV, // fixed-point, non-standard
SINGLE,
DOUBLE,
LONGDOUBLE,
FLOAT128, // float
RATIONAL,
REAL, // infinite precision, non-standard
COMPLEX,
VOIDPTR,
PTR,
OTHER
};

c_typet get_c_type(const typet &type) const;

Expand Down
8 changes: 8 additions & 0 deletions src/ansi-c/c_typecheck_type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1626,6 +1626,14 @@ void c_typecheck_baset::typecheck_typedef_type(typet &type)
{
type=integer_typet();
}
else if(symbol.base_name == CPROVER_PREFIX "natural")
{
type = natural_typet();
}
else if(symbol.base_name == CPROVER_PREFIX "real")
{
type = real_typet();
}
}

void c_typecheck_baset::adjust_function_parameter(typet &type) const
Expand Down
16 changes: 7 additions & 9 deletions src/ansi-c/expr2c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -246,11 +246,11 @@ std::string expr2ct::convert_rec(
{
return q + CPROVER_PREFIX + "string" + d;
}
else if(src.id()==ID_natural ||
src.id()==ID_integer ||
src.id()==ID_rational)
else if(
src.id() == ID_natural || src.id() == ID_integer ||
src.id() == ID_rational || src.id() == ID_real)
{
return q+src.id_string()+d;
return q + CPROVER_PREFIX + src.id_string() + d;
}
else if(src.id()==ID_empty)
{
Expand Down Expand Up @@ -1780,9 +1780,9 @@ std::string expr2ct::convert_constant(
const irep_idt value=src.get_value();
std::string dest;

if(type.id()==ID_integer ||
type.id()==ID_natural ||
type.id()==ID_rational)
if(
type.id() == ID_integer || type.id() == ID_natural ||
type.id() == ID_rational || type.id() == ID_real)
{
dest=id2string(value);
}
Expand Down Expand Up @@ -1821,8 +1821,6 @@ std::string expr2ct::convert_constant(
else
return "/*enum*/" + value_as_string;
}
else if(type.id()==ID_rational)
return convert_norep(src, precedence);
else if(type.id()==ID_bv)
{
// not C
Expand Down
1 change: 1 addition & 0 deletions src/util/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ SRC = arith_tools.cpp \
prefix_filter.cpp \
rational.cpp \
rational_tools.cpp \
real.cpp \
ref_expr_set.cpp \
refined_string_type.cpp \
rename.cpp \
Expand Down
2 changes: 1 addition & 1 deletion src/util/arith_tools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ constant_exprt from_integer(
{
const irep_idt &type_id=type.id();

if(type_id==ID_integer)
if(type_id == ID_integer || type_id == ID_rational || type_id == ID_real)
{
return constant_exprt(integer2string(int_value), type);
}
Expand Down
2 changes: 2 additions & 0 deletions src/util/format_type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ std::ostream &format_rec(std::ostream &os, const typet &type)
return os << "\xe2\x84\x95"; // u+2115, 'N'
else if(id == ID_rational)
return os << "\xe2\x84\x9a"; // u+211A, 'Q'
else if(id == ID_real)
return os << "\xe2\x84\x9d"; // u+211D, 'R'
else if(id == ID_mathematical_function)
{
const auto &mathematical_function = to_mathematical_function_type(type);
Expand Down
23 changes: 23 additions & 0 deletions src/util/real.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*******************************************************************\

Module: Real Numbers

Author: Michael Tautschnig

\*******************************************************************/

/// \file
/// Real Numbers

#include "real.h"

realt &realt::operator-()
{
integral.negate();
return *this;
}

std::ostream &operator<<(std::ostream &out, const realt &a)
{
return out << a.get_integral() << '.' << a.get_fractional();
}
53 changes: 53 additions & 0 deletions src/util/real.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*******************************************************************\

Module: Real Numbers

Author: Michael Tautschnig

\*******************************************************************/

#ifndef CPROVER_UTIL_REAL_H
#define CPROVER_UTIL_REAL_H

#include "mp_arith.h"

class realt
{
protected:
mp_integer integral, fractional;

public:
// constructors
realt() : integral(0), fractional(0)
{
}
explicit realt(const mp_integer &i) : integral(i), fractional(0)
{
}

realt &operator-();

bool operator==(const realt &n) const
{
return integral == n.integral && fractional == n.fractional;
}

bool operator!=(const realt &n) const
{
return integral != n.integral || fractional != n.fractional;
}

const mp_integer &get_integral() const
{
return integral;
}

const mp_integer &get_fractional() const
{
return fractional;
}
};

std::ostream &operator<<(std::ostream &out, const realt &a);

#endif // CPROVER_UTIL_REAL_H
15 changes: 10 additions & 5 deletions src/util/simplify_expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1035,11 +1035,11 @@ simplify_exprt::simplify_typecast(const typecast_exprt &expr)
return make_boolean_expr(int_value != 0);
}

if(expr_type_id==ID_unsignedbv ||
expr_type_id==ID_signedbv ||
expr_type_id==ID_c_enum ||
expr_type_id==ID_c_bit_field ||
expr_type_id==ID_integer)
if(
expr_type_id == ID_unsignedbv || expr_type_id == ID_signedbv ||
expr_type_id == ID_c_enum || expr_type_id == ID_c_bit_field ||
expr_type_id == ID_integer || expr_type_id == ID_natural ||
expr_type_id == ID_rational || expr_type_id == ID_real)
{
return from_integer(int_value, expr_type);
}
Expand Down Expand Up @@ -1189,6 +1189,11 @@ simplify_exprt::simplify_typecast(const typecast_exprt &expr)
rationalt r(int_value);
return from_rational(r);
}

if(expr_type_id == ID_real)
{
return from_integer(int_value, expr_type);
}
}
else if(op_type_id==ID_fixedbv)
{
Expand Down
Loading