如何计算重载运算符在具有特定类型操作数的代码库中使用的次数
How can I count number of times an overloaded operator was used in a code base with particular type of operands
我有一个模板化的类SafeInt<T>
(由Microsoft提供)。
理论上,这个类可以用来代替POD整数类型,并且可以在算术运算期间检测任何整数溢出。
对于这个类,我编写了一些自定义的模板化重载算术运算符(+、-、*、/)函数,它们的两个参数都是SafeInt<T>
的对象。
我把所有的整数类型都定义为SafeInt类类型。
我想在我的代码库中搜索上述二进制运算符的实例,其中两个操作数都是SafeInt类型。
我能想到的一些方法
-
使用正则表达式进行字符串搜索,并在代码中清除,以检测两个操作数都是SafeInt对象的运算符使用实例。
-
编写一个clang工具并处理AST来进行搜索(我还没有学会如何编写这样的工具。)
-
不知何故,添加一个计数器来计算自定义重载运算符的实例化次数。我花了很多时间尝试,但似乎不起作用。
有人能提出更好的方法吗?
如果我需要澄清什么,请告诉我。
谢谢。
简短回答
您可以使用clang-query
命令执行此操作:
$ clang-query
-c='m cxxOperatorCallExpr(callee(functionDecl(hasName("operator+"))), hasArgument(0, expr(hasType(cxxRecordDecl(hasName("SafeInt"))))), hasArgument(1, expr(hasType(cxxRecordDecl(hasName("SafeInt"))))))'
use-si.cc --
Match #1:
/home/scott/wrk/learn/clang/clang-query1/use-si.cc:10:3: note: "root" binds here
x + y; // reported
^~~~~
1 match.
什么是clang查询
clang-query
是一个实用程序,旨在帮助编写clang-tidy
检查。特别是,它理解AST Matchers的语言,可以用于交互式地探索给定匹配表达式匹配的内容。然而,如图所示,它也可以非交互式地用于查找任意的AST树模式。
StephenKelly的博客文章Exploring Clang Tooling Part 2:Examine The Clang AST with Clang query为clang-query
的使用提供了一个很好的介绍。
clang-query
程序包含在预构建的LLVM二进制文件中,也可以按照AST Matchers教程中的说明从源代码构建。
以上命令是如何工作的
-c
参数提供了一个非交互运行的命令。添加空白后,命令为:
m // Match (and report) every
cxxOperatorCallExpr( // operator function call
callee(functionDecl( // where the callee
hasName("operator+"))), // is "operator+", and
hasArgument(0, // where the first argument
expr(hasType(cxxRecordDecl( // is a class type
hasName("SafeInt"))))), // called "SafeInt",
hasArgument(1, // and the second argument
expr(hasType(cxxRecordDecl( // is also a class type
hasName("SafeInt")))))) // called "SafeInt".
命令行以use-si.cc --
结尾,意思是分析use-si.cc
,并且clang
不需要额外的编译器标志来解释它
clang-query
命令行具有与clang-tidy
相同的基本结构,包括通过-p compile_commands.json
一次扫描多个文件的能力,每个文件可能有不同的编译器选项。
示例输入
为了完整起见,我用来测试匹配器的输入是use-si.cc
:
// use-si.cc
#include "SafeInt.hpp" // SafeInt
void f1()
{
SafeInt<int> x(2);
SafeInt<int> y(3);
x + y; // reported
x + 2; // not reported
2 + x; // not reported
}
SafeInt.hpp
的来源https://github.com/dcleblanc/SafeInt,在Microsoft SafeInt页面上命名的回购。
要做到这一点,您显然必须能够识别重载到特定运算符定义的运算符的单独用途。从根本上讲,您需要C++编译器前端所做的工作:解析和名称解析(包括重载)。
显然,GCC和Clang具备这一基本能力。但您希望跟踪/显示特定运算符的所有用途。您可能会弯曲Clang(或GCC,更难),以便在逐个文件的基础上为您提供这些信息。
我们的DMS软件重组工具包及其C++前端也可以用于此。DMS提供通用的解析和符号表支持机制;C++前端专门为DMS处理具有完整、准确名称解析的C++,包括GCC5和MSVS2015的过载。它的符号表实际上为范围中的每个声明收集声明的点,以及该声明在精确源位置方面的使用列表。符号作用域包括作用域中有效的每个(重载)运算符的一个条目。你可以转到所需的符号表条目,枚举/计数引用列表以获得原始计数。DMS提供了标准的API。
我们的Java源浏览器使用相同类型的符号范围/定义/使用信息来构建基于HTML的类似JavaDoc的显示,在符号声明和使用之间具有完整的HTML链接。因此,对于任何符号声明,您都可以很容易地看到其用途。
C++前端有一个类似的HTMLizer,它在C++源代码上运行。它没有那么成熟/漂亮,但很结实。目前,它还没有显示声明符号的所有用途,但这将是一个非常简单的更改。
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 代码在main()中运行,但在函数中出现错误
- 在VS代码中交叉编译Windows与Linux上的MinGW的SDL程序
- 编译包含字符串的代码时遇到问题
- 我在c++代码中生成了一个运行时#3异常
- 如何在linux终端中同时编译和运行c++代码
- 为cl.exe(Visual Studio代码)指定命令行C++版本
- 在Linux for Windows上编译C++代码时出错
- 我的字符计数代码计算错误.为什么
- 孤立代码块在结构中引发异常
- 在编译C++代码(具有dlib和opencv)到WASM时面临问题
- GCC 带内联汇编和 -Ofast 为内存操作数生成额外的代码
- 没有运算符"[]"匹配这些操作数/没有模板化代码
- Visual studio:E0349 没有运算符<<匹配这些操作数(但代码中没有字符串)
- 编译逗号运算符的 C++ 代码右操作数中的错误不起作用
- 如何计算重载运算符在具有特定类型操作数的代码库中使用的次数
- 将.cpp更改为 .cu 后,>> C++ 代码中无法识别基本操作数
- 汇编程序代码,错误 C2443:操作数大小冲突
- 将C++代码从 VS2003 迁移到 VS2010 后出现错误 C2678,错误 C2679:二进制'=':未找到采用类型为 'int' 的右侧操作数的运算符
- 收到错误:将我的 c++ 代码从 Linux 移植到 android 时'asm'中的操作数约束不一致