Skip to content

Commit

Permalink
thradams#106 array indiretion fix
Browse files Browse the repository at this point in the history
  • Loading branch information
thradams committed Feb 25, 2024
1 parent 6e91c23 commit f7145ad
Show file tree
Hide file tree
Showing 776 changed files with 17,011 additions and 34 deletions.
17 changes: 14 additions & 3 deletions src/expressions.c
Original file line number Diff line number Diff line change
Expand Up @@ -2133,14 +2133,25 @@ struct expression* owner unary_expression(struct parser_ctx* ctx)
//the result of the indirection(unary*) operator applied to a pointer to object


if (!type_is_pointer(&new_expression->right->type))
if (!type_is_pointer_or_array(&new_expression->right->type))
{
compiler_diagnostic_message(ERROR_INDIRECTION_REQUIRES_POINTER_OPERAND,
ctx,
op_position,
"indirection requires pointer operand");
}
new_expression->type = type_remove_pointer(&new_expression->right->type);
if (type_is_pointer(&new_expression->right->type))
{
new_expression->type = type_remove_pointer(&new_expression->right->type);
}
else
{
compiler_diagnostic_message(W_ARRAY_INDIRECTION,
ctx,
op_position,
"array indirection");
new_expression->type = get_array_item_type(&new_expression->right->type);
}
}
else if (op == '&')
{
Expand Down Expand Up @@ -2698,7 +2709,7 @@ struct expression* owner additive_expression(struct parser_ctx* ctx)
struct token* operator_position = ctx->current;

struct expression* owner new_expression = calloc(1, sizeof * new_expression);
if (new_expression == NULL)
if (new_expression == NULL)
{
compiler_diagnostic_message(ERROR_OUT_OF_MEM, ctx, ctx->current, "out of mem");
throw;
Expand Down
15 changes: 8 additions & 7 deletions src/file.c
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
struct X { int i; void* p; };
void f(struct X* p) {}

int main()
int main(void)
{
const struct X x = {0};
f(&x);
}
#pragma cake diagnostic check "-Wdiscarded-qualifiers"
int n = 1;
int a[n]; // re-allocated 10 times, each with a different size
int k = (sizeof a / sizeof * a);

int b[2];
int k2 = (sizeof b / sizeof * b);
}
45 changes: 25 additions & 20 deletions src/flow_visit.c
Original file line number Diff line number Diff line change
Expand Up @@ -1228,7 +1228,7 @@ static int compare_function_arguments2(struct parser_ctx* ctx,
struct type t2 = type_remove_pointer(&p_current_parameter_type->type);
if (type_is_out(&t2))
{
pointer_to_out = true;
pointer_to_out = true;
}
type_destroy(&t2);
}
Expand Down Expand Up @@ -1328,11 +1328,9 @@ static void flow_visit_expression(struct flow_visit_ctx* ctx, struct expression*
break;
case PRIMARY_EXPRESSION_DECLARATOR:

if (p_expression->declarator->object.state & OBJECT_STATE_UNINITIALIZED)
if (!ctx->expression_is_not_evaluated &&
p_expression->declarator->object.state & OBJECT_STATE_UNINITIALIZED)
{
//TODO inside sizeof(v) is not an error. :D
//TODO function type...

if (!ctx->is_left_expression &&
!ctx->expression_is_not_evaluated)
{
Expand Down Expand Up @@ -1375,12 +1373,14 @@ static void flow_visit_expression(struct flow_visit_ctx* ctx, struct expression*
break;
case POSTFIX_ARRAY: {

flow_visit_expression(ctx, p_expression->left);
flow_visit_expression(ctx, p_expression->right);
flow_visit_expression(ctx, p_expression->left);
flow_visit_expression(ctx, p_expression->right);

struct type t = { 0 };
struct object* p_object = expression_get_object(p_expression->left, &t);
struct type t = { 0 };
struct object* p_object = expression_get_object(p_expression->left, &t);

if (!ctx->expression_is_not_evaluated)
{
if (p_object && p_object->state == OBJECT_STATE_UNINITIALIZED)
{
compiler_diagnostic_message(W_ANALYZER_UNINITIALIZED,
Expand All @@ -1393,9 +1393,11 @@ static void flow_visit_expression(struct flow_visit_ctx* ctx, struct expression*
ctx->ctx,
p_expression->left->first_token, "maybe using a uninitialized object");
}
type_destroy(&t);
}
break;

type_destroy(&t);
}
break;

case POSTFIX_FUNCTION_CALL:

Expand Down Expand Up @@ -1535,9 +1537,12 @@ static void flow_visit_expression(struct flow_visit_ctx* ctx, struct expression*

if (p_object && p_object->state == OBJECT_STATE_UNINITIALIZED)
{
compiler_diagnostic_message(W_ANALYZER_UNINITIALIZED,
ctx->ctx,
p_expression->right->first_token, "using a uninitialized object");
if (!ctx->expression_is_not_evaluated)
{
compiler_diagnostic_message(W_ANALYZER_UNINITIALIZED,
ctx->ctx,
p_expression->right->first_token, "using a uninitialized object");
}
}
else if (p_object && p_object->state & OBJECT_STATE_NULL)
{
Expand Down Expand Up @@ -1710,7 +1715,7 @@ static void flow_visit_compound_statement(struct flow_visit_ctx* ctx, struct com
/*lets restore the diagnostic state it was initialize because static analysis is a second pass*/
ctx->ctx->options.diagnostic_stack[ctx->ctx->options.diagnostic_stack_top_index] = p_compound_statement->diagnostic_flags;



struct flow_defer_scope* p_defer = flow_visit_ctx_push_tail_block(ctx);
p_defer->p_compound_statement = p_compound_statement;
Expand Down Expand Up @@ -2140,7 +2145,7 @@ enum object_state parse_string_state(const char* s, bool* invalid)

static void flow_visit_static_assert_declaration(struct flow_visit_ctx* ctx, struct static_assert_declaration* p_static_assert_declaration)
{
const bool t2 = ctx->expression_is_not_evaluated;
const bool t2 = ctx->expression_is_not_evaluated;
ctx->expression_is_not_evaluated = true;

flow_visit_expression(ctx, p_static_assert_declaration->constant_expression);
Expand Down Expand Up @@ -2168,7 +2173,7 @@ static void flow_visit_static_assert_declaration(struct flow_visit_ctx* ctx, str
{
/*TODO
check state
*/
struct type t = { 0 };
struct object* p_obj = expression_get_object(p_static_assert_declaration->constant_expression, &t);
Expand Down Expand Up @@ -2333,12 +2338,12 @@ static void flow_visit_declarator(struct flow_visit_ctx* ctx, struct declarator*
if (p_declarator->object.pointed)
{
set_object(&t2, p_declarator->object.pointed, (OBJECT_STATE_NOT_NULL | OBJECT_STATE_NULL));
}
type_destroy(&t2);
}
#endif
type_destroy(&t2);
}
#endif
}
}

/*if (p_declarator->pointer)
{
Expand Down
3 changes: 2 additions & 1 deletion src/lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -9773,7 +9773,8 @@ int fill_options(struct options* options,
*/
options->diagnostic_stack[0] = default_diagnostic;


options->diagnostic_stack[0].warnings &= ~(1ULL << W_STYLE);
//&~items;

#ifdef __EMSCRIPTEN__
options->flow_analysis = true;
Expand Down
6 changes: 4 additions & 2 deletions src/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ s_warnings[] = {
{W_MUST_USE_ADDRESSOF, "must-use-address-of"},
{W_PASSING_NULL_AS_ARRAY, "null-as-array"},
{W_INCOMPATIBLE_ENUN_TYPES, "incompatible-enum"},
{W_MULTICHAR_ERROR, "multi-char"}
{W_MULTICHAR_ERROR, "multi-char"},
{W_ARRAY_INDIRECTION,"array-indirection"},

};

Expand Down Expand Up @@ -127,7 +128,8 @@ int fill_options(struct options* options,
*/
options->diagnostic_stack[0] = default_diagnostic;


options->diagnostic_stack[0].warnings &= ~(1ULL << W_STYLE);
//&~items;

#ifdef __EMSCRIPTEN__
options->flow_analysis = true;
Expand Down
2 changes: 1 addition & 1 deletion src/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ enum diagnostic_id {
W_OWNERSHIP_NON_OWNER_TO_OWNER_ASSIGN,
W_DISCARDING_OWNER,
W_OWNERSHIP_NON_OWNER_MOVE,

W_ARRAY_INDIRECTION,
/*flow analysis errors*/
W_ANALYZER_OWNERSHIP_FLOW_MISSING_DTOR,

Expand Down
35 changes: 35 additions & 0 deletions tests/en-cpp-reference-c/cCode0.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//en.cppreference.com/w/c/algorithm/bsearch.html
#include <stdlib.h>
#include <stdio.h>

struct data {
int nr;
char const *value;
} dat[] = {
{1, "Foo"}, {2, "Bar"}, {3, "Hello"}, {4, "World"}
};

int data_cmp(void const *lhs, void const *rhs)
{
struct data const *const l = lhs;
struct data const *const r = rhs;

if (l->nr < r->nr) return -1;
else if (l->nr > r->nr) return 1;
else return 0;

// return (l->nr > r->nr) - (l->nr < r->nr); // possible shortcut
// return l->nr - r->nr; // erroneous shortcut (fails if INT_MIN is present)
}

int main(void)
{
struct data key = { .nr = 3 };
struct data const *res = bsearch(&key, dat, sizeof dat / sizeof dat[0],
sizeof dat[0], data_cmp);
if (res) {
printf("No %d: %s\n", res->nr, res->value);
} else {
printf("No %d not found\n", key.nr);
}
}
31 changes: 31 additions & 0 deletions tests/en-cpp-reference-c/cCode1.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//en.cppreference.com/w/c/algorithm/qsort.html
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

int compare_ints(const void* a, const void* b)
{
int arg1 = *(const int*)a;
int arg2 = *(const int*)b;

if (arg1 < arg2) return -1;
if (arg1 > arg2) return 1;
return 0;

// return (arg1 > arg2) - (arg1 < arg2); // possible shortcut
// return arg1 - arg2; // erroneous shortcut (fails if INT_MIN is present)
}

int main(void)
{
int ints[] = { -2, 99, 0, -743, 2, INT_MIN, 4 };
int size = sizeof ints / sizeof *ints;

qsort(ints, size, sizeof(int), compare_ints);

for (int i = 0; i < size; i++) {
printf("%d ", ints[i]);
}

printf("\n");
}
25 changes: 25 additions & 0 deletions tests/en-cpp-reference-c/cCode10.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//en.cppreference.com/w/c/chrono/localtime.html
#define __STDC_WANT_LIB_EXT1__ 1
#define _XOPEN_SOURCE // for putenv
#include <time.h>
#include <stdio.h>
#include <stdlib.h> // for putenv

int main(void)
{
time_t t = time(NULL);
printf("UTC: %s", asctime(gmtime(&t)));
printf("local: %s", asctime(localtime(&t)));
// POSIX-specific
putenv("TZ=Asia/Singapore");
printf("Singapore: %s", asctime(localtime(&t)));

#ifdef __STDC_LIB_EXT1__
struct tm buf;
char str[26];
asctime_s(str,sizeof str,gmtime_s(&t, &buf));
printf("UTC: %s", str);
asctime_s(str,sizeof str,localtime_s(&t, &buf));
printf("local: %s", str);
#endif
}
36 changes: 36 additions & 0 deletions tests/en-cpp-reference-c/cCode100.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//en.cppreference.com/w/c/language/character_constant.html
#include <stddef.h>
#include <stdio.h>
#include <uchar.h>

int main (void)
{
printf("constant value \n");
printf("-------- ----------\n");

// integer character constants,
int c1='a'; printf("'a':\t %#010x\n", c1);
int c2='🍌'; printf("'🍌':\t %#010x\n\n", c2); // implementation-defined

// multicharacter constant
int c3='ab'; printf("'ab':\t %#010x\n\n", c3); // implementation-defined

// 16-bit wide character constants
char16_t uc1 = u'a'; printf("'a':\t %#010x\n", (int)uc1);
char16_t uc2 = u'¢'; printf("'¢':\t %#010x\n", (int)uc2);
char16_t uc3 = u'猫'; printf("'猫':\t %#010x\n", (int)uc3);
// implementation-defined (🍌 maps to two 16-bit characters)
char16_t uc4 = u'🍌'; printf("'🍌':\t %#010x\n\n", (int)uc4);

// 32-bit wide character constants
char32_t Uc1 = U'a'; printf("'a':\t %#010x\n", (int)Uc1);
char32_t Uc2 = U'¢'; printf("'¢':\t %#010x\n", (int)Uc2);
char32_t Uc3 = U'猫'; printf("'猫':\t %#010x\n", (int)Uc3);
char32_t Uc4 = U'🍌'; printf("'🍌':\t %#010x\n\n", (int)Uc4);

// wide character constants
wchar_t wc1 = L'a'; printf("'a':\t %#010x\n", (int)wc1);
wchar_t wc2 = L'¢'; printf("'¢':\t %#010x\n", (int)wc2);
wchar_t wc3 = L'猫'; printf("'猫':\t %#010x\n", (int)wc3);
wchar_t wc4 = L'🍌'; printf("'🍌':\t %#010x\n\n", (int)wc4);
}
41 changes: 41 additions & 0 deletions tests/en-cpp-reference-c/cCode101.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//en.cppreference.com/w/c/language/compound_literal.html
#include <stdio.h>

int *p = (int[]){2, 4}; // creates an unnamed static array of type int[2]
// initializes the array to the values {2, 4}
// creates pointer p to point at the first element of
// the array
const float *pc = (const float []){1e0, 1e1, 1e2}; // read-only compound literal

struct point {double x,y;};

int main(void)
{
int n = 2, *p = &n;
p = (int [2]){*p}; // creates an unnamed automatic array of type int[2]
// initializes the first element to the value formerly
// held in *p
// initializes the second element to zero
// stores the address of the first element in p

void drawline1(struct point from, struct point to);
void drawline2(struct point *from, struct point *to);
drawline1(
(struct point){.x=1, .y=1}, // creates two structs with block scope and
(struct point){.x=3, .y=4}); // calls drawline1, passing them by value
drawline2(
&(struct point){.x=1, .y=1}, // creates two structs with block scope and
&(struct point){.x=3, .y=4}); // calls drawline2, passing their addresses
}

void drawline1(struct point from, struct point to)
{
printf("drawline1: `from` @ %p {%.2f, %.2f}, `to` @ %p {%.2f, %.2f}\n",
(void*)&from, from.x, from.y, (void*)&to, to.x, to.y);
}

void drawline2(struct point *from, struct point *to)
{
printf("drawline2: `from` @ %p {%.2f, %.2f}, `to` @ %p {%.2f, %.2f}\n",
(void*)from, from->x, from->y, (void*)to, to->x, to->y);
}
Loading

0 comments on commit f7145ad

Please sign in to comment.