+ /* TODO enable extensions */
+ expression_t *expression = parse_sub_expression(precedence);
+ /* TODO disable extensions */
+ return expression;
+}
+
+static expression_t *parse_builtin_classify_type(const unsigned precedence)
+{
+ eat(T___builtin_classify_type);
+
+ expression_t *result = allocate_expression_zero(EXPR_CLASSIFY_TYPE);
+ result->base.datatype = type_int;
+
+ expect('(');
+ expression_t *expression = parse_sub_expression(precedence);
+ expect(')');
+ result->classify_type.type_expression = expression;
+
+ return result;
+}
+
+static void semantic_incdec(unary_expression_t *expression)
+{
+ type_t *orig_type = expression->value->base.datatype;
+ if(orig_type == NULL)
+ return;
+
+ type_t *type = skip_typeref(orig_type);
+ if(!is_type_arithmetic(type) && type->kind != TYPE_POINTER) {
+ /* TODO: improve error message */
+ errorf(HERE, "operation needs an arithmetic or pointer type");
+ return;
+ }
+
+ expression->expression.datatype = orig_type;
+}
+
+static void semantic_unexpr_arithmetic(unary_expression_t *expression)
+{
+ type_t *orig_type = expression->value->base.datatype;
+ if(orig_type == NULL)
+ return;
+
+ type_t *type = skip_typeref(orig_type);
+ if(!is_type_arithmetic(type)) {
+ /* TODO: improve error message */
+ errorf(HERE, "operation needs an arithmetic type");
+ return;
+ }
+
+ expression->expression.datatype = orig_type;
+}
+
+static void semantic_unexpr_scalar(unary_expression_t *expression)
+{
+ type_t *orig_type = expression->value->base.datatype;
+ if(orig_type == NULL)
+ return;
+
+ type_t *type = skip_typeref(orig_type);
+ if (!is_type_scalar(type)) {
+ errorf(HERE, "operand of ! must be of scalar type");
+ return;
+ }
+
+ expression->expression.datatype = orig_type;
+}
+
+static void semantic_unexpr_integer(unary_expression_t *expression)
+{
+ type_t *orig_type = expression->value->base.datatype;
+ if(orig_type == NULL)
+ return;
+
+ type_t *type = skip_typeref(orig_type);
+ if (!is_type_integer(type)) {
+ errorf(HERE, "operand of ~ must be of integer type");
+ return;
+ }
+
+ expression->expression.datatype = orig_type;
+}
+
+static void semantic_dereference(unary_expression_t *expression)
+{
+ type_t *orig_type = expression->value->base.datatype;
+ if(orig_type == NULL)
+ return;
+
+ type_t *type = skip_typeref(orig_type);
+ if(!is_type_pointer(type)) {
+ errorf(HERE, "Unary '*' needs pointer or arrray type, but type '%T' given", orig_type);
+ return;
+ }
+
+ pointer_type_t *pointer_type = &type->pointer;
+ type_t *result_type = pointer_type->points_to;
+
+ result_type = automatic_type_conversion(result_type);
+ expression->expression.datatype = result_type;
+}
+
+/**
+ * Check the semantic of the address taken expression.
+ */
+static void semantic_take_addr(unary_expression_t *expression)
+{
+ expression_t *value = expression->value;
+ value->base.datatype = revert_automatic_type_conversion(value);
+
+ type_t *orig_type = value->base.datatype;
+ if(orig_type == NULL)
+ return;
+
+ if(value->kind == EXPR_REFERENCE) {
+ reference_expression_t *reference = (reference_expression_t*) value;
+ declaration_t *declaration = reference->declaration;
+ if(declaration != NULL) {
+ if (declaration->storage_class == STORAGE_CLASS_REGISTER) {
+ errorf(expression->expression.source_position,
+ "address of register variable '%Y' requested",
+ declaration->symbol);
+ }
+ declaration->address_taken = 1;
+ }
+ }
+
+ expression->expression.datatype = make_pointer_type(orig_type, TYPE_QUALIFIER_NONE);
+}
+
+#define CREATE_UNARY_EXPRESSION_PARSER(token_type, unexpression_type, sfunc) \
+static expression_t *parse_##unexpression_type(unsigned precedence) \
+{ \
+ eat(token_type); \
+ \
+ expression_t *unary_expression \
+ = allocate_expression_zero(unexpression_type); \
+ unary_expression->base.source_position = HERE; \
+ unary_expression->unary.value = parse_sub_expression(precedence); \
+ \
+ sfunc(&unary_expression->unary); \
+ \
+ return unary_expression; \
+}
+
+CREATE_UNARY_EXPRESSION_PARSER('-', EXPR_UNARY_NEGATE,
+ semantic_unexpr_arithmetic)
+CREATE_UNARY_EXPRESSION_PARSER('+', EXPR_UNARY_PLUS,
+ semantic_unexpr_arithmetic)
+CREATE_UNARY_EXPRESSION_PARSER('!', EXPR_UNARY_NOT,
+ semantic_unexpr_scalar)
+CREATE_UNARY_EXPRESSION_PARSER('*', EXPR_UNARY_DEREFERENCE,
+ semantic_dereference)
+CREATE_UNARY_EXPRESSION_PARSER('&', EXPR_UNARY_TAKE_ADDRESS,
+ semantic_take_addr)
+CREATE_UNARY_EXPRESSION_PARSER('~', EXPR_UNARY_BITWISE_NEGATE,
+ semantic_unexpr_integer)
+CREATE_UNARY_EXPRESSION_PARSER(T_PLUSPLUS, EXPR_UNARY_PREFIX_INCREMENT,
+ semantic_incdec)
+CREATE_UNARY_EXPRESSION_PARSER(T_MINUSMINUS, EXPR_UNARY_PREFIX_DECREMENT,
+ semantic_incdec)
+
+#define CREATE_UNARY_POSTFIX_EXPRESSION_PARSER(token_type, unexpression_type, \
+ sfunc) \
+static expression_t *parse_##unexpression_type(unsigned precedence, \
+ expression_t *left) \
+{ \
+ (void) precedence; \
+ eat(token_type); \
+ \
+ expression_t *unary_expression \
+ = allocate_expression_zero(unexpression_type); \
+ unary_expression->unary.value = left; \
+ \
+ sfunc(&unary_expression->unary); \
+ \
+ return unary_expression; \
+}
+
+CREATE_UNARY_POSTFIX_EXPRESSION_PARSER(T_PLUSPLUS,
+ EXPR_UNARY_POSTFIX_INCREMENT,
+ semantic_incdec)
+CREATE_UNARY_POSTFIX_EXPRESSION_PARSER(T_MINUSMINUS,
+ EXPR_UNARY_POSTFIX_DECREMENT,
+ semantic_incdec)
+
+static type_t *semantic_arithmetic(type_t *type_left, type_t *type_right)
+{
+ /* TODO: handle complex + imaginary types */
+
+ /* § 6.3.1.8 Usual arithmetic conversions */
+ if(type_left == type_long_double || type_right == type_long_double) {
+ return type_long_double;
+ } else if(type_left == type_double || type_right == type_double) {
+ return type_double;
+ } else if(type_left == type_float || type_right == type_float) {
+ return type_float;
+ }
+
+ type_right = promote_integer(type_right);
+ type_left = promote_integer(type_left);
+
+ if(type_left == type_right)
+ return type_left;
+
+ bool signed_left = is_type_signed(type_left);
+ bool signed_right = is_type_signed(type_right);
+ int rank_left = get_rank(type_left);
+ int rank_right = get_rank(type_right);
+ if(rank_left < rank_right) {
+ if(signed_left == signed_right || !signed_right) {
+ return type_right;
+ } else {
+ return type_left;
+ }
+ } else {
+ if(signed_left == signed_right || !signed_left) {
+ return type_left;
+ } else {
+ return type_right;
+ }
+ }
+}
+
+/**
+ * Check the semantic restrictions for a binary expression.
+ */
+static void semantic_binexpr_arithmetic(binary_expression_t *expression)
+{
+ expression_t *left = expression->left;
+ expression_t *right = expression->right;
+ type_t *orig_type_left = left->base.datatype;
+ type_t *orig_type_right = right->base.datatype;
+
+ if(orig_type_left == NULL || orig_type_right == NULL)
+ return;
+
+ type_t *type_left = skip_typeref(orig_type_left);
+ type_t *type_right = skip_typeref(orig_type_right);
+
+ if(!is_type_arithmetic(type_left) || !is_type_arithmetic(type_right)) {
+ /* TODO: improve error message */
+ errorf(HERE, "operation needs arithmetic types");
+ return;
+ }
+
+ type_t *arithmetic_type = semantic_arithmetic(type_left, type_right);
+ expression->left = create_implicit_cast(left, arithmetic_type);
+ expression->right = create_implicit_cast(right, arithmetic_type);
+ expression->expression.datatype = arithmetic_type;
+}
+
+static void semantic_shift_op(binary_expression_t *expression)
+{
+ expression_t *left = expression->left;
+ expression_t *right = expression->right;
+ type_t *orig_type_left = left->base.datatype;
+ type_t *orig_type_right = right->base.datatype;
+
+ if(orig_type_left == NULL || orig_type_right == NULL)
+ return;
+
+ type_t *type_left = skip_typeref(orig_type_left);
+ type_t *type_right = skip_typeref(orig_type_right);
+
+ if(!is_type_integer(type_left) || !is_type_integer(type_right)) {
+ /* TODO: improve error message */
+ errorf(HERE, "operation needs integer types");
+ return;
+ }
+
+ type_left = promote_integer(type_left);
+ type_right = promote_integer(type_right);
+
+ expression->left = create_implicit_cast(left, type_left);
+ expression->right = create_implicit_cast(right, type_right);
+ expression->expression.datatype = type_left;
+}
+
+static void semantic_add(binary_expression_t *expression)
+{
+ expression_t *left = expression->left;
+ expression_t *right = expression->right;
+ type_t *orig_type_left = left->base.datatype;
+ type_t *orig_type_right = right->base.datatype;
+
+ if(orig_type_left == NULL || orig_type_right == NULL)
+ return;
+
+ type_t *type_left = skip_typeref(orig_type_left);
+ type_t *type_right = skip_typeref(orig_type_right);
+
+ /* § 5.6.5 */
+ if(is_type_arithmetic(type_left) && is_type_arithmetic(type_right)) {
+ type_t *arithmetic_type = semantic_arithmetic(type_left, type_right);
+ expression->left = create_implicit_cast(left, arithmetic_type);
+ expression->right = create_implicit_cast(right, arithmetic_type);
+ expression->expression.datatype = arithmetic_type;
+ return;
+ } else if(is_type_pointer(type_left) && is_type_integer(type_right)) {
+ expression->expression.datatype = type_left;
+ } else if(is_type_pointer(type_right) && is_type_integer(type_left)) {
+ expression->expression.datatype = type_right;
+ } else {
+ errorf(HERE, "invalid operands to binary + ('%T', '%T')", orig_type_left, orig_type_right);
+ }
+}
+
+static void semantic_sub(binary_expression_t *expression)
+{
+ expression_t *left = expression->left;
+ expression_t *right = expression->right;
+ type_t *orig_type_left = left->base.datatype;
+ type_t *orig_type_right = right->base.datatype;
+
+ if(orig_type_left == NULL || orig_type_right == NULL)
+ return;
+
+ type_t *type_left = skip_typeref(orig_type_left);
+ type_t *type_right = skip_typeref(orig_type_right);
+
+ /* § 5.6.5 */
+ if(is_type_arithmetic(type_left) && is_type_arithmetic(type_right)) {
+ type_t *arithmetic_type = semantic_arithmetic(type_left, type_right);
+ expression->left = create_implicit_cast(left, arithmetic_type);
+ expression->right = create_implicit_cast(right, arithmetic_type);
+ expression->expression.datatype = arithmetic_type;
+ return;
+ } else if(is_type_pointer(type_left) && is_type_integer(type_right)) {
+ expression->expression.datatype = type_left;
+ } else if(is_type_pointer(type_left) && is_type_pointer(type_right)) {
+ if(!pointers_compatible(type_left, type_right)) {
+ errorf(HERE, "pointers to incompatible objects to binary - ('%T', '%T')", orig_type_left, orig_type_right);
+ } else {
+ expression->expression.datatype = type_ptrdiff_t;
+ }
+ } else {
+ errorf(HERE, "invalid operands to binary - ('%T', '%T')", orig_type_left, orig_type_right);
+ }
+}
+
+static void semantic_comparison(binary_expression_t *expression)
+{
+ expression_t *left = expression->left;
+ expression_t *right = expression->right;
+ type_t *orig_type_left = left->base.datatype;
+ type_t *orig_type_right = right->base.datatype;
+
+ if(orig_type_left == NULL || orig_type_right == NULL)
+ return;
+
+ type_t *type_left = skip_typeref(orig_type_left);
+ type_t *type_right = skip_typeref(orig_type_right);
+
+ /* TODO non-arithmetic types */
+ if(is_type_arithmetic(type_left) && is_type_arithmetic(type_right)) {
+ type_t *arithmetic_type = semantic_arithmetic(type_left, type_right);
+ expression->left = create_implicit_cast(left, arithmetic_type);
+ expression->right = create_implicit_cast(right, arithmetic_type);
+ expression->expression.datatype = arithmetic_type;
+ } else if (is_type_pointer(type_left) && is_type_pointer(type_right)) {
+ /* TODO check compatibility */
+ } else if (is_type_pointer(type_left)) {
+ expression->right = create_implicit_cast(right, type_left);
+ } else if (is_type_pointer(type_right)) {
+ expression->left = create_implicit_cast(left, type_right);
+ } else {
+ type_error_incompatible("invalid operands in comparison",
+ token.source_position, type_left, type_right);
+ }
+ expression->expression.datatype = type_int;
+}
+
+static void semantic_arithmetic_assign(binary_expression_t *expression)
+{
+ expression_t *left = expression->left;
+ expression_t *right = expression->right;
+ type_t *orig_type_left = left->base.datatype;
+ type_t *orig_type_right = right->base.datatype;
+
+ if(orig_type_left == NULL || orig_type_right == NULL)
+ return;
+
+ type_t *type_left = skip_typeref(orig_type_left);
+ type_t *type_right = skip_typeref(orig_type_right);
+
+ if(!is_type_arithmetic(type_left) || !is_type_arithmetic(type_right)) {
+ /* TODO: improve error message */
+ errorf(HERE, "operation needs arithmetic types");
+ return;
+ }
+
+ /* combined instructions are tricky. We can't create an implicit cast on
+ * the left side, because we need the uncasted form for the store.
+ * The ast2firm pass has to know that left_type must be right_type
+ * for the arithmetic operation and create a cast by itself */
+ type_t *arithmetic_type = semantic_arithmetic(type_left, type_right);
+ expression->right = create_implicit_cast(right, arithmetic_type);
+ expression->expression.datatype = type_left;
+}
+
+static void semantic_arithmetic_addsubb_assign(binary_expression_t *expression)
+{
+ expression_t *left = expression->left;
+ expression_t *right = expression->right;
+ type_t *orig_type_left = left->base.datatype;
+ type_t *orig_type_right = right->base.datatype;
+
+ if(orig_type_left == NULL || orig_type_right == NULL)
+ return;
+
+ type_t *type_left = skip_typeref(orig_type_left);
+ type_t *type_right = skip_typeref(orig_type_right);
+
+ if (is_type_arithmetic(type_left) && is_type_arithmetic(type_right)) {
+ /* combined instructions are tricky. We can't create an implicit cast on
+ * the left side, because we need the uncasted form for the store.
+ * The ast2firm pass has to know that left_type must be right_type
+ * for the arithmetic operation and create a cast by itself */
+ type_t *const arithmetic_type = semantic_arithmetic(type_left, type_right);
+ expression->right = create_implicit_cast(right, arithmetic_type);
+ expression->expression.datatype = type_left;
+ } else if (is_type_pointer(type_left) && is_type_integer(type_right)) {
+ expression->expression.datatype = type_left;
+ } else {
+ errorf(HERE, "incompatible types '%T' and '%T' in assignment", orig_type_left, orig_type_right);
+ return;
+ }
+}
+
+/**
+ * Check the semantic restrictions of a logical expression.
+ */
+static void semantic_logical_op(binary_expression_t *expression)
+{
+ expression_t *left = expression->left;
+ expression_t *right = expression->right;
+ type_t *orig_type_left = left->base.datatype;
+ type_t *orig_type_right = right->base.datatype;
+
+ if(orig_type_left == NULL || orig_type_right == NULL)
+ return;
+
+ type_t *type_left = skip_typeref(orig_type_left);
+ type_t *type_right = skip_typeref(orig_type_right);
+
+ if (!is_type_scalar(type_left) || !is_type_scalar(type_right)) {
+ /* TODO: improve error message */
+ errorf(HERE, "operation needs scalar types");
+ return;
+ }
+
+ expression->expression.datatype = type_int;
+}
+
+/**
+ * Checks if a compound type has constant fields.
+ */
+static bool has_const_fields(const compound_type_t *type)
+{
+ const context_t *context = &type->declaration->context;
+ const declaration_t *declaration = context->declarations;
+
+ for (; declaration != NULL; declaration = declaration->next) {
+ if (declaration->namespc != NAMESPACE_NORMAL)
+ continue;
+
+ const type_t *decl_type = skip_typeref(declaration->type);
+ if (decl_type->base.qualifiers & TYPE_QUALIFIER_CONST)
+ return true;
+ }
+ /* TODO */
+ return false;
+}
+
+/**
+ * Check the semantic restrictions of a binary assign expression.
+ */
+static void semantic_binexpr_assign(binary_expression_t *expression)
+{
+ expression_t *left = expression->left;
+ type_t *orig_type_left = left->base.datatype;
+
+ if(orig_type_left == NULL)
+ return;
+
+ type_t *type_left = revert_automatic_type_conversion(left);
+ type_left = skip_typeref(orig_type_left);