4.3.1.7.5.6.5. 处理内建函数的属性
4.3.1.7.5.6.5.1. 建立属性处理方法
虽然我们已经为内建函数的属性创建了节点,我们还未将它们加入到内建函数的节点中。而且即使没有属性,我们也需要在函数节点中明确地表示出来。
builtin_function_1 (continue)
3253 /* Possibly apply some default attributes to this built-in function. */
3254 if (attrs)
3255 decl_attributes (&decl, attrs, ATTR_FLAG_BUILT_IN);
3256 else
3257 decl_attributes (&decl, NULL_TREE, 0);
3258
3259 return decl;
3260 }
显然,语言定义出了可用的属性集的,进一步,某些属性的处理因平台而有不同。因此,首先我们需要根据语言及目标平台设定的处理方法。
139 tree
140 decl_attributes (tree *node, tree attributes, int flags) in attribs.c
141 {
142 tree a;
143 tree returned_attrs = NULL_TREE;
144
145 if (!attributes_initialized)
146 init_attributes ();
属性的处理方法由attribute_spec连同其它运行时信息收集在一起。在GCC v3.4.6,这些方法被分为4个集合。
42 static const struct attribute_spec *attribute_tables[4]; in attribs.c
2181 struct attribute_spec in tree.h
2182 {
2183 /* The name of the attribute (without any leading or trailing __),
2184 or NULL to mark the end of a table of attributes. */
2185 const char *const name;
2186 /* The minimum length of the list of arguments of the attribute. */
2187 const int min_length;
2188 /* The maximum length of the list of arguments of the attribute
2189 (-1 for no maximum). */
2190 const int max_length;
2191 /* Whether this attribute requires a DECL. If it does, it will be passed
2192 from types of DECLs, function return types and array element types to
2193 the DECLs, function types and array types respectively; but when
2194 applied to a type in any other circumstances, it will be ignored with
2195 a warning. (If greater control is desired for a given attribute,
2196 this should be false, and the flags argument to the handler may be
2197 used to gain greater control in that case.) */
2198 const bool decl_required;
2199 /* Whether this attribute requires a type. If it does, it will be passed
2200 from a DECL to the type of that DECL. */
2201 const bool type_required;
2202 /* Whether this attribute requires a function (or method) type. If it does,
2203 it will be passed from a function pointer type to the target type,
2204 and from a function return type (which is not itself a function
2205 pointer type) to the function type. */
2206 const bool function_type_required;
2207 /* Function to handle this attribute. NODE points to the node to which
2208 the attribute is to be applied. If a DECL, it should be modified in
2209 place; if a TYPE, a copy should be created. NAME is the name of the
2210 attribute (possibly with leading or trailing __). ARGS is the TREE_LIST
2211 of the arguments (which may be NULL). FLAGS gives further information
2212 about the context of the attribute. Afterwards, the attributes will
2213 be added to the DECL_ATTRIBUTES or TYPE_ATTRIBUTES, as appropriate,
2214 unless *NO_ADD_ATTRS is set to true (which should be done on error,
2215 as well as in any other cases when the attributes should not be added
2216 to the DECL or TYPE). Depending on FLAGS, any attributes to be
2217 applied to another type or DECL later may be returned;
2218 otherwise the return value should be NULL_TREE. This pointer may be
2219 NULL if no special handling is required beyond the checks implied
2220 by the rest of this structure. */
2221 tree (*const handler) (tree *node, tree name, tree args,
2222 int flags, bool *no_add_attrs);
2223 };
这4个集合的详细信息显示在下面的4个表中。
属性名字 | 最少 参数 | 最多参数 | del_req | type_req | func_req | 处理方法 |
packed | 0 | 0 | false | false | False | handle_packed_attribute |
nocommon | 0 | 0 | true | false | False | handle_nocommon_attribute |
common | 0 | 0 | true | false | False | handle_common_attribute |
noreturn | 0 | 0 | true | false | False | handle_noreturn_attribute |
volatile | 0 | 0 | true | false | False | handle_noreturn_attribute |
noinline | 0 | 0 | true | false | False | handle_noinline_attribute |
always_inline | 0 | 0 | true | false | False | handle_always_inline_attribute |
used | 0 | 0 | true | false | False | handle_used_attribute |
unused | 0 | 0 | false | false | False | handle_unused_attribute |
const | 0 | 0 | true | false | False | handle_const_attribute |
transparent_union | 0 | 0 | false | false | False | handle_transparent_union_attribute |
constructor | 0 | 0 | true | false | False | handle_constructor_attribute |
destructor | 0 | 0 | true | false | False | handle_destructor_attribute |
mode | 1 | 1 | false | true | false | handle_mode_attribute |
section | 1 | 1 | true | false | false | handle_section_attribute |
aligned | 0 | 1 | false | false | false | handle_aligned_attribute |
weak | 0 | 0 | true | false | false | handle_weak_attribute |
alias | 1 | 1 | true | false | false | handle_alias_attribute |
no_instrument_function | 0 | 0 | true | false | false | handle_no_instrument_function_attribute |
malloc | 0 | 0 | true | false | false | handle_malloc_attribute |
no_stack_limit | 0 | 0 | true | false | false | handle_no_limit_stack_attribute |
pure | 0 | 0 | true | false | false | handle_pure_attribute |
deprecated | 0 | 0 | false | false | false | handle_deprecated_attribute |
vector_size | 1 | 1 | false | true | false | handle_vector_size_attribute |
visibility | 1 | 1 | true | false | false | handle_visibility_attribute |
tls_model | 1 | 1 | true | false | false | handle_tls_model_attribute |
nonnull | 0 | -1 | false | true | true | handle_nonnull_attribute |
nothrow | 0 | 0 | true | false | false | handle_nothrow_attribute |
may_alias | 0 | 0 | false | true | false | NULL |
cleanup | 1 | 1 | true | false | false | handle_cleanup_attribute |
warn_unused_result | 0 | 0 | false | true | true | handle_warn_unused_result_attribute |
表12:用于C++的common_attribute_table中的内建函数
属性名字 | 最少 参数 | 最多参数 | del_req | type_req | func_req | 处理方法 |
java_interface | 0 | 0 | false | false | false | handle_java_interface_attribute |
com_interface | 0 | 0 | false | false | false | handle_com_interface_attribute |
init_priority | 1 | 1 | true | false | false | handle_init_priority_attribute |
表13:用于C++的attribute_table中的内建函数
属性名字 | 最少 参数 | 最多参数 | del_req | type_req | func_req | 处理方法 |
format | 3 | 3 | false | true | true | handle_format_attribute |
format_arg | 1 | 1 | false | true | true | handle_format_arg_attribute |
表14:用于C++的format_attribute_table中的内建函数
属性名字 | 最少 参数 | 最多参数 | del_req | type_req | func_req | 处理方法 |
stdcall | 0 | 0 | false | true | true | ix86_handle_cdecl_attribute |
fastcall | 0 | 0 | false | true | true | ix86_handle_cdecl_attribute |
cdecl | 0 | 0 | false | true | true | ix86_handle_cdecl_attribute |
regparm | 1 | 1 | false | true | true | ix86_handle_regparm_attribute |
ms_struct | 0 | 0 | false | false | false | ix86_handle_struct_attribute |
gcc_struct | 0 | 0 | false | false | false | ix86_handle_struct_attribute |
表15:用于C++的ix86_attribute_table中的内建函数
从下面的代码中,可以看到前3个表来自语言钩子,由语言来决定其内容;而最后的一个表是与语言无关,但依赖于平台的属性。
55 static void
56 init_attributes (void) in attribs.c
57 {
58 size_t i;
59
60 attribute_tables[0] = lang_hooks.common_attribute_table;
61 attribute_tables[1] = lang_hooks.attribute_table;
62 attribute_tables[2] = lang_hooks.format_attribute_table;
63 attribute_tables[3] = targetm.attribute_table;
64
65 /* Translate NULL pointers to pointers to the empty table. */
66 for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
67 if (attribute_tables[i] == NULL)
68 attribute_tables[i] = empty_attribute_table;
69
70 #ifdef ENABLE_CHECKING
...
125 #endif
126
127 attributes_initialized = true;
128 }
回忆对于内建函数“__builtin_vprintf”,其属性是built_in_attributes [ATTR_FORMAT_PRINTF_1_0],其节点形式如下图所示。
在上图中,可以清楚地看到属性节点通过域chain链接在一起,而域purpose则告知该属性作何用,并域value给出其内容。注意,域purpose实际上指向一个标识符节点。
decl_attributes (continue)
148 (*targetm.insert_attributes) (*node, &attributes);
149
150 for (a = attributes; a; a = TREE_CHAIN (a))
151 {
152 tree name = TREE_PURPOSE (a);
153 tree args = TREE_VALUE (a);
154 tree *anode = node;
155 const struct attribute_spec *spec = NULL;
156 bool no_add_attrs = 0;
157 tree fn_ptr_tmp = NULL_TREE;
158 size_t i;
159
160 for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
161 {
162 int j;
163
164 for (j = 0; attribute_tables[i][j].name != NULL; j++)
165 {
166 if (is_attribute_p (attribute_tables[i][j].name, name))
167 {
168 spec = &attribute_tables[i][j];
169 break;
170 }
171 }
172 if (spec != NULL)
173 break;
174 }
175
176 if (spec == NULL)
177 {
178 warning ("`%s' attribute directive ignored",
179 IDENTIFIER_POINTER (name));
180 continue;
181 }
182 else if (list_length (args) < spec->min_length
183 || (spec->max_length >= 0
184 && list_length (args) > spec->max_length))
185 {
186 error ("wrong number of arguments specified for `%s' attribute",
187 IDENTIFIER_POINTER (name));
188 continue;
189 }
在148行,对于x86机器,没有重新定义insert_attributes。默认地这个函数什么都不做。同时注意anode及node都是指针的指针,node一直保存着对应节点的地址,而anode根据情况,在节点中移动,寻找属性所应用的真正对象。为了澄清node的真正类属,参数flags给出了细节。当前,我们能用到如下的值:
ATTR_FLAG_DECL_NEXT:node是一个声明的类型,任一应该重新传入,以应用于声明而不是类型的属性,应该直接被返回。
ATTR_FLAG_FUNCTION_NEXT:node是一个函数返回类型,任一应该重新传入,以应用于函数类型,而不是返回类型的属性,应该被直接返回。
ATTR_FLAG_ARRAY_NEXT:node是一个数组元素的类型,任一应该重新传入,以应用于数组类型,而不是数组元素类型的属性,应该被直接返回。
ATTR_FLAG_TYPE_IN_PLACE:node是一个正在被创建的struct,union或enum类型,应该直接进行修改。
ATTR_FLAG_BUILT_IN:该属性默认地被应用于一个库函数,其名字显示其行为已知。如果属性事实上与函数类型不相符,它们将被无声地忽略。
这里,对于内建函数“__builtin_vprintf”, argument flags is ATTR_FLAG_BUILT_IN.
decl_attributes (continue)
191 if (spec->decl_required && !DECL_P (*anode))
192 {
193 if (flags & ((int) ATTR_FLAG_DECL_NEXT
194 | (int) ATTR_FLAG_FUNCTION_NEXT
195 | (int) ATTR_FLAG_ARRAY_NEXT))
196 {
197 /* Pass on this attribute to be tried again. */
198 returned_attrs = tree_cons (name, args, returned_attrs);
199 continue;
200 }
201 else
202 {
203 warning ("`%s' attribute does not apply to types",
204 IDENTIFIER_POINTER (name));
205 continue;
206 }
207 }
208
209 /* If we require a type, but were passed a decl, set up to make a
210 new type and update the one in the decl. ATTR_FLAG_TYPE_IN_PLACE
211 would have applied if we'd been passed a type, but we cannot modify
212 the decl's type in place here. */
213 if (spec->type_required && DECL_P (*anode))
214 {
215 anode = &TREE_TYPE (*anode);
216 flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE;
217 }
218
219 if (spec->function_type_required && TREE_CODE (*anode) != FUNCTION_TYPE
220 && TREE_CODE (*anode) != METHOD_TYPE)
221 {
222 if (TREE_CODE (*anode) == POINTER_TYPE
223 && (TREE_CODE (TREE_TYPE (*anode)) == FUNCTION_TYPE
224 || TREE_CODE (TREE_TYPE (*anode)) == METHOD_TYPE))
225 {
226 /* OK, this is a bit convoluted. We can't just make a copy
227 of the pointer type and modify its TREE_TYPE, because if
228 we change the attributes of the target type the pointer
229 type needs to have a different TYPE_MAIN_VARIANT. So we
230 pull out the target type now, frob it as appropriate, and
231 rebuild the pointer type later.
232
233 This would all be simpler if attributes were part of the
234 declarator, grumble grumble. */
235 fn_ptr_tmp = TREE_TYPE (*anode);
236 anode = &fn_ptr_tmp;
237 flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE;
238 }
239 else if (flags & (int) ATTR_FLAG_FUNCTION_NEXT)
240 {
241 /* Pass on this attribute to be tried again. */
242 returned_attrs = tree_cons (name, args, returned_attrs);
243 continue;
244 }
245
246 if (TREE_CODE (*anode) != FUNCTION_TYPE
247 && TREE_CODE (*anode) != METHOD_TYPE)
248 {
249 warning ("`%s' attribute only applies to function types",
250 IDENTIFIER_POINTER (name));
251 continue;
252 }
253 }
254
255 if (spec->handler != NULL)
256 returned_attrs = chainon ((*spec->handler) (anode, name, args,
257 flags, &no_add_attrs),
258 returned_attrs);
参考C++的format_attribute_table表,对于属性format,它应用于类型或函数类型,但node是一个FUNCTION_DECL。不过在215行,anode被更新为声明的类型——builtin_types [BT_FN_INT_CONST_STRING_VALIST_ARG]。