X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=attribute.c;h=07f152bbf29f65d5c11581e91bb8669502b17ecd;hb=bb8544d38aaa4c716603a5d565c3ff3840454ffc;hp=eca3f61d61b9772c2e6d672e3b1374d8f1197c54;hpb=f9580ab07acfdbde64386a8e3d12a1f56dcf4a54;p=cparser diff --git a/attribute.c b/attribute.c index eca3f61..07f152b 100644 --- a/attribute.c +++ b/attribute.c @@ -144,9 +144,15 @@ type_t *handle_attribute_mode(const attribute_t *attribute, type_t *orig_type) /* This isn't really correct, the backend should provide a list of machine * specific modes (according to gcc philosophy that is...) */ - attribute_argument_t *arg = attribute->a.arguments; - const char *symbol_str = arg->v.symbol->string; - bool sign = is_type_signed(type); + attribute_argument_t *arg = attribute->a.arguments; + if (arg == NULL) { + errorf(&attribute->source_position, + "__attribute__((mode(X))) misses argument"); + return orig_type; + } + + const char *symbol_str = arg->v.symbol->string; + bool sign = is_type_signed(type); atomic_type_kind_t akind; if (strcmp_underscore("QI", symbol_str) == 0 || strcmp_underscore("byte", symbol_str) == 0) { @@ -160,9 +166,8 @@ type_t *handle_attribute_mode(const attribute_t *attribute, type_t *orig_type) } else if (strcmp_underscore("DI", symbol_str) == 0) { akind = sign ? ATOMIC_TYPE_LONGLONG : ATOMIC_TYPE_ULONGLONG; } else { - if (warning.other) - warningf(&attribute->source_position, "ignoring unknown mode '%s'", - symbol_str); + source_position_t const *const pos = &attribute->source_position; + warningf(WARN_OTHER, pos, "ignoring unknown mode '%s'", symbol_str); return orig_type; } @@ -175,8 +180,8 @@ type_t *handle_attribute_mode(const attribute_t *attribute, type_t *orig_type) copy->enumt.akind = akind; return identify_new_type(copy); } else if (is_type_pointer(type)) { - warningf(&attribute->source_position, - "__attribute__((mode)) on pointers not implemented yet (ignored)"); + source_position_t const *const pos = &attribute->source_position; + warningf(WARN_OTHER, pos, "__attribute__((mode)) on pointers not implemented yet (ignored)"); return type; } @@ -221,18 +226,71 @@ static void handle_attribute_aligned(const attribute_t *attribute, break; case ENTITY_STRUCT: case ENTITY_UNION: - if (alignment > entity->compound.alignment) { + if (alignment > (int)entity->compound.alignment) { entity->compound.alignment = alignment; } break; - default: - if (warning.other) { - warningf(&attribute->source_position, - "alignment attribute specification on '%S' ignored", - entity->base.symbol); - } + default: { + source_position_t const *const pos = &attribute->source_position; + char const *const what = get_entity_kind_name(entity->kind); + symbol_t const *const sym = entity->base.symbol; + warningf(WARN_OTHER, pos, "alignment attribute specification on %s '%S' ignored", what, sym); + break; + } + } +} + +static const char *get_argument_string(const attribute_argument_t *argument) +{ + if (argument == NULL) + return NULL; + if (argument->kind != ATTRIBUTE_ARGUMENT_EXPRESSION) + return NULL; + expression_t *expression = argument->v.expression; + if (expression->kind != EXPR_STRING_LITERAL) + return NULL; + return expression->literal.value.begin; +} + +static void handle_attribute_visibility(const attribute_t *attribute, + entity_t *entity) +{ + /* This isn't really correct, the backend should provide a list of machine + * specific modes (according to gcc philosophy that is...) */ + attribute_argument_t *arg = attribute->a.arguments; + if (arg == NULL) { + errorf(&attribute->source_position, + "__attribute__((visibility(X))) misses argument"); + return; + } + const char *string = get_argument_string(arg); + if (string == NULL) { + errorf(&attribute->source_position, + "__attribute__((visibility(X))) argument is not a string"); + return; + } + elf_visibility_tag_t visibility = get_elf_visibility_from_string(string); + if (visibility == ELF_VISIBILITY_ERROR) { + errorf(&attribute->source_position, + "unknown visibility type '%s'", string); + return; + } + + switch (entity->kind) { + case ENTITY_VARIABLE: + entity->variable.elf_visibility = visibility; + break; + case ENTITY_FUNCTION: + entity->function.elf_visibility = visibility; + break; + default: { + source_position_t const *const pos = &attribute->source_position; + char const *const what = get_entity_kind_name(entity->kind); + symbol_t const *const sym = entity->base.symbol; + warningf(WARN_OTHER, pos, "visibility attribute specification on %s '%S' ignored", what, sym); break; } + } } static void warn_arguments(const attribute_t *attribute) @@ -240,11 +298,9 @@ static void warn_arguments(const attribute_t *attribute) if (attribute->a.arguments == NULL) return; - if (warning.other) { - warningf(&attribute->source_position, - "attribute '%s' needs no attributes", - get_attribute_name(attribute->kind)); - } + source_position_t const *const pos = &attribute->source_position; + char const *const what = get_attribute_name(attribute->kind); + warningf(WARN_OTHER, pos, "attribute '%s' needs no arguments", what); } static void handle_attribute_packed_e(const attribute_t *attribute, @@ -252,10 +308,10 @@ static void handle_attribute_packed_e(const attribute_t *attribute, { #if 0 if (entity->kind != ENTITY_STRUCT) { - warningf(&attribute->source_position, - "packed attribute on %s '%s' ignored", - get_entity_kind_name(entity->kind), - entity->base.symbol->string); + source_position_t const *const pos = &attribute->source_position; + char const *const what = get_entity_kind_name(entity->kind); + symbol_t const *const sym = entity->base.symbol; + warningf(WARN_OTHER, pos, "packed attribute on %s '%S' ignored", what, sym); return; } #endif @@ -267,14 +323,29 @@ static void handle_attribute_packed_e(const attribute_t *attribute, static void handle_attribute_packed(const attribute_t *attribute, type_t *type) { if (type->kind != TYPE_COMPOUND_STRUCT) { - warningf(&attribute->source_position, - "packed attribute on type '%T' ignored", type); + source_position_t const *const pos = &attribute->source_position; + warningf(WARN_OTHER, pos, "packed attribute on type '%T' ignored", type); return; } handle_attribute_packed_e(attribute, (entity_t*) type->compound.compound); } +static void handle_attribute_asm(const attribute_t *attribute, + entity_t *entity) +{ + attribute_argument_t *argument = attribute->a.arguments; + assert (argument->kind == ATTRIBUTE_ARGUMENT_EXPRESSION); + expression_t *expression = argument->v.expression; + if (expression->kind != EXPR_STRING_LITERAL) + errorf(&attribute->source_position, + "Invalid asm attribute expression"); + symbol_t *sym = symbol_table_insert(expression->string_literal.value.begin); + entity->function.actual_name = sym; + assert(argument->next == NULL); + return; +} + void handle_entity_attributes(const attribute_t *attributes, entity_t *entity) { if (entity->kind == ENTITY_TYPEDEF) { @@ -329,6 +400,14 @@ void handle_entity_attributes(const attribute_t *attributes, entity_t *entity) handle_attribute_packed_e(attribute, entity); break; + case ATTRIBUTE_GNU_ASM: + handle_attribute_asm(attribute, entity); + break; + + case ATTRIBUTE_GNU_VISIBILITY: + handle_attribute_visibility(attribute, entity); + break; + case ATTRIBUTE_MS_ALIGN: case ATTRIBUTE_GNU_ALIGNED: handle_attribute_aligned(attribute, entity); @@ -379,7 +458,7 @@ type_t *handle_type_attributes(const attribute_t *attributes, type_t *type) switch(attribute->kind) { case ATTRIBUTE_GNU_PACKED: handle_attribute_packed(attribute, type); - break; + break; case ATTRIBUTE_GNU_CDECL: case ATTRIBUTE_MS_CDECL: type = change_calling_convention(type, CC_CDECL); @@ -413,14 +492,7 @@ const char *get_deprecated_string(const attribute_t *attribute) continue; attribute_argument_t *argument = attribute->a.arguments; - if (argument == NULL) - return NULL; - if (argument->kind != ATTRIBUTE_ARGUMENT_EXPRESSION) - return NULL; - expression_t *expression = argument->v.expression; - if (expression->kind != EXPR_STRING_LITERAL) - return NULL; - return expression->string.value.begin; + return get_argument_string(argument); } return NULL; }