aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree.c')
-rw-r--r--gcc/tree.c255
1 files changed, 150 insertions, 105 deletions
diff --git a/gcc/tree.c b/gcc/tree.c
index 2461c9b..40524c3 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -44,6 +44,7 @@ Boston, MA 02111-1307, USA. */
#include "ggc.h"
#include "hashtab.h"
#include "output.h"
+#include "target.h"
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
@@ -2706,124 +2707,119 @@ build_type_attribute_variant (ttype, attribute)
return ttype;
}
-/* Return a 1 if ATTR_NAME and ATTR_ARGS is valid for either declaration DECL
- or type TYPE and 0 otherwise. Validity is determined the configuration
- macros VALID_MACHINE_DECL_ATTRIBUTE and VALID_MACHINE_TYPE_ATTRIBUTE. */
+/* Return 1 if ATTR_NAME and ATTR_ARGS is valid for either declaration
+ DECL or type TYPE and 0 otherwise. Validity is determined the
+ target functions valid_decl_attribute and valid_machine_attribute. */
int
valid_machine_attribute (attr_name, attr_args, decl, type)
- tree attr_name;
- tree attr_args ATTRIBUTE_UNUSED;
- tree decl ATTRIBUTE_UNUSED;
- tree type ATTRIBUTE_UNUSED;
-{
- int validated = 0;
-#ifdef VALID_MACHINE_DECL_ATTRIBUTE
- tree decl_attr_list = decl != 0 ? DECL_MACHINE_ATTRIBUTES (decl) : 0;
-#endif
-#ifdef VALID_MACHINE_TYPE_ATTRIBUTE
- tree type_attr_list = TYPE_ATTRIBUTES (type);
-#endif
-
+ tree attr_name;
+ tree attr_args;
+ tree decl;
+ tree type;
+{
if (TREE_CODE (attr_name) != IDENTIFIER_NODE)
abort ();
-#ifdef VALID_MACHINE_DECL_ATTRIBUTE
- if (decl != 0
- && VALID_MACHINE_DECL_ATTRIBUTE (decl, decl_attr_list, attr_name,
- attr_args))
+ if (decl && target.valid_decl_attribute != NULL)
{
- tree attr = lookup_attribute (IDENTIFIER_POINTER (attr_name),
- decl_attr_list);
+ tree decl_attrs = DECL_MACHINE_ATTRIBUTES (decl);
- if (attr != NULL_TREE)
- {
- /* Override existing arguments. Declarations are unique so we can
- modify this in place. */
- TREE_VALUE (attr) = attr_args;
- }
- else
+ if ((*target.valid_decl_attribute) (decl, decl_attrs, attr_name,
+ attr_args))
{
- decl_attr_list = tree_cons (attr_name, attr_args, decl_attr_list);
- decl = build_decl_attribute_variant (decl, decl_attr_list);
- }
+ tree attr = lookup_attribute (IDENTIFIER_POINTER (attr_name),
+ decl_attrs);
- validated = 1;
+ if (attr != NULL_TREE)
+ {
+ /* Override existing arguments. Declarations are unique
+ so we can modify this in place. */
+ TREE_VALUE (attr) = attr_args;
+ }
+ else
+ {
+ decl_attrs = tree_cons (attr_name, attr_args, decl_attrs);
+ decl = build_decl_attribute_variant (decl, decl_attrs);
+ }
+
+ /* Don't apply the attribute to both the decl and the type. */
+ return 1;
+ }
}
-#endif
-#ifdef VALID_MACHINE_TYPE_ATTRIBUTE
- if (validated)
- /* Don't apply the attribute to both the decl and the type. */
- ;
- else if (VALID_MACHINE_TYPE_ATTRIBUTE (type, type_attr_list, attr_name,
- attr_args))
+ if (target.valid_type_attribute != NULL)
{
- tree attr = lookup_attribute (IDENTIFIER_POINTER (attr_name),
- type_attr_list);
+ tree type_attrs = TYPE_ATTRIBUTES (type);
- if (attr != NULL_TREE)
+ if ((*target.valid_type_attribute) (type, type_attrs, attr_name,
+ attr_args))
{
- /* Override existing arguments.
- ??? This currently works since attribute arguments are not
- included in `attribute_hash_list'. Something more complicated
- may be needed in the future. */
- TREE_VALUE (attr) = attr_args;
- }
- else
- {
- /* If this is part of a declaration, create a type variant,
- otherwise, this is part of a type definition, so add it
- to the base type. */
- type_attr_list = tree_cons (attr_name, attr_args, type_attr_list);
- if (decl != 0)
- type = build_type_attribute_variant (type, type_attr_list);
- else
- TYPE_ATTRIBUTES (type) = type_attr_list;
- }
-
- if (decl != 0)
- TREE_TYPE (decl) = type;
+ tree attr = lookup_attribute (IDENTIFIER_POINTER (attr_name),
+ type_attrs);
- validated = 1;
- }
+ if (attr != NULL_TREE)
+ {
+ /* Override existing arguments. ??? This currently
+ works since attribute arguments are not included in
+ `attribute_hash_list'. Something more complicated
+ may be needed in the future. */
+ TREE_VALUE (attr) = attr_args;
+ }
+ else
+ {
+ /* If this is part of a declaration, create a type variant,
+ otherwise, this is part of a type definition, so add it
+ to the base type. */
+ type_attrs = tree_cons (attr_name, attr_args, type_attrs);
+ if (decl != 0)
+ type = build_type_attribute_variant (type, type_attrs);
+ else
+ TYPE_ATTRIBUTES (type) = type_attrs;
+ }
- /* Handle putting a type attribute on pointer-to-function-type by putting
- the attribute on the function type. */
- else if (POINTER_TYPE_P (type)
- && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
- && VALID_MACHINE_TYPE_ATTRIBUTE (TREE_TYPE (type), type_attr_list,
- attr_name, attr_args))
- {
- tree inner_type = TREE_TYPE (type);
- tree inner_attr_list = TYPE_ATTRIBUTES (inner_type);
- tree attr = lookup_attribute (IDENTIFIER_POINTER (attr_name),
- type_attr_list);
+ if (decl)
+ TREE_TYPE (decl) = type;
- if (attr != NULL_TREE)
- TREE_VALUE (attr) = attr_args;
- else
- {
- inner_attr_list = tree_cons (attr_name, attr_args, inner_attr_list);
- inner_type = build_type_attribute_variant (inner_type,
- inner_attr_list);
+ return 1;
}
- if (decl != 0)
- TREE_TYPE (decl) = build_pointer_type (inner_type);
- else
+ /* Handle putting a type attribute on pointer-to-function-type
+ by putting the attribute on the function type. */
+ else if (POINTER_TYPE_P (type)
+ && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
+ && (*target.valid_type_attribute) (TREE_TYPE (type), type_attrs,
+ attr_name, attr_args))
{
- /* Clear TYPE_POINTER_TO for the old inner type, since
- `type' won't be pointing to it anymore. */
- TYPE_POINTER_TO (TREE_TYPE (type)) = NULL_TREE;
- TREE_TYPE (type) = inner_type;
- }
+ tree inner_type = TREE_TYPE (type);
+ tree inner_attrs = TYPE_ATTRIBUTES (inner_type);
+ tree attr = lookup_attribute (IDENTIFIER_POINTER (attr_name),
+ type_attrs);
- validated = 1;
+ if (attr != NULL_TREE)
+ TREE_VALUE (attr) = attr_args;
+ else
+ {
+ inner_attrs = tree_cons (attr_name, attr_args, inner_attrs);
+ inner_type = build_type_attribute_variant (inner_type,
+ inner_attrs);
+ }
+
+ if (decl)
+ TREE_TYPE (decl) = build_pointer_type (inner_type);
+ else
+ {
+ /* Clear TYPE_POINTER_TO for the old inner type, since
+ `type' won't be pointing to it anymore. */
+ TYPE_POINTER_TO (TREE_TYPE (type)) = NULL_TREE;
+ TREE_TYPE (type) = inner_type;
+ }
+
+ return 1;
+ }
}
-#endif
- return validated;
+ return 0;
}
/* Return non-zero if IDENT is a valid name for attribute ATTR,
@@ -2938,34 +2934,83 @@ merge_attributes (a1, a2)
}
/* Given types T1 and T2, merge their attributes and return
- the result. */
+ the result. */
tree
-merge_machine_type_attributes (t1, t2)
+merge_type_attributes (t1, t2)
tree t1, t2;
{
-#ifdef MERGE_MACHINE_TYPE_ATTRIBUTES
- return MERGE_MACHINE_TYPE_ATTRIBUTES (t1, t2);
-#else
return merge_attributes (TYPE_ATTRIBUTES (t1),
TYPE_ATTRIBUTES (t2));
-#endif
}
/* Given decls OLDDECL and NEWDECL, merge their attributes and return
the result. */
tree
-merge_machine_decl_attributes (olddecl, newdecl)
+merge_decl_attributes (olddecl, newdecl)
tree olddecl, newdecl;
{
-#ifdef MERGE_MACHINE_DECL_ATTRIBUTES
- return MERGE_MACHINE_DECL_ATTRIBUTES (olddecl, newdecl);
-#else
return merge_attributes (DECL_MACHINE_ATTRIBUTES (olddecl),
DECL_MACHINE_ATTRIBUTES (newdecl));
-#endif
}
+
+#ifdef TARGET_DLLIMPORT_DECL_ATTRIBUTES
+
+/* Specialization of merge_decl_attributes for various Windows targets.
+
+ This handles the following situation:
+
+ __declspec (dllimport) int foo;
+ int foo;
+
+ The second instance of `foo' nullifies the dllimport. */
+
+tree
+merge_dllimport_decl_attributes (old, new)
+ tree old;
+ tree new;
+{
+ tree a;
+ int delete_dllimport_p;
+
+ old = DECL_MACHINE_ATTRIBUTES (old);
+ new = DECL_MACHINE_ATTRIBUTES (new);
+
+ /* What we need to do here is remove from `old' dllimport if it doesn't
+ appear in `new'. dllimport behaves like extern: if a declaration is
+ marked dllimport and a definition appears later, then the object
+ is not dllimport'd. */
+ if (lookup_attribute ("dllimport", old) != NULL_TREE
+ && lookup_attribute ("dllimport", new) == NULL_TREE)
+ delete_dllimport_p = 1;
+ else
+ delete_dllimport_p = 0;
+
+ a = merge_attributes (old, new);
+
+ if (delete_dllimport_p)
+ {
+ tree prev,t;
+
+ /* Scan the list for dllimport and delete it. */
+ for (prev = NULL_TREE, t = a; t; prev = t, t = TREE_CHAIN (t))
+ {
+ if (is_attribute_p ("dllimport", TREE_PURPOSE (t)))
+ {
+ if (prev == NULL_TREE)
+ a = TREE_CHAIN (a);
+ else
+ TREE_CHAIN (prev) = TREE_CHAIN (t);
+ break;
+ }
+ }
+ }
+
+ return a;
+}
+
+#endif /* TARGET_DLLIMPORT_DECL_ATTRIBUTES */
/* Set the type qualifiers for TYPE to TYPE_QUALS, which is a bitmask
of the various TYPE_QUAL values. */