Make parsing of __based() less intrusive.
[cparser] / type.c
diff --git a/type.c b/type.c
index 0646884..5967262 100644 (file)
--- a/type.c
+++ b/type.c
@@ -27,6 +27,7 @@
 #include "symbol_t.h"
 #include "type_hash.h"
 #include "adt/error.h"
+#include "adt/util.h"
 #include "lang_features.h"
 
 static struct obstack   _type_obst;
@@ -35,8 +36,8 @@ struct obstack         *type_obst                 = &_type_obst;
 static int              type_visited              = 0;
 static bool             print_implicit_array_size = false;
 
-static void intern_print_type_pre(const type_t *type, bool top);
-static void intern_print_type_post(const type_t *type, bool top);
+static void intern_print_type_pre(const type_t *type);
+static void intern_print_type_post(const type_t *type);
 
 typedef struct atomic_type_properties_t atomic_type_properties_t;
 struct atomic_type_properties_t {
@@ -300,9 +301,8 @@ void print_imaginary_type(const imaginary_type_t *type)
  * Print the first part (the prefix) of a type.
  *
  * @param type   The type to print.
- * @param top    true, if this is the top type, false if it's an embedded type.
  */
-static void print_function_type_pre(const function_type_t *type, bool top)
+static void print_function_type_pre(const function_type_t *type)
 {
        switch (type->linkage) {
                case LINKAGE_INVALID:
@@ -323,7 +323,7 @@ static void print_function_type_pre(const function_type_t *type, bool top)
        if (type->base.qualifiers != 0)
                fputc(' ', out);
 
-       intern_print_type_pre(type->return_type, false);
+       intern_print_type_pre(type->return_type);
 
        switch (type->calling_convention) {
        case CC_CDECL:    fputs("__cdecl ",    out); break;
@@ -332,25 +332,16 @@ static void print_function_type_pre(const function_type_t *type, bool top)
        case CC_THISCALL: fputs("__thiscall ", out); break;
        case CC_DEFAULT:  break;
        }
-
-       /* don't emit parenthesis if we're the toplevel type... */
-       if (!top)
-               fputc('(', out);
 }
 
 /**
  * Print the second part (the postfix) of a type.
  *
  * @param type   The type to print.
- * @param top    true, if this is the top type, false if it's an embedded type.
  */
 static void print_function_type_post(const function_type_t *type,
-                                     const scope_t *parameters, bool top)
+                                     const scope_t *parameters)
 {
-       /* don't emit parenthesis if we're the toplevel type... */
-       if (!top)
-               fputc(')', out);
-
        fputc('(', out);
        bool first = true;
        if (parameters == NULL) {
@@ -366,12 +357,14 @@ static void print_function_type_post(const function_type_t *type,
        } else {
                entity_t *parameter = parameters->entities;
                for (; parameter != NULL; parameter = parameter->base.next) {
+                       if (parameter->kind != ENTITY_PARAMETER)
+                               continue;
+
                        if (first) {
                                first = false;
                        } else {
                                fputs(", ", out);
                        }
-                       assert(is_declaration(parameter));
                        const type_t *const type = parameter->declaration.type;
                        if (type == NULL) {
                                fputs(parameter->base.symbol->string, out);
@@ -393,7 +386,7 @@ static void print_function_type_post(const function_type_t *type,
        }
        fputc(')', out);
 
-       intern_print_type_post(type->return_type, false);
+       intern_print_type_post(type->return_type);
 }
 
 /**
@@ -403,7 +396,10 @@ static void print_function_type_post(const function_type_t *type,
  */
 static void print_pointer_type_pre(const pointer_type_t *type)
 {
-       intern_print_type_pre(type->points_to, false);
+       type_t const *const points_to = type->points_to;
+       intern_print_type_pre(points_to);
+       if (points_to->kind == TYPE_ARRAY || points_to->kind == TYPE_FUNCTION)
+               fputs(" (", out);
        variable_t *const variable = type->base_variable;
        if (variable != NULL) {
                fputs(" __based(", out);
@@ -411,30 +407,37 @@ static void print_pointer_type_pre(const pointer_type_t *type)
                fputs(") ", out);
        }
        fputc('*', out);
-       print_type_qualifiers(type->base.qualifiers);
-       if (type->base.qualifiers != 0)
+       type_qualifiers_t const qual = type->base.qualifiers;
+       if (qual != 0)
                fputc(' ', out);
+       print_type_qualifiers(qual);
 }
 
 /**
- * Prints the prefix part of a reference type.
+ * Prints the postfix part of a pointer type.
  *
- * @param type   The reference type.
+ * @param type   The pointer type.
  */
-static void print_reference_type_pre(const reference_type_t *type)
+static void print_pointer_type_post(const pointer_type_t *type)
 {
-       intern_print_type_pre(type->refers_to, false);
-       fputc('&', out);
+       type_t const *const points_to = type->points_to;
+       if (points_to->kind == TYPE_ARRAY || points_to->kind == TYPE_FUNCTION)
+               fputc(')', out);
+       intern_print_type_post(points_to);
 }
 
 /**
- * Prints the postfix part of a pointer type.
+ * Prints the prefix part of a reference type.
  *
- * @param type   The pointer type.
+ * @param type   The reference type.
  */
-static void print_pointer_type_post(const pointer_type_t *type)
+static void print_reference_type_pre(const reference_type_t *type)
 {
-       intern_print_type_post(type->points_to, false);
+       type_t const *const refers_to = type->refers_to;
+       intern_print_type_pre(refers_to);
+       if (refers_to->kind == TYPE_ARRAY || refers_to->kind == TYPE_FUNCTION)
+               fputs(" (", out);
+       fputc('&', out);
 }
 
 /**
@@ -444,7 +447,10 @@ static void print_pointer_type_post(const pointer_type_t *type)
  */
 static void print_reference_type_post(const reference_type_t *type)
 {
-       intern_print_type_post(type->refers_to, false);
+       type_t const *const refers_to = type->refers_to;
+       if (refers_to->kind == TYPE_ARRAY || refers_to->kind == TYPE_FUNCTION)
+               fputc(')', out);
+       intern_print_type_post(refers_to);
 }
 
 /**
@@ -454,7 +460,7 @@ static void print_reference_type_post(const reference_type_t *type)
  */
 static void print_array_type_pre(const array_type_t *type)
 {
-       intern_print_type_pre(type->element_type, false);
+       intern_print_type_pre(type->element_type);
 }
 
 /**
@@ -476,7 +482,7 @@ static void print_array_type_post(const array_type_t *type)
                print_expression(type->size_expression);
        }
        fputc(']', out);
-       intern_print_type_post(type->element_type, false);
+       intern_print_type_post(type->element_type);
 }
 
 /**
@@ -488,7 +494,7 @@ static void print_bitfield_type_post(const bitfield_type_t *type)
 {
        fputs(" : ", out);
        print_expression(type->size_expression);
-       intern_print_type_post(type->base_type, false);
+       intern_print_type_post(type->base_type);
 }
 
 /**
@@ -620,7 +626,6 @@ static void print_typeof_type_pre(const typeof_type_t *const type)
 {
        fputs("typeof(", out);
        if (type->expression != NULL) {
-               assert(type->typeof_type == NULL);
                print_expression(type->expression);
        } else {
                print_type(type->typeof_type);
@@ -632,9 +637,8 @@ static void print_typeof_type_pre(const typeof_type_t *const type)
  * Prints the prefix part of a type.
  *
  * @param type   The type.
- * @param top    true if we print the toplevel type, false else.
  */
-static void intern_print_type_pre(const type_t *const type, const bool top)
+static void intern_print_type_pre(const type_t *const type)
 {
        switch(type->kind) {
        case TYPE_ERROR:
@@ -663,7 +667,7 @@ static void intern_print_type_pre(const type_t *const type, const bool top)
                fputs(type->builtin.symbol->string, out);
                return;
        case TYPE_FUNCTION:
-               print_function_type_pre(&type->function, top);
+               print_function_type_pre(&type->function);
                return;
        case TYPE_POINTER:
                print_pointer_type_pre(&type->pointer);
@@ -672,7 +676,7 @@ static void intern_print_type_pre(const type_t *const type, const bool top)
                print_reference_type_pre(&type->reference);
                return;
        case TYPE_BITFIELD:
-               intern_print_type_pre(type->bitfield.base_type, top);
+               intern_print_type_pre(type->bitfield.base_type);
                return;
        case TYPE_ARRAY:
                print_array_type_pre(&type->array);
@@ -691,13 +695,12 @@ static void intern_print_type_pre(const type_t *const type, const bool top)
  * Prints the postfix part of a type.
  *
  * @param type   The type.
- * @param top    true if we print the toplevel type, false else.
  */
-static void intern_print_type_post(const type_t *const type, const bool top)
+static void intern_print_type_post(const type_t *const type)
 {
        switch(type->kind) {
        case TYPE_FUNCTION:
-               print_function_type_post(&type->function, NULL, top);
+               print_function_type_post(&type->function, NULL);
                return;
        case TYPE_POINTER:
                print_pointer_type_post(&type->pointer);
@@ -748,15 +751,15 @@ void print_type_ext(const type_t *const type, const symbol_t *symbol,
                return;
        }
 
-       intern_print_type_pre(type, true);
+       intern_print_type_pre(type);
        if (symbol != NULL) {
                fputc(' ', out);
                fputs(symbol->string, out);
        }
        if (type->kind == TYPE_FUNCTION) {
-               print_function_type_post(&type->function, parameters, true);
+               print_function_type_post(&type->function, parameters);
        } else {
-               intern_print_type_post(type, true);
+               intern_print_type_post(type);
        }
 }
 
@@ -802,6 +805,7 @@ type_t *duplicate_type(const type_t *type)
 
        type_t *copy = obstack_alloc(type_obst, size);
        memcpy(copy, type, size);
+       copy->base.firm_type = NULL;
 
        return copy;
 }
@@ -822,12 +826,7 @@ type_t *get_unqualified_type(type_t *type)
        type_t *unqualified_type          = duplicate_type(type);
        unqualified_type->base.qualifiers = TYPE_QUALIFIER_NONE;
 
-       type_t *result = typehash_insert(unqualified_type);
-       if (result != unqualified_type) {
-               obstack_free(type_obst, unqualified_type);
-       }
-
-       return result;
+       return identify_new_type(unqualified_type);
 }
 
 type_t *get_qualified_type(type_t *orig_type, type_qualifiers_t const qual)
@@ -855,11 +854,7 @@ type_t *get_qualified_type(type_t *orig_type, type_qualifiers_t const qual)
                return type;
        }
 
-       type = typehash_insert(copy);
-       if (type != copy)
-               obstack_free(type_obst, copy);
-
-       return type;
+       return identify_new_type(copy);
 }
 
 /**
@@ -1219,14 +1214,19 @@ type_t *skip_typeref(type_t *type)
 {
        type_qualifiers_t qualifiers = TYPE_QUALIFIER_NONE;
        type_modifiers_t  modifiers  = TYPE_MODIFIER_NONE;
+       il_alignment_t    alignment  = 0;
 
        while (true) {
+               if (alignment < type->base.alignment)
+                       alignment = type->base.alignment;
+
                switch (type->kind) {
                case TYPE_ERROR:
                        return type;
                case TYPE_TYPEDEF: {
                        qualifiers |= type->base.qualifiers;
                        modifiers  |= type->base.modifiers;
+
                        const typedef_type_t *typedef_type = &type->typedeft;
                        if (typedef_type->resolved_type != NULL) {
                                type = typedef_type->resolved_type;
@@ -1235,22 +1235,20 @@ type_t *skip_typeref(type_t *type)
                        type = typedef_type->typedefe->type;
                        continue;
                }
-               case TYPE_TYPEOF: {
-                       const typeof_type_t *typeof_type = &type->typeoft;
-                       if (typeof_type->typeof_type != NULL) {
-                               type = typeof_type->typeof_type;
-                       } else {
-                               type = typeof_type->expression->base.type;
-                       }
+               case TYPE_TYPEOF:
+                       qualifiers |= type->base.qualifiers;
+                       modifiers  |= type->base.modifiers;
+                       type        = type->typeoft.typeof_type;
                        continue;
-               }
                default:
                        break;
                }
                break;
        }
 
-       if (qualifiers != TYPE_QUALIFIER_NONE || modifiers != TYPE_MODIFIER_NONE) {
+       if (qualifiers != TYPE_QUALIFIER_NONE ||
+                       modifiers  != TYPE_MODIFIER_NONE  ||
+                       alignment  >  type->base.alignment) {
                type_t *const copy = duplicate_type(type);
 
                /* for const with typedefed array type the element type has to be
@@ -1260,22 +1258,22 @@ type_t *skip_typeref(type_t *type)
                        element_type                   = duplicate_type(element_type);
                        element_type->base.qualifiers |= qualifiers;
                        element_type->base.modifiers  |= modifiers;
+                       element_type->base.alignment   = alignment;
                        copy->array.element_type       = element_type;
                } else {
                        copy->base.qualifiers |= qualifiers;
                        copy->base.modifiers  |= modifiers;
+                       copy->base.alignment   = alignment;
                }
 
-               type = typehash_insert(copy);
-               if (type != copy) {
-                       obstack_free(type_obst, copy);
-               }
+               type = identify_new_type(copy);
        }
 
        return type;
 }
 
-type_qualifiers_t get_type_qualifier(const type_t *type, bool skip_array_type) {
+type_qualifiers_t get_type_qualifier(const type_t *type, bool skip_array_type)
+{
        type_qualifiers_t qualifiers = TYPE_QUALIFIER_NONE;
 
        while (true) {
@@ -1290,15 +1288,9 @@ type_qualifiers_t get_type_qualifier(const type_t *type, bool skip_array_type) {
                        else
                                type = typedef_type->typedefe->type;
                        continue;
-               case TYPE_TYPEOF: {
-                       const typeof_type_t *typeof_type = &type->typeoft;
-                       if (typeof_type->typeof_type != NULL) {
-                               type = typeof_type->typeof_type;
-                       } else {
-                               type = typeof_type->expression->base.type;
-                       }
+               case TYPE_TYPEOF:
+                       type = type->typeoft.typeof_type;
                        continue;
-               }
                case TYPE_ARRAY:
                        if (skip_array_type) {
                                type = type->array.element_type;
@@ -1354,7 +1346,8 @@ atomic_type_kind_t get_uintptr_kind(void)
 /**
  * Find the atomic type kind representing a given size (signed).
  */
-atomic_type_kind_t find_signed_int_atomic_type_kind_for_size(unsigned size) {
+atomic_type_kind_t find_signed_int_atomic_type_kind_for_size(unsigned size)
+{
        static atomic_type_kind_t kinds[32];
 
        assert(size < 32);
@@ -1367,7 +1360,7 @@ atomic_type_kind_t find_signed_int_atomic_type_kind_for_size(unsigned size) {
                        ATOMIC_TYPE_LONG,
                        ATOMIC_TYPE_LONGLONG
                };
-               for(unsigned i = 0; i < sizeof(possible_kinds)/sizeof(possible_kinds[0]); ++i) {
+               for (size_t i = 0; i < lengthof(possible_kinds); ++i) {
                        if (get_atomic_type_size(possible_kinds[i]) == size) {
                                kind = possible_kinds[i];
                                break;
@@ -1381,7 +1374,8 @@ atomic_type_kind_t find_signed_int_atomic_type_kind_for_size(unsigned size) {
 /**
  * Find the atomic type kind representing a given size (signed).
  */
-atomic_type_kind_t find_unsigned_int_atomic_type_kind_for_size(unsigned size) {
+atomic_type_kind_t find_unsigned_int_atomic_type_kind_for_size(unsigned size)
+{
        static atomic_type_kind_t kinds[32];
 
        assert(size < 32);
@@ -1394,7 +1388,7 @@ atomic_type_kind_t find_unsigned_int_atomic_type_kind_for_size(unsigned size) {
                        ATOMIC_TYPE_ULONG,
                        ATOMIC_TYPE_ULONGLONG
                };
-               for(unsigned i = 0; i < sizeof(possible_kinds)/sizeof(possible_kinds[0]); ++i) {
+               for (size_t i = 0; i < lengthof(possible_kinds); ++i) {
                        if (get_atomic_type_size(possible_kinds[i]) == size) {
                                kind = possible_kinds[i];
                                break;
@@ -1409,7 +1403,7 @@ atomic_type_kind_t find_unsigned_int_atomic_type_kind_for_size(unsigned size) {
  * Hash the given type and return the "singleton" version
  * of it.
  */
-static type_t *identify_new_type(type_t *type)
+type_t *identify_new_type(type_t *type)
 {
        type_t *result = typehash_insert(type);
        if (result != type) {