X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ast.c;h=0fb422b53dc9c1fef6b1b904b14b01a147a5ed04;hb=cb69923e40a94f9b611874437f00d7d31abf3dd7;hp=af2a2d370ccfc0af79fb810bb6872fe347c292bd;hpb=c3ddc3ef878774faea470a71d2485f92ec14a089;p=cparser diff --git a/ast.c b/ast.c index af2a2d3..0fb422b 100644 --- a/ast.c +++ b/ast.c @@ -48,10 +48,7 @@ struct obstack ast_obstack; static int indent; -/** If set, implicit casts are printed. */ bool print_implicit_casts = false; - -/** If set parenthesis are printed to indicate operator precedence. */ bool print_parenthesis = false; static void print_statement(const statement_t *statement); @@ -69,11 +66,6 @@ void print_indent(void) print_string("\t"); } -static void print_symbol(const symbol_t *symbol) -{ - print_string(symbol->string); -} - static void print_stringrep(const string_t *string) { for (size_t i = 0; i < string->size; ++i) { @@ -108,8 +100,6 @@ static int right_to_left(unsigned precedence) static unsigned get_expression_precedence(expression_kind_t kind) { static const unsigned prec[] = { - [EXPR_UNKNOWN] = PREC_PRIMARY, - [EXPR_INVALID] = PREC_PRIMARY, [EXPR_REFERENCE] = PREC_PRIMARY, [EXPR_REFERENCE_ENUM_VALUE] = PREC_PRIMARY, [EXPR_LITERAL_INTEGER] = PREC_PRIMARY, @@ -152,7 +142,6 @@ static unsigned get_expression_precedence(expression_kind_t kind) [EXPR_UNARY_PREFIX_INCREMENT] = PREC_UNARY, [EXPR_UNARY_PREFIX_DECREMENT] = PREC_UNARY, [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, @@ -216,7 +205,7 @@ static void print_quoted_string(const string_t *const string, char border, print_char(border); const char *end = string->begin + string->size - skip; for (const char *c = string->begin; c != end; ++c) { - unsigned char const tc = *c; + const char tc = *c; if (tc == border) { print_string("\\"); } @@ -236,7 +225,7 @@ static void print_quoted_string(const string_t *const string, char border, } /* FALLTHROUGH */ default: - if (tc < 0x80 && !isprint(tc)) { + if ((unsigned)tc < 0x80 && !isprint(tc)) { print_format("\\%03o", (unsigned)tc); } else { print_char(tc); @@ -270,8 +259,8 @@ static void print_literal(const literal_expression_t *literal) case EXPR_LITERAL_INTEGER_OCTAL: case EXPR_LITERAL_FLOATINGPOINT: print_stringrep(&literal->value); - if (literal->suffix != NULL) - print_symbol(literal->suffix); + if (literal->suffix.size > 0) + print_stringrep(&literal->suffix); return; case EXPR_LITERAL_WIDE_CHARACTER: print_char('L'); @@ -416,7 +405,6 @@ static void print_unary_expression(const unary_expression_t *unexpr) print_expression_prec(unexpr->value, prec); print_string("--"); return; - case EXPR_UNARY_CAST_IMPLICIT: case EXPR_UNARY_CAST: print_string("("); print_type(unexpr->base.type); @@ -601,6 +589,12 @@ static void print_va_copy(const va_copy_expression_t *expression) static void print_select(const select_expression_t *expression) { print_expression_prec(expression->compound, PREC_POSTFIX); + /* do not print anything for anonymous struct/union selects + * FIXME: if the anonymous select was a '->' this will print '.' + */ + if (expression->compound_entry->base.symbol == NULL) + return; + if (is_type_pointer(skip_typeref(expression->compound->base.type))) { print_string("->"); } else { @@ -675,7 +669,8 @@ static void print_statement_expression(const statement_expression_t *expression) */ static void print_expression_prec(const expression_t *expression, unsigned top_prec) { - if (expression->kind == EXPR_UNARY_CAST_IMPLICIT && !print_implicit_casts) { + if (expression->kind == EXPR_UNARY_CAST + && expression->base.implicit && !print_implicit_casts) { expression = expression->unary.value; } @@ -687,9 +682,8 @@ static void print_expression_prec(const expression_t *expression, unsigned top_p if (parenthesized) print_string("("); switch (expression->kind) { - case EXPR_UNKNOWN: - case EXPR_INVALID: - print_string("$invalid expression$"); + case EXPR_ERROR: + print_string("$error$"); break; case EXPR_WIDE_STRING_LITERAL: case EXPR_STRING_LITERAL: @@ -757,13 +751,6 @@ static void print_expression_prec(const expression_t *expression, unsigned top_p case EXPR_STATEMENT: print_statement_expression(&expression->statement); break; - -#if 0 - default: - /* TODO */ - print_format("some expression of type %d", (int)expression->kind); - break; -#endif } if (parenthesized) print_string(")"); @@ -1193,8 +1180,8 @@ void print_statement(const statement_t *statement) case STATEMENT_LEAVE: print_leave_statement(&statement->leave); break; - case STATEMENT_INVALID: - print_string("$invalid statement$\n"); + case STATEMENT_ERROR: + print_string("$error statement$\n"); break; } } @@ -1433,6 +1420,13 @@ void print_declaration(const entity_t *entity) } break; + case ENTITY_COMPOUND_MEMBER: + print_type_ext(declaration->type, declaration->base.symbol, NULL); + if (entity->compound_member.bitfield) { + print_format(" : %u", entity->compound_member.bit_size); + } + break; + default: print_type_ext(declaration->type, declaration->base.symbol, NULL); break; @@ -1478,19 +1472,14 @@ void print_entity(const entity_t *entity) return; case ENTITY_STRUCT: print_string("struct "); - print_string(entity->base.symbol->string); - if (entity->structe.complete) { - print_string(" "); - print_compound_definition(&entity->structe); - } - print_string(";"); - return; + goto print_compound; case ENTITY_UNION: print_string("union "); +print_compound: print_string(entity->base.symbol->string); - if (entity->unione.complete) { + if (entity->compound.complete) { print_string(" "); - print_compound_definition(&entity->unione); + print_compound_definition(&entity->compound); } print_string(";"); return; @@ -1512,8 +1501,6 @@ void print_entity(const entity_t *entity) case ENTITY_LABEL: case ENTITY_ENUM_VALUE: panic("print_entity used on unexpected entity type"); - case ENTITY_INVALID: - break; } panic("Invalid entity type encountered"); } @@ -1550,7 +1537,7 @@ expression_classification_t is_constant_initializer(const initializer_t *initial return EXPR_CLASS_CONSTANT; case INITIALIZER_VALUE: - return is_constant_expression(initializer->value.value); + return is_linker_constant(initializer->value.value); case INITIALIZER_LIST: { expression_classification_t all = EXPR_CLASS_CONSTANT; @@ -1567,50 +1554,59 @@ expression_classification_t is_constant_initializer(const initializer_t *initial panic("invalid initializer kind found"); } -static expression_classification_t is_object_with_linker_constant_address(const expression_t *expression) +/** + * Checks if an expression references an object with a constant/known location + * to the linker. Example: + * - "x", "*&x" with x being a global variable. The value of x need not be + * constant but the address of x is. + * - "a.b.c" when a has a constant/known location to the linker + */ +static expression_classification_t is_object_with_linker_constant_address( + const expression_t *expression) { switch (expression->kind) { case EXPR_UNARY_DEREFERENCE: - return is_address_constant(expression->unary.value); + return is_linker_constant(expression->unary.value); case EXPR_SELECT: { type_t *base_type = skip_typeref(expression->select.compound->base.type); if (is_type_pointer(base_type)) { /* it's a -> */ - return is_address_constant(expression->select.compound); + return is_linker_constant(expression->select.compound); } else { return is_object_with_linker_constant_address(expression->select.compound); } } case EXPR_ARRAY_ACCESS: { - expression_classification_t const ref = is_address_constant(expression->array_access.array_ref); + expression_classification_t const ref = is_linker_constant(expression->array_access.array_ref); expression_classification_t const idx = is_constant_expression(expression->array_access.index); return ref < idx ? ref : idx; } case EXPR_REFERENCE: { entity_t *entity = expression->reference.entity; - if (is_declaration(entity)) { - switch ((storage_class_tag_t)entity->declaration.storage_class) { - case STORAGE_CLASS_NONE: - case STORAGE_CLASS_EXTERN: - case STORAGE_CLASS_STATIC: - return - entity->kind != ENTITY_VARIABLE || - !entity->variable.thread_local ? EXPR_CLASS_CONSTANT : - EXPR_CLASS_VARIABLE; - - case STORAGE_CLASS_REGISTER: - case STORAGE_CLASS_TYPEDEF: - case STORAGE_CLASS_AUTO: - break; - } + if (!is_declaration(entity)) + return EXPR_CLASS_VARIABLE; + + switch ((storage_class_tag_t)entity->declaration.storage_class) { + case STORAGE_CLASS_NONE: + case STORAGE_CLASS_EXTERN: + case STORAGE_CLASS_STATIC: + return + entity->kind != ENTITY_VARIABLE || + !entity->variable.thread_local ? EXPR_CLASS_CONSTANT : + EXPR_CLASS_VARIABLE; + + case STORAGE_CLASS_REGISTER: + case STORAGE_CLASS_TYPEDEF: + case STORAGE_CLASS_AUTO: + break; } return EXPR_CLASS_VARIABLE; } - case EXPR_INVALID: + case EXPR_ERROR: return EXPR_CLASS_ERROR; default: @@ -1618,7 +1614,7 @@ static expression_classification_t is_object_with_linker_constant_address(const } } -expression_classification_t is_address_constant(const expression_t *expression) +expression_classification_t is_linker_constant(const expression_t *expression) { switch (expression->kind) { case EXPR_STRING_LITERAL: @@ -1627,6 +1623,9 @@ expression_classification_t is_address_constant(const expression_t *expression) case EXPR_LABEL_ADDRESS: return EXPR_CLASS_CONSTANT; + case EXPR_COMPOUND_LITERAL: + return is_constant_initializer(expression->compound_literal.initializer); + case EXPR_UNARY_TAKE_ADDRESS: return is_object_with_linker_constant_address(expression->unary.value); @@ -1635,7 +1634,7 @@ expression_classification_t is_address_constant(const expression_t *expression) = revert_automatic_type_conversion(expression->unary.value); /* dereferencing a function is a NOP */ if (is_type_function(real_type)) { - return is_address_constant(expression->unary.value); + return is_linker_constant(expression->unary.value); } /* FALLTHROUGH */ } @@ -1645,13 +1644,11 @@ expression_classification_t is_address_constant(const expression_t *expression) if (!is_type_pointer(dest) && ( dest->kind != TYPE_ATOMIC || !(get_atomic_type_flags(dest->atomic.akind) & ATOMIC_TYPE_FLAG_INTEGER) || - get_atomic_type_size(dest->atomic.akind) < get_atomic_type_size(get_intptr_kind()) + get_atomic_type_size(dest->atomic.akind) < get_type_size(type_void_ptr) )) - return EXPR_CLASS_VARIABLE; + return is_constant_expression(expression); - expression_classification_t const expr = is_constant_expression(expression->unary.value); - expression_classification_t const addr = is_address_constant(expression->unary.value); - return expr > addr ? expr : addr; + return is_linker_constant(expression->unary.value); } case EXPR_BINARY_ADD: @@ -1662,17 +1659,17 @@ expression_classification_t is_address_constant(const expression_t *expression) type_t *const rtype = skip_typeref(right->base.type); if (is_type_pointer(ltype)) { - expression_classification_t const l = is_address_constant(left); + expression_classification_t const l = is_linker_constant(left); expression_classification_t const r = is_constant_expression(right); return l < r ? l : r; } else if (is_type_pointer(rtype)) { expression_classification_t const l = is_constant_expression(left); - expression_classification_t const r = is_address_constant(right); + expression_classification_t const r = is_linker_constant(right); return l < r ? l : r; } else if (!is_type_valid(ltype) || !is_type_valid(rtype)) { return EXPR_CLASS_ERROR; } else { - return EXPR_CLASS_VARIABLE; + return is_constant_expression(expression); } } @@ -1698,9 +1695,7 @@ expression_classification_t is_address_constant(const expression_t *expression) skip_typeref(revert_automatic_type_conversion(expression)); if (!is_type_array(type)) return EXPR_CLASS_VARIABLE; - expression_classification_t const ref = is_address_constant(expression->array_access.array_ref); - expression_classification_t const idx = is_constant_expression(expression->array_access.index); - return ref < idx ? ref : idx; + return is_linker_constant(expression->array_access.array_ref); } case EXPR_CONDITIONAL: { @@ -1711,17 +1706,33 @@ expression_classification_t is_address_constant(const expression_t *expression) if (fold_constant_to_bool(c)) { expression_t const *const t = expression->conditional.true_expression; - return is_address_constant(t != NULL ? t : c); + return is_linker_constant(t != NULL ? t : c); } else { - return is_address_constant(expression->conditional.false_expression); + return is_linker_constant(expression->conditional.false_expression); } } - case EXPR_INVALID: - return EXPR_CLASS_ERROR; + case EXPR_SELECT: { + entity_t *entity = expression->select.compound_entry; + if (!is_declaration(entity)) + return EXPR_CLASS_VARIABLE; + type_t *type = skip_typeref(entity->declaration.type); + if (is_type_array(type)) { + /* arrays automatically convert to their address */ + expression_t *compound = expression->select.compound; + type_t *base_type = skip_typeref(compound->base.type); + if (is_type_pointer(base_type)) { + /* it's a -> */ + return is_linker_constant(compound); + } else { + return is_object_with_linker_constant_address(compound); + } + } + return EXPR_CLASS_VARIABLE; + } default: - return EXPR_CLASS_VARIABLE; + return is_constant_expression(expression); } } @@ -1739,15 +1750,8 @@ static expression_classification_t is_builtin_const_call(const expression_t *exp return EXPR_CLASS_VARIABLE; switch (ref->entity->function.btk) { - case bk_gnu_builtin_huge_val: - case bk_gnu_builtin_huge_valf: - case bk_gnu_builtin_huge_vall: - case bk_gnu_builtin_inf: - case bk_gnu_builtin_inff: - case bk_gnu_builtin_infl: - case bk_gnu_builtin_nan: - case bk_gnu_builtin_nanf: - case bk_gnu_builtin_nanl: + case BUILTIN_INF: + case BUILTIN_NAN: return EXPR_CLASS_CONSTANT; default: return EXPR_CLASS_VARIABLE; @@ -1797,7 +1801,7 @@ static expression_classification_t is_object_with_constant_address(const express case EXPR_UNARY_DEREFERENCE: return is_constant_pointer(expression->unary.value); - case EXPR_INVALID: + case EXPR_ERROR: return EXPR_CLASS_ERROR; default: @@ -1874,8 +1878,7 @@ expression_classification_t is_constant_expression(const expression_t *expressio case EXPR_UNARY_NOT: return is_constant_expression(expression->unary.value); - case EXPR_UNARY_CAST: - case EXPR_UNARY_CAST_IMPLICIT: { + case EXPR_UNARY_CAST: { type_t *const type = skip_typeref(expression->base.type); if (is_type_scalar(type)) return is_constant_expression(expression->unary.value); @@ -1948,39 +1951,18 @@ expression_classification_t is_constant_expression(const expression_t *expressio } } - case EXPR_INVALID: + case EXPR_ERROR: return EXPR_CLASS_ERROR; - - case EXPR_UNKNOWN: - break; } panic("invalid expression found (is constant expression)"); } -/** - * Initialize the AST construction. - */ void init_ast(void) { obstack_init(&ast_obstack); } -/** - * Free the AST. - */ void exit_ast(void) { obstack_free(&ast_obstack, NULL); } - -/** - * Allocate an AST object of the given size. - * - * @param size the size of the object to allocate - * - * @return A new allocated object in the AST memeory space. - */ -void *(allocate_ast)(size_t size) -{ - return _allocate_ast(size); -}