F diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txtinclude_directories(src/semantics/identifiers)include_directories(src/semantics/memory)include_directories(src/semantics/value)+ include_directories(src/semantics/constraints)include_directories(src/misc)src/semantics/value/type.csrc/semantics/value/evaluation.csrc/semantics/value/constant.c- src/semantics/value/constraints.c+ src/semantics/constraints/expression_constraints.c+ src/semantics/constraints/statement_constraints.csrc/semantics/value/value.csrc/semantics/identifiers/denoted.csrc/semantics/identifiers/scope.cF 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.cif(parse_function_definitions && get_and_check(translation_data,KW_OPEN_CURLY)){struct Type_Function *function_type;+ struct Denoted_Function *hold_function;++ hold_function=(struct Denoted_Function*)hold;function_type=(struct Type_Function*)((struct Denoted_Function*)hold)->type;- ((struct Denoted_Function*)hold) ->body=+++ hold_function->function_scope=(struct Function_Scope*)get_function_scope(scope,(struct Denoted_Function*)hold);++ function_type->function_prototype_scope->parent=(struct Scope*)hold_function->function_scope;++ hold_function->body=(struct AST_Compound_Statement*)parse_finish_compound_statement(translation_data,(struct Scope*)function_type->function_prototype_scope);Queue_Push(where_to_push,get_function_definition_tree(scope,(struct Denoted_Function*)hold));break;F diff --git a/src/frontend/parse/parse_statement.c b/src/frontend/parse/parse_statement.c --- a/src/frontend/parse/parse_statement.c +++ b/src/frontend/parse/parse_statement.cif(translation_data->tokens->size==0)return NULL;--switch(kw_get(translation_data)){case KW_NOTYPE:push_translation_error("statement expected",translation_data);return (struct AST*)get_error_tree(NULL);-case KW_OPEN_CURLY:chomp(translation_data);return parse_finish_compound_statement(translation_data,scope);chomp(translation_data);return parse_finish_default_statement(translation_data,scope);case KW_ID:- /*TODO check if id is in function scope*/- if(0)+ if(check(translation_data,KW_COLUMN,1)){return parse_finish_labeled_statement(translation_data,scope,ST_LABEL);}elsestruct AST_Labeled_Statement *ret;if(check(translation_data,KW_ID,0)){- ret=get_labeled_statement_tree(Queue_Pop(translation_data->tokens),NULL,type);+ ret=get_labeled_statement_tree(Queue_Pop(translation_data->tokens),NULL,type,translation_data,scope);if(get_and_check(translation_data,KW_COLUMN)){ret->statement=parse_statement(translation_data,scope);struct AST* parse_finish_default_statement(struct Translation_Data* translation_data,struct Scope *scope){struct AST_Labeled_Statement *ret;- ret=get_labeled_statement_tree(NULL,NULL,ST_DEFAULT);+ ret=get_labeled_statement_tree(NULL,NULL,ST_DEFAULT,translation_data,scope);if(get_and_check(translation_data,KW_COLUMN)){ret->statement=parse_statement(translation_data,scope);struct AST_Return_Statement *hold;if(get_and_check(translation_data,KW_SEMI_COLUMN)){- hold=get_return_statement_tree(get_nop_tree());+ hold=get_return_statement_tree(get_nop_tree(),translation_data,scope);return (struct AST*)hold;}- hold=get_return_statement_tree(parse_expression(translation_data,scope));+ hold=get_return_statement_tree(parse_expression(translation_data,scope),translation_data,scope);if(get_and_check(translation_data,KW_SEMI_COLUMN)){return (struct AST*)hold;F diff --git a/src/frontend/parse/parse_statement.h b/src/frontend/parse/parse_statement.h --- a/src/frontend/parse/parse_statement.h +++ b/src/frontend/parse/parse_statement.h#include <program.h>+ struct AST* parse_statement(struct Translation_Data* translation_data,struct Scope *scope);struct AST* parse_finish_compound_statement(struct Translation_Data* translation_data,struct Scope *scope);- struct AST* parse_op_e_cl_st(struct Translation_Data* translation_data,struct Scope *scope);+ //struct AST* parse_op_e_cl_st(struct Translation_Data* translation_data,struct Scope *scope);struct AST* parse_finish_if_statement(struct Translation_Data* translation_data,struct Scope *scope);struct AST* parse_finish_switch_statement(struct Translation_Data* translation_data,struct Scope *scope);struct AST* parse_finish_do_while_statement(struct Translation_Data* translation_data,struct Scope *scope);F diff --git a/src/program/gcc_error.c b/src/program/gcc_error.c --- a/src/program/gcc_error.c +++ b/src/program/gcc_error.cchar* get_string_for_type_error(struct Type *type,struct Translation_Data *translation_data){char *ret;+ struct Type *current;- ret=gstr_to_heap("type");+ ret=gstr_to_heap("");+ current=type;++ while(type_is_derivative(current))+ {+ switch(current->specifier)+ {++ case TS_POINTER:+ ret=gstr_append_and_consume(gstr_to_heap("*"),ret);+ current=((struct Type_Pointer*)current)->points_to;+ break;+ case TS_ARRAY:+ ret=gstr_append_and_consume(gstr_to_heap("("),ret);+ ret=gstr_append_and_consume(ret,gstr_to_heap(")[]"));+ current=((struct Type_Array*)current)->is_array_of;+ break;+ case TS_FUNC: /*TODO*/+ goto hack;+ default:+ assert(0);+ }+ }+ hack:+ switch(current->specifier)+ {+ case TS_DOUBLE:+ ret=gstr_append_and_consume(gstr_to_heap("double"),ret);+ break;+ case TS_FLOAT:+ ret=gstr_append_and_consume(gstr_to_heap("float"),ret);+ break;+ case TS_INT:+ ret=gstr_append_and_consume(gstr_to_heap("int"),ret);+ break;+ case TS_CHAR:+ ret=gstr_append_and_consume(gstr_to_heap("char"),ret);+ break;+ default:+ ret=gstr_append_and_consume(gstr_to_heap("type"),ret);+ }return ret;}char* get_string_for_denoted_error(struct Denoted *denoted,struct Translation_Data *translation_data)F diff --git a/src/semantics/ast.c b/src/semantics/ast.c --- a/src/semantics/ast.c +++ b/src/semantics/ast.cstruct AST_Expression* get_cast_expression_tree(struct AST_Expression *operand,struct Type *type,struct Translation_Data *translation_data){struct Type *operand_type;- if(!type_is_scalar(type))+ if(!type_is_scalar(type) || operand->type==ERROR){push_translation_error("cast type needs to be of scalar type",translation_data);push_translation_note("got %T instead",translation_data,type);struct AST_Function_Expression* get_function_expression_tree(struct AST_Expression *id,struct Queue *arg_list,struct Translation_Data *translation_data){+struct AST_Function_Expression *ret;struct Type_Function *id_type;size_t i;id_type=(struct Type_Function*)extract_expresion_value_type(id->value,translation_data);ret=malloc(sizeof(struct AST_Function_Expression));ret->type=OP_FUNCTION;- ret->value=get_expression_value_rvalue(get_temp_object(id_type->return_type));+ ret->value=NULL; /*So, we need to know if there is some error somewhere before we can begin extracting lvalue information*/ret->id=id;ret->number_of_arguments=arg_list->size;assert(arg_list->size==0);- if(constraint_check_function_expression(ret,translation_data))+ if(constraint_check_function_expression(ret,translation_data) && id->type!=ERROR && id_type->specifier!=TS_ERROR)+ {+ ret->value=get_expression_value_rvalue(get_temp_object(id_type->return_type));return ret;+ }else+ {return (struct AST_Function_Expression*)get_error_tree((struct AST*)ret);+ }}struct AST_Unary_Expression* get_unary_expression_tree(struct AST_Expression *operand,struct Expression_Value *value,enum AST_Type type){{push_translation_error("using undeclared id in expression",translation_data);free(ret);- return NULL;+ return (struct AST_Designator*)get_error_tree(NULL);}else{switch(hold_denoted->denotation)}- struct AST_Labeled_Statement* get_labeled_statement_tree(struct token *label,struct AST* statement,enum AST_Type type)+ struct AST_Labeled_Statement* get_labeled_statement_tree(struct token *label,struct AST* statement,enum AST_Type type,struct Translation_Data *translation_data,struct Scope *scope){struct AST_Labeled_Statement *ret;ret=malloc(sizeof(struct AST_Labeled_Statement));ret->type=ST_FOR;return ret;}- struct AST_Return_Statement* get_return_statement_tree(struct AST* return_expression)+ struct AST_Return_Statement* get_return_statement_tree(struct AST* return_expression,struct Translation_Data *translation_data,struct Scope *scope){struct AST_Return_Statement *ret;- ret=malloc(sizeof(struct AST_If_Statement));- ret->type=ST_RETURN;- ret->return_expression=return_expression;- return ret;+ struct Denoted_Function *hold_function;+ struct Type *return_type;++ hold_function=get_enclosing_function(scope);+ return_type=((struct Type_Function*)hold_function->type)->return_type;++ if(constraint_check_return_statement(return_expression,return_type,translation_data))+ {+ ret=malloc(sizeof(struct AST_If_Statement));+ ret->type=ST_RETURN;+ if(return_expression==NULL)+ ret->return_expression=NULL;+ else+ ret->return_expression=(struct AST*)get_cast_expression_tree((struct AST_Expression*)return_expression,return_type,translation_data);++ return ret;+ }else+ {+ return (struct AST_Return_Statement*)get_error_tree(return_expression);+ }}struct AST_Goto_Statement* get_goto_statement_tree(struct token *label,struct Scope *scope)F diff --git a/src/semantics/ast.h b/src/semantics/ast.h --- a/src/semantics/ast.h +++ b/src/semantics/ast.h- struct AST_Labeled_Statement* get_labeled_statement_tree(struct token *label,struct AST* statement,enum AST_Type type);+ struct AST_Labeled_Statement* get_labeled_statement_tree(struct token *label,struct AST* statement,enum AST_Type type,struct Translation_Data *translation_data,struct Scope *scope);struct AST_Compound_Statement* get_compound_statement_tree(struct Scope *parent_scope);struct AST_If_Statement* get_if_statement_tree();struct AST_Switch_Statement* get_switch_statement_tree();struct AST_While_Statement* get_while_statement_tree();struct AST_Do_While_Statement* get_do_while_statement_tree();struct AST_For_Statement* get_for_statement_tree();- struct AST_Return_Statement* get_return_statement_tree(struct AST* return_expression);+ struct AST_Return_Statement* get_return_statement_tree(struct AST* return_expression,struct Translation_Data *translation_data,struct Scope *scope);struct AST_Goto_Statement* get_goto_statement_tree(struct token *label,struct Scope *scope);struct AST* get_nop_tree();struct AST_Type_Definition* get_type_definition_tree(struct Denoted_Type *definition);F diff --git a/src/semantics/constraints/constraints.h b/src/semantics/constraints/constraints.h new file mode 100644 --- /dev/null +++ b/src/semantics/constraints/constraints.h+ #ifndef WONKY_CONSTRAINTS_H+ #define WONKY_CONSTRAINTS_H WONKY_CONSTRAINTS_H++ #include<expression_constraints.h>+ #include<statement_constraints.h>++ #endifF diff --git a/src/semantics/constraints/expression_constraints.c b/src/semantics/constraints/expression_constraints.c new file mode 100644 --- /dev/null +++ b/src/semantics/constraints/expression_constraints.c+ #ifndef WONKY_EXPRESSION_CONSTRAINTS_C+ #define WONKY_EXPRESSION_CONSTRAINTS_C WONKY_EXPRESSION_CONSTRAINTS_C+ #include <expression_constraints.h>++ /*the operands of % shall both have an integer type 6.5.5*/+ _Bool constraint_check_modulo_expression(struct AST_Expression *left,struct AST_Expression *right,struct Translation_Data *translation_data)+ {+ struct Type *left_type;+ struct Type *right_type;++ if(left->type==ERROR || right->type==ERROR)+ return 0;++ left_type=extract_expresion_value_type(left->value,translation_data);+ right_type=extract_expresion_value_type(right->value,translation_data);+ if(!type_is_integer_type(left_type))+ {+ push_translation_error("expected integer type in right operand of modulo operation",translation_data);+ return 0;+ }+ if(!type_is_integer_type(right_type))+ {+ push_translation_error("expected integer type in right operand of modulo operation",translation_data);+ return 0;+ }+ return 1;+ }+ /*constraints only on modulo operation 6.5.5*/+ _Bool constraint_check_multiplicative_expression(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type operation,struct Translation_Data *translation_data)+ {++ if(left->type==ERROR || right->type==ERROR)+ return 0;++ if(operation==OP_REMAINDER)+ {+ return constraint_check_modulo_expression(left,right,translation_data);+ }else+ {+ struct Type *left_type;+ struct Type *right_type;+ left_type=extract_expresion_value_type(left->value,translation_data);+ right_type=extract_expresion_value_type(right->value,translation_data);++ if(type_is_arithmetic(left_type) && type_is_arithmetic(right_type))+ {+ return 1;+ }else+ {+ push_translation_error("constraint check violation in multiplicative expression",translation_data);+ return 0;+ }+ }+ assert(0);+ }+ /*for addition both operands shall have arithmetic type, or one operand shall be of pointer type and the other of integer type.+ * for subtraction one of the following shall hold+ * both operands shall have arihtmetic type+ * both operands are pointers to qualified or unqualified versions of compatible object types+ * left operand is a pointer to an object type and the right operand has integer type*/+ _Bool constraint_check_additive_expression(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type operation,struct Translation_Data *translation_data)+ {+ struct Type *left_type;+ struct Type *right_type;++ if(left->type==ERROR || right->type==ERROR)+ return 0;+++ assert(operation==OP_SUBTRACTION || operation==OP_ADDITION);+++ left_type=extract_expresion_value_type(left->value,translation_data);+ right_type=extract_expresion_value_type(right->value,translation_data);+ if(operation==OP_ADDITION) // operation is '+'+ {+ if(type_is_arithmetic(left_type))+ {+ if(type_is_arithmetic(right_type))+ {+ return 1;+ }else if(type_is_pointer_to_object(right_type))+ {+ return 1;+ }else+ {+ push_translation_error("unexpected type of right operand of addition",translation_data);+ return 0;+ }+ }else if(type_is_pointer_to_object(left_type))+ {+ if(type_is_arithmetic(right_type))+ {+ return 1;+ }else+ {+ push_translation_error("unexpected type of right operand of addition",translation_data);+ return 0;+ }+ }else+ {+ push_translation_error("unexpected type of left operand of addition",translation_data);+ return 0;+ }+ }else // operation is '-'+ {+ if(type_is_arithmetic(left_type) && type_is_arithmetic(right_type))+ {+ return 1;+ }else if(type_is_pointer_to_object(left_type))+ {+ if(type_is_integer_type(right_type) || type_is_pointer_to_object(right_type))+ {+ return 1;+ }else+ {+ push_translation_error("unexpected type of right operand of addition",translation_data);+ return 0;+ }+ }else+ {+ push_translation_error("unexpected type of left operand of addition",translation_data);+ return 0;+ }+ }++ }+ /*each of the operands shall have integer type 6.5.7*/+ _Bool constraint_check_shift_expression(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type operation,struct Translation_Data *translation_data)+ {+ struct Type *left_type;+ struct Type *right_type;++ if(left->type==ERROR || right->type==ERROR)+ return 0;++ left_type=extract_expresion_value_type(left->value,translation_data);+ right_type=extract_expresion_value_type(right->value,translation_data);+ if(type_is_integer_type(left_type) && type_is_integer_type(right_type))+ {+ return 1;+ }else+ {+ push_translation_error("both operands of shift operation must be of integer type",translation_data);+ return 0;+ }+ }+ _Bool constraint_check_bitwise_expression(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type operation,struct Translation_Data *translation_data)+ {++ if(left->type==ERROR || right->type==ERROR)+ return 0;++ return 1;+ }+ /*+ * One of the following shall hold:+ * both operands have real type+ * both operands are pointers to qualified or unqualified versions of compatible object types+ * both operands are pointers to qualified or unqualified versions of compatible incomplete type+ *+ * */+ _Bool constraint_check_relational_operation(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type operation,struct Translation_Data *translation_data)+ {++ if(left->type==ERROR || right->type==ERROR)+ return 0;++ return 1;+ }+ /* One of the following shall hold:+ * both operands have arithmetic type+ * both operands are pointers to qualified or unqualified versions of compatible types+ * one operand is a pointer to object or incomplete type and the other is a pointer to a qualified or unqualified version of void+ * one operand is a pointer and the other is a null pointer constant*/+ _Bool constraint_check_equality_expression(struct AST_Expression *left,struct AST_Expression *right,struct Translation_Data *translation_data)+ {+ struct Type *left_type;+ struct Type *right_type;++ if(left->type==ERROR || right->type==ERROR)+ return 0;++ left_type=extract_expresion_value_type(left->value,translation_data);+ right_type=extract_expresion_value_type(right->value,translation_data);+ if(type_is_arithmetic(left_type) && type_is_arithmetic(right_type))+ {+ return 1;+ }else if(type_is_pointer_to_object(left_type))+ {+ if(type_is_pointer_to_object(right_type))+ {+ if(types_are_compatible(left_type,right_type))+ {+ return 1;+ }else+ {+ push_translation_error("checking for equality between pointers of incompatible types",translation_data);+ return 0;+ }+ }else if(ast_is_null_pointer_constant((struct AST*)right) || type_is_pointer_to_void(right_type))+ {+ return 1;+ }else+ {+ push_translation_error("rhs is not a pointer",translation_data);+ return 0;+ }+ }else if(type_is_pointer_to_object(right_type))+ {+ if(ast_is_null_pointer_constant((struct AST*)left) || type_is_pointer_to_void(left_type))+ return 1;+ else+ {+ push_translation_error("lhs is not a pointer",translation_data);+ return 0;+ }+ }else if(type_is_pointer_to_incomplete_type(left_type))+ {+ if(type_is_pointer_to_void(right_type) || ast_is_null_pointer_constant((struct AST*)right))+ {+ return 1;+ }else+ {+ push_translation_error("rhs is not a pointer",translation_data);+ return 0;+ }+ }else if(type_is_pointer_to_incomplete_type(right_type))+ {+ if(type_is_pointer_to_void(left_type) || ast_is_null_pointer_constant((struct AST*)left))+ {+ return 1;+ }+ else+ {+ push_translation_error("lhs is not a pointer",translation_data);+ return 0;+ }+ }else if(left_type->specifier==TS_POINTER)+ {+ if(ast_is_null_pointer_constant((struct AST*)right))+ {+ return 1;+ }else+ {+ push_translation_error("rhs is not a null constant",translation_data);+ return 0;+ }+ }else if(right_type->specifier==TS_POINTER)+ {+ if(ast_is_null_pointer_constant((struct AST*)left))+ {+ return 1;+ }else+ {+ push_translation_error("lhs is not a null constant",translation_data);+ return 0;+ }+ }+ }+ /*each of the operands shall have scallar type 6.5.13 6.5.14*/+ _Bool constraint_check_logical_expression(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type operation,struct Translation_Data *translation_data)+ {+ struct Type *left_type;+ struct Type *right_type;++ if(left->type==ERROR || right->type==ERROR)+ return 0;++ left_type=extract_expresion_value_type(left->value,translation_data);+ right_type=extract_expresion_value_type(right->value,translation_data);++ if(type_is_scalar(left_type) && type_is_scalar(right_type))+ {+ return 1;+ }else+ {+ push_translation_error("both operands of logical expression must be of scallar type",translation_data);+ return 0;+ }+ }+ /*+ left operand is a modifiable lvalue++ One of the following shall hold:+ 1. Left operand has qualified or unqualified arithmetic type and the+ right has arithmetic type++ 2. The left operand has a qualified or unqualified version of a+ structure or union type compatible with the type of the right++ 3. Both operands are pointers to qualified or unqualified versions+ of compatible types, and the type pointed ot by the left has all+ the qualifiers of the type pointed by the right++ 4. One operand is a pointer to an object to or incomplete type and the+ other is a pointer to a qualified or unqualified version of void,+ and the type pointed to by the left has all the qualifiers of the+ type pointed to by the right++ 5. The left operand is a pointer and the right is a null pointer+ constant++ 6. The left operand has type _Bool and+ the right is a pointer++ 6.5.16.1+ * */+ _Bool constraint_check_simple_assignment_expression(struct AST_Expression *left,struct AST_Expression *right,struct Translation_Data *translation_data)+ {+ struct Type *left_type;+ struct Type *right_type;++ if(left->type==ERROR || right->type==ERROR)+ return 0;+++ if(!expression_value_is_modifiable(left->value))+ {+ push_translation_error("left operand of assignment operator must be modifiable",translation_data);+ return 0;+ }++ left_type=extract_expresion_value_type(left->value,translation_data);+ right_type=extract_expresion_value_type(right->value,translation_data);++ if(type_is_arithmetic(left_type) && type_is_arithmetic(right_type))+ {+ return 1;+ }else if(type_is_struct_union(left_type) && types_are_compatible_unqualified(left_type,right_type))+ {+ return 1;+ }else if(left_type->specifier==TS_POINTER && types_are_compatible_unqualified(left_type,right_type))+ {+ return 1;+ }else if(left_type->specifier==TS_POINTER && ast_is_null_pointer_constant((struct AST*)right))+ {+ return 1;+ }else+ {+ push_translation_error("constraint check violation in simple assignment expression",translation_data);+ return 0;+ }+ //TODO ADD _BOOL TS+ }+ /*+ left operand is a modifiable lvalue+ if += or -=+ 1. left operand shall be a pointer to an object and the right operand shall be of integer type+ 2. left operand shall be qualified or unqualified arithmetic type and the right shall be an arithmetic type+ else+ each operand shall have arithmetic type consistent with those allowed by the corresponding binary operator++ 6.5.16.2+ */+ _Bool constraint_check_compound_assignment_expression(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type operation,struct Translation_Data *translation_data)+ {+ struct Type *left_type;+ struct Type *right_type;+++ if(left->type==ERROR || right->type==ERROR)+ return 0;++ if(!expression_value_is_modifiable(left->value))+ {+ push_translation_error("left operand of assignment operator must be modifiable",translation_data);+ return 0;+ }++ switch(operation)+ {+ case OP_ADD_ASSIGN:+ case OP_SUBTRACT_ASSIGN:++ left_type=extract_expresion_value_type(left->value,translation_data);+ right_type=extract_expresion_value_type(right->value,translation_data);+ if(left_type->specifier==TS_POINTER && type_is_integer_type(right_type))+ {+ return 1;+ }else if(type_is_arithmetic(left_type) && type_is_arithmetic(right_type))+ {+ return 1;+ }else+ {+ push_translation_error("constraint check violation in compound assignment expression",translation_data);+ return 0;+ }+ assert(0);+ case OP_MULTIPLY_ASSIGN:+ case OP_DIV_ASSIGN:+ case OP_REMAINDER_ASSIGN:+ return constraint_check_multiplicative_expression(left,right,operation,translation_data);+ case OP_SHIFT_RIGHT_ASSIGN:+ case OP_SHIFT_LEFT_ASSIGN:+ return constraint_check_shift_expression(left,right,operation,translation_data);+ case OP_AND_ASSIGN:+ case OP_XOR_ASSIGN:+ case OP_PIPE_ASSIGN:+ return constraint_check_bitwise_expression(left,right,operation,translation_data);+ default:+ assert(0);+ }+ }+ /*+ none that I could see+ */+ _Bool constraint_check_comma_expression(struct AST_Expression *left,struct AST_Expression *right,struct Translation_Data *translation_data)+ {++ if(left->type==ERROR || right->type==ERROR)+ return 0;++ return 1;+ }+ /*+ one of the expressions shall have type pointer to object the other shall have integer+ */+ _Bool constraint_check_array_subscript_expression(struct AST_Expression *left,struct AST_Expression *right,struct Translation_Data *translation_data)+ {+ struct Type *left_type;+ struct Type *right_type;++ if(left->type==ERROR || right->type==ERROR)+ return 0;+++ left_type=extract_expresion_value_type(left->value,translation_data);+ right_type=extract_expresion_value_type(right->value,translation_data);++ if(type_is_pointer(left_type) && type_is_integer_type(right_type))+ {+ return 1;+ }else if(type_is_pointer(right_type) && type_is_integer_type(left_type))+ {+ return 1;+ }else+ {+ push_translation_error("constraint check violation in array subscript expression",translation_data);+ return 0;+ }++ }+ /*+ left is (un)qualified struct or union, second is an id of a memeber of the struct or union+ NOTE: we don't check if id is a member of the struct or union here+ */+ _Bool constraint_check_struct_union_member_expression(struct AST_Expression *left,struct token *id,struct Translation_Data *translation_data)+ {+ struct Type *left_type;++ if(left->type==ERROR)+ return 0;++ left_type=extract_expresion_value_type(left->value,translation_data);+ return type_is_struct_union(left_type);+ }+ /*+ see above+ */+ _Bool constraint_check_struct_union_member_trough_ptr_expression(struct AST_Expression *left,struct token *id,struct Translation_Data *translation_data)+ {+ struct Type *left_type;++ if(left->type==ERROR)+ return 0;++ left_type=extract_expresion_value_type(left->value,translation_data);+ if(type_is_pointer_to_object(left_type))+ {+ left_type=((struct Type_Pointer*)left_type)->points_to;+ return type_is_struct_union(left_type);+ }else+ {+ push_translation_error("constraint check violation in member access expression",translation_data);+ return 0;+ }+ }+ /*+ First operand shall have scaller type+ One of the following shall hold for the second and third operands+ both operands have arithmetic type+ both operands have the same structure or union type+ both operands have void type+ both operands are pointers of (un)qualified versions of compatible types+ one operand is a pointer and the other is a null pointer constant+ one operand is a pointer to an object or incomplete type and the other is a pointer to a (un)qualified version of void+ */+ _Bool constraint_check_conditional_expression(struct AST_Expression *left,struct AST_Expression *center,struct AST_Expression *right,struct Translation_Data *translation_data)+ {+ struct Type *left_type;++ if(left->type==ERROR || center->type==ERROR || right->type==ERROR)+ return 0;++ left_type=extract_expresion_value_type(left->value,translation_data);+ if(!type_is_arithmetic(left_type))+ {+ push_translation_error("first operand of conditional expression must be of arithmetic type",translation_data);+ return 0;+ }else+ {+ struct Type *center_type;+ struct Type *right_type;++ right_type=extract_expresion_value_type(right->value,translation_data);+ center_type=extract_expresion_value_type(center->value,translation_data);++ if(type_is_arithmetic(right_type) && type_is_arithmetic(center_type))+ {+ return 1;+ }else if(type_is_struct_union(center_type) && types_are_compatible(center_type,right_type))+ {+ return 1;+ }else if(center_type->specifier==TS_VOID && right_type->specifier==TS_VOID)+ {+ return 1;+ }else if(type_is_pointer(center_type) && types_are_compatible(center_type,right_type))+ {+ return 1;+ }else if(type_is_pointer(center_type) && ast_is_null_pointer_constant((struct AST*)right))+ {+ return 1;+ }else if(type_is_pointer(right_type) && ast_is_null_pointer_constant((struct AST*)center))+ {+ return 1;+ }else if( (type_is_pointer_to_object(center_type) || type_is_pointer_to_incomplete_type(center_type)) && type_is_pointer_to_void(right_type))+ {+ return 1;+ }else if( (type_is_pointer_to_object(center_type) || type_is_pointer_to_incomplete_type(center_type)) && type_is_pointer_to_void(right_type))+ {+ return 1;+ }else+ {+ push_translation_error("constraint check violation in member contitional expression",translation_data);+ return 0;+ }+ }+ }+ _Bool constraint_check_function_expression(struct AST_Function_Expression *proposed_function,struct Translation_Data *translation_data)+ {+ struct Type *expected_argument_type;+ struct Type *given_argument_type;+ struct Type_Function *proposed_function_type;+ size_t i;++ if(proposed_function->type==ERROR)+ return 0;++ proposed_function_type=(struct Type_Function*)extract_expresion_value_type(proposed_function->id->value,translation_data);+ if(proposed_function_type->specifier!=TS_FUNC)+ {+ push_translation_error("is not a function",translation_data);+ return 0;+ }++ 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)+ {++ if(proposed_function->arg_list[i]->type==ERROR)+ return 0;++ expected_argument_type=proposed_function_type->arguments[i]->object->type;+ given_argument_type=extract_expresion_value_type(proposed_function->arg_list[i]->value,translation_data);++ if(!types_are_compatible_unqualified(expected_argument_type,given_argument_type))+ {+ push_translation_error("incompatible types of argument",translation_data);+ return 0;+ }+ }+ return 1;+ }+ _Bool constraint_check_indirection_expression(struct AST_Expression *operand,struct Translation_Data *translation_data)+ {+ struct Type *operand_type;++ if(operand->type==ERROR)+ return 0;++ operand_type=extract_expresion_value_type(operand->value,translation_data);+ if(operand_type->specifier==TS_POINTER)+ {+ return 1;+ }else+ {+ push_translation_error("needs pointer type",translation_data);+ return 0;+ }+ }+ _Bool constraint_check_address_expression(struct AST_Expression *operand,struct Translation_Data *translation_data)+ {+ struct Type *operand_type;++ if(operand->type==ERROR)+ return 0;++ operand_type=extract_expresion_value_type(operand->value,translation_data);+ if(operand->value->type==VALUE_FUNCTION_DESIGNATOR || operand->type==OP_ARR_SUBSCRIPT || operand->type==OP_DEREFERENCE)+ {+ return 1;+ }else if(operand->value->type==VALUE_LVALUE)+ {+ struct Object *hold_operand_object;+ hold_operand_object=((struct Expression_Value_LValue*)operand->value)->object;+ if(hold_operand_object->kind==OBJECT_KIND_BITFIELD || hold_operand_object->storage_class==SCS_REGISTER)+ {+ push_translation_error("can't get the address of such an operand",translation_data);+ return 0;+ }else+ {+ return 1;+ }+ }else+ {+ push_translation_error("cast type needs to be of scalar type",translation_data);+ return 0;+ }+ }+ _Bool constraint_check_sizeof_by_type(struct Type *type)+ {+ if(type->specifier==TS_ERROR)+ return 0;+ else+ return 1;+ }+ _Bool constraint_check_sizeof_expression(struct AST_Expression *expression,struct Translation_Data *translation_data)+ {+ if(expression->type==ERROR)+ return 0;+ else+ return 1;+ }+ /*+ * operand shall have arithmetic type+ */+ _Bool constraint_check_unary_plus_minus(struct AST_Expression *operand,enum AST_Type operation,struct Translation_Data *translation_data)+ {+ struct Type *operand_type;++ if(operand->type==ERROR)+ return 0;++ operand_type=extract_expresion_value_type(operand->value,translation_data);+ if(type_is_arithmetic(operand_type))+ {+ return 1;+ }else+ {+ push_translation_error("operan of unary +/- must be of arithmetic type",translation_data);+ return 0;+ }+ }+ /*+ * operand shall have integer type+ */+ _Bool constraint_check_unary_bitwise_not(struct AST_Expression *operand,struct Translation_Data *translation_data)+ {+ struct Type *operand_type;++ if(operand->type==ERROR)+ return 0;++ operand_type=extract_expresion_value_type(operand->value,translation_data);+ if(type_is_integer_type(operand_type))+ {+ return 1;+ }else+ {+ push_translation_error("operand of unary ~ must be of integer type",translation_data);+ return 0;+ }+ }+ /*+ * operand shall have scalar type+ */+ _Bool constraint_check_unary_logical_not(struct AST_Expression *operand,struct Translation_Data *translation_data)+ {+ struct Type *operand_type;++ if(operand->type==ERROR)+ return 0;++ operand_type=extract_expresion_value_type(operand->value,translation_data);+ if(type_is_scalar(operand_type))+ {+ return 1;+ }else+ {+ push_translation_error("operand of unary ! operand must be of scallar type",translation_data);+ return 0;+ }++ }+ /*+ operand is a modifiable lvalue and has a (un)qualified real or pointer type+ * */+ _Bool constraint_check_postfix_inc_dec_expression(struct AST_Expression *operand,enum AST_Type operation,struct Translation_Data *translation_data)+ {+ struct Type *operand_type;++ if(operand->type==ERROR)+ return 0;++ if(!expression_value_is_modifiable(operand->value))+ {+ push_translation_error("expected modifiable lvalue as operand to the ++/-- operator",translation_data);+ return 0;+ }+ operand_type=extract_expresion_value_type(operand->value,translation_data);+ if(type_is_real(operand_type) || type_is_pointer(operand_type))+ {+ return 1;+ }else+ {+ push_translation_error("expected real or pointer type as the type of the operand in the ++/-- operator",translation_data);+ return 0;+ }+ }+ /*+ operand is a modifiable lvalue and has a (un)qualified real or pointer type+ * */+ _Bool constraint_check_prefix_inc_dec_expression(struct AST_Expression *operand,enum AST_Type operation,struct Translation_Data *translation_data)+ {+ if(operand->type==ERROR)+ return 0;+ return constraint_check_postfix_inc_dec_expression(operand,operation,translation_data);+ }+ _Bool constraint_check_cast_expression(struct Type *type,struct AST_Expression *expression,struct Translation_Data *translation_data)+ {+ if(expression->type==ERROR || type->specifier==TS_ERROR)+ return 0;+ return 1;+ }+ #endifF diff --git a/src/semantics/constraints/expression_constraints.h b/src/semantics/constraints/expression_constraints.h new file mode 100644 --- /dev/null +++ b/src/semantics/constraints/expression_constraints.h+ #ifndef WONKY_EXPRESSION_CONSTRAINTS_H+ #define WONKY_EXPRESSION_CONSTRAINTS_H WONKY_EXPRESSION_CONSTRAINTS_H+ #include <ast.h>++ _Bool constraint_check_modulo_expression(struct AST_Expression *left,struct AST_Expression *right,struct Translation_Data *translation_data);+ _Bool constraint_check_multiplicative_expression(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type operation,struct Translation_Data *translation_data);+ _Bool constraint_check_additive_expression(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type operation,struct Translation_Data *translation_data);+ _Bool constraint_check_shift_expression(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type operation,struct Translation_Data *translation_data);+ _Bool constraint_check_bitwise_expression(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type operation,struct Translation_Data *translation_data);+ _Bool constraint_check_relational_operation(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type operation,struct Translation_Data *translation_data);+ _Bool constraint_check_equality_expression(struct AST_Expression *left,struct AST_Expression *right,struct Translation_Data *translation_data);+ _Bool constraint_check_logical_expression(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type operation,struct Translation_Data *translation_data);+ _Bool constraint_check_simple_assignment_expression(struct AST_Expression *left,struct AST_Expression *right,struct Translation_Data *translation_data);+ _Bool constraint_check_compound_assignment_expression(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type operation,struct Translation_Data *translation_data);+ _Bool constraint_check_comma_expression(struct AST_Expression *left,struct AST_Expression *right,struct Translation_Data *translation_data);+ _Bool constraint_check_array_subscript_expression(struct AST_Expression *left,struct AST_Expression *right,struct Translation_Data *translation_data);+ _Bool constraint_check_struct_union_member_expression(struct AST_Expression *left,struct token *id,struct Translation_Data *translation_data);+ _Bool constraint_check_struct_union_member_trough_ptr_expression(struct AST_Expression *left,struct token *id,struct Translation_Data *translation_data);+ _Bool constraint_check_conditional_expression(struct AST_Expression *left,struct AST_Expression *center,struct AST_Expression *right,struct Translation_Data *translation_data);+ _Bool constraint_check_function_expression(struct AST_Function_Expression *proposed_function,struct Translation_Data *translation_data);+ _Bool constraint_check_indirection_expression(struct AST_Expression *operand,struct Translation_Data *translation_data);+ _Bool constraint_check_address_expression(struct AST_Expression *operand,struct Translation_Data *translation_data);+ _Bool constraint_check_sizeof_by_type(struct Type *type);+ _Bool constraint_check_unary_plus_minus(struct AST_Expression *operand,enum AST_Type operation,struct Translation_Data *translation_data);+ _Bool constraint_check_unary_bitwise_not(struct AST_Expression *operand,struct Translation_Data *translation_data);+ _Bool constraint_check_unary_logical_not(struct AST_Expression *operand,struct Translation_Data *translation_data);+ _Bool constraint_check_postfix_inc_dec_expression(struct AST_Expression *operand,enum AST_Type operation,struct Translation_Data *translation_data);+ _Bool constraint_check_prefix_inc_dec_expression(struct AST_Expression *operand,enum AST_Type operation,struct Translation_Data *translation_data);+ _Bool constraint_check_sizeof_expression(struct AST_Expression *expression,struct Translation_Data *translation_data);+ _Bool constraint_check_cast_expression(struct Type *type,struct AST_Expression *expression,struct Translation_Data *translation_data);+++ #endifF diff --git a/src/semantics/constraints/statement_constraints.c b/src/semantics/constraints/statement_constraints.c new file mode 100644 --- /dev/null +++ b/src/semantics/constraints/statement_constraints.c+ #ifndef WONKY_STATEMENT_CONSTRAINTS_C+ #define WONKY_STATEMENT_CONSTRAINTS_C WONKY_STATEMENT_CONSTRAINTS_C+ #include <statement_constraints.h>+++ _Bool constraint_check_return_statement(struct AST *return_expression,struct Type *return_type,struct Translation_Data *translation_data)+ {++ if(return_expression==NULL)+ {+ return 1;+ }else if(return_expression->type==ERROR || return_type->specifier==TS_ERROR )+ {+ return 0;+ }else+ {++ struct Type *expression_type;+ struct Expression_Value *value;++ value=((struct AST_Expression*)return_expression)->value;+ expression_type=extract_expresion_value_type(value,translation_data);++ if(!types_are_identical(expression_type,return_type))+ {+ push_translation_error("Returned expression should have %T type, got %T instead",translation_data,return_type,expression_type);+ return 0;+ }else+ {+ return 1;+ }+ }+++ assert(0);++ }+ #endifF diff --git a/src/semantics/constraints/statement_constraints.h b/src/semantics/constraints/statement_constraints.h new file mode 100644 --- /dev/null +++ b/src/semantics/constraints/statement_constraints.h+ #ifndef WONKY_STATEMENT_CONSTRAINTS_H+ #define WONKY_STATEMENT_CONSTRAINTS_H WONKY_STATEMENT_CONSTRAINTS_H+ #include <ast.h>+ #include <type.h>++++ /*_Bool constraint_check_case_statement(struct ,struct Translation_Data *translation_data);*/+ /*_Bool constraint_check_default(struct ,struct Translation_Data *translation_data);*/+ _Bool constraint_check_label(struct AST_Labeled_Statement *label,struct AST_Compound_Statement *function_block,struct Translation_Data *translation_data);++ /*must have scallar controlling expression*/+ _Bool constraint_check_if_statement(struct AST_If_Statement *if_statement,struct Translation_Data *translation_data);+ /*must have integer controlling expresion*/+ _Bool constraint_check_switch_statement(struct AST_Switch_Statement *switch_statement,struct Translation_Data *translation_data);++ /*+ the controlling statement shall have scalar type+ the declaration part shall only declare identifiers for objects having storage class auto or reigster+ */+ _Bool constraint_check_while_statement(struct AST_While_Statement *while_statement,struct Translation_Data *translation_data);+ _Bool constraint_check_do_while_statement(struct AST_Do_While_Statement *do_while_statement,struct Translation_Data *translation_data);+ _Bool constraint_check_for_statement(struct AST_For_Statement *for_statement,struct Translation_Data *translation_data);++ _Bool constraint_check_goto_statement(struct AST_Goto_Statement *goto_statement,struct Translation_Data *translation_data);+ _Bool constraint_check_continue_statement(struct AST_Labeled_Statement *continue_statement,struct Translation_Data *translation_data);+ _Bool constraint_check_break_statement(struct AST* break_statement,struct Translation_Data *translation_data);++ /*must be in a function and must return with the function return type , empty expressions are premmited under functions returning void*/+ _Bool constraint_check_return_statement(struct AST *return_expression,struct Type *return_type,struct Translation_Data *translation_data);+++ #endifF diff --git a/src/semantics/identifiers/denoted.c b/src/semantics/identifiers/denoted.c --- a/src/semantics/identifiers/denoted.c +++ b/src/semantics/identifiers/denoted.cret->location=NULL;ret->function_specifier=fs;ret->body=NULL;+ ret->function_scope=NULL;return (struct Denoted*)ret;}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.hstruct Location *location;enum Function_Specifier function_specifier;+ struct Function_Scope *function_scope;struct AST_Compound_Statement *body;};struct Denoted_ObjectF diff --git a/src/semantics/identifiers/scope.c b/src/semantics/identifiers/scope.c --- a/src/semantics/identifiers/scope.c +++ b/src/semantics/identifiers/scope.creturn (struct Scope*)ret;}- struct Scope* get_function_scope(struct Scope *parent)+ struct Scope* get_function_scope(struct Scope *parent,struct Denoted_Function *function){struct Function_Scope *ret;assert(parent!=NULL && parent->type==FILE_SCOPE);ret=malloc(sizeof(struct Function_Scope));ret->type=FUNCTION_SCOPE;ret->parent=parent;+ ret->function=function;Map_Init(&ret->labels);}+ struct Denoted_Function* get_enclosing_function(struct Scope *scope)+ {+ struct Scope *current;+ current=scope;+ while(current->type!=FUNCTION_SCOPE && current!=NULL)+ {+ assert(current->type!=FILE_SCOPE);+ current=current->parent;+ }++ if(current==NULL)+ return NULL;/*TODO maybe return a denoted_error*/++ return ((struct Function_Scope*)current)->function;+ }_Bool check_if_typedefed(struct Scope* scope,struct token *id){struct Denoted *hold;F diff --git a/src/semantics/identifiers/scope.h b/src/semantics/identifiers/scope.h --- a/src/semantics/identifiers/scope.h +++ b/src/semantics/identifiers/scope.h{enum Scope_Type type;struct Scope *parent;++ struct Denoted_Function *function;Map labels;};struct Scope* get_normal_scope(struct Scope *parent,enum Scope_Type type);- struct Scope* get_function_scope(struct Scope *parent);+ struct Scope* get_function_scope(struct Scope *parent,struct Denoted_Function *function);void* check_label(struct Scope *current,struct token *id);struct Denoted* check_tag(struct Scope *current,struct token *id);void Scope_Push(struct Scope *scope,struct Denoted *declarator,struct Translation_Data *translation_data);+ struct Denoted_Function* get_enclosing_function(struct Scope *scope);+void delete_scope(struct Scope *scope);void delete_normal_scope(struct Normal_Scope *scope);void delete_function_scope(struct Function_Scope *scope);F diff --git a/src/semantics/value/constraints.c b/src/semantics/value/constraints.c deleted file mode 100644 --- a/src/semantics/value/constraints.c +++ /dev/null- #ifndef WONKY_CONSTRAINTS_C- #define WONKY_CONSTRAINTS_C WONKY_CONSTRAINTS_C- #include <constraints.h>-- /*the operands of % shall both have an integer type 6.5.5*/- _Bool constraint_check_modulo_expression(struct AST_Expression *left,struct AST_Expression *right,struct Translation_Data *translation_data)- {- struct Type *left_type;- struct Type *right_type;-- if(left->type==ERROR || right->type==ERROR)- return 0;-- left_type=extract_expresion_value_type(left->value,translation_data);- right_type=extract_expresion_value_type(right->value,translation_data);- if(!type_is_integer_type(left_type))- {- push_translation_error("expected integer type in right operand of modulo operation",translation_data);- return 0;- }- if(!type_is_integer_type(right_type))- {- push_translation_error("expected integer type in right operand of modulo operation",translation_data);- return 0;- }- return 1;- }- /*constraints only on modulo operation 6.5.5*/- _Bool constraint_check_multiplicative_expression(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type operation,struct Translation_Data *translation_data)- {-- if(left->type==ERROR || right->type==ERROR)- return 0;-- if(operation==OP_REMAINDER)- {- return constraint_check_modulo_expression(left,right,translation_data);- }else- {- struct Type *left_type;- struct Type *right_type;- left_type=extract_expresion_value_type(left->value,translation_data);- right_type=extract_expresion_value_type(right->value,translation_data);-- if(type_is_arithmetic(left_type) && type_is_arithmetic(right_type))- {- return 1;- }else- {- push_translation_error("constraint check violation in multiplicative expression",translation_data);- return 0;- }- }- assert(0);- }- /*for addition both operands shall have arithmetic type, or one operand shall be of pointer type and the other of integer type.- * for subtraction one of the following shall hold- * both operands shall have arihtmetic type- * both operands are pointers to qualified or unqualified versions of compatible object types- * left operand is a pointer to an object type and the right operand has integer type*/- _Bool constraint_check_additive_expression(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type operation,struct Translation_Data *translation_data)- {- struct Type *left_type;- struct Type *right_type;-- if(left->type==ERROR || right->type==ERROR)- return 0;--- assert(operation==OP_SUBTRACTION || operation==OP_ADDITION);--- left_type=extract_expresion_value_type(left->value,translation_data);- right_type=extract_expresion_value_type(right->value,translation_data);- if(operation==OP_ADDITION) // operation is '+'- {- if(type_is_arithmetic(left_type))- {- if(type_is_arithmetic(right_type))- {- return 1;- }else if(type_is_pointer_to_object(right_type))- {- return 1;- }else- {- push_translation_error("unexpected type of right operand of addition",translation_data);- return 0;- }- }else if(type_is_pointer_to_object(left_type))- {- if(type_is_arithmetic(right_type))- {- return 1;- }else- {- push_translation_error("unexpected type of right operand of addition",translation_data);- return 0;- }- }else- {- push_translation_error("unexpected type of left operand of addition",translation_data);- return 0;- }- }else // operation is '-'- {- if(type_is_arithmetic(left_type) && type_is_arithmetic(right_type))- {- return 1;- }else if(type_is_pointer_to_object(left_type))- {- if(type_is_integer_type(right_type) || type_is_pointer_to_object(right_type))- {- return 1;- }else- {- push_translation_error("unexpected type of right operand of addition",translation_data);- return 0;- }- }else- {- push_translation_error("unexpected type of left operand of addition",translation_data);- return 0;- }- }-- }- /*each of the operands shall have integer type 6.5.7*/- _Bool constraint_check_shift_expression(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type operation,struct Translation_Data *translation_data)- {- struct Type *left_type;- struct Type *right_type;-- if(left->type==ERROR || right->type==ERROR)- return 0;-- left_type=extract_expresion_value_type(left->value,translation_data);- right_type=extract_expresion_value_type(right->value,translation_data);- if(type_is_integer_type(left_type) && type_is_integer_type(right_type))- {- return 1;- }else- {- push_translation_error("both operands of shift operation must be of integer type",translation_data);- return 0;- }- }- _Bool constraint_check_bitwise_expression(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type operation,struct Translation_Data *translation_data)- {-- if(left->type==ERROR || right->type==ERROR)- return 0;-- return 1;- }- /*- * One of the following shall hold:- * both operands have real type- * both operands are pointers to qualified or unqualified versions of compatible object types- * both operands are pointers to qualified or unqualified versions of compatible incomplete type- *- * */- _Bool constraint_check_relational_operation(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type operation,struct Translation_Data *translation_data)- {-- if(left->type==ERROR || right->type==ERROR)- return 0;-- return 1;- }- /* One of the following shall hold:- * both operands have arithmetic type- * both operands are pointers to qualified or unqualified versions of compatible types- * one operand is a pointer to object or incomplete type and the other is a pointer to a qualified or unqualified version of void- * one operand is a pointer and the other is a null pointer constant*/- _Bool constraint_check_equality_expression(struct AST_Expression *left,struct AST_Expression *right,struct Translation_Data *translation_data)- {- struct Type *left_type;- struct Type *right_type;-- if(left->type==ERROR || right->type==ERROR)- return 0;-- left_type=extract_expresion_value_type(left->value,translation_data);- right_type=extract_expresion_value_type(right->value,translation_data);- if(type_is_arithmetic(left_type) && type_is_arithmetic(right_type))- {- return 1;- }else if(type_is_pointer_to_object(left_type))- {- if(type_is_pointer_to_object(right_type))- {- if(types_are_compatible(left_type,right_type))- {- return 1;- }else- {- push_translation_error("checking for equality between pointers of incompatible types",translation_data);- return 0;- }- }else if(ast_is_null_pointer_constant((struct AST*)right) || type_is_pointer_to_void(right_type))- {- return 1;- }else- {- push_translation_error("rhs is not a pointer",translation_data);- return 0;- }- }else if(type_is_pointer_to_object(right_type))- {- if(ast_is_null_pointer_constant((struct AST*)left) || type_is_pointer_to_void(left_type))- return 1;- else- {- push_translation_error("lhs is not a pointer",translation_data);- return 0;- }- }else if(type_is_pointer_to_incomplete_type(left_type))- {- if(type_is_pointer_to_void(right_type) || ast_is_null_pointer_constant((struct AST*)right))- {- return 1;- }else- {- push_translation_error("rhs is not a pointer",translation_data);- return 0;- }- }else if(type_is_pointer_to_incomplete_type(right_type))- {- if(type_is_pointer_to_void(left_type) || ast_is_null_pointer_constant((struct AST*)left))- {- return 1;- }- else- {- push_translation_error("lhs is not a pointer",translation_data);- return 0;- }- }else if(left_type->specifier==TS_POINTER)- {- if(ast_is_null_pointer_constant((struct AST*)right))- {- return 1;- }else- {- push_translation_error("rhs is not a null constant",translation_data);- return 0;- }- }else if(right_type->specifier==TS_POINTER)- {- if(ast_is_null_pointer_constant((struct AST*)left))- {- return 1;- }else- {- push_translation_error("lhs is not a null constant",translation_data);- return 0;- }- }- }- /*each of the operands shall have scallar type 6.5.13 6.5.14*/- _Bool constraint_check_logical_expression(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type operation,struct Translation_Data *translation_data)- {- struct Type *left_type;- struct Type *right_type;-- if(left->type==ERROR || right->type==ERROR)- return 0;-- left_type=extract_expresion_value_type(left->value,translation_data);- right_type=extract_expresion_value_type(right->value,translation_data);-- if(type_is_scalar(left_type) && type_is_scalar(right_type))- {- return 1;- }else- {- push_translation_error("both operands of logical expression must be of scallar type",translation_data);- return 0;- }- }- /*- left operand is a modifiable lvalue-- One of the following shall hold:- 1. Left operand has qualified or unqualified arithmetic type and the- right has arithmetic type-- 2. The left operand has a qualified or unqualified version of a- structure or union type compatible with the type of the right-- 3. Both operands are pointers to qualified or unqualified versions- of compatible types, and the type pointed ot by the left has all- the qualifiers of the type pointed by the right-- 4. One operand is a pointer to an object to or incomplete type and the- other is a pointer to a qualified or unqualified version of void,- and the type pointed to by the left has all the qualifiers of the- type pointed to by the right-- 5. The left operand is a pointer and the right is a null pointer- constant-- 6. The left operand has type _Bool and- the right is a pointer-- 6.5.16.1- * */- _Bool constraint_check_simple_assignment_expression(struct AST_Expression *left,struct AST_Expression *right,struct Translation_Data *translation_data)- {- struct Type *left_type;- struct Type *right_type;-- if(left->type==ERROR || right->type==ERROR)- return 0;--- if(!expression_value_is_modifiable(left->value))- {- push_translation_error("left operand of assignment operator must be modifiable",translation_data);- return 0;- }-- left_type=extract_expresion_value_type(left->value,translation_data);- right_type=extract_expresion_value_type(right->value,translation_data);-- if(type_is_arithmetic(left_type) && type_is_arithmetic(right_type))- {- return 1;- }else if(type_is_struct_union(left_type) && types_are_compatible_unqualified(left_type,right_type))- {- return 1;- }else if(left_type->specifier==TS_POINTER && types_are_compatible_unqualified(left_type,right_type))- {- return 1;- }else if(left_type->specifier==TS_POINTER && ast_is_null_pointer_constant((struct AST*)right))- {- return 1;- }else- {- push_translation_error("constraint check violation in simple assignment expression",translation_data);- return 0;- }- //TODO ADD _BOOL TS- }- /*- left operand is a modifiable lvalue- if += or -=- 1. left operand shall be a pointer to an object and the right operand shall be of integer type- 2. left operand shall be qualified or unqualified arithmetic type and the right shall be an arithmetic type- else- each operand shall have arithmetic type consistent with those allowed by the corresponding binary operator-- 6.5.16.2- */- _Bool constraint_check_compound_assignment_expression(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type operation,struct Translation_Data *translation_data)- {- struct Type *left_type;- struct Type *right_type;--- if(left->type==ERROR || right->type==ERROR)- return 0;-- if(!expression_value_is_modifiable(left->value))- {- push_translation_error("left operand of assignment operator must be modifiable",translation_data);- return 0;- }-- switch(operation)- {- case OP_ADD_ASSIGN:- case OP_SUBTRACT_ASSIGN:-- left_type=extract_expresion_value_type(left->value,translation_data);- right_type=extract_expresion_value_type(right->value,translation_data);- if(left_type->specifier==TS_POINTER && type_is_integer_type(right_type))- {- return 1;- }else if(type_is_arithmetic(left_type) && type_is_arithmetic(right_type))- {- return 1;- }else- {- push_translation_error("constraint check violation in compound assignment expression",translation_data);- return 0;- }- assert(0);- case OP_MULTIPLY_ASSIGN:- case OP_DIV_ASSIGN:- case OP_REMAINDER_ASSIGN:- return constraint_check_multiplicative_expression(left,right,operation,translation_data);- case OP_SHIFT_RIGHT_ASSIGN:- case OP_SHIFT_LEFT_ASSIGN:- return constraint_check_shift_expression(left,right,operation,translation_data);- case OP_AND_ASSIGN:- case OP_XOR_ASSIGN:- case OP_PIPE_ASSIGN:- return constraint_check_bitwise_expression(left,right,operation,translation_data);- default:- assert(0);- }- }- /*- none that I could see- */- _Bool constraint_check_comma_expression(struct AST_Expression *left,struct AST_Expression *right,struct Translation_Data *translation_data)- {-- if(left->type==ERROR || right->type==ERROR)- return 0;-- return 1;- }- /*- one of the expressions shall have type pointer to object the other shall have integer- */- _Bool constraint_check_array_subscript_expression(struct AST_Expression *left,struct AST_Expression *right,struct Translation_Data *translation_data)- {- struct Type *left_type;- struct Type *right_type;-- if(left->type==ERROR || right->type==ERROR)- return 0;--- left_type=extract_expresion_value_type(left->value,translation_data);- right_type=extract_expresion_value_type(right->value,translation_data);-- if(type_is_pointer(left_type) && type_is_integer_type(right_type))- {- return 1;- }else if(type_is_pointer(right_type) && type_is_integer_type(left_type))- {- return 1;- }else- {- push_translation_error("constraint check violation in array subscript expression",translation_data);- return 0;- }-- }- /*- left is (un)qualified struct or union, second is an id of a memeber of the struct or union- NOTE: we don't check if id is a member of the struct or union here- */- _Bool constraint_check_struct_union_member_expression(struct AST_Expression *left,struct token *id,struct Translation_Data *translation_data)- {- struct Type *left_type;-- if(left->type==ERROR)- return 0;-- left_type=extract_expresion_value_type(left->value,translation_data);- return type_is_struct_union(left_type);- }- /*- see above- */- _Bool constraint_check_struct_union_member_trough_ptr_expression(struct AST_Expression *left,struct token *id,struct Translation_Data *translation_data)- {- struct Type *left_type;-- if(left->type==ERROR)- return 0;-- left_type=extract_expresion_value_type(left->value,translation_data);- if(type_is_pointer_to_object(left_type))- {- left_type=((struct Type_Pointer*)left_type)->points_to;- return type_is_struct_union(left_type);- }else- {- push_translation_error("constraint check violation in member access expression",translation_data);- return 0;- }- }- /*- First operand shall have scaller type- One of the following shall hold for the second and third operands- both operands have arithmetic type- both operands have the same structure or union type- both operands have void type- both operands are pointers of (un)qualified versions of compatible types- one operand is a pointer and the other is a null pointer constant- one operand is a pointer to an object or incomplete type and the other is a pointer to a (un)qualified version of void- */- _Bool constraint_check_conditional_expression(struct AST_Expression *left,struct AST_Expression *center,struct AST_Expression *right,struct Translation_Data *translation_data)- {- struct Type *left_type;-- if(left->type==ERROR || center->type==ERROR || right->type==ERROR)- return 0;-- left_type=extract_expresion_value_type(left->value,translation_data);- if(!type_is_arithmetic(left_type))- {- push_translation_error("first operand of conditional expression must be of arithmetic type",translation_data);- return 0;- }else- {- struct Type *center_type;- struct Type *right_type;-- right_type=extract_expresion_value_type(right->value,translation_data);- center_type=extract_expresion_value_type(center->value,translation_data);-- if(type_is_arithmetic(right_type) && type_is_arithmetic(center_type))- {- return 1;- }else if(type_is_struct_union(center_type) && types_are_compatible(center_type,right_type))- {- return 1;- }else if(center_type->specifier==TS_VOID && right_type->specifier==TS_VOID)- {- return 1;- }else if(type_is_pointer(center_type) && types_are_compatible(center_type,right_type))- {- return 1;- }else if(type_is_pointer(center_type) && ast_is_null_pointer_constant((struct AST*)right))- {- return 1;- }else if(type_is_pointer(right_type) && ast_is_null_pointer_constant((struct AST*)center))- {- return 1;- }else if( (type_is_pointer_to_object(center_type) || type_is_pointer_to_incomplete_type(center_type)) && type_is_pointer_to_void(right_type))- {- return 1;- }else if( (type_is_pointer_to_object(center_type) || type_is_pointer_to_incomplete_type(center_type)) && type_is_pointer_to_void(right_type))- {- return 1;- }else- {- push_translation_error("constraint check violation in member contitional expression",translation_data);- return 0;- }- }- }- _Bool constraint_check_function_expression(struct AST_Function_Expression *proposed_function,struct Translation_Data *translation_data)- {- struct Type *expected_argument_type;- struct Type *given_argument_type;- struct Type_Function *proposed_function_type;- size_t i;-- if(proposed_function->type==ERROR)- return 0;-- proposed_function_type=(struct Type_Function*)extract_expresion_value_type(proposed_function->id->value,translation_data);- if(proposed_function_type->specifier!=TS_FUNC)- {- push_translation_error("is not a function",translation_data);- return 0;- }-- 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)- {- expected_argument_type=proposed_function_type->arguments[i]->object->type;- given_argument_type=extract_expresion_value_type(proposed_function->arg_list[i]->value,translation_data);- if(!types_are_compatible_unqualified(expected_argument_type,given_argument_type))- {- push_translation_error("incompatible types of argument",translation_data);- return 0;- }- }- return 1;- }- _Bool constraint_check_indirection_expression(struct AST_Expression *operand,struct Translation_Data *translation_data)- {- struct Type *operand_type;-- if(operand->type==ERROR)- return 0;-- operand_type=extract_expresion_value_type(operand->value,translation_data);- if(operand_type->specifier==TS_POINTER)- {- return 1;- }else- {- push_translation_error("needs pointer type",translation_data);- return 0;- }- }- _Bool constraint_check_address_expression(struct AST_Expression *operand,struct Translation_Data *translation_data)- {- struct Type *operand_type;-- if(operand->type==ERROR)- return 0;-- operand_type=extract_expresion_value_type(operand->value,translation_data);- if(operand->value->type==VALUE_FUNCTION_DESIGNATOR || operand->type==OP_ARR_SUBSCRIPT || operand->type==OP_DEREFERENCE)- {- return 1;- }else if(operand->value->type==VALUE_LVALUE)- {- struct Object *hold_operand_object;- hold_operand_object=((struct Expression_Value_LValue*)operand->value)->object;- if(hold_operand_object->kind==OBJECT_KIND_BITFIELD || hold_operand_object->storage_class==SCS_REGISTER)- {- push_translation_error("can't get the address of such an operand",translation_data);- return 0;- }else- {- return 1;- }- }else- {- push_translation_error("cast type needs to be of scalar type",translation_data);- return 0;- }- }- _Bool constraint_check_sizeof_by_type(struct Type *type)- {- if(type->specifier==TS_ERROR)- return 0;- else- return 1;- }- _Bool constraint_check_sizeof_expression(struct AST_Expression *expression,struct Translation_Data *translation_data)- {- if(expression->type==ERROR)- return 0;- else- return 1;- }- /*- * operand shall have arithmetic type- */- _Bool constraint_check_unary_plus_minus(struct AST_Expression *operand,enum AST_Type operation,struct Translation_Data *translation_data)- {- struct Type *operand_type;-- if(operand->type==ERROR)- return 0;-- operand_type=extract_expresion_value_type(operand->value,translation_data);- if(type_is_arithmetic(operand_type))- {- return 1;- }else- {- push_translation_error("operan of unary +/- must be of arithmetic type",translation_data);- return 0;- }- }- /*- * operand shall have integer type- */- _Bool constraint_check_unary_bitwise_not(struct AST_Expression *operand,struct Translation_Data *translation_data)- {- struct Type *operand_type;-- if(operand->type==ERROR)- return 0;-- operand_type=extract_expresion_value_type(operand->value,translation_data);- if(type_is_integer_type(operand_type))- {- return 1;- }else- {- push_translation_error("operand of unary ~ must be of integer type",translation_data);- return 0;- }- }- /*- * operand shall have scalar type- */- _Bool constraint_check_unary_logical_not(struct AST_Expression *operand,struct Translation_Data *translation_data)- {- struct Type *operand_type;-- if(operand->type==ERROR)- return 0;-- operand_type=extract_expresion_value_type(operand->value,translation_data);- if(type_is_scalar(operand_type))- {- return 1;- }else- {- push_translation_error("operand of unary ! operand must be of scallar type",translation_data);- return 0;- }-- }- /*- operand is a modifiable lvalue and has a (un)qualified real or pointer type- * */- _Bool constraint_check_postfix_inc_dec_expression(struct AST_Expression *operand,enum AST_Type operation,struct Translation_Data *translation_data)- {- struct Type *operand_type;-- if(operand->type==ERROR)- return 0;-- if(!expression_value_is_modifiable(operand->value))- {- push_translation_error("expected modifiable lvalue as operand to the ++/-- operator",translation_data);- return 0;- }- operand_type=extract_expresion_value_type(operand->value,translation_data);- if(type_is_real(operand_type) || type_is_pointer(operand_type))- {- return 1;- }else- {- push_translation_error("expected real or pointer type as the type of the operand in the ++/-- operator",translation_data);- return 0;- }- }- /*- operand is a modifiable lvalue and has a (un)qualified real or pointer type- * */- _Bool constraint_check_prefix_inc_dec_expression(struct AST_Expression *operand,enum AST_Type operation,struct Translation_Data *translation_data)- {- if(operand->type==ERROR)- return 0;- return constraint_check_postfix_inc_dec_expression(operand,operation,translation_data);- }- _Bool constraint_check_cast_expression(struct Type *type,struct AST_Expression *expression,struct Translation_Data *translation_data)- {- if(expression->type==ERROR || type->specifier==TS_ERROR)- return 0;- return 1;- }- #endifF diff --git a/src/semantics/value/constraints.h b/src/semantics/value/constraints.h deleted file mode 100644 --- a/src/semantics/value/constraints.h +++ /dev/null- #ifndef WONKY_CONSTRAINTS_H- #define WONKY_CONSTRAINTS_H WONKY_CONSTRAINTS_H- #include <constraints.hh>- #include <ast.h>-- _Bool constraint_check_modulo_expression(struct AST_Expression *left,struct AST_Expression *right,struct Translation_Data *translation_data);- _Bool constraint_check_multiplicative_expression(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type operation,struct Translation_Data *translation_data);- _Bool constraint_check_additive_expression(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type operation,struct Translation_Data *translation_data);- _Bool constraint_check_shift_expression(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type operation,struct Translation_Data *translation_data);- _Bool constraint_check_bitwise_expression(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type operation,struct Translation_Data *translation_data);- _Bool constraint_check_relational_operation(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type operation,struct Translation_Data *translation_data);- _Bool constraint_check_equality_expression(struct AST_Expression *left,struct AST_Expression *right,struct Translation_Data *translation_data);- _Bool constraint_check_logical_expression(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type operation,struct Translation_Data *translation_data);- _Bool constraint_check_simple_assignment_expression(struct AST_Expression *left,struct AST_Expression *right,struct Translation_Data *translation_data);- _Bool constraint_check_compound_assignment_expression(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type operation,struct Translation_Data *translation_data);- _Bool constraint_check_comma_expression(struct AST_Expression *left,struct AST_Expression *right,struct Translation_Data *translation_data);- _Bool constraint_check_array_subscript_expression(struct AST_Expression *left,struct AST_Expression *right,struct Translation_Data *translation_data);- _Bool constraint_check_struct_union_member_expression(struct AST_Expression *left,struct token *id,struct Translation_Data *translation_data);- _Bool constraint_check_struct_union_member_trough_ptr_expression(struct AST_Expression *left,struct token *id,struct Translation_Data *translation_data);- _Bool constraint_check_conditional_expression(struct AST_Expression *left,struct AST_Expression *center,struct AST_Expression *right,struct Translation_Data *translation_data);- _Bool constraint_check_function_expression(struct AST_Function_Expression *proposed_function,struct Translation_Data *translation_data);- _Bool constraint_check_indirection_expression(struct AST_Expression *operand,struct Translation_Data *translation_data);- _Bool constraint_check_address_expression(struct AST_Expression *operand,struct Translation_Data *translation_data);- _Bool constraint_check_sizeof_by_type(struct Type *type);- _Bool constraint_check_unary_plus_minus(struct AST_Expression *operand,enum AST_Type operation,struct Translation_Data *translation_data);- _Bool constraint_check_unary_bitwise_not(struct AST_Expression *operand,struct Translation_Data *translation_data);- _Bool constraint_check_unary_logical_not(struct AST_Expression *operand,struct Translation_Data *translation_data);- _Bool constraint_check_postfix_inc_dec_expression(struct AST_Expression *operand,enum AST_Type operation,struct Translation_Data *translation_data);- _Bool constraint_check_prefix_inc_dec_expression(struct AST_Expression *operand,enum AST_Type operation,struct Translation_Data *translation_data);- _Bool constraint_check_sizeof_expression(struct AST_Expression *expression,struct Translation_Data *translation_data);- _Bool constraint_check_cast_expression(struct Type *type,struct AST_Expression *expression,struct Translation_Data *translation_data);--- #endifF diff --git a/src/semantics/value/constraints.hh b/src/semantics/value/constraints.hh deleted file mode 100644 --- a/src/semantics/value/constraints.hh +++ /dev/null- #ifndef WONKY_CONSTRAINTS_HH- #define WONKY_CONSTRAINTS_HH WONKY_CONSTRAINTS_HH-- #endifF 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.c{return (type->specifier==TS_FLOAT || type->specifier==TS_DOUBLE);}+ _Bool type_is_derivative(struct Type *type)+ {+ return (type->specifier==TS_POINTER || type->specifier==TS_ARRAY || type->specifier==TS_FUNC);+ }_Bool type_is_constant(struct Type *type){switch(type->specifier)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.h_Bool type_is_pointer_to_void(struct Type *type);_Bool type_is_real(struct Type *type);_Bool type_is_floating(struct Type *type);+ _Bool type_is_derivative(struct Type *type);/*these return 0 if constant/volatile-ness make no sense for the type*/_Bool type_is_constant(struct Type *type);