annotate gcc/attribs.c @ 127:4c56639505ff

fix function.c and add CbC-example Makefile
author mir3636
date Wed, 11 Apr 2018 18:46:58 +0900
parents 04ced10e8804
children 84e7813d76e9
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1 /* Functions dealing with attribute handling, used by most front ends.
111
kono
parents: 67
diff changeset
2 Copyright (C) 1992-2017 Free Software Foundation, Inc.
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
3
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
4 This file is part of GCC.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
5
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
6 GCC is free software; you can redistribute it and/or modify it under
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
7 the terms of the GNU General Public License as published by the Free
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
8 Software Foundation; either version 3, or (at your option) any later
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
9 version.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
10
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
14 for more details.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
15
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
16 You should have received a copy of the GNU General Public License
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
17 along with GCC; see the file COPYING3. If not see
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
18 <http://www.gnu.org/licenses/>. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
19
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
20 #include "config.h"
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
21 #include "system.h"
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
22 #include "coretypes.h"
111
kono
parents: 67
diff changeset
23 #include "target.h"
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
24 #include "tree.h"
111
kono
parents: 67
diff changeset
25 #include "stringpool.h"
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
26 #include "diagnostic-core.h"
111
kono
parents: 67
diff changeset
27 #include "attribs.h"
kono
parents: 67
diff changeset
28 #include "stor-layout.h"
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
29 #include "langhooks.h"
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
30 #include "plugin.h"
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
31
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
32 /* Table of the tables of attributes (common, language, format, machine)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
33 searched. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
34 static const struct attribute_spec *attribute_tables[4];
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
35
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
36 /* Substring representation. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
37
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
38 struct substring
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
39 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
40 const char *str;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
41 int length;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
42 };
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
43
111
kono
parents: 67
diff changeset
44 /* Simple hash function to avoid need to scan whole string. */
kono
parents: 67
diff changeset
45
kono
parents: 67
diff changeset
46 static inline hashval_t
kono
parents: 67
diff changeset
47 substring_hash (const char *str, int l)
kono
parents: 67
diff changeset
48 {
kono
parents: 67
diff changeset
49 return str[0] + str[l - 1] * 256 + l * 65536;
kono
parents: 67
diff changeset
50 }
kono
parents: 67
diff changeset
51
kono
parents: 67
diff changeset
52 /* Used for attribute_hash. */
kono
parents: 67
diff changeset
53
kono
parents: 67
diff changeset
54 struct attribute_hasher : nofree_ptr_hash <attribute_spec>
kono
parents: 67
diff changeset
55 {
kono
parents: 67
diff changeset
56 typedef substring *compare_type;
kono
parents: 67
diff changeset
57 static inline hashval_t hash (const attribute_spec *);
kono
parents: 67
diff changeset
58 static inline bool equal (const attribute_spec *, const substring *);
kono
parents: 67
diff changeset
59 };
kono
parents: 67
diff changeset
60
kono
parents: 67
diff changeset
61 inline hashval_t
kono
parents: 67
diff changeset
62 attribute_hasher::hash (const attribute_spec *spec)
kono
parents: 67
diff changeset
63 {
kono
parents: 67
diff changeset
64 const int l = strlen (spec->name);
kono
parents: 67
diff changeset
65 return substring_hash (spec->name, l);
kono
parents: 67
diff changeset
66 }
kono
parents: 67
diff changeset
67
kono
parents: 67
diff changeset
68 inline bool
kono
parents: 67
diff changeset
69 attribute_hasher::equal (const attribute_spec *spec, const substring *str)
kono
parents: 67
diff changeset
70 {
kono
parents: 67
diff changeset
71 return (strncmp (spec->name, str->str, str->length) == 0
kono
parents: 67
diff changeset
72 && !spec->name[str->length]);
kono
parents: 67
diff changeset
73 }
kono
parents: 67
diff changeset
74
kono
parents: 67
diff changeset
75 /* Scoped attribute name representation. */
kono
parents: 67
diff changeset
76
kono
parents: 67
diff changeset
77 struct scoped_attributes
kono
parents: 67
diff changeset
78 {
kono
parents: 67
diff changeset
79 const char *ns;
kono
parents: 67
diff changeset
80 vec<attribute_spec> attributes;
kono
parents: 67
diff changeset
81 hash_table<attribute_hasher> *attribute_hash;
kono
parents: 67
diff changeset
82 };
kono
parents: 67
diff changeset
83
kono
parents: 67
diff changeset
84 /* The table of scope attributes. */
kono
parents: 67
diff changeset
85 static vec<scoped_attributes> attributes_table;
kono
parents: 67
diff changeset
86
kono
parents: 67
diff changeset
87 static scoped_attributes* find_attribute_namespace (const char*);
kono
parents: 67
diff changeset
88 static void register_scoped_attribute (const struct attribute_spec *,
kono
parents: 67
diff changeset
89 scoped_attributes *);
kono
parents: 67
diff changeset
90
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
91 static bool attributes_initialized = false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
92
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
93 /* Default empty table of attributes. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
94
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
95 static const struct attribute_spec empty_attribute_table[] =
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
96 {
111
kono
parents: 67
diff changeset
97 { NULL, 0, 0, false, false, false, NULL, false }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
98 };
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
99
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
100 /* Return base name of the attribute. Ie '__attr__' is turned into 'attr'.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
101 To avoid need for copying, we simply return length of the string. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
102
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
103 static void
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
104 extract_attribute_substring (struct substring *str)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
105 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
106 if (str->length > 4 && str->str[0] == '_' && str->str[1] == '_'
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
107 && str->str[str->length - 1] == '_' && str->str[str->length - 2] == '_')
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
108 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
109 str->length -= 4;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
110 str->str += 2;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
111 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
112 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
113
111
kono
parents: 67
diff changeset
114 /* Insert an array of attributes ATTRIBUTES into a namespace. This
kono
parents: 67
diff changeset
115 array must be NULL terminated. NS is the name of attribute
kono
parents: 67
diff changeset
116 namespace. The function returns the namespace into which the
kono
parents: 67
diff changeset
117 attributes have been registered. */
kono
parents: 67
diff changeset
118
kono
parents: 67
diff changeset
119 scoped_attributes*
kono
parents: 67
diff changeset
120 register_scoped_attributes (const struct attribute_spec * attributes,
kono
parents: 67
diff changeset
121 const char* ns)
kono
parents: 67
diff changeset
122 {
kono
parents: 67
diff changeset
123 scoped_attributes *result = NULL;
kono
parents: 67
diff changeset
124
kono
parents: 67
diff changeset
125 /* See if we already have attributes in the namespace NS. */
kono
parents: 67
diff changeset
126 result = find_attribute_namespace (ns);
kono
parents: 67
diff changeset
127
kono
parents: 67
diff changeset
128 if (result == NULL)
kono
parents: 67
diff changeset
129 {
kono
parents: 67
diff changeset
130 /* We don't have any namespace NS yet. Create one. */
kono
parents: 67
diff changeset
131 scoped_attributes sa;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
132
111
kono
parents: 67
diff changeset
133 if (attributes_table.is_empty ())
kono
parents: 67
diff changeset
134 attributes_table.create (64);
kono
parents: 67
diff changeset
135
kono
parents: 67
diff changeset
136 memset (&sa, 0, sizeof (sa));
kono
parents: 67
diff changeset
137 sa.ns = ns;
kono
parents: 67
diff changeset
138 sa.attributes.create (64);
kono
parents: 67
diff changeset
139 result = attributes_table.safe_push (sa);
kono
parents: 67
diff changeset
140 result->attribute_hash = new hash_table<attribute_hasher> (200);
kono
parents: 67
diff changeset
141 }
kono
parents: 67
diff changeset
142
kono
parents: 67
diff changeset
143 /* Really add the attributes to their namespace now. */
kono
parents: 67
diff changeset
144 for (unsigned i = 0; attributes[i].name != NULL; ++i)
kono
parents: 67
diff changeset
145 {
kono
parents: 67
diff changeset
146 result->attributes.safe_push (attributes[i]);
kono
parents: 67
diff changeset
147 register_scoped_attribute (&attributes[i], result);
kono
parents: 67
diff changeset
148 }
kono
parents: 67
diff changeset
149
kono
parents: 67
diff changeset
150 gcc_assert (result != NULL);
kono
parents: 67
diff changeset
151
kono
parents: 67
diff changeset
152 return result;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
153 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
154
111
kono
parents: 67
diff changeset
155 /* Return the namespace which name is NS, NULL if none exist. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
156
111
kono
parents: 67
diff changeset
157 static scoped_attributes*
kono
parents: 67
diff changeset
158 find_attribute_namespace (const char* ns)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
159 {
111
kono
parents: 67
diff changeset
160 unsigned ix;
kono
parents: 67
diff changeset
161 scoped_attributes *iter;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
162
111
kono
parents: 67
diff changeset
163 FOR_EACH_VEC_ELT (attributes_table, ix, iter)
kono
parents: 67
diff changeset
164 if (ns == iter->ns
kono
parents: 67
diff changeset
165 || (iter->ns != NULL
kono
parents: 67
diff changeset
166 && ns != NULL
kono
parents: 67
diff changeset
167 && !strcmp (iter->ns, ns)))
kono
parents: 67
diff changeset
168 return iter;
kono
parents: 67
diff changeset
169 return NULL;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
170 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
171
111
kono
parents: 67
diff changeset
172 /* Make some sanity checks on the attribute tables. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
173
111
kono
parents: 67
diff changeset
174 static void
kono
parents: 67
diff changeset
175 check_attribute_tables (void)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
176 {
111
kono
parents: 67
diff changeset
177 for (size_t i = 0; i < ARRAY_SIZE (attribute_tables); i++)
kono
parents: 67
diff changeset
178 for (size_t j = 0; attribute_tables[i][j].name != NULL; j++)
kono
parents: 67
diff changeset
179 {
kono
parents: 67
diff changeset
180 /* The name must not begin and end with __. */
kono
parents: 67
diff changeset
181 const char *name = attribute_tables[i][j].name;
kono
parents: 67
diff changeset
182 int len = strlen (name);
kono
parents: 67
diff changeset
183
kono
parents: 67
diff changeset
184 gcc_assert (!(name[0] == '_' && name[1] == '_'
kono
parents: 67
diff changeset
185 && name[len - 1] == '_' && name[len - 2] == '_'));
kono
parents: 67
diff changeset
186
kono
parents: 67
diff changeset
187 /* The minimum and maximum lengths must be consistent. */
kono
parents: 67
diff changeset
188 gcc_assert (attribute_tables[i][j].min_length >= 0);
kono
parents: 67
diff changeset
189
kono
parents: 67
diff changeset
190 gcc_assert (attribute_tables[i][j].max_length == -1
kono
parents: 67
diff changeset
191 || (attribute_tables[i][j].max_length
kono
parents: 67
diff changeset
192 >= attribute_tables[i][j].min_length));
kono
parents: 67
diff changeset
193
kono
parents: 67
diff changeset
194 /* An attribute cannot require both a DECL and a TYPE. */
kono
parents: 67
diff changeset
195 gcc_assert (!attribute_tables[i][j].decl_required
kono
parents: 67
diff changeset
196 || !attribute_tables[i][j].type_required);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
197
111
kono
parents: 67
diff changeset
198 /* If an attribute requires a function type, in particular
kono
parents: 67
diff changeset
199 it requires a type. */
kono
parents: 67
diff changeset
200 gcc_assert (!attribute_tables[i][j].function_type_required
kono
parents: 67
diff changeset
201 || attribute_tables[i][j].type_required);
kono
parents: 67
diff changeset
202 }
kono
parents: 67
diff changeset
203
kono
parents: 67
diff changeset
204 /* Check that each name occurs just once in each table. */
kono
parents: 67
diff changeset
205 for (size_t i = 0; i < ARRAY_SIZE (attribute_tables); i++)
kono
parents: 67
diff changeset
206 for (size_t j = 0; attribute_tables[i][j].name != NULL; j++)
kono
parents: 67
diff changeset
207 for (size_t k = j + 1; attribute_tables[i][k].name != NULL; k++)
kono
parents: 67
diff changeset
208 gcc_assert (strcmp (attribute_tables[i][j].name,
kono
parents: 67
diff changeset
209 attribute_tables[i][k].name));
kono
parents: 67
diff changeset
210
kono
parents: 67
diff changeset
211 /* Check that no name occurs in more than one table. Names that
kono
parents: 67
diff changeset
212 begin with '*' are exempt, and may be overridden. */
kono
parents: 67
diff changeset
213 for (size_t i = 0; i < ARRAY_SIZE (attribute_tables); i++)
kono
parents: 67
diff changeset
214 for (size_t j = i + 1; j < ARRAY_SIZE (attribute_tables); j++)
kono
parents: 67
diff changeset
215 for (size_t k = 0; attribute_tables[i][k].name != NULL; k++)
kono
parents: 67
diff changeset
216 for (size_t l = 0; attribute_tables[j][l].name != NULL; l++)
kono
parents: 67
diff changeset
217 gcc_assert (attribute_tables[i][k].name[0] == '*'
kono
parents: 67
diff changeset
218 || strcmp (attribute_tables[i][k].name,
kono
parents: 67
diff changeset
219 attribute_tables[j][l].name));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
220 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
221
111
kono
parents: 67
diff changeset
222 /* Initialize attribute tables, and make some sanity checks if checking is
kono
parents: 67
diff changeset
223 enabled. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
224
111
kono
parents: 67
diff changeset
225 void
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
226 init_attributes (void)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
227 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
228 size_t i;
111
kono
parents: 67
diff changeset
229
kono
parents: 67
diff changeset
230 if (attributes_initialized)
kono
parents: 67
diff changeset
231 return;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
232
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
233 attribute_tables[0] = lang_hooks.common_attribute_table;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
234 attribute_tables[1] = lang_hooks.attribute_table;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
235 attribute_tables[2] = lang_hooks.format_attribute_table;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
236 attribute_tables[3] = targetm.attribute_table;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
237
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
238 /* Translate NULL pointers to pointers to the empty table. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
239 for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
240 if (attribute_tables[i] == NULL)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
241 attribute_tables[i] = empty_attribute_table;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
242
111
kono
parents: 67
diff changeset
243 if (flag_checking)
kono
parents: 67
diff changeset
244 check_attribute_tables ();
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
245
111
kono
parents: 67
diff changeset
246 for (i = 0; i < ARRAY_SIZE (attribute_tables); ++i)
kono
parents: 67
diff changeset
247 /* Put all the GNU attributes into the "gnu" namespace. */
kono
parents: 67
diff changeset
248 register_scoped_attributes (attribute_tables[i], "gnu");
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
249
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
250 invoke_plugin_callbacks (PLUGIN_ATTRIBUTES, NULL);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
251 attributes_initialized = true;
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
252 }
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
253
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
254 /* Insert a single ATTR into the attribute table. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
255
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
256 void
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
257 register_attribute (const struct attribute_spec *attr)
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
258 {
111
kono
parents: 67
diff changeset
259 register_scoped_attribute (attr, find_attribute_namespace ("gnu"));
kono
parents: 67
diff changeset
260 }
kono
parents: 67
diff changeset
261
kono
parents: 67
diff changeset
262 /* Insert a single attribute ATTR into a namespace of attributes. */
kono
parents: 67
diff changeset
263
kono
parents: 67
diff changeset
264 static void
kono
parents: 67
diff changeset
265 register_scoped_attribute (const struct attribute_spec *attr,
kono
parents: 67
diff changeset
266 scoped_attributes *name_space)
kono
parents: 67
diff changeset
267 {
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
268 struct substring str;
111
kono
parents: 67
diff changeset
269 attribute_spec **slot;
kono
parents: 67
diff changeset
270
kono
parents: 67
diff changeset
271 gcc_assert (attr != NULL && name_space != NULL);
kono
parents: 67
diff changeset
272
kono
parents: 67
diff changeset
273 gcc_assert (name_space->attribute_hash);
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
274
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
275 str.str = attr->name;
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
276 str.length = strlen (str.str);
111
kono
parents: 67
diff changeset
277
kono
parents: 67
diff changeset
278 /* Attribute names in the table must be in the form 'text' and not
kono
parents: 67
diff changeset
279 in the form '__text__'. */
kono
parents: 67
diff changeset
280 gcc_assert (str.length > 0 && str.str[0] != '_');
kono
parents: 67
diff changeset
281
kono
parents: 67
diff changeset
282 slot = name_space->attribute_hash
kono
parents: 67
diff changeset
283 ->find_slot_with_hash (&str, substring_hash (str.str, str.length),
kono
parents: 67
diff changeset
284 INSERT);
kono
parents: 67
diff changeset
285 gcc_assert (!*slot || attr->name[0] == '*');
kono
parents: 67
diff changeset
286 *slot = CONST_CAST (struct attribute_spec *, attr);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
287 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
288
111
kono
parents: 67
diff changeset
289 /* Return the spec for the scoped attribute with namespace NS and
kono
parents: 67
diff changeset
290 name NAME. */
kono
parents: 67
diff changeset
291
kono
parents: 67
diff changeset
292 static const struct attribute_spec *
kono
parents: 67
diff changeset
293 lookup_scoped_attribute_spec (const_tree ns, const_tree name)
kono
parents: 67
diff changeset
294 {
kono
parents: 67
diff changeset
295 struct substring attr;
kono
parents: 67
diff changeset
296 scoped_attributes *attrs;
kono
parents: 67
diff changeset
297
kono
parents: 67
diff changeset
298 const char *ns_str = (ns != NULL_TREE) ? IDENTIFIER_POINTER (ns): NULL;
kono
parents: 67
diff changeset
299
kono
parents: 67
diff changeset
300 attrs = find_attribute_namespace (ns_str);
kono
parents: 67
diff changeset
301
kono
parents: 67
diff changeset
302 if (attrs == NULL)
kono
parents: 67
diff changeset
303 return NULL;
kono
parents: 67
diff changeset
304
kono
parents: 67
diff changeset
305 attr.str = IDENTIFIER_POINTER (name);
kono
parents: 67
diff changeset
306 attr.length = IDENTIFIER_LENGTH (name);
kono
parents: 67
diff changeset
307 extract_attribute_substring (&attr);
kono
parents: 67
diff changeset
308 return attrs->attribute_hash->find_with_hash (&attr,
kono
parents: 67
diff changeset
309 substring_hash (attr.str,
kono
parents: 67
diff changeset
310 attr.length));
kono
parents: 67
diff changeset
311 }
kono
parents: 67
diff changeset
312
kono
parents: 67
diff changeset
313 /* Return the spec for the attribute named NAME. If NAME is a TREE_LIST,
kono
parents: 67
diff changeset
314 it also specifies the attribute namespace. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
315
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
316 const struct attribute_spec *
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
317 lookup_attribute_spec (const_tree name)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
318 {
111
kono
parents: 67
diff changeset
319 tree ns;
kono
parents: 67
diff changeset
320 if (TREE_CODE (name) == TREE_LIST)
kono
parents: 67
diff changeset
321 {
kono
parents: 67
diff changeset
322 ns = TREE_PURPOSE (name);
kono
parents: 67
diff changeset
323 name = TREE_VALUE (name);
kono
parents: 67
diff changeset
324 }
kono
parents: 67
diff changeset
325 else
kono
parents: 67
diff changeset
326 ns = get_identifier ("gnu");
kono
parents: 67
diff changeset
327 return lookup_scoped_attribute_spec (ns, name);
kono
parents: 67
diff changeset
328 }
kono
parents: 67
diff changeset
329
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
330
111
kono
parents: 67
diff changeset
331 /* Return the namespace of the attribute ATTR. This accessor works on
kono
parents: 67
diff changeset
332 GNU and C++11 (scoped) attributes. On GNU attributes,
kono
parents: 67
diff changeset
333 it returns an identifier tree for the string "gnu".
kono
parents: 67
diff changeset
334
kono
parents: 67
diff changeset
335 Please read the comments of cxx11_attribute_p to understand the
kono
parents: 67
diff changeset
336 format of attributes. */
kono
parents: 67
diff changeset
337
kono
parents: 67
diff changeset
338 static tree
kono
parents: 67
diff changeset
339 get_attribute_namespace (const_tree attr)
kono
parents: 67
diff changeset
340 {
kono
parents: 67
diff changeset
341 if (cxx11_attribute_p (attr))
kono
parents: 67
diff changeset
342 return TREE_PURPOSE (TREE_PURPOSE (attr));
kono
parents: 67
diff changeset
343 return get_identifier ("gnu");
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
344 }
111
kono
parents: 67
diff changeset
345
kono
parents: 67
diff changeset
346
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
347 /* Process the attributes listed in ATTRIBUTES and install them in *NODE,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
348 which is either a DECL (including a TYPE_DECL) or a TYPE. If a DECL,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
349 it should be modified in place; if a TYPE, a copy should be created
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
350 unless ATTR_FLAG_TYPE_IN_PLACE is set in FLAGS. FLAGS gives further
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
351 information, in the form of a bitwise OR of flags in enum attribute_flags
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
352 from tree.h. Depending on these flags, some attributes may be
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
353 returned to be applied at a later stage (for example, to apply
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
354 a decl attribute to the declaration rather than to its type). */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
355
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
356 tree
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
357 decl_attributes (tree *node, tree attributes, int flags)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
358 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
359 tree a;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
360 tree returned_attrs = NULL_TREE;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
361
111
kono
parents: 67
diff changeset
362 if (TREE_TYPE (*node) == error_mark_node || attributes == error_mark_node)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
363 return NULL_TREE;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
364
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
365 if (!attributes_initialized)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
366 init_attributes ();
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
367
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
368 /* If this is a function and the user used #pragma GCC optimize, add the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
369 options to the attribute((optimize(...))) list. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
370 if (TREE_CODE (*node) == FUNCTION_DECL && current_optimize_pragma)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
371 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
372 tree cur_attr = lookup_attribute ("optimize", attributes);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
373 tree opts = copy_list (current_optimize_pragma);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
374
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
375 if (! cur_attr)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
376 attributes
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
377 = tree_cons (get_identifier ("optimize"), opts, attributes);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
378 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
379 TREE_VALUE (cur_attr) = chainon (opts, TREE_VALUE (cur_attr));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
380 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
381
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
382 if (TREE_CODE (*node) == FUNCTION_DECL
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
383 && optimization_current_node != optimization_default_node
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
384 && !DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
385 DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node) = optimization_current_node;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
386
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
387 /* If this is a function and the user used #pragma GCC target, add the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
388 options to the attribute((target(...))) list. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
389 if (TREE_CODE (*node) == FUNCTION_DECL
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
390 && current_target_pragma
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
391 && targetm.target_option.valid_attribute_p (*node, NULL_TREE,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
392 current_target_pragma, 0))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
393 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
394 tree cur_attr = lookup_attribute ("target", attributes);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
395 tree opts = copy_list (current_target_pragma);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
396
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
397 if (! cur_attr)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
398 attributes = tree_cons (get_identifier ("target"), opts, attributes);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
399 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
400 TREE_VALUE (cur_attr) = chainon (opts, TREE_VALUE (cur_attr));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
401 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
402
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
403 /* A "naked" function attribute implies "noinline" and "noclone" for
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
404 those targets that support it. */
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
405 if (TREE_CODE (*node) == FUNCTION_DECL
111
kono
parents: 67
diff changeset
406 && attributes
kono
parents: 67
diff changeset
407 && lookup_attribute ("naked", attributes) != NULL
kono
parents: 67
diff changeset
408 && lookup_attribute_spec (get_identifier ("naked")))
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
409 {
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
410 if (lookup_attribute ("noinline", attributes) == NULL)
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
411 attributes = tree_cons (get_identifier ("noinline"), NULL, attributes);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
412
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
413 if (lookup_attribute ("noclone", attributes) == NULL)
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
414 attributes = tree_cons (get_identifier ("noclone"), NULL, attributes);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
415 }
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
416
111
kono
parents: 67
diff changeset
417 /* A "noipa" function attribute implies "noinline", "noclone" and "no_icf"
kono
parents: 67
diff changeset
418 for those targets that support it. */
kono
parents: 67
diff changeset
419 if (TREE_CODE (*node) == FUNCTION_DECL
kono
parents: 67
diff changeset
420 && attributes
kono
parents: 67
diff changeset
421 && lookup_attribute ("noipa", attributes) != NULL
kono
parents: 67
diff changeset
422 && lookup_attribute_spec (get_identifier ("noipa")))
kono
parents: 67
diff changeset
423 {
kono
parents: 67
diff changeset
424 if (lookup_attribute ("noinline", attributes) == NULL)
kono
parents: 67
diff changeset
425 attributes = tree_cons (get_identifier ("noinline"), NULL, attributes);
kono
parents: 67
diff changeset
426
kono
parents: 67
diff changeset
427 if (lookup_attribute ("noclone", attributes) == NULL)
kono
parents: 67
diff changeset
428 attributes = tree_cons (get_identifier ("noclone"), NULL, attributes);
kono
parents: 67
diff changeset
429
kono
parents: 67
diff changeset
430 if (lookup_attribute ("no_icf", attributes) == NULL)
kono
parents: 67
diff changeset
431 attributes = tree_cons (get_identifier ("no_icf"), NULL, attributes);
kono
parents: 67
diff changeset
432 }
kono
parents: 67
diff changeset
433
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
434 targetm.insert_attributes (*node, &attributes);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
435
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
436 for (a = attributes; a; a = TREE_CHAIN (a))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
437 {
111
kono
parents: 67
diff changeset
438 tree ns = get_attribute_namespace (a);
kono
parents: 67
diff changeset
439 tree name = get_attribute_name (a);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
440 tree args = TREE_VALUE (a);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
441 tree *anode = node;
111
kono
parents: 67
diff changeset
442 const struct attribute_spec *spec =
kono
parents: 67
diff changeset
443 lookup_scoped_attribute_spec (ns, name);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
444 bool no_add_attrs = 0;
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
445 int fn_ptr_quals = 0;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
446 tree fn_ptr_tmp = NULL_TREE;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
447
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
448 if (spec == NULL)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
449 {
111
kono
parents: 67
diff changeset
450 if (!(flags & (int) ATTR_FLAG_BUILT_IN))
kono
parents: 67
diff changeset
451 {
kono
parents: 67
diff changeset
452 if (ns == NULL_TREE || !cxx11_attribute_p (a))
kono
parents: 67
diff changeset
453 warning (OPT_Wattributes, "%qE attribute directive ignored",
kono
parents: 67
diff changeset
454 name);
kono
parents: 67
diff changeset
455 else
kono
parents: 67
diff changeset
456 warning (OPT_Wattributes,
kono
parents: 67
diff changeset
457 "%<%E::%E%> scoped attribute directive ignored",
kono
parents: 67
diff changeset
458 ns, name);
kono
parents: 67
diff changeset
459 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
460 continue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
461 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
462 else if (list_length (args) < spec->min_length
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
463 || (spec->max_length >= 0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
464 && list_length (args) > spec->max_length))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
465 {
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
466 error ("wrong number of arguments specified for %qE attribute",
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
467 name);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
468 continue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
469 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
470 gcc_assert (is_attribute_p (spec->name, name));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
471
111
kono
parents: 67
diff changeset
472 if (TYPE_P (*node)
kono
parents: 67
diff changeset
473 && cxx11_attribute_p (a)
kono
parents: 67
diff changeset
474 && !(flags & ATTR_FLAG_TYPE_IN_PLACE))
kono
parents: 67
diff changeset
475 {
kono
parents: 67
diff changeset
476 /* This is a c++11 attribute that appertains to a
kono
parents: 67
diff changeset
477 type-specifier, outside of the definition of, a class
kono
parents: 67
diff changeset
478 type. Ignore it. */
kono
parents: 67
diff changeset
479 if (warning (OPT_Wattributes, "attribute ignored"))
kono
parents: 67
diff changeset
480 inform (input_location,
kono
parents: 67
diff changeset
481 "an attribute that appertains to a type-specifier "
kono
parents: 67
diff changeset
482 "is ignored");
kono
parents: 67
diff changeset
483 continue;
kono
parents: 67
diff changeset
484 }
kono
parents: 67
diff changeset
485
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
486 if (spec->decl_required && !DECL_P (*anode))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
487 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
488 if (flags & ((int) ATTR_FLAG_DECL_NEXT
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
489 | (int) ATTR_FLAG_FUNCTION_NEXT
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
490 | (int) ATTR_FLAG_ARRAY_NEXT))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
491 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
492 /* Pass on this attribute to be tried again. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
493 returned_attrs = tree_cons (name, args, returned_attrs);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
494 continue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
495 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
496 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
497 {
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
498 warning (OPT_Wattributes, "%qE attribute does not apply to types",
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
499 name);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
500 continue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
501 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
502 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
503
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
504 /* If we require a type, but were passed a decl, set up to make a
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
505 new type and update the one in the decl. ATTR_FLAG_TYPE_IN_PLACE
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
506 would have applied if we'd been passed a type, but we cannot modify
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
507 the decl's type in place here. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
508 if (spec->type_required && DECL_P (*anode))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
509 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
510 anode = &TREE_TYPE (*anode);
111
kono
parents: 67
diff changeset
511 flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
512 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
513
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
514 if (spec->function_type_required && TREE_CODE (*anode) != FUNCTION_TYPE
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
515 && TREE_CODE (*anode) != METHOD_TYPE)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
516 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
517 if (TREE_CODE (*anode) == POINTER_TYPE
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
518 && (TREE_CODE (TREE_TYPE (*anode)) == FUNCTION_TYPE
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
519 || TREE_CODE (TREE_TYPE (*anode)) == METHOD_TYPE))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
520 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
521 /* OK, this is a bit convoluted. We can't just make a copy
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
522 of the pointer type and modify its TREE_TYPE, because if
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
523 we change the attributes of the target type the pointer
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
524 type needs to have a different TYPE_MAIN_VARIANT. So we
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
525 pull out the target type now, frob it as appropriate, and
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
526 rebuild the pointer type later.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
527
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
528 This would all be simpler if attributes were part of the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
529 declarator, grumble grumble. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
530 fn_ptr_tmp = TREE_TYPE (*anode);
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
531 fn_ptr_quals = TYPE_QUALS (*anode);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
532 anode = &fn_ptr_tmp;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
533 flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
534 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
535 else if (flags & (int) ATTR_FLAG_FUNCTION_NEXT)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
536 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
537 /* Pass on this attribute to be tried again. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
538 returned_attrs = tree_cons (name, args, returned_attrs);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
539 continue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
540 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
541
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
542 if (TREE_CODE (*anode) != FUNCTION_TYPE
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
543 && TREE_CODE (*anode) != METHOD_TYPE)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
544 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
545 warning (OPT_Wattributes,
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
546 "%qE attribute only applies to function types",
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
547 name);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
548 continue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
549 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
550 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
551
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
552 if (TYPE_P (*anode)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
553 && (flags & (int) ATTR_FLAG_TYPE_IN_PLACE)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
554 && TYPE_SIZE (*anode) != NULL_TREE)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
555 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
556 warning (OPT_Wattributes, "type attributes ignored after type is already defined");
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
557 continue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
558 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
559
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
560 if (spec->handler != NULL)
111
kono
parents: 67
diff changeset
561 {
kono
parents: 67
diff changeset
562 int cxx11_flag =
kono
parents: 67
diff changeset
563 cxx11_attribute_p (a) ? ATTR_FLAG_CXX11 : 0;
kono
parents: 67
diff changeset
564
kono
parents: 67
diff changeset
565 returned_attrs = chainon ((*spec->handler) (anode, name, args,
kono
parents: 67
diff changeset
566 flags|cxx11_flag,
kono
parents: 67
diff changeset
567 &no_add_attrs),
kono
parents: 67
diff changeset
568 returned_attrs);
kono
parents: 67
diff changeset
569 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
570
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
571 /* Layout the decl in case anything changed. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
572 if (spec->type_required && DECL_P (*node)
111
kono
parents: 67
diff changeset
573 && (VAR_P (*node)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
574 || TREE_CODE (*node) == PARM_DECL
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
575 || TREE_CODE (*node) == RESULT_DECL))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
576 relayout_decl (*node);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
577
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
578 if (!no_add_attrs)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
579 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
580 tree old_attrs;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
581 tree a;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
582
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
583 if (DECL_P (*anode))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
584 old_attrs = DECL_ATTRIBUTES (*anode);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
585 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
586 old_attrs = TYPE_ATTRIBUTES (*anode);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
587
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
588 for (a = lookup_attribute (spec->name, old_attrs);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
589 a != NULL_TREE;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
590 a = lookup_attribute (spec->name, TREE_CHAIN (a)))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
591 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
592 if (simple_cst_equal (TREE_VALUE (a), args) == 1)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
593 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
594 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
595
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
596 if (a == NULL_TREE)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
597 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
598 /* This attribute isn't already in the list. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
599 if (DECL_P (*anode))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
600 DECL_ATTRIBUTES (*anode) = tree_cons (name, args, old_attrs);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
601 else if (flags & (int) ATTR_FLAG_TYPE_IN_PLACE)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
602 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
603 TYPE_ATTRIBUTES (*anode) = tree_cons (name, args, old_attrs);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
604 /* If this is the main variant, also push the attributes
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
605 out to the other variants. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
606 if (*anode == TYPE_MAIN_VARIANT (*anode))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
607 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
608 tree variant;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
609 for (variant = *anode; variant;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
610 variant = TYPE_NEXT_VARIANT (variant))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
611 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
612 if (TYPE_ATTRIBUTES (variant) == old_attrs)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
613 TYPE_ATTRIBUTES (variant)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
614 = TYPE_ATTRIBUTES (*anode);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
615 else if (!lookup_attribute
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
616 (spec->name, TYPE_ATTRIBUTES (variant)))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
617 TYPE_ATTRIBUTES (variant) = tree_cons
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
618 (name, args, TYPE_ATTRIBUTES (variant));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
619 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
620 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
621 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
622 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
623 *anode = build_type_attribute_variant (*anode,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
624 tree_cons (name, args,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
625 old_attrs));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
626 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
627 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
628
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
629 if (fn_ptr_tmp)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
630 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
631 /* Rebuild the function pointer type and put it in the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
632 appropriate place. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
633 fn_ptr_tmp = build_pointer_type (fn_ptr_tmp);
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
634 if (fn_ptr_quals)
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
635 fn_ptr_tmp = build_qualified_type (fn_ptr_tmp, fn_ptr_quals);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
636 if (DECL_P (*node))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
637 TREE_TYPE (*node) = fn_ptr_tmp;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
638 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
639 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
640 gcc_assert (TREE_CODE (*node) == POINTER_TYPE);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
641 *node = fn_ptr_tmp;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
642 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
643 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
644 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
645
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
646 return returned_attrs;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
647 }
111
kono
parents: 67
diff changeset
648
kono
parents: 67
diff changeset
649 /* Return TRUE iff ATTR has been parsed by the front-end as a C++-11
kono
parents: 67
diff changeset
650 attribute.
kono
parents: 67
diff changeset
651
kono
parents: 67
diff changeset
652 When G++ parses a C++11 attribute, it is represented as
kono
parents: 67
diff changeset
653 a TREE_LIST which TREE_PURPOSE is itself a TREE_LIST. TREE_PURPOSE
kono
parents: 67
diff changeset
654 (TREE_PURPOSE (ATTR)) is the namespace of the attribute, and the
kono
parents: 67
diff changeset
655 TREE_VALUE (TREE_PURPOSE (ATTR)) is its non-qualified name. Please
kono
parents: 67
diff changeset
656 use get_attribute_namespace and get_attribute_name to retrieve the
kono
parents: 67
diff changeset
657 namespace and name of the attribute, as these accessors work with
kono
parents: 67
diff changeset
658 GNU attributes as well. */
kono
parents: 67
diff changeset
659
kono
parents: 67
diff changeset
660 bool
kono
parents: 67
diff changeset
661 cxx11_attribute_p (const_tree attr)
kono
parents: 67
diff changeset
662 {
kono
parents: 67
diff changeset
663 if (attr == NULL_TREE
kono
parents: 67
diff changeset
664 || TREE_CODE (attr) != TREE_LIST)
kono
parents: 67
diff changeset
665 return false;
kono
parents: 67
diff changeset
666
kono
parents: 67
diff changeset
667 return (TREE_CODE (TREE_PURPOSE (attr)) == TREE_LIST);
kono
parents: 67
diff changeset
668 }
kono
parents: 67
diff changeset
669
kono
parents: 67
diff changeset
670 /* Return the name of the attribute ATTR. This accessor works on GNU
kono
parents: 67
diff changeset
671 and C++11 (scoped) attributes.
kono
parents: 67
diff changeset
672
kono
parents: 67
diff changeset
673 Please read the comments of cxx11_attribute_p to understand the
kono
parents: 67
diff changeset
674 format of attributes. */
kono
parents: 67
diff changeset
675
kono
parents: 67
diff changeset
676 tree
kono
parents: 67
diff changeset
677 get_attribute_name (const_tree attr)
kono
parents: 67
diff changeset
678 {
kono
parents: 67
diff changeset
679 if (cxx11_attribute_p (attr))
kono
parents: 67
diff changeset
680 return TREE_VALUE (TREE_PURPOSE (attr));
kono
parents: 67
diff changeset
681 return TREE_PURPOSE (attr);
kono
parents: 67
diff changeset
682 }
kono
parents: 67
diff changeset
683
kono
parents: 67
diff changeset
684 /* Subroutine of set_method_tm_attributes. Apply TM attribute ATTR
kono
parents: 67
diff changeset
685 to the method FNDECL. */
kono
parents: 67
diff changeset
686
kono
parents: 67
diff changeset
687 void
kono
parents: 67
diff changeset
688 apply_tm_attr (tree fndecl, tree attr)
kono
parents: 67
diff changeset
689 {
kono
parents: 67
diff changeset
690 decl_attributes (&TREE_TYPE (fndecl), tree_cons (attr, NULL, NULL), 0);
kono
parents: 67
diff changeset
691 }
kono
parents: 67
diff changeset
692
kono
parents: 67
diff changeset
693 /* Makes a function attribute of the form NAME(ARG_NAME) and chains
kono
parents: 67
diff changeset
694 it to CHAIN. */
kono
parents: 67
diff changeset
695
kono
parents: 67
diff changeset
696 tree
kono
parents: 67
diff changeset
697 make_attribute (const char *name, const char *arg_name, tree chain)
kono
parents: 67
diff changeset
698 {
kono
parents: 67
diff changeset
699 tree attr_name;
kono
parents: 67
diff changeset
700 tree attr_arg_name;
kono
parents: 67
diff changeset
701 tree attr_args;
kono
parents: 67
diff changeset
702 tree attr;
kono
parents: 67
diff changeset
703
kono
parents: 67
diff changeset
704 attr_name = get_identifier (name);
kono
parents: 67
diff changeset
705 attr_arg_name = build_string (strlen (arg_name), arg_name);
kono
parents: 67
diff changeset
706 attr_args = tree_cons (NULL_TREE, attr_arg_name, NULL_TREE);
kono
parents: 67
diff changeset
707 attr = tree_cons (attr_name, attr_args, chain);
kono
parents: 67
diff changeset
708 return attr;
kono
parents: 67
diff changeset
709 }
kono
parents: 67
diff changeset
710
kono
parents: 67
diff changeset
711
kono
parents: 67
diff changeset
712 /* Common functions used for target clone support. */
kono
parents: 67
diff changeset
713
kono
parents: 67
diff changeset
714 /* Comparator function to be used in qsort routine to sort attribute
kono
parents: 67
diff changeset
715 specification strings to "target". */
kono
parents: 67
diff changeset
716
kono
parents: 67
diff changeset
717 static int
kono
parents: 67
diff changeset
718 attr_strcmp (const void *v1, const void *v2)
kono
parents: 67
diff changeset
719 {
kono
parents: 67
diff changeset
720 const char *c1 = *(char *const*)v1;
kono
parents: 67
diff changeset
721 const char *c2 = *(char *const*)v2;
kono
parents: 67
diff changeset
722 return strcmp (c1, c2);
kono
parents: 67
diff changeset
723 }
kono
parents: 67
diff changeset
724
kono
parents: 67
diff changeset
725 /* ARGLIST is the argument to target attribute. This function tokenizes
kono
parents: 67
diff changeset
726 the comma separated arguments, sorts them and returns a string which
kono
parents: 67
diff changeset
727 is a unique identifier for the comma separated arguments. It also
kono
parents: 67
diff changeset
728 replaces non-identifier characters "=,-" with "_". */
kono
parents: 67
diff changeset
729
kono
parents: 67
diff changeset
730 char *
kono
parents: 67
diff changeset
731 sorted_attr_string (tree arglist)
kono
parents: 67
diff changeset
732 {
kono
parents: 67
diff changeset
733 tree arg;
kono
parents: 67
diff changeset
734 size_t str_len_sum = 0;
kono
parents: 67
diff changeset
735 char **args = NULL;
kono
parents: 67
diff changeset
736 char *attr_str, *ret_str;
kono
parents: 67
diff changeset
737 char *attr = NULL;
kono
parents: 67
diff changeset
738 unsigned int argnum = 1;
kono
parents: 67
diff changeset
739 unsigned int i;
kono
parents: 67
diff changeset
740
kono
parents: 67
diff changeset
741 for (arg = arglist; arg; arg = TREE_CHAIN (arg))
kono
parents: 67
diff changeset
742 {
kono
parents: 67
diff changeset
743 const char *str = TREE_STRING_POINTER (TREE_VALUE (arg));
kono
parents: 67
diff changeset
744 size_t len = strlen (str);
kono
parents: 67
diff changeset
745 str_len_sum += len + 1;
kono
parents: 67
diff changeset
746 if (arg != arglist)
kono
parents: 67
diff changeset
747 argnum++;
kono
parents: 67
diff changeset
748 for (i = 0; i < strlen (str); i++)
kono
parents: 67
diff changeset
749 if (str[i] == ',')
kono
parents: 67
diff changeset
750 argnum++;
kono
parents: 67
diff changeset
751 }
kono
parents: 67
diff changeset
752
kono
parents: 67
diff changeset
753 attr_str = XNEWVEC (char, str_len_sum);
kono
parents: 67
diff changeset
754 str_len_sum = 0;
kono
parents: 67
diff changeset
755 for (arg = arglist; arg; arg = TREE_CHAIN (arg))
kono
parents: 67
diff changeset
756 {
kono
parents: 67
diff changeset
757 const char *str = TREE_STRING_POINTER (TREE_VALUE (arg));
kono
parents: 67
diff changeset
758 size_t len = strlen (str);
kono
parents: 67
diff changeset
759 memcpy (attr_str + str_len_sum, str, len);
kono
parents: 67
diff changeset
760 attr_str[str_len_sum + len] = TREE_CHAIN (arg) ? ',' : '\0';
kono
parents: 67
diff changeset
761 str_len_sum += len + 1;
kono
parents: 67
diff changeset
762 }
kono
parents: 67
diff changeset
763
kono
parents: 67
diff changeset
764 /* Replace "=,-" with "_". */
kono
parents: 67
diff changeset
765 for (i = 0; i < strlen (attr_str); i++)
kono
parents: 67
diff changeset
766 if (attr_str[i] == '=' || attr_str[i]== '-')
kono
parents: 67
diff changeset
767 attr_str[i] = '_';
kono
parents: 67
diff changeset
768
kono
parents: 67
diff changeset
769 if (argnum == 1)
kono
parents: 67
diff changeset
770 return attr_str;
kono
parents: 67
diff changeset
771
kono
parents: 67
diff changeset
772 args = XNEWVEC (char *, argnum);
kono
parents: 67
diff changeset
773
kono
parents: 67
diff changeset
774 i = 0;
kono
parents: 67
diff changeset
775 attr = strtok (attr_str, ",");
kono
parents: 67
diff changeset
776 while (attr != NULL)
kono
parents: 67
diff changeset
777 {
kono
parents: 67
diff changeset
778 args[i] = attr;
kono
parents: 67
diff changeset
779 i++;
kono
parents: 67
diff changeset
780 attr = strtok (NULL, ",");
kono
parents: 67
diff changeset
781 }
kono
parents: 67
diff changeset
782
kono
parents: 67
diff changeset
783 qsort (args, argnum, sizeof (char *), attr_strcmp);
kono
parents: 67
diff changeset
784
kono
parents: 67
diff changeset
785 ret_str = XNEWVEC (char, str_len_sum);
kono
parents: 67
diff changeset
786 str_len_sum = 0;
kono
parents: 67
diff changeset
787 for (i = 0; i < argnum; i++)
kono
parents: 67
diff changeset
788 {
kono
parents: 67
diff changeset
789 size_t len = strlen (args[i]);
kono
parents: 67
diff changeset
790 memcpy (ret_str + str_len_sum, args[i], len);
kono
parents: 67
diff changeset
791 ret_str[str_len_sum + len] = i < argnum - 1 ? '_' : '\0';
kono
parents: 67
diff changeset
792 str_len_sum += len + 1;
kono
parents: 67
diff changeset
793 }
kono
parents: 67
diff changeset
794
kono
parents: 67
diff changeset
795 XDELETEVEC (args);
kono
parents: 67
diff changeset
796 XDELETEVEC (attr_str);
kono
parents: 67
diff changeset
797 return ret_str;
kono
parents: 67
diff changeset
798 }
kono
parents: 67
diff changeset
799
kono
parents: 67
diff changeset
800
kono
parents: 67
diff changeset
801 /* This function returns true if FN1 and FN2 are versions of the same function,
kono
parents: 67
diff changeset
802 that is, the target strings of the function decls are different. This assumes
kono
parents: 67
diff changeset
803 that FN1 and FN2 have the same signature. */
kono
parents: 67
diff changeset
804
kono
parents: 67
diff changeset
805 bool
kono
parents: 67
diff changeset
806 common_function_versions (tree fn1, tree fn2)
kono
parents: 67
diff changeset
807 {
kono
parents: 67
diff changeset
808 tree attr1, attr2;
kono
parents: 67
diff changeset
809 char *target1, *target2;
kono
parents: 67
diff changeset
810 bool result;
kono
parents: 67
diff changeset
811
kono
parents: 67
diff changeset
812 if (TREE_CODE (fn1) != FUNCTION_DECL
kono
parents: 67
diff changeset
813 || TREE_CODE (fn2) != FUNCTION_DECL)
kono
parents: 67
diff changeset
814 return false;
kono
parents: 67
diff changeset
815
kono
parents: 67
diff changeset
816 attr1 = lookup_attribute ("target", DECL_ATTRIBUTES (fn1));
kono
parents: 67
diff changeset
817 attr2 = lookup_attribute ("target", DECL_ATTRIBUTES (fn2));
kono
parents: 67
diff changeset
818
kono
parents: 67
diff changeset
819 /* At least one function decl should have the target attribute specified. */
kono
parents: 67
diff changeset
820 if (attr1 == NULL_TREE && attr2 == NULL_TREE)
kono
parents: 67
diff changeset
821 return false;
kono
parents: 67
diff changeset
822
kono
parents: 67
diff changeset
823 /* Diagnose missing target attribute if one of the decls is already
kono
parents: 67
diff changeset
824 multi-versioned. */
kono
parents: 67
diff changeset
825 if (attr1 == NULL_TREE || attr2 == NULL_TREE)
kono
parents: 67
diff changeset
826 {
kono
parents: 67
diff changeset
827 if (DECL_FUNCTION_VERSIONED (fn1) || DECL_FUNCTION_VERSIONED (fn2))
kono
parents: 67
diff changeset
828 {
kono
parents: 67
diff changeset
829 if (attr2 != NULL_TREE)
kono
parents: 67
diff changeset
830 {
kono
parents: 67
diff changeset
831 std::swap (fn1, fn2);
kono
parents: 67
diff changeset
832 attr1 = attr2;
kono
parents: 67
diff changeset
833 }
kono
parents: 67
diff changeset
834 error_at (DECL_SOURCE_LOCATION (fn2),
kono
parents: 67
diff changeset
835 "missing %<target%> attribute for multi-versioned %qD",
kono
parents: 67
diff changeset
836 fn2);
kono
parents: 67
diff changeset
837 inform (DECL_SOURCE_LOCATION (fn1),
kono
parents: 67
diff changeset
838 "previous declaration of %qD", fn1);
kono
parents: 67
diff changeset
839 /* Prevent diagnosing of the same error multiple times. */
kono
parents: 67
diff changeset
840 DECL_ATTRIBUTES (fn2)
kono
parents: 67
diff changeset
841 = tree_cons (get_identifier ("target"),
kono
parents: 67
diff changeset
842 copy_node (TREE_VALUE (attr1)),
kono
parents: 67
diff changeset
843 DECL_ATTRIBUTES (fn2));
kono
parents: 67
diff changeset
844 }
kono
parents: 67
diff changeset
845 return false;
kono
parents: 67
diff changeset
846 }
kono
parents: 67
diff changeset
847
kono
parents: 67
diff changeset
848 target1 = sorted_attr_string (TREE_VALUE (attr1));
kono
parents: 67
diff changeset
849 target2 = sorted_attr_string (TREE_VALUE (attr2));
kono
parents: 67
diff changeset
850
kono
parents: 67
diff changeset
851 /* The sorted target strings must be different for fn1 and fn2
kono
parents: 67
diff changeset
852 to be versions. */
kono
parents: 67
diff changeset
853 if (strcmp (target1, target2) == 0)
kono
parents: 67
diff changeset
854 result = false;
kono
parents: 67
diff changeset
855 else
kono
parents: 67
diff changeset
856 result = true;
kono
parents: 67
diff changeset
857
kono
parents: 67
diff changeset
858 XDELETEVEC (target1);
kono
parents: 67
diff changeset
859 XDELETEVEC (target2);
kono
parents: 67
diff changeset
860
kono
parents: 67
diff changeset
861 return result;
kono
parents: 67
diff changeset
862 }
kono
parents: 67
diff changeset
863
kono
parents: 67
diff changeset
864 /* Return a new name by appending SUFFIX to the DECL name. If make_unique
kono
parents: 67
diff changeset
865 is true, append the full path name of the source file. */
kono
parents: 67
diff changeset
866
kono
parents: 67
diff changeset
867 char *
kono
parents: 67
diff changeset
868 make_unique_name (tree decl, const char *suffix, bool make_unique)
kono
parents: 67
diff changeset
869 {
kono
parents: 67
diff changeset
870 char *global_var_name;
kono
parents: 67
diff changeset
871 int name_len;
kono
parents: 67
diff changeset
872 const char *name;
kono
parents: 67
diff changeset
873 const char *unique_name = NULL;
kono
parents: 67
diff changeset
874
kono
parents: 67
diff changeset
875 name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
kono
parents: 67
diff changeset
876
kono
parents: 67
diff changeset
877 /* Get a unique name that can be used globally without any chances
kono
parents: 67
diff changeset
878 of collision at link time. */
kono
parents: 67
diff changeset
879 if (make_unique)
kono
parents: 67
diff changeset
880 unique_name = IDENTIFIER_POINTER (get_file_function_name ("\0"));
kono
parents: 67
diff changeset
881
kono
parents: 67
diff changeset
882 name_len = strlen (name) + strlen (suffix) + 2;
kono
parents: 67
diff changeset
883
kono
parents: 67
diff changeset
884 if (make_unique)
kono
parents: 67
diff changeset
885 name_len += strlen (unique_name) + 1;
kono
parents: 67
diff changeset
886 global_var_name = XNEWVEC (char, name_len);
kono
parents: 67
diff changeset
887
kono
parents: 67
diff changeset
888 /* Use '.' to concatenate names as it is demangler friendly. */
kono
parents: 67
diff changeset
889 if (make_unique)
kono
parents: 67
diff changeset
890 snprintf (global_var_name, name_len, "%s.%s.%s", name, unique_name,
kono
parents: 67
diff changeset
891 suffix);
kono
parents: 67
diff changeset
892 else
kono
parents: 67
diff changeset
893 snprintf (global_var_name, name_len, "%s.%s", name, suffix);
kono
parents: 67
diff changeset
894
kono
parents: 67
diff changeset
895 return global_var_name;
kono
parents: 67
diff changeset
896 }
kono
parents: 67
diff changeset
897
kono
parents: 67
diff changeset
898 /* Make a dispatcher declaration for the multi-versioned function DECL.
kono
parents: 67
diff changeset
899 Calls to DECL function will be replaced with calls to the dispatcher
kono
parents: 67
diff changeset
900 by the front-end. Return the decl created. */
kono
parents: 67
diff changeset
901
kono
parents: 67
diff changeset
902 tree
kono
parents: 67
diff changeset
903 make_dispatcher_decl (const tree decl)
kono
parents: 67
diff changeset
904 {
kono
parents: 67
diff changeset
905 tree func_decl;
kono
parents: 67
diff changeset
906 char *func_name;
kono
parents: 67
diff changeset
907 tree fn_type, func_type;
kono
parents: 67
diff changeset
908
kono
parents: 67
diff changeset
909 func_name = xstrdup (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
kono
parents: 67
diff changeset
910
kono
parents: 67
diff changeset
911 fn_type = TREE_TYPE (decl);
kono
parents: 67
diff changeset
912 func_type = build_function_type (TREE_TYPE (fn_type),
kono
parents: 67
diff changeset
913 TYPE_ARG_TYPES (fn_type));
kono
parents: 67
diff changeset
914
kono
parents: 67
diff changeset
915 func_decl = build_fn_decl (func_name, func_type);
kono
parents: 67
diff changeset
916 XDELETEVEC (func_name);
kono
parents: 67
diff changeset
917 TREE_USED (func_decl) = 1;
kono
parents: 67
diff changeset
918 DECL_CONTEXT (func_decl) = NULL_TREE;
kono
parents: 67
diff changeset
919 DECL_INITIAL (func_decl) = error_mark_node;
kono
parents: 67
diff changeset
920 DECL_ARTIFICIAL (func_decl) = 1;
kono
parents: 67
diff changeset
921 /* Mark this func as external, the resolver will flip it again if
kono
parents: 67
diff changeset
922 it gets generated. */
kono
parents: 67
diff changeset
923 DECL_EXTERNAL (func_decl) = 1;
kono
parents: 67
diff changeset
924 /* This will be of type IFUNCs have to be externally visible. */
kono
parents: 67
diff changeset
925 TREE_PUBLIC (func_decl) = 1;
kono
parents: 67
diff changeset
926
kono
parents: 67
diff changeset
927 return func_decl;
kono
parents: 67
diff changeset
928 }
kono
parents: 67
diff changeset
929
kono
parents: 67
diff changeset
930 /* Returns true if decl is multi-versioned and DECL is the default function,
kono
parents: 67
diff changeset
931 that is it is not tagged with target specific optimization. */
kono
parents: 67
diff changeset
932
kono
parents: 67
diff changeset
933 bool
kono
parents: 67
diff changeset
934 is_function_default_version (const tree decl)
kono
parents: 67
diff changeset
935 {
kono
parents: 67
diff changeset
936 if (TREE_CODE (decl) != FUNCTION_DECL
kono
parents: 67
diff changeset
937 || !DECL_FUNCTION_VERSIONED (decl))
kono
parents: 67
diff changeset
938 return false;
kono
parents: 67
diff changeset
939 tree attr = lookup_attribute ("target", DECL_ATTRIBUTES (decl));
kono
parents: 67
diff changeset
940 gcc_assert (attr);
kono
parents: 67
diff changeset
941 attr = TREE_VALUE (TREE_VALUE (attr));
kono
parents: 67
diff changeset
942 return (TREE_CODE (attr) == STRING_CST
kono
parents: 67
diff changeset
943 && strcmp (TREE_STRING_POINTER (attr), "default") == 0);
kono
parents: 67
diff changeset
944 }
kono
parents: 67
diff changeset
945
kono
parents: 67
diff changeset
946 /* Return a declaration like DDECL except that its DECL_ATTRIBUTES
kono
parents: 67
diff changeset
947 is ATTRIBUTE. */
kono
parents: 67
diff changeset
948
kono
parents: 67
diff changeset
949 tree
kono
parents: 67
diff changeset
950 build_decl_attribute_variant (tree ddecl, tree attribute)
kono
parents: 67
diff changeset
951 {
kono
parents: 67
diff changeset
952 DECL_ATTRIBUTES (ddecl) = attribute;
kono
parents: 67
diff changeset
953 return ddecl;
kono
parents: 67
diff changeset
954 }
kono
parents: 67
diff changeset
955
kono
parents: 67
diff changeset
956 /* Return a type like TTYPE except that its TYPE_ATTRIBUTE
kono
parents: 67
diff changeset
957 is ATTRIBUTE and its qualifiers are QUALS.
kono
parents: 67
diff changeset
958
kono
parents: 67
diff changeset
959 Record such modified types already made so we don't make duplicates. */
kono
parents: 67
diff changeset
960
kono
parents: 67
diff changeset
961 tree
kono
parents: 67
diff changeset
962 build_type_attribute_qual_variant (tree otype, tree attribute, int quals)
kono
parents: 67
diff changeset
963 {
kono
parents: 67
diff changeset
964 tree ttype = otype;
kono
parents: 67
diff changeset
965 if (! attribute_list_equal (TYPE_ATTRIBUTES (ttype), attribute))
kono
parents: 67
diff changeset
966 {
kono
parents: 67
diff changeset
967 tree ntype;
kono
parents: 67
diff changeset
968
kono
parents: 67
diff changeset
969 /* Building a distinct copy of a tagged type is inappropriate; it
kono
parents: 67
diff changeset
970 causes breakage in code that expects there to be a one-to-one
kono
parents: 67
diff changeset
971 relationship between a struct and its fields.
kono
parents: 67
diff changeset
972 build_duplicate_type is another solution (as used in
kono
parents: 67
diff changeset
973 handle_transparent_union_attribute), but that doesn't play well
kono
parents: 67
diff changeset
974 with the stronger C++ type identity model. */
kono
parents: 67
diff changeset
975 if (TREE_CODE (ttype) == RECORD_TYPE
kono
parents: 67
diff changeset
976 || TREE_CODE (ttype) == UNION_TYPE
kono
parents: 67
diff changeset
977 || TREE_CODE (ttype) == QUAL_UNION_TYPE
kono
parents: 67
diff changeset
978 || TREE_CODE (ttype) == ENUMERAL_TYPE)
kono
parents: 67
diff changeset
979 {
kono
parents: 67
diff changeset
980 warning (OPT_Wattributes,
kono
parents: 67
diff changeset
981 "ignoring attributes applied to %qT after definition",
kono
parents: 67
diff changeset
982 TYPE_MAIN_VARIANT (ttype));
kono
parents: 67
diff changeset
983 return build_qualified_type (ttype, quals);
kono
parents: 67
diff changeset
984 }
kono
parents: 67
diff changeset
985
kono
parents: 67
diff changeset
986 ttype = build_qualified_type (ttype, TYPE_UNQUALIFIED);
kono
parents: 67
diff changeset
987 if (lang_hooks.types.copy_lang_qualifiers
kono
parents: 67
diff changeset
988 && otype != TYPE_MAIN_VARIANT (otype))
kono
parents: 67
diff changeset
989 ttype = (lang_hooks.types.copy_lang_qualifiers
kono
parents: 67
diff changeset
990 (ttype, TYPE_MAIN_VARIANT (otype)));
kono
parents: 67
diff changeset
991
kono
parents: 67
diff changeset
992 ntype = build_distinct_type_copy (ttype);
kono
parents: 67
diff changeset
993
kono
parents: 67
diff changeset
994 TYPE_ATTRIBUTES (ntype) = attribute;
kono
parents: 67
diff changeset
995
kono
parents: 67
diff changeset
996 hashval_t hash = type_hash_canon_hash (ntype);
kono
parents: 67
diff changeset
997 ntype = type_hash_canon (hash, ntype);
kono
parents: 67
diff changeset
998
kono
parents: 67
diff changeset
999 /* If the target-dependent attributes make NTYPE different from
kono
parents: 67
diff changeset
1000 its canonical type, we will need to use structural equality
kono
parents: 67
diff changeset
1001 checks for this type. */
kono
parents: 67
diff changeset
1002 if (TYPE_STRUCTURAL_EQUALITY_P (ttype)
kono
parents: 67
diff changeset
1003 || !comp_type_attributes (ntype, ttype))
kono
parents: 67
diff changeset
1004 SET_TYPE_STRUCTURAL_EQUALITY (ntype);
kono
parents: 67
diff changeset
1005 else if (TYPE_CANONICAL (ntype) == ntype)
kono
parents: 67
diff changeset
1006 TYPE_CANONICAL (ntype) = TYPE_CANONICAL (ttype);
kono
parents: 67
diff changeset
1007
kono
parents: 67
diff changeset
1008 ttype = build_qualified_type (ntype, quals);
kono
parents: 67
diff changeset
1009 if (lang_hooks.types.copy_lang_qualifiers
kono
parents: 67
diff changeset
1010 && otype != TYPE_MAIN_VARIANT (otype))
kono
parents: 67
diff changeset
1011 ttype = lang_hooks.types.copy_lang_qualifiers (ttype, otype);
kono
parents: 67
diff changeset
1012 }
kono
parents: 67
diff changeset
1013 else if (TYPE_QUALS (ttype) != quals)
kono
parents: 67
diff changeset
1014 ttype = build_qualified_type (ttype, quals);
kono
parents: 67
diff changeset
1015
kono
parents: 67
diff changeset
1016 return ttype;
kono
parents: 67
diff changeset
1017 }
kono
parents: 67
diff changeset
1018
kono
parents: 67
diff changeset
1019 /* Compare two identifier nodes representing attributes.
kono
parents: 67
diff changeset
1020 Return true if they are the same, false otherwise. */
kono
parents: 67
diff changeset
1021
kono
parents: 67
diff changeset
1022 static bool
kono
parents: 67
diff changeset
1023 cmp_attrib_identifiers (const_tree attr1, const_tree attr2)
kono
parents: 67
diff changeset
1024 {
kono
parents: 67
diff changeset
1025 /* Make sure we're dealing with IDENTIFIER_NODEs. */
kono
parents: 67
diff changeset
1026 gcc_checking_assert (TREE_CODE (attr1) == IDENTIFIER_NODE
kono
parents: 67
diff changeset
1027 && TREE_CODE (attr2) == IDENTIFIER_NODE);
kono
parents: 67
diff changeset
1028
kono
parents: 67
diff changeset
1029 /* Identifiers can be compared directly for equality. */
kono
parents: 67
diff changeset
1030 if (attr1 == attr2)
kono
parents: 67
diff changeset
1031 return true;
kono
parents: 67
diff changeset
1032
kono
parents: 67
diff changeset
1033 return cmp_attribs (IDENTIFIER_POINTER (attr1), IDENTIFIER_LENGTH (attr1),
kono
parents: 67
diff changeset
1034 IDENTIFIER_POINTER (attr2), IDENTIFIER_LENGTH (attr2));
kono
parents: 67
diff changeset
1035 }
kono
parents: 67
diff changeset
1036
kono
parents: 67
diff changeset
1037 /* Compare two constructor-element-type constants. Return 1 if the lists
kono
parents: 67
diff changeset
1038 are known to be equal; otherwise return 0. */
kono
parents: 67
diff changeset
1039
kono
parents: 67
diff changeset
1040 static bool
kono
parents: 67
diff changeset
1041 simple_cst_list_equal (const_tree l1, const_tree l2)
kono
parents: 67
diff changeset
1042 {
kono
parents: 67
diff changeset
1043 while (l1 != NULL_TREE && l2 != NULL_TREE)
kono
parents: 67
diff changeset
1044 {
kono
parents: 67
diff changeset
1045 if (simple_cst_equal (TREE_VALUE (l1), TREE_VALUE (l2)) != 1)
kono
parents: 67
diff changeset
1046 return false;
kono
parents: 67
diff changeset
1047
kono
parents: 67
diff changeset
1048 l1 = TREE_CHAIN (l1);
kono
parents: 67
diff changeset
1049 l2 = TREE_CHAIN (l2);
kono
parents: 67
diff changeset
1050 }
kono
parents: 67
diff changeset
1051
kono
parents: 67
diff changeset
1052 return l1 == l2;
kono
parents: 67
diff changeset
1053 }
kono
parents: 67
diff changeset
1054
kono
parents: 67
diff changeset
1055 /* Check if "omp declare simd" attribute arguments, CLAUSES1 and CLAUSES2, are
kono
parents: 67
diff changeset
1056 the same. */
kono
parents: 67
diff changeset
1057
kono
parents: 67
diff changeset
1058 static bool
kono
parents: 67
diff changeset
1059 omp_declare_simd_clauses_equal (tree clauses1, tree clauses2)
kono
parents: 67
diff changeset
1060 {
kono
parents: 67
diff changeset
1061 tree cl1, cl2;
kono
parents: 67
diff changeset
1062 for (cl1 = clauses1, cl2 = clauses2;
kono
parents: 67
diff changeset
1063 cl1 && cl2;
kono
parents: 67
diff changeset
1064 cl1 = OMP_CLAUSE_CHAIN (cl1), cl2 = OMP_CLAUSE_CHAIN (cl2))
kono
parents: 67
diff changeset
1065 {
kono
parents: 67
diff changeset
1066 if (OMP_CLAUSE_CODE (cl1) != OMP_CLAUSE_CODE (cl2))
kono
parents: 67
diff changeset
1067 return false;
kono
parents: 67
diff changeset
1068 if (OMP_CLAUSE_CODE (cl1) != OMP_CLAUSE_SIMDLEN)
kono
parents: 67
diff changeset
1069 {
kono
parents: 67
diff changeset
1070 if (simple_cst_equal (OMP_CLAUSE_DECL (cl1),
kono
parents: 67
diff changeset
1071 OMP_CLAUSE_DECL (cl2)) != 1)
kono
parents: 67
diff changeset
1072 return false;
kono
parents: 67
diff changeset
1073 }
kono
parents: 67
diff changeset
1074 switch (OMP_CLAUSE_CODE (cl1))
kono
parents: 67
diff changeset
1075 {
kono
parents: 67
diff changeset
1076 case OMP_CLAUSE_ALIGNED:
kono
parents: 67
diff changeset
1077 if (simple_cst_equal (OMP_CLAUSE_ALIGNED_ALIGNMENT (cl1),
kono
parents: 67
diff changeset
1078 OMP_CLAUSE_ALIGNED_ALIGNMENT (cl2)) != 1)
kono
parents: 67
diff changeset
1079 return false;
kono
parents: 67
diff changeset
1080 break;
kono
parents: 67
diff changeset
1081 case OMP_CLAUSE_LINEAR:
kono
parents: 67
diff changeset
1082 if (simple_cst_equal (OMP_CLAUSE_LINEAR_STEP (cl1),
kono
parents: 67
diff changeset
1083 OMP_CLAUSE_LINEAR_STEP (cl2)) != 1)
kono
parents: 67
diff changeset
1084 return false;
kono
parents: 67
diff changeset
1085 break;
kono
parents: 67
diff changeset
1086 case OMP_CLAUSE_SIMDLEN:
kono
parents: 67
diff changeset
1087 if (simple_cst_equal (OMP_CLAUSE_SIMDLEN_EXPR (cl1),
kono
parents: 67
diff changeset
1088 OMP_CLAUSE_SIMDLEN_EXPR (cl2)) != 1)
kono
parents: 67
diff changeset
1089 return false;
kono
parents: 67
diff changeset
1090 default:
kono
parents: 67
diff changeset
1091 break;
kono
parents: 67
diff changeset
1092 }
kono
parents: 67
diff changeset
1093 }
kono
parents: 67
diff changeset
1094 return true;
kono
parents: 67
diff changeset
1095 }
kono
parents: 67
diff changeset
1096
kono
parents: 67
diff changeset
1097
kono
parents: 67
diff changeset
1098 /* Compare two attributes for their value identity. Return true if the
kono
parents: 67
diff changeset
1099 attribute values are known to be equal; otherwise return false. */
kono
parents: 67
diff changeset
1100
kono
parents: 67
diff changeset
1101 bool
kono
parents: 67
diff changeset
1102 attribute_value_equal (const_tree attr1, const_tree attr2)
kono
parents: 67
diff changeset
1103 {
kono
parents: 67
diff changeset
1104 if (TREE_VALUE (attr1) == TREE_VALUE (attr2))
kono
parents: 67
diff changeset
1105 return true;
kono
parents: 67
diff changeset
1106
kono
parents: 67
diff changeset
1107 if (TREE_VALUE (attr1) != NULL_TREE
kono
parents: 67
diff changeset
1108 && TREE_CODE (TREE_VALUE (attr1)) == TREE_LIST
kono
parents: 67
diff changeset
1109 && TREE_VALUE (attr2) != NULL_TREE
kono
parents: 67
diff changeset
1110 && TREE_CODE (TREE_VALUE (attr2)) == TREE_LIST)
kono
parents: 67
diff changeset
1111 {
kono
parents: 67
diff changeset
1112 /* Handle attribute format. */
kono
parents: 67
diff changeset
1113 if (is_attribute_p ("format", get_attribute_name (attr1)))
kono
parents: 67
diff changeset
1114 {
kono
parents: 67
diff changeset
1115 attr1 = TREE_VALUE (attr1);
kono
parents: 67
diff changeset
1116 attr2 = TREE_VALUE (attr2);
kono
parents: 67
diff changeset
1117 /* Compare the archetypes (printf/scanf/strftime/...). */
kono
parents: 67
diff changeset
1118 if (!cmp_attrib_identifiers (TREE_VALUE (attr1), TREE_VALUE (attr2)))
kono
parents: 67
diff changeset
1119 return false;
kono
parents: 67
diff changeset
1120 /* Archetypes are the same. Compare the rest. */
kono
parents: 67
diff changeset
1121 return (simple_cst_list_equal (TREE_CHAIN (attr1),
kono
parents: 67
diff changeset
1122 TREE_CHAIN (attr2)) == 1);
kono
parents: 67
diff changeset
1123 }
kono
parents: 67
diff changeset
1124 return (simple_cst_list_equal (TREE_VALUE (attr1),
kono
parents: 67
diff changeset
1125 TREE_VALUE (attr2)) == 1);
kono
parents: 67
diff changeset
1126 }
kono
parents: 67
diff changeset
1127
kono
parents: 67
diff changeset
1128 if (TREE_VALUE (attr1)
kono
parents: 67
diff changeset
1129 && TREE_CODE (TREE_VALUE (attr1)) == OMP_CLAUSE
kono
parents: 67
diff changeset
1130 && TREE_VALUE (attr2)
kono
parents: 67
diff changeset
1131 && TREE_CODE (TREE_VALUE (attr2)) == OMP_CLAUSE)
kono
parents: 67
diff changeset
1132 return omp_declare_simd_clauses_equal (TREE_VALUE (attr1),
kono
parents: 67
diff changeset
1133 TREE_VALUE (attr2));
kono
parents: 67
diff changeset
1134
kono
parents: 67
diff changeset
1135 return (simple_cst_equal (TREE_VALUE (attr1), TREE_VALUE (attr2)) == 1);
kono
parents: 67
diff changeset
1136 }
kono
parents: 67
diff changeset
1137
kono
parents: 67
diff changeset
1138 /* Return 0 if the attributes for two types are incompatible, 1 if they
kono
parents: 67
diff changeset
1139 are compatible, and 2 if they are nearly compatible (which causes a
kono
parents: 67
diff changeset
1140 warning to be generated). */
kono
parents: 67
diff changeset
1141 int
kono
parents: 67
diff changeset
1142 comp_type_attributes (const_tree type1, const_tree type2)
kono
parents: 67
diff changeset
1143 {
kono
parents: 67
diff changeset
1144 const_tree a1 = TYPE_ATTRIBUTES (type1);
kono
parents: 67
diff changeset
1145 const_tree a2 = TYPE_ATTRIBUTES (type2);
kono
parents: 67
diff changeset
1146 const_tree a;
kono
parents: 67
diff changeset
1147
kono
parents: 67
diff changeset
1148 if (a1 == a2)
kono
parents: 67
diff changeset
1149 return 1;
kono
parents: 67
diff changeset
1150 for (a = a1; a != NULL_TREE; a = TREE_CHAIN (a))
kono
parents: 67
diff changeset
1151 {
kono
parents: 67
diff changeset
1152 const struct attribute_spec *as;
kono
parents: 67
diff changeset
1153 const_tree attr;
kono
parents: 67
diff changeset
1154
kono
parents: 67
diff changeset
1155 as = lookup_attribute_spec (get_attribute_name (a));
kono
parents: 67
diff changeset
1156 if (!as || as->affects_type_identity == false)
kono
parents: 67
diff changeset
1157 continue;
kono
parents: 67
diff changeset
1158
kono
parents: 67
diff changeset
1159 attr = lookup_attribute (as->name, CONST_CAST_TREE (a2));
kono
parents: 67
diff changeset
1160 if (!attr || !attribute_value_equal (a, attr))
kono
parents: 67
diff changeset
1161 break;
kono
parents: 67
diff changeset
1162 }
kono
parents: 67
diff changeset
1163 if (!a)
kono
parents: 67
diff changeset
1164 {
kono
parents: 67
diff changeset
1165 for (a = a2; a != NULL_TREE; a = TREE_CHAIN (a))
kono
parents: 67
diff changeset
1166 {
kono
parents: 67
diff changeset
1167 const struct attribute_spec *as;
kono
parents: 67
diff changeset
1168
kono
parents: 67
diff changeset
1169 as = lookup_attribute_spec (get_attribute_name (a));
kono
parents: 67
diff changeset
1170 if (!as || as->affects_type_identity == false)
kono
parents: 67
diff changeset
1171 continue;
kono
parents: 67
diff changeset
1172
kono
parents: 67
diff changeset
1173 if (!lookup_attribute (as->name, CONST_CAST_TREE (a1)))
kono
parents: 67
diff changeset
1174 break;
kono
parents: 67
diff changeset
1175 /* We don't need to compare trees again, as we did this
kono
parents: 67
diff changeset
1176 already in first loop. */
kono
parents: 67
diff changeset
1177 }
kono
parents: 67
diff changeset
1178 /* All types - affecting identity - are equal, so
kono
parents: 67
diff changeset
1179 there is no need to call target hook for comparison. */
kono
parents: 67
diff changeset
1180 if (!a)
kono
parents: 67
diff changeset
1181 return 1;
kono
parents: 67
diff changeset
1182 }
kono
parents: 67
diff changeset
1183 if (lookup_attribute ("transaction_safe", CONST_CAST_TREE (a)))
kono
parents: 67
diff changeset
1184 return 0;
kono
parents: 67
diff changeset
1185 if ((lookup_attribute ("nocf_check", TYPE_ATTRIBUTES (type1)) != NULL)
kono
parents: 67
diff changeset
1186 ^ (lookup_attribute ("nocf_check", TYPE_ATTRIBUTES (type2)) != NULL))
kono
parents: 67
diff changeset
1187 return 0;
kono
parents: 67
diff changeset
1188 /* As some type combinations - like default calling-convention - might
kono
parents: 67
diff changeset
1189 be compatible, we have to call the target hook to get the final result. */
kono
parents: 67
diff changeset
1190 return targetm.comp_type_attributes (type1, type2);
kono
parents: 67
diff changeset
1191 }
kono
parents: 67
diff changeset
1192
kono
parents: 67
diff changeset
1193 /* Return a type like TTYPE except that its TYPE_ATTRIBUTE
kono
parents: 67
diff changeset
1194 is ATTRIBUTE.
kono
parents: 67
diff changeset
1195
kono
parents: 67
diff changeset
1196 Record such modified types already made so we don't make duplicates. */
kono
parents: 67
diff changeset
1197
kono
parents: 67
diff changeset
1198 tree
kono
parents: 67
diff changeset
1199 build_type_attribute_variant (tree ttype, tree attribute)
kono
parents: 67
diff changeset
1200 {
kono
parents: 67
diff changeset
1201 return build_type_attribute_qual_variant (ttype, attribute,
kono
parents: 67
diff changeset
1202 TYPE_QUALS (ttype));
kono
parents: 67
diff changeset
1203 }
kono
parents: 67
diff changeset
1204
kono
parents: 67
diff changeset
1205 /* A variant of lookup_attribute() that can be used with an identifier
kono
parents: 67
diff changeset
1206 as the first argument, and where the identifier can be either
kono
parents: 67
diff changeset
1207 'text' or '__text__'.
kono
parents: 67
diff changeset
1208
kono
parents: 67
diff changeset
1209 Given an attribute ATTR_IDENTIFIER, and a list of attributes LIST,
kono
parents: 67
diff changeset
1210 return a pointer to the attribute's list element if the attribute
kono
parents: 67
diff changeset
1211 is part of the list, or NULL_TREE if not found. If the attribute
kono
parents: 67
diff changeset
1212 appears more than once, this only returns the first occurrence; the
kono
parents: 67
diff changeset
1213 TREE_CHAIN of the return value should be passed back in if further
kono
parents: 67
diff changeset
1214 occurrences are wanted. ATTR_IDENTIFIER must be an identifier but
kono
parents: 67
diff changeset
1215 can be in the form 'text' or '__text__'. */
kono
parents: 67
diff changeset
1216 static tree
kono
parents: 67
diff changeset
1217 lookup_ident_attribute (tree attr_identifier, tree list)
kono
parents: 67
diff changeset
1218 {
kono
parents: 67
diff changeset
1219 gcc_checking_assert (TREE_CODE (attr_identifier) == IDENTIFIER_NODE);
kono
parents: 67
diff changeset
1220
kono
parents: 67
diff changeset
1221 while (list)
kono
parents: 67
diff changeset
1222 {
kono
parents: 67
diff changeset
1223 gcc_checking_assert (TREE_CODE (get_attribute_name (list))
kono
parents: 67
diff changeset
1224 == IDENTIFIER_NODE);
kono
parents: 67
diff changeset
1225
kono
parents: 67
diff changeset
1226 if (cmp_attrib_identifiers (attr_identifier,
kono
parents: 67
diff changeset
1227 get_attribute_name (list)))
kono
parents: 67
diff changeset
1228 /* Found it. */
kono
parents: 67
diff changeset
1229 break;
kono
parents: 67
diff changeset
1230 list = TREE_CHAIN (list);
kono
parents: 67
diff changeset
1231 }
kono
parents: 67
diff changeset
1232
kono
parents: 67
diff changeset
1233 return list;
kono
parents: 67
diff changeset
1234 }
kono
parents: 67
diff changeset
1235
kono
parents: 67
diff changeset
1236 /* Remove any instances of attribute ATTR_NAME in LIST and return the
kono
parents: 67
diff changeset
1237 modified list. */
kono
parents: 67
diff changeset
1238
kono
parents: 67
diff changeset
1239 tree
kono
parents: 67
diff changeset
1240 remove_attribute (const char *attr_name, tree list)
kono
parents: 67
diff changeset
1241 {
kono
parents: 67
diff changeset
1242 tree *p;
kono
parents: 67
diff changeset
1243 gcc_checking_assert (attr_name[0] != '_');
kono
parents: 67
diff changeset
1244
kono
parents: 67
diff changeset
1245 for (p = &list; *p;)
kono
parents: 67
diff changeset
1246 {
kono
parents: 67
diff changeset
1247 tree l = *p;
kono
parents: 67
diff changeset
1248
kono
parents: 67
diff changeset
1249 tree attr = get_attribute_name (l);
kono
parents: 67
diff changeset
1250 if (is_attribute_p (attr_name, attr))
kono
parents: 67
diff changeset
1251 *p = TREE_CHAIN (l);
kono
parents: 67
diff changeset
1252 else
kono
parents: 67
diff changeset
1253 p = &TREE_CHAIN (l);
kono
parents: 67
diff changeset
1254 }
kono
parents: 67
diff changeset
1255
kono
parents: 67
diff changeset
1256 return list;
kono
parents: 67
diff changeset
1257 }
kono
parents: 67
diff changeset
1258
kono
parents: 67
diff changeset
1259 /* Return an attribute list that is the union of a1 and a2. */
kono
parents: 67
diff changeset
1260
kono
parents: 67
diff changeset
1261 tree
kono
parents: 67
diff changeset
1262 merge_attributes (tree a1, tree a2)
kono
parents: 67
diff changeset
1263 {
kono
parents: 67
diff changeset
1264 tree attributes;
kono
parents: 67
diff changeset
1265
kono
parents: 67
diff changeset
1266 /* Either one unset? Take the set one. */
kono
parents: 67
diff changeset
1267
kono
parents: 67
diff changeset
1268 if ((attributes = a1) == 0)
kono
parents: 67
diff changeset
1269 attributes = a2;
kono
parents: 67
diff changeset
1270
kono
parents: 67
diff changeset
1271 /* One that completely contains the other? Take it. */
kono
parents: 67
diff changeset
1272
kono
parents: 67
diff changeset
1273 else if (a2 != 0 && ! attribute_list_contained (a1, a2))
kono
parents: 67
diff changeset
1274 {
kono
parents: 67
diff changeset
1275 if (attribute_list_contained (a2, a1))
kono
parents: 67
diff changeset
1276 attributes = a2;
kono
parents: 67
diff changeset
1277 else
kono
parents: 67
diff changeset
1278 {
kono
parents: 67
diff changeset
1279 /* Pick the longest list, and hang on the other list. */
kono
parents: 67
diff changeset
1280
kono
parents: 67
diff changeset
1281 if (list_length (a1) < list_length (a2))
kono
parents: 67
diff changeset
1282 attributes = a2, a2 = a1;
kono
parents: 67
diff changeset
1283
kono
parents: 67
diff changeset
1284 for (; a2 != 0; a2 = TREE_CHAIN (a2))
kono
parents: 67
diff changeset
1285 {
kono
parents: 67
diff changeset
1286 tree a;
kono
parents: 67
diff changeset
1287 for (a = lookup_ident_attribute (get_attribute_name (a2),
kono
parents: 67
diff changeset
1288 attributes);
kono
parents: 67
diff changeset
1289 a != NULL_TREE && !attribute_value_equal (a, a2);
kono
parents: 67
diff changeset
1290 a = lookup_ident_attribute (get_attribute_name (a2),
kono
parents: 67
diff changeset
1291 TREE_CHAIN (a)))
kono
parents: 67
diff changeset
1292 ;
kono
parents: 67
diff changeset
1293 if (a == NULL_TREE)
kono
parents: 67
diff changeset
1294 {
kono
parents: 67
diff changeset
1295 a1 = copy_node (a2);
kono
parents: 67
diff changeset
1296 TREE_CHAIN (a1) = attributes;
kono
parents: 67
diff changeset
1297 attributes = a1;
kono
parents: 67
diff changeset
1298 }
kono
parents: 67
diff changeset
1299 }
kono
parents: 67
diff changeset
1300 }
kono
parents: 67
diff changeset
1301 }
kono
parents: 67
diff changeset
1302 return attributes;
kono
parents: 67
diff changeset
1303 }
kono
parents: 67
diff changeset
1304
kono
parents: 67
diff changeset
1305 /* Given types T1 and T2, merge their attributes and return
kono
parents: 67
diff changeset
1306 the result. */
kono
parents: 67
diff changeset
1307
kono
parents: 67
diff changeset
1308 tree
kono
parents: 67
diff changeset
1309 merge_type_attributes (tree t1, tree t2)
kono
parents: 67
diff changeset
1310 {
kono
parents: 67
diff changeset
1311 return merge_attributes (TYPE_ATTRIBUTES (t1),
kono
parents: 67
diff changeset
1312 TYPE_ATTRIBUTES (t2));
kono
parents: 67
diff changeset
1313 }
kono
parents: 67
diff changeset
1314
kono
parents: 67
diff changeset
1315 /* Given decls OLDDECL and NEWDECL, merge their attributes and return
kono
parents: 67
diff changeset
1316 the result. */
kono
parents: 67
diff changeset
1317
kono
parents: 67
diff changeset
1318 tree
kono
parents: 67
diff changeset
1319 merge_decl_attributes (tree olddecl, tree newdecl)
kono
parents: 67
diff changeset
1320 {
kono
parents: 67
diff changeset
1321 return merge_attributes (DECL_ATTRIBUTES (olddecl),
kono
parents: 67
diff changeset
1322 DECL_ATTRIBUTES (newdecl));
kono
parents: 67
diff changeset
1323 }
kono
parents: 67
diff changeset
1324
kono
parents: 67
diff changeset
1325 /* Duplicate all attributes with name NAME in ATTR list to *ATTRS if
kono
parents: 67
diff changeset
1326 they are missing there. */
kono
parents: 67
diff changeset
1327
kono
parents: 67
diff changeset
1328 void
kono
parents: 67
diff changeset
1329 duplicate_one_attribute (tree *attrs, tree attr, const char *name)
kono
parents: 67
diff changeset
1330 {
kono
parents: 67
diff changeset
1331 attr = lookup_attribute (name, attr);
kono
parents: 67
diff changeset
1332 if (!attr)
kono
parents: 67
diff changeset
1333 return;
kono
parents: 67
diff changeset
1334 tree a = lookup_attribute (name, *attrs);
kono
parents: 67
diff changeset
1335 while (attr)
kono
parents: 67
diff changeset
1336 {
kono
parents: 67
diff changeset
1337 tree a2;
kono
parents: 67
diff changeset
1338 for (a2 = a; a2; a2 = lookup_attribute (name, TREE_CHAIN (a2)))
kono
parents: 67
diff changeset
1339 if (attribute_value_equal (attr, a2))
kono
parents: 67
diff changeset
1340 break;
kono
parents: 67
diff changeset
1341 if (!a2)
kono
parents: 67
diff changeset
1342 {
kono
parents: 67
diff changeset
1343 a2 = copy_node (attr);
kono
parents: 67
diff changeset
1344 TREE_CHAIN (a2) = *attrs;
kono
parents: 67
diff changeset
1345 *attrs = a2;
kono
parents: 67
diff changeset
1346 }
kono
parents: 67
diff changeset
1347 attr = lookup_attribute (name, TREE_CHAIN (attr));
kono
parents: 67
diff changeset
1348 }
kono
parents: 67
diff changeset
1349 }
kono
parents: 67
diff changeset
1350
kono
parents: 67
diff changeset
1351 /* Duplicate all attributes from user DECL to the corresponding
kono
parents: 67
diff changeset
1352 builtin that should be propagated. */
kono
parents: 67
diff changeset
1353
kono
parents: 67
diff changeset
1354 void
kono
parents: 67
diff changeset
1355 copy_attributes_to_builtin (tree decl)
kono
parents: 67
diff changeset
1356 {
kono
parents: 67
diff changeset
1357 tree b = builtin_decl_explicit (DECL_FUNCTION_CODE (decl));
kono
parents: 67
diff changeset
1358 if (b)
kono
parents: 67
diff changeset
1359 duplicate_one_attribute (&DECL_ATTRIBUTES (b),
kono
parents: 67
diff changeset
1360 DECL_ATTRIBUTES (decl), "omp declare simd");
kono
parents: 67
diff changeset
1361 }
kono
parents: 67
diff changeset
1362
kono
parents: 67
diff changeset
1363 #if TARGET_DLLIMPORT_DECL_ATTRIBUTES
kono
parents: 67
diff changeset
1364
kono
parents: 67
diff changeset
1365 /* Specialization of merge_decl_attributes for various Windows targets.
kono
parents: 67
diff changeset
1366
kono
parents: 67
diff changeset
1367 This handles the following situation:
kono
parents: 67
diff changeset
1368
kono
parents: 67
diff changeset
1369 __declspec (dllimport) int foo;
kono
parents: 67
diff changeset
1370 int foo;
kono
parents: 67
diff changeset
1371
kono
parents: 67
diff changeset
1372 The second instance of `foo' nullifies the dllimport. */
kono
parents: 67
diff changeset
1373
kono
parents: 67
diff changeset
1374 tree
kono
parents: 67
diff changeset
1375 merge_dllimport_decl_attributes (tree old, tree new_tree)
kono
parents: 67
diff changeset
1376 {
kono
parents: 67
diff changeset
1377 tree a;
kono
parents: 67
diff changeset
1378 int delete_dllimport_p = 1;
kono
parents: 67
diff changeset
1379
kono
parents: 67
diff changeset
1380 /* What we need to do here is remove from `old' dllimport if it doesn't
kono
parents: 67
diff changeset
1381 appear in `new'. dllimport behaves like extern: if a declaration is
kono
parents: 67
diff changeset
1382 marked dllimport and a definition appears later, then the object
kono
parents: 67
diff changeset
1383 is not dllimport'd. We also remove a `new' dllimport if the old list
kono
parents: 67
diff changeset
1384 contains dllexport: dllexport always overrides dllimport, regardless
kono
parents: 67
diff changeset
1385 of the order of declaration. */
kono
parents: 67
diff changeset
1386 if (!VAR_OR_FUNCTION_DECL_P (new_tree))
kono
parents: 67
diff changeset
1387 delete_dllimport_p = 0;
kono
parents: 67
diff changeset
1388 else if (DECL_DLLIMPORT_P (new_tree)
kono
parents: 67
diff changeset
1389 && lookup_attribute ("dllexport", DECL_ATTRIBUTES (old)))
kono
parents: 67
diff changeset
1390 {
kono
parents: 67
diff changeset
1391 DECL_DLLIMPORT_P (new_tree) = 0;
kono
parents: 67
diff changeset
1392 warning (OPT_Wattributes, "%q+D already declared with dllexport "
kono
parents: 67
diff changeset
1393 "attribute: dllimport ignored", new_tree);
kono
parents: 67
diff changeset
1394 }
kono
parents: 67
diff changeset
1395 else if (DECL_DLLIMPORT_P (old) && !DECL_DLLIMPORT_P (new_tree))
kono
parents: 67
diff changeset
1396 {
kono
parents: 67
diff changeset
1397 /* Warn about overriding a symbol that has already been used, e.g.:
kono
parents: 67
diff changeset
1398 extern int __attribute__ ((dllimport)) foo;
kono
parents: 67
diff changeset
1399 int* bar () {return &foo;}
kono
parents: 67
diff changeset
1400 int foo;
kono
parents: 67
diff changeset
1401 */
kono
parents: 67
diff changeset
1402 if (TREE_USED (old))
kono
parents: 67
diff changeset
1403 {
kono
parents: 67
diff changeset
1404 warning (0, "%q+D redeclared without dllimport attribute "
kono
parents: 67
diff changeset
1405 "after being referenced with dll linkage", new_tree);
kono
parents: 67
diff changeset
1406 /* If we have used a variable's address with dllimport linkage,
kono
parents: 67
diff changeset
1407 keep the old DECL_DLLIMPORT_P flag: the ADDR_EXPR using the
kono
parents: 67
diff changeset
1408 decl may already have had TREE_CONSTANT computed.
kono
parents: 67
diff changeset
1409 We still remove the attribute so that assembler code refers
kono
parents: 67
diff changeset
1410 to '&foo rather than '_imp__foo'. */
kono
parents: 67
diff changeset
1411 if (VAR_P (old) && TREE_ADDRESSABLE (old))
kono
parents: 67
diff changeset
1412 DECL_DLLIMPORT_P (new_tree) = 1;
kono
parents: 67
diff changeset
1413 }
kono
parents: 67
diff changeset
1414
kono
parents: 67
diff changeset
1415 /* Let an inline definition silently override the external reference,
kono
parents: 67
diff changeset
1416 but otherwise warn about attribute inconsistency. */
kono
parents: 67
diff changeset
1417 else if (VAR_P (new_tree) || !DECL_DECLARED_INLINE_P (new_tree))
kono
parents: 67
diff changeset
1418 warning (OPT_Wattributes, "%q+D redeclared without dllimport "
kono
parents: 67
diff changeset
1419 "attribute: previous dllimport ignored", new_tree);
kono
parents: 67
diff changeset
1420 }
kono
parents: 67
diff changeset
1421 else
kono
parents: 67
diff changeset
1422 delete_dllimport_p = 0;
kono
parents: 67
diff changeset
1423
kono
parents: 67
diff changeset
1424 a = merge_attributes (DECL_ATTRIBUTES (old), DECL_ATTRIBUTES (new_tree));
kono
parents: 67
diff changeset
1425
kono
parents: 67
diff changeset
1426 if (delete_dllimport_p)
kono
parents: 67
diff changeset
1427 a = remove_attribute ("dllimport", a);
kono
parents: 67
diff changeset
1428
kono
parents: 67
diff changeset
1429 return a;
kono
parents: 67
diff changeset
1430 }
kono
parents: 67
diff changeset
1431
kono
parents: 67
diff changeset
1432 /* Handle a "dllimport" or "dllexport" attribute; arguments as in
kono
parents: 67
diff changeset
1433 struct attribute_spec.handler. */
kono
parents: 67
diff changeset
1434
kono
parents: 67
diff changeset
1435 tree
kono
parents: 67
diff changeset
1436 handle_dll_attribute (tree * pnode, tree name, tree args, int flags,
kono
parents: 67
diff changeset
1437 bool *no_add_attrs)
kono
parents: 67
diff changeset
1438 {
kono
parents: 67
diff changeset
1439 tree node = *pnode;
kono
parents: 67
diff changeset
1440 bool is_dllimport;
kono
parents: 67
diff changeset
1441
kono
parents: 67
diff changeset
1442 /* These attributes may apply to structure and union types being created,
kono
parents: 67
diff changeset
1443 but otherwise should pass to the declaration involved. */
kono
parents: 67
diff changeset
1444 if (!DECL_P (node))
kono
parents: 67
diff changeset
1445 {
kono
parents: 67
diff changeset
1446 if (flags & ((int) ATTR_FLAG_DECL_NEXT | (int) ATTR_FLAG_FUNCTION_NEXT
kono
parents: 67
diff changeset
1447 | (int) ATTR_FLAG_ARRAY_NEXT))
kono
parents: 67
diff changeset
1448 {
kono
parents: 67
diff changeset
1449 *no_add_attrs = true;
kono
parents: 67
diff changeset
1450 return tree_cons (name, args, NULL_TREE);
kono
parents: 67
diff changeset
1451 }
kono
parents: 67
diff changeset
1452 if (TREE_CODE (node) == RECORD_TYPE
kono
parents: 67
diff changeset
1453 || TREE_CODE (node) == UNION_TYPE)
kono
parents: 67
diff changeset
1454 {
kono
parents: 67
diff changeset
1455 node = TYPE_NAME (node);
kono
parents: 67
diff changeset
1456 if (!node)
kono
parents: 67
diff changeset
1457 return NULL_TREE;
kono
parents: 67
diff changeset
1458 }
kono
parents: 67
diff changeset
1459 else
kono
parents: 67
diff changeset
1460 {
kono
parents: 67
diff changeset
1461 warning (OPT_Wattributes, "%qE attribute ignored",
kono
parents: 67
diff changeset
1462 name);
kono
parents: 67
diff changeset
1463 *no_add_attrs = true;
kono
parents: 67
diff changeset
1464 return NULL_TREE;
kono
parents: 67
diff changeset
1465 }
kono
parents: 67
diff changeset
1466 }
kono
parents: 67
diff changeset
1467
kono
parents: 67
diff changeset
1468 if (!VAR_OR_FUNCTION_DECL_P (node) && TREE_CODE (node) != TYPE_DECL)
kono
parents: 67
diff changeset
1469 {
kono
parents: 67
diff changeset
1470 *no_add_attrs = true;
kono
parents: 67
diff changeset
1471 warning (OPT_Wattributes, "%qE attribute ignored",
kono
parents: 67
diff changeset
1472 name);
kono
parents: 67
diff changeset
1473 return NULL_TREE;
kono
parents: 67
diff changeset
1474 }
kono
parents: 67
diff changeset
1475
kono
parents: 67
diff changeset
1476 if (TREE_CODE (node) == TYPE_DECL
kono
parents: 67
diff changeset
1477 && TREE_CODE (TREE_TYPE (node)) != RECORD_TYPE
kono
parents: 67
diff changeset
1478 && TREE_CODE (TREE_TYPE (node)) != UNION_TYPE)
kono
parents: 67
diff changeset
1479 {
kono
parents: 67
diff changeset
1480 *no_add_attrs = true;
kono
parents: 67
diff changeset
1481 warning (OPT_Wattributes, "%qE attribute ignored",
kono
parents: 67
diff changeset
1482 name);
kono
parents: 67
diff changeset
1483 return NULL_TREE;
kono
parents: 67
diff changeset
1484 }
kono
parents: 67
diff changeset
1485
kono
parents: 67
diff changeset
1486 is_dllimport = is_attribute_p ("dllimport", name);
kono
parents: 67
diff changeset
1487
kono
parents: 67
diff changeset
1488 /* Report error on dllimport ambiguities seen now before they cause
kono
parents: 67
diff changeset
1489 any damage. */
kono
parents: 67
diff changeset
1490 if (is_dllimport)
kono
parents: 67
diff changeset
1491 {
kono
parents: 67
diff changeset
1492 /* Honor any target-specific overrides. */
kono
parents: 67
diff changeset
1493 if (!targetm.valid_dllimport_attribute_p (node))
kono
parents: 67
diff changeset
1494 *no_add_attrs = true;
kono
parents: 67
diff changeset
1495
kono
parents: 67
diff changeset
1496 else if (TREE_CODE (node) == FUNCTION_DECL
kono
parents: 67
diff changeset
1497 && DECL_DECLARED_INLINE_P (node))
kono
parents: 67
diff changeset
1498 {
kono
parents: 67
diff changeset
1499 warning (OPT_Wattributes, "inline function %q+D declared as "
kono
parents: 67
diff changeset
1500 " dllimport: attribute ignored", node);
kono
parents: 67
diff changeset
1501 *no_add_attrs = true;
kono
parents: 67
diff changeset
1502 }
kono
parents: 67
diff changeset
1503 /* Like MS, treat definition of dllimported variables and
kono
parents: 67
diff changeset
1504 non-inlined functions on declaration as syntax errors. */
kono
parents: 67
diff changeset
1505 else if (TREE_CODE (node) == FUNCTION_DECL && DECL_INITIAL (node))
kono
parents: 67
diff changeset
1506 {
kono
parents: 67
diff changeset
1507 error ("function %q+D definition is marked dllimport", node);
kono
parents: 67
diff changeset
1508 *no_add_attrs = true;
kono
parents: 67
diff changeset
1509 }
kono
parents: 67
diff changeset
1510
kono
parents: 67
diff changeset
1511 else if (VAR_P (node))
kono
parents: 67
diff changeset
1512 {
kono
parents: 67
diff changeset
1513 if (DECL_INITIAL (node))
kono
parents: 67
diff changeset
1514 {
kono
parents: 67
diff changeset
1515 error ("variable %q+D definition is marked dllimport",
kono
parents: 67
diff changeset
1516 node);
kono
parents: 67
diff changeset
1517 *no_add_attrs = true;
kono
parents: 67
diff changeset
1518 }
kono
parents: 67
diff changeset
1519
kono
parents: 67
diff changeset
1520 /* `extern' needn't be specified with dllimport.
kono
parents: 67
diff changeset
1521 Specify `extern' now and hope for the best. Sigh. */
kono
parents: 67
diff changeset
1522 DECL_EXTERNAL (node) = 1;
kono
parents: 67
diff changeset
1523 /* Also, implicitly give dllimport'd variables declared within
kono
parents: 67
diff changeset
1524 a function global scope, unless declared static. */
kono
parents: 67
diff changeset
1525 if (current_function_decl != NULL_TREE && !TREE_STATIC (node))
kono
parents: 67
diff changeset
1526 TREE_PUBLIC (node) = 1;
kono
parents: 67
diff changeset
1527 }
kono
parents: 67
diff changeset
1528
kono
parents: 67
diff changeset
1529 if (*no_add_attrs == false)
kono
parents: 67
diff changeset
1530 DECL_DLLIMPORT_P (node) = 1;
kono
parents: 67
diff changeset
1531 }
kono
parents: 67
diff changeset
1532 else if (TREE_CODE (node) == FUNCTION_DECL
kono
parents: 67
diff changeset
1533 && DECL_DECLARED_INLINE_P (node)
kono
parents: 67
diff changeset
1534 && flag_keep_inline_dllexport)
kono
parents: 67
diff changeset
1535 /* An exported function, even if inline, must be emitted. */
kono
parents: 67
diff changeset
1536 DECL_EXTERNAL (node) = 0;
kono
parents: 67
diff changeset
1537
kono
parents: 67
diff changeset
1538 /* Report error if symbol is not accessible at global scope. */
kono
parents: 67
diff changeset
1539 if (!TREE_PUBLIC (node) && VAR_OR_FUNCTION_DECL_P (node))
kono
parents: 67
diff changeset
1540 {
kono
parents: 67
diff changeset
1541 error ("external linkage required for symbol %q+D because of "
kono
parents: 67
diff changeset
1542 "%qE attribute", node, name);
kono
parents: 67
diff changeset
1543 *no_add_attrs = true;
kono
parents: 67
diff changeset
1544 }
kono
parents: 67
diff changeset
1545
kono
parents: 67
diff changeset
1546 /* A dllexport'd entity must have default visibility so that other
kono
parents: 67
diff changeset
1547 program units (shared libraries or the main executable) can see
kono
parents: 67
diff changeset
1548 it. A dllimport'd entity must have default visibility so that
kono
parents: 67
diff changeset
1549 the linker knows that undefined references within this program
kono
parents: 67
diff changeset
1550 unit can be resolved by the dynamic linker. */
kono
parents: 67
diff changeset
1551 if (!*no_add_attrs)
kono
parents: 67
diff changeset
1552 {
kono
parents: 67
diff changeset
1553 if (DECL_VISIBILITY_SPECIFIED (node)
kono
parents: 67
diff changeset
1554 && DECL_VISIBILITY (node) != VISIBILITY_DEFAULT)
kono
parents: 67
diff changeset
1555 error ("%qE implies default visibility, but %qD has already "
kono
parents: 67
diff changeset
1556 "been declared with a different visibility",
kono
parents: 67
diff changeset
1557 name, node);
kono
parents: 67
diff changeset
1558 DECL_VISIBILITY (node) = VISIBILITY_DEFAULT;
kono
parents: 67
diff changeset
1559 DECL_VISIBILITY_SPECIFIED (node) = 1;
kono
parents: 67
diff changeset
1560 }
kono
parents: 67
diff changeset
1561
kono
parents: 67
diff changeset
1562 return NULL_TREE;
kono
parents: 67
diff changeset
1563 }
kono
parents: 67
diff changeset
1564
kono
parents: 67
diff changeset
1565 #endif /* TARGET_DLLIMPORT_DECL_ATTRIBUTES */
kono
parents: 67
diff changeset
1566
kono
parents: 67
diff changeset
1567 /* Given two lists of attributes, return true if list l2 is
kono
parents: 67
diff changeset
1568 equivalent to l1. */
kono
parents: 67
diff changeset
1569
kono
parents: 67
diff changeset
1570 int
kono
parents: 67
diff changeset
1571 attribute_list_equal (const_tree l1, const_tree l2)
kono
parents: 67
diff changeset
1572 {
kono
parents: 67
diff changeset
1573 if (l1 == l2)
kono
parents: 67
diff changeset
1574 return 1;
kono
parents: 67
diff changeset
1575
kono
parents: 67
diff changeset
1576 return attribute_list_contained (l1, l2)
kono
parents: 67
diff changeset
1577 && attribute_list_contained (l2, l1);
kono
parents: 67
diff changeset
1578 }
kono
parents: 67
diff changeset
1579
kono
parents: 67
diff changeset
1580 /* Given two lists of attributes, return true if list L2 is
kono
parents: 67
diff changeset
1581 completely contained within L1. */
kono
parents: 67
diff changeset
1582 /* ??? This would be faster if attribute names were stored in a canonicalized
kono
parents: 67
diff changeset
1583 form. Otherwise, if L1 uses `foo' and L2 uses `__foo__', the long method
kono
parents: 67
diff changeset
1584 must be used to show these elements are equivalent (which they are). */
kono
parents: 67
diff changeset
1585 /* ??? It's not clear that attributes with arguments will always be handled
kono
parents: 67
diff changeset
1586 correctly. */
kono
parents: 67
diff changeset
1587
kono
parents: 67
diff changeset
1588 int
kono
parents: 67
diff changeset
1589 attribute_list_contained (const_tree l1, const_tree l2)
kono
parents: 67
diff changeset
1590 {
kono
parents: 67
diff changeset
1591 const_tree t1, t2;
kono
parents: 67
diff changeset
1592
kono
parents: 67
diff changeset
1593 /* First check the obvious, maybe the lists are identical. */
kono
parents: 67
diff changeset
1594 if (l1 == l2)
kono
parents: 67
diff changeset
1595 return 1;
kono
parents: 67
diff changeset
1596
kono
parents: 67
diff changeset
1597 /* Maybe the lists are similar. */
kono
parents: 67
diff changeset
1598 for (t1 = l1, t2 = l2;
kono
parents: 67
diff changeset
1599 t1 != 0 && t2 != 0
kono
parents: 67
diff changeset
1600 && get_attribute_name (t1) == get_attribute_name (t2)
kono
parents: 67
diff changeset
1601 && TREE_VALUE (t1) == TREE_VALUE (t2);
kono
parents: 67
diff changeset
1602 t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2))
kono
parents: 67
diff changeset
1603 ;
kono
parents: 67
diff changeset
1604
kono
parents: 67
diff changeset
1605 /* Maybe the lists are equal. */
kono
parents: 67
diff changeset
1606 if (t1 == 0 && t2 == 0)
kono
parents: 67
diff changeset
1607 return 1;
kono
parents: 67
diff changeset
1608
kono
parents: 67
diff changeset
1609 for (; t2 != 0; t2 = TREE_CHAIN (t2))
kono
parents: 67
diff changeset
1610 {
kono
parents: 67
diff changeset
1611 const_tree attr;
kono
parents: 67
diff changeset
1612 /* This CONST_CAST is okay because lookup_attribute does not
kono
parents: 67
diff changeset
1613 modify its argument and the return value is assigned to a
kono
parents: 67
diff changeset
1614 const_tree. */
kono
parents: 67
diff changeset
1615 for (attr = lookup_ident_attribute (get_attribute_name (t2),
kono
parents: 67
diff changeset
1616 CONST_CAST_TREE (l1));
kono
parents: 67
diff changeset
1617 attr != NULL_TREE && !attribute_value_equal (t2, attr);
kono
parents: 67
diff changeset
1618 attr = lookup_ident_attribute (get_attribute_name (t2),
kono
parents: 67
diff changeset
1619 TREE_CHAIN (attr)))
kono
parents: 67
diff changeset
1620 ;
kono
parents: 67
diff changeset
1621
kono
parents: 67
diff changeset
1622 if (attr == NULL_TREE)
kono
parents: 67
diff changeset
1623 return 0;
kono
parents: 67
diff changeset
1624 }
kono
parents: 67
diff changeset
1625
kono
parents: 67
diff changeset
1626 return 1;
kono
parents: 67
diff changeset
1627 }
kono
parents: 67
diff changeset
1628
kono
parents: 67
diff changeset
1629 /* The backbone of lookup_attribute(). ATTR_LEN is the string length
kono
parents: 67
diff changeset
1630 of ATTR_NAME, and LIST is not NULL_TREE.
kono
parents: 67
diff changeset
1631
kono
parents: 67
diff changeset
1632 The function is called from lookup_attribute in order to optimize
kono
parents: 67
diff changeset
1633 for size. */
kono
parents: 67
diff changeset
1634
kono
parents: 67
diff changeset
1635 tree
kono
parents: 67
diff changeset
1636 private_lookup_attribute (const char *attr_name, size_t attr_len, tree list)
kono
parents: 67
diff changeset
1637 {
kono
parents: 67
diff changeset
1638 while (list)
kono
parents: 67
diff changeset
1639 {
kono
parents: 67
diff changeset
1640 tree attr = get_attribute_name (list);
kono
parents: 67
diff changeset
1641 size_t ident_len = IDENTIFIER_LENGTH (attr);
kono
parents: 67
diff changeset
1642 if (cmp_attribs (attr_name, attr_len, IDENTIFIER_POINTER (attr),
kono
parents: 67
diff changeset
1643 ident_len))
kono
parents: 67
diff changeset
1644 break;
kono
parents: 67
diff changeset
1645 list = TREE_CHAIN (list);
kono
parents: 67
diff changeset
1646 }
kono
parents: 67
diff changeset
1647
kono
parents: 67
diff changeset
1648 return list;
kono
parents: 67
diff changeset
1649 }