AST 中的表达式大小对于成员访问不正确
Expression size in AST is incorrect for member access
假设我有以下代码:
struct S {
int abcd = 0;
};
int main() {
S s;
return s.abcd;
}
对应的AST部分:
-FunctionDecl 0x563ddd3a3e20 <line:5:1, line:8:1> line:5:5 main 'int ()'
`-CompoundStmt 0x563ddd3a4570 <col:12, line:8:1>
|-DeclStmt 0x563ddd3a44e0 <line:6:1, col:4>
| `-VarDecl 0x563ddd3a3f40 <col:1, col:3> col:3 used s 'S' callinit
| `-CXXConstructExpr 0x563ddd3a44b8 <col:3> 'S' 'void () noexcept'
`-ReturnStmt 0x563ddd3a4560 <line:7:1, col:10>
`-ImplicitCastExpr 0x563ddd3a4548 <col:8, col:10> 'int' <LValueToRValue>
`-MemberExpr 0x563ddd3a4518 <col:8, col:10> 'int' lvalue .abcd 0x563ddd3a3d10
`-DeclRefExpr 0x563ddd3a44f8 <col:8> 'S' lvalue Var 0x563ddd3a3f40 's' 'S'
问题是:根据 AST,return 语句跨越 10 列,而实际上它跨越 13。
但是 如果我们用大括号括住成员访问权限,那么它会给出预期的大小:
int main() {
S s;
return (s.abcd);
}
`-FunctionDecl 0x562842792e20 <line:5:1, line:8:1> line:5:5 main 'int ()'
`-CompoundStmt 0x562842793590 <col:12, line:8:1>
|-DeclStmt 0x5628427934e0 <line:6:1, col:4>
| `-VarDecl 0x562842792f40 <col:1, col:3> col:3 used s 'S' callinit
| `-CXXConstructExpr 0x5628427934b8 <col:3> 'S' 'void () noexcept'
`-ReturnStmt 0x562842793580 <line:7:1, col:15>
`-ImplicitCastExpr 0x562842793568 <col:8, col:15> 'int' <LValueToRValue>
`-ParenExpr 0x562842793548 <col:8, col:15> 'int' lvalue
`-MemberExpr 0x562842793518 <col:9, col:11> 'int' lvalue .abcd 0x562842792d10
`-DeclRefExpr 0x5628427934f8 <col:9> 'S' lvalue Var 0x562842792f40 's' 'S'
另外可以看到ParenExpr
跨越了8-15列,而MemberExpr
跨越了9-11列,暴露了后面AST节点的奇怪之处。
我是不是漏掉了什么?
我正在进行源到源的转换,我想获得 expressions/statements 的正确大小。现在我不知道该怎么做。 getEndLoc()
对于原始 return 语句也 returns .
(点运算符)的位置。
clang version 9.0.1
我决定在 cfe-dev 邮件列表上寻求帮助,这是我学到的。
看来我完全误解了getBeginLoc()
/getEndLoc()
的意思。 getBeginLoc()
returns 第一个标记的开始位置,而 getEndLoc()
returns 最后一个标记的开始。
要结束令牌,可以使用 Lexer::getLocForEndOfToken(...)
。
文档也可能有帮助:
https://clang.llvm.org/docs/InternalsManual.html#sourcerange-and-charsourcerange
假设我有以下代码:
struct S {
int abcd = 0;
};
int main() {
S s;
return s.abcd;
}
对应的AST部分:
-FunctionDecl 0x563ddd3a3e20 <line:5:1, line:8:1> line:5:5 main 'int ()'
`-CompoundStmt 0x563ddd3a4570 <col:12, line:8:1>
|-DeclStmt 0x563ddd3a44e0 <line:6:1, col:4>
| `-VarDecl 0x563ddd3a3f40 <col:1, col:3> col:3 used s 'S' callinit
| `-CXXConstructExpr 0x563ddd3a44b8 <col:3> 'S' 'void () noexcept'
`-ReturnStmt 0x563ddd3a4560 <line:7:1, col:10>
`-ImplicitCastExpr 0x563ddd3a4548 <col:8, col:10> 'int' <LValueToRValue>
`-MemberExpr 0x563ddd3a4518 <col:8, col:10> 'int' lvalue .abcd 0x563ddd3a3d10
`-DeclRefExpr 0x563ddd3a44f8 <col:8> 'S' lvalue Var 0x563ddd3a3f40 's' 'S'
问题是:根据 AST,return 语句跨越 10 列,而实际上它跨越 13。
但是 如果我们用大括号括住成员访问权限,那么它会给出预期的大小:
int main() {
S s;
return (s.abcd);
}
`-FunctionDecl 0x562842792e20 <line:5:1, line:8:1> line:5:5 main 'int ()'
`-CompoundStmt 0x562842793590 <col:12, line:8:1>
|-DeclStmt 0x5628427934e0 <line:6:1, col:4>
| `-VarDecl 0x562842792f40 <col:1, col:3> col:3 used s 'S' callinit
| `-CXXConstructExpr 0x5628427934b8 <col:3> 'S' 'void () noexcept'
`-ReturnStmt 0x562842793580 <line:7:1, col:15>
`-ImplicitCastExpr 0x562842793568 <col:8, col:15> 'int' <LValueToRValue>
`-ParenExpr 0x562842793548 <col:8, col:15> 'int' lvalue
`-MemberExpr 0x562842793518 <col:9, col:11> 'int' lvalue .abcd 0x562842792d10
`-DeclRefExpr 0x5628427934f8 <col:9> 'S' lvalue Var 0x562842792f40 's' 'S'
另外可以看到ParenExpr
跨越了8-15列,而MemberExpr
跨越了9-11列,暴露了后面AST节点的奇怪之处。
我是不是漏掉了什么?
我正在进行源到源的转换,我想获得 expressions/statements 的正确大小。现在我不知道该怎么做。 getEndLoc()
对于原始 return 语句也 returns .
(点运算符)的位置。
clang version 9.0.1
我决定在 cfe-dev 邮件列表上寻求帮助,这是我学到的。
看来我完全误解了getBeginLoc()
/getEndLoc()
的意思。 getBeginLoc()
returns 第一个标记的开始位置,而 getEndLoc()
returns 最后一个标记的开始。
要结束令牌,可以使用 Lexer::getLocForEndOfToken(...)
。
文档也可能有帮助: https://clang.llvm.org/docs/InternalsManual.html#sourcerange-and-charsourcerange