[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