annotate gcc/d/d-attribs.cc @ 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
145
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1 /* d-attribs.c -- D attributes handling.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2 Copyright (C) 2015-2020 Free Software Foundation, Inc.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
4 GCC is free software; you can redistribute it and/or modify
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
5 it under the terms of the GNU General Public License as published by
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
6 the Free Software Foundation; either version 3, or (at your option)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
7 any later version.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
8
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
9 GCC is distributed in the hope that it will be useful,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
12 GNU General Public License for more details.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
13
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
14 You should have received a copy of the GNU General Public License
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
15 along with GCC; see the file COPYING3. If not see
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
16 <http://www.gnu.org/licenses/>. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
17
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
18 /* Implementation of attribute handlers for user defined attributes and
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
19 internal built-in functions. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
20
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
21 #include "config.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
22 #include "system.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
23 #include "coretypes.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
24
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
25 #include "dmd/declaration.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
26 #include "dmd/mtype.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
27
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
28 #include "tree.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
29 #include "diagnostic.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
30 #include "tm.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
31 #include "cgraph.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
32 #include "toplev.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
33 #include "target.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
34 #include "common/common-target.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
35 #include "stringpool.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
36 #include "attribs.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
37 #include "varasm.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
38
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
39 #include "d-tree.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
40
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
41
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
42 /* Internal attribute handlers for built-in functions. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
43 static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
44 static tree handle_leaf_attribute (tree *, tree, tree, int, bool *);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
45 static tree handle_const_attribute (tree *, tree, tree, int, bool *);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
46 static tree handle_malloc_attribute (tree *, tree, tree, int, bool *);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
47 static tree handle_pure_attribute (tree *, tree, tree, int, bool *);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
48 static tree handle_novops_attribute (tree *, tree, tree, int, bool *);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
49 static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
50 static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
51 static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
52 static tree handle_transaction_pure_attribute (tree *, tree, tree, int, bool *);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
53 static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
54 static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
55
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
56 /* D attribute handlers for user defined attributes. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
57 static tree d_handle_noinline_attribute (tree *, tree, tree, int, bool *);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
58 static tree d_handle_forceinline_attribute (tree *, tree, tree, int, bool *);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
59 static tree d_handle_flatten_attribute (tree *, tree, tree, int, bool *);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
60 static tree d_handle_target_attribute (tree *, tree, tree, int, bool *);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
61 static tree d_handle_noclone_attribute (tree *, tree, tree, int, bool *);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
62 static tree d_handle_section_attribute (tree *, tree, tree, int, bool *);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
63 static tree d_handle_alias_attribute (tree *, tree, tree, int, bool *);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
64 static tree d_handle_weak_attribute (tree *, tree, tree, int, bool *) ;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
65
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
66 /* Helper to define attribute exclusions. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
67 #define ATTR_EXCL(name, function, type, variable) \
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
68 { name, function, type, variable }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
69
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
70 /* Define attributes that are mutually exclusive with one another. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
71 static const struct attribute_spec::exclusions attr_noreturn_exclusions[] =
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
72 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
73 ATTR_EXCL ("const", true, true, true),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
74 ATTR_EXCL ("malloc", true, true, true),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
75 ATTR_EXCL ("pure", true, true, true),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
76 ATTR_EXCL ("returns_twice", true, true, true),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
77 ATTR_EXCL (NULL, false, false, false),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
78 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
79
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
80 static const struct attribute_spec::exclusions attr_returns_twice_exclusions[] =
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
81 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
82 ATTR_EXCL ("noreturn", true, true, true),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
83 ATTR_EXCL (NULL, false, false, false),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
84 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
85
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
86 static const struct attribute_spec::exclusions attr_const_pure_exclusions[] =
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
87 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
88 ATTR_EXCL ("const", true, true, true),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
89 ATTR_EXCL ("noreturn", true, true, true),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
90 ATTR_EXCL ("pure", true, true, true),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
91 ATTR_EXCL (NULL, false, false, false)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
92 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
93
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
94 static const struct attribute_spec::exclusions attr_inline_exclusions[] =
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
95 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
96 ATTR_EXCL ("noinline", true, true, true),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
97 ATTR_EXCL (NULL, false, false, false),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
98 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
99
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
100 static const struct attribute_spec::exclusions attr_noinline_exclusions[] =
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
101 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
102 ATTR_EXCL ("forceinline", true, true, true),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
103 ATTR_EXCL (NULL, false, false, false),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
104 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
105
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
106 /* Helper to define an attribute. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
107 #define ATTR_SPEC(name, min_len, max_len, decl_req, type_req, fn_type_req, \
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
108 affects_type_identity, handler, exclude) \
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
109 { name, min_len, max_len, decl_req, type_req, fn_type_req, \
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
110 affects_type_identity, handler, exclude }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
111
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
112 /* Table of machine-independent attributes.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
113 For internal use (marking of built-ins) only. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
114 const attribute_spec d_langhook_common_attribute_table[] =
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
115 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
116 ATTR_SPEC ("noreturn", 0, 0, true, false, false, false,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
117 handle_noreturn_attribute, attr_noreturn_exclusions),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
118 ATTR_SPEC ("leaf", 0, 0, true, false, false, false,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
119 handle_leaf_attribute, NULL),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
120 ATTR_SPEC ("const", 0, 0, true, false, false, false,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
121 handle_const_attribute, attr_const_pure_exclusions),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
122 ATTR_SPEC ("malloc", 0, 0, true, false, false, false,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
123 handle_malloc_attribute, NULL),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
124 ATTR_SPEC ("returns_twice", 0, 0, true, false, false, false,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
125 handle_returns_twice_attribute, attr_returns_twice_exclusions),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
126 ATTR_SPEC ("pure", 0, 0, true, false, false, false,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
127 handle_pure_attribute, attr_const_pure_exclusions),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
128 ATTR_SPEC ("nonnull", 0, -1, false, true, true, false,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
129 handle_nonnull_attribute, NULL),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
130 ATTR_SPEC ("nothrow", 0, 0, true, false, false, false,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
131 handle_nothrow_attribute, NULL),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
132 ATTR_SPEC ("transaction_pure", 0, 0, false, true, true, false,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
133 handle_transaction_pure_attribute, NULL),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
134 ATTR_SPEC ("no vops", 0, 0, true, false, false, false,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
135 handle_novops_attribute, NULL),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
136 ATTR_SPEC ("type generic", 0, 0, false, true, true, false,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
137 handle_type_generic_attribute, NULL),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
138 ATTR_SPEC ("fn spec", 1, 1, false, true, true, false,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
139 handle_fnspec_attribute, NULL),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
140 ATTR_SPEC (NULL, 0, 0, false, false, false, false, NULL, NULL),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
141 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
142
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
143 /* Table of D language attributes exposed by `gcc.attribute' UDAs. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
144 const attribute_spec d_langhook_attribute_table[] =
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
145 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
146 ATTR_SPEC ("noinline", 0, 0, true, false, false, false,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
147 d_handle_noinline_attribute, attr_noinline_exclusions),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
148 ATTR_SPEC ("forceinline", 0, 0, true, false, false, false,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
149 d_handle_forceinline_attribute, attr_inline_exclusions),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
150 ATTR_SPEC ("flatten", 0, 0, true, false, false, false,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
151 d_handle_flatten_attribute, NULL),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
152 ATTR_SPEC ("target", 1, -1, true, false, false, false,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
153 d_handle_target_attribute, NULL),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
154 ATTR_SPEC ("noclone", 0, 0, true, false, false, false,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
155 d_handle_noclone_attribute, NULL),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
156 ATTR_SPEC ("section", 1, 1, true, false, false, false,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
157 d_handle_section_attribute, NULL),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
158 ATTR_SPEC ("alias", 1, 1, true, false, false, false,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
159 d_handle_alias_attribute, NULL),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
160 ATTR_SPEC ("weak", 0, 0, true, false, false, false,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
161 d_handle_weak_attribute, NULL),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
162 ATTR_SPEC (NULL, 0, 0, false, false, false, false, NULL, NULL),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
163 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
164
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
165
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
166 /* Insert the type attribute ATTRNAME with value VALUE into TYPE.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
167 Returns a new variant of the original type declaration. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
168
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
169 tree
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
170 insert_type_attribute (tree type, const char *attrname, tree value)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
171 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
172 tree ident = get_identifier (attrname);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
173
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
174 if (value)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
175 value = tree_cons (NULL_TREE, value, NULL_TREE);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
176
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
177 tree attribs = merge_attributes (TYPE_ATTRIBUTES (type),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
178 tree_cons (ident, value, NULL_TREE));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
179
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
180 return build_type_attribute_variant (type, attribs);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
181 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
182
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
183 /* Insert the decl attribute ATTRNAME with value VALUE into DECL. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
184
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
185 tree
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
186 insert_decl_attribute (tree decl, const char *attrname, tree value)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
187 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
188 tree ident = get_identifier (attrname);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
189
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
190 if (value)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
191 value = tree_cons (NULL_TREE, value, NULL_TREE);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
192
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
193 tree attribs = merge_attributes (DECL_ATTRIBUTES (decl),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
194 tree_cons (ident, value, NULL_TREE));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
195
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
196 return build_decl_attribute_variant (decl, attribs);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
197 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
198
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
199 /* Returns TRUE if NAME is an attribute recognized as being handled by
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
200 the `gcc.attribute' module. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
201
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
202 static bool
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
203 uda_attribute_p (const char *name)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
204 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
205 tree ident = get_identifier (name);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
206
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
207 /* Search both our language, and target attribute tables.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
208 Common and format attributes are kept internal. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
209 for (const attribute_spec *p = d_langhook_attribute_table; p->name; p++)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
210 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
211 if (get_identifier (p->name) == ident)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
212 return true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
213 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
214
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
215 for (const attribute_spec *p = targetm.attribute_table; p->name; p++)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
216 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
217 if (get_identifier (p->name) == ident)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
218 return true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
219 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
220
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
221 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
222 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
223
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
224 /* [attribute/uda]
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
225
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
226 User Defined Attributes (UDA) are compile time expressions that can be
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
227 attached to a declaration. These attributes can then be queried, extracted,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
228 and manipulated at compile-time. There is no run-time component to them.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
229
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
230 Expand and merge all UDAs found in the EATTRS list that are of type
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
231 `gcc.attribute.Attribute'. This symbol is internally recognized by the
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
232 compiler and maps them to their equivalent GCC attribute. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
233
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
234 tree
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
235 build_attributes (Expressions *eattrs)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
236 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
237 if (!eattrs)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
238 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
239
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
240 expandTuples (eattrs);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
241
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
242 tree attribs = NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
243
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
244 for (size_t i = 0; i < eattrs->dim; i++)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
245 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
246 Expression *attr = (*eattrs)[i];
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
247 Dsymbol *sym = attr->type->toDsymbol (0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
248
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
249 if (!sym)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
250 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
251
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
252 /* Attribute symbol must come from the `gcc.attribute' module. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
253 Dsymbol *mod = (Dsymbol*) sym->getModule ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
254 if (!(strcmp (mod->toChars (), "attribute") == 0
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
255 && mod->parent != NULL
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
256 && strcmp (mod->parent->toChars (), "gcc") == 0
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
257 && !mod->parent->parent))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
258 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
259
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
260 /* Get the result of the attribute if it hasn't already been folded. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
261 if (attr->op == TOKcall)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
262 attr = attr->ctfeInterpret ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
263
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
264 /* Should now have a struct `Attribute("attrib", "value", ...)'
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
265 initializer list. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
266 gcc_assert (attr->op == TOKstructliteral);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
267 Expressions *elems = ((StructLiteralExp*) attr)->elements;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
268 Expression *e0 = (*elems)[0];
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
269
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
270 if (e0->op != TOKstring)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
271 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
272 error ("expected string attribute, not %qs", e0->toChars ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
273 return error_mark_node;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
274 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
275
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
276 StringExp *se = (StringExp*) e0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
277 gcc_assert (se->sz == 1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
278
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
279 /* Empty string attribute, just ignore it. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
280 if (se->len == 0)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
281 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
282
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
283 /* Check if the attribute is recognized and handled.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
284 Done here to report the diagnostic at the right location. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
285 const char *name = (const char *)(se->len ? se->string : "");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
286 if (!uda_attribute_p (name))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
287 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
288 warning_at (make_location_t (e0->loc), OPT_Wattributes,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
289 "unknown attribute %qs", name);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
290 return error_mark_node;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
291 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
292
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
293 /* Chain all attribute arguments together. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
294 tree args = NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
295
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
296 for (size_t j = 1; j < elems->dim; j++)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
297 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
298 Expression *e = (*elems)[j];
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
299 tree t;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
300 if (e->op == TOKstring && ((StringExp *) e)->sz == 1)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
301 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
302 StringExp *s = (StringExp *) e;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
303 const char *string = (const char *)(s->len ? s->string : "");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
304 t = build_string (s->len, string);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
305 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
306 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
307 t = build_expr (e);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
308
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
309 args = chainon (args, build_tree_list (0, t));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
310 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
311
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
312 tree list = build_tree_list (get_identifier (name), args);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
313 attribs = chainon (attribs, list);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
314 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
315
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
316 return attribs;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
317 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
318
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
319 /* Built-in attribute handlers. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
320
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
321 /* Handle a "noreturn" attribute; arguments as in
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
322 struct attribute_spec.handler. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
323
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
324 static tree
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
325 handle_noreturn_attribute (tree *node, tree ARG_UNUSED (name),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
326 tree ARG_UNUSED (args), int ARG_UNUSED (flags),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
327 bool * ARG_UNUSED (no_add_attrs))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
328 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
329 tree type = TREE_TYPE (*node);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
330
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
331 if (TREE_CODE (*node) == FUNCTION_DECL)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
332 TREE_THIS_VOLATILE (*node) = 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
333 else if (TREE_CODE (type) == POINTER_TYPE
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
334 && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
335 TREE_TYPE (*node)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
336 = build_pointer_type
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
337 (build_type_variant (TREE_TYPE (type),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
338 TYPE_READONLY (TREE_TYPE (type)), 1));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
339 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
340 gcc_unreachable ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
341
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
342 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
343 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
344
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
345 /* Handle a "leaf" attribute; arguments as in
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
346 struct attribute_spec.handler. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
347
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
348 static tree
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
349 handle_leaf_attribute (tree *node, tree name,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
350 tree ARG_UNUSED (args),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
351 int ARG_UNUSED (flags), bool *no_add_attrs)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
352 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
353 if (TREE_CODE (*node) != FUNCTION_DECL)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
354 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
355 warning (OPT_Wattributes, "%qE attribute ignored", name);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
356 *no_add_attrs = true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
357 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
358 if (!TREE_PUBLIC (*node))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
359 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
360 warning (OPT_Wattributes, "%qE attribute has no effect", name);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
361 *no_add_attrs = true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
362 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
363
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
364 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
365 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
366
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
367 /* Handle a "const" attribute; arguments as in
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
368 struct attribute_spec.handler. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
369
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
370 static tree
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
371 handle_const_attribute (tree *node, tree ARG_UNUSED (name),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
372 tree ARG_UNUSED (args), int ARG_UNUSED (flags),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
373 bool * ARG_UNUSED (no_add_attrs))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
374 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
375 tree type = TREE_TYPE (*node);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
376
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
377 if (TREE_CODE (*node) == FUNCTION_DECL)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
378 TREE_READONLY (*node) = 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
379 else if (TREE_CODE (type) == POINTER_TYPE
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
380 && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
381 TREE_TYPE (*node)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
382 = build_pointer_type
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
383 (build_type_variant (TREE_TYPE (type), 1,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
384 TREE_THIS_VOLATILE (TREE_TYPE (type))));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
385 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
386 gcc_unreachable ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
387
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
388 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
389 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
390
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
391 /* Handle a "malloc" attribute; arguments as in
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
392 struct attribute_spec.handler. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
393
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
394 tree
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
395 handle_malloc_attribute (tree *node, tree ARG_UNUSED (name),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
396 tree ARG_UNUSED (args), int ARG_UNUSED (flags),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
397 bool * ARG_UNUSED (no_add_attrs))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
398 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
399 gcc_assert (TREE_CODE (*node) == FUNCTION_DECL
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
400 && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (*node))));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
401 DECL_IS_MALLOC (*node) = 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
402 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
403 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
404
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
405 /* Handle a "pure" attribute; arguments as in
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
406 struct attribute_spec.handler. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
407
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
408 static tree
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
409 handle_pure_attribute (tree *node, tree ARG_UNUSED (name),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
410 tree ARG_UNUSED (args), int ARG_UNUSED (flags),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
411 bool * ARG_UNUSED (no_add_attrs))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
412 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
413 gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
414 DECL_PURE_P (*node) = 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
415 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
416 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
417
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
418 /* Handle a "no vops" attribute; arguments as in
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
419 struct attribute_spec.handler. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
420
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
421 static tree
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
422 handle_novops_attribute (tree *node, tree ARG_UNUSED (name),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
423 tree ARG_UNUSED (args), int ARG_UNUSED (flags),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
424 bool * ARG_UNUSED (no_add_attrs))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
425 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
426 gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
427 DECL_IS_NOVOPS (*node) = 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
428 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
429 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
430
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
431 /* Helper for nonnull attribute handling; fetch the operand number
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
432 from the attribute argument list. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
433
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
434 static bool
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
435 get_nonnull_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
436 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
437 /* Verify the arg number is a constant. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
438 if (!tree_fits_uhwi_p (arg_num_expr))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
439 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
440
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
441 *valp = TREE_INT_CST_LOW (arg_num_expr);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
442 return true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
443 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
444
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
445 /* Handle the "nonnull" attribute. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
446
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
447 static tree
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
448 handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
449 tree args, int ARG_UNUSED (flags),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
450 bool * ARG_UNUSED (no_add_attrs))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
451 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
452 tree type = *node;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
453
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
454 /* If no arguments are specified, all pointer arguments should be
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
455 non-null. Verify a full prototype is given so that the arguments
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
456 will have the correct types when we actually check them later.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
457 Avoid diagnosing type-generic built-ins since those have no
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
458 prototype. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
459 if (!args)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
460 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
461 gcc_assert (prototype_p (type)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
462 || !TYPE_ATTRIBUTES (type)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
463 || lookup_attribute ("type generic", TYPE_ATTRIBUTES (type)));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
464
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
465 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
466 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
467
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
468 /* Argument list specified. Verify that each argument number references
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
469 a pointer argument. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
470 for (; args; args = TREE_CHAIN (args))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
471 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
472 tree argument;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
473 unsigned HOST_WIDE_INT arg_num = 0, ck_num;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
474
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
475 if (!get_nonnull_operand (TREE_VALUE (args), &arg_num))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
476 gcc_unreachable ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
477
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
478 argument = TYPE_ARG_TYPES (type);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
479 if (argument)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
480 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
481 for (ck_num = 1; ; ck_num++)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
482 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
483 if (!argument || ck_num == arg_num)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
484 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
485 argument = TREE_CHAIN (argument);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
486 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
487
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
488 gcc_assert (argument
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
489 && TREE_CODE (TREE_VALUE (argument)) == POINTER_TYPE);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
490 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
491 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
492
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
493 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
494 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
495
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
496 /* Handle a "nothrow" attribute; arguments as in
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
497 struct attribute_spec.handler. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
498
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
499 static tree
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
500 handle_nothrow_attribute (tree *node, tree ARG_UNUSED (name),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
501 tree ARG_UNUSED (args), int ARG_UNUSED (flags),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
502 bool * ARG_UNUSED (no_add_attrs))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
503 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
504 gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
505 TREE_NOTHROW (*node) = 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
506 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
507 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
508
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
509 /* Handle a "type_generic" attribute. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
510
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
511 static tree
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
512 handle_type_generic_attribute (tree *node, tree ARG_UNUSED (name),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
513 tree ARG_UNUSED (args), int ARG_UNUSED (flags),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
514 bool * ARG_UNUSED (no_add_attrs))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
515 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
516 /* Ensure we have a function type. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
517 gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
518
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
519 /* Ensure we have a variadic function. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
520 gcc_assert (!prototype_p (*node) || stdarg_p (*node));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
521
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
522 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
523 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
524
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
525 /* Handle a "transaction_pure" attribute. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
526
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
527 static tree
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
528 handle_transaction_pure_attribute (tree *node, tree ARG_UNUSED (name),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
529 tree ARG_UNUSED (args),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
530 int ARG_UNUSED (flags),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
531 bool * ARG_UNUSED (no_add_attrs))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
532 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
533 /* Ensure we have a function type. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
534 gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
535
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
536 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
537 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
538
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
539 /* Handle a "returns_twice" attribute. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
540
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
541 static tree
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
542 handle_returns_twice_attribute (tree *node, tree ARG_UNUSED (name),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
543 tree ARG_UNUSED (args),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
544 int ARG_UNUSED (flags),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
545 bool * ARG_UNUSED (no_add_attrs))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
546 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
547 gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
548
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
549 DECL_IS_RETURNS_TWICE (*node) = 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
550
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
551 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
552 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
553
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
554 /* Handle a "fn spec" attribute; arguments as in
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
555 struct attribute_spec.handler. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
556
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
557 tree
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
558 handle_fnspec_attribute (tree *node ATTRIBUTE_UNUSED, tree ARG_UNUSED (name),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
559 tree args, int ARG_UNUSED (flags),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
560 bool *no_add_attrs ATTRIBUTE_UNUSED)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
561 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
562 gcc_assert (args
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
563 && TREE_CODE (TREE_VALUE (args)) == STRING_CST
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
564 && !TREE_CHAIN (args));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
565 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
566 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
567
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
568 /* Language specific attribute handlers. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
569
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
570 /* Handle a "noinline" attribute. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
571
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
572 static tree
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
573 d_handle_noinline_attribute (tree *node, tree name,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
574 tree ARG_UNUSED (args),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
575 int ARG_UNUSED (flags), bool *no_add_attrs)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
576 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
577 Type *t = TYPE_LANG_FRONTEND (TREE_TYPE (*node));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
578
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
579 if (t->ty == Tfunction)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
580 DECL_UNINLINABLE (*node) = 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
581 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
582 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
583 warning (OPT_Wattributes, "%qE attribute ignored", name);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
584 *no_add_attrs = true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
585 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
586
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
587 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
588 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
589
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
590 /* Handle a "forceinline" attribute. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
591
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
592 static tree
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
593 d_handle_forceinline_attribute (tree *node, tree name,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
594 tree ARG_UNUSED (args),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
595 int ARG_UNUSED (flags),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
596 bool *no_add_attrs)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
597 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
598 Type *t = TYPE_LANG_FRONTEND (TREE_TYPE (*node));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
599
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
600 if (t->ty == Tfunction)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
601 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
602 tree attributes = DECL_ATTRIBUTES (*node);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
603
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
604 /* Push attribute always_inline. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
605 if (! lookup_attribute ("always_inline", attributes))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
606 DECL_ATTRIBUTES (*node) = tree_cons (get_identifier ("always_inline"),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
607 NULL_TREE, attributes);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
608
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
609 DECL_DECLARED_INLINE_P (*node) = 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
610 DECL_NO_INLINE_WARNING_P (*node) = 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
611 DECL_DISREGARD_INLINE_LIMITS (*node) = 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
612 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
613 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
614 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
615 warning (OPT_Wattributes, "%qE attribute ignored", name);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
616 *no_add_attrs = true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
617 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
618
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
619 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
620 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
621
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
622 /* Handle a "flatten" attribute. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
623
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
624 static tree
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
625 d_handle_flatten_attribute (tree *node, tree name,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
626 tree args ATTRIBUTE_UNUSED,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
627 int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
628 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
629 Type *t = TYPE_LANG_FRONTEND (TREE_TYPE (*node));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
630
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
631 if (t->ty != Tfunction)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
632 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
633 warning (OPT_Wattributes, "%qE attribute ignored", name);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
634 *no_add_attrs = true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
635 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
636
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
637 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
638 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
639
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
640 /* Handle a "target" attribute. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
641
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
642 static tree
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
643 d_handle_target_attribute (tree *node, tree name, tree args, int flags,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
644 bool *no_add_attrs)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
645 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
646 Type *t = TYPE_LANG_FRONTEND (TREE_TYPE (*node));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
647
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
648 /* Ensure we have a function type. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
649 if (t->ty != Tfunction)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
650 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
651 warning (OPT_Wattributes, "%qE attribute ignored", name);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
652 *no_add_attrs = true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
653 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
654 else if (! targetm.target_option.valid_attribute_p (*node, name, args, flags))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
655 *no_add_attrs = true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
656
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
657 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
658 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
659
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
660 /* Handle a "noclone" attribute. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
661
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
662 static tree
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
663 d_handle_noclone_attribute (tree *node, tree name,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
664 tree ARG_UNUSED (args),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
665 int ARG_UNUSED (flags),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
666 bool *no_add_attrs)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
667 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
668 Type *t = TYPE_LANG_FRONTEND (TREE_TYPE (*node));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
669
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
670 if (t->ty == Tfunction)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
671 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
672 tree attributes = DECL_ATTRIBUTES (*node);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
673
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
674 /* Push attribute noclone. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
675 if (! lookup_attribute ("noclone", attributes))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
676 DECL_ATTRIBUTES (*node) = tree_cons (get_identifier ("noclone"),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
677 NULL_TREE, attributes);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
678 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
679 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
680 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
681 warning (OPT_Wattributes, "%qE attribute ignored", name);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
682 *no_add_attrs = true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
683 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
684
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
685 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
686 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
687
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
688 /* Handle a "section" attribute; arguments as in
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
689 struct attribute_spec.handler. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
690
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
691 static tree
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
692 d_handle_section_attribute (tree *node, tree ARG_UNUSED (name), tree args,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
693 int ARG_UNUSED (flags), bool *no_add_attrs)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
694 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
695 tree decl = *node;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
696
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
697 if (targetm_common.have_named_sections)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
698 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
699 if (VAR_OR_FUNCTION_DECL_P (decl)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
700 && TREE_CODE (TREE_VALUE (args)) == STRING_CST)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
701 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
702 if (VAR_P (decl)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
703 && current_function_decl != NULL_TREE
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
704 && !TREE_STATIC (decl))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
705 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
706 error_at (DECL_SOURCE_LOCATION (decl),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
707 "section attribute cannot be specified for "
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
708 "local variables");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
709 *no_add_attrs = true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
710 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
711
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
712 /* The decl may have already been given a section attribute
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
713 from a previous declaration. Ensure they match. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
714 else if (DECL_SECTION_NAME (decl) != NULL
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
715 && strcmp (DECL_SECTION_NAME (decl),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
716 TREE_STRING_POINTER (TREE_VALUE (args))) != 0)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
717 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
718 error ("section of %q+D conflicts with previous declaration",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
719 *node);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
720 *no_add_attrs = true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
721 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
722 else if (VAR_P (decl)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
723 && !targetm.have_tls && targetm.emutls.tmpl_section
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
724 && DECL_THREAD_LOCAL_P (decl))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
725 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
726 error ("section of %q+D cannot be overridden", *node);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
727 *no_add_attrs = true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
728 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
729 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
730 set_decl_section_name (decl,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
731 TREE_STRING_POINTER (TREE_VALUE (args)));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
732 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
733 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
734 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
735 error ("section attribute not allowed for %q+D", *node);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
736 *no_add_attrs = true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
737 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
738 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
739 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
740 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
741 error_at (DECL_SOURCE_LOCATION (*node),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
742 "section attributes are not supported for this target");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
743 *no_add_attrs = true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
744 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
745
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
746 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
747 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
748
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
749 /* Handle an "alias" attribute; arguments as in
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
750 struct attribute_spec.handler. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
751
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
752 static tree
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
753 d_handle_alias_attribute (tree *node, tree ARG_UNUSED (name),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
754 tree args, int ARG_UNUSED (flags),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
755 bool *no_add_attrs ATTRIBUTE_UNUSED)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
756 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
757 tree decl = *node;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
758
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
759 if (TREE_CODE (decl) != FUNCTION_DECL
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
760 && TREE_CODE (decl) != VAR_DECL)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
761 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
762 warning (OPT_Wattributes, "%qE attribute ignored", name);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
763 *no_add_attrs = true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
764 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
765 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
766 else if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
767 || (TREE_CODE (decl) != FUNCTION_DECL
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
768 && TREE_PUBLIC (decl) && !DECL_EXTERNAL (decl))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
769 /* A static variable declaration is always a tentative definition,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
770 but the alias is a non-tentative definition which overrides. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
771 || (TREE_CODE (decl) != FUNCTION_DECL
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
772 && ! TREE_PUBLIC (decl) && DECL_INITIAL (decl)))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
773 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
774 error ("%q+D defined both normally and as %qE attribute", decl, name);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
775 *no_add_attrs = true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
776 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
777 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
778 else if (decl_function_context (decl))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
779 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
780 error ("%q+D alias functions must be global", name);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
781 *no_add_attrs = true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
782 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
783 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
784 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
785 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
786 tree id;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
787
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
788 id = TREE_VALUE (args);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
789 if (TREE_CODE (id) != STRING_CST)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
790 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
791 error ("attribute %qE argument not a string", name);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
792 *no_add_attrs = true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
793 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
794 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
795 id = get_identifier (TREE_STRING_POINTER (id));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
796 /* This counts as a use of the object pointed to. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
797 TREE_USED (id) = 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
798
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
799 if (TREE_CODE (decl) == FUNCTION_DECL)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
800 DECL_INITIAL (decl) = error_mark_node;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
801 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
802 TREE_STATIC (decl) = 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
803
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
804 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
805 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
806 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
807
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
808 /* Handle a "weak" attribute; arguments as in
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
809 struct attribute_spec.handler. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
810
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
811 static tree
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
812 d_handle_weak_attribute (tree *node, tree name,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
813 tree ARG_UNUSED (args),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
814 int ARG_UNUSED (flags),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
815 bool * ARG_UNUSED (no_add_attrs))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
816 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
817 if (TREE_CODE (*node) == FUNCTION_DECL
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
818 && DECL_DECLARED_INLINE_P (*node))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
819 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
820 warning (OPT_Wattributes, "inline function %q+D declared weak", *node);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
821 *no_add_attrs = true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
822 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
823 else if (VAR_OR_FUNCTION_DECL_P (*node))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
824 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
825 struct symtab_node *n = symtab_node::get (*node);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
826 if (n && n->refuse_visibility_changes)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
827 error ("%q+D declared weak after being used", *node);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
828 declare_weak (*node);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
829 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
830 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
831 warning (OPT_Wattributes, "%qE attribute ignored", name);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
832
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
833 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
834 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
835