F diff --git a/src/semantics/ast.c b/src/semantics/ast.c
--- a/src/semantics/ast.c
+++ b/src/semantics/ast.c
return ret;
}
+ struct AST_Expression* get_promoted_expression(struct AST_Expression *operand,struct Translation_Data *translation_data)
+ {
+ struct Type *operand_type;
+ struct Type *promotion_type;
+
+ operand_type=extract_expresion_value_type(operand,translation_data);
+ promotion_type=get_type_for_promotion(operand_type,translation_data);
+ if(types_are_identical(operand_type,promotion_type))
+ return get_cast_expression_tree(operand,promotion_type,translation_data);
+ else
+ return operand;
+ }
+
/*TODO remove this*/
- struct AST_Binary_Expression* get_binary_expression_tree(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type type)
+ struct AST_Binary_Expression* get_binary_expression_tree(struct AST_Expression *left,struct AST_Expression *right,struct Expression_Value *value,enum AST_Type type)
{
struct AST_Binary_Expression *ret;
ret=malloc(sizeof(struct AST_Binary_Expression));
ret->type=type;
ret->left=left;
ret->right=right;
+ ret->value=value;
return ret;
}
+ struct AST_Binary_Expression* get_binary_expression_after_conversion(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type type,struct Translation_Data *translation_data)
+ {
+ struct Type_Basic *left_type;
+ struct Type_Basic *right_type;
+
+ left=get_promoted_expression(left,translation_data);
+ right=get_promoted_expression(right,translation_data);
+
+ left_type=(struct Type_Basic*)extract_expresion_value_type(left,translation_data);
+ right_type=(struct Type_Basic*)extract_expresion_value_type(right,translation_data);
+
+ if(left_type->specifier==TS_DOUBLE)
+ {
+ if(right_type->specifier==TS_DOUBLE && right_type->constraint==TC_LONG)
+ left=get_cast_expression_tree(left,(struct Type*)right_type);
+ else
+ right=get_cast_expression_tree(right,(struct Type*)left_type);
+
+ }else if(right_type->specifier==TS_DOUBLE)
+ {
+ if(left_type->specifier==TS_DOUBLE && left_type->constraint==TC_LONG)
+ right=get_cast_expression_tree(right,(struct Type*)left_type);
+ else
+ left=get_cast_expression_tree(left,(struct Type*)right_type);
+ }else if(left_type->specifier==TS_FLOAT)
+ {
+ right=get_cast_expression_tree(right,left_type);
+ }else if(right_type->specifier==TS_FLOAT)
+ {
+ left=get_cast_expression_tree(left,right_type);
+ }else if(!types_are_identical(left_type,right_type))
+ {
+ /*should have integers by now*/
+ int left_rank;
+ int right_rank;
+ struct Type_Basic *greater_type;
+
+
+ left_rank=type_get_integer_conversion_rank(left_type);
+ right_rank=type_get_integer_conversion_rank(right_type);
+
+ if(left_type->sign==TSIGN_SIGNED)
+ {
+ if(right_type->sign==TSIGN_SIGNED || left_rank!=right_rank)
+ greater_type=(left_rank<right_rank?right_type:left_type);
+ else
+ greater_type=get_type_insecure(left_type->specifier,TSIGN_UNSIGNED,left_type->constraint,left_type->size,translation_data);
+ }
+ else
+ {
+ if(right_type->sign==TSIGN_UNSIGNED || left_rank!=right_rank)
+ greater_type=(left_rank<right_rank?right_type:left_type);
+ else
+ greater_type=get_type_insecure(right_type->specifier,TSIGN_UNSIGNED,right_type->constraint,right_type->size,translation_data);
+ }
+
+ left=get_cast_expression_tree(left,greater_type,translation_data);
+ right=get_cast_expression_tree(right,greater_type,translation_data);
+ }
+
+ return get_binary_expression_tree(left,right,type);
+ }
+
+
struct AST_Unary_Expression* get_indirection_expression_tree(struct AST_Expression *operand,struct Translation_Data *translation_data)
{
struct Type_Pointer *operand_type;
}
- struct AST_Unary_Expression* get_cast_expression_tree(struct AST_Expression *operand,struct Type *type,struct Translation_Data *translation_data)
+ struct AST_Expression* get_cast_expression_tree(struct AST_Expression *operand,struct Type *type,struct Translation_Data *translation_data)
{
- struct AST_Unary_Expression *ret;
+ struct Type *operand_type;
if(!type_is_scalar(type))
- { push_translation_error("cast type needs to be of scalar type",translation_data);return NULL; }
+ { push_translation_error("cast type needs to be of scalar type",translation_data);return NULL; }
+ operand_type=extract_expresion_value_type(operand,translation_data);
+ if(types_are_identical(operand_type,type))
+ return operand;
- ret=malloc(sizeof(struct AST_Unary_Expression));
- ret->type=OP_CAST;
- ret->value=get_expression_value_rvalue(get_temp_object(extract_expresion_value_type(operand->value,translation_data)));
- ret->operand=operand;
+ return get_unary_expression_tree(
+ operand,
+ get_expression_value_rvalue(get_temp_object(extract_expresion_value_type(operand->value,translation_data))),
+ OP_CAST
+ );
return ret;
}
struct AST_Unary_Expression* get_sizeof_by_type_tree(struct Type *type)
{
- struct AST_Unary_Expression *ret;
-
- ret=malloc(sizeof(struct AST_Unary_Expression));
- ret->type=OP_SIZEOF;
- ret->value=get_expression_value_rvalue(get_temp_object(type));
- ret->operand=NULL;
- return ret;
+ return get_unary_expression_tree(NULL,get_expression_value_rvalue(get_temp_object(type)),OP_SIZEOF);
}
{
struct Type *left_type;
struct Type *member_type;
- struct AST_Binary_Expression *ret;
left_type=extract_expresion_value_type(left->value,translation_data);
if(left_type->specifier!=TS_POINTER)
if(!type_is_of_object(member_type))
{push_translation_error("expected pointer to object type in array subscript",translation_data);return NULL;}
- ret=malloc(sizeof(struct AST_Binary_Expression));
- ret->type=OP_ARR_SUBSCRIPT;
- ret->value=get_expression_value_lvalue(get_temp_object(member_type));
-
- ret->left=left;
- ret->right=right;
-
- return ret;
+ return get_binary_expression_tree(left,right,get_expression_value_lvalue(get_temp_object(member_type)),OP_ARR_SUBSCRIPT);
}
struct AST_Binary_Expression* get_struct_union_member_tree(struct AST_Expression *left,struct token *id,struct Translation_Data *translation_data)
struct AST_Unary_Expression* get_unary_arithmetic_tree(struct AST_Expression *operand,enum AST_Type operation,struct Translation_Data *translation_data)
{
struct Type *operand_type;
- struct AST_Unary_Expression *ret;
- operand_type=extract_expresion_value_type(operand->value);
if(operation==OP_UNARY_PLUS || operation==OP_UNARY_MINUS)
{
+ operand=get_promoted_expression(operand);
+ operand_type=extract_expresion_value_type(operand->value);
+
if(type_is_arithmetic(operand_type))
{
- ret=malloc(sizeof(struct AST_Unary_Expression));
- ret->type=operand;
- ret->operand=operand;
- ret->value=get
-
+ return get_unary_expression_tree(
+ operand,
+ get_expression_value_rvalue(get_temp_object(operand_type)),
+ operation
+ );
}else
{
push_translation_error("expected scalar type for operand in unary operation",translation_data);
- return NULL;
+ return get_error_tree(operand);
}
}
}
Queue_Init(&ret->arguments);
return ret;
}
- struct AST_Unary_Expression* get_unary_expression_tree(struct AST_Expression *operand,enum AST_Type type)
+ struct AST_Unary_Expression* get_unary_expression_tree(struct AST_Expression *operand,struct Expression_Value *value,enum AST_Type type)
{
struct AST_Unary_Expression *ret;
ret=malloc(sizeof(struct AST_Unary_Expression));
ret->operand=operand;
ret->type=type;
+ ret->value=value;
return ret;
}
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_Error* get_error_tree(struct AST *error);
struct AST_Declaration_Error* get_declaration_error_tree(struct Denoted *error);
+ struct AST_Expression* get_promoted_expression(struct AST_Expression *operand,struct Translation_Data *translation_data);
+ struct AST_Expression* get_cast_expression_tree(struct AST_Expression *operand,struct Type *type,struct Translation_Data *translation_data);
- struct AST_Binary_Expression* get_binary_expression_tree(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type type);
+ struct AST_Binary_Expression* get_binary_expression_tree(struct AST_Expression *left,struct AST_Expression *right,struct Expression_Value *value,enum AST_Type type);
+ struct AST_Binary_Expression* get_binary_expression_after_conversion(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type type,struct Translation_Data *translation_data);
+
struct AST_Binary_Expression* get_array_subscript_tree(struct AST_Expression *left,struct AST_Expression *right,struct Translation_Data *translation_data);
struct AST_Binary_Expression* get_struct_union_member_tree(struct AST_Expression *left,struct token *id,struct Translation_Data *translation_data);
struct AST_Conditional_Expression* get_conditional_expression_tree(struct AST_Expression *left,struct AST_Expression *center,struct AST_Expression *right);
struct AST_Function_Expression* get_function_expression_tree(struct AST_Expression *id,struct Scope *scope);
- struct AST_Unary_Expression* get_unary_expression_tree(struct AST_Expression *operand,enum AST_Type type);
+ struct AST_Unary_Expression* get_unary_expression_tree(struct AST_Expression *operand,struct Expression_Value *value,enum AST_Type type);
struct AST_Unary_Expression* get_indirection_expression_tree(struct AST_Expression *operand,struct Translation_Data *translation_data);
struct AST_Unary_Expression* get_address_expression_tree(struct AST_Expression *operand);
struct AST_Unary_Expression* get_sizeof_by_type_tree(struct Type *type);
- struct AST_Unary_Expression* get_cast_expression_tree(struct AST_Expression *operand,struct Type *type,struct Translation_Data *translation_data);
struct AST_Unary_Expression* get_unary_arithmetic_tree(struct AST_Expression *operand,enum AST_Type operation,struct Translation_Data *translation_data);
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.c
return 0;
}
}
+
+ struct Type* get_type_for_promotion(struct Type *type,struct Translation_Data *translation_data)
+ {
+ if(type->specifier==TS_CHAR)
+ {
+ return get_type_insecure(TS_INT,TSIGN_NONE,TC_NONE,INT_SIZE,translation_data);
+ }
+ else if(type->specifier==TS_INT)
+ {
+ struct Type_Basic *cache_type;
+ cache_type=(struct Type_Basic*)type;
+ if(cache_type->constraint==TC_SHORT)
+ return get_type_insecure(TS_INT,TSIGN_NONE,TC_NONE,INT_SIZE,translation_data);
+ else
+ return type;
+
+ }else if(type->specifier==TS_BITFIELD)
+ {
+ struct Type_Bit_Field *cache_type;
+ cache_type=(struct Type_Bit_Field*)type;
+ if(cache_type->number_of_bits< 8 * INT_SIZE)
+ return get_type_insecure(TS_INT,TSIGN_NONE,TC_NONE,INT_SIZE,translation_data);
+ else if(cache_type->number_of_bits== 8 * INT_SIZE)
+ return get_type_insecure(TS_INT,TSIGN_UNSIGNED,TC_NONE,INT_SIZE,translation_data);
+ else
+ return type;
+ }else
+ {
+ return type;
+ }
+
+
+
+ }
+ /*TODO*/
+ int type_get_integer_conversion_rank(struct Type_Basic *type)
+ {
+ switch(type->specifier)
+ {
+ case TS_CHAR:
+ return 0;
+ case TS_INT:
+ switch(type->constraint)
+ {
+ case TC_LONG_LONG:
+ return 4;
+ case TC_LONG:
+ return 3;
+ case TC_NONE:
+ return 2;
+ case TC_SHORT:
+ return 1;
+ default:
+ assert(0);
+ }
+ default:
+ assert(0);
+ }
+ }
+
#endif
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
struct Type* 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);
-
-
+ struct Type* get_type_for_promotion(struct Type *type,struct Translation_Data *translation_data);
void delete_enum(struct Enum *enumeration);
char type_is_struct_union(struct Type *type);
char type_is_constant_or_has_constant_member(struct Type *type);
+ int type_get_integer_conversion_rank(struct Type_Basic *type);