叮当 AST 匹配 ostream <<
clang AST matching ostream <<
我正在尝试为某些涉及流媒体的场景编写一个整洁的检查。考虑这个简单的函数:
#include <iostream>
#include <stdint.h>
void foo(std::ostream& os, uint8_t i) {
os << i;
os << 4 << i;
}
如果我运行clang-query
来测试一些匹配器:
$ clang-query foo.cxx --
clang-query> match cxxOperatorCallExpr(hasOverloadedOperatorName("<<"))
// [ ... snip some std library matches ... ]
Match #7:
foo.cxx:5:5: note: "root" binds here
os << i;
^~~~~~~
Match #8:
foo.cxx:6:5: note: "root" binds here
os << 4 << i;
^~~~~~~~~~~~
Match #9:
foo.cxx:6:5: note: "root" binds here
os << 4 << i;
^~~~~~~
这与我在此程序中的所有 3 种operator<<
用途相匹配。伟大。但是,如果我尝试为第一个参数添加过滤器:
clang-query> match cxxOperatorCallExpr(hasOverloadedOperatorName("<<"), hasArgument(0, expr(hasType(asString("std::ostream")))))
Match #1:
foo.cxx:5:5: note: "root" binds here
os << i;
^~~~~~~
Match #2:
foo.cxx:6:5: note: "root" binds here
os << 4 << i;
^~~~~~~
就是这样。它与整个表达式不匹配 os << 4 << i
.为什么不呢?该表达式具有类型 std::ostream
。如果我直接转储 AST,我会看到:
|-CXXOperatorCallExpr 0x953f618 <line:6:5, col:16> 'basic_ostream<char, struct std::char_traits<char> >':'class std::basic_ostream<char>' lvalue
| |-ImplicitCastExpr 0x953f600 <col:13> 'basic_ostream<char, struct std::char_traits<char> > &(*)(basic_ostream<char, struct std::char_traits<char> > &, unsigned char)' <FunctionToPointerDecay>
| | `-DeclRefExpr 0x953f5d8 <col:13> 'basic_ostream<char, struct std::char_traits<char> > &(basic_ostream<char, struct std::char_traits<char> > &, unsigned char)' lvalue Function 0x94bcd40 'operator<<' 'basic_ostream<char, struct std::char_traits<char> > &(basic_ostream<char, struct std::char_traits<char> > &, unsigned char)'
| |-CXXOperatorCallExpr 0x953f160 <col:5, col:11> 'std::basic_ostream<char, struct std::char_traits<char> >::__ostream_type':'class std::basic_ostream<char>' lvalue
| | |-ImplicitCastExpr 0x953f148 <col:8> 'std::basic_ostream<char, struct std::char_traits<char> >::__ostream_type &(*)(int)' <FunctionToPointerDecay>
| | | `-DeclRefExpr 0x953f0c0 <col:8> 'std::basic_ostream<char, struct std::char_traits<char> >::__ostream_type &(int)' lvalue CXXMethod 0x94b7740 'operator<<' 'std::basic_ostream<char, struct std::char_traits<char> >::__ostream_type &(int)'
| | |-DeclRefExpr 0x953ec88 <col:5> 'std::ostream':'class std::basic_ostream<char>' lvalue ParmVar 0x953e470 'os' 'std::ostream &'
| | `-IntegerLiteral 0x953ecb0 <col:11> 'int' 4
| `-ImplicitCastExpr 0x953f5c0 <col:16> 'uint8_t':'unsigned char' <LValueToRValue>
| `-DeclRefExpr 0x953f1a8 <col:16> 'uint8_t':'unsigned char' lvalue ParmVar 0x953e500 'i' 'uint8_t':'unsigned char'
外在和内CXXOperatorCallExpr
都说他们的表达是class std::basic_ostream<char> lvalue
。正确匹配此论点的正确方法是什么?
对
<<
的第一个子调用的返回类型肯定有问题,请参阅以下匹配器,它也与"class std::__1::basic_ostream<char>"
匹配,并随之缺少调用:
clang-query> match callExpr(hasArgument(0, expr(hasType(anyOf(asString("class std::__1::basic_ostream<char>"), asString("std::ostream"))))))
Match #1:
/Users/ug/clangtest/main.cc:5:5: note: "root" binds here
os << i;
^~~~~~~
Match #2:
/Users/ug/clangtest/main.cc:6:5: note: "root" binds here
os << 4 << i;
^~~~~~~~~~~~
Match #3:
/Users/ug/clangtest/main.cc:6:5: note: "root" binds here
os << 4 << i;
^~~~~~~
3 matches.
相关文章:
- 请解释这句话(cout<<1+int((a<b)^((b-a)&1) )<<endl
- 呼叫运营商<<临时
- ostream过载时的缓冲区冲洗
- 需要从 istream 和 ostream 派生 iostream
- 如何防止clang格式在流运算符调用之间添加换行符<<
- <<操作员在下面的行中工作
- "ostream &os"有什么用?
- 为什么常量词在重载运算符中不与 ostream 对象一起使用<<?
- 我的运算符重载是否有效<<(流插入)左操作数不是 ostream
- C++表达SFINAE和ostream操纵器
- 在抛出 'std::runtime_error' 的实例后终止调用 what(): Filebuf 和 ostream 的 I/O 错误
- oStream 不打印添加两个 valarray 的结果(使用运算符重载)
- C++运算符<<调用::ostream而不是std::osttream
- BOOST ::变体无法解决运算符&lt;&lt;对于STD :: Ostream
- C++ostream:没有运算符匹配<<&应在'&'代币
- 重载运算符<<用于ostream语法
- 重载ostream&时转换错误无效;operator< & lt;
- 运算符<<(ostream&os,..)用于模板类
- std::ostream&operator< & lt; (std:: ostream&压力,压力& &;val)
- 上Ostream & lt; & lt;重载的困惑