- }
- else if ( args = TREE_CHAIN(name),
- (!strcmp (IDENTIFIER_POINTER (name = TREE_PURPOSE (name)), "mode")
- || !strcmp (IDENTIFIER_POINTER (name), "__mode__"))
- && list_length (args) == 1
- && TREE_CODE (TREE_VALUE (args)) == IDENTIFIER_NODE)
- {
- int i;
- char *specified_name = IDENTIFIER_POINTER (TREE_VALUE (args));
- enum machine_mode mode = VOIDmode;
- tree typefm;
-
- /* Give this decl a type with the specified mode.
- First check for the special modes. */
- if (! strcmp (specified_name, "byte")
- || ! strcmp (specified_name, "__byte__"))
- mode = byte_mode;
- else if (!strcmp (specified_name, "word")
- || ! strcmp (specified_name, "__word__"))
- mode = word_mode;
- else if (! strcmp (specified_name, "pointer")
- || !strcmp (specified_name, "__pointer__"))
- mode = ptr_mode;
- else
- for (i = 0; i < NUM_MACHINE_MODES; i++)
- if (!strcmp (specified_name, GET_MODE_NAME (i)))
- mode = (enum machine_mode) i;
-
- if (mode == VOIDmode)
- error_with_decl (decl, "unknown machine mode `%s'", specified_name);
- else if ((typefm = type_for_mode (mode, TREE_UNSIGNED (type))) == 0)
- error_with_decl (decl, "no data type for mode `%s'", specified_name);
- else
- {
- TREE_TYPE (decl) = type = typefm;
- DECL_SIZE (decl) = 0;
- layout_decl (decl, 0);
- }
- }
- else if ((!strcmp (IDENTIFIER_POINTER (name), "section")
- || !strcmp (IDENTIFIER_POINTER (name), "__section__"))
- && list_length (args) == 1
- && TREE_CODE (TREE_VALUE (args)) == STRING_CST)
- {
+ continue;
+ }
+ else if (list_length (args) < attrtab[i].min
+ || list_length (args) > attrtab[i].max)
+ {
+ error ("wrong number of arguments specified for `%s' attribute",
+ IDENTIFIER_POINTER (name));
+ continue;
+ }
+
+ id = attrtab[i].id;
+ switch (id)
+ {
+ case A_PACKED:
+ if (is_type)
+ TYPE_PACKED (type) = 1;
+ else if (TREE_CODE (decl) == FIELD_DECL)
+ DECL_PACKED (decl) = 1;
+ /* We can't set DECL_PACKED for a VAR_DECL, because the bit is
+ used for DECL_REGISTER. It wouldn't mean anything anyway. */
+ else
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ break;
+
+ case A_NOCOMMON:
+ if (TREE_CODE (decl) == VAR_DECL)
+ DECL_COMMON (decl) = 0;
+ else
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ break;
+
+ case A_COMMON:
+ if (TREE_CODE (decl) == VAR_DECL)
+ DECL_COMMON (decl) = 1;
+ else
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ break;
+
+ case A_NORETURN:
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ TREE_THIS_VOLATILE (decl) = 1;
+ else if (TREE_CODE (type) == POINTER_TYPE
+ && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
+ TREE_TYPE (decl) = type
+ = build_pointer_type
+ (build_type_variant (TREE_TYPE (type),
+ TREE_READONLY (TREE_TYPE (type)), 1));
+ else
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ break;
+
+ case A_UNUSED:
+ if (TREE_CODE (decl) == PARM_DECL || TREE_CODE (decl) == VAR_DECL
+ || TREE_CODE (decl) == FUNCTION_DECL)
+ TREE_USED (decl) = 1;
+ else
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ break;
+
+ case A_CONST:
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ TREE_READONLY (decl) = 1;
+ else if (TREE_CODE (type) == POINTER_TYPE
+ && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
+ TREE_TYPE (decl) = type
+ = build_pointer_type
+ (build_type_variant (TREE_TYPE (type), 1,
+ TREE_THIS_VOLATILE (TREE_TYPE (type))));
+ else
+ warning ( "`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ break;
+
+ case A_T_UNION:
+ if (is_type
+ && TREE_CODE (type) == UNION_TYPE
+ && (decl == 0
+ || (TYPE_FIELDS (type) != 0
+ && TYPE_MODE (type) == DECL_MODE (TYPE_FIELDS (type)))))
+ TYPE_TRANSPARENT_UNION (type) = 1;
+ else if (decl != 0 && TREE_CODE (decl) == PARM_DECL
+ && TREE_CODE (type) == UNION_TYPE
+ && TYPE_MODE (type) == DECL_MODE (TYPE_FIELDS (type)))
+ DECL_TRANSPARENT_UNION (decl) = 1;
+ else
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ break;
+
+ case A_CONSTRUCTOR:
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && TREE_CODE (type) == FUNCTION_TYPE
+ && decl_function_context (decl) == 0)
+ {
+ DECL_STATIC_CONSTRUCTOR (decl) = 1;
+ TREE_USED (decl) = 1;
+ }
+ else
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ break;
+
+ case A_DESTRUCTOR:
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && TREE_CODE (type) == FUNCTION_TYPE
+ && decl_function_context (decl) == 0)
+ {
+ DECL_STATIC_DESTRUCTOR (decl) = 1;
+ TREE_USED (decl) = 1;
+ }
+ else
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ break;
+
+ case A_MODE:
+ if (TREE_CODE (TREE_VALUE (args)) != IDENTIFIER_NODE)
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ else
+ {
+ int j;
+ char *p = IDENTIFIER_POINTER (TREE_VALUE (args));
+ int len = strlen (p);
+ enum machine_mode mode = VOIDmode;
+ tree typefm;
+
+ if (len > 4 && p[0] == '_' && p[1] == '_'
+ && p[len - 1] == '_' && p[len - 2] == '_')
+ {
+ char *newp = (char *) alloca (len - 1);
+
+ strcpy (newp, &p[2]);
+ newp[len - 4] = '\0';
+ p = newp;
+ }
+
+ /* Give this decl a type with the specified mode.
+ First check for the special modes. */
+ if (! strcmp (p, "byte"))
+ mode = byte_mode;
+ else if (!strcmp (p, "word"))
+ mode = word_mode;
+ else if (! strcmp (p, "pointer"))
+ mode = ptr_mode;
+ else
+ for (j = 0; j < NUM_MACHINE_MODES; j++)
+ if (!strcmp (p, GET_MODE_NAME (j)))
+ mode = (enum machine_mode) j;
+
+ if (mode == VOIDmode)
+ error ("unknown machine mode `%s'", p);
+ else if (0 == (typefm = type_for_mode (mode,
+ TREE_UNSIGNED (type))))
+ error ("no data type for mode `%s'", p);
+ else
+ {
+ TREE_TYPE (decl) = type = typefm;
+ DECL_SIZE (decl) = 0;
+ layout_decl (decl, 0);
+ }
+ }
+ break;
+
+ case A_SECTION: