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. */
};
/**
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.
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:
}
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) {
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;
}
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);
{
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);
}
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)
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)
{
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,
struct pointer_type_t {
type_base_t base;
type_t *points_to;
+ variable_t *base_variable; /**< Microsoft __based() extension */
};
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. */
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);