Studying note of GCC-3.4.6 source (60)

4.3.1.7.5.6.5.              Processing attributes of builtin

4.3.1.7.5.6.5.1.        Install attribute handlers

Though we create nodes for attributes of builtin functions, we still don’t install them into the builtin function. And even there is no attribute, we should express this fact in the function node explicitly.

 

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   }

 

Obviously, the language determines the set of available attributes, further some attributes’ processing methods depend on target. So first, we need to select out the correct methods according to the language and the target.

 

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 handling methods are collected by attribute_spec with other running information. In GCC v3.4.6, the methods are grouped into 4 sets.

 

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   };

 

The detail information about these 4 sets are given in following 4 tables.

name

min args

max args

del_req

type_req

func_req

handler

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

Table 12: builtin functions of common_attribute_table for C++

name

min args

max args

del_req

type_req

func_req

handler

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

Table 13: builtin function of attribute_table for C++

name

min args

max args

del_req

type_req

func_req

handler

format

3

3

false

true

true

handle_format_attribute

format_arg

1

1

false

true

true

handle_format_arg_attribute

Table 14: builtin function of format_attribute_table for C++

name

min args

max args

del_req

type_req

func_req

handler

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

Table 15: builtin function of ix86_attribute_table for x86 machine

In below code, it can see that the first 3 tables are set by language hook, which have their content filled by the language; and in the last table are attributes unrelated to language but depend on target.

 

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    }

 

Remember that in the builtin function “__builtin_vprintf”, its attributes are given in built_in_attributes [ATTR_FORMAT_PRINTF_1_0], and its structure is shown is below figure.

d

In this image, it is clearly that attributes are linked tegother by field chain, with field purpose tells out what it is for and field value gives out its content. Notice that purpose field in fact is a node of identifier.

 

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        }

 

At line 148, for x86 machine, insert_attributes is not redefined. It does nothing by default. Andnote that anode and node are both pointer of pointer, node always keeps the address of the tree node, and anode transfer within the node for searching the real object the attributes being applied. To clarify the real kind of the node, argument flags is used give out the detail. Currently, below enumerators are in used:

ATTR_FLAG_DECL_NEXT: node is the type of a declaration, and any attributes that should be passed in again to be applied to the declaration rather than the type should be returned.

ATTR_FLAG_FUNCTION_NEXT: node is a function-return-type, and any attributes that should be passed in again to be applied to the function type rather than the return type should be returned.

ATTR_FLAG_ARRAY_NEXT: node is an array-element-type, and any attributes that should be passed in again to be applied to the array type rather than the element type should be returned.

ATTR_FLAG_TYPE_IN_PLACE: node is a struct, union or enum type being created, and should be modified in place.

ATTR_FLAG_BUILT_IN: The attributes are being applied by default to a library function whose name indicates known behavior, and should be silently ignored if they are not in fact compatible with the function type.

Here for builtin “__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);

 

Refer to builtin function for format_attribute_table for C++, for attribute of format, it requires type and function type, but node is a FUNCTION_DECL. However, at line 215, anode is updated to the type of declaration - builtin_types [BT_FN_INT_CONST_STRING_VALIST_ARG].

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值