现在的位置: 首页 > 综合 > 正文

GCC-3.4.6源代码学习笔记(61)

2013年01月12日 ⁄ 综合 ⁄ 共 3671字 ⁄ 字号 评论关闭

4.3.1.7.5.6.5.2.        处理format属性

对于printfscanf等类型的函数,真正的检查要在调用处进行。在其声明中,只进行少许检查,由handle_format_attribute 执行。现在参数args是节点ATTR_PRINTF_1_0,而传入的no_add_attrs0

 

2741   tree

2742   handle_format_attribute (tree *node, tree name ATTRIBUTE_UNUSED,      in c-format.c

2743                      tree args, int flags, bool *no_add_attrs)

2744   {

2745     tree type = *node;

2746     function_format_info info;

2747     tree argument;

2748  

2749     if (!decode_format_attr (args, &info, 0))

2750     {

2751       *no_add_attrs = true;

2752       return NULL_TREE;

2753     }

 

第一步是验证属性ATTR_PRINTF_1_0。工作很简单——检查要求的格式是有效的,所带的实参是合理的。编译器定义了下面的类型来携带所需要的信息。

 

58      enum format_type { printf_format_type, asm_fprintf_format_type,                     in c-format.c

59                     gcc_diag_format_type, gcc_cdiag_format_type,

60                     gcc_cxxdiag_format_type,

61                     scanf_format_type, strftime_format_type,

62                     strfmon_format_type, format_type_error };

 

64      typedef struct function_format_info

65      {

66        enum format_type format_type;     /* type of format (printf, scanf, etc.) */

67        unsigned HOST_WIDE_INT format_num;    /* number of format argument */

68        unsigned HOST_WIDE_INT first_arg_num; /* number of first arg (zero for varargs) */

69      } function_format_info;

 

178    static bool

179    decode_format_attr (tree args, function_format_info *info, int validated_p) in c-format.c

180    {

181      tree format_type_id = TREE_VALUE (args);

182      tree format_num_expr = TREE_VALUE (TREE_CHAIN (args));

183      tree first_arg_num_expr

184        = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args)));

185   

186      if (TREE_CODE (format_type_id) != IDENTIFIER_NODE)

187      {

188        if (validated_p)

189          abort ();

190        error ("unrecognized format specifier");

191         return false;

192      }

193      else

194      {

195        const char *p = IDENTIFIER_POINTER (format_type_id);

196   

197        info->format_type = decode_format_type (p);

198   

199        if (info->format_type == format_type_error)

200        {

201          if (validated_p)

202            abort ();

203          warning ("`%s' is an unrecognized format function type", p);

204          return false;

205        }

206      }

 

验证格式的类型简单明了。为了保存所有格式类型的信息,GCC维护了一个全局数组format_types,该数组以format_type为索引。在format_types中找出格式所对应的名字就能得到答案。

 

1036   static enum format_type

1037   decode_format_type (const char *s)                                                           in c-format.c

1038   {

1039     int i;

1040     int slen;

1041     slen = strlen (s);

1042     for (i = 0; i < (int) format_type_error; i++)

1043     {

1044       int alen;

1045      if (!strcmp (s, format_types[i].name))

1046         break;

1047       alen = strlen (format_types[i].name);

1048       if (slen == alen + 4 && s[0] == '_' && s[1] == '_'

1049           && s[slen - 1] == '_' && s[slen - 2] == '_'

1050           && !strncmp (s + 2, format_types[i].name, alen))

1051         break;

1052     }

1053     return ((enum format_type) i);

1054   }

 

而对于格式属性的参数的要求是,它们必须是常量,而且格式字符串必须出现在要被格式的参数之前(如果有的话,记住0表示不使用)。

 

decode_format_attr (continue)

 

208      if (!get_constant (format_num_expr, &info->format_num, validated_p))

209      {

210        error ("format string has invalid operand number");

211         return false;

212      }

213   

214      if (!get_constant (first_arg_num_expr, &info->first_arg_num, validated_p))

215      {

216        error ("'...' has invalid operand number");

217        return false;

218      }

219   

220      if (info->first_arg_num != 0 && info->first_arg_num <= info->format_num)

221      {

222        if (validated_p)

223          abort ();

224        error ("format string arg follows the args to be formatted");

225        return false;

226      }

227   

228      return true;

229    }

 

现在下面的typebuiltin_types [BT_FN_INT_CONST_STRING_VALIST_ARG]——内建函数“__builtin_vprintf”的类型。对于对应格式字符串的参数,它应该是const_string_type_node,这个类型在c_common_nodes_and_builtins中创建,是代表“const char*”的节点。

 

handle_format_attribute (continue)

 

2755     argument = TYPE_ARG_TYPES (type);

2756     if (argument)

2757     {

2758       if (!

抱歉!评论已关闭.