[EXPR_UNARY_CAST] = PREC_UNARY,
[EXPR_UNARY_CAST_IMPLICIT] = PREC_UNARY,
[EXPR_UNARY_ASSUME] = PREC_PRIMARY,
+ [EXPR_UNARY_DELETE] = PREC_UNARY,
+ [EXPR_UNARY_DELETE_ARRAY] = PREC_UNARY,
[EXPR_UNARY_THROW] = PREC_ASSIGNMENT,
[EXPR_BINARY_ADD] = PREC_ADDITIVE,
{
unsigned prec = get_expression_precedence(unexpr->base.kind);
switch(unexpr->base.kind) {
- case EXPR_UNARY_NEGATE: fputc('-', out); break;
- case EXPR_UNARY_PLUS: fputc('+', out); break;
- case EXPR_UNARY_NOT: fputc('!', out); break;
- case EXPR_UNARY_BITWISE_NEGATE: fputc('~', out); break;
- case EXPR_UNARY_PREFIX_INCREMENT: fputs("++", out); break;
- case EXPR_UNARY_PREFIX_DECREMENT: fputs("--", out); break;
- case EXPR_UNARY_DEREFERENCE: fputc('*', out); break;
- case EXPR_UNARY_TAKE_ADDRESS: fputc('&', out); break;
+ case EXPR_UNARY_NEGATE: fputc('-', out); break;
+ case EXPR_UNARY_PLUS: fputc('+', out); break;
+ case EXPR_UNARY_NOT: fputc('!', out); break;
+ case EXPR_UNARY_BITWISE_NEGATE: fputc('~', out); break;
+ case EXPR_UNARY_PREFIX_INCREMENT: fputs("++", out); break;
+ case EXPR_UNARY_PREFIX_DECREMENT: fputs("--", out); break;
+ case EXPR_UNARY_DEREFERENCE: fputc('*', out); break;
+ case EXPR_UNARY_TAKE_ADDRESS: fputc('&', out); break;
+ case EXPR_UNARY_DELETE: fputs("delete ", out); break;
+ case EXPR_UNARY_DELETE_ARRAY: fputs("delete [] ", out); break;
case EXPR_UNARY_POSTFIX_INCREMENT:
print_expression_prec(unexpr->value, prec);
case EXPR_UNARY_PREFIX_DECREMENT:
case EXPR_UNARY_ASSUME: /* has VOID type */
case EXPR_UNARY_DEREFERENCE:
+ case EXPR_UNARY_DELETE:
+ case EXPR_UNARY_DELETE_ARRAY:
case EXPR_UNARY_THROW:
case EXPR_BINARY_ASSIGN:
case EXPR_BINARY_MUL_ASSIGN:
EXPR_UNARY_CAST,
EXPR_UNARY_CAST_IMPLICIT, /**< compiler generated cast */
EXPR_UNARY_ASSUME, /**< MS __assume() */
+ EXPR_UNARY_DELETE,
+ EXPR_UNARY_DELETE_ARRAY,
EXPR_UNARY_THROW,
EXPR_UNARY_LAST = EXPR_UNARY_THROW,
case EXPR_UNARY_PREFIX_DECREMENT: \
case EXPR_UNARY_CAST: \
case EXPR_UNARY_CAST_IMPLICIT: \
- case EXPR_UNARY_ASSUME:
+ case EXPR_UNARY_ASSUME: \
+ case EXPR_UNARY_DELETE: \
+ case EXPR_UNARY_DELETE_ARRAY:
/**
* unary expression with optinal operand
case T___noop: \
case T__assume: \
case T_sizeof: \
+ case T_delete: \
case T_throw:
/**
lhs_decl = NULL;
goto unary;
- case EXPR_UNARY_DEREFERENCE:
- if (lhs_decl == DECL_ANY)
- lhs_decl = NULL;
- goto unary;
case EXPR_UNARY_THROW:
if (expr->unary.value == NULL)
return;
+ /* FALLTHROUGH */
+ case EXPR_UNARY_DEREFERENCE:
+ case EXPR_UNARY_DELETE:
+ case EXPR_UNARY_DELETE_ARRAY:
+ if (lhs_decl == DECL_ANY)
+ lhs_decl = NULL;
goto unary;
case EXPR_UNARY_NEGATE:
return create_invalid_expression();
}
+/**
+ * Parse a delete expression
+ * ISO/IEC 14882:1998(E) §5.3.5
+ */
+static expression_t *parse_delete(void)
+{
+ expression_t *const result = allocate_expression_zero(EXPR_UNARY_DELETE);
+ result->base.source_position = *HERE;
+ result->base.type = type_void;
+
+ eat(T_delete);
+
+ if (token.type == '[') {
+ next_token();
+ result->kind = EXPR_UNARY_DELETE_ARRAY;
+ expect(']');
+end_error:;
+ }
+
+ expression_t *const value = parse_sub_expression(PREC_CAST);
+ result->unary.value = value;
+
+ type_t *const type = skip_typeref(value->base.type);
+ if (!is_type_pointer(type)) {
+ errorf(&value->base.source_position,
+ "operand of delete must have pointer type");
+ } else if (warning.other &&
+ is_type_atomic(skip_typeref(type->pointer.points_to), ATOMIC_TYPE_VOID)) {
+ warningf(&value->base.source_position,
+ "deleting 'void*' is undefined");
+ }
+
+ return result;
+}
+
/**
* Parse a throw expression
* ISO/IEC 14882:1998(E) §15:1
case EXPR_UNARY_CAST_IMPLICIT: return true;
case EXPR_UNARY_ASSUME: return true;
+ case EXPR_UNARY_DELETE: return true;
+ case EXPR_UNARY_DELETE_ARRAY: return true;
case EXPR_UNARY_THROW: return true;
case EXPR_BINARY_ADD: return false;
register_expression_parser(parse_alignof, T___alignof__);
register_expression_parser(parse_extension, T___extension__);
register_expression_parser(parse_builtin_classify_type, T___builtin_classify_type);
+ register_expression_parser(parse_delete, T_delete);
register_expression_parser(parse_throw, T_throw);
}