Skip to content

Commit

Permalink
many fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
thradams committed Feb 28, 2024
1 parent 5d4205f commit e990a55
Show file tree
Hide file tree
Showing 73 changed files with 88,722 additions and 86,257 deletions.
30 changes: 11 additions & 19 deletions ownership.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

Last Updated 27/12/2023
Last Updated 27/02/2024

This is a work in progress, both design and implementation. Cake source itself is being used to validate the concepts.

Expand Down Expand Up @@ -1092,32 +1092,24 @@ int main() {
If the compiler supports ownership checks and qualifiers such as _Owner, _View, _Obj\_view, etc., it must define `__STDC_OWNERSHIP__`.
However, even if the compiler implements ownership, it is not active by default. The objective is to have a smooth transition allowing some files without checks. For instance, a thirty part code inside your project.
For instance, when compiling this file, even if the compiler supports ownership we don't have errors or warnings because the checks are not enabled by default.
We utilize a header with macro versions for each keyword.
For example, the macro owner corresponds to the keyword _Owner.
This approach offers the advantage that macros can be declared empty for compilers that
do not support ownership checks.
```c
#include <ownership.h>
#include <stdlib.h>
int main() {
void * p = malloc(1);
void * owner p = malloc(1); //error: missing owner qualifier
}
```

A second define `__OWNERSHIP_H__`, is used to enable ownership.
This define is set when we include `<ownership.h>` at beginning.
> Currently cake is using the same headers of VS and GCC that are not aware of ownership.
For this reason, `ownership.h` itself is declaring malloc.
When we parsing malloc from MSVC/GCC we ignore the diferences, but at the current version
`ownership.h` header must be included before to take efect.

```c
#include <ownership.h>
#include <stdlib.h>

int main() {
void * p = malloc(1); //error: missing owner qualifier
}
```

The other advantage of having a `<ownership.h>` is because owner is a macro that can be defined as empty in case the compiler does not support ownership, allowing the same code to be compiled in compilers without ownership support.


> Currently cake is using the same headers of VS and GCC that are not aware of ownership. For this reason, `ownership.h` itself is declaring malloc etc and the second declaration of malloc inside stdlib.h will not complain with the discrepancy of ownership qualifiers between declarations.

15 changes: 15 additions & 0 deletions ownership_samples.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Learning Cake owership by samples

Learning Cake owernship by samples is an effective way to grasp the ownership concepts and syntax
through practical examples.


```c
#include <stdio.h>
int main()
{
void * p = malloc(1);
}
```


1 change: 1 addition & 0 deletions src/build.c
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ int main()
generate_doc("../README.md", "./web/index.html");
generate_doc("../warnings.md", "./web/warnings.html");
generate_doc("../ownership.md", "./web/ownership.html");
generate_doc("../ownership_samples.md", "./web/ownership_samples.html");


remove("hoedown.exe");
Expand Down
48 changes: 27 additions & 21 deletions src/expressions.c
Original file line number Diff line number Diff line change
Expand Up @@ -592,7 +592,7 @@ struct generic_association* owner generic_association(struct parser_ctx* ctx)
}
else
{
compiler_diagnostic_message(C_UNEXPECTED, ctx, ctx->current, "unexpected");
compiler_diagnostic_message(C_ERROR_UNEXPECTED, ctx, ctx->current, "unexpected");
}
parser_match_tk(ctx, ':');
p_generic_association->expression = assignment_expression(ctx);
Expand Down Expand Up @@ -713,10 +713,12 @@ struct generic_selection* owner generic_selection(struct parser_ctx* ctx)
{
/*extension*/
p_generic_selection->type_name = type_name(ctx);
if (p_generic_selection->type_name == NULL) throw;
}
else
{
p_generic_selection->expression = assignment_expression(ctx);
if (p_generic_selection->expression == NULL) throw;
}

parser_match_tk(ctx, ',');
Expand Down Expand Up @@ -771,6 +773,8 @@ struct generic_selection* owner generic_selection(struct parser_ctx* ctx)
}
catch
{
generic_selection_delete(p_generic_selection);
p_generic_selection = NULL;
}
return p_generic_selection;
}
Expand Down Expand Up @@ -931,14 +935,9 @@ struct expression* owner character_constant_expression(struct parser_ctx* ctx)
p++;
p++;

if (sizeof(wchar_t) > sizeof(short))
{
p_expression_node->type.type_specifier_flags = TYPE_SPECIFIER_UNSIGNED | TYPE_SPECIFIER_INT;
}
else
{
p_expression_node->type.type_specifier_flags = TYPE_SPECIFIER_UNSIGNED | TYPE_SPECIFIER_SHORT;
}

p_expression_node->type.type_specifier_flags = CAKE_WCHAR_T_TYPE_SPECIFIER;

/*
wchar_t character constant prefixed by the letter L has type wchar_t, an integer type defined in
the <stddef.h> header. The value of a wchar_t character constant containing a single multibyte
Expand All @@ -956,6 +955,7 @@ struct expression* owner character_constant_expression(struct parser_ctx* ctx)
p = utf8_decode(p, &c);
if (p == 0)
break;
//TODO \u
value = value * 256 + c;
if (value > INT_MAX)
{
Expand Down Expand Up @@ -1080,6 +1080,8 @@ static bool is_integer_or_floating_constant(enum token_type type)

struct object* expression_get_object(struct expression* p_expression, struct type* p_type)
{
if (p_expression == NULL)
return NULL;
if (p_expression->expression_type == PRIMARY_EXPRESSION_DECLARATOR)
{
if (p_type)
Expand Down Expand Up @@ -1287,13 +1289,7 @@ struct expression* owner primary_expression(struct parser_ctx* ctx)
GCC or MSVC.
windows it is short linux is
*/
char_type =
_Generic((wchar_t)0,
short: TYPE_SPECIFIER_SHORT,
unsigned short : TYPE_SPECIFIER_UNSIGNED | TYPE_SPECIFIER_SHORT,
int : TYPE_SPECIFIER_INT,
unsigned int : TYPE_SPECIFIER_UNSIGNED | TYPE_SPECIFIER_INT
);
char_type = CAKE_WCHAR_T_TYPE_SPECIFIER;
}

