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