Skip to content

Commit

Permalink
fixes and docs
Browse files Browse the repository at this point in the history
  • Loading branch information
thradams committed Apr 22, 2024
1 parent 7727cd3 commit 09ca439
Show file tree
Hide file tree
Showing 155 changed files with 7,366 additions and 6,515 deletions.
92 changes: 92 additions & 0 deletions ownership.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,99 @@ int main()

<button onclick="Try(this)">try</button>

When \_Opt qualifier is aplied to structs it makes all member \_Opt.
For instance:

```c
#pragma nullable enable

void free(void * _Opt p);
char * _Opt strdup();

void print_name(const char* name);

struct X {
char * name;
};

void use_x(struct X * p)
{
//p->name is non-nullable here
print_name(p->name);
}

void x_destroy(_Opt struct X * p)
{
//p->name is nullable here
free(p); //free accepts null
}

int main()
{
_Opt struct X x = {0};
char * _Opt temp = strdup();
if (temp)
{
x.name = temp;
use_x(&x);
}
x_destroy(&x);
}

```
<button onclick="Try(this)">try</button>
This can be used to implement destructors where the object can be partially
constructed in case of some error.
For other functions, like use_x, the object must be completely constructed, and in this case, name must not be null.
Currently cake is not checkin nullable at initialization.
```c
struct X x = {0}; //no complaing about name being null
```

This allows a initialization in multiple steps.

```c
use_x(&x); //warning name is null
```
```c
#pragma nullable enable
void free(void * _Opt p);
char * _Opt strdup();
void print_name(const char* name);
struct X {
char * name;
};
void use_x(struct X * p)
{
//p->name is non-nullable here
print_name(p->name);
}
void x_destroy(_Opt struct X * p)
{
//p->name is nullable here
free(p); //free accepts nullable p
}
int main()
{
struct X x = {0};
use_x(&x);
x_destroy(&x);
}
```

<button onclick="Try(this)">try</button>

### Owner References

