Let is_constant_expression() and friends return an enum so constant expressions can...
[cparser] / attribute.c
index 1a868d6..1ea8f1d 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * This file is part of cparser.
- * Copyright (C) 2007-2008 Matthias Braun <matze@braunis.de>
+ * Copyright (C) 2007-2009 Matthias Braun <matze@braunis.de>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -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] = {
@@ -241,7 +242,7 @@ static void warn_arguments(const attribute_t *attribute)
 
        if (warning.other) {
                warningf(&attribute->source_position,
-                                "attribute '%s' needs no attributes",
+                                "attribute '%s' needs no arguments",
                                 get_attribute_name(attribute->kind));
        }
 }
@@ -309,6 +310,7 @@ void handle_entity_attributes(const attribute_t *attributes, entity_t *entity)
                case ATTRIBUTE_GNU_UNUSED:        modifiers |= DM_UNUSED; break;
                case ATTRIBUTE_GNU_DLLIMPORT:     modifiers |= DM_DLLIMPORT; break;
                case ATTRIBUTE_GNU_DLLEXPORT:     modifiers |= DM_DLLEXPORT; break;
+               case ATTRIBUTE_GNU_WEAK:          modifiers |= DM_WEAK; break;
 
                case ATTRIBUTE_MS_ALLOCATE:      modifiers |= DM_MALLOC; break;
                case ATTRIBUTE_MS_DLLIMPORT:     modifiers |= DM_DLLIMPORT; break;
@@ -358,7 +360,7 @@ void handle_entity_attributes(const attribute_t *attributes, entity_t *entity)
 
 static type_t *change_calling_convention(type_t *type, cc_kind_t cconv)
 {
-       if (!is_type_function(type)) {
+       if (is_typeref(type) || !is_type_function(type)) {
                return type;
        }
 
@@ -377,7 +379,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);
@@ -418,7 +420,56 @@ const char *get_deprecated_string(const attribute_t *attribute)
                expression_t *expression = argument->v.expression;
                if (expression->kind != EXPR_STRING_LITERAL)
                        return NULL;
-               return expression->string.value.begin;
+               return expression->literal.value.begin;
        }
        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);
+       }
+}