Index: trunk/src/gcc/gcc/config/i386/emx.c
===================================================================
--- trunk/src/gcc/gcc/config/i386/emx.c	(revision 597)
+++ trunk/src/gcc/gcc/config/i386/emx.c	(revision 598)
@@ -30,4 +30,6 @@
 #include "toplev.h"
 #include "flags.h"
+
+#define BIRD_DEBUG
 
 /* The size of the target's pointer type.  */
@@ -66,5 +68,5 @@
 void dump (tree node)
 {
-    tree        type, type2, context;
+    tree type, type2, context, name;
     if (!node)
         return;
@@ -73,9 +75,11 @@
     type2 = type ? TREE_TYPE(type) : NULL;
     context = DECL_P (node) ? DECL_CONTEXT (node) : NULL_TREE;
-    fprintf(stderr, "dbg: node=%d %s type=%d %s type_type=%d %s context=%d %s\n",
+    name = DECL_P (node) ? DECL_NAME (node) : NULL_TREE;
+    fprintf(stderr, "dbg: node=%d %s type=%d %s type_type=%d %s context=%d %s name=%s\n",
             TREE_CODE(node), code(node),
             type ? TREE_CODE(type) : -1, code(type),
             type2 ? TREE_CODE(type2) : -1, code(type2),
-            context ? TREE_CODE(context) : -1, code(context));
+            context ? TREE_CODE(context) : -1, code(context),
+            name ? IDENTIFIER_POINTER (name) : "<none>");
 }
 
