Skip to content

Commit 2cdc8ec

Browse files
committed
Updates parser and type checking to handle ranges
We now support ranges on code contracts when specifiying which portions of an array should or should not change. We update the parser and type checking to support this new annotations within assigns clauses. Signed-off-by: Felipe R. Monteiro <[email protected]>
1 parent 2c7d136 commit 2cdc8ec

File tree

4 files changed

+109
-1
lines changed

4 files changed

+109
-1
lines changed

src/ansi-c/c_typecheck_base.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ class c_typecheck_baset:
168168
virtual void typecheck_expr_operands(exprt &expr);
169169
virtual void typecheck_expr_comma(exprt &expr);
170170
virtual void typecheck_expr_constant(exprt &expr);
171+
virtual void typecheck_expr_range(exprt &expr);
171172
virtual void typecheck_expr_side_effect(side_effect_exprt &expr);
172173
virtual void typecheck_expr_unary_arithmetic(exprt &expr);
173174
virtual void typecheck_expr_unary_boolean(exprt &expr);

src/ansi-c/c_typecheck_expr.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,10 @@ void c_typecheck_baset::typecheck_expr_main(exprt &expr)
491491
{
492492
// already type checked
493493
}
494+
else if(expr.id() == ID_range)
495+
{
496+
typecheck_expr_range(expr);
497+
}
494498
else
495499
{
496500
error().source_location = expr.source_location();
@@ -499,6 +503,16 @@ void c_typecheck_baset::typecheck_expr_main(exprt &expr)
499503
}
500504
}
501505

506+
void c_typecheck_baset::typecheck_expr_range(exprt &expr)
507+
{
508+
// Already type checked
509+
exprt &lower = to_range_exprt(expr).op0();
510+
exprt &upper = to_range_exprt(expr).op1();
511+
512+
implicit_typecast_arithmetic(lower);
513+
implicit_typecast_arithmetic(upper);
514+
}
515+
502516
void c_typecheck_baset::typecheck_expr_comma(exprt &expr)
503517
{
504518
expr.type() = to_binary_expr(expr).op1().type();

src/ansi-c/parser.y

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ extern char *yyansi_ctext;
101101
%token TOK_NE "!="
102102
%token TOK_ANDAND "&&"
103103
%token TOK_OROR "||"
104+
%token TOK_RANGE ".."
104105
%token TOK_ELLIPSIS "..."
105106

106107
/*** modifying assignment operators ***/
@@ -532,15 +533,62 @@ target_list:
532533
;
533534

534535
target:
536+
deref_target
537+
| target '[' array_index ']'
538+
{ binary($$, $1, $2, ID_range, $3); }
539+
| target '[' array_range ']'
540+
{ binary($$, $1, $2, ID_range, $3); }
541+
;
542+
543+
array_index:
535544
identifier
536-
| '*' target
545+
| integer
546+
;
547+
548+
array_range:
549+
array_index ',' array_index
550+
{
551+
$$=$2;
552+
set($$, ID_range);
553+
mto($$, $1);
554+
mto($$, $3);
555+
}
556+
;
557+
558+
deref_target:
559+
member_target
560+
| '*' deref_target
537561
{
538562
$$=$1;
539563
set($$, ID_dereference);
540564
mto($$, $2);
541565
}
542566
;
543567

568+
member_target:
569+
primary_target
570+
| member_target '.' member_name
571+
{
572+
$$=$2;
573+
set($$, ID_member);
574+
mto($$, $1);
575+
parser_stack($$).set(ID_component_name, parser_stack($3).get(ID_C_base_name));
576+
}
577+
| member_target TOK_ARROW member_name
578+
{
579+
$$=$2;
580+
set($$, ID_ptrmember);
581+
mto($$, $1);
582+
parser_stack($$).set(ID_component_name, parser_stack($3).get(ID_C_base_name));
583+
}
584+
;
585+
586+
primary_target:
587+
identifier
588+
| '(' target ')'
589+
{ $$ = $2; }
590+
;
591+
544592
statement_expression: '(' compound_statement ')'
545593
{
546594
$$=$1;

src/util/std_expr.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -824,6 +824,51 @@ inline multi_ary_exprt &to_multi_ary_expr(exprt &expr)
824824
return static_cast<multi_ary_exprt &>(expr);
825825
}
826826

827+
/// \brief A base class for int-range expressions
828+
class range_exprt : public expr_protectedt
829+
{
830+
public:
831+
range_exprt(exprt &lower, exprt &upper, typet _type)
832+
: expr_protectedt(
833+
ID_range,
834+
std::move(_type),
835+
{std::move(lower), std::move(upper)})
836+
{
837+
}
838+
839+
// make op0 and op1 public
840+
using exprt::op0;
841+
using exprt::op1;
842+
843+
const exprt &op2() const = delete;
844+
exprt &op2() = delete;
845+
const exprt &op3() const = delete;
846+
exprt &op3() = delete;
847+
};
848+
849+
/// \brief Cast an exprt to a \ref range_exprt
850+
///
851+
/// \a expr must be known to be \ref range_exprt.
852+
///
853+
/// \param expr: Source expression
854+
/// \return Object of type \ref range_exprt
855+
inline const range_exprt &to_range_exprt(const exprt &expr)
856+
{
857+
PRECONDITION(expr.id() == ID_range);
858+
return static_cast<const range_exprt &>(expr);
859+
}
860+
861+
/// \brief Cast an exprt to a \ref range_exprt
862+
///
863+
/// \a expr must be known to be \ref range_exprt.
864+
///
865+
/// \param expr: Source expression
866+
/// \return Object of type \ref range_exprt
867+
inline range_exprt &to_range_exprt(exprt &expr)
868+
{
869+
PRECONDITION(expr.id() == ID_range);
870+
return static_cast<range_exprt &>(expr);
871+
}
827872

828873
/// \brief The plus expression
829874
/// Associativity is not specified.

0 commit comments

Comments
 (0)