- if (!(name = TREE_VALUE (a)))
- continue;
- else if (name == get_identifier ("packed")
- || name == get_identifier ("__packed__"))
- {
- 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_with_decl (decl, "`packed' attribute ignored");
- }
- else if (name == get_identifier ("noreturn")
- || name == get_identifier ("__noreturn__")
- || name == get_identifier ("volatile")
- || name == get_identifier ("__volatile__"))
- {
- 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_with_decl (decl,
- (IDENTIFIER_POINTER (name)[0] == 'n'
- || IDENTIFIER_POINTER (name)[2] == 'n')
- ? "`noreturn' attribute ignored"
- : "`volatile' attribute ignored");
- }
- else if (name == get_identifier ("const")
- || name == get_identifier ("__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_with_decl (decl, "`const' attribute ignored");
- }
- else if (name == get_identifier ("transparent_union")
- || name == get_identifier ("__transparent_union__"))
- {
- if (TREE_CODE (decl) == PARM_DECL
- && TREE_CODE (type) == UNION_TYPE
- && TYPE_MODE (type) == DECL_MODE (TYPE_FIELDS (type)))
- DECL_TRANSPARENT_UNION (decl) = 1;
- else if (TREE_CODE (decl) == TYPE_DECL
- && TREE_CODE (type) == UNION_TYPE
- && TYPE_MODE (type) == DECL_MODE (TYPE_FIELDS (type)))
- TYPE_TRANSPARENT_UNION (type) = 1;
- else
- warning_with_decl (decl, "`transparent_union' attribute ignored");
- }
- else if (name == get_identifier ("constructor")
- || name == get_identifier ("__constructor__"))
- {
- if (TREE_CODE (decl) != FUNCTION_DECL
- || TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
- || decl_function_context (decl))
- {
- error_with_decl (decl,
- "`constructor' attribute meaningless for non-function %s");
- continue;
- }
- DECL_STATIC_CONSTRUCTOR (decl) = 1;
- }
- else if (name == get_identifier ("destructor")
- || name == get_identifier ("__destructor__"))
- {
- if (TREE_CODE (decl) != FUNCTION_DECL
- || TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
- || decl_function_context (decl))
- {
- error_with_decl (decl,
- "`destructor' attribute meaningless for non-function %s");
- continue;
- }
- DECL_STATIC_DESTRUCTOR (decl) = 1;
- }
- 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 ("unknown machine mode `%s'", specified_name);
- else if ((typefm = type_for_mode (mode, TREE_UNSIGNED (type))) == 0)
- error ("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)
- {
+ {
+ tree name = TREE_PURPOSE (a);
+ tree args = TREE_VALUE (a);
+ int i;
+ enum attrs id;
+
+ for (i = 0; i < attrtab_idx; i++)
+ if (attrtab[i].name == name)
+ break;
+
+ if (i == attrtab_idx)
+ {
+ if (! valid_machine_attribute (name, args, decl, type))
+ warning ("`%s' attribute directive ignored",
+ IDENTIFIER_POINTER (name));
+ else if (decl != 0)
+ type = TREE_TYPE (decl);
+ continue;
+ }
+ else if (attrtab[i].decl_req && decl == 0)
+ {
+ warning ("`%s' attribute does not apply to types",
+ IDENTIFIER_POINTER (name));
+ 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: