annotate gcc/attribs.c @ 158:494b0b89df80 default tip

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