widl: Add support for "inline" on function definitions.
authorRob Shearman <rob@codeweavers.com>
Tue, 29 Apr 2008 19:40:30 +0000 (20:40 +0100)
committerAlexandre Julliard <julliard@winehq.org>
Wed, 30 Apr 2008 09:31:21 +0000 (11:31 +0200)
Fix applying calling convention to function type.

tools/widl/header.c
tools/widl/parser.l
tools/widl/parser.y
tools/widl/widltypes.h

index 572cac44fd2b9c28aa9aa2fff758c2c78f2d2488..e3538e66555104f3b05a0e24f083ad8042c0d5ed 100644 (file)
@@ -312,6 +312,7 @@ void write_type_v(FILE *h, type_t *t, int is_field, int declonly,
     int i;
     const char *callconv = get_attrp(pt->attrs, ATTR_CALLCONV);
     if (!callconv) callconv = "";
+    if (is_attr(pt->attrs, ATTR_INLINE)) fprintf(h, "inline ");
     write_type_left(h, pt->ref, declonly);
     fputc(' ', h);
     if (ptr_level) fputc('(', h);
index c0fbd7d20c38a19e5448d0e577bea7dd9320ac2d..c202409c570e265d2f21e280834ec4a591b3ce30 100644 (file)
@@ -233,7 +233,8 @@ static const struct keyword keywords[] = {
        {"hyper",                       tHYPER},
        {"import",                      tIMPORT},
        {"importlib",                   tIMPORTLIB},
-       {"in_line",                     tINLINE},
+       {"in_line",                     tIN_LINE},
+       {"inline",                      tINLINE},
        {"int",                         tINT},
        {"interface",                   tINTERFACE},
        {"library",                     tLIBRARY},
index 7ed7566ebe47f8857502b28af5ee6b488027e161..8c99da44f94ff15ef8a070d4f2bb16b3f39ae943 100644 (file)
@@ -116,7 +116,6 @@ static type_t *make_int(int sign);
 static typelib_t *make_library(const char *name, const attr_list_t *attrs);
 static type_t *make_func_type(var_list_t *args);
 static type_t *make_pointer_type(type_t *ref, attr_list_t *attrs);
-static void type_set_function_callconv(type_t *type, char *callconv);
 static type_t *append_ptrchain_type(type_t *ptrchain, type_t *type);
 
 static type_t *reg_type(type_t *type, const char *name, int t);
@@ -139,14 +138,14 @@ static statement_t *process_typedefs(var_list_t *names);
 static void check_arg(var_t *arg);
 static void check_functions(const type_t *iface);
 static void check_all_user_types(const statement_list_t *stmts);
-static const attr_list_t *check_iface_attrs(const char *name, const attr_list_t *attrs);
+static attr_list_t *check_iface_attrs(const char *name, attr_list_t *attrs);
 static attr_list_t *check_function_attrs(const char *name, attr_list_t *attrs);
 static attr_list_t *check_typedef_attrs(attr_list_t *attrs);
 static attr_list_t *check_field_attrs(const char *name, attr_list_t *attrs);
-static const attr_list_t *check_library_attrs(const char *name, const attr_list_t *attrs);
+static attr_list_t *check_library_attrs(const char *name, attr_list_t *attrs);
 static attr_list_t *check_dispiface_attrs(const char *name, attr_list_t *attrs);
-static const attr_list_t *check_module_attrs(const char *name, const attr_list_t *attrs);
-static const attr_list_t *check_coclass_attrs(const char *name, const attr_list_t *attrs);
+static attr_list_t *check_module_attrs(const char *name, attr_list_t *attrs);
+static attr_list_t *check_coclass_attrs(const char *name, attr_list_t *attrs);
 const char *get_attr_display_name(enum attr_type type);
 static void add_explicit_handle_if_necessary(func_t *func);
 
@@ -234,7 +233,7 @@ static statement_list_t *append_statement(statement_list_t *list, statement_t *s
 %token tIMMEDIATEBIND
 %token tIMPLICITHANDLE
 %token tIMPORT tIMPORTLIB
-%token tIN tINLINE
+%token tIN tIN_LINE tINLINE
 %token tINPUTSYNC
 %token tINT tINT64
 %token tINTERFACE
@@ -286,7 +285,7 @@ static statement_list_t *append_statement(statement_list_t *list, statement_t *s
 %token tVOID
 %token tWCHAR tWIREMARSHAL
 
-%type <attr> attribute type_qualifier
+%type <attr> attribute type_qualifier function_specifier
 %type <attr_list> m_attributes attributes attrib_list m_type_qual_list decl_spec_no_type m_decl_spec_no_type
 %type <str_list> str_list
 %type <expr> m_expr expr expr_const expr_int_const array
@@ -968,6 +967,10 @@ moduledef: modulehdr '{' int_statements '}'
                                                }
        ;
 
+function_specifier:
+         tINLINE                               { $$ = make_attr(ATTR_INLINE); }
+       ;
+
 type_qualifier:
          tCONST                                { $$ = make_attr(ATTR_CONST); }
        ;
@@ -987,12 +990,13 @@ m_decl_spec_no_type:                              { $$ = NULL; }
 
 decl_spec_no_type:
          type_qualifier m_decl_spec_no_type    { $$ = append_attr($2, $1); }
+       | function_specifier m_decl_spec_no_type  { $$ = append_attr($2, $1); }
        ;
 
 declarator:
          '*' m_type_qual_list declarator %prec PPTR
                                                { $$ = $3; $$->type = append_ptrchain_type($$->type, make_pointer_type(NULL, $2)); }
-       | callconv declarator                   { $$ = $2; type_set_function_callconv($$->func_type, $1); }
+       | callconv declarator                   { $$ = $2; $$->type->attrs = append_attr($$->type->attrs, make_attrp(ATTR_CALLCONV, $1)); }
        | direct_declarator
        ;
 
@@ -1157,6 +1161,19 @@ static attr_list_t *append_attr(attr_list_t *list, attr_t *attr)
     return list;
 }
 
+static attr_list_t *move_attr(attr_list_t *dst, attr_list_t *src, enum attr_type type)
+{
+  attr_t *attr;
+  if (!src) return dst;
+  LIST_FOR_EACH_ENTRY(attr, src, attr_t, entry)
+    if (attr->type == type)
+    {
+      list_remove(&attr->entry);
+      return append_attr(dst, attr);
+    }
+  return dst;
+}
+
 static attr_list_t *append_attr_list(attr_list_t *new_list, attr_list_t *old_list)
 {
   struct list *entry;
@@ -1309,16 +1326,6 @@ static type_t *make_func_type(var_list_t *args)
   return t;
 }
 
-static void type_set_function_callconv(type_t *type, char *callconv)
-{
-  if (!type)
-    error_loc("calling convention applied to non-function-pointer type\n");
-  for (; is_ptr(type); type = type->ref)
-    ;
-  assert(type->type == RPC_FC_FUNCTION);
-  type->attrs = append_attr(NULL, make_attrp(ATTR_CALLCONV, callconv));
-}
-
 static type_t *make_pointer_type(type_t *ref, attr_list_t *attrs)
 {
     type_t *t = make_type(pointer_default, ref);
@@ -1348,6 +1355,20 @@ static void set_type(var_t *v, type_t *type, const declarator_t *decl,
   type_t *atype, **ptype;
   array_dims_t *arr = decl ? decl->array : NULL;
 
+  if (is_attr(type->attrs, ATTR_INLINE))
+  {
+    if (!decl || !decl->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 = decl->func_type; is_ptr(t); t = t->ref)
+        ;
+      t->attrs = move_attr(t->attrs, type->attrs, ATTR_INLINE);
+    }
+  }
+
   /* add type onto the end of the pointers in pident->type */
   v->type = append_ptrchain_type(decl ? decl->type : NULL, type);
 
@@ -1496,20 +1517,31 @@ static void set_type(var_t *v, type_t *type, const declarator_t *decl,
    * function and make v->type point to the function side of the declaration */
   if (decl && decl->func_type)
   {
-    type_t *t;
+    type_t *ft, *t;
     type_t *return_type = v->type;
     v->type = decl->func_type;
-    for (t = v->type; is_ptr(t); t = t->ref)
+    for (ft = v->type; is_ptr(ft); ft = ft->ref)
       ;
-    assert(t->type == RPC_FC_FUNCTION);
-    t->ref = return_type;
-    if (is_object_interface && !is_attr(t->attrs, ATTR_CALLCONV))
+    assert(ft->type == RPC_FC_FUNCTION);
+    ft->ref = return_type;
+    /* move calling convention attribute, if present, from pointer nodes to
+     * function node */
+    for (t = v->type; is_ptr(t); t = t->ref)
+      ft->attrs = move_attr(ft->attrs, t->attrs, ATTR_CALLCONV);
+    if (is_object_interface && !is_attr(ft->attrs, ATTR_CALLCONV))
     {
       static char *stdmethodcalltype;
       if (!stdmethodcalltype) stdmethodcalltype = strdup("STDMETHODCALLTYPE");
-      t->attrs = append_attr(NULL, make_attrp(ATTR_CALLCONV, stdmethodcalltype));
+      ft->attrs = append_attr(NULL, make_attrp(ATTR_CALLCONV, stdmethodcalltype));
     }
   }
+  else
+  {
+    type_t *t;
+    for (t = v->type; is_ptr(t); t = t->ref)
+      if (is_attr(t->attrs, ATTR_CALLCONV))
+        error_loc("calling convention applied to non-function-pointer type\n");
+  }
 }
 
 static var_list_t *set_var_types(attr_list_t *attrs, type_t *type, declarator_list_t *decls)
@@ -2163,6 +2195,7 @@ struct allowed_attr allowed_attr[] =
     /* ATTR_IMMEDIATEBIND */    { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "immediatebind" },
     /* ATTR_IMPLICIT_HANDLE */  { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "implicit_handle" },
     /* ATTR_IN */               { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "in" },
+    /* ATTR_INLINE */           { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "inline" },
     /* ATTR_INPUTSYNC */        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "inputsync" },
     /* ATTR_LENGTHIS */         { 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, "length_is" },
     /* ATTR_LIBLCID */          { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, "lcid" },
@@ -2205,7 +2238,7 @@ const char *get_attr_display_name(enum attr_type type)
     return allowed_attr[type].display_name;
 }
 
-static const attr_list_t *check_iface_attrs(const char *name, const attr_list_t *attrs)
+static attr_list_t *check_iface_attrs(const char *name, attr_list_t *attrs)
 {
   const attr_t *attr;
   if (!attrs) return attrs;
@@ -2276,7 +2309,7 @@ static attr_list_t *check_field_attrs(const char *name, attr_list_t *attrs)
   return attrs;
 }
 
-static const attr_list_t *check_library_attrs(const char *name, const attr_list_t *attrs)
+static attr_list_t *check_library_attrs(const char *name, attr_list_t *attrs)
 {
   const attr_t *attr;
   if (!attrs) return attrs;
@@ -2302,7 +2335,7 @@ static attr_list_t *check_dispiface_attrs(const char *name, attr_list_t *attrs)
   return attrs;
 }
 
-static const attr_list_t *check_module_attrs(const char *name, const attr_list_t *attrs)
+static attr_list_t *check_module_attrs(const char *name, attr_list_t *attrs)
 {
   const attr_t *attr;
   if (!attrs) return attrs;
@@ -2315,7 +2348,7 @@ static const attr_list_t *check_module_attrs(const char *name, const attr_list_t
   return attrs;
 }
 
-static const attr_list_t *check_coclass_attrs(const char *name, const attr_list_t *attrs)
+static attr_list_t *check_coclass_attrs(const char *name, attr_list_t *attrs)
 {
   const attr_t *attr;
   if (!attrs) return attrs;
index dbf74cc615b24662aac4be0f7ccd359000f00a9a..e96040753b3505bbf86536c6601f5a4135b56355 100644 (file)
@@ -105,6 +105,7 @@ enum attr_type
     ATTR_IMMEDIATEBIND,
     ATTR_IMPLICIT_HANDLE,
     ATTR_IN,
+    ATTR_INLINE,
     ATTR_INPUTSYNC,
     ATTR_LENGTHIS,
     ATTR_LIBLCID,
@@ -256,7 +257,7 @@ struct _type_t {
   enum type_kind kind;
   unsigned char type;
   struct _type_t *ref;
-  const attr_list_t *attrs;
+  attr_list_t *attrs;
   func_list_t *funcs;             /* interfaces and modules */
   var_list_t *fields_or_args;     /* interfaces, structures, enumerations and functions (for args) */
   ifref_list_t *ifaces;           /* coclasses */