为__attribute __支持自定义((格式)) [英] Custom support for __attribute__((format))

查看:158
本文介绍了为__attribute __支持自定义((格式))的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

GCC和锵两者都有支持,使对可变参数的功能,如的printf 编译时检查。这些编译器接受的语法如下:

Both GCC and Clang have a support to make compile-time checks on variable argument functions like printf. These compilers accept syntax like:

extern void dprintf(int dlevel, const char *format, ...)
  __attribute__((format(printf, 2, 3)));  /* 2=format 3=params */

在OSX中,Cocoa框架也使用了这样的一个扩展的NSString

On OSX, the Cocoa framework also use an extension of this for NSString:

#define NS_FORMAT_FUNCTION(F,A) __attribute__((format(__NSString__, F, A)))

在我们公司,我们有像一堆类即basestring 自定义的C ++框架从 BaseObject 所有派生。在即basestring 有几个可变参数的方法类似于的sprintf ,但也有一些扩展。例如,%S预计类型的参数即basestring * % @需要一个 BaseObject * 参数。

In our company, we have a custom C++ framework with a bunch of classes like BaseString all deriving from BaseObject. In BaseString there are a few variable argument methods similar to sprintf, but with some extensions. For example, "%S" expects an argument of type BaseString*, and "%@" expects a BaseObject* argument.

我想执行的在我们的项目参数的编译时检查,但由于扩展, __属性__((格式(printf的)))给很多假阳性警告。

I would like to perform a compile-time check of the arguments in our projects, but because of the extensions, __attribute__((format(printf))) give lots of false positive warnings.

有没有一种方法来定制 __ __属性的支持((格式))两个编译器中的一个?如果需要修补程序编译器源代码,它是可行的在一个合理的时间?另外,是否有其他的皮棉的喜欢,可以执行检查工具?

Is there a way to customize the support of __attribute__((format)) for one of the two compilers ? If this requires a patch to the compiler source, is it doable in a reasonable amount of time ? Alternatively, are there other lint like tools that could perform the check ?

推荐答案

问了这个问题,一年半后,我想出了一个完全不同的方法来解决真正的问题:有什么办法静态检查类型的自定义可变参数的格式化报表?

One year and a half after having asked this question, I came out with a totally different approach to solve the real problem: Is there any way to statically check the types of custom variadic formatting statements?

有关完整,因为它可以帮助其他人,这里是解决方案,我终于实现。它拥有超过原来的问题有两个好处:

For completeness and because it can help other people, here is the solution I have finally implemented. It has two advantages over the original question:


  • 比较简单:在不到一天的时间来实现;

  • 编译器独立:可以检查C ++ code任何平台(Windows,Android的,OSX,...)上

一个Perl脚本解析源$ C ​​$ C,认定该格式字符串和德codeS里面他们百分之修饰。然后,将全部的论点为模板的身份函数的调用 CheckFormat<> 。例如:

A Perl script parses the source code, finds the formatting strings and decodes the percent modifiers inside them. It then wraps all arguments with a call to a template identity function CheckFormat<>. Example:

str->appendFormat("%hhu items (%.2f %%) from %S processed", 
    nbItems, 
    nbItems * 100. / totalItems, 
    subject);

变成了:

str->appendFormat("%hhu items (%.2f %%) from %S processed", 
    CheckFormat<CFL::u, CFM::hh>(nbItems  ), 
    CheckFormat<CFL::f, CFM::_>(nbItems * 100. / totalItems  ), 
    CheckFormat<CFL::S, CFM::_, const BaseString*>(subject  ));

该枚举 CFL CFM 和模板函数 CheckFormat 必须在这样的公共头文件中定义(这是一个提取物,大约有24重载)。

The enumerations CFL, CFM and the template function CheckFormat must be defined in a common header file like this (this is an extract, there are around 24 overloads).

enum class CFL
{
    c, d, i=d, star=i, u, o=u, x=u, X=u, f, F=f, e=f, E=f, g=f, G=f, p, s, S, P=S, at
};
enum class CFM
{
    hh, h, l, z, ll, L=ll, _
};
template<CFL letter, CFM modifier, typename T> inline T CheckFormat(T value) { CFL test= value; (void)test; return value; }
template<> inline const BaseString* CheckFormat<CFL::S, CFM::_, const BaseString*>(const BaseString* value) { return value; }
template<> inline const BaseObject* CheckFormat<CFL::at, CFM::_, const BaseObject*>(const BaseObject* value) { return value; }
template<> inline const char* CheckFormat<CFL::s, CFM::_, const char*>(const char* value) { return value; }
template<> inline const void* CheckFormat<CFL::p, CFM::_, const void*>(const void* value) { return value; }
template<> inline char CheckFormat<CFL::c, CFM::_, char>(char value) { return value; }
template<> inline double CheckFormat<CFL::f, CFM::_, double>(double value) { return value; }
template<> inline float CheckFormat<CFL::f, CFM::_, float>(float value) { return value; }
template<> inline int CheckFormat<CFL::d, CFM::_, int>(int value) { return value; }

...

具有编译错误后,很容易用常规的前pression恢复原来的形式 CheckFormat&LT; [^&LT;] *&GT; \\(?(*)\\) 其捕获取代。

这篇关于为__attribute __支持自定义((格式))的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