F diff --git a/src/debug/wobler/wobler_tests.h b/src/debug/wobler/wobler_tests.h --- a/src/debug/wobler/wobler_tests.h +++ b/src/debug/wobler/wobler_tests.h.how_much_time_should_execution_take=TEST_TIME_BASELINE,},{+ .filenames={"test_variadic_function.c"},+ .test_function=should_compile,+ .how_much_time_should_execution_take=TEST_TIME_BASELINE,+ },+ {+ .filenames={"test_variadic_function_error.c"},+ .test_function=should_not_compile,+ .how_much_time_should_execution_take=TEST_TIME_BASELINE,+ },+ {+ .filenames={"test_variadic_function_error2.c"},+ .test_function=should_not_compile,+ .how_much_time_should_execution_take=TEST_TIME_BASELINE,+ },+ {.filenames={"test_declaration_speed.c"},.test_function=should_compile,.how_much_time_should_execution_take=TEST_TIME_BASELINE,F diff --git a/src/frontend/parse/parse_declaration.c b/src/frontend/parse/parse_declaration.c --- a/src/frontend/parse/parse_declaration.c +++ b/src/frontend/parse/parse_declaration.c{parse_finish_function_definition(translation_data,scope,(struct Denoted_Function*)hold,where_to_push_function_definitions);break; /*leave the declarator parser loop*/+ }else+ {+ Scope_Push(scope,hold,translation_data);}}else if(hold->denotation==DT_Object){{parse_declaration_inner(translation_data,scope,where_to_push_declarations,where_to_push_declarations,0);}-void parse_finish_function_definition(struct Translation_Data *translation_data,struct Scope *scope,struct Denoted_Function *function,struct Queue *where_to_push){struct Type_Function *function_type;{struct Queue *parameters;struct Normal_Scope *function_prototype_scope;+ _Bool is_variadic=0;function_prototype_scope=(struct Normal_Scope*)get_normal_scope(scope,FUNCTION_PROTOTYPE_SCOPE);parameters=malloc(sizeof(struct Queue));Queue_Init(parameters);- parse_paramenter_list(translation_data,function_prototype_scope,parameters);- base->type=(struct Type*)get_function_type(base->type,parameters,function_prototype_scope);+ is_variadic=parse_paramenter_list(translation_data,function_prototype_scope,parameters);+ base->type=(struct Type*)get_function_type(base->type,parameters,function_prototype_scope,is_variadic,translation_data);}else{/*parameter-list:- (declaratoion-specifiers (declarator | abstract-declarator),)++ (declaratoion-specifiers (declarator | abstract-declarator),)* [ ... ]++ returns 1 if it's a variadic function+ 0 otherwise*/- void parse_paramenter_list(struct Translation_Data *translation_data,struct Normal_Scope *function_prototype_scope,struct Queue *parameters)+ _Bool parse_paramenter_list(struct Translation_Data *translation_data,struct Normal_Scope *function_prototype_scope,struct Queue *parameters){if(get_and_check(translation_data,KW_CLOSE_NORMAL))- return;+ return 0;struct Denotation_Prototype *prototype;struct Denoted_Base *base;struct Denoted *hold;+ _Bool is_variadic=0;do{+ if(get_and_check(translation_data,KW_ELIPSIS))+ {+ is_variadic=1;+ break;+ }prototype=parse_declaration_specifiers(translation_data,(struct Scope*)function_prototype_scope);base=get_denoted_base(prototype);// delete_denoted(hold);delete_denoted_prototype(prototype);delete_denoted_base(base);- return;+ return 0;}hold=extract_denoted(base,prototype,1);delete_denoted_base(base);}while(get_and_check(translation_data,KW_COMMA));++if(!get_and_check(translation_data,KW_CLOSE_NORMAL)){/*TODO error*/push_translation_error("expected a ')' finishing the parameter list",translation_data);Queue_Push(parameters,get_denoted_error(NULL));- return;}+ return is_variadic;}/*type-name:F diff --git a/src/frontend/parse/parse_declaration.h b/src/frontend/parse/parse_declaration.h --- a/src/frontend/parse/parse_declaration.h +++ b/src/frontend/parse/parse_declaration.hchar parse_struct_declaration(struct Translation_Data *translation_data,struct Struct_Union *base);struct Denoted* parse_struct_declarator(struct Translation_Data *translation_data,struct Scope *scope,struct Denotation_Prototype *prototype);void parse_enum_specifier_finish(struct Translation_Data *translation_data,struct Scope *scope,struct Enum *enumeration);- void parse_paramenter_list(struct Translation_Data *translation_data,struct Normal_Scope *function_prototype_scope,struct Queue *parameters);+ _Bool parse_paramenter_list(struct Translation_Data *translation_data,struct Normal_Scope *function_prototype_scope,struct Queue *parameters);struct Type* parse_type_name(struct Translation_Data *translation_data,struct Scope *scope);struct Type* parse_abstract_declarator(struct Translation_Data *translation_data,struct Scope *scope,struct Denotation_Prototype *prototype);F diff --git a/src/frontend/parse/parse_expression.c b/src/frontend/parse/parse_expression.c --- a/src/frontend/parse/parse_expression.c +++ b/src/frontend/parse/parse_expression.cif(get_and_check(translation_data,KW_CLOSE_NORMAL)){- wonky_assert(is_valid_function_expression(ret));+ wonky_assert(is_valid_ast((struct AST*)ret));return ret;}else{F diff --git a/src/semantics/ast.c b/src/semantics/ast.c --- a/src/semantics/ast.c +++ b/src/semantics/ast.csize_t i;if(id->type==ERROR)+ {+ while(arg_list->size>0)+ delete_ast(Queue_Pop(arg_list));return (struct AST_Function_Expression*)get_error_tree((struct AST*)id);+ }else{id_type=(struct Type_Function*)extract_expresion_value_type(id->value,translation_data);F diff --git a/src/semantics/constraints/expression_constraints.c b/src/semantics/constraints/expression_constraints.c --- a/src/semantics/constraints/expression_constraints.c +++ b/src/semantics/constraints/expression_constraints.creturn 0;}- if(proposed_function_type->number_of_arguments!=proposed_function->number_of_arguments)+ if(proposed_function_type->is_variadic)+ {+ if(proposed_function_type->number_of_arguments>proposed_function->number_of_arguments)+ {+ push_translation_error("to little arguments given for variadic function",translation_data);+ return 0;+ }+ }else if(proposed_function_type->number_of_arguments!=proposed_function->number_of_arguments){push_translation_error("mismatching number of arguments",translation_data);return 0;}- for(i=0;i<proposed_function->number_of_arguments;++i)+ for(i=0;i<proposed_function_type->number_of_arguments;++i){if(proposed_function->arg_list[i]->type==ERROR)if(!types_are_compatible_unqualified(expected_argument_type,given_argument_type)){- push_translation_error("incompatible types of argument",translation_data);+ push_translation_error("incompatible types of arguments",translation_data);+ push_translation_note("expected %T, but got %T",translation_data,expected_argument_type,given_argument_type);return 0;}}F diff --git a/src/semantics/identifiers/denoted.h b/src/semantics/identifiers/denoted.h --- a/src/semantics/identifiers/denoted.h +++ b/src/semantics/identifiers/denoted.hsize_t size;_Bool is_const:1;_Bool is_volatile:1;+ _Bool is_variadic_function:1;};F diff --git a/src/semantics/value/type.c b/src/semantics/value/type.c --- a/src/semantics/value/type.c +++ b/src/semantics/value/type.creturn (struct Type*)ret;}- struct Type* get_function_type(struct Type *return_type,struct Queue *parameters,struct Normal_Scope* function_prototype_scope)+ struct Type* get_function_type(struct Type *return_type,struct Queue *parameters,struct Normal_Scope* function_prototype_scope,_Bool is_variadic,struct Translation_Data *translation_data){struct Type_Function *ret;size_t i;ret->number_of_arguments=parameters->size;ret->arguments=malloc(sizeof(struct Denoted_Object*)*ret->number_of_arguments);+ ret->is_variadic=is_variadic;for(i=0;parameters->size>0;++i){ret->arguments[i]=(struct Denoted_Object*)Queue_Pop(parameters);free(parameters);ret=(struct Type_Function*)type_check_and_push((struct Type*)ret,return_type->node,sizeof(struct Type_Function));+ if(is_variadic && ret->number_of_arguments==0)+ {+ push_translation_error("variadic function needs atleast one named argument",translation_data);+ return (struct Type*)get_type_error((struct Type*)ret);+ }+wonky_assert(is_valid_type_function(ret));return (struct Type*)ret;}F diff --git a/src/semantics/value/type.h b/src/semantics/value/type.h --- a/src/semantics/value/type.h +++ b/src/semantics/value/type.hstruct Denoted_Object** arguments;struct Normal_Scope *function_prototype_scope;+ _Bool is_variadic;+};struct Type_Enum{struct Type* get_pointer_type(struct Type *points_to,_Bool is_const,_Bool is_volatile);struct Type* get_array_type(struct Type *array_of,struct AST* number_of_elements,struct Translation_Data *translation_data);struct Type* get_enum_type(struct Denotation_Prototype *prototype);- struct Type* get_function_type(struct Type *return_type,struct Queue *parameters,struct Normal_Scope* function_prototype_scope);+ struct Type* get_function_type(struct Type *return_type,struct Queue *parameters,struct Normal_Scope* function_prototype_scope,_Bool is_variadic,struct Translation_Data *translation_data);struct Type_Basic* get_type_insecure(enum Type_Specifier type_specifier,enum Type_Signedness sign,enum Type_Constraint constraint,size_t type_size,struct Translation_Data *translation_data);F diff --git a/tests/test_variadic_function.c b/tests/test_variadic_function.c new file mode 100644 --- /dev/null +++ b/tests/test_variadic_function.c++ extern int printf(const char *format,...);+++ int main()+ {+ return printf("Hello %s \n","world!");+ }F diff --git a/tests/test_variadic_function_error.c b/tests/test_variadic_function_error.c new file mode 100644 --- /dev/null +++ b/tests/test_variadic_function_error.c+ int a(...);F diff --git a/tests/test_variadic_function_error2.c b/tests/test_variadic_function_error2.c new file mode 100644 --- /dev/null +++ b/tests/test_variadic_function_error2.c+ int a(int a, int b,...);++ int main()+ {+ return a(1);+ }