通过bash脚本查找和修改函数定义(C ++)

5

目前我正在从事一个相当大的项目。为了提高我们代码的质量,我们决定强制在每个函数中处理返回值(错误代码)。GCC支持有关函数返回值的警告,但函数定义必须先于以下标志。

static __attribute__((warn_unused_result)) ErrorCode test() { /* code goes here */ }

我希望你能实现一个bash脚本,解析整个源码,并在出现以下情况时发出警告:
__attribute__((warn_unused_result))

缺失。请注意,所有需要这种修改的函数都返回一个叫做 ErrorCode 的类型。你认为这可以通过一个 bash 脚本实现吗?


我建议您考虑将此编写为clang插件。我编写了一个插件,分析符号使用并警告大约350行代码中的无用包含,因此它并不特别困难。 - Dark Falcon
3个回答

5
也许你可以使用带有正则表达式的 sed 工具。以下命令在我测试的几个文件中都有效:
sed -r "s/ErrorCode\s+\w+\s*(.*)\s*\{/__attribute__((warn_unused_result)) \0/g" test.cpp

如果您对正则表达式不熟悉,那么该模式基本上转换为:
错误代码,一些空格,一些字母数字(函数名称),可能有一些空格,打开括号,任何内容(参数),关闭括号,可能有一些空格,打开大括号。
如果找到此模式,则在前面加上__attribute__((warn_unused_result))。请注意,仅当您始终将开放大括号放在与参数相同的行中,并且在函数声明中没有换行符时,才能使用此方法。

谢谢!我想我可以用这个。但是它可能会产生很多错误。据我所知,这将自动替换指定的出现次数。对于我的口味来说,这有点太过激进了。是否有任何选项,使命令仅返回可能进行替换的行和文件,以便我仍然可以决定是否进行替换? - Flo Ryan
你可以使用 grep -E "ErrorCode\s+\w+\s*(.*)\s*\{" 来打印所有符合正则表达式的行。 - Jonas Greitemann

3
一个简单的方法是通过使用ctags。您可以在所有源代码上创建一个标记文件,然后解析标记文件。但是,我不太确定标记文件的格式。我在这里使用的变体(Exuberant Ctags 5.8)似乎会在第四列中放置一个“f”,如果标记表示一个函数。因此,在这种情况下,我将使用awk来过滤表示函数的所有标记,然后使用grep来丢弃所有没有__attribute__((warn_unused_result))的行。

因此,简而言之,首先执行以下操作:

$ ctags **/*.c

这将在当前目录中创建一个名为“tags”的文件。命令可能也是ctags-exuberant,具体取决于您的变量。 ** / * .c 是一种在您的shell中可能有效的全局模式-如果不行,则必须以另一种方式提供您的源文件(查看ctags选项)。

然后你需要过滤函数:

$ cat tags | awk -F '\t' '$4 == "f" {print $0}' | grep -v "__attribute__((warn_unused_result))"

我看了一下这个,似乎很有前途。然而据我所知,这种方法并不关心函数返回值的类型。然而,我只想处理返回值为ErrorCode的函数。 - Flo Ryan
啊,抱歉,我在你的问题中错过了那个。那么,你需要用正则表达式来尝试一下。第一次尝试可能会像这样:cat tags | awk -F '\t' '$4 == "f" {print $3}' | grep '.*ErrorCode .*('。请注意,我让awk只打印列$3,其中包含了我的版本ctags中函数的模式。但是,我不太确定在特殊情况下是否有效,例如当返回类型与函数名不在同一行时。你应该多试试并控制结果。 - Georg P.

1
不,通常情况下是不可能的。我所知道的语言中,C++语法最为复杂,并且在一般情况下无法通过正则表达式解析C++。如果你限制自己使用非常狭窄的用途,你可能会成功,但我不确定在你的情况下是否可行。 我也认为这个练习不值得花费精力,因为有时忽略函数的结果是可以的。

这并不复杂,它是一种相当严格的语言。 - 123
1
好的,有些东西可以同时非常严格和非常复杂。就像我之前说的,无法对一般的C++代码进行正则表达式解析。 - SergeyA
解析通过ctags创建的文件对我很有用。还可以处理命名空间、内联函数、模板等内容... - Flo Ryan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接