From 9901ca07efc9af25e27ace2a0bd5885c3ddd6d5e Mon Sep 17 00:00:00 2001 From: Matthias Braun Date: Mon, 17 Aug 2009 12:45:38 +0000 Subject: [PATCH] when redeclaring stuff with different attributes merge the attributes and don't display the redundant declaration warning [r26373] --- attribute.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ attribute_t.h | 2 ++ parser.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 101 insertions(+), 2 deletions(-) diff --git a/attribute.c b/attribute.c index 3e42ff2..9385333 100644 --- a/attribute.c +++ b/attribute.c @@ -24,6 +24,7 @@ #include "warning.h" #include "attribute_t.h" #include "symbol_t.h" +#include "adt/error.h" #include "type_t.h" static const char *const attribute_names[ATTRIBUTE_LAST+1] = { @@ -422,3 +423,52 @@ const char *get_deprecated_string(const attribute_t *attribute) } return NULL; } + +static bool property_attribute_equal(const attribute_property_argument_t *prop1, + const attribute_property_argument_t *prop2) +{ + return prop1->put_symbol == prop2->put_symbol + && prop1->get_symbol == prop2->get_symbol; +} + +static bool attribute_argument_equal(const attribute_argument_t *arg1, + const attribute_argument_t *arg2) +{ + if (arg1->kind != arg2->kind) + return false; + + switch (arg1->kind) { + case ATTRIBUTE_ARGUMENT_SYMBOL: + return arg1->v.symbol == arg2->v.symbol; + case ATTRIBUTE_ARGUMENT_EXPRESSION: + /* TODO */ + return false; + } + panic("Unknown argument type found"); +} + +static bool attribute_arguments_equal(const attribute_argument_t *args1, + const attribute_argument_t *args2) +{ + for ( ; args1 != NULL && args2 != NULL; + args1 = args1->next, args2 = args2->next) { + if (!attribute_argument_equal(args1, args2)) + return false; + } + /* both should be NULL now */ + return args1 == args2; +} + +bool attributes_equal(const attribute_t *attr1, const attribute_t *attr2) +{ + if (attr1->kind != attr2->kind) + return false; + + switch (attr1->kind) { + case ATTRIBUTE_MS_PROPERTY: + return property_attribute_equal(attr1->a.property, attr2->a.property); + default: + return attribute_arguments_equal(attr1->a.arguments, + attr2->a.arguments); + } +} diff --git a/attribute_t.h b/attribute_t.h index 1a62aeb..652b17d 100644 --- a/attribute_t.h +++ b/attribute_t.h @@ -143,4 +143,6 @@ struct attribute_t { const char *get_attribute_name(attribute_kind_t kind); +bool attributes_equal(const attribute_t *attr1, const attribute_t *attr2); + #endif diff --git a/parser.c b/parser.c index 1686f34..dc94f49 100644 --- a/parser.c +++ b/parser.c @@ -4275,6 +4275,47 @@ static bool is_error_entity(entity_t *const ent) return false; } +static bool contains_attribute(const attribute_t *list, const attribute_t *attr) +{ + for (const attribute_t *tattr = list; tattr != NULL; tattr = tattr->next) { + if (attributes_equal(tattr, attr)) + return true; + } + return false; +} + +/** + * test wether new_list contains any attributes not included in old_list + */ +static bool has_new_attributes(const attribute_t *old_list, + const attribute_t *new_list) +{ + for (const attribute_t *attr = new_list; attr != NULL; attr = attr->next) { + if (!contains_attribute(old_list, attr)) + return true; + } + return false; +} + +/** + * Merge in attributes from an attribute list (probably from a previous + * declaration with the same name). Warning: destroys the old structure + * of the attribute list - don't reuse attributes after this call. + */ +static void merge_in_attributes(declaration_t *decl, attribute_t *attributes) +{ + attribute_t *next; + for (attribute_t *attr = attributes; attr != NULL; attr = next) { + next = attr->next; + if (contains_attribute(decl->attributes, attr)) + continue; + + /* move attribute to new declarations attributes list */ + attr->next = decl->attributes; + decl->attributes = attr; + } +} + /** * record entities for the NAMESPACE_NORMAL, and produce error messages/warnings * for various problems that occur for multiple definitions @@ -4429,8 +4470,14 @@ static entity_t *record_entity(entity_t *entity, const bool is_definition) if (old_storage_class == STORAGE_CLASS_EXTERN && new_storage_class == STORAGE_CLASS_EXTERN) { -warn_redundant_declaration: - if (!is_definition && + +warn_redundant_declaration: ; + bool has_new_attrs + = has_new_attributes(prev_decl->attributes, + decl->attributes); + if (has_new_attrs) { + merge_in_attributes(decl, prev_decl->attributes); + } else if (!is_definition && warning.redundant_decls && is_type_valid(prev_type) && strcmp(previous_entity->base.source_position.input_name, -- 2.20.1