我们想从一个类类型中找到所有的指针比较。例如,我们有一个类a和从a派生的类B、C等。
A *pa;
A *pa2;
B *pb;
所有比较,如if (pa == pa2)或if (pa != pb)必须在源代码中找到。
我知道我们可以使用CLang分析器来查找这些比较,但是我们的源代码与CLang不兼容。我们使用的是visual studio 2015。
请不要给出这样的解决方案;从源代码中删除类A,然后尝试编译它,以便找到类A中不能编译的所有用法。
谁有办法找到它?像CppCheck这样的工具(检查可能的错误)或Visual Studio扩展?
编辑:有人知道吗,我怎么能找到我的代码与CppDepend/CQLinq语法的所有比较?它也可以帮助我。CppDepend使用CLang,但如果有解析错误,它会继续解析。
我们的DMS软件再造工具包及其c++ 14前端可以用来做这件事。
DMS是一种通用的程序分析和转换机制,可以对其进行定制,以实现对作为插件模块提供给它的编程语言的预期效果。它的c++ 14前端可配置地处理纯ANSI、GCC/clang风格的语法或Visual Studio语法。它包括一个完整的预处理器。要实现OP的目的,可以将DMS配置为:
- 解析编译单元,生成AST。
- 为每个编译单元执行名称和类型解析。这将构建包含类型信息的符号表,并提供基础用于计算任意表达式的类型。这种能力是内置到DMS的c++前端。
- 抓取AST,查找操作符==和!=
- 要求DMS计算右侧和左侧子表达式的类型
- 验证类型是目标类,还是从目标类继承的类型。(假设目标类被识别为定义在某个源文件/行位置;这可以通过搜索符号表来找到。检查一种类型是否从另一种类型派生,只需递归搜索为符号表记录的可能的多个父链接(链接以检查父链接是否为所需的目标类型)。
- 报告操作员的文件名、源行和列。
以上每个步骤都由DMS和c++ 14前端提供的机制/api直接支持。这可能需要将几页自定义代码添加到DMS中才能实现此效果。
我的解决方案是:(如@M。M说)用模板包装器类包装指针,它实现了像-> *
这样的操作符重载(因此减少了编译问题),并删除了像== !=
这样的比较操作符(因此找到了编译错误的比较)。可以用正则表达式替换所有指针。(A *
with A_Wrapper
)
我还发现,在map中使用指针类似于指针比较。如果你在映射中使用指针,你也应该在你的包装类中删除<
-Operator。
当然,我有编译错误,但这些错误并不难解决。这似乎是一定的解决办法。
我猜我错过了这个问题。因此,您只需通过比较找到指向类型A, B, C等的指针的所有实例,其中指针在条件表达式中使用…
那么你知道所有的类型名了。这意味着有有限的类型和有限的比较,例如== != <=>= <>对吧?
因此,对于所有类型创建的每个指针实例,构建一个表。这将为您提供正在查找的每个指针的编码名称。
fred *myfred, *yourfred, *thefred;
account *primaryacct, *secondacct;…等等…
您的表应该是:
myfred
yourfred
thefred
primaryacct
secondacct
现在对于每一个的每个实例-从第一个'myfred'开始查找myfred后面跟着==然后是!=等等(吸收任何空格),当你找到第一个(比较的左侧)时,例如
secondacct<=
,然后得到右边),并将其与构建的表中的每个指针编码名称进行比较。当你有一个像我弗雷德这样的对手!你爱怎么用它就怎么用吧。为了便于讨论,我们假设您希望执行全局搜索并替换给定的比较或比较列表,您可以通过打开另一个文件进行输出来执行此操作,当您读入并找到每个事件时,您可以将其输出到新的源代码文件中。
基本上就是找到每一个比较,看看它的每一边,看看两边是否都有一个编码名称在你的表中。从本质上讲,您只是在比较字符串的有限组合的两侧使用相同的标识符表来解析代码-它们仍然是:[== != <=>= <</p>>)
我不知道有什么软件工具可以做到这一点,但是你可以很快地编写这个代码。当然,它只有一个目的,但它会让工作很快完成。
我当然假设您的源代码是文本形式,并且您可以打开文件并读取它来完成此操作。如果是这样,那么您可以得到任何您喜欢的结果,例如,为每个文件和行找到每个表达比较的出现列表。
在读取-
时抓取整行代码在C中-只需使用fgets
在c++中使用getline
然后用上面描述的逻辑解析你读入的缓冲区。
-------------- 编辑 --------------- 关于评论
@YusufRamazanKaragöz - Oak -我为过度概括道歉。您是否有机会提供一个包含其中一些问题的代码示例—例如,如果它包含多行怎么办?我的思维过程是基于你写的"所有比较,如if (pa == pa2)或if (pa != pb)必须在我们的源代码中找到",没有更多的东西,所以我没有扩展到函数返回等。至于构建表格——你知道类型,对吗?因此,对于每一行声明了这些类型变量的代码,你都应该这样构建它。例如,如果我想要一个包含程序所有文件的每行代码中每个char定义变量的表——我将在所有行中搜索char这个词。然后,在该行之后,我会寻找逗号分隔的字符串,直到没有逗号或分号(可以继续到下一行,因此使用fget代替fgets)。有些声明是直接的,有些可能是*char,有些是char[] -等等。然后我就有了一个包含所有char类型变量的列表。我的意思是,如果你对你正在谈论的类型名执行搜索,你不能看到它出现的行,以及它之后声明的所有内容吗?如果可以,那么就可以构建索引表。还是有什么原因让我不明白为什么不能这么做?查找强制转换值会创建另一组解析规则,并使任务进一步复杂化,就像模板到对象的比较一样。从最初的问题开始,直到现在我才真正理解你的困境。我真的很想提供帮助,但也许一段涵盖每种解析范式的代码可以帮助我确定我是否可以。事实上,如果你能告诉我你为什么要这么做的话会让我更好地思考。你想要全球性地改变某些东西吗?如果你认为努力是徒劳的,我当然会听从你的决定,停止尝试。谢谢你的时间和耐心,我希望你能找到一个解决方案。