Commit 36df4cf5 authored by Sergio Costas's avatar Sergio Costas

Merge branch 'remove_alias'

parents 7d0c0eef 4af21b89
......@@ -14,7 +14,7 @@ The tags are automagically removed by the C Preprocessor, so
they are completely transparent to the compiler. That also
means that there are no fancy libraries, runtimes or expandable
macros: the source code is just standard, plain C. The tags just
serve to annotate specific information for the CRUST preprocessor,
allows to annotate specific information for the CRUST preprocessor,
but they aren't used during compilation.
It can be useful for projects where RUST is not feasible, like
......@@ -166,11 +166,12 @@ it must be stored in a CRUST *borrowed* variable.
Every time a CRUST variable is passed as an argument to a function, the
ownership is passed too, so, from that point, it will be in the FREED
state inside the calling function because it is assumed that the block
has been freed in the called function. There is an exception, and it is
when the argument in the called function is marked as *borrowed*. In that
case, the called function can't free the block, but can modify it, because
the ownership is retained in the caller function.
state inside the calling function until it is assigned a new block,
because it is assumed that the block has been freed in the called
function. There is an exception, and it is when the argument in the
called function is marked as *borrowed*. In that case, the called
function can't free the block, but can modify it, because the
ownership is retained in the caller function.
Trying to use a CRUST variable that is in UNINITIALIZED or FREED status is
an error, either using it as an argument when calling a function or accessing
......@@ -180,10 +181,22 @@ dangling pointer).
Global variables are an special case: since it is not possible to know
its state (because it can be changed outside the current function), they
are assumed to be in NOT_NULL_OR_NULL status when used as the origin, and
in UNINITIALIZED status when used as the destination. But it is important
to remember that assigning a CRUST variable to a global CRUST variable will
mark the former as FREED.
are assumed to be in NOT_NULL_OR_NULL status by default, and it is checked
at exit that they are in NOT_NULL, NULL or NOT_NULL_OR_NULL state (
never in FREED or UNINITIALIZED state). Assigning a CRUST variable to a global
variable is allowed, and the variable will not be marked as freed, but the
global variable will work like an alias variable (this is: freeing the
block pointed by a local variable copied in a global variable will result
in the global variable being also freed). It is possible to have several global
variables pointing to the same block during the life of the function.
When the execution reaches the end of the function all variables are checked.
It is an error to reach the end with CRUST variables in NOT_NULL or
NOT_NULL_OR_NULL state. There is an exception: when a local variable has been
copied to a global variable, it is not needed to free it. But at the end
of the execution, each block pointed by global variables must be pointed by
only one global variable (it is an error to reach the end of the function
and have two or more global variables pointing to the same block).
CRUST understand some comparisons, so this code:
......
This diff is collapsed.
This diff is collapsed.
......@@ -34,6 +34,7 @@ void main() {
crust_t param1 = NULL;
crust_t param2 = (crust_t) "hello world";
crust_t param3 = NULL;
__crust_debug__
calling6(param2->member);
......
......@@ -2,9 +2,14 @@ typedef __crust_t__ unsigned char *crust_t;
#define NULL ((void *)0)
crust_t global_var1;
crust_t global1;
void function2(crust_t param);
void function(crust_t param3) {
void function(crust_t param) {
global_var1 = param3; // It is fine: since we are storing the block from "param3" in a global variable, it is not a dangling pointer
if (global1 == NULL) {
global1 = param; // It is fine: since we are storing the block from "param3" in a global variable, it is not a dangling pointer
} else {
function2(param);
}
}
......@@ -21,6 +21,5 @@ void main(crust_t param1, crust_t param2) {
alias2->next = alias1; // All this is legal
__crust_debug__
}
__crust_disable__
}
......@@ -11,7 +11,6 @@ typedef struct {
crust_t function();
void main() {
tmp_struct data1;
tmp_struct data1 = 1; // to ensure that it is not NULL
data1.function_p = function; // This is legal
__crust_disable__
}
......@@ -7,6 +7,12 @@ crust_t global_var2;
void function(crust_t param1) {
global_var1 = param1; // It is fine: since we are storing the block from "param3" in a global variable, it is not a dangling pointer
global_var2 = param1; // ERROR: it is not allowed to assign the same block to several global variables
if ((global_var1 == NULL) && (global_var2 == NULL)) {
global_var1 = param1; // It is fine: since we are storing the block from "param3" in a global variable, it is not a dangling pointer
global_var2 = param1; // It is fine to assign the same block to several global variables
// Here param1 is not freed, but is OK because it is in a global variable
__crust_debug__
} else {
function(param1); // free param1 to avoid an error
}
}
......@@ -5,8 +5,16 @@ typedef __crust_t__ unsigned char *crust_t;
crust_t global_var1;
crust_t global_var2;
void function2(crust_t);
void function(crust_t param1) {
global_var1 = param1; // It is fine: since we are storing the block from "param3" in a global variable, it is not a dangling pointer
global_var2 = global_var1; // ERROR: it is not allowed to assign the same block to several global variables
if ((global_var1 == NULL) && (global_var2 == NULL)) {
global_var1 = param1; // It is fine: since we are storing the block from "param3" in a global variable, it is not a dangling pointer
global_var2 = global_var1; // It is fine to assign the same block to several global variables
// Here param1 is not freed, but is OK because it is in a global variable
__crust_debug__
} else {
function(param1); // free param1 to avoid an error
}
}
......@@ -5,8 +5,10 @@ crust_t *var2;
void function(void) {
if (var1 == NULL) {
__crust_debug__
var1 = (crust_t)var2;
__crust_debug__
var2++;
}
}
typedef __crust_t__ unsigned char *crust_t;
crust_t var1;
void function(crust_t);
void main(crust_t __crust_not_null__ arg1) {
if (var1 == NULL) {
var1 = arg1; // fine
__crust_debug__
arg1 = NULL; // It is fine because it has been assigned to a global variable
__crust_debug__
} else {
function(arg1);
}
}
typedef __crust_t__ unsigned char *crust_t;
crust_t var1;
void function(crust_t);
void main(crust_t __crust_not_null__ arg1) {
if (var1 == NULL) {
var1 = arg1;
}
function(arg1);
// ERROR: there is a global variable with FREED status at exit
}
typedef __crust_t__ unsigned char *crust_t;
crust_t var1;
crust_t var2;
void function(crust_t);
void main(crust_t __crust_not_null__ arg1) {
if ((var1 == NULL) && (var2 == NULL)) {
var1 = arg1;
var2 = arg1;
} else {
function(arg1);
}
__crust_debug__
// ERROR: there are two global variables pointing to the same block
}
typedef __crust_t__ unsigned char *crust_t;
struct {
char var1;
int var2;
} global_var;
void function(crust_t);
void main(crust_t __crust_not_null__ var) {
global_var.var1 = var; // this is fine
__crust_debug__
}
#define NULL ((void *)0)
__crust_t__ struct crust_t2 {
char var1;
int var2;
__crust_t__ struct crust_t2 *next;
};
void main(__crust_t__ struct crust_t2 *var) {
__crust_t__ struct crust_t2 *tmp;
for(; var != NULL; var = tmp) {
tmp = var->next;
}
}
#define NULL ((void *)0)
struct crust_ts {
char var1;
int var2;
struct crust_ts *next;
};
typedef __crust_t__ struct crust_ts* crust_t;
void function(crust_t var) {
crust_t tmp;
for(; var != NULL; var = tmp) {
tmp = var->next;
}
}
#define NULL ((void *)0)
struct crust_ts {
char var1;
int var2;
struct crust_ts *next;
};
typedef __crust_t__ struct crust_ts* crust_t;
void function2(crust_t);
void function(crust_t var) {
crust_t tmp;
for(; var != NULL; var = tmp) {
tmp = var->next;
function2(var);
}
}
typedef __crust_t__ unsigned char *crust_t;
int function(crust_t param1, crust_t param2) {
void function2(crust_t param);
void function(crust_t param1, crust_t param2) {
crust_t param3 = param1;
param3 = param2; // ERROR: param3 is overwriten by another variable without being NULL
__crust_disable__ // added here to ensure only one error per unitest
function2(param3);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment