annotate gcc/attribs.c @ 131:84e7813d76e9

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