@@ -88,45 +92,33 @@
 
 
-tree ix86_handle_system_attribute (tree *node, tree name, tree args,
+tree ix86_handle_vacpp_attribute (tree *node, tree name, tree args,
   int flags, bool *no_add_attrs)
 {
-  tree          type;
-  (void)args; (void)flags;
-
-dfprintf ((stderr, "dbg: %s flags=%x\n", __FUNCTION__, flags));
-DUMP (*node);
-
-  type = TREE_TYPE (*node);
-  if (DECL_P (*node))
-    switch (TREE_CODE (type))
-      {
-        case FUNCTION_TYPE:
-          {
-            tree          context;
-            size_t        sl;
-            const char *  oldsym;
-            char *        newsym;
-
-            /* typedef and field may end up here. they should not get their name changed! */
-            if (TREE_CODE (*node) == FIELD_DECL | TREE_CODE (*node) == TYPE_DECL)
-                return NULL_TREE;
-
-            /* class method (static) ends up here too, they should be get their
-               name changed. Try check if context is RECORD_TYPE and pray that
-               means it's a class...
-               @todo: verify the class detection here! CLASSTYPE_DECLARED_CLASS?  */
-            context = DECL_CONTEXT (*node);
-            DUMP ((context));
-            if (context && (    TREE_CODE (context) == RECORD_TYPE
-                            ||  TREE_CODE (context) == UNION_TYPE))
-              return NULL_TREE;
-            /** @todo more decl code checks? */
-
-
-            /* _System mangling!
-               Specifying '*' as first symbol character tells gcc (see varasm.c,
+  tree id, type;
+  size_t sl;
+  const char *oldsym;
+  char *newsym;
+
+  DUMP (*node);
+
+  switch (TREE_CODE (*node))
+    {
+      case FUNCTION_DECL:
+        /* This is the core of attribute handling. Every other code is
+           designed so that we end up with a function declaration and
+           an attached attribute (either optlink or system). */
+        if (!strcmp (IDENTIFIER_POINTER (name), "system"))
+          {
+            /* Here we mangle _System functions as defined by IBM specs.
+               The function always gets its name as-is (unless it is a method,
+               which is a undefined case as VACPP always use _Optlink for methods,
+               at least that's what I have understood from the docs). */
+            if (TREE_CODE (TREE_TYPE (*node)) == METHOD_TYPE)
+              break;
+
+            oldsym = IDENTIFIER_POINTER (DECL_NAME (*node));
+            /* Specifying '*' as first symbol character tells gcc (see varasm.c,
                function assemble_name()) to output the label as-is rather than
                invoking the ASM_OUTPUT_LABELREF macro (which prepends a underscore) */
-            oldsym = IDENTIFIER_POINTER (DECL_NAME (*node));
             sl = strlen (oldsym);
             newsym = xmalloc (sl + 2);
@@ -134,118 +126,76 @@
             memcpy (newsym + 1, oldsym, sl + 1);
             SET_DECL_ASSEMBLER_NAME (*node, get_identifier (newsym));
-            dfprintf((stderr, "dbg: name change: %s -> %s\n", oldsym, newsym));
-            return NULL_TREE;
-          }
-        case POINTER_TYPE:
-          /* Pointer-to-a-function type is allowed */
-	  if (TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE
-           && TREE_CODE (TREE_TYPE (type)) != METHOD_TYPE)
+          }
+        else if (!strcmp (IDENTIFIER_POINTER (name), "optlink"))
+          {
+            /* All function types have a name which should be mangled
+               by _Optlink specification. */
+            id = DECL_ASSEMBLER_NAME (*node);
+            /* Remove the leading underscore. */
+            oldsym = IDENTIFIER_POINTER (id);
+            sl = strlen (oldsym);
+            newsym = xmalloc (sl + 2);
+            newsym [0] = '*';
+            memcpy (newsym + 1, oldsym, sl + 1);
+            XEXP (DECL_RTL (*node), 0) = gen_rtx (SYMBOL_REF, Pmode,
+              IDENTIFIER_POINTER (get_identifier (newsym)));
+          }
+        else /* Huh?! */
+          goto warn;
+
+        /* The attribute should really be attached to our _TYPE,
+           not to the _DECL */
+        type = TREE_TYPE (*node);
+        goto attach_attr;
+
+      case TYPE_DECL:
+        /* If this is a type declaration with our attribute,
+           we allow it only if it is a pointer-to-a-function type */
+        type = TREE_TYPE (*node);
+        if (TREE_CODE (type) == POINTER_TYPE
+         && (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
+          || TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE))
+          /* Since it is just a type it doesn't have any label to mangle,
+             but if we attach the attribute to the type all calls through
+             this pointer will get arguments passed correctly */
+          {
+            /* Attach the attribute to the (FUNCTION|METHOD)_TYPE node */
+            type = TREE_TYPE (type);
+attach_attr:TYPE_ATTRIBUTES (type) = chainon (TYPE_ATTRIBUTES (type),
+                                              tree_cons (name, args, NULL_TREE));
+            *no_add_attrs = true;
             break;
-        case METHOD_TYPE:
-        case FIELD_DECL:
-        case TYPE_DECL:
-          /* Not a error but no action either */
-          return NULL_TREE;
-        default:
-          break;
-      }
-  else if (TREE_CODE (*node) == POINTER_TYPE && type)
-    { /* Pointer-to-a-function type is allowed */
-      switch (TREE_CODE (type))
-        {
-          case FUNCTION_TYPE:
-          case METHOD_TYPE:
-            return NULL_TREE;
-          default:
-            break;
-        }
-    }
-  /* potential warnings get here */
-
-  /* IF there is a function in the works, we don't complain and
-     make sure _System is tried again on the function declaration.
-     OR if this is a function type we need to pass it up to the
-     declaration which is likely to be a some kind of type or field.
-     */
-  if (   (flags & (int)ATTR_FLAG_FUNCTION_NEXT)
-      || TREE_CODE (*node) == FUNCTION_TYPE
-      || TREE_CODE (*node) == METHOD_TYPE)
-    return tree_cons (name, args, NULL_TREE);
-
-  warning ("`%s' attribute only applies to functions and function types",
-           IDENTIFIER_POINTER (name));
-  *no_add_attrs = true;
-
-  return NULL_TREE;
-}
-
-
-tree ix86_handle_optlink_attribute (tree *node, tree name, tree args,
-  int flags, bool *no_add_attrs)
-{
-  tree id, type, typeset;
-  size_t sl;
-  const char *oldsym;
-  char *newsym;
-
-  (void)args; (void)flags;
-
-  typeset = NULL;
-  type = TREE_TYPE (*node);
-  if (DECL_P (*node))
-    switch (TREE_CODE (type))
-      {
-        case FUNCTION_TYPE:
-        case METHOD_TYPE:
-          typeset = type;
-        case FIELD_DECL:                /* how come these needs mangling? */
-        case TYPE_DECL:
-          id = DECL_ASSEMBLER_NAME (*node);
-          /* Remove the leading underscore */
-          oldsym = IDENTIFIER_POINTER (id);
-          sl = strlen (oldsym);
-          newsym = xmalloc (sl + 2);
-          newsym [0] = '*';
-          memcpy (newsym + 1, oldsym, sl + 1);
-          XEXP (DECL_RTL (*node), 0) = gen_rtx (SYMBOL_REF, Pmode,
-            IDENTIFIER_POINTER (get_identifier (newsym)));
-          break;
-        case POINTER_TYPE:
-          /* Pointer-to-a-function type is allowed */
-	  if (TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE
-           && TREE_CODE (TREE_TYPE (type)) != METHOD_TYPE)
-            goto warn;
-/*@@@@@todo: not finished*/
-          typeset = type;
-          break;
-        default:
-          goto warn;
-      }
-  else if (TREE_CODE (*node) == POINTER_TYPE && type)
-    { /* Pointer-to-a-function type is allowed */
-      switch (TREE_CODE (type))
-        {
-          case FUNCTION_TYPE:
-          case METHOD_TYPE:
-            typeset = type;
-            break;
-          default:
-            goto warn;
-        }
-    }
-  else
-    {
-warn: warning ("`%s' attribute only applies to functions and function types",
-               IDENTIFIER_POINTER (name));
-      *no_add_attrs = true;
-      DUMP (*node);
-    }
-
-  /* attach attribute to type. */
-  if (typeset)
-    {
-      id = tree_cons (name, args, NULL_TREE);
-      TYPE_ATTRIBUTES (typeset) = chainon (TYPE_ATTRIBUTES (typeset), id);
-      return id;
+          }
+        goto warn;
+
+      case POINTER_TYPE:
+        if (flags & ATTR_FLAG_FUNCTION_NEXT)
+          {
+            /* This is the return type for a function. Ignore attribute
+               for the return type itself and re-apply it later to the
+               function itself. */
+defer_attr: *no_add_attrs = true;
+            return tree_cons (name, args, NULL_TREE);
+          }
+        else if (flags & ATTR_FLAG_DECL_NEXT)
+          {
+            /* The node passed is the type of a DECL that will follow.
+               If the decl is a function or a method, tell decl_attributes()
+               that the attribute should be applied to the decl rather than
+               to its return type  */
+            type = TREE_TYPE (*node);
+            if (type
+             && (TREE_CODE (type) == FUNCTION_TYPE
+              || TREE_CODE (type) == METHOD_TYPE))
+               goto defer_attr;
+          }
+        goto warn;
+
+      default:
+warn:   warning ("`%s' attribute only applies to functions and function types",
+                 IDENTIFIER_POINTER (name));
+        *no_add_attrs = true;
+        DUMP (*node);
+        break;
     }
 
@@ -277,5 +227,5 @@
     strcpy (lbl, "__POST$");
     if (func_label[0] == '*')
-        func_label++;
+      func_label++;
     strcat (lbl, func_label);
     ASM_OUTPUT_LABEL (f, lbl);
Index: trunk/src/gcc/gcc/config/i386/emx.h
===================================================================
--- trunk/src/gcc/gcc/config/i386/emx.h	(revision 597)
+++ trunk/src/gcc/gcc/config/i386/emx.h	(revision 598)
@@ -91,13 +91,14 @@
 #define DWARF2_UNWIND_INFO 1
 
+/* This function handles both _System and _Optlink attributes */
+extern tree ix86_handle_vacpp_attribute PARAMS ((tree *, tree, tree, int, _Bool *));
+
 /* We want the _System attribute */
 #define TARGET_SYSTEM_DECL_ATTRIBUTES
-/* Handle _System attribute */
-extern tree ix86_handle_system_attribute PARAMS ((tree *, tree, tree, int, _Bool *));
+#define ix86_handle_system_attribute ix86_handle_vacpp_attribute
 
 /* We want the _Optlink attribute */
 #define TARGET_OPTLINK_DECL_ATTRIBUTES
-/* Handle _Optlink attribute */
-extern tree ix86_handle_optlink_attribute PARAMS ((tree *, tree, tree, int, _Bool *));
+#define ix86_handle_optlink_attribute ix86_handle_vacpp_attribute
 
 /* This macros will stick a label to exception table for current file,
Index: trunk/src/gcc/gcc/cp/decl.c
===================================================================
--- trunk/src/gcc/gcc/cp/decl.c	(revision 597)
+++ trunk/src/gcc/gcc/cp/decl.c	(revision 598)
@@ -13638,5 +13638,5 @@
   else
     {
-      decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, NULL);
+      decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, &attrs);
       /* If the declarator is not suitable for a function definition,
 	 cause a syntax error.  */
