Index: /trunk/src/gcc/gcc/config/i386/emx.c
===================================================================
--- /trunk/src/gcc/gcc/config/i386/emx.c	(revision 602)
+++ /trunk/src/gcc/gcc/config/i386/emx.c	(revision 603)
@@ -31,5 +31,4 @@
 #include "flags.h"
 
-#define BIRD_DEBUG
 
 /* The size of the target's pointer type.  */
@@ -37,4 +36,7 @@
 #define PTR_SIZE (POINTER_SIZE / BITS_PER_UNIT)
 #endif
+
+/** @todo remove debug code */
+/*#define BIRD_DEBUG*/
 #ifdef BIRD_DEBUG
 static const char *code(tree node)
@@ -95,5 +97,5 @@
   int flags, bool *no_add_attrs)
 {
-  tree id, type;
+  tree id, type, context;
   size_t sl;
   const char *oldsym;
@@ -107,6 +109,8 @@
         /* 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"))
+           an attached attribute (either optlink or system).
+           This is the only part which is changing the mangling. */
+        if (   !strcmp (IDENTIFIER_POINTER (name), "__system__")
+            || !strcmp (IDENTIFIER_POINTER (name), "system") )
           {
             /* Here we mangle _System functions as defined by IBM specs.
@@ -114,21 +118,36 @@
                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) */
-            sl = strlen (oldsym);
-            newsym = xmalloc (sl + 2);
-            newsym [0] = '*';
-            memcpy (newsym + 1, oldsym, sl + 1);
-            SET_DECL_ASSEMBLER_NAME (*node, get_identifier (newsym));
+            /* @todo: verify the class detection here! Does it require use of
+                CLASSTYPE_DECLARED_CLASS (meaning it doesn't applies to plain
+                structs/unions) ? */
+            if (   TREE_CODE (TREE_TYPE (*node)) != METHOD_TYPE
+                && (   !(context = DECL_CONTEXT (*node))
+                    || (   TREE_CODE (context) != RECORD_TYPE
+                        && TREE_CODE (context) != UNION_TYPE)))
+              {
+                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) */
+                sl = strlen (oldsym);
+                newsym = xmalloc (sl + 2);
+                newsym [0] = '*';
+                memcpy (newsym + 1, oldsym, sl + 1);
+                SET_DECL_ASSEMBLER_NAME (*node, get_identifier (newsym));
+                dfprintf((stderr, "dbg: system %s -> %s\n", oldsym, newsym));
+              }
           }
-        else if (!strcmp (IDENTIFIER_POINTER (name), "optlink"))
+        else if (   !strcmp (IDENTIFIER_POINTER (name), "__optlink__")
+                 || !strcmp (IDENTIFIER_POINTER (name), "optlink"))
           {
-            /* All function types have a name which should be mangled
-               by _Optlink specification. */
+            /* At the moment we're only implementing OS/2 VAC linking
+               compatibility for the C language. This means that no leading
+               underscore.
+               For C++ we are not compatible. It doesn't make that much sense
+               either since we're not VFT compatible either. For simplisity
+               and safty we are removing the leading underscore from the
+               default mangled names to catch invalid declarations in the
+               linking. */
+
             id = DECL_ASSEMBLER_NAME (*node);
             /* Remove the leading underscore. */
@@ -140,61 +159,78 @@
             XEXP (DECL_RTL (*node), 0) = gen_rtx (SYMBOL_REF, Pmode,
               IDENTIFIER_POINTER (get_identifier (newsym)));
+            dfprintf((stderr, "dbg: optlink %s -> %s\n", oldsym, newsym));
           }
-        else /* Huh?! */
-          goto warn;
+        else /* Internal error!!! */
+          {
+            warning ("`%s' is an unknown attribute name for ix86_handle_vacpp_attribute()",
+                     IDENTIFIER_POINTER (name));
+            *no_add_attrs = true;
+            break;
+          }
 
         /* The attribute should really be attached to our _TYPE,
-           not to the _DECL */
+           not to the _DECL. (yeah, we need to do this!) */
         type = TREE_TYPE (*node);
-        goto attach_attr;
-
+        TYPE_ATTRIBUTES (type) = chainon (TYPE_ATTRIBUTES (type),
+                                          tree_cons (name, args, NULL_TREE));
+        *no_add_attrs = true;
+        break;
+
+      /* Only function declarations needs mangling changes, however other
+         declarations involving function types needs to get the parameter
+         passing right. */
+      case FIELD_DECL:
+        /* Struct, union or class member declaration. Same handling as
+           type declarations. */
       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 */
+        /* If this is a type declaration with our attribute, we allow it
+           only if it is a pointer-to-a-function type or 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 */
+        if (TREE_CODE (type) == POINTER_TYPE)
+          type = TREE_TYPE(type);
+        if (   TREE_CODE (type) == FUNCTION_TYPE
+            || TREE_CODE (type) == METHOD_TYPE)
           {
             /* Attach the attribute to the (FUNCTION|METHOD)_TYPE node */
-            type = TREE_TYPE (type);
-attach_attr:TYPE_ATTRIBUTES (type) = chainon (TYPE_ATTRIBUTES (type),
+            TYPE_ATTRIBUTES (type) = chainon (TYPE_ATTRIBUTES (type),
                                               tree_cons (name, args, NULL_TREE));
             *no_add_attrs = true;
             break;
           }
-        goto warn;
-
+        warning ("`%s' attribute only applies to functions and function types (typecode=%d)",
+                 IDENTIFIER_POINTER (name), type ? (int)TREE_CODE (type) : -1);
+        *no_add_attrs = true;
+        break;
+
+
+      /* For types involving functions we need to convince decl_attributes
+         (and it callers) to supply a declaration in case the mangling needs
+         to be changed. */
       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;
+        /* We allow:
+           This being the return type of a function which is coming soon.
+           This being a function pointer which declaration is coming next.
+           Everything else is concidered inappropriate use of the attribute. */
+        if (   !(flags & ATTR_FLAG_FUNCTION_NEXT)
+            && (    !(flags & ATTR_FLAG_DECL_NEXT)
+                ||  !(type = TREE_TYPE (*node))
+                || (   TREE_CODE (type) != FUNCTION_TYPE
+                    && TREE_CODE (type) != METHOD_TYPE)))
+        {
+            warning ("`%s' attribute only applies to functions and function types (typecode=%d)",
+                     IDENTIFIER_POINTER (name), type ? (int)TREE_CODE (type) : -1);
+            *no_add_attrs = true;
+            break;
+        }
+        /* fall thru */
+      case FUNCTION_TYPE:
+      case METHOD_TYPE:
+        *no_add_attrs = true;
+        return tree_cons (name, args, NULL_TREE);
 
       default:
-warn:   warning ("`%s' attribute only applies to functions and function types",
-                 IDENTIFIER_POINTER (name));
+        warning ("`%s' attribute only applies to functions and function types (code=%d)",
+                 IDENTIFIER_POINTER (name), TREE_CODE (*node));
         *no_add_attrs = true;
-        DUMP (*node);
         break;
     }