Expand Down
41 changes: 40 additions & 1 deletion src/expressions.c
Original file line number Diff line number Diff line change
Expand Up @@ -1358,7 +1358,27 @@ struct object* expression_get_object(struct expression* p_expression, struct obj
}
else if (p_expression->expression_type == CAST_EXPRESSION)
{
return expression_get_object(p_expression->left, p_object, nullable_enabled);

struct object* p = expression_get_object(p_expression->left, p_object, nullable_enabled);
if (p)
{
if (type_is_pointer(&p_expression->type_name->type))
{
//casting from 0 to pointer we need to change the zero to null
//#define NULL ((void*)0)
if (p->state & OBJECT_STATE_ZERO)
{
p->state &= ~ OBJECT_STATE_ZERO;
p->state |= OBJECT_STATE_NULL;
}
if (p->state & OBJECT_STATE_NOT_ZERO)
{
p->state &= ~ OBJECT_STATE_NOT_ZERO;
p->state |= OBJECT_STATE_NOT_NULL;
}
}
}
return p;
}
else if (p_expression->expression_type == POSTFIX_DOT)
{
Expand Down Expand Up @@ -1511,6 +1531,25 @@ struct object* expression_get_object(struct expression* p_expression, struct obj
//
return p_obj;
}
else if (p_expression->expression_type == CONDITIONAL_EXPRESSION)
{
struct object o = make_object(&p_expression->type, NULL, p_expression);
struct object obj1 = { 0 };
struct object* p_obj1 = expression_get_object(p_expression->left, &obj1, nullable_enabled);

struct object obj2 = { 0 };
struct object* p_obj2 = expression_get_object(p_expression->right, &obj2, nullable_enabled);


object_merge_state(&o, p_obj1, p_obj2);
object_swap(p_object, &o);

object_destroy(&o);
object_destroy(&obj1);
object_destroy(&obj2);

return p_object;
}
else if (p_expression->expression_type == EQUALITY_EXPRESSION_EQUAL ||
p_expression->expression_type == EQUALITY_EXPRESSION_NOT_EQUAL)
{
Expand Down
147 changes: 54 additions & 93 deletions src/flow_visit.c
Original file line number Diff line number Diff line change
Expand Up @@ -1152,6 +1152,12 @@ static void pop_states(struct flow_visit_ctx* ctx, int n)
static void flow_visit_initializer(struct flow_visit_ctx* ctx, struct initializer* p_initializer);
static void flow_visit_declarator(struct flow_visit_ctx* ctx, struct declarator* p_declarator);

static void braced_initializer_set_object(struct braced_initializer* p, struct type* type, struct object* object)
{
if (p->initializer_list == NULL) {}
//TODO currently it is zero
object_set_zero(type, object);
}

static void flow_visit_init_declarator_new(struct flow_visit_ctx* ctx, struct init_declarator* p_init_declarator)
{
Expand Down Expand Up @@ -1192,17 +1198,19 @@ static void flow_visit_init_declarator_new(struct flow_visit_ctx* ctx, struct in
struct object* p_right_object =
expression_get_object(p_init_declarator->initializer->assignment_expression, &temp_obj, nullable_enabled);

object_assignment3(ctx->ctx,
p_init_declarator->initializer->assignment_expression->first_token,
ASSIGMENT_TYPE_OBJECTS,
false,
type_is_view(&p_init_declarator->p_declarator->type),
type_is_nullable(&p_init_declarator->p_declarator->type, ctx->ctx->options.null_checks_enabled),
&p_init_declarator->p_declarator->type,
&p_init_declarator->p_declarator->object,
&p_init_declarator->initializer->assignment_expression->type,
p_right_object);

if (p_right_object)
{
object_assignment3(ctx->ctx,
p_init_declarator->initializer->assignment_expression->first_token,
ASSIGMENT_TYPE_OBJECTS,
false,
type_is_view(&p_init_declarator->p_declarator->type),
type_is_nullable(&p_init_declarator->p_declarator->type, ctx->ctx->options.null_checks_enabled),
&p_init_declarator->p_declarator->type,
&p_init_declarator->p_declarator->object,
&p_init_declarator->initializer->assignment_expression->type,
p_right_object);
}
//cast?
if (expression_is_malloc(p_init_declarator->initializer->assignment_expression))
{
Expand All @@ -1215,15 +1223,10 @@ p_right_object);
type_destroy(&t);
p_init_declarator->p_declarator->object.state = OBJECT_STATE_NOT_NULL | OBJECT_STATE_NULL;
objects_push_back(&ctx->arena, po);



}
else if (expression_is_calloc(p_init_declarator->initializer->assignment_expression))
{
struct object* owner po = calloc(1, sizeof * po);


struct type t = type_remove_pointer(&p_init_declarator->p_declarator->type);
struct object o = make_object(&t, p_init_declarator->p_declarator, NULL);
object_set_zero(&t, &o);
Expand All @@ -1234,105 +1237,63 @@ p_right_object);
p_init_declarator->p_declarator->object.state = OBJECT_STATE_NOT_NULL | OBJECT_STATE_NULL;
objects_push_back(&ctx->arena, po);
}
#if 0
else
{
const struct token* const token_position =
p_init_declarator->p_declarator->name ?
p_init_declarator->p_declarator->name :
p_init_declarator->p_declarator->first_token
;

if (p_right_object)
{
object_assignment3(ctx->ctx,
token_position,
ASSIGMENT_TYPE_OBJECTS,
false,
type_is_view(&p_init_declarator->p_declarator->type),
type_is_nullable(&p_init_declarator->p_declarator->type, ctx->ctx->options.null_checks_enabled),
&p_init_declarator->p_declarator->type,
&p_init_declarator->p_declarator->object,
&p_init_declarator->initializer->assignment_expression->type,
p_right_object

);
}
else
{
//provisory handling too deep -> -> -> indirection
const bool is_nullable = type_is_nullable(&p_init_declarator->p_declarator->type, nullable_enabled);
object_set_unknown(&p_init_declarator->p_declarator->type,
is_nullable,
&p_init_declarator->p_declarator->object,
nullable_enabled);
}

}
#endif
object_destroy(&temp_obj);
}
else if (p_init_declarator->initializer &&
p_init_declarator->initializer->braced_initializer)
{
bool is_zero_initialized = false;
if (p_init_declarator->initializer->braced_initializer->initializer_list == NULL)
{
is_zero_initialized = true;
}
else
{
if (p_init_declarator->initializer->braced_initializer->initializer_list->size == 1 &&
p_init_declarator->initializer->braced_initializer->initializer_list->head->assignment_expression)
{
struct constant_value* p_constant_value =
&p_init_declarator->initializer->braced_initializer->initializer_list->head->assignment_expression->constant_value;

if (constant_value_is_valid(p_constant_value) &&
constant_value_to_ull(p_constant_value) == 0)
{
is_zero_initialized = true;
}
struct object o = make_object(&p_init_declarator->p_declarator->type, p_init_declarator->p_declarator, NULL);

}
}
braced_initializer_set_object(p_init_declarator->initializer->braced_initializer,
&p_init_declarator->p_declarator->type,
&o);

if (is_zero_initialized)
{
object_set_zero(&p_init_declarator->p_declarator->type, &p_init_declarator->p_declarator->object);
}
else
{
object_set_zero(&p_init_declarator->p_declarator->type, &p_init_declarator->p_declarator->object);
}
struct object* p_right_object = &o;
object_assignment3(ctx->ctx,
p_init_declarator->p_declarator->first_token,
ASSIGMENT_TYPE_OBJECTS,
false,
type_is_view(&p_init_declarator->p_declarator->type),
type_is_nullable(&p_init_declarator->p_declarator->type, ctx->ctx->options.null_checks_enabled),
&p_init_declarator->p_declarator->type,
&p_init_declarator->p_declarator->object,
&p_init_declarator->p_declarator->type,
p_right_object);
object_destroy(&o);
}
else
{
struct object o = make_object(&p_init_declarator->p_declarator->type, p_init_declarator->p_declarator, NULL);

if (p_init_declarator->p_declarator->declaration_specifiers &&
(
(p_init_declarator->p_declarator->declaration_specifiers->storage_class_specifier_flags & STORAGE_SPECIFIER_EXTERN) ||
(p_init_declarator->p_declarator->declaration_specifiers->storage_class_specifier_flags & STORAGE_SPECIFIER_STATIC)
)
)
{
object_set_zero(&p_init_declarator->p_declarator->type, &p_init_declarator->p_declarator->object);
object_set_zero(&p_init_declarator->p_declarator->type, &o);
}
else
{
object_set_uninitialized(&p_init_declarator->p_declarator->type, &p_init_declarator->p_declarator->object);
object_set_uninitialized(&p_init_declarator->p_declarator->type, &o);
}



}
}


//if (p_init_declarator->initializer)
// flow_visit_initializer(ctx, p_init_declarator->initializer);

//if (p_init_declarator->p_declarator)
// flow_visit_declarator(ctx, p_init_declarator->p_declarator);
struct object* p_right_object = &o;
object_assignment3(ctx->ctx,
p_init_declarator->p_declarator->first_token,
ASSIGMENT_TYPE_OBJECTS,
false,
type_is_view(&p_init_declarator->p_declarator->type),
type_is_nullable(&p_init_declarator->p_declarator->type, ctx->ctx->options.null_checks_enabled),
&p_init_declarator->p_declarator->type,
&p_init_declarator->p_declarator->object,
&p_init_declarator->p_declarator->type,
p_right_object);
object_destroy(&o);
}
}

}


Expand Down
Loading

0 comments on commit 09ca439

Please sign in to comment.