Skip to content

Commit

Permalink
fix void*
Browse files Browse the repository at this point in the history
  • Loading branch information
thradams committed Apr 23, 2024
1 parent 28a070e commit 6eb39c4
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 31 deletions.
32 changes: 27 additions & 5 deletions ownership.md
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ Invoking a function `fclose` is analogous to assignment of the argument `f2`, re
Sample - Declaration of fopen and fclose

```c
FILE * _Owner _fopen( const char *filename, const char *mode );
FILE * _Owner _Opt fopen( const char *filename, const char *mode );
void fclose(FILE * _Owner p);
```
Expand Down Expand Up @@ -330,6 +330,28 @@ A **view reference** is an object referencing another object without managing it

**Rule:** The lifetime of the referenced object must be longer than the lifetime of the view reference.

Sample

```c
#pragma nullable enable
#pragma ownership enable

struct X
{
int i;
}
int main(){

struct X * _Opt p = nullptr;
{
struct X x = {};
p = &x;
}
p->i = 1; //warning
}
```
<button onclick="Try(this)">try</button>

The most common view references are pointers called **view pointers**.

The view qualifier is not necessary for pointers, since it's the default behavior.
Expand Down Expand Up @@ -495,7 +517,7 @@ void x_delete(struct X * _Owner _Opt p) {
}

