Parse and check semantic of delete expressions.
authorChristoph Mallon <christoph.mallon@gmx.de>
Mon, 27 Oct 2008 11:40:23 +0000 (11:40 +0000)
committerChristoph Mallon <christoph.mallon@gmx.de>
Mon, 27 Oct 2008 11:40:23 +0000 (11:40 +0000)
[r23225]

ast.c
ast_t.h
parser.c

diff --git a/ast.c b/ast.c
index 8800c1f..b4efb68 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -131,6 +131,8 @@ static unsigned get_expression_precedence(expression_kind_t kind)
                [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,
@@ -475,14 +477,16 @@ static void print_unary_expression(const unary_expression_t *unexpr)
 {
        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);
@@ -1766,6 +1770,8 @@ bool is_constant_expression(const expression_t *expression)
        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:
diff --git a/ast_t.h b/ast_t.h
index 0f6a815..583e040 100644 (file)
--- a/ast_t.h
+++ b/ast_t.h
@@ -102,6 +102,8 @@ typedef enum expression_kind_t {
        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,
 
@@ -210,7 +212,9 @@ typedef enum funcname_kind_t {
        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
index b0b3008..859d29d 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -296,6 +296,7 @@ static void semantic_comparison(binary_expression_t *expression);
        case T___noop:                   \
        case T__assume:                  \
        case T_sizeof:                   \
+       case T_delete:                   \
        case T_throw:
 
 /**
@@ -2041,14 +2042,16 @@ static void mark_decls_read(expression_t *const expr, declaration_t *lhs_decl)
                                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:
@@ -7779,6 +7782,41 @@ end_error:
        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
@@ -8666,6 +8704,8 @@ static bool expression_has_effect(const expression_t *const expr)
 
                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;
@@ -8925,6 +8965,7 @@ static void init_expression_parsers(void)
        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);
 }