Improve diagnostic handling: Add [-Wfoo] and -Werror-foo.
[cparser] / attribute.c
index 1ea8f1d..07f152b 100644 (file)
@@ -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 arguments",
-                                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);
@@ -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->literal.value.begin;
+               return get_argument_string(argument);
        }
        return NULL;
 }