[PATCH 11/18] widl: now using type qualifier and func specifier enums on decl_spec_t rather than attributes on the type_t
Richard Pospesel
richard at torproject.org
Wed Jun 5 20:34:08 CDT 2019
Signed-off-by: Richard Pospesel <richard at torproject.org>
---
tools/widl/header.c | 20 +++---
tools/widl/parser.y | 148 ++++++++++++++++++++++++++++++++---------
tools/widl/widltypes.h | 19 +++++-
3 files changed, 144 insertions(+), 43 deletions(-)
diff --git a/tools/widl/header.c b/tools/widl/header.c
index eb4ac8ed0b..02f22095b1 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -309,7 +309,7 @@ void write_declspec_left(FILE* h, const decl_spec_t *ds, enum name_type name_typ
name = type_get_name(t, name_type);
- if (is_attr(t->attrs, ATTR_CONST) &&
+ if ((ds->typequalifier == TYPE_QUALIFIER_CONST) &&
(type_is_alias(t) || !is_ptr(t)))
fprintf(h, "const ");
@@ -360,7 +360,7 @@ void write_declspec_left(FILE* h, const decl_spec_t *ds, enum name_type name_typ
{
write_declspec_left(h, type_pointer_get_ref(t), name_type, declonly);
write_pointer_left(h, type_pointer_get_ref_type(t));
- if (is_attr(t->attrs, ATTR_CONST)) fprintf(h, "const ");
+ if (ds->typequalifier == TYPE_QUALIFIER_CONST) fprintf(h, "const ");
break;
}
case TYPE_ARRAY:
@@ -501,14 +501,16 @@ static void write_type_v(FILE *h, const decl_spec_t *ds, int is_field, int declo
if (!h) return;
if (t) {
- for (pt = t; is_ptr(pt); pt = type_pointer_get_ref_type(pt), ptr_level++)
+ const decl_spec_t *dpt = NULL;
+ for (dpt = ds; is_ptr(dpt->type); dpt = type_pointer_get_ref(dpt->type), ptr_level++)
;
+ pt = dpt->type;
if (type_get_type_detect_alias(pt) == TYPE_FUNCTION) {
int i;
const char *callconv = get_attrp(pt->attrs, ATTR_CALLCONV);
if (!callconv && is_object_interface) callconv = "STDMETHODCALLTYPE";
- if (is_attr(pt->attrs, ATTR_INLINE)) fprintf(h, "inline ");
+ if (dpt->funcspecifier == FUNCTION_SPECIFIER_INLINE) fprintf(h, "inline ");
write_declspec_left(h, type_function_get_retdeclspec(pt), NAME_DEFAULT, declonly);
fputc(' ', h);
if (ptr_level) fputc('(', h);
@@ -809,17 +811,17 @@ static void write_typedef(FILE *header, type_t *type)
int is_const_decl(const var_t *var)
{
- const type_t *t;
+ const decl_spec_t *ds;
/* strangely, MIDL accepts a const attribute on any pointer in the
* declaration to mean that data isn't being instantiated. this appears
* to be a bug, but there is no benefit to being incompatible with MIDL,
* so we'll do the same thing */
- for (t = var->declspec.type; ; )
+ for (ds = &var->declspec; ;)
{
- if (is_attr(t->attrs, ATTR_CONST))
+ if (ds->typequalifier == TYPE_QUALIFIER_CONST)
return TRUE;
- else if (is_ptr(t))
- t = type_pointer_get_ref_type(t);
+ else if (is_ptr(ds->type))
+ ds = type_pointer_get_ref(ds->type);
else break;
}
return FALSE;
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index ed1dced0b2..54dd3421c2 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -61,6 +61,7 @@ static str_list_t *append_str(str_list_t *list, char *str);
static attr_list_t *append_attr(attr_list_t *list, attr_t *attr);
static attr_list_t *append_attr_list(attr_list_t *new_list, attr_list_t *old_list);
static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t *right, attr_t *attr, enum storage_class stgclass);
+static decl_spec_t *make_decl_spec2(type_t *type, decl_spec_t *left, decl_spec_t *right, enum storage_class stgclass, enum type_qualifier typequalifier, enum function_specifier funcspecifier);
static attr_t *make_attr(enum attr_type type);
static attr_t *make_attrv(enum attr_type type, unsigned int val);
static attr_t *make_attrp(enum attr_type type, void *val);
@@ -1255,6 +1256,17 @@ static attr_list_t *move_attr(attr_list_t *dst, attr_list_t *src, enum attr_type
return dst;
}
+static attr_list_t *remove_attr(attr_list_t *lst, enum attr_type type)
+{
+ attr_t *attr;
+ LIST_FOR_EACH_ENTRY(attr, lst, attr_t, entry)
+ if (attr->type == type)
+ {
+ list_remove(&attr->entry);
+ }
+ return lst;
+}
+
static attr_list_t *append_attr_list(attr_list_t *new_list, attr_list_t *old_list)
{
struct list *entry;
@@ -1293,52 +1305,90 @@ static attr_list_t *map_attrs(const attr_list_t *list, map_attrs_filter_t filter
}
static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t *right, attr_t *attr, enum storage_class stgclass)
+{
+ enum type_qualifier typequalifier = TYPE_QUALIFIER_NONE;
+ enum function_specifier funcspecifier = FUNCTION_SPECIFIER_NONE;
+
+ assert(attr == NULL || attr->type == ATTR_CONST || attr->type == ATTR_INLINE);
+
+ if (attr != NULL)
+ {
+ if (attr->type == ATTR_CONST)
+ typequalifier = TYPE_QUALIFIER_CONST;
+ else if (attr->type == ATTR_INLINE)
+ funcspecifier = FUNCTION_SPECIFIER_INLINE;
+ }
+
+ return make_decl_spec2(type, left, right, stgclass, typequalifier, funcspecifier);
+}
+
+static decl_spec_t *make_decl_spec2(type_t *type, decl_spec_t *left, decl_spec_t *right, enum storage_class stgclass, enum type_qualifier typequalifier, enum function_specifier funcspecifier)
{
decl_spec_t *declspec = left ? left : right;
if (!declspec)
{
declspec = xmalloc(sizeof(*declspec));
declspec->type = NULL;
- declspec->attrs = NULL;
declspec->stgclass = STG_NONE;
+ declspec->typequalifier = TYPE_QUALIFIER_NONE;
+ declspec->funcspecifier = FUNCTION_SPECIFIER_NONE;
}
declspec->type = type;
if (left && declspec != left)
{
- declspec->attrs = append_attr_list(declspec->attrs, left->attrs);
if (declspec->stgclass == STG_NONE)
declspec->stgclass = left->stgclass;
else if (left->stgclass != STG_NONE)
error_loc("only one storage class can be specified\n");
+
+ if (declspec->typequalifier == TYPE_QUALIFIER_NONE)
+ declspec->typequalifier = left->typequalifier;
+ else if (left->typequalifier != TYPE_QUALIFIER_NONE)
+ error_loc("only one type qualifier can be specified\n");
+
+ if (declspec->funcspecifier == FUNCTION_SPECIFIER_NONE)
+ declspec->funcspecifier = left->funcspecifier;
+ else if (left->funcspecifier != FUNCTION_SPECIFIER_NONE)
+ error_loc("only one function specifier can be specified\n");
+
assert(!left->type);
free(left);
}
if (right && declspec != right)
{
- declspec->attrs = append_attr_list(declspec->attrs, right->attrs);
if (declspec->stgclass == STG_NONE)
declspec->stgclass = right->stgclass;
else if (right->stgclass != STG_NONE)
error_loc("only one storage class can be specified\n");
+
+ if (declspec->typequalifier == TYPE_QUALIFIER_NONE)
+ declspec->typequalifier = right->typequalifier;
+ else if (right->typequalifier != TYPE_QUALIFIER_NONE)
+ error_loc("only one type qualifier can be specified\n");
+
+ if (declspec->funcspecifier == FUNCTION_SPECIFIER_NONE)
+ declspec->funcspecifier = right->funcspecifier;
+ else if (right->funcspecifier != FUNCTION_SPECIFIER_NONE)
+ error_loc("only one function specifier can be specified\n");
+
assert(!right->type);
free(right);
}
- declspec->attrs = append_attr(declspec->attrs, attr);
if (declspec->stgclass == STG_NONE)
declspec->stgclass = stgclass;
else if (stgclass != STG_NONE)
error_loc("only one storage class can be specified\n");
- /* apply attributes to type */
- if (type && declspec->attrs)
- {
- attr_list_t *attrs;
- declspec->type = duptype(type, 1);
- attrs = map_attrs(type->attrs, NULL);
- declspec->type->attrs = append_attr_list(attrs, declspec->attrs);
- declspec->attrs = NULL;
- }
+ if (declspec->typequalifier == TYPE_QUALIFIER_NONE)
+ declspec->typequalifier = typequalifier;
+ else if (typequalifier != TYPE_QUALIFIER_NONE)
+ error_loc("only one type qualifier can be specified\n");
+
+ if (declspec->funcspecifier == FUNCTION_SPECIFIER_NONE)
+ declspec->funcspecifier = funcspecifier;
+ else if (funcspecifier != FUNCTION_SPECIFIER_NONE)
+ error_loc("only one function specifier can be specified\n");
return declspec;
}
@@ -1476,7 +1526,8 @@ static type_t *get_array_or_ptr_ref(type_t *type)
static type_t *append_chain_type(type_t *chain, type_t *type)
{
- type_t *chain_type;
+ type_t *chain_type = NULL;
+ decl_spec_t *chain_declspec = NULL;
if (!chain)
return type;
@@ -1484,12 +1535,20 @@ static type_t *append_chain_type(type_t *chain, type_t *type)
;
if (is_ptr(chain_type))
- chain_type->details.pointer.ref.type = type;
+ chain_declspec = &chain_type->details.pointer.ref;
else if (is_array(chain_type))
- chain_type->details.array.elem.type = type;
+ chain_declspec = &chain_type->details.array.elem;
else
assert(0);
+ chain_declspec->type = type;
+ /* we need to move the ATTR_CONST attribute off the type of the pointee and onto its declspec
+ * typequalifier on the pointer */
+ if (is_attr(type->attrs, ATTR_CONST)) {
+ type->attrs = remove_attr(type->attrs, ATTR_CONST);
+ chain_declspec->typequalifier = TYPE_QUALIFIER_CONST;
+ }
+
return chain;
}
@@ -1508,7 +1567,7 @@ static warning_list_t *append_warning(warning_list_t *list, int num)
return list;
}
-static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const declarator_t *decl,
+static var_t *declare_var(attr_list_t *attrs, decl_spec_t *declspec, const declarator_t *decl,
int top)
{
var_t *v = decl->var;
@@ -1517,25 +1576,50 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl
expr_t *dim;
type_t **ptype;
type_t *func_type = decl ? decl->func_type : NULL;
- type_t *type = decl_spec->type;
+ type_t *type = declspec->type;
- if (is_attr(type->attrs, ATTR_INLINE))
- {
+
+ if (declspec->funcspecifier == FUNCTION_SPECIFIER_INLINE) {
if (!func_type)
error_loc("inline attribute applied to non-function type\n");
else
{
- type_t *t;
- /* move inline attribute from return type node to function node */
- for (t = func_type; is_ptr(t); t = type_pointer_get_ref_type(t))
- ;
- t->attrs = move_attr(t->attrs, type->attrs, ATTR_INLINE);
+ v->declspec.funcspecifier = declspec->funcspecifier;
}
}
- /* add type onto the end of the pointers in pident->type */
- v->declspec.type = append_chain_type(decl ? decl->type : NULL, type);
- v->declspec.stgclass = decl_spec->stgclass;
+ /* if the var type is a pointerish, we need to move the type qualifier to the pointee's declspec
+ * unless the pointee already has const type qualifier*/
+
+ /* we need to shuffle aroundand tranlate between TYPE_QUALIFEIR_CONST and ATTR_CONST
+ * in this block */
+ if (!decl)
+ {
+ /* simplest case, no pointers to deal with here */
+ v->declspec.typequalifier = declspec->typequalifier;
+ } else if (decl->bits) {
+ /* dealing with a bitfield, just pass it on */
+ v->declspec.type = type_new_bitfield(declspec, decl->bits);
+ }
+ else {
+ /* here we're dealing with a pointerish type chain, so we need to pull
+ * the typequalifier off of the declspec and stick them in the type's attr list
+ */
+ if (declspec->typequalifier == TYPE_QUALIFIER_CONST) {
+ type->attrs = append_attr(type->attrs, make_attr(ATTR_CONST));
+ assert(is_attr(type->attrs, ATTR_CONST));
+ }
+
+ v->declspec.type = append_chain_type(decl->type, type);
+ /* finally pull the ATTR_CONST attribute off the head of the pointerish type chain,
+ * and stick on the var's declspec */
+ if (is_attr(v->declspec.type->attrs, ATTR_CONST)) {
+ v->declspec.type->attrs = remove_attr(v->declspec.type->attrs, ATTR_CONST);
+ v->declspec.typequalifier = TYPE_QUALIFIER_CONST;
+ }
+ }
+
+ v->declspec.stgclass = declspec->stgclass;
v->attrs = attrs;
/* check for pointer attribute being applied to non-pointer, non-array
@@ -1676,12 +1760,17 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl
{
type_t *ft, *t;
type_t *return_type = v->declspec.type;
+ enum type_qualifier typequalifier = v->declspec.typequalifier;
+
v->declspec.type = func_type;
+ v->declspec.typequalifier = TYPE_QUALIFIER_NONE;
for (ft = v->declspec.type; is_ptr(ft); ft = type_pointer_get_ref_type(ft))
;
assert(type_get_type_detect_alias(ft) == TYPE_FUNCTION);
ft->details.function->retval = make_var(xstrdup("_RetVal"));
ft->details.function->retval->declspec.type = return_type;
+ ft->details.function->retval->declspec.typequalifier = typequalifier;
+
/* move calling convention attribute, if present, from pointer nodes to
* function node */
for (t = v->declspec.type; is_ptr(t); t = type_pointer_get_ref_type(t))
@@ -1695,9 +1784,6 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl
error_loc("calling convention applied to non-function-pointer type\n");
}
- if (decl->bits)
- v->declspec.type = type_new_bitfield(&v->declspec, decl->bits);
-
return v;
}
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
index 6a4e331182..b3665bc4bb 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -235,6 +235,18 @@ enum storage_class
STG_REGISTER,
};
+enum type_qualifier
+{
+ TYPE_QUALIFIER_NONE,
+ TYPE_QUALIFIER_CONST
+};
+
+enum function_specifier
+{
+ FUNCTION_SPECIFIER_NONE,
+ FUNCTION_SPECIFIER_INLINE,
+};
+
enum statement_type
{
STMT_LIBRARY,
@@ -297,8 +309,9 @@ struct str_list_entry_t
struct _decl_spec_t
{
type_t *type;
- attr_list_t *attrs;
enum storage_class stgclass;
+ enum type_qualifier typequalifier;
+ enum function_specifier funcspecifier;
};
struct _attr_t {
@@ -626,9 +639,9 @@ static inline int is_global_namespace(const struct namespace *namespace)
static inline decl_spec_t *init_declspec(decl_spec_t *declspec, type_t *type)
{
declspec->type = type;
- declspec->attrs = NULL;
declspec->stgclass = STG_NONE;
-
+ declspec->typequalifier=TYPE_QUALIFIER_NONE;
+ declspec->funcspecifier=FUNCTION_SPECIFIER_NONE;
return declspec;
}
--
2.17.1
More information about the wine-devel
mailing list