From 81ff3ebe240b1126303b8eb0237e6f8be114d01f Mon Sep 17 00:00:00 2001
From: thradams
Date: Mon, 24 Jun 2024 19:08:55 -0300
Subject: [PATCH] -autoconfig option added, unit tests
---
manual.md | 7 +
src/build.c | 11 +-
src/cakeconfig.h | 31 -
src/expressions.c | 47 +-
src/expressions.h | 6 +
src/file.c | 24 +-
src/flow_object.c | 56 +-
src/flow_object.h | 14 +-
src/flow_visit.c | 13 +-
src/lib.c | 1196 ++++++++++++++++++++-------------
src/main.c | 9 +-
src/options.c | 9 +-
src/options.h | 6 +
src/parser.c | 244 ++++++-
src/parser.h | 51 +-
src/tokenizer.c | 858 +++++++++++------------
src/tokenizer.h | 2 +
src/web/manual.html | 315 ++++-----
tests/unit-tests/test_17900.c | 1 +
tests/unit-tests/test_20000.c | 30 +
tests/unit-tests/test_20100.c | 18 +
tests/unit-tests/test_20200.c | 11 +
tests/unit-tests/test_20300.c | 16 +
vc/cprimev3.vcxproj.user | 2 +-
24 files changed, 1833 insertions(+), 1144 deletions(-)
delete mode 100644 src/cakeconfig.h
create mode 100644 tests/unit-tests/test_20000.c
create mode 100644 tests/unit-tests/test_20100.c
create mode 100644 tests/unit-tests/test_20200.c
create mode 100644 tests/unit-tests/test_20300.c
diff --git a/manual.md b/manual.md
index ca769d41..e28667eb 100644
--- a/manual.md
+++ b/manual.md
@@ -58,6 +58,8 @@ Sample of cakeconfig.h
```
+Cake also have the option -autoconfig that generates the cakeconfig.h automatically.
+
Cake also includes standard header files. The objective is to allow usage even without installing GCC or MSVC. You can set this path on `cakeconfig.h` but mixing cake headers with other headers is not recommended.
## Command line
@@ -140,6 +142,11 @@ Output is compatible with visual studio IDE. We can click on the error message a
This option enables an static analysis of program flow. This is required for some
ownership checks
+### -autoconfig
+Generates cakeconfig.h header.
+On Windows, it must be generated inside the Visual Studio Command Prompt to read the INCLUDE variable.
+On Linux, it calls GCC with echo | gcc -v -E - 2>&1 and reads the output.
+
## Output
One directory called **out** is created keeping the same directory structure of the input files.
diff --git a/src/build.c b/src/build.c
index 8a3727f9..b9dad5a1 100644
--- a/src/build.c
+++ b/src/build.c
@@ -331,13 +331,14 @@ int main()
To find GCC directories use
echo | gcc -E -Wp,-v -
*/
- if (mysytem("./cake "
+
+ //Generates cakeconfig.h
+ mysytem("./cake -autoconfig");
+
+ //Uses previouly generated cakeconfig.h to find include dir
+ if (mysytem("./cake "
" -D__x86_64__ "
" -fanalyzer "
- " -I/usr/lib/gcc/x86_64-linux-gnu/11/include/ "
- " -I/usr/local/include/ "
- " -I/usr/include/x86_64-linux-gnu/ "
- " -I/usr/include/ "
HEADER_FILES
SOURCE_FILES) != 0)
{
diff --git a/src/cakeconfig.h b/src/cakeconfig.h
deleted file mode 100644
index 0aeb713a..00000000
--- a/src/cakeconfig.h
+++ /dev/null
@@ -1,31 +0,0 @@
-
-#ifdef __linux__
-/*
- To find the include directories used my GCC type:
- cc -E -Wp,-v - < /dev/null 2>&1 | grep '^ /'
-*/
-#pragma dir "/usr/lib/gcc/x86_64-linux-gnu/11/include"
-#pragma dir "/usr/local/include"
-#pragma dir "/usr/include/x86_64-linux-gnu"
-#pragma dir "/usr/include"
-
-#endif
-
-#ifdef _WIN32
-/*
- To find the include directories used my MSVC,
- open Visual Studio Developer Commmand prompt and type:
- echo %INCLUDE%.
- Running Cake inside mscv command prompt uses %INCLUDE% automatically.
-*/
-#pragma dir "C:/Program Files/Microsoft Visual Studio/2022/Professional/VC/Tools/MSVC/14.38.33130/include"
-#pragma dir "C:/Program Files/Microsoft Visual Studio/2022/Professional/VC/Tools/MSVC/14.38.33130/ATLMFC/include"
-#pragma dir "C:/Program Files/Microsoft Visual Studio/2022/Professional/VC/Auxiliary/VS/include"
-#pragma dir "C:/Program Files (x86)/Windows Kits/10/include/10.0.22000.0/ucrt"
-#pragma dir "C:/Program Files (x86)/Windows Kits/10/include/10.0.22000.0/um"
-#pragma dir "C:/Program Files (x86)/Windows Kits/10/include/10.0.22000.0/shared"
-#pragma dir "C:/Program Files (x86)/Windows Kits/10/include/10.0.22000.0/winrt"
-#pragma dir "C:/Program Files (x86)/Windows Kits/10/include/10.0.22000.0/cppwinrt"
-#pragma dir "C:/Program Files (x86)/Windows Kits/NETFXSDK/4.8/include/um"
-
-#endif
diff --git a/src/expressions.c b/src/expressions.c
index cebc4bfe..40eddf7e 100644
--- a/src/expressions.c
+++ b/src/expressions.c
@@ -61,7 +61,7 @@ double constant_value_to_double(const struct constant_value* a)
case TYPE_UNSIGNED_LONG_LONG:
return (double)a->ullvalue;
default:
- return 0;
+ break;
}
return 0;
@@ -103,7 +103,7 @@ unsigned long long constant_value_to_ull(const struct constant_value* a)
case TYPE_UNSIGNED_LONG_LONG:
return (unsigned long long)a->ullvalue;
default:
- return 0;
+ break;
}
return 0;
@@ -119,7 +119,7 @@ long long constant_value_to_ll(const struct constant_value* a)
case TYPE_UNSIGNED_LONG_LONG:
return (long long)a->ullvalue;
default:
- return 0;
+ break;
}
return 0;
@@ -135,7 +135,7 @@ bool constant_value_to_bool(const struct constant_value* a)
case TYPE_UNSIGNED_LONG_LONG:
return a->ullvalue != 0;
default:
- return 0;
+ break;
}
return 0;
@@ -529,14 +529,14 @@ static int compare_function_arguments(struct parser_ctx* ctx,
p_current_parameter_type = p_param_list->head;
}
-
+
struct argument_expression* p_current_argument = p_argument_expression_list->head;
while (p_current_argument && p_current_parameter_type)
{
check_assigment(ctx, &p_current_parameter_type->type, p_current_argument->expression, ASSIGMENT_TYPE_PARAMETER);
p_current_argument = p_current_argument->next;
- p_current_parameter_type = p_current_parameter_type->next;
+ p_current_parameter_type = p_current_parameter_type->next;
}
if (p_current_argument != NULL && !p_param_list->is_var_args)
@@ -2978,7 +2978,7 @@ struct expression* owner additive_expression(struct parser_ctx* ctx)
new_expression->left = p_expression_node;
p_expression_node = NULL; /*MOVED*/
-
+
new_expression->right = multiplicative_expression(ctx);
if (new_expression->right == NULL)
{
@@ -3305,10 +3305,11 @@ struct expression* owner relational_expression(struct parser_ctx* ctx)
return p_expression_node;
}
-static void check_diferent_enuns(struct parser_ctx* ctx,
+void check_diferent_enuns(struct parser_ctx* ctx,
const struct token* operator_token,
struct expression* left,
- struct expression* right)
+ struct expression* right,
+ const char * message)
{
if (left->type.type_specifier_flags & TYPE_SPECIFIER_ENUM &&
right->type.type_specifier_flags & TYPE_SPECIFIER_ENUM)
@@ -3324,10 +3325,18 @@ static void check_diferent_enuns(struct parser_ctx* ctx,
if (right->type.enum_specifier->tag_token)
righttag = right->type.enum_specifier->tag_token->lexeme;
+ char finalmessage[200]={0};
+ snprintf(finalmessage,
+ sizeof finalmessage,
+ "%s (enum %s, enum %s)",
+ message,
+ lefttag,
+ righttag);
+
compiler_diagnostic_message(W_ENUN_CONVERSION,
ctx,
operator_token,
- "implicit conversion from 'enum %s' to 'enum %s'",
+ finalmessage,
lefttag,
righttag);
}
@@ -3391,7 +3400,8 @@ struct expression* owner equality_expression(struct parser_ctx* ctx)
throw;
new_expression->last_token = new_expression->right->last_token;
- check_diferent_enuns(ctx, operator_token, new_expression->left, new_expression->right);
+ check_diferent_enuns(ctx, operator_token, new_expression->left, new_expression->right,
+ "comparing different enums.");
new_expression->first_token = operator_token;
@@ -3557,7 +3567,6 @@ struct expression* owner exclusive_or_expression(struct parser_ctx* ctx)
struct expression* owner inclusive_or_expression(struct parser_ctx* ctx)
{
-
/*
inclusive-OR-expression:
exclusive-OR-expression
@@ -3573,6 +3582,7 @@ struct expression* owner inclusive_or_expression(struct parser_ctx* ctx)
while (ctx->current != NULL &&
(ctx->current->type == '|'))
{
+ struct token* operator_token = ctx->current;
parser_match(ctx);
struct expression* owner new_expression = calloc(1, sizeof * new_expression);
if (new_expression == NULL)
@@ -3590,6 +3600,13 @@ struct expression* owner inclusive_or_expression(struct parser_ctx* ctx)
expression_delete(new_expression);
throw;
}
+
+ check_diferent_enuns(ctx,
+ operator_token,
+ new_expression->left,
+ new_expression->right,
+ "operator '|' between enumerations of different types.");
+
new_expression->last_token = new_expression->right->last_token;
new_expression->constant_value =
constant_value_op(&new_expression->left->constant_value, &new_expression->right->constant_value, '|');
@@ -3845,7 +3862,9 @@ struct expression* owner assignment_expression(struct parser_ctx* ctx)
new_expression->type.storage_class_specifier_flags &= ~STORAGE_SPECIFIER_FUNCTION_RETURN;
new_expression->type.storage_class_specifier_flags &= ~STORAGE_SPECIFIER_FUNCTION_RETURN_NODISCARD;
- check_diferent_enuns(ctx, op_token, new_expression->left, new_expression->right);
+ check_diferent_enuns(ctx, op_token, new_expression->left, new_expression->right,
+ "assignment of different enums.");
+
new_expression->left->is_assigment_expression = true;
if (new_expression->left->left)
new_expression->left->left->is_assigment_expression = true;
@@ -3869,7 +3888,7 @@ void argument_expression_list_push(struct argument_expression_list* list, struct
}
else
{
- assert(list->tail->next == NULL);
+ assert(list->tail->next == NULL);
list->tail->next = pitem;
}
list->tail = pitem;
diff --git a/src/expressions.h b/src/expressions.h
index b9ce7be5..efd30e4b 100644
--- a/src/expressions.h
+++ b/src/expressions.h
@@ -244,3 +244,9 @@ void expression_evaluate_equal_not_equal(const struct expression* left,
struct expression* result,
int op,
bool disabled);
+
+void check_diferent_enuns(struct parser_ctx* ctx,
+ const struct token* operator_token,
+ struct expression* left,
+ struct expression* right,
+ const char * message);
diff --git a/src/file.c b/src/file.c
index a3b68a46..c924c2ff 100644
--- a/src/file.c
+++ b/src/file.c
@@ -1,21 +1,13 @@
#pragma safety enable
+enum E1 {A, B};
+enum E2 {C, D};
-
-
-void free( void* _Owner ptr);
-void* _Owner malloc(int size);
-struct X { char * _Owner text; };
-
-void x_destroy(struct X* _Obj_owner p)
+void f(enum E1 e)
{
- free(p->text);
-}
-
-void x_delete(struct X* _Owner _Opt p)
-{
- if (p)
+ switch(e)
{
- x_destroy(p);
- free(p);
+ case A:break;
+ case 12:break;
}
-}
\ No newline at end of file
+}
+int main(){}
diff --git a/src/flow_object.c b/src/flow_object.c
index 1f67cdf3..465553dd 100644
--- a/src/flow_object.c
+++ b/src/flow_object.c
@@ -29,6 +29,13 @@ bool flow_object_is_not_null(struct flow_object* p)
}
+bool flow_object_can_be_not_null_or_moved(struct flow_object* p)
+{
+ enum object_state e = p->current.state;
+ return (e & OBJECT_STATE_NOT_NULL) ||
+ (e & OBJECT_STATE_MOVED);
+}
+
bool flow_object_is_null(struct flow_object* p)
{
enum object_state e = p->current.state;
@@ -51,7 +58,7 @@ bool flow_object_is_not_zero(struct flow_object* p)
(e & OBJECT_STATE_NOT_ZERO));
}
-bool flow_object_maybe_is_null(struct flow_object* p)
+bool flow_object_can_be_null(struct flow_object* p)
{
enum object_state e = p->current.state;
@@ -59,11 +66,23 @@ bool flow_object_maybe_is_null(struct flow_object* p)
}
bool flow_object_is_uninitialized(struct flow_object* p)
+{
+ enum object_state e = p->current.state;
+ return e == OBJECT_STATE_UNINITIALIZED;
+}
+
+bool flow_object_can_be_uninitialized(struct flow_object* p)
{
enum object_state e = p->current.state;
return (e & OBJECT_STATE_UNINITIALIZED);
}
+bool flow_object_can_have_its_lifetime_ended(struct flow_object* p)
+{
+ enum object_state e = p->current.state;
+ return (e & OBJECT_STATE_LIFE_TIME_ENDED);
+}
+
static void object_state_to_string_core(enum object_state e)
{
@@ -504,11 +523,11 @@ struct flow_object* make_object_core(struct flow_visit_ctx* ctx,
//assert((p_declarator_opt == NULL) != (p_expression_origin == NULL));
if (p_declarator_opt == NULL)
{
- assert(p_expression_origin != NULL);
+ //assert(p_expression_origin != NULL);
}
if (p_expression_origin == NULL)
{
- assert(p_declarator_opt != NULL);
+ // assert(p_declarator_opt != NULL);
}
@@ -806,7 +825,7 @@ void print_object_core(int ident,
if (flow_object_is_null(p_visitor->p_object))
{
}
- else if (flow_object_is_uninitialized(p_visitor->p_object))
+ else if (flow_object_can_be_uninitialized(p_visitor->p_object))
{
}
else
@@ -2186,7 +2205,7 @@ void checked_read_object_core(struct flow_visit_ctx* ctx,
if (type_is_pointer(p_visitor->p_type) &&
!is_nullable &&
!type_is_nullable(p_visitor->p_type, ctx->ctx->options.null_checks_enabled) &&
- flow_object_maybe_is_null(p_visitor->p_object))
+ flow_object_can_be_null(p_visitor->p_object))
{
compiler_diagnostic_message(W_FLOW_NULL_DEREFERENCE,
ctx->ctx,
@@ -2197,8 +2216,7 @@ void checked_read_object_core(struct flow_visit_ctx* ctx,
if (type_is_pointer(p_visitor->p_type) &&
check_pointed_object &&
- p_visitor->p_object->current.state & OBJECT_STATE_NOT_NULL /*we don't need to check pointed object*/
- )
+ flow_object_can_be_not_null_or_moved(p_visitor->p_object))
{
struct type t2 = type_remove_pointer(p_visitor->p_type);
@@ -2230,18 +2248,18 @@ void checked_read_object_core(struct flow_visit_ctx* ctx,
previous_names);
}
-#if 0
+
//TODO there is some problem with OBJECT_STATE_LIFE_TIME_ENDED
//state somewhere!
- if (p_object->current.state & OBJECT_STATE_LIFE_TIME_ENDED)
+ if (p_visitor->p_object->current.state & OBJECT_STATE_LIFE_TIME_ENDED)
{
- compiler_diagnostic_message(W_FLOW_UNINITIALIZED,
- ctx->ctx,
- position_token,
- "lifetime ended '%s'",
- previous_names);
+ //compiler_diagnostic_message(W_FLOW_UNINITIALIZED,
+ // ctx->ctx,
+ // position_token,
+ // "lifetime ended '%s'",
+ // previous_names);
}
-#endif
+
}
}
@@ -2518,14 +2536,12 @@ void end_of_storage_visit(struct flow_visit_ctx* ctx,
s_visit_number++);
}
-
-bool object_is_zero_or_null(const struct flow_object* p_object)
+bool flow_object_is_zero_or_null(const struct flow_object* p_object)
{
return (p_object->current.state == OBJECT_STATE_NULL) ||
(p_object->current.state == OBJECT_STATE_ZERO);
}
-
/*
This function must check and do the flow assignment of
a = b
@@ -2632,7 +2648,7 @@ static void flow_assignment_core(
checked_empty(ctx, p_visitor_a->p_type, p_visitor_a->p_object, error_position);
}
- if (object_is_zero_or_null(p_visitor_b->p_object))
+ if (flow_object_is_zero_or_null(p_visitor_b->p_object))
{
if (type_is_array(p_visitor_b->p_type))
{
@@ -2664,7 +2680,7 @@ static void flow_assignment_core(
{
checked_empty(ctx, p_visitor_a->p_type, p_visitor_a->p_object, error_position);
- if (object_is_zero_or_null(p_visitor_b->p_object))
+ if (flow_object_is_zero_or_null(p_visitor_b->p_object))
{
//0 to objec_owner??
//a = nullpr
diff --git a/src/flow_object.h b/src/flow_object.h
index e6b6d396..86906e5a 100644
--- a/src/flow_object.h
+++ b/src/flow_object.h
@@ -98,8 +98,9 @@ struct flow_object
struct flow_object_state current;
int id; //helps debugging
- bool is_temporary;
+ bool is_temporary;
};
+
void flow_object_set_is_moved(struct flow_object* p_object);
void flow_object_set_can_be_uninitialized(struct flow_object* p_object);
void flow_object_set_is_unitialized(struct flow_object* p_object);
@@ -109,15 +110,22 @@ void flow_object_set_current_state_to_is_null(struct flow_object* p);
int flow_object_add_state(struct flow_object* p, struct flow_object_state *owner pnew);
+bool flow_object_is_zero_or_null(const struct flow_object* p_object);
bool flow_object_is_not_null(struct flow_object* p);
+bool flow_object_can_be_not_null_or_moved(struct flow_object* p);
+
bool flow_object_is_null(struct flow_object* p);
+bool flow_object_can_be_null(struct flow_object* p);
+
bool flow_object_is_not_zero(struct flow_object* p);
bool flow_object_is_zero(struct flow_object* p);
-bool flow_object_maybe_is_null(struct flow_object* p);
bool flow_object_is_uninitialized(struct flow_object* p);
+bool flow_object_can_be_uninitialized(struct flow_object* p);
+
+bool flow_object_can_have_its_lifetime_ended(struct flow_object* p);
void flow_object_print_state(struct flow_object* p);
@@ -175,7 +183,7 @@ void checked_read_object(struct flow_visit_ctx* ctx,
const struct token* position_token,
bool check_pointed_object);
-bool object_is_zero_or_null(const struct flow_object* p_object);
+
void end_of_storage_visit(struct flow_visit_ctx* ctx,
struct type* p_type,
bool type_is_view,
diff --git a/src/flow_visit.c b/src/flow_visit.c
index 250cbb59..4e3944fc 100644
--- a/src/flow_visit.c
+++ b/src/flow_visit.c
@@ -1818,7 +1818,7 @@ static void flow_visit_expression(struct flow_visit_ctx* ctx, struct expression*
if (p_object != NULL)
{
- if (p_object->current.state & OBJECT_STATE_NULL)
+ if (flow_object_can_be_null(p_object))
{
if (ctx->expression_is_not_evaluated)
{
@@ -1830,7 +1830,7 @@ static void flow_visit_expression(struct flow_visit_ctx* ctx, struct expression*
p_expression->left->first_token, "object is possibly null");
}
}
- else if (p_object->current.state & OBJECT_STATE_UNINITIALIZED)
+ else if (flow_object_can_be_uninitialized(p_object))
{
if (ctx->expression_is_not_evaluated)
{
@@ -1842,7 +1842,7 @@ static void flow_visit_expression(struct flow_visit_ctx* ctx, struct expression*
p_expression->left->first_token, "object is possibly uninitialized");
}
}
- else if (p_object->current.state & OBJECT_STATE_LIFE_TIME_ENDED)
+ else if (flow_object_can_have_its_lifetime_ended(p_object))
{
if (ctx->expression_is_not_evaluated)
{
@@ -1967,6 +1967,7 @@ static void flow_visit_expression(struct flow_visit_ctx* ctx, struct expression*
break;
case UNARY_EXPRESSION_NOT:
+ flow_check_pointer_used_as_bool(ctx, p_expression->right);
flow_visit_expression(ctx, p_expression->right, d);
declarator_array_invert(d);
break;
@@ -2027,7 +2028,7 @@ static void flow_visit_expression(struct flow_visit_ctx* ctx, struct expression*
p_expression->right->first_token, "using a uninitialized object");
}
}
- else if (p_object0 && flow_object_maybe_is_null(p_object0))
+ else if (p_object0 && flow_object_can_be_null(p_object0))
{
/*
*p = 1*
@@ -2282,8 +2283,8 @@ static void flow_visit_expression(struct flow_visit_ctx* ctx, struct expression*
case LOGICAL_AND_EXPRESSION:
{
- //flow_check_pointer_used_as_bool(ctx, p_expression->left);
- //flow_check_pointer_used_as_bool(ctx, p_expression->right);
+ flow_check_pointer_used_as_bool(ctx, p_expression->left);
+ flow_check_pointer_used_as_bool(ctx, p_expression->right);
struct declarator_array left_set = { 0 };
flow_visit_expression(ctx, p_expression->left, &left_set);
diff --git a/src/lib.c b/src/lib.c
index 533a3daa..124de440 100644
--- a/src/lib.c
+++ b/src/lib.c
@@ -867,6 +867,7 @@ struct options
/*
+ -fdiagnostics-format=msvc
-msvc-output
*/
bool visual_studio_ouput_format;
@@ -883,6 +884,11 @@ struct options
*/
bool dump_pptokens;
+ /*
+ -autoconfig
+ */
+ bool auto_config;
+
/*
-o filename
defines the ouputfile when 1 file is used
@@ -898,6 +904,8 @@ void print_help();
+#define CAKE_CFG_FNAME "/cakeconfig.h"
+
struct include_dir
{
const char* owner path;
@@ -2551,7 +2559,7 @@ static void tokenizer_set_error(struct tokenizer_ctx* ctx, struct stream* stream
ctx->n_errors++;
#ifndef TEST
char buffer[200] = { 0 };
- va_list args = {0};
+ va_list args = { 0 };
va_start(args, fmt);
/*int n =*/ vsnprintf(buffer, sizeof(buffer), fmt, args);
va_end(args);
@@ -2575,7 +2583,7 @@ static void tokenizer_set_warning(struct tokenizer_ctx* ctx, struct stream* stre
#ifndef TEST
char buffer[200] = { 0 };
- va_list args= {0};
+ va_list args = { 0 };
va_start(args, fmt);
/*int n =*/ vsnprintf(buffer, sizeof(buffer), fmt, args);
va_end(args);
@@ -2651,7 +2659,7 @@ bool preprocessor_diagnostic_message(enum diagnostic_id w, struct preprocessor_c
print_position(p_token->token_origin->lexeme, p_token->line, p_token->col, ctx->options.visual_studio_ouput_format);
char buffer[200] = { 0 };
- va_list args= {0};
+ va_list args = { 0 };
va_start(args, fmt);
/*int n =*/ vsnprintf(buffer, sizeof(buffer), fmt, args);
va_end(args);
@@ -2687,8 +2695,32 @@ bool preprocessor_diagnostic_message(enum diagnostic_id w, struct preprocessor_c
struct include_dir* include_dir_add(struct include_dir_list* list, const char* path)
{
+ if (path == NULL)
+ return NULL;
+
struct include_dir* owner p_new_include_dir = calloc(1, sizeof * p_new_include_dir);
- p_new_include_dir->path = strdup(path);
+ if (p_new_include_dir == NULL)
+ return NULL;
+
+ int len = strlen(path);
+ if (path[len - 1] == '\\')
+ {
+ //windows path format ending with \ .
+ p_new_include_dir->path = strdup(path);
+ }
+ else if (path[len - 1] != '/')
+ {
+ /*
+ not ending with \, we add it
+ */
+ p_new_include_dir->path = malloc(len + 2);
+ snprintf(p_new_include_dir->path, len + 2, "%s/", path);
+ }
+ else
+ {
+ p_new_include_dir->path = strdup(path);
+ }
+
if (list->head == NULL)
{
list->head = p_new_include_dir;
@@ -3133,228 +3165,228 @@ enum token_type is_punctuator(struct stream* stream)
*/
switch (stream->current[0])
{
- case '[':
- type = '[';
- stream_match(stream);
- break;
- case ']':
- type = ']';
- stream_match(stream);
- break;
- case '(':
- type = '(';
+ case '[':
+ type = '[';
+ stream_match(stream);
+ break;
+ case ']':
+ type = ']';
+ stream_match(stream);
+ break;
+ case '(':
+ type = '(';
+ stream_match(stream);
+ break;
+ case ')':
+ type = ')';
+ stream_match(stream);
+ break;
+ case '{':
+ type = '{';
+ stream_match(stream);
+ break;
+ case '}':
+ type = '}';
+ stream_match(stream);
+ break;
+ case ';':
+ type = ';';
+ stream_match(stream);
+ break;
+ case ',':
+ type = ',';
+ stream_match(stream);
+ break;
+ case '!':
+ type = '!';
+ stream_match(stream);
+ if (stream->current[0] == '=')
+ {
+ type = '!=';
stream_match(stream);
- break;
- case ')':
- type = ')';
+ }
+ break;
+ case ':':
+ type = ':';
+ stream_match(stream);
+ if (stream->current[0] == ':')
+ {
+ type = '::';
stream_match(stream);
- break;
- case '{':
- type = '{';
+ }
+ break;
+ case '~':
+ type = '~';
+ stream_match(stream);
+ break;
+ case '?':
+ type = '?';
+ stream_match(stream);
+ break;
+ case '/':
+ type = '/';
+ stream_match(stream);
+ if (stream->current[0] == '=')
+ {
+ type = '/=';
stream_match(stream);
- break;
- case '}':
- type = '}';
+ }
+ break;
+ case '*':
+ type = '*';
+ stream_match(stream);
+ if (stream->current[0] == '=')
+ {
+ type = '*=';
stream_match(stream);
- break;
- case ';':
- type = ';';
+ }
+ break;
+ case '%':
+ type = '%';
+ stream_match(stream);
+ if (stream->current[0] == '=')
+ {
+ type = '%=';
stream_match(stream);
- break;
- case ',':
- type = ',';
+ }
+ break;
+ case '-':
+ type = '-';
+ stream_match(stream);
+ if (stream->current[0] == '>')
+ {
+ type = '->';
stream_match(stream);
- break;
- case '!':
- type = '!';
+ }
+ else if (stream->current[0] == '-')
+ {
+ type = '--';
stream_match(stream);
- if (stream->current[0] == '=')
- {
- type = '!=';
- stream_match(stream);
- }
- break;
- case ':':
- type = ':';
+ }
+ else if (stream->current[0] == '=')
+ {
+ type = '-=';
stream_match(stream);
- if (stream->current[0] == ':')
- {
- type = '::';
- stream_match(stream);
- }
- break;
- case '~':
- type = '~';
+ }
+ break;
+ case '|':
+ type = '|';
+ stream_match(stream);
+ if (stream->current[0] == '|')
+ {
+ type = '||';
stream_match(stream);
- break;
- case '?':
- type = '?';
+ }
+ else if (stream->current[0] == '=')
+ {
+ type = '|=';
stream_match(stream);
- break;
- case '/':
- type = '/';
+ }
+ break;
+ case '+':
+ type = '+';
+ stream_match(stream);
+ if (stream->current[0] == '+')
+ {
+ type = '++';
stream_match(stream);
- if (stream->current[0] == '=')
- {
- type = '/=';
- stream_match(stream);
- }
- break;
- case '*':
- type = '*';
+ }
+ else if (stream->current[0] == '=')
+ {
+ type = '+=';
stream_match(stream);
- if (stream->current[0] == '=')
- {
- type = '*=';
- stream_match(stream);
- }
- break;
- case '%':
- type = '%';
+ }
+ break;
+ case '=':
+ type = '=';
+ stream_match(stream);
+ if (stream->current[0] == '=')
+ {
+ type = '==';
stream_match(stream);
- if (stream->current[0] == '=')
- {
- type = '%=';
- stream_match(stream);
- }
- break;
- case '-':
- type = '-';
+ }
+ break;
+ case '^':
+ type = '^';
+ stream_match(stream);
+ if (stream->current[0] == '=')
+ {
+ type = '^=';
stream_match(stream);
- if (stream->current[0] == '>')
- {
- type = '->';
- stream_match(stream);
- }
- else if (stream->current[0] == '-')
- {
- type = '--';
- stream_match(stream);
- }
- else if (stream->current[0] == '=')
- {
- type = '-=';
- stream_match(stream);
- }
- break;
- case '|':
- type = '|';
+ }
+ break;
+ case '&':
+ type = '&';
+ stream_match(stream);
+ if (stream->current[0] == '&')
+ {
+ type = '&&';
stream_match(stream);
- if (stream->current[0] == '|')
- {
- type = '||';
- stream_match(stream);
- }
- else if (stream->current[0] == '=')
- {
- type = '|=';
- stream_match(stream);
- }
- break;
- case '+':
- type = '+';
+ }
+ else if (stream->current[0] == '=')
+ {
+ type = '&=';
stream_match(stream);
- if (stream->current[0] == '+')
- {
- type = '++';
- stream_match(stream);
- }
- else if (stream->current[0] == '=')
- {
- type = '+=';
- stream_match(stream);
- }
- break;
- case '=':
- type = '=';
+ }
+ break;
+ case '>':
+ type = '>';
+ stream_match(stream);
+ if (stream->current[0] == '>')
+ {
+ type = '>>';
stream_match(stream);
if (stream->current[0] == '=')
{
- type = '==';
+ type = '>>=';
stream_match(stream);
}
- break;
- case '^':
- type = '^';
+ }
+ else if (stream->current[0] == '=')
+ {
+ type = '>=';
stream_match(stream);
- if (stream->current[0] == '=')
- {
- type = '^=';
- stream_match(stream);
- }
- break;
- case '&':
- type = '&';
+ }
+
+ break;
+ case '<':
+ type = '<';
+ stream_match(stream);
+ if (stream->current[0] == '<')
+ {
+ type = '<<';
stream_match(stream);
- if (stream->current[0] == '&')
- {
- type = '&&';
- stream_match(stream);
- }
- else if (stream->current[0] == '=')
+ if (stream->current[0] == '=')
{
- type = '&=';
+ type = '<<=';
stream_match(stream);
}
- break;
- case '>':
- type = '>';
+ }
+ else if (stream->current[0] == '=')
+ {
+ type = '<=';
stream_match(stream);
- if (stream->current[0] == '>')
- {
- type = '>>';
- stream_match(stream);
- if (stream->current[0] == '=')
- {
- type = '>>=';
- stream_match(stream);
- }
- }
- else if (stream->current[0] == '=')
- {
- type = '>=';
- stream_match(stream);
- }
-
- break;
- case '<':
- type = '<';
+ }
+ break;
+ case '#':
+ type = '#';
+ stream_match(stream);
+ if (stream->current[0] == '#')
+ {
+ type = '##';
stream_match(stream);
- if (stream->current[0] == '<')
- {
- type = '<<';
- stream_match(stream);
- if (stream->current[0] == '=')
- {
- type = '<<=';
- stream_match(stream);
- }
- }
- else if (stream->current[0] == '=')
- {
- type = '<=';
- stream_match(stream);
- }
- break;
- case '#':
- type = '#';
+ }
+ break;
+ case '.':
+ type = '.';
+ stream_match(stream);
+ if (stream->current[0] == '.' && stream->current[1] == '.')
+ {
+ type = '...';
stream_match(stream);
- if (stream->current[0] == '#')
- {
- type = '##';
- stream_match(stream);
- }
- break;
- case '.':
- type = '.';
stream_match(stream);
- if (stream->current[0] == '.' && stream->current[1] == '.')
- {
- type = '...';
- stream_match(stream);
- stream_match(stream);
- }
- break;
+ }
+ break;
}
return type;
}
@@ -3755,7 +3787,7 @@ struct token_list embed_tokenizer(struct preprocessor_ctx* ctx, const char* file
}
char buffer[30] = { 0 };
- int c = snprintf(buffer, sizeof buffer, "%d", (int) ch);
+ int c = snprintf(buffer, sizeof buffer, "%d", (int)ch);
struct token* owner p_new_token = new_token(buffer, &buffer[c], TK_PPNUMBER);
p_new_token->flags |= addflags;
@@ -3848,7 +3880,7 @@ struct token_list tokenizer(struct tokenizer_ctx* ctx, const char* text, const c
//windows have case insensive paths
for (char* p = p_new->lexeme; *p; p++)
{
- *p = (char) tolower(*p);
+ *p = (char)tolower(*p);
}
#endif
p_new->level = level;
@@ -4647,7 +4679,7 @@ long long preprocessor_constant_expression(struct preprocessor_ctx* ctx,
struct token_list list2 = preprocessor(ctx, &list1, 1);
ctx->flags = flags;
-
+
long long value = 0;
if (list2.head == NULL)
@@ -4668,10 +4700,10 @@ long long preprocessor_constant_expression(struct preprocessor_ctx* ctx,
struct preprocessor_ctx pre_ctx = { 0 };
-
+
pre_ctx.input_list = list4;
pre_ctx.current = pre_ctx.input_list.head;
-
+
if (pre_constant_expression(&pre_ctx, &value) != 0)
{
preprocessor_diagnostic_message(C_ERROR_EXPRESSION_ERROR, ctx, first, "expression error");
@@ -4680,7 +4712,7 @@ long long preprocessor_constant_expression(struct preprocessor_ctx* ctx,
ctx->conditional_inclusion = false;
preprocessor_ctx_destroy(&pre_ctx);
-
+
}
@@ -5149,7 +5181,6 @@ struct token_list control_line(struct preprocessor_ctx* ctx, struct token_list*
try
{
-
if (!is_active)
{
//se nao esta ativo eh ignorado
@@ -5569,7 +5600,7 @@ struct token_list control_line(struct preprocessor_ctx* ctx, struct token_list*
if (input_list->head && strcmp(input_list->head->lexeme, "once") == 0)
{
- hashmap_set(&ctx->pragma_once_map, input_list->head->token_origin->lexeme, (void*) 1, 0);
+ hashmap_set(&ctx->pragma_once_map, input_list->head->token_origin->lexeme, (void*)1, 0);
match_token_level(&r, input_list, TK_IDENTIFIER, level, ctx);//pragma
r.tail->flags |= TK_FLAG_FINAL;
}
@@ -5577,6 +5608,12 @@ struct token_list control_line(struct preprocessor_ctx* ctx, struct token_list*
{
match_token_level(&r, input_list, TK_IDENTIFIER, level, ctx);//pragma
skip_blanks_level(ctx, &r, input_list, level);
+ if (input_list->head->type != TK_STRING_LITERAL)
+ {
+ preprocessor_diagnostic_message(C_ERROR_UNEXPECTED, ctx, input_list->head, "expected string");
+ throw;
+ }
+
char path[200] = { 0 };
strncpy(path, input_list->head->lexeme + 1, strlen(input_list->head->lexeme) - 2);
include_dir_add(&ctx->include_dir, path);
@@ -6283,7 +6320,7 @@ int lexeme_cmp(const char* s1, const char* s2)
s2++;
}
- return *(const unsigned char*) s1 - *(const unsigned char*) s2;
+ return *(const unsigned char*)s1 - *(const unsigned char*)s2;
}
void remove_line_continuation(char* s)
@@ -6859,13 +6896,11 @@ void check_unused_macros(struct owner_hash_map* map)
void include_config_header(struct preprocessor_ctx* ctx)
{
-#define CAKE_CFG_FNAME "/cakeconfig.h"
char executable_path[MAX_PATH - sizeof(CAKE_CFG_FNAME)] = { 0 };
get_self_path(executable_path, sizeof(executable_path));
dirname(executable_path);
char path[MAX_PATH] = { 0 };
snprintf(path, sizeof path, "%s" CAKE_CFG_FNAME, executable_path);
-#undef CAKE_CFG_FNAME
/*
* windows
echo %INCLUDE%
@@ -6874,23 +6909,26 @@ void include_config_header(struct preprocessor_ctx* ctx)
*/
char* owner str = read_file(path);
+ if (str)
+ {
+ const enum diagnostic_id w =
+ ctx->options.diagnostic_stack[ctx->options.diagnostic_stack_top_index].warnings;
+ struct tokenizer_ctx tctx = { 0 };
+ struct token_list l = tokenizer(&tctx, str, "standard macros inclusion", 0, TK_FLAG_NONE);
+ struct token_list l10 = preprocessor(ctx, &l, 0);
+ mark_macros_as_used(&ctx->macros);
+ token_list_destroy(&l);
+ free(str);
+ token_list_destroy(&l10);
- const enum diagnostic_id w =
- ctx->options.diagnostic_stack[ctx->options.diagnostic_stack_top_index].warnings;
-
-
-
- struct tokenizer_ctx tctx = { 0 };
- struct token_list l = tokenizer(&tctx, str, "standard macros inclusion", 0, TK_FLAG_NONE);
- struct token_list l10 = preprocessor(ctx, &l, 0);
- mark_macros_as_used(&ctx->macros);
- token_list_destroy(&l);
- free(str);
- token_list_destroy(&l10);
-
- /*restore*/
- ctx->options.diagnostic_stack[ctx->options.diagnostic_stack_top_index].warnings = w;
+ /*restore*/
+ ctx->options.diagnostic_stack[ctx->options.diagnostic_stack_top_index].warnings = w;
+ }
+ else
+ {
+ //cakeconfig.h is optional
+ }
}
void add_standard_macros(struct preprocessor_ctx* ctx)
@@ -6963,7 +7001,7 @@ void add_standard_macros(struct preprocessor_ctx* ctx)
#endif
"#define _INTEGRAL_MAX_BITS " TOSTRING(_INTEGRAL_MAX_BITS) "\n" /*Use of __int64 should be conditional on the predefined macro _INTEGRAL_MAX_BITS*/
-
+
"#define _MSC_VER " TOSTRING(_MSC_VER) "\n"
"#define _M_IX86 " TOSTRING(_M_IX86) "\n"
"#define __fastcall\n"
@@ -7144,191 +7182,191 @@ const char* get_token_name(enum token_type tk)
{
switch (tk)
{
- case TK_NONE: return "TK_NONE";
- case TK_NEWLINE: return "TK_NEWLINE";
- case TK_WHITE_SPACE: return "TK_WHITE_SPACE";
- case TK_EXCLAMATION_MARK: return "TK_EXCLAMATION_MARK";
- case TK_QUOTATION_MARK: return "TK_QUOTATION_MARK";
- case TK_NUMBER_SIGN: return "TK_NUMBER_SIGN";
- case TK_DOLLAR_SIGN: return "TK_DOLLAR_SIGN";
- case TK_PERCENT_SIGN: return "TK_PERCENT_SIGN";
- case TK_AMPERSAND: return "TK_AMPERSAND";
- case TK_APOSTROPHE: return "TK_APOSTROPHE";
- case TK_LEFT_PARENTHESIS: return "TK_LEFT_PARENTHESIS";
- case TK_RIGHT_PARENTHESIS: return "TK_RIGHT_PARENTHESIS";
- case TK_ASTERISK: return "TK_ASTERISK";
- case TK_PLUS_SIGN: return "TK_PLUS_SIGN";
- case TK_COMMA: return "TK_COMMA";
- case TK_HYPHEN_MINUS: return "TK_HYPHEN_MINUS";
- case TK_FULL_STOP: return "TK_FULL_STOP";
- case TK_SOLIDUS: return "TK_SOLIDUS";
- case TK_COLON: return "TK_COLON";
- case TK_SEMICOLON: return "TK_SEMICOLON";
- case TK_LESS_THAN_SIGN: return "TK_LESS_THAN_SIGN";
- case TK_EQUALS_SIGN: return "TK_EQUALS_SIGN";
- case TK_GREATER_THAN_SIGN: return "TK_GREATER_THAN_SIGN";
- case TK_QUESTION_MARK: return "TK_QUESTION_MARK";
- case TK_COMMERCIAL_AT: return "TK_COMMERCIAL_AT";
- case TK_LEFT_SQUARE_BRACKET: return "TK_LEFT_SQUARE_BRACKET";
- case TK_REVERSE_SOLIDUS: return "TK_REVERSE_SOLIDUS";
- case TK_RIGHT_SQUARE_BRACKET: return "TK_RIGHT_SQUARE_BRACKET";
- case TK_CIRCUMFLEX_ACCENT: return "TK_CIRCUMFLEX_ACCENT";
- case TK_FLOW_LINE: return "TK_FLOW_LINE";
- case TK_GRAVE_ACCENT: return "TK_GRAVE_ACCENT";
- case TK_LEFT_CURLY_BRACKET: return "TK_LEFT_CURLY_BRACKET";
- case TK_VERTICAL_LINE: return "TK_VERTICAL_LINE";
- case TK_RIGHT_CURLY_BRACKET: return "TK_RIGHT_CURLY_BRACKET";
- case TK_TILDE: return "TK_TILDE";
- case TK_PREPROCESSOR_LINE: return "TK_PREPROCESSOR_LINE";
- case TK_PRAGMA: return "TK_PRAGMA";
- case TK_STRING_LITERAL: return "TK_STRING_LITERAL";
- case TK_CHAR_CONSTANT: return "TK_CHAR_CONSTANT";
- case TK_LINE_COMMENT: return "TK_LINE_COMMENT";
- case TK_COMMENT: return "TK_COMMENT";
- case TK_PPNUMBER: return "TK_PPNUMBER";
-
- case ANY_OTHER_PP_TOKEN: return "ANY_OTHER_PP_TOKEN"; //@ por ex
-
- /*PPNUMBER sao convertidos para constantes antes do parse*/
- case TK_COMPILER_DECIMAL_CONSTANT: return "TK_COMPILER_DECIMAL_CONSTANT";
- case TK_COMPILER_OCTAL_CONSTANT: return "TK_COMPILER_OCTAL_CONSTANT";
- case TK_COMPILER_HEXADECIMAL_CONSTANT: return "TK_COMPILER_HEXADECIMAL_CONSTANT";
- case TK_COMPILER_BINARY_CONSTANT: return "TK_COMPILER_BINARY_CONSTANT";
- case TK_COMPILER_DECIMAL_FLOATING_CONSTANT: return "TK_COMPILER_DECIMAL_FLOATING_CONSTANT";
- case TK_COMPILER_HEXADECIMAL_FLOATING_CONSTANT: return "TK_COMPILER_HEXADECIMAL_FLOATING_CONSTANT";
-
-
- case TK_PLACEMARKER: return "TK_PLACEMARKER";
-
- case TK_BLANKS: return "TK_BLANKS";
- case TK_PLUSPLUS: return "TK_PLUSPLUS";
- case TK_MINUSMINUS: return "TK_MINUSMINUS";
- case TK_ARROW: return "TK_ARROW";
- case TK_SHIFTLEFT: return "TK_SHIFTLEFT";
- case TK_SHIFTRIGHT: return "TK_SHIFTRIGHT";
- case TK_LOGICAL_OPERATOR_OR: return "TK_LOGICAL_OPERATOR_OR";
- case TK_LOGICAL_OPERATOR_AND: return "TK_LOGICAL_OPERATOR_AND";
-
- case TK_MACRO_CONCATENATE_OPERATOR: return "TK_MACRO_CONCATENATE_OPERATOR";
-
- case TK_IDENTIFIER: return "TK_IDENTIFIER";
- case TK_IDENTIFIER_RECURSIVE_MACRO: return "TK_IDENTIFIER_RECURSIVE_MACRO"; /*usado para evitar recursao expansao macro*/
-
- case TK_BEGIN_OF_FILE: return "TK_BEGIN_OF_FILE";
-
- //C23 keywords
- case TK_KEYWORD_AUTO: return "TK_KEYWORD_AUTO";
- case TK_KEYWORD_BREAK: return "TK_KEYWORD_BREAK";
- case TK_KEYWORD_CASE: return "TK_KEYWORD_CASE";
- case TK_KEYWORD_CONSTEXPR: return "TK_KEYWORD_CONSTEXPR";
- case TK_KEYWORD_CHAR: return "TK_KEYWORD_CHAR";
- case TK_KEYWORD_CONST: return "TK_KEYWORD_CONST";
- case TK_KEYWORD_CONTINUE: return "TK_KEYWORD_CONTINUE";
- case TK_KEYWORD_CATCH: return "TK_KEYWORD_CATCH"; /*extension*/
- case TK_KEYWORD_DEFAULT: return "TK_KEYWORD_DEFAULT";
- case TK_KEYWORD_DO: return "TK_KEYWORD_DO";
- case TK_KEYWORD_DEFER: return "TK_KEYWORD_DEFER"; /*extension*/
- case TK_KEYWORD_DOUBLE: return "TK_KEYWORD_DOUBLE";
- case TK_KEYWORD_ELSE: return "TK_KEYWORD_ELSE";
- case TK_KEYWORD_ENUM: return "TK_KEYWORD_ENUM";
- case TK_KEYWORD_EXTERN: return "TK_KEYWORD_EXTERN";
- case TK_KEYWORD_FLOAT: return "TK_KEYWORD_FLOAT";
- case TK_KEYWORD_FOR: return "TK_KEYWORD_FOR";
- case TK_KEYWORD_GOTO: return "TK_KEYWORD_GOTO";
- case TK_KEYWORD_IF: return "TK_KEYWORD_IF";
- case TK_KEYWORD_INLINE: return "TK_KEYWORD_INLINE";
- case TK_KEYWORD_INT: return "TK_KEYWORD_INT";
- case TK_KEYWORD_LONG: return "TK_KEYWORD_LONG";
- case TK_KEYWORD__INT8: return "TK_KEYWORD__INT8";
- case TK_KEYWORD__INT16: return "TK_KEYWORD__INT16";
- case TK_KEYWORD__INT32: return "TK_KEYWORD__INT32";
- case TK_KEYWORD__INT64: return "TK_KEYWORD__INT64";
-
+ case TK_NONE: return "TK_NONE";
+ case TK_NEWLINE: return "TK_NEWLINE";
+ case TK_WHITE_SPACE: return "TK_WHITE_SPACE";
+ case TK_EXCLAMATION_MARK: return "TK_EXCLAMATION_MARK";
+ case TK_QUOTATION_MARK: return "TK_QUOTATION_MARK";
+ case TK_NUMBER_SIGN: return "TK_NUMBER_SIGN";
+ case TK_DOLLAR_SIGN: return "TK_DOLLAR_SIGN";
+ case TK_PERCENT_SIGN: return "TK_PERCENT_SIGN";
+ case TK_AMPERSAND: return "TK_AMPERSAND";
+ case TK_APOSTROPHE: return "TK_APOSTROPHE";
+ case TK_LEFT_PARENTHESIS: return "TK_LEFT_PARENTHESIS";
+ case TK_RIGHT_PARENTHESIS: return "TK_RIGHT_PARENTHESIS";
+ case TK_ASTERISK: return "TK_ASTERISK";
+ case TK_PLUS_SIGN: return "TK_PLUS_SIGN";
+ case TK_COMMA: return "TK_COMMA";
+ case TK_HYPHEN_MINUS: return "TK_HYPHEN_MINUS";
+ case TK_FULL_STOP: return "TK_FULL_STOP";
+ case TK_SOLIDUS: return "TK_SOLIDUS";
+ case TK_COLON: return "TK_COLON";
+ case TK_SEMICOLON: return "TK_SEMICOLON";
+ case TK_LESS_THAN_SIGN: return "TK_LESS_THAN_SIGN";
+ case TK_EQUALS_SIGN: return "TK_EQUALS_SIGN";
+ case TK_GREATER_THAN_SIGN: return "TK_GREATER_THAN_SIGN";
+ case TK_QUESTION_MARK: return "TK_QUESTION_MARK";
+ case TK_COMMERCIAL_AT: return "TK_COMMERCIAL_AT";
+ case TK_LEFT_SQUARE_BRACKET: return "TK_LEFT_SQUARE_BRACKET";
+ case TK_REVERSE_SOLIDUS: return "TK_REVERSE_SOLIDUS";
+ case TK_RIGHT_SQUARE_BRACKET: return "TK_RIGHT_SQUARE_BRACKET";
+ case TK_CIRCUMFLEX_ACCENT: return "TK_CIRCUMFLEX_ACCENT";
+ case TK_FLOW_LINE: return "TK_FLOW_LINE";
+ case TK_GRAVE_ACCENT: return "TK_GRAVE_ACCENT";
+ case TK_LEFT_CURLY_BRACKET: return "TK_LEFT_CURLY_BRACKET";
+ case TK_VERTICAL_LINE: return "TK_VERTICAL_LINE";
+ case TK_RIGHT_CURLY_BRACKET: return "TK_RIGHT_CURLY_BRACKET";
+ case TK_TILDE: return "TK_TILDE";
+ case TK_PREPROCESSOR_LINE: return "TK_PREPROCESSOR_LINE";
+ case TK_PRAGMA: return "TK_PRAGMA";
+ case TK_STRING_LITERAL: return "TK_STRING_LITERAL";
+ case TK_CHAR_CONSTANT: return "TK_CHAR_CONSTANT";
+ case TK_LINE_COMMENT: return "TK_LINE_COMMENT";
+ case TK_COMMENT: return "TK_COMMENT";
+ case TK_PPNUMBER: return "TK_PPNUMBER";
+
+ case ANY_OTHER_PP_TOKEN: return "ANY_OTHER_PP_TOKEN"; //@ por ex
+
+ /*PPNUMBER sao convertidos para constantes antes do parse*/
+ case TK_COMPILER_DECIMAL_CONSTANT: return "TK_COMPILER_DECIMAL_CONSTANT";
+ case TK_COMPILER_OCTAL_CONSTANT: return "TK_COMPILER_OCTAL_CONSTANT";
+ case TK_COMPILER_HEXADECIMAL_CONSTANT: return "TK_COMPILER_HEXADECIMAL_CONSTANT";
+ case TK_COMPILER_BINARY_CONSTANT: return "TK_COMPILER_BINARY_CONSTANT";
+ case TK_COMPILER_DECIMAL_FLOATING_CONSTANT: return "TK_COMPILER_DECIMAL_FLOATING_CONSTANT";
+ case TK_COMPILER_HEXADECIMAL_FLOATING_CONSTANT: return "TK_COMPILER_HEXADECIMAL_FLOATING_CONSTANT";
+
+
+ case TK_PLACEMARKER: return "TK_PLACEMARKER";
+
+ case TK_BLANKS: return "TK_BLANKS";
+ case TK_PLUSPLUS: return "TK_PLUSPLUS";
+ case TK_MINUSMINUS: return "TK_MINUSMINUS";
+ case TK_ARROW: return "TK_ARROW";
+ case TK_SHIFTLEFT: return "TK_SHIFTLEFT";
+ case TK_SHIFTRIGHT: return "TK_SHIFTRIGHT";
+ case TK_LOGICAL_OPERATOR_OR: return "TK_LOGICAL_OPERATOR_OR";
+ case TK_LOGICAL_OPERATOR_AND: return "TK_LOGICAL_OPERATOR_AND";
+
+ case TK_MACRO_CONCATENATE_OPERATOR: return "TK_MACRO_CONCATENATE_OPERATOR";
+
+ case TK_IDENTIFIER: return "TK_IDENTIFIER";
+ case TK_IDENTIFIER_RECURSIVE_MACRO: return "TK_IDENTIFIER_RECURSIVE_MACRO"; /*usado para evitar recursao expansao macro*/
+
+ case TK_BEGIN_OF_FILE: return "TK_BEGIN_OF_FILE";
+
+ //C23 keywords
+ case TK_KEYWORD_AUTO: return "TK_KEYWORD_AUTO";
+ case TK_KEYWORD_BREAK: return "TK_KEYWORD_BREAK";
+ case TK_KEYWORD_CASE: return "TK_KEYWORD_CASE";
+ case TK_KEYWORD_CONSTEXPR: return "TK_KEYWORD_CONSTEXPR";
+ case TK_KEYWORD_CHAR: return "TK_KEYWORD_CHAR";
+ case TK_KEYWORD_CONST: return "TK_KEYWORD_CONST";
+ case TK_KEYWORD_CONTINUE: return "TK_KEYWORD_CONTINUE";
+ case TK_KEYWORD_CATCH: return "TK_KEYWORD_CATCH"; /*extension*/
+ case TK_KEYWORD_DEFAULT: return "TK_KEYWORD_DEFAULT";
+ case TK_KEYWORD_DO: return "TK_KEYWORD_DO";
+ case TK_KEYWORD_DEFER: return "TK_KEYWORD_DEFER"; /*extension*/
+ case TK_KEYWORD_DOUBLE: return "TK_KEYWORD_DOUBLE";
+ case TK_KEYWORD_ELSE: return "TK_KEYWORD_ELSE";
+ case TK_KEYWORD_ENUM: return "TK_KEYWORD_ENUM";
+ case TK_KEYWORD_EXTERN: return "TK_KEYWORD_EXTERN";
+ case TK_KEYWORD_FLOAT: return "TK_KEYWORD_FLOAT";
+ case TK_KEYWORD_FOR: return "TK_KEYWORD_FOR";
+ case TK_KEYWORD_GOTO: return "TK_KEYWORD_GOTO";
+ case TK_KEYWORD_IF: return "TK_KEYWORD_IF";
+ case TK_KEYWORD_INLINE: return "TK_KEYWORD_INLINE";
+ case TK_KEYWORD_INT: return "TK_KEYWORD_INT";
+ case TK_KEYWORD_LONG: return "TK_KEYWORD_LONG";
+ case TK_KEYWORD__INT8: return "TK_KEYWORD__INT8";
+ case TK_KEYWORD__INT16: return "TK_KEYWORD__INT16";
+ case TK_KEYWORD__INT32: return "TK_KEYWORD__INT32";
+ case TK_KEYWORD__INT64: return "TK_KEYWORD__INT64";
+
+
+ case TK_KEYWORD_REGISTER: return "TK_KEYWORD_REGISTER";
+ case TK_KEYWORD_RESTRICT: return "TK_KEYWORD_RESTRICT";
+ case TK_KEYWORD_RETURN: return "TK_KEYWORD_RETURN";
+ case TK_KEYWORD_SHORT: return "TK_KEYWORD_SHORT";
+ case TK_KEYWORD_SIGNED: return "TK_KEYWORD_SIGNED";
+ case TK_KEYWORD_SIZEOF: return "TK_KEYWORD_SIZEOF";
+
+ case TK_KEYWORD_STATIC: return "TK_KEYWORD_STATIC";
+ case TK_KEYWORD_STRUCT: return "TK_KEYWORD_STRUCT";
+ case TK_KEYWORD_SWITCH: return "TK_KEYWORD_SWITCH";
+ case TK_KEYWORD_TYPEDEF: return "TK_KEYWORD_TYPEDEF";
+ case TK_KEYWORD_TRY: return "TK_KEYWORD_TRY"; /*extension*/
+ case TK_KEYWORD_THROW: return "TK_KEYWORD_THROW"; /*extension*/
+ case TK_KEYWORD_UNION: return "TK_KEYWORD_UNION";
+ case TK_KEYWORD_UNSIGNED: return "TK_KEYWORD_UNSIGNED";
+ case TK_KEYWORD_VOID: return "TK_KEYWORD_VOID";
+ case TK_KEYWORD_VOLATILE: return "TK_KEYWORD_VOLATILE";
+ case TK_KEYWORD_WHILE: return "TK_KEYWORD_WHILE";
+
+ case TK_KEYWORD__ALIGNAS: return "TK_KEYWORD__ALIGNAS";
+ case TK_KEYWORD__ALIGNOF: return "TK_KEYWORD__ALIGNOF";
+ case TK_KEYWORD__ATOMIC: return "TK_KEYWORD__ATOMIC";
+ //microsoft
+ //KEYWORD__FASTCALL,
+ //KEYWORD__STDCALL
+ //
+ case TK_KEYWORD__ASM: return "TK_KEYWORD__ASM";
+ //end microsoft
+ case TK_KEYWORD__BOOL: return "TK_KEYWORD__BOOL";
+ case TK_KEYWORD__COMPLEX: return "TK_KEYWORD__COMPLEX";
+ case TK_KEYWORD__DECIMAL128: return "TK_KEYWORD__DECIMAL128";
+ case TK_KEYWORD__DECIMAL32: return "TK_KEYWORD__DECIMAL32";
+ case TK_KEYWORD__DECIMAL64: return "TK_KEYWORD__DECIMAL64";
+ case TK_KEYWORD__GENERIC: return "TK_KEYWORD__GENERIC";
+ case TK_KEYWORD__IMAGINARY: return "TK_KEYWORD__IMAGINARY";
+ case TK_KEYWORD__NORETURN: return "TK_KEYWORD__NORETURN";
+ case TK_KEYWORD__STATIC_ASSERT: return "TK_KEYWORD__STATIC_ASSERT";
+ case TK_KEYWORD_ASSERT: return "TK_KEYWORD_ASSERT"; /*extension*/
+ case TK_KEYWORD__THREAD_LOCAL: return "TK_KEYWORD__THREAD_LOCAL";
- case TK_KEYWORD_REGISTER: return "TK_KEYWORD_REGISTER";
- case TK_KEYWORD_RESTRICT: return "TK_KEYWORD_RESTRICT";
- case TK_KEYWORD_RETURN: return "TK_KEYWORD_RETURN";
- case TK_KEYWORD_SHORT: return "TK_KEYWORD_SHORT";
- case TK_KEYWORD_SIGNED: return "TK_KEYWORD_SIGNED";
- case TK_KEYWORD_SIZEOF: return "TK_KEYWORD_SIZEOF";
-
- case TK_KEYWORD_STATIC: return "TK_KEYWORD_STATIC";
- case TK_KEYWORD_STRUCT: return "TK_KEYWORD_STRUCT";
- case TK_KEYWORD_SWITCH: return "TK_KEYWORD_SWITCH";
- case TK_KEYWORD_TYPEDEF: return "TK_KEYWORD_TYPEDEF";
- case TK_KEYWORD_TRY: return "TK_KEYWORD_TRY"; /*extension*/
- case TK_KEYWORD_THROW: return "TK_KEYWORD_THROW"; /*extension*/
- case TK_KEYWORD_UNION: return "TK_KEYWORD_UNION";
- case TK_KEYWORD_UNSIGNED: return "TK_KEYWORD_UNSIGNED";
- case TK_KEYWORD_VOID: return "TK_KEYWORD_VOID";
- case TK_KEYWORD_VOLATILE: return "TK_KEYWORD_VOLATILE";
- case TK_KEYWORD_WHILE: return "TK_KEYWORD_WHILE";
-
- case TK_KEYWORD__ALIGNAS: return "TK_KEYWORD__ALIGNAS";
- case TK_KEYWORD__ALIGNOF: return "TK_KEYWORD__ALIGNOF";
- case TK_KEYWORD__ATOMIC: return "TK_KEYWORD__ATOMIC";
- //microsoft
- //KEYWORD__FASTCALL,
- //KEYWORD__STDCALL
- //
- case TK_KEYWORD__ASM: return "TK_KEYWORD__ASM";
- //end microsoft
- case TK_KEYWORD__BOOL: return "TK_KEYWORD__BOOL";
- case TK_KEYWORD__COMPLEX: return "TK_KEYWORD__COMPLEX";
- case TK_KEYWORD__DECIMAL128: return "TK_KEYWORD__DECIMAL128";
- case TK_KEYWORD__DECIMAL32: return "TK_KEYWORD__DECIMAL32";
- case TK_KEYWORD__DECIMAL64: return "TK_KEYWORD__DECIMAL64";
- case TK_KEYWORD__GENERIC: return "TK_KEYWORD__GENERIC";
- case TK_KEYWORD__IMAGINARY: return "TK_KEYWORD__IMAGINARY";
- case TK_KEYWORD__NORETURN: return "TK_KEYWORD__NORETURN";
- case TK_KEYWORD__STATIC_ASSERT: return "TK_KEYWORD__STATIC_ASSERT";
- case TK_KEYWORD_ASSERT: return "TK_KEYWORD_ASSERT"; /*extension*/
- case TK_KEYWORD__THREAD_LOCAL: return "TK_KEYWORD__THREAD_LOCAL";
-
- case TK_KEYWORD_TYPEOF: return "TK_KEYWORD_TYPEOF"; /*C23*/
-
- case TK_KEYWORD_TRUE: return "TK_KEYWORD_TRUE"; /*C23*/
- case TK_KEYWORD_FALSE: return "TK_KEYWORD_FALSE"; /*C23*/
- case TK_KEYWORD_NULLPTR: return "TK_KEYWORD_NULLPTR"; /*C23*/
- case TK_KEYWORD_TYPEOF_UNQUAL: return "TK_KEYWORD_TYPEOF_UNQUAL"; /*C23*/
- case TK_KEYWORD__BITINT: return "TK_KEYWORD__BITINT"; /*C23*/
-
-
-
- /*cake extension*/
- case TK_KEYWORD__OWNER: return "TK_KEYWORD__OWNER";
- case TK_KEYWORD__OUT: return "TK_KEYWORD__OUT";
- case TK_KEYWORD__OBJ_OWNER: return "TK_KEYWORD__OBJ_OWNER";
- case TK_KEYWORD__VIEW: return "TK_KEYWORD__VIEW";
- case TK_KEYWORD__OPT: return "TK_KEYWORD__OPT";
-
+ case TK_KEYWORD_TYPEOF: return "TK_KEYWORD_TYPEOF"; /*C23*/
- /*extension compile time functions*/
- case TK_KEYWORD_STATIC_DEBUG: return "TK_KEYWORD_STATIC_DEBUG"; /*extension*/
- case TK_KEYWORD_STATIC_DEBUG_EX: return "TK_KEYWORD_STATIC_DEBUG_EX"; /*extension*/
- case TK_KEYWORD_STATIC_STATE: return "TK_KEYWORD_STATIC_STATE"; /*extension*/
- case TK_KEYWORD_STATIC_SET: return "TK_KEYWORD_STATIC_SET"; /*extension*/
- case TK_KEYWORD_ATTR_ADD: return "TK_KEYWORD_ATTR_ADD"; /*extension*/
- case TK_KEYWORD_ATTR_REMOVE: return "TK_KEYWORD_ATTR_REMOVE"; /*extension*/
- case TK_KEYWORD_ATTR_HAS: return "TK_KEYWORD_ATTR_HAS"; /*extension*/
-
- /*https://en.cppreference.com/w/cpp/header/type_traits*/
-
- case TK_KEYWORD_IS_POINTER: return "TK_KEYWORD_IS_POINTER";
- case TK_KEYWORD_IS_LVALUE: return "TK_KEYWORD_IS_LVALUE";
- case TK_KEYWORD_IS_CONST: return "TK_KEYWORD_IS_CONST";
- case TK_KEYWORD_IS_OWNER: return "TK_KEYWORD_IS_OWNER";
- case TK_KEYWORD_IS_ARRAY: return "TK_KEYWORD_IS_ARRAY";
- case TK_KEYWORD_IS_FUNCTION: return "TK_KEYWORD_IS_FUNCTION";
- case TK_KEYWORD_IS_SCALAR: return "TK_KEYWORD_IS_SCALAR";
- case TK_KEYWORD_IS_ARITHMETIC: return "TK_KEYWORD_IS_ARITHMETIC";
- case TK_KEYWORD_IS_FLOATING_POINT: return "TK_KEYWORD_IS_FLOATING_POINT";
- case TK_KEYWORD_IS_INTEGRAL: return "TK_KEYWORD_IS_INTEGRAL";
+ case TK_KEYWORD_TRUE: return "TK_KEYWORD_TRUE"; /*C23*/
+ case TK_KEYWORD_FALSE: return "TK_KEYWORD_FALSE"; /*C23*/
+ case TK_KEYWORD_NULLPTR: return "TK_KEYWORD_NULLPTR"; /*C23*/
+ case TK_KEYWORD_TYPEOF_UNQUAL: return "TK_KEYWORD_TYPEOF_UNQUAL"; /*C23*/
+ case TK_KEYWORD__BITINT: return "TK_KEYWORD__BITINT"; /*C23*/
- default:
- return "TK_X_MISSING_NAME";
+
+
+ /*cake extension*/
+ case TK_KEYWORD__OWNER: return "TK_KEYWORD__OWNER";
+ case TK_KEYWORD__OUT: return "TK_KEYWORD__OUT";
+ case TK_KEYWORD__OBJ_OWNER: return "TK_KEYWORD__OBJ_OWNER";
+ case TK_KEYWORD__VIEW: return "TK_KEYWORD__VIEW";
+ case TK_KEYWORD__OPT: return "TK_KEYWORD__OPT";
+
+
+ /*extension compile time functions*/
+ case TK_KEYWORD_STATIC_DEBUG: return "TK_KEYWORD_STATIC_DEBUG"; /*extension*/
+ case TK_KEYWORD_STATIC_DEBUG_EX: return "TK_KEYWORD_STATIC_DEBUG_EX"; /*extension*/
+ case TK_KEYWORD_STATIC_STATE: return "TK_KEYWORD_STATIC_STATE"; /*extension*/
+ case TK_KEYWORD_STATIC_SET: return "TK_KEYWORD_STATIC_SET"; /*extension*/
+ case TK_KEYWORD_ATTR_ADD: return "TK_KEYWORD_ATTR_ADD"; /*extension*/
+ case TK_KEYWORD_ATTR_REMOVE: return "TK_KEYWORD_ATTR_REMOVE"; /*extension*/
+ case TK_KEYWORD_ATTR_HAS: return "TK_KEYWORD_ATTR_HAS"; /*extension*/
+
+ /*https://en.cppreference.com/w/cpp/header/type_traits*/
+
+ case TK_KEYWORD_IS_POINTER: return "TK_KEYWORD_IS_POINTER";
+ case TK_KEYWORD_IS_LVALUE: return "TK_KEYWORD_IS_LVALUE";
+ case TK_KEYWORD_IS_CONST: return "TK_KEYWORD_IS_CONST";
+ case TK_KEYWORD_IS_OWNER: return "TK_KEYWORD_IS_OWNER";
+ case TK_KEYWORD_IS_ARRAY: return "TK_KEYWORD_IS_ARRAY";
+ case TK_KEYWORD_IS_FUNCTION: return "TK_KEYWORD_IS_FUNCTION";
+ case TK_KEYWORD_IS_SCALAR: return "TK_KEYWORD_IS_SCALAR";
+ case TK_KEYWORD_IS_ARITHMETIC: return "TK_KEYWORD_IS_ARITHMETIC";
+ case TK_KEYWORD_IS_FLOATING_POINT: return "TK_KEYWORD_IS_FLOATING_POINT";
+ case TK_KEYWORD_IS_INTEGRAL: return "TK_KEYWORD_IS_INTEGRAL";
+
+ default:
+ break;
}
- return "";
+ return "TK_X_MISSING_NAME";
};
@@ -7384,11 +7422,11 @@ void print_literal(const char* s)
{
switch (*s)
{
- case '\n':
- printf("\\n");
- break;
- default:
- printf("%c", *s);
+ case '\n':
+ printf("\\n");
+ break;
+ default:
+ printf("%c", *s);
}
s++;
}
@@ -7429,7 +7467,7 @@ const char* owner get_code_as_we_see_plus_macros(struct token_list* list)
/*useful to debug visit.c*/
void print_code_as_we_see(struct token_list* list, bool remove_comments)
{
-
+
struct token* current = list->head;
while (current && current != list->tail->next)
{
@@ -10337,7 +10375,8 @@ int fill_options(struct options* options,
}
- if (strcmp(argv[i], "-msvc-output") == 0)
+ if (strcmp(argv[i], "-msvc-output") == 0 ||
+ strcmp(argv[i], "-fdiagnostics-format=msvc") == 0) //same as clang
{
options->visual_studio_ouput_format = true;
continue;
@@ -10377,6 +10416,12 @@ int fill_options(struct options* options,
continue;
}
+ if (strcmp(argv[i], "-autoconfig") == 0)
+ {
+ options->auto_config = true;
+ continue;
+ }
+
//
if (strcmp(argv[i], "-target=c89") == 0)
{
@@ -11160,6 +11205,12 @@ void expression_evaluate_equal_not_equal(const struct expression* left,
int op,
bool disabled);
+void check_diferent_enuns(struct parser_ctx* ctx,
+ const struct token* operator_token,
+ struct expression* left,
+ struct expression* right,
+ const char * message);
+
//#pragma once
@@ -11264,8 +11315,9 @@ struct flow_object
struct flow_object_state current;
int id; //helps debugging
- bool is_temporary;
+ bool is_temporary;
};
+
void flow_object_set_is_moved(struct flow_object* p_object);
void flow_object_set_can_be_uninitialized(struct flow_object* p_object);
void flow_object_set_is_unitialized(struct flow_object* p_object);
@@ -11275,15 +11327,22 @@ void flow_object_set_current_state_to_is_null(struct flow_object* p);
int flow_object_add_state(struct flow_object* p, struct flow_object_state *owner pnew);
+bool flow_object_is_zero_or_null(const struct flow_object* p_object);
bool flow_object_is_not_null(struct flow_object* p);
+bool flow_object_can_be_not_null_or_moved(struct flow_object* p);
+
bool flow_object_is_null(struct flow_object* p);
+bool flow_object_can_be_null(struct flow_object* p);
+
bool flow_object_is_not_zero(struct flow_object* p);
bool flow_object_is_zero(struct flow_object* p);
-bool flow_object_maybe_is_null(struct flow_object* p);
bool flow_object_is_uninitialized(struct flow_object* p);
+bool flow_object_can_be_uninitialized(struct flow_object* p);
+
+bool flow_object_can_have_its_lifetime_ended(struct flow_object* p);
void flow_object_print_state(struct flow_object* p);
@@ -11341,7 +11400,7 @@ void checked_read_object(struct flow_visit_ctx* ctx,
const struct token* position_token,
bool check_pointed_object);
-bool object_is_zero_or_null(const struct flow_object* p_object);
+
void end_of_storage_visit(struct flow_visit_ctx* ctx,
struct type* p_type,
bool type_is_view,
@@ -11396,8 +11455,12 @@ struct report
int test_succeeded;
enum diagnostic_id last_diagnostic_id;
-};
+ /*
+ direct commands like -autoconfig doesnt use report
+ */
+ bool ignore_this_report;
+};
struct parser_ctx
{
@@ -11418,6 +11481,13 @@ struct parser_ctx
*/
const struct try_statement* p_current_try_statement_opt;
+ /*
+ * Points to the select_stament we're in. Or null.
+ */
+ const struct selection_statement * p_current_selection_statement;
+
+
+
FILE* owner sarif_file;
view struct token_list input_list;
@@ -12835,7 +12905,7 @@ double constant_value_to_double(const struct constant_value* a)
case TYPE_UNSIGNED_LONG_LONG:
return (double)a->ullvalue;
default:
- return 0;
+ break;
}
return 0;
@@ -12877,7 +12947,7 @@ unsigned long long constant_value_to_ull(const struct constant_value* a)
case TYPE_UNSIGNED_LONG_LONG:
return (unsigned long long)a->ullvalue;
default:
- return 0;
+ break;
}
return 0;
@@ -12893,7 +12963,7 @@ long long constant_value_to_ll(const struct constant_value* a)
case TYPE_UNSIGNED_LONG_LONG:
return (long long)a->ullvalue;
default:
- return 0;
+ break;
}
return 0;
@@ -12909,7 +12979,7 @@ bool constant_value_to_bool(const struct constant_value* a)
case TYPE_UNSIGNED_LONG_LONG:
return a->ullvalue != 0;
default:
- return 0;
+ break;
}
return 0;
@@ -13303,14 +13373,14 @@ static int compare_function_arguments(struct parser_ctx* ctx,
p_current_parameter_type = p_param_list->head;
}
-
+
struct argument_expression* p_current_argument = p_argument_expression_list->head;
while (p_current_argument && p_current_parameter_type)
{
check_assigment(ctx, &p_current_parameter_type->type, p_current_argument->expression, ASSIGMENT_TYPE_PARAMETER);
p_current_argument = p_current_argument->next;
- p_current_parameter_type = p_current_parameter_type->next;
+ p_current_parameter_type = p_current_parameter_type->next;
}
if (p_current_argument != NULL && !p_param_list->is_var_args)
@@ -15752,7 +15822,7 @@ struct expression* owner additive_expression(struct parser_ctx* ctx)
new_expression->left = p_expression_node;
p_expression_node = NULL; /*MOVED*/
-
+
new_expression->right = multiplicative_expression(ctx);
if (new_expression->right == NULL)
{
@@ -16079,10 +16149,11 @@ struct expression* owner relational_expression(struct parser_ctx* ctx)
return p_expression_node;
}
-static void check_diferent_enuns(struct parser_ctx* ctx,
+void check_diferent_enuns(struct parser_ctx* ctx,
const struct token* operator_token,
struct expression* left,
- struct expression* right)
+ struct expression* right,
+ const char * message)
{
if (left->type.type_specifier_flags & TYPE_SPECIFIER_ENUM &&
right->type.type_specifier_flags & TYPE_SPECIFIER_ENUM)
@@ -16098,10 +16169,18 @@ static void check_diferent_enuns(struct parser_ctx* ctx,
if (right->type.enum_specifier->tag_token)
righttag = right->type.enum_specifier->tag_token->lexeme;
+ char finalmessage[200]={0};
+ snprintf(finalmessage,
+ sizeof finalmessage,
+ "%s (enum %s, enum %s)",
+ message,
+ lefttag,
+ righttag);
+
compiler_diagnostic_message(W_ENUN_CONVERSION,
ctx,
operator_token,
- "implicit conversion from 'enum %s' to 'enum %s'",
+ finalmessage,
lefttag,
righttag);
}
@@ -16165,7 +16244,8 @@ struct expression* owner equality_expression(struct parser_ctx* ctx)
throw;
new_expression->last_token = new_expression->right->last_token;
- check_diferent_enuns(ctx, operator_token, new_expression->left, new_expression->right);
+ check_diferent_enuns(ctx, operator_token, new_expression->left, new_expression->right,
+ "comparing different enums.");
new_expression->first_token = operator_token;
@@ -16331,7 +16411,6 @@ struct expression* owner exclusive_or_expression(struct parser_ctx* ctx)
struct expression* owner inclusive_or_expression(struct parser_ctx* ctx)
{
-
/*
inclusive-OR-expression:
exclusive-OR-expression
@@ -16347,6 +16426,7 @@ struct expression* owner inclusive_or_expression(struct parser_ctx* ctx)
while (ctx->current != NULL &&
(ctx->current->type == '|'))
{
+ struct token* operator_token = ctx->current;
parser_match(ctx);
struct expression* owner new_expression = calloc(1, sizeof * new_expression);
if (new_expression == NULL)
@@ -16364,6 +16444,13 @@ struct expression* owner inclusive_or_expression(struct parser_ctx* ctx)
expression_delete(new_expression);
throw;
}
+
+ check_diferent_enuns(ctx,
+ operator_token,
+ new_expression->left,
+ new_expression->right,
+ "operator '|' between enumerations of different types.");
+
new_expression->last_token = new_expression->right->last_token;
new_expression->constant_value =
constant_value_op(&new_expression->left->constant_value, &new_expression->right->constant_value, '|');
@@ -16619,7 +16706,9 @@ struct expression* owner assignment_expression(struct parser_ctx* ctx)
new_expression->type.storage_class_specifier_flags &= ~STORAGE_SPECIFIER_FUNCTION_RETURN;
new_expression->type.storage_class_specifier_flags &= ~STORAGE_SPECIFIER_FUNCTION_RETURN_NODISCARD;
- check_diferent_enuns(ctx, op_token, new_expression->left, new_expression->right);
+ check_diferent_enuns(ctx, op_token, new_expression->left, new_expression->right,
+ "assignment of different enums.");
+
new_expression->left->is_assigment_expression = true;
if (new_expression->left->left)
new_expression->left->left->is_assigment_expression = true;
@@ -16643,7 +16732,7 @@ void argument_expression_list_push(struct argument_expression_list* list, struct
}
else
{
- assert(list->tail->next == NULL);
+ assert(list->tail->next == NULL);
list->tail->next = pitem;
}
list->tail = pitem;
@@ -21067,6 +21156,13 @@ bool flow_object_is_not_null(struct flow_object* p)
}
+bool flow_object_can_be_not_null_or_moved(struct flow_object* p)
+{
+ enum object_state e = p->current.state;
+ return (e & OBJECT_STATE_NOT_NULL) ||
+ (e & OBJECT_STATE_MOVED);
+}
+
bool flow_object_is_null(struct flow_object* p)
{
enum object_state e = p->current.state;
@@ -21089,7 +21185,7 @@ bool flow_object_is_not_zero(struct flow_object* p)
(e & OBJECT_STATE_NOT_ZERO));
}
-bool flow_object_maybe_is_null(struct flow_object* p)
+bool flow_object_can_be_null(struct flow_object* p)
{
enum object_state e = p->current.state;
@@ -21097,11 +21193,23 @@ bool flow_object_maybe_is_null(struct flow_object* p)
}
bool flow_object_is_uninitialized(struct flow_object* p)
+{
+ enum object_state e = p->current.state;
+ return e == OBJECT_STATE_UNINITIALIZED;
+}
+
+bool flow_object_can_be_uninitialized(struct flow_object* p)
{
enum object_state e = p->current.state;
return (e & OBJECT_STATE_UNINITIALIZED);
}
+bool flow_object_can_have_its_lifetime_ended(struct flow_object* p)
+{
+ enum object_state e = p->current.state;
+ return (e & OBJECT_STATE_LIFE_TIME_ENDED);
+}
+
static void object_state_to_string_core(enum object_state e)
{
@@ -21542,11 +21650,11 @@ struct flow_object* make_object_core(struct flow_visit_ctx* ctx,
//assert((p_declarator_opt == NULL) != (p_expression_origin == NULL));
if (p_declarator_opt == NULL)
{
- assert(p_expression_origin != NULL);
+ //assert(p_expression_origin != NULL);
}
if (p_expression_origin == NULL)
{
- assert(p_declarator_opt != NULL);
+ // assert(p_declarator_opt != NULL);
}
@@ -21844,7 +21952,7 @@ void print_object_core(int ident,
if (flow_object_is_null(p_visitor->p_object))
{
}
- else if (flow_object_is_uninitialized(p_visitor->p_object))
+ else if (flow_object_can_be_uninitialized(p_visitor->p_object))
{
}
else
@@ -23224,7 +23332,7 @@ void checked_read_object_core(struct flow_visit_ctx* ctx,
if (type_is_pointer(p_visitor->p_type) &&
!is_nullable &&
!type_is_nullable(p_visitor->p_type, ctx->ctx->options.null_checks_enabled) &&
- flow_object_maybe_is_null(p_visitor->p_object))
+ flow_object_can_be_null(p_visitor->p_object))
{
compiler_diagnostic_message(W_FLOW_NULL_DEREFERENCE,
ctx->ctx,
@@ -23235,8 +23343,7 @@ void checked_read_object_core(struct flow_visit_ctx* ctx,
if (type_is_pointer(p_visitor->p_type) &&
check_pointed_object &&
- p_visitor->p_object->current.state & OBJECT_STATE_NOT_NULL /*we don't need to check pointed object*/
- )
+ flow_object_can_be_not_null_or_moved(p_visitor->p_object))
{
struct type t2 = type_remove_pointer(p_visitor->p_type);
@@ -23268,18 +23375,18 @@ void checked_read_object_core(struct flow_visit_ctx* ctx,
previous_names);
}
-#if 0
+
//TODO there is some problem with OBJECT_STATE_LIFE_TIME_ENDED
//state somewhere!
- if (p_object->current.state & OBJECT_STATE_LIFE_TIME_ENDED)
+ if (p_visitor->p_object->current.state & OBJECT_STATE_LIFE_TIME_ENDED)
{
- compiler_diagnostic_message(W_FLOW_UNINITIALIZED,
- ctx->ctx,
- position_token,
- "lifetime ended '%s'",
- previous_names);
+ //compiler_diagnostic_message(W_FLOW_UNINITIALIZED,
+ // ctx->ctx,
+ // position_token,
+ // "lifetime ended '%s'",
+ // previous_names);
}
-#endif
+
}
}
@@ -23556,14 +23663,12 @@ void end_of_storage_visit(struct flow_visit_ctx* ctx,
s_visit_number++);
}
-
-bool object_is_zero_or_null(const struct flow_object* p_object)
+bool flow_object_is_zero_or_null(const struct flow_object* p_object)
{
return (p_object->current.state == OBJECT_STATE_NULL) ||
(p_object->current.state == OBJECT_STATE_ZERO);
}
-
/*
This function must check and do the flow assignment of
a = b
@@ -23670,7 +23775,7 @@ static void flow_assignment_core(
checked_empty(ctx, p_visitor_a->p_type, p_visitor_a->p_object, error_position);
}
- if (object_is_zero_or_null(p_visitor_b->p_object))
+ if (flow_object_is_zero_or_null(p_visitor_b->p_object))
{
if (type_is_array(p_visitor_b->p_type))
{
@@ -23702,7 +23807,7 @@ static void flow_assignment_core(
{
checked_empty(ctx, p_visitor_a->p_type, p_visitor_a->p_object, error_position);
- if (object_is_zero_or_null(p_visitor_b->p_object))
+ if (flow_object_is_zero_or_null(p_visitor_b->p_object))
{
//0 to objec_owner??
//a = nullpr
@@ -27226,12 +27331,12 @@ struct init_declarator* owner init_declarator(struct parser_ctx* ctx,
p_init_declarator->p_declarator->direct_declarator->array_declarator != NULL ||
p_init_declarator->p_declarator->direct_declarator->function_declarator != NULL)
{
- compiler_diagnostic_message(C_ERROR_AUTO_NEEDS_SINGLE_DECLARATOR, ctx, p_init_declarator->p_declarator->first_token, "'auto' requires a plain identifier, possibly with attributes, as declarator");
+ compiler_diagnostic_message(C_ERROR_AUTO_NEEDS_SINGLE_DECLARATOR, ctx, p_init_declarator->p_declarator->first_token, "'auto' requires a plain identifier");
throw;
}
if (p_init_declarator->p_declarator->pointer != NULL)
{
- compiler_diagnostic_message(C_ERROR_AUTO_NEEDS_SINGLE_DECLARATOR, ctx, p_init_declarator->p_declarator->first_token, "'auto' requires a plain identifier, possibly with attributes, as declarator");
+ compiler_diagnostic_message(C_ERROR_AUTO_NEEDS_SINGLE_DECLARATOR, ctx, p_init_declarator->p_declarator->first_token, "'auto' requires a plain identifier");
throw;
}
@@ -31027,6 +31132,28 @@ struct label* owner label(struct parser_ctx* ctx)
p_label->constant_expression = constant_expression(ctx, true);
if (parser_match_tk(ctx, ':') != 0)
throw;
+ if (p_label->constant_expression &&
+ ctx->p_current_selection_statement &&
+ ctx->p_current_selection_statement->condition &&
+ ctx->p_current_selection_statement->condition->expression)
+ {
+ if (type_is_enum(&ctx->p_current_selection_statement->condition->expression->type))
+ {
+ if (type_is_enum(&p_label->constant_expression->type))
+ {
+ check_diferent_enuns(ctx,
+ p_label->constant_expression->first_token,
+ p_label->constant_expression,
+ ctx->p_current_selection_statement->condition->expression,
+ "switch case between enumerations of different types.");
+ }
+ else
+ {
+ //enum and something else...
+ }
+ }
+ }
+
}
else if (ctx->current->type == TK_KEYWORD_DEFAULT)
{
@@ -31557,7 +31684,11 @@ struct selection_statement* owner selection_statement(struct parser_ctx* ctx)
//compiler_diagnostic_message(W_CONDITIONAL_IS_CONSTANT, ctx, p_selection_statement->init_statement_expression->first_token, "conditional expression is constant");
//}
+ const struct selection_statement* previous = ctx->p_current_selection_statement;
+ ctx->p_current_selection_statement = p_selection_statement;
p_selection_statement->secondary_block = secondary_block(ctx);
+ ctx->p_current_selection_statement = previous;
+
if (p_selection_statement->secondary_block == NULL)
throw;
@@ -32197,7 +32328,7 @@ WINBASEAPI DWORD WINAPI GetEnvironmentVariableA(
LPCSTR lpName,
LPSTR lpBuffer,
DWORD nSize
- );
+);
#else
@@ -32315,6 +32446,143 @@ void ast_format_visit(struct ast* ast)
void c_visit(struct ast* ast)
{}
+
+int generate_config_file(const char* configpath)
+{
+ FILE* outfile = NULL;
+ int error = 0;
+ try
+ {
+ outfile = fopen(configpath, "w");
+ if (outfile == NULL)
+ {
+ printf("Cannot open the file '%s' for writing.\n", configpath);
+ error = errno;
+ throw;
+ }
+
+ fprintf(outfile, "//This was generated by running cake -autoconfig \n");
+
+
+#ifdef __linux__
+
+ fprintf(outfile, "This file was generated reading the ouput of\n");
+ fprintf(outfile, "//echo | gcc -v -E - 2>&1\n");
+ fprintf(outfile, "\n");
+
+ char path[400] = { 0 };
+ char* command = "echo | gcc -v -E - 2>&1";
+ int in_include_section = 0;
+
+ // Open the command for reading
+ FILE* fp = popen(command, "r");
+ if (fp == NULL)
+ {
+ fprintf(stderr, "Failed to run command\n");
+ error = errno;
+ throw;
+ }
+
+ // Read the output a line at a time
+ while (fgets(path, sizeof(path), fp) != NULL)
+ {
+ // Check if we are in the "#include <...> search starts here:" section
+ if (strstr(path, "#include <...> search starts here:") != NULL)
+ {
+ in_include_section = 1;
+ continue;
+ }
+ // Check if we have reached the end of the include section
+ if (in_include_section && strstr(path, "End of search list.") != NULL)
+ {
+ break;
+ }
+ // Print the include directories
+ if (in_include_section)
+ {
+ const char* p = path;
+ while (*p == ' ') p++;
+
+ int len = strlen(path);
+ if (path[len - 1] == '\n')
+ path[len - 1] = '\0';
+
+ fprintf(outfile, "#pragma dir \"%s\"\n", p);
+ }
+ }
+
+ fprintf(outfile, "\n");
+
+ // Close the command stream
+ pclose(fp);
+
+#endif
+
+#ifdef _WIN32
+ char env[2000] = { 0 };
+ int n = GetEnvironmentVariableA("INCLUDE", env, sizeof(env));
+
+ if (n <= 0)
+ {
+ printf("INCLUDE not found.\nPlease, run cake -autoconfig inside visual studio command prompty.\n");
+ error = 1;
+ throw;
+ }
+
+ fprintf(outfile, "This file was generated reading the variable INCLUDE inside Visual Studio Command Prompt.\n");
+ fprintf(outfile, "echo %%INCLUDE%% \n");
+
+ const char* p = env;
+ for (;;)
+ {
+ if (*p == '\0')
+ {
+ break;
+ }
+ char filename_local[500] = { 0 };
+ int count = 0;
+ while (*p != '\0' && (*p != ';' && *p != '\n'))
+ {
+ filename_local[count] = *p;
+ p++;
+ count++;
+ }
+ filename_local[count] = 0;
+ if (count > 0)
+ {
+ strcat(filename_local, "/");
+ char* pch = filename_local;
+ while (*pch)
+ {
+ if (*pch == '\\')
+ *pch = '/';
+ pch++;
+ }
+
+ fprintf(outfile, "#pragma dir \"%s\"\n", filename_local);
+ }
+ if (*p == '\0')
+ {
+ break;
+ }
+ p++;
+ }
+#endif
+ }
+ catch
+ {
+ }
+ if (outfile)
+ fclose(outfile);
+
+ if (error == 0)
+ {
+ printf("file '%s'\n", configpath);
+ printf("successfully generated\n");
+ }
+ return error;
+}
+
int compile_one_file(const char* file_name,
struct options* options,
const char* out_file_name,
@@ -32708,6 +32976,17 @@ int compile(int argc, const char** argv, struct report* report)
return 1;
}
+ char executable_path[MAX_PATH - sizeof(CAKE_CFG_FNAME)] = { 0 };
+ get_self_path(executable_path, sizeof(executable_path));
+ dirname(executable_path);
+ char cakeconfig_path[MAX_PATH] = { 0 };
+ snprintf(cakeconfig_path, sizeof cakeconfig_path, "%s" CAKE_CFG_FNAME, executable_path);
+
+ if (options.auto_config) //-autoconfig
+ {
+ report->ignore_this_report = true;
+ return generate_config_file(cakeconfig_path);
+ }
report->test_mode = options.test_mode;
@@ -37587,7 +37866,7 @@ static void flow_visit_expression(struct flow_visit_ctx* ctx, struct expression*
if (p_object != NULL)
{
- if (p_object->current.state & OBJECT_STATE_NULL)
+ if (flow_object_can_be_null(p_object))
{
if (ctx->expression_is_not_evaluated)
{
@@ -37599,7 +37878,7 @@ static void flow_visit_expression(struct flow_visit_ctx* ctx, struct expression*
p_expression->left->first_token, "object is possibly null");
}
}
- else if (p_object->current.state & OBJECT_STATE_UNINITIALIZED)
+ else if (flow_object_can_be_uninitialized(p_object))
{
if (ctx->expression_is_not_evaluated)
{
@@ -37611,7 +37890,7 @@ static void flow_visit_expression(struct flow_visit_ctx* ctx, struct expression*
p_expression->left->first_token, "object is possibly uninitialized");
}
}
- else if (p_object->current.state & OBJECT_STATE_LIFE_TIME_ENDED)
+ else if (flow_object_can_have_its_lifetime_ended(p_object))
{
if (ctx->expression_is_not_evaluated)
{
@@ -37736,6 +38015,7 @@ static void flow_visit_expression(struct flow_visit_ctx* ctx, struct expression*
break;
case UNARY_EXPRESSION_NOT:
+ flow_check_pointer_used_as_bool(ctx, p_expression->right);
flow_visit_expression(ctx, p_expression->right, d);
declarator_array_invert(d);
break;
@@ -37796,7 +38076,7 @@ static void flow_visit_expression(struct flow_visit_ctx* ctx, struct expression*
p_expression->right->first_token, "using a uninitialized object");
}
}
- else if (p_object0 && flow_object_maybe_is_null(p_object0))
+ else if (p_object0 && flow_object_can_be_null(p_object0))
{
/*
*p = 1*
@@ -38051,8 +38331,8 @@ static void flow_visit_expression(struct flow_visit_ctx* ctx, struct expression*
case LOGICAL_AND_EXPRESSION:
{
- //flow_check_pointer_used_as_bool(ctx, p_expression->left);
- //flow_check_pointer_used_as_bool(ctx, p_expression->right);
+ flow_check_pointer_used_as_bool(ctx, p_expression->left);
+ flow_check_pointer_used_as_bool(ctx, p_expression->right);
struct declarator_array left_set = { 0 };
flow_visit_expression(ctx, p_expression->left, &left_set);
diff --git a/src/main.c b/src/main.c
index 3393f711..a43e9431 100644
--- a/src/main.c
+++ b/src/main.c
@@ -51,6 +51,9 @@ int main(int argc, char** argv)
//-msvc-output
+ /*
+ /nologo ?
+ */
printf("Cake " CAKE_VERSION "\n");
printf("\n\n");
@@ -63,7 +66,11 @@ int main(int argc, char** argv)
struct report report = { 0 };
compile(argc, (const char**)argv, &report);
- print_report(&report, true);
+
+ if (!report.ignore_this_report)
+ {
+ print_report(&report, true);
+ }
return report.error_count > 0 ? EXIT_FAILURE : EXIT_SUCCESS;
diff --git a/src/options.c b/src/options.c
index 06a5a0de..a6797329 100644
--- a/src/options.c
+++ b/src/options.c
@@ -291,7 +291,8 @@ int fill_options(struct options* options,
}
- if (strcmp(argv[i], "-msvc-output") == 0)
+ if (strcmp(argv[i], "-msvc-output") == 0 ||
+ strcmp(argv[i], "-fdiagnostics-format=msvc") == 0) //same as clang
{
options->visual_studio_ouput_format = true;
continue;
@@ -331,6 +332,12 @@ int fill_options(struct options* options,
continue;
}
+ if (strcmp(argv[i], "-autoconfig") == 0)
+ {
+ options->auto_config = true;
+ continue;
+ }
+
//
if (strcmp(argv[i], "-target=c89") == 0)
{
diff --git a/src/options.h b/src/options.h
index efa1e70d..b741c03a 100644
--- a/src/options.h
+++ b/src/options.h
@@ -333,6 +333,7 @@ struct options
/*
+ -fdiagnostics-format=msvc
-msvc-output
*/
bool visual_studio_ouput_format;
@@ -349,6 +350,11 @@ struct options
*/
bool dump_pptokens;
+ /*
+ -autoconfig
+ */
+ bool auto_config;
+
/*
-o filename
defines the ouputfile when 1 file is used
diff --git a/src/parser.c b/src/parser.c
index 60622bc8..26ad76d8 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -2589,12 +2589,12 @@ struct init_declarator* owner init_declarator(struct parser_ctx* ctx,
p_init_declarator->p_declarator->direct_declarator->array_declarator != NULL ||
p_init_declarator->p_declarator->direct_declarator->function_declarator != NULL)
{
- compiler_diagnostic_message(C_ERROR_AUTO_NEEDS_SINGLE_DECLARATOR, ctx, p_init_declarator->p_declarator->first_token, "'auto' requires a plain identifier, possibly with attributes, as declarator");
+ compiler_diagnostic_message(C_ERROR_AUTO_NEEDS_SINGLE_DECLARATOR, ctx, p_init_declarator->p_declarator->first_token, "'auto' requires a plain identifier");
throw;
}
if (p_init_declarator->p_declarator->pointer != NULL)
{
- compiler_diagnostic_message(C_ERROR_AUTO_NEEDS_SINGLE_DECLARATOR, ctx, p_init_declarator->p_declarator->first_token, "'auto' requires a plain identifier, possibly with attributes, as declarator");
+ compiler_diagnostic_message(C_ERROR_AUTO_NEEDS_SINGLE_DECLARATOR, ctx, p_init_declarator->p_declarator->first_token, "'auto' requires a plain identifier");
throw;
}
@@ -3817,6 +3817,18 @@ struct type_specifier_qualifier* owner type_specifier_qualifier(struct parser_ct
return type_specifier_qualifier;
}
+const struct enumerator* find_enumerator_by_value(const struct enum_specifier* p_enum_specifier, long long value)
+{
+ struct enumerator* p = p_enum_specifier->enumerator_list.head;
+ while (p)
+ {
+ if (p->value == value)
+ return p;
+ p = p->next;
+ }
+ return NULL;
+}
+
void enum_specifier_delete(struct enum_specifier* owner opt p)
{
if (p)
@@ -6390,6 +6402,70 @@ struct label* owner label(struct parser_ctx* ctx)
p_label->constant_expression = constant_expression(ctx, true);
if (parser_match_tk(ctx, ':') != 0)
throw;
+
+ long long case_value = constant_value_to_ll(&p_label->constant_expression->constant_value);
+
+ struct switch_value* p_switch_value = ctx->switch_value;
+ while (p_switch_value)
+ {
+ if (p_switch_value->value == case_value)
+ {
+ //already handled
+ break;
+ }
+ p_switch_value = p_switch_value->next;
+ }
+
+ struct switch_value* newvalue = calloc(1, sizeof * newvalue);
+ if (newvalue)
+ {
+ newvalue->value = case_value;
+ newvalue->next = ctx->switch_value ? ctx->switch_value->next : NULL;
+ ctx->switch_value = newvalue;
+ }
+
+ if (p_label->constant_expression &&
+ ctx->p_current_selection_statement &&
+ ctx->p_current_selection_statement->condition &&
+ ctx->p_current_selection_statement->condition->expression)
+ {
+ if (type_is_enum(&ctx->p_current_selection_statement->condition->expression->type))
+ {
+ if (type_is_enum(&p_label->constant_expression->type))
+ {
+ check_diferent_enuns(ctx,
+ p_label->constant_expression->first_token,
+ p_label->constant_expression,
+ ctx->p_current_selection_statement->condition->expression,
+ "mismatch in enumeration types");
+ }
+ else
+ {
+ //enum and something else...
+ }
+ }
+
+ const struct enum_specifier* p_enum_specifier =
+ get_complete_enum_specifier(ctx->p_current_selection_statement->condition->expression->type.enum_specifier);
+ if (p_enum_specifier)
+ {
+ const struct enumerator* p_enumerator = find_enumerator_by_value(p_enum_specifier, case_value);
+ if (p_enumerator == NULL)
+ {
+ compiler_diagnostic_message(W_ENUN_CONVERSION,
+ ctx,
+ p_label->constant_expression->first_token,
+ "case value '%lld' not in enumerated type 'enum %s'",
+ case_value,
+ p_enum_specifier->tag_name);
+ }
+ else
+ {
+
+ }
+ }
+ }
+
}
else if (ctx->current->type == TK_KEYWORD_DEFAULT)
{
@@ -6920,7 +6996,17 @@ struct selection_statement* owner selection_statement(struct parser_ctx* ctx)
//compiler_diagnostic_message(W_CONDITIONAL_IS_CONSTANT, ctx, p_selection_statement->init_statement_expression->first_token, "conditional expression is constant");
//}
+ const struct selection_statement* previous = ctx->p_current_selection_statement;
+ ctx->p_current_selection_statement = p_selection_statement;
+
+ struct switch_value* previous_switch_value = ctx->switch_value;
+
p_selection_statement->secondary_block = secondary_block(ctx);
+ ctx->p_current_selection_statement = previous;
+
+ //ver auqias naoi foram usados
+ ctx->switch_value = previous_switch_value;
+
if (p_selection_statement->secondary_block == NULL)
throw;
@@ -7560,7 +7646,7 @@ WINBASEAPI DWORD WINAPI GetEnvironmentVariableA(
LPCSTR lpName,
LPSTR lpBuffer,
DWORD nSize
- );
+);
#else
@@ -7678,6 +7764,143 @@ void ast_format_visit(struct ast* ast)
void c_visit(struct ast* ast)
{}
+
+int generate_config_file(const char* configpath)
+{
+ FILE* outfile = NULL;
+ int error = 0;
+ try
+ {
+ outfile = fopen(configpath, "w");
+ if (outfile == NULL)
+ {
+ printf("Cannot open the file '%s' for writing.\n", configpath);
+ error = errno;
+ throw;
+ }
+
+ fprintf(outfile, "//This was generated by running cake -autoconfig \n");
+
+
+#ifdef __linux__
+
+ fprintf(outfile, "This file was generated reading the ouput of\n");
+ fprintf(outfile, "//echo | gcc -v -E - 2>&1\n");
+ fprintf(outfile, "\n");
+
+ char path[400] = { 0 };
+ char* command = "echo | gcc -v -E - 2>&1";
+ int in_include_section = 0;
+
+ // Open the command for reading
+ FILE* fp = popen(command, "r");
+ if (fp == NULL)
+ {
+ fprintf(stderr, "Failed to run command\n");
+ error = errno;
+ throw;
+ }
+
+ // Read the output a line at a time
+ while (fgets(path, sizeof(path), fp) != NULL)
+ {
+ // Check if we are in the "#include <...> search starts here:" section
+ if (strstr(path, "#include <...> search starts here:") != NULL)
+ {
+ in_include_section = 1;
+ continue;
+ }
+ // Check if we have reached the end of the include section
+ if (in_include_section && strstr(path, "End of search list.") != NULL)
+ {
+ break;
+ }
+ // Print the include directories
+ if (in_include_section)
+ {
+ const char* p = path;
+ while (*p == ' ') p++;
+
+ int len = strlen(path);
+ if (path[len - 1] == '\n')
+ path[len - 1] = '\0';
+
+ fprintf(outfile, "#pragma dir \"%s\"\n", p);
+}
+ }
+
+ fprintf(outfile, "\n");
+
+ // Close the command stream
+ pclose(fp);
+
+#endif
+
+#ifdef _WIN32
+ char env[2000] = { 0 };
+ int n = GetEnvironmentVariableA("INCLUDE", env, sizeof(env));
+
+ if (n <= 0)
+ {
+ printf("INCLUDE not found.\nPlease, run cake -autoconfig inside visual studio command prompty.\n");
+ error = 1;
+ throw;
+ }
+
+ fprintf(outfile, "This file was generated reading the variable INCLUDE inside Visual Studio Command Prompt.\n");
+ fprintf(outfile, "echo %%INCLUDE%% \n");
+
+ const char* p = env;
+ for (;;)
+ {
+ if (*p == '\0')
+ {
+ break;
+ }
+ char filename_local[500] = { 0 };
+ int count = 0;
+ while (*p != '\0' && (*p != ';' && *p != '\n'))
+ {
+ filename_local[count] = *p;
+ p++;
+ count++;
+ }
+ filename_local[count] = 0;
+ if (count > 0)
+ {
+ strcat(filename_local, "/");
+ char* pch = filename_local;
+ while (*pch)
+ {
+ if (*pch == '\\')
+ *pch = '/';
+ pch++;
+ }
+
+ fprintf(outfile, "#pragma dir \"%s\"\n", filename_local);
+ }
+ if (*p == '\0')
+ {
+ break;
+ }
+ p++;
+ }
+#endif
+ }
+ catch
+ {
+ }
+ if (outfile)
+ fclose(outfile);
+
+ if (error == 0)
+ {
+ printf("file '%s'\n", configpath);
+ printf("successfully generated\n");
+ }
+ return error;
+}
+
int compile_one_file(const char* file_name,
struct options* options,
const char* out_file_name,
@@ -8052,11 +8275,11 @@ static int create_multiple_paths(const char* root, const char* outdir)
printf("error creating output folder '%s' - %s\n", temp, get_posix_error_message(er));
return er;
}
- }
+ }
if (*p == '\0')
break;
p++;
- }
+}
return 0;
#else
return -1;
@@ -8071,6 +8294,17 @@ int compile(int argc, const char** argv, struct report* report)
return 1;
}
+ char executable_path[MAX_PATH - sizeof(CAKE_CFG_FNAME)] = { 0 };
+ get_self_path(executable_path, sizeof(executable_path));
+ dirname(executable_path);
+ char cakeconfig_path[MAX_PATH] = { 0 };
+ snprintf(cakeconfig_path, sizeof cakeconfig_path, "%s" CAKE_CFG_FNAME, executable_path);
+
+ if (options.auto_config) //-autoconfig
+ {
+ report->ignore_this_report = true;
+ return generate_config_file(cakeconfig_path);
+ }
report->test_mode = options.test_mode;
diff --git a/src/parser.h b/src/parser.h
index e3d0c656..a5277f32 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -45,14 +45,18 @@ struct report
int error_count;
int warnings_count;
int info_count;
-
+
bool test_mode;
int test_failed;
int test_succeeded;
enum diagnostic_id last_diagnostic_id;
-};
+ /*
+ direct commands like -autoconfig doesnt use report
+ */
+ bool ignore_this_report;
+};
struct parser_ctx
{
@@ -73,6 +77,15 @@ struct parser_ctx
*/
const struct try_statement* p_current_try_statement_opt;
+ /*
+ * Points to the select_stament we're in. Or null.
+ */
+ const struct selection_statement* p_current_selection_statement;
+
+ struct switch_value { long long value; struct switch_value* next; };
+ struct switch_value* switch_value;
+
+
FILE* owner sarif_file;
view struct token_list input_list;
@@ -87,7 +100,7 @@ struct parser_ctx
bool inside_generic_association;
-
+
struct report* p_report;
};
@@ -163,7 +176,7 @@ struct declaration_specifiers
enum type_specifier_flags type_specifier_flags;
enum type_qualifier_flags type_qualifier_flags;
enum storage_class_specifier_flags storage_class_specifier_flags;
-
+
struct attribute_specifier_sequence* owner p_attribute_specifier_sequence_opt;
/*shortcuts*/
@@ -203,7 +216,7 @@ struct static_assert_declaration
"static_debug" ( constant-expression ) ;
"static_set" ( constant-expression , string-literal) ;
*/
-
+
struct token* first_token;
struct token* last_token;
struct expression* owner constant_expression;
@@ -396,7 +409,7 @@ struct declaration
struct token* first_token;
struct token* last_token;
-
+
struct declaration* owner next;
};
void declaration_delete(struct declaration* owner opt p);
@@ -404,10 +417,10 @@ struct declaration* owner external_declaration(struct parser_ctx* ctx);
struct simple_declaration
{
- /*
+ /*
This is an extension to support C++ 17 if with initialization
-
- simple-declaration:
+
+ simple-declaration:
declaration-specifiers init-declarator-list opt ;
attribute-specifier-sequence declaration-specifiers init-declarator-list ;
*/
@@ -435,14 +448,14 @@ struct condition {
struct expression* owner expression;
struct attribute_specifier_sequence* owner p_attribute_specifier_sequence_opt;
struct declaration_specifiers* owner p_declaration_specifiers;
-
+
/*
OBS:
We must use p_init_declarator because it is kept on the scope
as init_declarator when we are trying to parse init-statement or condition that
are very similar
*/
- struct init_declarator * owner p_init_declarator;
+ struct init_declarator* owner p_init_declarator;
struct token* first_token;
struct token* last_token;
@@ -472,7 +485,7 @@ struct atomic_type_specifier
/*
atomic-type-specifier:
"_Atomic" ( type-name )
- */
+ */
struct token* token;
struct type_name* owner type_name;
};
@@ -526,6 +539,10 @@ struct enum_specifier* owner enum_specifier(struct parser_ctx*);
void enum_specifier_delete(struct enum_specifier* owner opt p);
const struct enum_specifier* get_complete_enum_specifier(const struct enum_specifier* p_enum_specifier);
+const struct enumerator* find_enumerator_by_value(const struct enum_specifier* p_enum_specifier, long long value);
+
+
+
struct member_declaration_list
{
/*
@@ -657,10 +674,10 @@ struct declarator
int num_uses; /*used to show not used warnings*/
/*user by flow analysis*/
- struct flow_object * p_object;
+ struct flow_object* p_object;
/*final declarator type (after auto, typeof etc)*/
- struct type type;
+ struct type type;
};
enum type_specifier_flags declarator_get_type_specifier_flags(const struct declarator* p);
@@ -1063,11 +1080,11 @@ struct selection_statement
selection-statement:
"if" ( init-statement opt condition ) secondary-block
"if" ( init-statement opt condition ) secondary-block "else" secondary-block
- switch ( init-statement opt condition ) secondary-block
+ switch ( init-statement opt condition ) secondary-block
*/
struct init_statement* owner p_init_statement;
struct condition* owner condition;
-
+
struct secondary_block* owner secondary_block;
struct secondary_block* owner else_secondary_block_opt;
@@ -1223,7 +1240,7 @@ struct secondary_block
};
void secondary_block_delete(struct secondary_block* owner opt p);
-bool secondary_block_ends_with_jump(struct secondary_block * p_secondary_block);
+bool secondary_block_ends_with_jump(struct secondary_block* p_secondary_block);
struct unlabeled_statement
{
diff --git a/src/tokenizer.c b/src/tokenizer.c
index 3e40f2c6..76f06847 100644
--- a/src/tokenizer.c
+++ b/src/tokenizer.c
@@ -132,7 +132,7 @@ static void tokenizer_set_error(struct tokenizer_ctx* ctx, struct stream* stream
ctx->n_errors++;
#ifndef TEST
char buffer[200] = { 0 };
- va_list args = {0};
+ va_list args = { 0 };
va_start(args, fmt);
/*int n =*/ vsnprintf(buffer, sizeof(buffer), fmt, args);
va_end(args);
@@ -156,7 +156,7 @@ static void tokenizer_set_warning(struct tokenizer_ctx* ctx, struct stream* stre
#ifndef TEST
char buffer[200] = { 0 };
- va_list args= {0};
+ va_list args = { 0 };
va_start(args, fmt);
/*int n =*/ vsnprintf(buffer, sizeof(buffer), fmt, args);
va_end(args);
@@ -232,7 +232,7 @@ bool preprocessor_diagnostic_message(enum diagnostic_id w, struct preprocessor_c
print_position(p_token->token_origin->lexeme, p_token->line, p_token->col, ctx->options.visual_studio_ouput_format);
char buffer[200] = { 0 };
- va_list args= {0};
+ va_list args = { 0 };
va_start(args, fmt);
/*int n =*/ vsnprintf(buffer, sizeof(buffer), fmt, args);
va_end(args);
@@ -268,8 +268,32 @@ bool preprocessor_diagnostic_message(enum diagnostic_id w, struct preprocessor_c
struct include_dir* include_dir_add(struct include_dir_list* list, const char* path)
{
+ if (path == NULL)
+ return NULL;
+
struct include_dir* owner p_new_include_dir = calloc(1, sizeof * p_new_include_dir);
- p_new_include_dir->path = strdup(path);
+ if (p_new_include_dir == NULL)
+ return NULL;
+
+ int len = strlen(path);
+ if (path[len - 1] == '\\')
+ {
+ //windows path format ending with \ .
+ p_new_include_dir->path = strdup(path);
+ }
+ else if (path[len - 1] != '/')
+ {
+ /*
+ not ending with \, we add it
+ */
+ p_new_include_dir->path = malloc(len + 2);
+ snprintf(p_new_include_dir->path, len + 2, "%s/", path);
+ }
+ else
+ {
+ p_new_include_dir->path = strdup(path);
+ }
+
if (list->head == NULL)
{
list->head = p_new_include_dir;
@@ -714,228 +738,228 @@ enum token_type is_punctuator(struct stream* stream)
*/
switch (stream->current[0])
{
- case '[':
- type = '[';
- stream_match(stream);
- break;
- case ']':
- type = ']';
- stream_match(stream);
- break;
- case '(':
- type = '(';
+ case '[':
+ type = '[';
+ stream_match(stream);
+ break;
+ case ']':
+ type = ']';
+ stream_match(stream);
+ break;
+ case '(':
+ type = '(';
+ stream_match(stream);
+ break;
+ case ')':
+ type = ')';
+ stream_match(stream);
+ break;
+ case '{':
+ type = '{';
+ stream_match(stream);
+ break;
+ case '}':
+ type = '}';
+ stream_match(stream);
+ break;
+ case ';':
+ type = ';';
+ stream_match(stream);
+ break;
+ case ',':
+ type = ',';
+ stream_match(stream);
+ break;
+ case '!':
+ type = '!';
+ stream_match(stream);
+ if (stream->current[0] == '=')
+ {
+ type = '!=';
stream_match(stream);
- break;
- case ')':
- type = ')';
+ }
+ break;
+ case ':':
+ type = ':';
+ stream_match(stream);
+ if (stream->current[0] == ':')
+ {
+ type = '::';
stream_match(stream);
- break;
- case '{':
- type = '{';
+ }
+ break;
+ case '~':
+ type = '~';
+ stream_match(stream);
+ break;
+ case '?':
+ type = '?';
+ stream_match(stream);
+ break;
+ case '/':
+ type = '/';
+ stream_match(stream);
+ if (stream->current[0] == '=')
+ {
+ type = '/=';
stream_match(stream);
- break;
- case '}':
- type = '}';
+ }
+ break;
+ case '*':
+ type = '*';
+ stream_match(stream);
+ if (stream->current[0] == '=')
+ {
+ type = '*=';
stream_match(stream);
- break;
- case ';':
- type = ';';
+ }
+ break;
+ case '%':
+ type = '%';
+ stream_match(stream);
+ if (stream->current[0] == '=')
+ {
+ type = '%=';
stream_match(stream);
- break;
- case ',':
- type = ',';
+ }
+ break;
+ case '-':
+ type = '-';
+ stream_match(stream);
+ if (stream->current[0] == '>')
+ {
+ type = '->';
stream_match(stream);
- break;
- case '!':
- type = '!';
+ }
+ else if (stream->current[0] == '-')
+ {
+ type = '--';
stream_match(stream);
- if (stream->current[0] == '=')
- {
- type = '!=';
- stream_match(stream);
- }
- break;
- case ':':
- type = ':';
+ }
+ else if (stream->current[0] == '=')
+ {
+ type = '-=';
stream_match(stream);
- if (stream->current[0] == ':')
- {
- type = '::';
- stream_match(stream);
- }
- break;
- case '~':
- type = '~';
+ }
+ break;
+ case '|':
+ type = '|';
+ stream_match(stream);
+ if (stream->current[0] == '|')
+ {
+ type = '||';
stream_match(stream);
- break;
- case '?':
- type = '?';
+ }
+ else if (stream->current[0] == '=')
+ {
+ type = '|=';
stream_match(stream);
- break;
- case '/':
- type = '/';
+ }
+ break;
+ case '+':
+ type = '+';
+ stream_match(stream);
+ if (stream->current[0] == '+')
+ {
+ type = '++';
stream_match(stream);
- if (stream->current[0] == '=')
- {
- type = '/=';
- stream_match(stream);
- }
- break;
- case '*':
- type = '*';
+ }
+ else if (stream->current[0] == '=')
+ {
+ type = '+=';
stream_match(stream);
- if (stream->current[0] == '=')
- {
- type = '*=';
- stream_match(stream);
- }
- break;
- case '%':
- type = '%';
+ }
+ break;
+ case '=':
+ type = '=';
+ stream_match(stream);
+ if (stream->current[0] == '=')
+ {
+ type = '==';
stream_match(stream);
- if (stream->current[0] == '=')
- {
- type = '%=';
- stream_match(stream);
- }
- break;
- case '-':
- type = '-';
+ }
+ break;
+ case '^':
+ type = '^';
+ stream_match(stream);
+ if (stream->current[0] == '=')
+ {
+ type = '^=';
stream_match(stream);
- if (stream->current[0] == '>')
- {
- type = '->';
- stream_match(stream);
- }
- else if (stream->current[0] == '-')
- {
- type = '--';
- stream_match(stream);
- }
- else if (stream->current[0] == '=')
- {
- type = '-=';
- stream_match(stream);
- }
- break;
- case '|':
- type = '|';
+ }
+ break;
+ case '&':
+ type = '&';
+ stream_match(stream);
+ if (stream->current[0] == '&')
+ {
+ type = '&&';
stream_match(stream);
- if (stream->current[0] == '|')
- {
- type = '||';
- stream_match(stream);
- }
- else if (stream->current[0] == '=')
- {
- type = '|=';
- stream_match(stream);
- }
- break;
- case '+':
- type = '+';
+ }
+ else if (stream->current[0] == '=')
+ {
+ type = '&=';
stream_match(stream);
- if (stream->current[0] == '+')
- {
- type = '++';
- stream_match(stream);
- }
- else if (stream->current[0] == '=')
- {
- type = '+=';
- stream_match(stream);
- }
- break;
- case '=':
- type = '=';
+ }
+ break;
+ case '>':
+ type = '>';
+ stream_match(stream);
+ if (stream->current[0] == '>')
+ {
+ type = '>>';
stream_match(stream);
if (stream->current[0] == '=')
{
- type = '==';
+ type = '>>=';
stream_match(stream);
}
- break;
- case '^':
- type = '^';
+ }
+ else if (stream->current[0] == '=')
+ {
+ type = '>=';
stream_match(stream);
- if (stream->current[0] == '=')
- {
- type = '^=';
- stream_match(stream);
- }
- break;
- case '&':
- type = '&';
+ }
+
+ break;
+ case '<':
+ type = '<';
+ stream_match(stream);
+ if (stream->current[0] == '<')
+ {
+ type = '<<';
stream_match(stream);
- if (stream->current[0] == '&')
- {
- type = '&&';
- stream_match(stream);
- }
- else if (stream->current[0] == '=')
+ if (stream->current[0] == '=')
{
- type = '&=';
+ type = '<<=';
stream_match(stream);
}
- break;
- case '>':
- type = '>';
+ }
+ else if (stream->current[0] == '=')
+ {
+ type = '<=';
stream_match(stream);
- if (stream->current[0] == '>')
- {
- type = '>>';
- stream_match(stream);
- if (stream->current[0] == '=')
- {
- type = '>>=';
- stream_match(stream);
- }
- }
- else if (stream->current[0] == '=')
- {
- type = '>=';
- stream_match(stream);
- }
-
- break;
- case '<':
- type = '<';
+ }
+ break;
+ case '#':
+ type = '#';
+ stream_match(stream);
+ if (stream->current[0] == '#')
+ {
+ type = '##';
stream_match(stream);
- if (stream->current[0] == '<')
- {
- type = '<<';
- stream_match(stream);
- if (stream->current[0] == '=')
- {
- type = '<<=';
- stream_match(stream);
- }
- }
- else if (stream->current[0] == '=')
- {
- type = '<=';
- stream_match(stream);
- }
- break;
- case '#':
- type = '#';
+ }
+ break;
+ case '.':
+ type = '.';
+ stream_match(stream);
+ if (stream->current[0] == '.' && stream->current[1] == '.')
+ {
+ type = '...';
stream_match(stream);
- if (stream->current[0] == '#')
- {
- type = '##';
- stream_match(stream);
- }
- break;
- case '.':
- type = '.';
stream_match(stream);
- if (stream->current[0] == '.' && stream->current[1] == '.')
- {
- type = '...';
- stream_match(stream);
- stream_match(stream);
- }
- break;
+ }
+ break;
}
return type;
}
@@ -1336,7 +1360,7 @@ struct token_list embed_tokenizer(struct preprocessor_ctx* ctx, const char* file
}
char buffer[30] = { 0 };
- int c = snprintf(buffer, sizeof buffer, "%d", (int) ch);
+ int c = snprintf(buffer, sizeof buffer, "%d", (int)ch);
struct token* owner p_new_token = new_token(buffer, &buffer[c], TK_PPNUMBER);
p_new_token->flags |= addflags;
@@ -1429,7 +1453,7 @@ struct token_list tokenizer(struct tokenizer_ctx* ctx, const char* text, const c
//windows have case insensive paths
for (char* p = p_new->lexeme; *p; p++)
{
- *p = (char) tolower(*p);
+ *p = (char)tolower(*p);
}
#endif
p_new->level = level;
@@ -2228,7 +2252,7 @@ long long preprocessor_constant_expression(struct preprocessor_ctx* ctx,
struct token_list list2 = preprocessor(ctx, &list1, 1);
ctx->flags = flags;
-
+
long long value = 0;
if (list2.head == NULL)
@@ -2249,10 +2273,10 @@ long long preprocessor_constant_expression(struct preprocessor_ctx* ctx,
struct preprocessor_ctx pre_ctx = { 0 };
-
+
pre_ctx.input_list = list4;
pre_ctx.current = pre_ctx.input_list.head;
-
+
if (pre_constant_expression(&pre_ctx, &value) != 0)
{
preprocessor_diagnostic_message(C_ERROR_EXPRESSION_ERROR, ctx, first, "expression error");
@@ -2261,7 +2285,7 @@ long long preprocessor_constant_expression(struct preprocessor_ctx* ctx,
ctx->conditional_inclusion = false;
preprocessor_ctx_destroy(&pre_ctx);
-
+
}
@@ -2730,7 +2754,6 @@ struct token_list control_line(struct preprocessor_ctx* ctx, struct token_list*
try
{
-
if (!is_active)
{
//se nao esta ativo eh ignorado
@@ -3150,7 +3173,7 @@ struct token_list control_line(struct preprocessor_ctx* ctx, struct token_list*
if (input_list->head && strcmp(input_list->head->lexeme, "once") == 0)
{
- hashmap_set(&ctx->pragma_once_map, input_list->head->token_origin->lexeme, (void*) 1, 0);
+ hashmap_set(&ctx->pragma_once_map, input_list->head->token_origin->lexeme, (void*)1, 0);
match_token_level(&r, input_list, TK_IDENTIFIER, level, ctx);//pragma
r.tail->flags |= TK_FLAG_FINAL;
}
@@ -3158,6 +3181,12 @@ struct token_list control_line(struct preprocessor_ctx* ctx, struct token_list*
{
match_token_level(&r, input_list, TK_IDENTIFIER, level, ctx);//pragma
skip_blanks_level(ctx, &r, input_list, level);
+ if (input_list->head->type != TK_STRING_LITERAL)
+ {
+ preprocessor_diagnostic_message(C_ERROR_UNEXPECTED, ctx, input_list->head, "expected string");
+ throw;
+ }
+
char path[200] = { 0 };
strncpy(path, input_list->head->lexeme + 1, strlen(input_list->head->lexeme) - 2);
include_dir_add(&ctx->include_dir, path);
@@ -3864,7 +3893,7 @@ int lexeme_cmp(const char* s1, const char* s2)
s2++;
}
- return *(const unsigned char*) s1 - *(const unsigned char*) s2;
+ return *(const unsigned char*)s1 - *(const unsigned char*)s2;
}
void remove_line_continuation(char* s)
@@ -4440,13 +4469,11 @@ void check_unused_macros(struct owner_hash_map* map)
void include_config_header(struct preprocessor_ctx* ctx)
{
-#define CAKE_CFG_FNAME "/cakeconfig.h"
char executable_path[MAX_PATH - sizeof(CAKE_CFG_FNAME)] = { 0 };
get_self_path(executable_path, sizeof(executable_path));
dirname(executable_path);
char path[MAX_PATH] = { 0 };
snprintf(path, sizeof path, "%s" CAKE_CFG_FNAME, executable_path);
-#undef CAKE_CFG_FNAME
/*
* windows
echo %INCLUDE%
@@ -4455,23 +4482,26 @@ void include_config_header(struct preprocessor_ctx* ctx)
*/
char* owner str = read_file(path);
+ if (str)
+ {
+ const enum diagnostic_id w =
+ ctx->options.diagnostic_stack[ctx->options.diagnostic_stack_top_index].warnings;
+ struct tokenizer_ctx tctx = { 0 };
+ struct token_list l = tokenizer(&tctx, str, "standard macros inclusion", 0, TK_FLAG_NONE);
+ struct token_list l10 = preprocessor(ctx, &l, 0);
+ mark_macros_as_used(&ctx->macros);
+ token_list_destroy(&l);
+ free(str);
+ token_list_destroy(&l10);
- const enum diagnostic_id w =
- ctx->options.diagnostic_stack[ctx->options.diagnostic_stack_top_index].warnings;
-
-
-
- struct tokenizer_ctx tctx = { 0 };
- struct token_list l = tokenizer(&tctx, str, "standard macros inclusion", 0, TK_FLAG_NONE);
- struct token_list l10 = preprocessor(ctx, &l, 0);
- mark_macros_as_used(&ctx->macros);
- token_list_destroy(&l);
- free(str);
- token_list_destroy(&l10);
-
- /*restore*/
- ctx->options.diagnostic_stack[ctx->options.diagnostic_stack_top_index].warnings = w;
+ /*restore*/
+ ctx->options.diagnostic_stack[ctx->options.diagnostic_stack_top_index].warnings = w;
+ }
+ else
+ {
+ //cakeconfig.h is optional
+ }
}
void add_standard_macros(struct preprocessor_ctx* ctx)
@@ -4544,7 +4574,7 @@ void add_standard_macros(struct preprocessor_ctx* ctx)
#endif
"#define _INTEGRAL_MAX_BITS " TOSTRING(_INTEGRAL_MAX_BITS) "\n" /*Use of __int64 should be conditional on the predefined macro _INTEGRAL_MAX_BITS*/
-
+
"#define _MSC_VER " TOSTRING(_MSC_VER) "\n"
"#define _M_IX86 " TOSTRING(_M_IX86) "\n"
"#define __fastcall\n"
@@ -4725,191 +4755,191 @@ const char* get_token_name(enum token_type tk)
{
switch (tk)
{
- case TK_NONE: return "TK_NONE";
- case TK_NEWLINE: return "TK_NEWLINE";
- case TK_WHITE_SPACE: return "TK_WHITE_SPACE";
- case TK_EXCLAMATION_MARK: return "TK_EXCLAMATION_MARK";
- case TK_QUOTATION_MARK: return "TK_QUOTATION_MARK";
- case TK_NUMBER_SIGN: return "TK_NUMBER_SIGN";
- case TK_DOLLAR_SIGN: return "TK_DOLLAR_SIGN";
- case TK_PERCENT_SIGN: return "TK_PERCENT_SIGN";
- case TK_AMPERSAND: return "TK_AMPERSAND";
- case TK_APOSTROPHE: return "TK_APOSTROPHE";
- case TK_LEFT_PARENTHESIS: return "TK_LEFT_PARENTHESIS";
- case TK_RIGHT_PARENTHESIS: return "TK_RIGHT_PARENTHESIS";
- case TK_ASTERISK: return "TK_ASTERISK";
- case TK_PLUS_SIGN: return "TK_PLUS_SIGN";
- case TK_COMMA: return "TK_COMMA";
- case TK_HYPHEN_MINUS: return "TK_HYPHEN_MINUS";
- case TK_FULL_STOP: return "TK_FULL_STOP";
- case TK_SOLIDUS: return "TK_SOLIDUS";
- case TK_COLON: return "TK_COLON";
- case TK_SEMICOLON: return "TK_SEMICOLON";
- case TK_LESS_THAN_SIGN: return "TK_LESS_THAN_SIGN";
- case TK_EQUALS_SIGN: return "TK_EQUALS_SIGN";
- case TK_GREATER_THAN_SIGN: return "TK_GREATER_THAN_SIGN";
- case TK_QUESTION_MARK: return "TK_QUESTION_MARK";
- case TK_COMMERCIAL_AT: return "TK_COMMERCIAL_AT";
- case TK_LEFT_SQUARE_BRACKET: return "TK_LEFT_SQUARE_BRACKET";
- case TK_REVERSE_SOLIDUS: return "TK_REVERSE_SOLIDUS";
- case TK_RIGHT_SQUARE_BRACKET: return "TK_RIGHT_SQUARE_BRACKET";
- case TK_CIRCUMFLEX_ACCENT: return "TK_CIRCUMFLEX_ACCENT";
- case TK_FLOW_LINE: return "TK_FLOW_LINE";
- case TK_GRAVE_ACCENT: return "TK_GRAVE_ACCENT";
- case TK_LEFT_CURLY_BRACKET: return "TK_LEFT_CURLY_BRACKET";
- case TK_VERTICAL_LINE: return "TK_VERTICAL_LINE";
- case TK_RIGHT_CURLY_BRACKET: return "TK_RIGHT_CURLY_BRACKET";
- case TK_TILDE: return "TK_TILDE";
- case TK_PREPROCESSOR_LINE: return "TK_PREPROCESSOR_LINE";
- case TK_PRAGMA: return "TK_PRAGMA";
- case TK_STRING_LITERAL: return "TK_STRING_LITERAL";
- case TK_CHAR_CONSTANT: return "TK_CHAR_CONSTANT";
- case TK_LINE_COMMENT: return "TK_LINE_COMMENT";
- case TK_COMMENT: return "TK_COMMENT";
- case TK_PPNUMBER: return "TK_PPNUMBER";
-
- case ANY_OTHER_PP_TOKEN: return "ANY_OTHER_PP_TOKEN"; //@ por ex
-
- /*PPNUMBER sao convertidos para constantes antes do parse*/
- case TK_COMPILER_DECIMAL_CONSTANT: return "TK_COMPILER_DECIMAL_CONSTANT";
- case TK_COMPILER_OCTAL_CONSTANT: return "TK_COMPILER_OCTAL_CONSTANT";
- case TK_COMPILER_HEXADECIMAL_CONSTANT: return "TK_COMPILER_HEXADECIMAL_CONSTANT";
- case TK_COMPILER_BINARY_CONSTANT: return "TK_COMPILER_BINARY_CONSTANT";
- case TK_COMPILER_DECIMAL_FLOATING_CONSTANT: return "TK_COMPILER_DECIMAL_FLOATING_CONSTANT";
- case TK_COMPILER_HEXADECIMAL_FLOATING_CONSTANT: return "TK_COMPILER_HEXADECIMAL_FLOATING_CONSTANT";
-
-
- case TK_PLACEMARKER: return "TK_PLACEMARKER";
-
- case TK_BLANKS: return "TK_BLANKS";
- case TK_PLUSPLUS: return "TK_PLUSPLUS";
- case TK_MINUSMINUS: return "TK_MINUSMINUS";
- case TK_ARROW: return "TK_ARROW";
- case TK_SHIFTLEFT: return "TK_SHIFTLEFT";
- case TK_SHIFTRIGHT: return "TK_SHIFTRIGHT";
- case TK_LOGICAL_OPERATOR_OR: return "TK_LOGICAL_OPERATOR_OR";
- case TK_LOGICAL_OPERATOR_AND: return "TK_LOGICAL_OPERATOR_AND";
-
- case TK_MACRO_CONCATENATE_OPERATOR: return "TK_MACRO_CONCATENATE_OPERATOR";
-
- case TK_IDENTIFIER: return "TK_IDENTIFIER";
- case TK_IDENTIFIER_RECURSIVE_MACRO: return "TK_IDENTIFIER_RECURSIVE_MACRO"; /*usado para evitar recursao expansao macro*/
-
- case TK_BEGIN_OF_FILE: return "TK_BEGIN_OF_FILE";
-
- //C23 keywords
- case TK_KEYWORD_AUTO: return "TK_KEYWORD_AUTO";
- case TK_KEYWORD_BREAK: return "TK_KEYWORD_BREAK";
- case TK_KEYWORD_CASE: return "TK_KEYWORD_CASE";
- case TK_KEYWORD_CONSTEXPR: return "TK_KEYWORD_CONSTEXPR";
- case TK_KEYWORD_CHAR: return "TK_KEYWORD_CHAR";
- case TK_KEYWORD_CONST: return "TK_KEYWORD_CONST";
- case TK_KEYWORD_CONTINUE: return "TK_KEYWORD_CONTINUE";
- case TK_KEYWORD_CATCH: return "TK_KEYWORD_CATCH"; /*extension*/
- case TK_KEYWORD_DEFAULT: return "TK_KEYWORD_DEFAULT";
- case TK_KEYWORD_DO: return "TK_KEYWORD_DO";
- case TK_KEYWORD_DEFER: return "TK_KEYWORD_DEFER"; /*extension*/
- case TK_KEYWORD_DOUBLE: return "TK_KEYWORD_DOUBLE";
- case TK_KEYWORD_ELSE: return "TK_KEYWORD_ELSE";
- case TK_KEYWORD_ENUM: return "TK_KEYWORD_ENUM";
- case TK_KEYWORD_EXTERN: return "TK_KEYWORD_EXTERN";
- case TK_KEYWORD_FLOAT: return "TK_KEYWORD_FLOAT";
- case TK_KEYWORD_FOR: return "TK_KEYWORD_FOR";
- case TK_KEYWORD_GOTO: return "TK_KEYWORD_GOTO";
- case TK_KEYWORD_IF: return "TK_KEYWORD_IF";
- case TK_KEYWORD_INLINE: return "TK_KEYWORD_INLINE";
- case TK_KEYWORD_INT: return "TK_KEYWORD_INT";
- case TK_KEYWORD_LONG: return "TK_KEYWORD_LONG";
- case TK_KEYWORD__INT8: return "TK_KEYWORD__INT8";
- case TK_KEYWORD__INT16: return "TK_KEYWORD__INT16";
- case TK_KEYWORD__INT32: return "TK_KEYWORD__INT32";
- case TK_KEYWORD__INT64: return "TK_KEYWORD__INT64";
-
-
- case TK_KEYWORD_REGISTER: return "TK_KEYWORD_REGISTER";
- case TK_KEYWORD_RESTRICT: return "TK_KEYWORD_RESTRICT";
- case TK_KEYWORD_RETURN: return "TK_KEYWORD_RETURN";
- case TK_KEYWORD_SHORT: return "TK_KEYWORD_SHORT";
- case TK_KEYWORD_SIGNED: return "TK_KEYWORD_SIGNED";
- case TK_KEYWORD_SIZEOF: return "TK_KEYWORD_SIZEOF";
-
- case TK_KEYWORD_STATIC: return "TK_KEYWORD_STATIC";
- case TK_KEYWORD_STRUCT: return "TK_KEYWORD_STRUCT";
- case TK_KEYWORD_SWITCH: return "TK_KEYWORD_SWITCH";
- case TK_KEYWORD_TYPEDEF: return "TK_KEYWORD_TYPEDEF";
- case TK_KEYWORD_TRY: return "TK_KEYWORD_TRY"; /*extension*/
- case TK_KEYWORD_THROW: return "TK_KEYWORD_THROW"; /*extension*/
- case TK_KEYWORD_UNION: return "TK_KEYWORD_UNION";
- case TK_KEYWORD_UNSIGNED: return "TK_KEYWORD_UNSIGNED";
- case TK_KEYWORD_VOID: return "TK_KEYWORD_VOID";
- case TK_KEYWORD_VOLATILE: return "TK_KEYWORD_VOLATILE";
- case TK_KEYWORD_WHILE: return "TK_KEYWORD_WHILE";
-
- case TK_KEYWORD__ALIGNAS: return "TK_KEYWORD__ALIGNAS";
- case TK_KEYWORD__ALIGNOF: return "TK_KEYWORD__ALIGNOF";
- case TK_KEYWORD__ATOMIC: return "TK_KEYWORD__ATOMIC";
- //microsoft
- //KEYWORD__FASTCALL,
- //KEYWORD__STDCALL
- //
- case TK_KEYWORD__ASM: return "TK_KEYWORD__ASM";
- //end microsoft
- case TK_KEYWORD__BOOL: return "TK_KEYWORD__BOOL";
- case TK_KEYWORD__COMPLEX: return "TK_KEYWORD__COMPLEX";
- case TK_KEYWORD__DECIMAL128: return "TK_KEYWORD__DECIMAL128";
- case TK_KEYWORD__DECIMAL32: return "TK_KEYWORD__DECIMAL32";
- case TK_KEYWORD__DECIMAL64: return "TK_KEYWORD__DECIMAL64";
- case TK_KEYWORD__GENERIC: return "TK_KEYWORD__GENERIC";
- case TK_KEYWORD__IMAGINARY: return "TK_KEYWORD__IMAGINARY";
- case TK_KEYWORD__NORETURN: return "TK_KEYWORD__NORETURN";
- case TK_KEYWORD__STATIC_ASSERT: return "TK_KEYWORD__STATIC_ASSERT";
- case TK_KEYWORD_ASSERT: return "TK_KEYWORD_ASSERT"; /*extension*/
- case TK_KEYWORD__THREAD_LOCAL: return "TK_KEYWORD__THREAD_LOCAL";
-
- case TK_KEYWORD_TYPEOF: return "TK_KEYWORD_TYPEOF"; /*C23*/
-
- case TK_KEYWORD_TRUE: return "TK_KEYWORD_TRUE"; /*C23*/
- case TK_KEYWORD_FALSE: return "TK_KEYWORD_FALSE"; /*C23*/
- case TK_KEYWORD_NULLPTR: return "TK_KEYWORD_NULLPTR"; /*C23*/
- case TK_KEYWORD_TYPEOF_UNQUAL: return "TK_KEYWORD_TYPEOF_UNQUAL"; /*C23*/
- case TK_KEYWORD__BITINT: return "TK_KEYWORD__BITINT"; /*C23*/
-
-
-
- /*cake extension*/
- case TK_KEYWORD__OWNER: return "TK_KEYWORD__OWNER";
- case TK_KEYWORD__OUT: return "TK_KEYWORD__OUT";
- case TK_KEYWORD__OBJ_OWNER: return "TK_KEYWORD__OBJ_OWNER";
- case TK_KEYWORD__VIEW: return "TK_KEYWORD__VIEW";
- case TK_KEYWORD__OPT: return "TK_KEYWORD__OPT";
-
-
- /*extension compile time functions*/
- case TK_KEYWORD_STATIC_DEBUG: return "TK_KEYWORD_STATIC_DEBUG"; /*extension*/
- case TK_KEYWORD_STATIC_DEBUG_EX: return "TK_KEYWORD_STATIC_DEBUG_EX"; /*extension*/
- case TK_KEYWORD_STATIC_STATE: return "TK_KEYWORD_STATIC_STATE"; /*extension*/
- case TK_KEYWORD_STATIC_SET: return "TK_KEYWORD_STATIC_SET"; /*extension*/
- case TK_KEYWORD_ATTR_ADD: return "TK_KEYWORD_ATTR_ADD"; /*extension*/
- case TK_KEYWORD_ATTR_REMOVE: return "TK_KEYWORD_ATTR_REMOVE"; /*extension*/
- case TK_KEYWORD_ATTR_HAS: return "TK_KEYWORD_ATTR_HAS"; /*extension*/
-
- /*https://en.cppreference.com/w/cpp/header/type_traits*/
-
- case TK_KEYWORD_IS_POINTER: return "TK_KEYWORD_IS_POINTER";
- case TK_KEYWORD_IS_LVALUE: return "TK_KEYWORD_IS_LVALUE";
- case TK_KEYWORD_IS_CONST: return "TK_KEYWORD_IS_CONST";
- case TK_KEYWORD_IS_OWNER: return "TK_KEYWORD_IS_OWNER";
- case TK_KEYWORD_IS_ARRAY: return "TK_KEYWORD_IS_ARRAY";
- case TK_KEYWORD_IS_FUNCTION: return "TK_KEYWORD_IS_FUNCTION";
- case TK_KEYWORD_IS_SCALAR: return "TK_KEYWORD_IS_SCALAR";
- case TK_KEYWORD_IS_ARITHMETIC: return "TK_KEYWORD_IS_ARITHMETIC";
- case TK_KEYWORD_IS_FLOATING_POINT: return "TK_KEYWORD_IS_FLOATING_POINT";
- case TK_KEYWORD_IS_INTEGRAL: return "TK_KEYWORD_IS_INTEGRAL";
-
- default:
- return "TK_X_MISSING_NAME";
- }
- return "";
+ case TK_NONE: return "TK_NONE";
+ case TK_NEWLINE: return "TK_NEWLINE";
+ case TK_WHITE_SPACE: return "TK_WHITE_SPACE";
+ case TK_EXCLAMATION_MARK: return "TK_EXCLAMATION_MARK";
+ case TK_QUOTATION_MARK: return "TK_QUOTATION_MARK";
+ case TK_NUMBER_SIGN: return "TK_NUMBER_SIGN";
+ case TK_DOLLAR_SIGN: return "TK_DOLLAR_SIGN";
+ case TK_PERCENT_SIGN: return "TK_PERCENT_SIGN";
+ case TK_AMPERSAND: return "TK_AMPERSAND";
+ case TK_APOSTROPHE: return "TK_APOSTROPHE";
+ case TK_LEFT_PARENTHESIS: return "TK_LEFT_PARENTHESIS";
+ case TK_RIGHT_PARENTHESIS: return "TK_RIGHT_PARENTHESIS";
+ case TK_ASTERISK: return "TK_ASTERISK";
+ case TK_PLUS_SIGN: return "TK_PLUS_SIGN";
+ case TK_COMMA: return "TK_COMMA";
+ case TK_HYPHEN_MINUS: return "TK_HYPHEN_MINUS";
+ case TK_FULL_STOP: return "TK_FULL_STOP";
+ case TK_SOLIDUS: return "TK_SOLIDUS";
+ case TK_COLON: return "TK_COLON";
+ case TK_SEMICOLON: return "TK_SEMICOLON";
+ case TK_LESS_THAN_SIGN: return "TK_LESS_THAN_SIGN";
+ case TK_EQUALS_SIGN: return "TK_EQUALS_SIGN";
+ case TK_GREATER_THAN_SIGN: return "TK_GREATER_THAN_SIGN";
+ case TK_QUESTION_MARK: return "TK_QUESTION_MARK";
+ case TK_COMMERCIAL_AT: return "TK_COMMERCIAL_AT";
+ case TK_LEFT_SQUARE_BRACKET: return "TK_LEFT_SQUARE_BRACKET";
+ case TK_REVERSE_SOLIDUS: return "TK_REVERSE_SOLIDUS";
+ case TK_RIGHT_SQUARE_BRACKET: return "TK_RIGHT_SQUARE_BRACKET";
+ case TK_CIRCUMFLEX_ACCENT: return "TK_CIRCUMFLEX_ACCENT";
+ case TK_FLOW_LINE: return "TK_FLOW_LINE";
+ case TK_GRAVE_ACCENT: return "TK_GRAVE_ACCENT";
+ case TK_LEFT_CURLY_BRACKET: return "TK_LEFT_CURLY_BRACKET";
+ case TK_VERTICAL_LINE: return "TK_VERTICAL_LINE";
+ case TK_RIGHT_CURLY_BRACKET: return "TK_RIGHT_CURLY_BRACKET";
+ case TK_TILDE: return "TK_TILDE";
+ case TK_PREPROCESSOR_LINE: return "TK_PREPROCESSOR_LINE";
+ case TK_PRAGMA: return "TK_PRAGMA";
+ case TK_STRING_LITERAL: return "TK_STRING_LITERAL";
+ case TK_CHAR_CONSTANT: return "TK_CHAR_CONSTANT";
+ case TK_LINE_COMMENT: return "TK_LINE_COMMENT";
+ case TK_COMMENT: return "TK_COMMENT";
+ case TK_PPNUMBER: return "TK_PPNUMBER";
+
+ case ANY_OTHER_PP_TOKEN: return "ANY_OTHER_PP_TOKEN"; //@ por ex
+
+ /*PPNUMBER sao convertidos para constantes antes do parse*/
+ case TK_COMPILER_DECIMAL_CONSTANT: return "TK_COMPILER_DECIMAL_CONSTANT";
+ case TK_COMPILER_OCTAL_CONSTANT: return "TK_COMPILER_OCTAL_CONSTANT";
+ case TK_COMPILER_HEXADECIMAL_CONSTANT: return "TK_COMPILER_HEXADECIMAL_CONSTANT";
+ case TK_COMPILER_BINARY_CONSTANT: return "TK_COMPILER_BINARY_CONSTANT";
+ case TK_COMPILER_DECIMAL_FLOATING_CONSTANT: return "TK_COMPILER_DECIMAL_FLOATING_CONSTANT";
+ case TK_COMPILER_HEXADECIMAL_FLOATING_CONSTANT: return "TK_COMPILER_HEXADECIMAL_FLOATING_CONSTANT";
+
+
+ case TK_PLACEMARKER: return "TK_PLACEMARKER";
+
+ case TK_BLANKS: return "TK_BLANKS";
+ case TK_PLUSPLUS: return "TK_PLUSPLUS";
+ case TK_MINUSMINUS: return "TK_MINUSMINUS";
+ case TK_ARROW: return "TK_ARROW";
+ case TK_SHIFTLEFT: return "TK_SHIFTLEFT";
+ case TK_SHIFTRIGHT: return "TK_SHIFTRIGHT";
+ case TK_LOGICAL_OPERATOR_OR: return "TK_LOGICAL_OPERATOR_OR";
+ case TK_LOGICAL_OPERATOR_AND: return "TK_LOGICAL_OPERATOR_AND";
+
+ case TK_MACRO_CONCATENATE_OPERATOR: return "TK_MACRO_CONCATENATE_OPERATOR";
+
+ case TK_IDENTIFIER: return "TK_IDENTIFIER";
+ case TK_IDENTIFIER_RECURSIVE_MACRO: return "TK_IDENTIFIER_RECURSIVE_MACRO"; /*usado para evitar recursao expansao macro*/
+
+ case TK_BEGIN_OF_FILE: return "TK_BEGIN_OF_FILE";
+
+ //C23 keywords
+ case TK_KEYWORD_AUTO: return "TK_KEYWORD_AUTO";
+ case TK_KEYWORD_BREAK: return "TK_KEYWORD_BREAK";
+ case TK_KEYWORD_CASE: return "TK_KEYWORD_CASE";
+ case TK_KEYWORD_CONSTEXPR: return "TK_KEYWORD_CONSTEXPR";
+ case TK_KEYWORD_CHAR: return "TK_KEYWORD_CHAR";
+ case TK_KEYWORD_CONST: return "TK_KEYWORD_CONST";
+ case TK_KEYWORD_CONTINUE: return "TK_KEYWORD_CONTINUE";
+ case TK_KEYWORD_CATCH: return "TK_KEYWORD_CATCH"; /*extension*/
+ case TK_KEYWORD_DEFAULT: return "TK_KEYWORD_DEFAULT";
+ case TK_KEYWORD_DO: return "TK_KEYWORD_DO";
+ case TK_KEYWORD_DEFER: return "TK_KEYWORD_DEFER"; /*extension*/
+ case TK_KEYWORD_DOUBLE: return "TK_KEYWORD_DOUBLE";
+ case TK_KEYWORD_ELSE: return "TK_KEYWORD_ELSE";
+ case TK_KEYWORD_ENUM: return "TK_KEYWORD_ENUM";
+ case TK_KEYWORD_EXTERN: return "TK_KEYWORD_EXTERN";
+ case TK_KEYWORD_FLOAT: return "TK_KEYWORD_FLOAT";
+ case TK_KEYWORD_FOR: return "TK_KEYWORD_FOR";
+ case TK_KEYWORD_GOTO: return "TK_KEYWORD_GOTO";
+ case TK_KEYWORD_IF: return "TK_KEYWORD_IF";
+ case TK_KEYWORD_INLINE: return "TK_KEYWORD_INLINE";
+ case TK_KEYWORD_INT: return "TK_KEYWORD_INT";
+ case TK_KEYWORD_LONG: return "TK_KEYWORD_LONG";
+ case TK_KEYWORD__INT8: return "TK_KEYWORD__INT8";
+ case TK_KEYWORD__INT16: return "TK_KEYWORD__INT16";
+ case TK_KEYWORD__INT32: return "TK_KEYWORD__INT32";
+ case TK_KEYWORD__INT64: return "TK_KEYWORD__INT64";
+
+
+ case TK_KEYWORD_REGISTER: return "TK_KEYWORD_REGISTER";
+ case TK_KEYWORD_RESTRICT: return "TK_KEYWORD_RESTRICT";
+ case TK_KEYWORD_RETURN: return "TK_KEYWORD_RETURN";
+ case TK_KEYWORD_SHORT: return "TK_KEYWORD_SHORT";
+ case TK_KEYWORD_SIGNED: return "TK_KEYWORD_SIGNED";
+ case TK_KEYWORD_SIZEOF: return "TK_KEYWORD_SIZEOF";
+
+ case TK_KEYWORD_STATIC: return "TK_KEYWORD_STATIC";
+ case TK_KEYWORD_STRUCT: return "TK_KEYWORD_STRUCT";
+ case TK_KEYWORD_SWITCH: return "TK_KEYWORD_SWITCH";
+ case TK_KEYWORD_TYPEDEF: return "TK_KEYWORD_TYPEDEF";
+ case TK_KEYWORD_TRY: return "TK_KEYWORD_TRY"; /*extension*/
+ case TK_KEYWORD_THROW: return "TK_KEYWORD_THROW"; /*extension*/
+ case TK_KEYWORD_UNION: return "TK_KEYWORD_UNION";
+ case TK_KEYWORD_UNSIGNED: return "TK_KEYWORD_UNSIGNED";
+ case TK_KEYWORD_VOID: return "TK_KEYWORD_VOID";
+ case TK_KEYWORD_VOLATILE: return "TK_KEYWORD_VOLATILE";
+ case TK_KEYWORD_WHILE: return "TK_KEYWORD_WHILE";
+
+ case TK_KEYWORD__ALIGNAS: return "TK_KEYWORD__ALIGNAS";
+ case TK_KEYWORD__ALIGNOF: return "TK_KEYWORD__ALIGNOF";
+ case TK_KEYWORD__ATOMIC: return "TK_KEYWORD__ATOMIC";
+ //microsoft
+ //KEYWORD__FASTCALL,
+ //KEYWORD__STDCALL
+ //
+ case TK_KEYWORD__ASM: return "TK_KEYWORD__ASM";
+ //end microsoft
+ case TK_KEYWORD__BOOL: return "TK_KEYWORD__BOOL";
+ case TK_KEYWORD__COMPLEX: return "TK_KEYWORD__COMPLEX";
+ case TK_KEYWORD__DECIMAL128: return "TK_KEYWORD__DECIMAL128";
+ case TK_KEYWORD__DECIMAL32: return "TK_KEYWORD__DECIMAL32";
+ case TK_KEYWORD__DECIMAL64: return "TK_KEYWORD__DECIMAL64";
+ case TK_KEYWORD__GENERIC: return "TK_KEYWORD__GENERIC";
+ case TK_KEYWORD__IMAGINARY: return "TK_KEYWORD__IMAGINARY";
+ case TK_KEYWORD__NORETURN: return "TK_KEYWORD__NORETURN";
+ case TK_KEYWORD__STATIC_ASSERT: return "TK_KEYWORD__STATIC_ASSERT";
+ case TK_KEYWORD_ASSERT: return "TK_KEYWORD_ASSERT"; /*extension*/
+ case TK_KEYWORD__THREAD_LOCAL: return "TK_KEYWORD__THREAD_LOCAL";
+
+ case TK_KEYWORD_TYPEOF: return "TK_KEYWORD_TYPEOF"; /*C23*/
+
+ case TK_KEYWORD_TRUE: return "TK_KEYWORD_TRUE"; /*C23*/
+ case TK_KEYWORD_FALSE: return "TK_KEYWORD_FALSE"; /*C23*/
+ case TK_KEYWORD_NULLPTR: return "TK_KEYWORD_NULLPTR"; /*C23*/
+ case TK_KEYWORD_TYPEOF_UNQUAL: return "TK_KEYWORD_TYPEOF_UNQUAL"; /*C23*/
+ case TK_KEYWORD__BITINT: return "TK_KEYWORD__BITINT"; /*C23*/
+
+
+
+ /*cake extension*/
+ case TK_KEYWORD__OWNER: return "TK_KEYWORD__OWNER";
+ case TK_KEYWORD__OUT: return "TK_KEYWORD__OUT";
+ case TK_KEYWORD__OBJ_OWNER: return "TK_KEYWORD__OBJ_OWNER";
+ case TK_KEYWORD__VIEW: return "TK_KEYWORD__VIEW";
+ case TK_KEYWORD__OPT: return "TK_KEYWORD__OPT";
+
+
+ /*extension compile time functions*/
+ case TK_KEYWORD_STATIC_DEBUG: return "TK_KEYWORD_STATIC_DEBUG"; /*extension*/
+ case TK_KEYWORD_STATIC_DEBUG_EX: return "TK_KEYWORD_STATIC_DEBUG_EX"; /*extension*/
+ case TK_KEYWORD_STATIC_STATE: return "TK_KEYWORD_STATIC_STATE"; /*extension*/
+ case TK_KEYWORD_STATIC_SET: return "TK_KEYWORD_STATIC_SET"; /*extension*/
+ case TK_KEYWORD_ATTR_ADD: return "TK_KEYWORD_ATTR_ADD"; /*extension*/
+ case TK_KEYWORD_ATTR_REMOVE: return "TK_KEYWORD_ATTR_REMOVE"; /*extension*/
+ case TK_KEYWORD_ATTR_HAS: return "TK_KEYWORD_ATTR_HAS"; /*extension*/
+
+ /*https://en.cppreference.com/w/cpp/header/type_traits*/
+
+ case TK_KEYWORD_IS_POINTER: return "TK_KEYWORD_IS_POINTER";
+ case TK_KEYWORD_IS_LVALUE: return "TK_KEYWORD_IS_LVALUE";
+ case TK_KEYWORD_IS_CONST: return "TK_KEYWORD_IS_CONST";
+ case TK_KEYWORD_IS_OWNER: return "TK_KEYWORD_IS_OWNER";
+ case TK_KEYWORD_IS_ARRAY: return "TK_KEYWORD_IS_ARRAY";
+ case TK_KEYWORD_IS_FUNCTION: return "TK_KEYWORD_IS_FUNCTION";
+ case TK_KEYWORD_IS_SCALAR: return "TK_KEYWORD_IS_SCALAR";
+ case TK_KEYWORD_IS_ARITHMETIC: return "TK_KEYWORD_IS_ARITHMETIC";
+ case TK_KEYWORD_IS_FLOATING_POINT: return "TK_KEYWORD_IS_FLOATING_POINT";
+ case TK_KEYWORD_IS_INTEGRAL: return "TK_KEYWORD_IS_INTEGRAL";
+
+ default:
+ break;
+ }
+ return "TK_X_MISSING_NAME";
};
@@ -4965,11 +4995,11 @@ void print_literal(const char* s)
{
switch (*s)
{
- case '\n':
- printf("\\n");
- break;
- default:
- printf("%c", *s);
+ case '\n':
+ printf("\\n");
+ break;
+ default:
+ printf("%c", *s);
}
s++;
}
@@ -5010,7 +5040,7 @@ const char* owner get_code_as_we_see_plus_macros(struct token_list* list)
/*useful to debug visit.c*/
void print_code_as_we_see(struct token_list* list, bool remove_comments)
{
-
+
struct token* current = list->head;
while (current && current != list->tail->next)
{
diff --git a/src/tokenizer.h b/src/tokenizer.h
index 47ee181b..3ec2055c 100644
--- a/src/tokenizer.h
+++ b/src/tokenizer.h
@@ -5,6 +5,8 @@
#include "options.h"
#include "ownership.h"
+#define CAKE_CFG_FNAME "/cakeconfig.h"
+
struct include_dir
{
const char* owner path;
diff --git a/src/web/manual.html b/src/web/manual.html
index 09d3d69d..1ff1c68e 100644
--- a/src/web/manual.html
+++ b/src/web/manual.html
@@ -47,247 +47,250 @@ Cake - C23 and Beyond
-fanalyzer
+
+-autoconfig
+
-Output
+Output
-Setting the path
+Setting the path
-Pre-defined macros
+Pre-defined macros
-C99 Transformations
+C99 Transformations
-C11 Transformations
+C11 Transformations
-C23 Transformations
+C23 Transformations
-C2Y Transformations
+C2Y Transformations
-Cake Extensions (Not in C23, C2Y)
+Cake Extensions (Not in C23, C2Y)
-Versions
+Versions
Intro
@@ -349,6 +352,8 @@ Include directories
+Cake also have the option -autoconfig that generates the cakeconfig.h automatically.
+
Cake also includes standard header files. The objective is to allow usage even without installing GCC or MSVC. You can set this path on cakeconfig.h
but mixing cake headers with other headers is not recommended.
Command line
@@ -448,7 +453,13 @@ -fanalyzer
This option enables an static analysis of program flow. This is required for some
ownership checks
-Output
+-autoconfig
+
+Generates cakeconfig.h header.
+On Windows, it must be generated inside the Visual Studio Command Prompt to read the INCLUDE variable.
+On Linux, it calls GCC with echo | gcc -v -E - 2>&1 and reads the output.
+
+Output
One directory called out is created keeping the same directory structure of the input files.
@@ -482,14 +493,14 @@ Output
├── file2.c
-Setting the path
+Setting the path
This command is useful on windows to add the current path to system path. (This is not persistent)
set PATH=%PATH%;%CD%
-Pre-defined macros
+Pre-defined macros
#define __CAKE__ 202311L
#define __STDC_VERSION__ 202311L
@@ -498,15 +509,15 @@ Pre-defined macros
The define STDC_OWNERSHIP indicates that the compiler suports owneship checks
-Pre-defined macros for MSVC compatibility
+Pre-defined macros for MSVC compatibility
https://learn.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=msvc-170#standard-predefined-macros
-Pre-defined macros for GCC compatibility
+Pre-defined macros for GCC compatibility
https://gcc.gnu.org/onlinedocs/cpp/Predefined-Macros.html
-C99 Transformations
+C99 Transformations
C89 is the minimum target.
@@ -521,7 +532,7 @@ C99 Transformations
#define __STDC_VERSION__ 199901L //C99
-C99 restrict pointers
+C99 restrict pointers
void f(const char* restrict s);
@@ -533,7 +544,7 @@ C99 restrict pointers
N448
-C99 Variable-length array (VLA)
+C99 Variable-length array (VLA)
The idea is not implement variable length arrays with automatic storage duration. (__STDC_NO_VLA__ 1).
@@ -578,7 +589,7 @@ C99 Variable-length array (VLA)
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n683.htm
-C99 Flexible array members
+C99 Flexible array members
struct s {
int n;
@@ -594,7 +605,7 @@ C99 Flexible array members
};
-C99 static and type qualifiers in parameter array declarators
+C99 static and type qualifiers in parameter array declarators
#include <stdlib.h>
@@ -625,15 +636,15 @@ C99 static and type qualifiers in parameter array declaratorsCakes extend this check for arrays without static as well.
-C99 Complex and imaginary support
+C99 Complex and imaginary support
Not implemented
-C99 Universal character names (\u and \U)
+C99 Universal character names (\u and \U)
TODO
-C99 Hexadecimal floating constants
+C99 Hexadecimal floating constants
double d = 0x1p+1;
@@ -647,7 +658,7 @@ C99 Hexadecimal floating constants
floating point using strtod then snprintf.
That means this conversion is not precise.
-C99 Compound literals
+C99 Compound literals
struct s {
int i;
@@ -682,7 +693,7 @@ C99 Compound literals
N716
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n716.htm
-C99 Designated initializers
+C99 Designated initializers
int main()
{
@@ -708,25 +719,25 @@ C99 Designated initializers
N494
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n494.pdf
-C99 Line comments
+C99 Line comments
When compiling to C89 line comments are converted to
/comments/.
-C99 inline functions
+C99 inline functions
TODO
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n741.htm
-C99 _Pragma preprocessing operator
+C99 _Pragma preprocessing operator
TODO
-C99 __func__ predefined identifier
+C99 __func__ predefined identifier
Parsed. C89 conversion not implemented yet.
-C99 Variadic macros
+C99 Variadic macros
We need to expand the macro when comping to C89.
This is covered by # macro expand.
@@ -766,7 +777,7 @@ C99 Variadic macros
N707
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n707.htm
-C99 _Bool
+C99 _Bool
When compiling to C89 _Bool is replaced by unsigned char.
@@ -791,7 +802,7 @@ C99 _Bool
Alternative design - typedef ?
Considering C23 has bool and the objective of C89 version is to have a version that compiles in C++ the best option would be use bool, true, false.
-C11 Transformations
+C11 Transformations
#define __STDC_VERSION__ 201112L //C11
@@ -800,15 +811,15 @@ C11 Transformations
https://files.lhmouse.com/standards/ISO%20C%20N2176.pdf
-C11 _Static_assert
+C11 _Static_assert
When compiling to versions < C11 _Static_Assert is removed.
-C11 Anonymous structures and unions
+C11 Anonymous structures and unions
TODO
-C11 _Noreturn
+C11 _Noreturn
_Noreturn void f () {
abort(); // ok
@@ -824,11 +835,11 @@ C11 _Noreturn
C23 attribute [[noreturn]] provides similar semantics. The _Noreturn function specifier is an obsolescent feature
-C11 Thread_local/Atomic
+C11 Thread_local/Atomic
Parsed but not transformed.
-C11 type-generic expressions (_Generic)
+C11 type-generic expressions (_Generic)
When compiling to C99, C89 we keep the expression that matches the type.
@@ -875,7 +886,7 @@ C11 type-generic expressions (_Generic)
}
-C11 u' ' U' ' character constants
+C11 u' ' U' ' character constants
//TODO
@@ -892,7 +903,7 @@ C11 u' ' U' ' character constants
Important: Cake assume source is utf8 encoded.
-C11 u8"literals"
+C11 u8"literals"
u8 literals are converted to escape sequences.
@@ -911,7 +922,7 @@ C11 u8"literals"
Important: Cake assume source is utf8 encoded.
-C11 _Alignof or C23 alignof
+C11 _Alignof or C23 alignof
When compiling to C99 or C89 it is replaced by the equivalent constant.
@@ -929,11 +940,11 @@ C11 _Alignof or C23 alignof
}
-C11 _Alignas or C23 alignas
+C11 _Alignas or C23 alignas
Not implemented.
-C23 Transformations
+C23 Transformations
https://open-std.org/JTC1/SC22/WG14/www/docs/n3096.pdf
@@ -941,11 +952,11 @@ C23 Transformations
#define __STDC_VERSION__ 202311L //C23
-C23 _Decimal32, _Decimal64, and _Decimal128
+C23 _Decimal32, _Decimal64, and _Decimal128
Not implemented.
-C23 static_assert / single-argument static_assert
+C23 static_assert / single-argument static_assert
In C23 static_assert is a keyword and the text message is optional.
@@ -973,12 +984,12 @@ C23 static_assert / single-argument static_assert
In < C11 it is replaced by one space;
-C23 u8 character prefix
+C23 u8 character prefix
Not implemented yet.
https://open-std.org/JTC1/SC22/WG14/www/docs/n2418.pdf
-C23 No function declarators without prototypes
+C23 No function declarators without prototypes
https://www.open-std.org/JTC1/SC22/WG14/www/docs/n2841.htm
@@ -991,7 +1002,7 @@ C23 No function declarators without prototypes
https://open-std.org/JTC1/SC22/WG14/www/docs/n2432.pdf
-C23 Improved Tag Compatibility
+C23 Improved Tag Compatibility
Not implemented yet.
@@ -1015,7 +1026,7 @@ C23 Improved Tag Compatibility
}
-C23 Unnamed parameters in function definitions
+C23 Unnamed parameters in function definitions
int f(int );
@@ -1027,7 +1038,7 @@ C23 Unnamed parameters in function definitions
Cake should add a dummy name when generating C < 23. (Not implemented yet)
-C23 Digit separators
+C23 Digit separators
int main()
{
@@ -1047,7 +1058,7 @@ C23 Digit separators
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2626.pdf
-C23 Binary literals
+C23 Binary literals
#define X 0b1010
@@ -1073,7 +1084,7 @@ C23 Binary literals
This transformation happens at token level, so even preprocessor and inactive blocks are transformed.
-C23 Introduce the nullptr constant
+C23 Introduce the nullptr constant
int main()
@@ -1098,7 +1109,7 @@ C23 Introduce the nullptr constant
https://open-std.org/JTC1/SC22/WG14/www/docs/n3042.htm
-C23 Make false and true first-class language features
+C23 Make false and true first-class language features
When compiling to C89 bool is replaced by unsigned char, true by 1 and false by 0.
@@ -1107,7 +1118,7 @@ C23 Make false and true first-class language features
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2935.pdf
-C23 {} empty initializer
+C23 {} empty initializer
int main()
@@ -1149,7 +1160,7 @@ C23 {} empty initializer
Note: Cake code is 100% equivalent because it does not make padding bit zero.
-C23 auto
+C23 auto
static auto a = 3.5;
auto p = &a;
@@ -1171,7 +1182,7 @@ C23 auto
https://open-std.org/JTC1/SC22/WG14/www/docs/n3007.htm
-C23 typeof / typeof_unqual
+C23 typeof / typeof_unqual
#define SWAP(a, b) \
@@ -1260,11 +1271,11 @@ C23 typeof / typeof_unqual
https://open-std.org/JTC1/SC22/WG14/www/docs/n2927.htm
https://open-std.org/JTC1/SC22/WG14/www/docs/n2930.pdf
-C23 Improved Normal Enumerations
+C23 Improved Normal Enumerations
https://open-std.org/JTC1/SC22/WG14/www/docs/n3029.htm
-C23 constexpr
+C23 constexpr
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3018.htm
@@ -1306,7 +1317,7 @@ C23 constexpr
TODO: Maybe suffix like ULL etc makes the code easier to read.
-C23 Enhancements to Enumerations
+C23 Enhancements to Enumerations
enum X : short {
A
@@ -1330,7 +1341,7 @@ C23 Enhancements to Enumerations
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3030.htm
-C23 Attributes
+C23 Attributes
Conversion to < C23 will just remove the attributes.
@@ -1340,23 +1351,23 @@ C23 Attributes
Related: Standard Attributes in C and C++ - Timur Doumler - ACCU 2023
https://youtu.be/EpAEFjbTh3I
-C23 fallthrough attribute
+C23 fallthrough attribute
Not implemented
https://open-std.org/JTC1/SC22/WG14/www/docs/n2408.pdf
-C23 deprecated attribute
+C23 deprecated attribute
Partially implemented
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2334.pdf
-C23 maybe_unused attribute
+C23 maybe_unused attribute
Implemented
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2270.pdf
-C23 nodiscard attribute
+C23 nodiscard attribute
Partially implemented
@@ -1364,18 +1375,18 @@ C23 nodiscard attribute
https://open-std.org/JTC1/SC22/WG14/www/docs/n2448.pdf
-C23 [[unsequenced]] and [[reproducible]]
+C23 [[unsequenced]] and [[reproducible]]
Parsed.
https://open-std.org/JTC1/SC22/WG14/www/docs/n2956.htm
-C23 __has_attribute
+C23 __has_attribute
Its is implemented in cake.
Conversion < C23 not defined. Maybe a define.
-C23 __has_include
+C23 __has_include
#if __has_include(<stdio.h>)
@@ -1393,7 +1404,7 @@ C23 __has_include
Its is implemented in cake.
Conversion < C23 not defined. Maybe a define.
-C23 #warning
+C23 #warning
When compiling to versions < 23 it is commented out.
@@ -1413,7 +1424,7 @@ C23 #warning
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2686.pdf
-C23 #embed
+C23 #embed
#include <stdio.h>
@@ -1465,7 +1476,7 @@ C23 #embed
}
-C23 #elifdef #elifndef
+C23 #elifdef #elifndef
#define Y
@@ -1492,7 +1503,7 @@ C23 #elifdef #elifndef
-C23 __VA_OPT__
+C23 __VA_OPT__
Implemented.
Requires #pragma expand. (TODO make the expansion automatic)
@@ -1564,11 +1575,11 @@ C23 __VA_OPT__
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3033.htm
-C23 BitInt(N))
+C23 BitInt(N))
Not implemented
-C23 Compound Literals with storage specifier
+C23 Compound Literals with storage specifier
Not implemented yet.
@@ -1593,13 +1604,13 @@ C23 Compound Literals with storage specifier
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3038.htm
-C23 Variably-modified (VM) types
+C23 Variably-modified (VM) types
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2778.pdf
-C2Y Transformations
+C2Y Transformations
-Extension - defer
+Extension - defer
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3199.htm
@@ -1646,7 +1657,7 @@ Extension - defer
}
-Extension - if with initializer
+Extension - if with initializer
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3196.htm
@@ -1680,7 +1691,7 @@ Extension - if with initializer
C++ proposal
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0305r0.html
-Extension typename on _Generic
+Extension typename on _Generic
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3260.pdf
@@ -1695,9 +1706,9 @@ Extension typename on _Generic
}
-Cake Extensions (Not in C23, C2Y)
+Cake Extensions (Not in C23, C2Y)
-Extension - try catch throw
+Extension - try catch throw
try-statement:
try secondary-block
@@ -1729,7 +1740,7 @@ Extension - try catch throw
}
-Extension Literal function - lambdas
+Extension Literal function - lambdas
Lambdas without capture where implemented using a syntax similar of compound literal for function pointer.
@@ -1770,14 +1781,14 @@ Extension Literal function - lambdas
}
-Extension #pragma dir
+Extension #pragma dir
#pragma dir "C:/Program Files (x86)/Windows Kits/10//include/10.0.22000.0/cppwinrt"
pragma dir makes the preprocessor include the directory when searching for includes.
-Extension #pragma expand
+Extension #pragma expand
pragma expand tells the C back-end to not hide macro expansions. This is necessary when
the compiler makes changes inside the macro code.
@@ -1820,7 +1831,7 @@ Extension #pragma expand
-Type traits
+Type traits
We have some compile time functions to infer properties of types.
@@ -1852,11 +1863,11 @@ Type traits
-Extension - Ownership checks
+Extension - Ownership checks
See ownership
-Extension assert statement
+Extension assert statement
In cake assert is an statement. The reason is because it works as tips for flow analysis
and these checks are checked in runtime in debug bugs.
@@ -1867,5 +1878,5 @@
Extension assert statement
When cake reads GCC MSVC headers it overrides the macro assert to match the cake
assert statement.
-Versions
+Versions