int main() {
struct X * _Owner pX = calloc(1, sizeof * pX);
struct X * _Owner _Opt _pX = calloc(1, sizeof * pX);
if (pX) {
/*...*/;
x_delete( pX);
Expand All @@ -506,17 +528,17 @@ int main() {
<button onclick="Try(this)">try</button>
### Conversion from owner pointer to void * owner
### Conversion from `T * _Owner` to `void * _Owner`
**Rule:** Assignment or cast of a owner pointer to void * owner requires the pointed object to be empty.
**Rule:** Assignment or cast from `T * _Owner` to `void * _Owner` requires the pointed object T to be empty.
```c
#pragma nullable enable
#pragma ownership enable
struct X {
char _Owner text;
char * _Owner text;
};
struct X * _Owner make();
Expand Down
7 changes: 4 additions & 3 deletions src/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ struct X {
char *_Owner name;
};

void x_destroy(_Opt struct X * _Obj_owner x)
{
//free(x.name);
struct X * _Owner f();
int main(){
struct X * _Owner p = f();
void * _Owner p2 = p;
}
38 changes: 33 additions & 5 deletions src/lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -11359,6 +11359,9 @@ void end_of_storage_visit(struct parser_ctx* ctx,
const char* previous_names);


bool object_is_expansible(const struct object* p_object);



#if __STDC_VERSION__ >= 202311L
#define NODISCARD [[nodiscard]]
Expand Down Expand Up @@ -21230,6 +21233,15 @@ bool is_uninitialized(enum object_state e)
return (e & OBJECT_STATE_UNINITIALIZED);
}

/*
returns true if the pointer object can/should be expanded
*/
bool object_is_expansible(const struct object* p_object)
{
return (p_object->state != OBJECT_STATE_NULL &&
p_object->state != OBJECT_STATE_UNINITIALIZED &&
p_object->ref.size == 0);
}

void object_state_to_string(enum object_state e)
{
Expand Down Expand Up @@ -23946,7 +23958,7 @@ static void end_of_storage_visit_core(struct parser_ctx* ctx,
char buffer[100] = { 0 };
snprintf(buffer, sizeof buffer, "%s", previous_names);
struct type t2 = type_remove_pointer(p_type);

for (int i = 0; i < p_object->ref.size; i++)
{
end_of_storage_visit_core(ctx, &t2, b_type_is_view, p_object->ref.data[i], position, buffer, visit_number);
Expand Down Expand Up @@ -24156,17 +24168,33 @@ void object_assignment3(

if (!a_type_is_view && type_is_owner(p_a_type))
{
if (p_b_object->ref.size > 0)
//*b must be empty before copying to void* owner
struct type t = type_remove_pointer(p_b_type);

if (p_b_object->ref.size == 0)
{
// The question is..if we had this object expanded
// could it possible have resources?
//-> {...}
if (object_is_expansible(p_b_object) &&
type_is_owner(&t))
{
//if the anwser is yes then we need a warning
compiler_diagnostic_message(W_FLOW_MISSING_DTOR,
ctx,
error_position,
"pointed object may be not empty");
}
}
else
{
//*b must be empty before copying to void* owner
struct type t = type_remove_pointer(p_b_type);
for (int i = 0; i < p_b_object->ref.size; i++)
{
checked_empty(ctx, &t, p_b_object->ref.data[i], error_position);
object_set_deleted(&t, p_b_object->ref.data[i]);
}
type_destroy(&t);
}
type_destroy(&t);

if (assigment_type == ASSIGMENT_TYPE_PARAMETER)
{
Expand Down
35 changes: 30 additions & 5 deletions src/object.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,15 @@ bool is_uninitialized(enum object_state e)
return (e & OBJECT_STATE_UNINITIALIZED);
}

/*
returns true if the pointer object can/should be expanded
*/
bool object_is_expansible(const struct object* p_object)
{
return (p_object->state != OBJECT_STATE_NULL &&
p_object->state != OBJECT_STATE_UNINITIALIZED &&
p_object->ref.size == 0);
}

void object_state_to_string(enum object_state e)
{
Expand Down Expand Up @@ -2767,7 +2776,7 @@ static void end_of_storage_visit_core(struct parser_ctx* ctx,
char buffer[100] = { 0 };
snprintf(buffer, sizeof buffer, "%s", previous_names);
struct type t2 = type_remove_pointer(p_type);

for (int i = 0; i < p_object->ref.size; i++)
{
end_of_storage_visit_core(ctx, &t2, b_type_is_view, p_object->ref.data[i], position, buffer, visit_number);
Expand Down Expand Up @@ -2977,17 +2986,33 @@ void object_assignment3(

if (!a_type_is_view && type_is_owner(p_a_type))
{
if (p_b_object->ref.size > 0)
//*b must be empty before copying to void* owner
struct type t = type_remove_pointer(p_b_type);

if (p_b_object->ref.size == 0)
{
// The question is..if we had this object expanded
// could it possible have resources?
//-> {...}
if (object_is_expansible(p_b_object) &&
type_is_owner(&t))
{
//if the anwser is yes then we need a warning
compiler_diagnostic_message(W_FLOW_MISSING_DTOR,
ctx,
error_position,
"pointed object may be not empty");
}
}
else
{
//*b must be empty before copying to void* owner
struct type t = type_remove_pointer(p_b_type);
for (int i = 0; i < p_b_object->ref.size; i++)
{
checked_empty(ctx, &t, p_b_object->ref.data[i], error_position);
object_set_deleted(&t, p_b_object->ref.data[i]);
}
type_destroy(&t);
}
type_destroy(&t);

if (assigment_type == ASSIGMENT_TYPE_PARAMETER)
{
Expand Down
3 changes: 3 additions & 0 deletions src/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,3 +184,6 @@ void end_of_storage_visit(struct parser_ctx* ctx,
struct object* p_object,
const struct token* position_token,
const char* previous_names);


bool object_is_expansible(const struct object* p_object);
34 changes: 28 additions & 6 deletions src/web/ownership.html
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ <h1>Cake - C23 and Beyond</h1>
<a href="#toc_8">Deleting Owner Pointers</a>
</li>
<li>
<a href="#toc_9">Conversion from owner pointer to void * owner</a>
<a href="#toc_9">Conversion from <code>T * _Owner</code> to <code>void * _Owner</code></a>
</li>
</ul>
</li>
Expand Down Expand Up @@ -325,7 +325,7 @@ <h3 id="toc_3">Owner References</h3>

<p>Sample - Declaration of fopen and fclose</p>

<pre><code class="language-c">FILE * _Owner _fopen( const char *filename, const char *mode );
<pre><code class="language-c">FILE * _Owner _Opt fopen( const char *filename, const char *mode );
void fclose(FILE * _Owner p);
</code></pre>

Expand Down Expand Up @@ -390,6 +390,28 @@ <h3 id="toc_5">View references</h3>

<p><strong>Rule:</strong> The lifetime of the referenced object must be longer than the lifetime of the view reference.</p>

<p>Sample</p>

<pre><code class="language-c">#pragma nullable enable
#pragma ownership enable

struct X
{
int i;
}
int main(){

struct X * _Opt p = nullptr;
{
struct X x = {};
p = &amp;x;
}
p-&gt;i = 1; //warning
}
</code></pre>

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

<p>The most common view references are pointers called <strong>view pointers</strong>. </p>

<p>The view qualifier is not necessary for pointers, since it&#39;s the default behavior.
Expand Down Expand Up @@ -556,7 +578,7 @@ <h3 id="toc_8">Deleting Owner Pointers</h3>
}

int main() {
struct X * _Owner pX = calloc(1, sizeof * pX);
struct X * _Owner _Opt _pX = calloc(1, sizeof * pX);
if (pX) {
/*...*/;
x_delete( pX);
Expand All @@ -567,16 +589,16 @@ <h3 id="toc_8">Deleting Owner Pointers</h3>

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

<h3 id="toc_9">Conversion from owner pointer to void * owner</h3>
<h3 id="toc_9">Conversion from <code>T * _Owner</code> to <code>void * _Owner</code></h3>

<p><strong>Rule:</strong> Assignment or cast of a owner pointer to void * owner requires the pointed object to be empty.</p>
<p><strong>Rule:</strong> Assignment or cast from <code>T * _Owner</code> to <code>void * _Owner</code> requires the pointed object T to be empty.</p>

<pre><code class="language-c">
#pragma nullable enable
#pragma ownership enable

struct X {
char _Owner text;
char * _Owner text;
};

struct X * _Owner make();
Expand Down
12 changes: 5 additions & 7 deletions tests/unit-tests/out/file.c
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@

#pragma nullable enable
#pragma ownership enable
#pragma nullable enable

struct X {
int * p;
char */*_Owner*/ name;
};


int main()
void x_destroy(_Opt struct X * /*_Obj_owner*/ x)
{
struct X x = {0};
}
//free(x.name);
}

0 comments on commit 6eb39c4

Please sign in to comment.