p_expression_node->type = type_make_literal_string(string_literal_byte_size(ctx->current->lexeme), char_type);
Expand Down Expand Up @@ -1377,6 +1373,7 @@ struct expression* owner primary_expression(struct parser_ctx* ctx)
p_expression_node->expression_type = PRIMARY_EXPRESSION_GENERIC;

p_expression_node->generic_selection = generic_selection(ctx);
if (p_expression_node->generic_selection == NULL) throw;

p_expression_node->last_token = p_expression_node->generic_selection->last_token;

Expand Down Expand Up @@ -1409,11 +1406,14 @@ struct expression* owner primary_expression(struct parser_ctx* ctx)
}
else
{
compiler_diagnostic_message(C_UNEXPECTED, ctx, ctx->current, "unexpected");
compiler_diagnostic_message(C_ERROR_UNEXPECTED, ctx, ctx->current, "unexpected");
}
}
catch
{
expression_delete(p_expression_node);
p_expression_node = NULL;

}


Expand Down Expand Up @@ -2545,7 +2545,9 @@ struct expression* owner cast_expression(struct parser_ctx* ctx)
}
else
{
compiler_diagnostic_message(C_UNEXPECTED, ctx, ctx->current, "unexpected");
compiler_diagnostic_message(C_ERROR_UNEXPECTED, ctx, ctx->current, "expected expression");
assert(p_expression_node == NULL);
throw;
}
}
catch
Expand Down Expand Up @@ -2777,7 +2779,7 @@ struct expression* owner additive_expression(struct parser_ctx* ctx)
{
expression_delete(new_expression);
new_expression = NULL;
compiler_diagnostic_message(C_UNEXPECTED, ctx, ctx->current, "internal error");
compiler_diagnostic_message(C_ERROR_UNEXPECTED, ctx, ctx->current, "internal error");
throw;
}
}
Expand Down Expand Up @@ -3412,9 +3414,10 @@ struct expression* owner logical_and_expression(struct parser_ctx* ctx)
int code = type_common(&new_expression->left->type, &new_expression->right->type, &new_expression->type);
if (code != 0)
{

type_print(&new_expression->left->type);
type_print(&new_expression->right->type);
compiler_diagnostic_message(C_ERROR_INVALID_TYPE, ctx, ctx->current, "invalid types logicl and expression");
compiler_diagnostic_message(C_ERROR_INVALID_TYPE, ctx, ctx->current, "invalid types logical and expression");
expression_delete(new_expression);
throw;
}
Expand Down Expand Up @@ -3591,13 +3594,16 @@ struct expression* owner assignment_expression(struct parser_ctx* ctx)


check_diferent_enuns(ctx, op_token, new_expression->left, new_expression->right);

new_expression->left->is_assigment_expression = true;
if (new_expression->left->left)
new_expression->left->left->is_assigment_expression = true;
p_expression_node = new_expression;
}
}
catch
{
}

return p_expression_node;
}

Expand Down
3 changes: 3 additions & 0 deletions src/expressions.h
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,9 @@ struct expression
struct expression* owner condition_expr;
struct expression* owner left;
struct expression* owner right;

bool is_assigment_expression;

};

void expression_delete(struct expression* owner opt p);
Expand Down
63 changes: 27 additions & 36 deletions src/file.c
Original file line number Diff line number Diff line change
@@ -1,38 +1,29 @@

void* _Owner malloc(unsigned long size);
void free(void* _Owner ptr);

struct Y {
char* _Owner p0;
int* _Owner p2;
double i2;
//en.cppreference.com/w/c/language/_Alignas.html
#include <stdalign.h>
#include <stdio.h>

// every object of type struct sse_t will be aligned to 16-byte boundary
// (note: needs support for DR 444)
struct sse_t
{
alignas(16) float sse_data[4];
};

struct X {
char* _Owner text;
int* _Owner p1;
int i;
struct Y* pY;

// every object of type struct data will be aligned to 128-byte boundary
struct data
{
char x;
alignas(128) char cacheline[128]; // over-aligned array of char,
// not array of over-aligned chars
};

void init(struct X* p);

int main() {
struct X x;
/*lying here, to avoid error of using uninitialized*/
static_set(x, "zero");
init(&x);

static_state(x.p1, "maybe-null");
static_state(x.i, "any");
static_state(x.pY, "maybe-null");
static_state(x.pY->p0, "maybe-null");
static_state(x.pY->p2, "maybe-null");
static_state(x.pY->i2, "any");
free(x);
}


void dummy() {}

#pragma cake diagnostic check "-Wmaybe-uninitialized"

int main(void)
{
printf("sizeof(data) = %zu (1 byte + 127 bytes padding + 128-byte array)\n",
sizeof(struct data));

printf("alignment of sse_t is %zu\n", alignof(struct sse_t));

alignas(2048) struct data d; // this instance of data is aligned even stricter
(void)d; // suppresses "maybe unused" warning
}
Loading

0 comments on commit e990a55

Please sign in to comment.