- parsing of __based implemented (more semantic in assignment might be needed)
authorMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Mon, 17 Nov 2008 01:14:41 +0000 (01:14 +0000)
committerMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Mon, 17 Nov 2008 01:14:41 +0000 (01:14 +0000)
[r23718]

parser.c
type.c
type_hash.c
type_t.h

index 7e2f224..d4f54fb 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -84,6 +84,7 @@ struct declaration_specifiers_t {
        symbol_t          *get_property_sym;  /**< the name of the get property if set. */
        symbol_t          *put_property_sym;  /**< the name of the put property if set. */
        type_t            *type;
+       variable_t        *based_variable;    /**< Microsoft __based variable. */
 };
 
 /**
@@ -3404,6 +3405,40 @@ static entity_t *create_error_entity(symbol_t *symbol, entity_kind_tag_t kind)
        return entity;
 }
 
+static void parse_microsoft_based(declaration_specifiers_t *specifiers)
+{
+       if (token.type != T_IDENTIFIER) {
+               parse_error_expected("while parsing __based", T_IDENTIFIER, NULL);
+               return;
+       }
+       symbol_t *symbol = token.v.symbol;
+       entity_t *entity = get_entity(symbol, NAMESPACE_NORMAL);
+
+       if (entity == NULL || entity->base.kind != ENTITY_VARIABLE) {
+               errorf(HERE, "'%Y' is not a variable name.", symbol);
+               entity = create_error_entity(symbol, ENTITY_VARIABLE);
+       } else {
+               variable_t *variable = &entity->variable;
+
+               if (specifiers->based_variable != NULL) {
+                       errorf(HERE, "__based type qualifier specified more than once");
+               }
+               specifiers->based_variable = variable;
+
+               type_t *const type = variable->base.type;
+
+               if (is_type_valid(type)) {
+                       if (! is_type_pointer(skip_typeref(type))) {
+                               errorf(HERE, "variable in __based modifier must have pointer type instead of %T", type);
+                       }
+                       if (variable->base.base.parent_scope != file_scope) {
+                               errorf(HERE, "a nonstatic local variable may not be used in a __based specification");
+                       }
+               }
+       }
+       next_token();
+}
+
 /**
  * Finish the construction of a struct type by calculating
  * its size, offsets, alignment.
@@ -3547,6 +3582,15 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers)
                        expect(')');
                        break;
 
+               case T__based:
+                       next_token();
+                       expect('(');
+                       add_anchor_token(')');
+                       parse_microsoft_based(specifiers);
+                       rem_anchor_token(')');
+                       expect(')');
+                       break;
+
                case T___thread:
                        switch (specifiers->storage_class) {
                        case STORAGE_CLASS_NONE:
@@ -4424,7 +4468,7 @@ static void parse_declaration_attributes(entity_t *entity)
 }
 
 static type_t *construct_declarator_type(construct_type_t *construct_list,
-                                         type_t *type)
+                                         type_t *type, variable_t *variable)
 {
        construct_type_t *iter = construct_list;
        for( ; iter != NULL; iter = iter->next) {
@@ -4458,7 +4502,7 @@ static type_t *construct_declarator_type(construct_type_t *construct_list,
 
                case CONSTRUCT_POINTER: {
                        parsed_pointer_t *parsed_pointer = (parsed_pointer_t*) iter;
-                       type = make_pointer_type(type, parsed_pointer->type_qualifiers);
+                       type = make_based_pointer_type(type, parsed_pointer->type_qualifiers, variable);
                        continue;
                }
 
@@ -4524,7 +4568,7 @@ static entity_t *parse_declarator(const declaration_specifiers_t *specifiers,
 
        construct_type_t *construct_type
                = parse_inner_declarator(&env, may_be_abstract);
-       type_t *type = construct_declarator_type(construct_type, specifiers->type);
+       type_t *type = construct_declarator_type(construct_type, specifiers->type, specifiers->based_variable);
 
        if (construct_type != NULL) {
                obstack_free(&temp_obst, construct_type);
@@ -4586,7 +4630,7 @@ static type_t *parse_abstract_declarator(type_t *base_type)
 {
        construct_type_t *construct_type = parse_inner_declarator(NULL, 1);
 
-       type_t *result = construct_declarator_type(construct_type, base_type);
+       type_t *result = construct_declarator_type(construct_type, base_type, NULL);
        if (construct_type != NULL) {
                obstack_free(&temp_obst, construct_type);
        }
diff --git a/type.c b/type.c
index 3ab686d..59876f6 100644 (file)
--- a/type.c
+++ b/type.c
@@ -391,6 +391,12 @@ 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);
+       variable_t *const variable = type->base_variable;
+       if (variable != NULL) {
+               fputs(" __based(", out);
+               fputs(variable->base.base.symbol->string, out);
+               fputs(") ", out);
+       }
        fputs("*", out);
        print_type_qualifiers(type->base.qualifiers);
        if (type->base.qualifiers != 0)
@@ -1426,14 +1432,38 @@ type_t *make_pointer_type(type_t *points_to, type_qualifiers_t qualifiers)
        type_t *type = obstack_alloc(type_obst, sizeof(pointer_type_t));
        memset(type, 0, sizeof(pointer_type_t));
 
-       type->kind              = TYPE_POINTER;
-       type->base.qualifiers   = qualifiers;
-       type->base.alignment    = 0;
-       type->pointer.points_to = points_to;
+       type->kind                  = TYPE_POINTER;
+       type->base.qualifiers       = qualifiers;
+       type->base.alignment        = 0;
+       type->pointer.points_to     = points_to;
+       type->pointer.base_variable = NULL;
 
        return identify_new_type(type);
 }
 
+/**
+ * Creates a new based pointer type.
+ *
+ * @param points_to   The points-to type for the new type.
+ * @param qualifiers  Type qualifiers for the new type.
+ * @param variable    The based variable
+ */
+type_t *make_based_pointer_type(type_t *points_to,
+                                                               type_qualifiers_t qualifiers, variable_t *variable)
+{
+       type_t *type = obstack_alloc(type_obst, sizeof(pointer_type_t));
+       memset(type, 0, sizeof(pointer_type_t));
+
+       type->kind                  = TYPE_POINTER;
+       type->base.qualifiers       = qualifiers;
+       type->base.alignment        = 0;
+       type->pointer.points_to     = points_to;
+       type->pointer.base_variable = variable;
+
+       return identify_new_type(type);
+}
+
+
 type_t *make_array_type(type_t *element_type, size_t size,
                         type_qualifiers_t qualifiers)
 {
index ad0732f..046e6af 100644 (file)
@@ -231,7 +231,8 @@ static bool function_types_equal(const function_type_t *type1,
 static bool pointer_types_equal(const pointer_type_t *type1,
                                 const pointer_type_t *type2)
 {
-       return type1->points_to == type2->points_to;
+       return type1->points_to     == type2->points_to &&
+              type1->base_variable == type2->base_variable;
 }
 
 static bool array_types_equal(const array_type_t *type1,
index a8f07fc..dfacdfa 100644 (file)
--- a/type_t.h
+++ b/type_t.h
@@ -91,6 +91,7 @@ struct builtin_type_t {
 struct pointer_type_t {
        type_base_t  base;
        type_t      *points_to;
+       variable_t  *base_variable;  /**< Microsoft __based() extension */
 };
 
 struct array_type_t {
@@ -113,7 +114,7 @@ struct array_type_t {
  */
 struct function_parameter_t {
        type_t               *type;  /**< The parameter type. */
-       function_parameter_t *next;  /**< Points to the next type inthe parameter list.*/
+       function_parameter_t *next;  /**< Points to the next type in the parameter list.*/
 };
 
 /** Linkage specifications. */
@@ -203,6 +204,8 @@ type_t *make_atomic_type(atomic_type_kind_t type, type_qualifiers_t qualifiers);
 type_t *make_complex_type(atomic_type_kind_t type, type_qualifiers_t qualifiers);
 type_t *make_imaginary_type(atomic_type_kind_t type, type_qualifiers_t qualifiers);
 type_t *make_pointer_type(type_t *points_to, type_qualifiers_t qualifiers);
+type_t *make_based_pointer_type(type_t *points_to,
+                                                               type_qualifiers_t qualifiers, variable_t *variable);
 type_t *make_array_type(type_t *element_type, size_t size,
                         type_qualifiers_t qualifiers);