c++ - 为什么 clang++ 和 clang-check 会产生不同的 AST?
问题描述
我正在尝试分析来自这个小代码片段的 clang 的 AST。
struct Foo {
Foo() = default;
Foo(int num) : i(num) {}
Foo(Foo &&other) {
i = other.i;
other.i = 0;
}
int i = 0;
};
Foo createAElidable(int i);
void func() { Foo foo = createAElidable(1234); }
Foo createAElidable(int i) { return Foo(i); }
运行“clang++ -Xclang -ast-dump example.cpp”给我这个输出:
TranslationUnitDecl #1 0x55c2ba1c07d8 <<invalid sloc>> <invalid sloc>
|-TypedefDecl #2 0x55c2ba1c10e0 <<invalid sloc>> <invalid sloc> implicit
| `-BuiltinType 0x55c2ba1c0d80 '__int128'
|-TypedefDecl #3 0x55c2ba1c1158 <<invalid sloc>> <invalid sloc> implicit
| `-BuiltinType 0x55c2ba1c0da0 'unsigned __int128'
|-TypedefDecl #9 0x55c2ba1c14f8 <<invalid sloc>> <invalid sloc> implicit
| `-RecordType 0x55c2ba1c1250 '__NSConstantString_tag'
| `-CXXRecord 0x55c2ba1c11b8 '__NSConstantString_tag'
|-TypedefDecl #10 0x55c2ba1c15a0 <<invalid sloc>> <invalid sloc> implicit
| `-PointerType 0x55c2ba1c1560 'char *'
| `-BuiltinType 0x55c2ba1c0880 'char'
|-TypedefDecl #16 0x55c2ba202118 <<invalid sloc>> <invalid sloc> implicit
| `-ConstantArrayType 0x55c2ba2020c0 '__va_list_tag [1]' 1
| `-RecordType 0x55c2ba1c16a0 '__va_list_tag'
| `-CXXRecord 0x55c2ba1c1600 '__va_list_tag'
|-CXXRecordDecl #17 0x55c2ba202178 <test27_copy_elision2.cpp:1:1, line:10:1> line:1:8 referenced
| |-CXXRecordDecl #18 0x55c2ba202298 <col:1, col:8> col:8 implicit referenced
| |-CXXConstructorDecl #19 0x55c2ba2023b8 <line:2:3, col:17> col:3 constexpr
| |-CXXConstructorDecl #21 0x55c2ba202548 <line:3:3, col:26> col:3 used
| | |-ParmVarDecl #20 0x55c2ba202480 <col:7, col:11> col:11 used
| | |-CXXCtorInitializer Field 0x55c2ba2027d8 'i' 'int'
| | | `-ImplicitCastExpr #32 0x55c2ba202c68 <col:20> 'int' <LValueToRValue>
| | | `-DeclRefExpr #30 0x55c2ba202c18 <col:20> 'int' lvalue ParmVar 0x55c2ba202480 'num' 'int'
| | `-CompoundStmt 0x55c2ba202cb8 <col:25, col:26>
| |-CXXConstructorDecl #23 0x55c2ba202708 <line:4:3, line:7:3> line:4:3 used
| | |-ParmVarDecl #22 0x55c2ba202638 <col:7, col:13> col:13 used
| | |-CXXCtorInitializer Field 0x55c2ba2027d8 'i' 'int'
| | | `-CXXDefaultInitExpr #33 0x55c2ba202cc8 <col:3> 'int'
| | `-CompoundStmt 0x55c2ba202f18 <col:20, line:7:3>
| | |-BinaryOperator #40 0x55c2ba202e40 <line:5:5, col:15> 'int' lvalue '='
| | | |-MemberExpr #36 0x55c2ba202d88 <col:5> 'int' lvalue ->i 0x55c2ba2027d8
| | | | `-CXXThisExpr #35 0x55c2ba202d70 <col:5> 'Foo *' implicit this
| | | `-ImplicitCastExpr #39 0x55c2ba202e20 <col:9, col:15> 'int' <LValueToRValue>
| | | `-MemberExpr #38 0x55c2ba202de8 <col:9, col:15> 'int' lvalue .i 0x55c2ba2027d8
| | | `-DeclRefExpr #37 0x55c2ba202dc0 <col:9> 'Foo' lvalue ParmVar 0x55c2ba202638 'other' 'Foo &&'
| | `-BinaryOperator #44 0x55c2ba202ef0 <line:6:5, col:15> 'int' lvalue '='
| | |-MemberExpr #42 0x55c2ba202e90 <col:5, col:11> 'int' lvalue .i 0x55c2ba2027d8
| | | `-DeclRefExpr #41 0x55c2ba202e68 <col:5> 'Foo' lvalue ParmVar 0x55c2ba202638 'other' 'Foo &&'
| | `-IntegerLiteral #43 0x55c2ba202ec8 <col:15> 'int' 0
| |-FieldDecl #24 0x55c2ba2027d8 <line:9:3, col:11> col:7 referenced
| | `-IntegerLiteral #29 0x55c2ba202bf0 <col:11> 'int' 0
| |-CXXConstructorDecl #25 0x55c2ba202858 <line:1:8> col:8 implicit constexpr
| | `-ParmVarDecl #26 0x55c2ba202978 <col:8> col:8
| |-CXXMethodDecl #27 0x55c2ba202a18 <col:8> col:8 implicit
| | `-ParmVarDecl #28 0x55c2ba202b28 <col:8> col:8
| `-CXXDestructorDecl #55 0x55c2ba2313a8 <col:8> col:8 implicit referenced
|-FunctionDecl #46 0x55c2ba231048 <line:12:1, col:26> col:5 used
| `-ParmVarDecl #45 0x55c2ba230f80 <col:21, col:25> col:25
|-FunctionDecl #48 0x55c2ba231168 <line:14:1, col:48> col:6
| `-CompoundStmt 0x55c2ba231548 <col:13, col:48>
| `-DeclStmt 0x55c2ba231530 <col:15, col:46>
| `-VarDecl #49 0x55c2ba231220 <col:15, col:45> col:19
| `-ExprWithCleanups #58 0x55c2ba231510 <col:25, col:45> 'Foo'
| `-CXXConstructExpr #57 0x55c2ba2314d8 <col:25, col:45> 'Foo' 'void (Foo &&)' elidable
| `-MaterializeTemporaryExpr #56 0x55c2ba2314b8 <col:25, col:45> 'Foo' xvalue
| `-CallExpr #54 0x55c2ba231378 <col:25, col:45> 'Foo'
| |-ImplicitCastExpr #53 0x55c2ba231358 <col:25> 'Foo (*)(int)' <FunctionToPointerDecay>
| | `-DeclRefExpr #52 0x55c2ba231308 <col:25> 'Foo (int)' lvalue Function 0x55c2ba231048 'createAElidable' 'Foo (int)'
| `-IntegerLiteral #51 0x55c2ba2312e0 <col:41> 'int' 1234
`-FunctionDecl #60 0x55c2ba231610 prev 0x55c2ba231048 <line:16:1, col:45> col:5 used
|-ParmVarDecl #59 0x55c2ba231578 <col:21, col:25> col:25 used
`-CompoundStmt 0x55c2ba231808 <col:28, col:45>
`-ReturnStmt 0x55c2ba2317f8 <col:30, col:42>
`-ExprWithCleanups #67 0x55c2ba2317d8 <col:37, col:42> 'Foo'
`-CXXConstructExpr #66 0x55c2ba2317a0 <col:37, col:42> 'Foo' 'void (Foo &&)' elidable
`-MaterializeTemporaryExpr #65 0x55c2ba231780 <col:37, col:42> 'Foo' xvalue
`-CXXFunctionalCastExpr #64 0x55c2ba231750 <col:37, col:42> 'Foo' functional cast to struct Foo <ConstructorConversion>
`-CXXConstructExpr #63 0x55c2ba231718 <col:37, col:42> 'Foo' 'void (int)'
`-ImplicitCastExpr #62 0x55c2ba2316f8 <col:41> 'int' <LValueToRValue>
`-DeclRefExpr #61 0x55c2ba2316d0 <col:41> 'int' lvalue ParmVar 0x55c2ba231578 'i' 'int'
到目前为止,一切都很好。
Clang 的源代码还附带了他们重构 api 的示例。一种称为 clang-check,它还提供 AST 转储。
“clang-check --ast-dump”产生:
TranslationUnitDecl #1 0x563d3b96bfa8 <<invalid sloc>> <invalid sloc>
|-TypedefDecl #2 0x563d3b96c8b0 <<invalid sloc>> <invalid sloc> implicit
| `-BuiltinType 0x563d3b96c550 '__int128'
|-TypedefDecl #3 0x563d3b96c928 <<invalid sloc>> <invalid sloc> implicit
| `-BuiltinType 0x563d3b96c570 'unsigned __int128'
|-TypedefDecl #9 0x563d3b96ccc8 <<invalid sloc>> <invalid sloc> implicit
| `-RecordType 0x563d3b96ca20 '__NSConstantString_tag'
| `-CXXRecord 0x563d3b96c988 '__NSConstantString_tag'
|-TypedefDecl #10 0x563d3b96cd70 <<invalid sloc>> <invalid sloc> implicit
| `-PointerType 0x563d3b96cd30 'char *'
| `-BuiltinType 0x563d3b96c050 'char'
|-TypedefDecl #16 0x563d3b9ac468 <<invalid sloc>> <invalid sloc> implicit
| `-ConstantArrayType 0x563d3b9ac410 '__va_list_tag [1]' 1
| `-RecordType 0x563d3b96ce70 '__va_list_tag'
| `-CXXRecord 0x563d3b96cdd0 '__va_list_tag'
|-CXXRecordDecl #17 0x563d3b9ac4c8 </home/tyrdal/projects/emx-llvm/worktrees/mo_clang_12/test_clang_ccode/test27_copy_elision2.cpp:1:1, line:10:1> line:1:8 referenced
| |-CXXRecordDecl #18 0x563d3b9ac5e8 <col:1, col:8> col:8 implicit referenced
| |-CXXConstructorDecl #19 0x563d3b9ac708 <line:2:3, col:17> col:3 constexpr
| |-CXXConstructorDecl #21 0x563d3b9ac898 <line:3:3, col:26> col:3 used
| | |-ParmVarDecl #20 0x563d3b9ac7d0 <col:7, col:11> col:11 used
| | |-CXXCtorInitializer Field 0x563d3b9acb28 'i' 'int'
| | | `-ImplicitCastExpr #32 0x563d3b9acfb8 <col:20> 'int' <LValueToRValue>
| | | `-DeclRefExpr #30 0x563d3b9acf68 <col:20> 'int' lvalue ParmVar 0x563d3b9ac7d0 'num' 'int'
| | `-CompoundStmt 0x563d3b9ad008 <col:25, col:26>
| |-CXXConstructorDecl #23 0x563d3b9aca58 <line:4:3, line:7:3> line:4:3
| | |-ParmVarDecl #22 0x563d3b9ac988 <col:7, col:13> col:13 used
| | |-CXXCtorInitializer Field 0x563d3b9acb28 'i' 'int'
| | | `-CXXDefaultInitExpr #33 0x563d3b9ad018 <col:3> 'int'
| | `-CompoundStmt 0x563d3b9ad268 <col:20, line:7:3>
| | |-BinaryOperator #40 0x563d3b9ad190 <line:5:5, col:15> 'int' lvalue '='
| | | |-MemberExpr #36 0x563d3b9ad0d8 <col:5> 'int' lvalue ->i 0x563d3b9acb28
| | | | `-CXXThisExpr #35 0x563d3b9ad0c0 <col:5> 'Foo *' implicit this
| | | `-ImplicitCastExpr #39 0x563d3b9ad170 <col:9, col:15> 'int' <LValueToRValue>
| | | `-MemberExpr #38 0x563d3b9ad138 <col:9, col:15> 'int' lvalue .i 0x563d3b9acb28
| | | `-DeclRefExpr #37 0x563d3b9ad110 <col:9> 'Foo' lvalue ParmVar 0x563d3b9ac988 'other' 'Foo &&'
| | `-BinaryOperator #44 0x563d3b9ad240 <line:6:5, col:15> 'int' lvalue '='
| | |-MemberExpr #42 0x563d3b9ad1e0 <col:5, col:11> 'int' lvalue .i 0x563d3b9acb28
| | | `-DeclRefExpr #41 0x563d3b9ad1b8 <col:5> 'Foo' lvalue ParmVar 0x563d3b9ac988 'other' 'Foo &&'
| | `-IntegerLiteral #43 0x563d3b9ad218 <col:15> 'int' 0
| |-FieldDecl #24 0x563d3b9acb28 <line:9:3, col:11> col:7 referenced
| | `-IntegerLiteral #29 0x563d3b9acf40 <col:11> 'int' 0
| |-CXXConstructorDecl #25 0x563d3b9acba8 <line:1:8> col:8 implicit constexpr
| | `-ParmVarDecl #26 0x563d3b9accc8 <col:8> col:8
| |-CXXMethodDecl #27 0x563d3b9acd68 <col:8> col:8 implicit
| | `-ParmVarDecl #28 0x563d3b9ace78 <col:8> col:8
| `-CXXDestructorDecl #55 0x563d3b9dd3a8 <col:8> col:8 implicit referenced
|-FunctionDecl #46 0x563d3b9dd048 <line:12:1, col:26> col:5 used
| `-ParmVarDecl #45 0x563d3b9dcf80 <col:21, col:25> col:25
|-FunctionDecl #48 0x563d3b9dd168 <line:14:1, col:48> col:6
| `-CompoundStmt 0x563d3b9dd4d0 <col:13, col:48>
| `-DeclStmt 0x563d3b9dd4b8 <col:15, col:46>
| `-VarDecl #49 0x563d3b9dd220 <col:15, col:45> col:19
| `-CallExpr #54 0x563d3b9dd378 <col:25, col:45> 'Foo'
| |-ImplicitCastExpr #53 0x563d3b9dd358 <col:25> 'Foo (*)(int)' <FunctionToPointerDecay>
| | `-DeclRefExpr #52 0x563d3b9dd308 <col:25> 'Foo (int)' lvalue Function 0x563d3b9dd048 'createAElidable' 'Foo (int)'
| `-IntegerLiteral #51 0x563d3b9dd2e0 <col:41> 'int' 1234
`-FunctionDecl #57 0x563d3b9dd598 prev 0x563d3b9dd048 <line:16:1, col:45> col:5 used
|-ParmVarDecl #56 0x563d3b9dd500 <col:21, col:25> col:25 used
`-CompoundStmt 0x563d3b9dd718 <col:28, col:45>
`-ReturnStmt 0x563d3b9dd708 <col:30, col:42>
`-CXXFunctionalCastExpr #61 0x563d3b9dd6d8 <col:37, col:42> 'Foo' functional cast to struct Foo <ConstructorConversion>
`-CXXConstructExpr #60 0x563d3b9dd6a0 <col:37, col:42> 'Foo' 'void (int)'
`-ImplicitCastExpr #59 0x563d3b9dd680 <col:41> 'int' <LValueToRValue>
`-DeclRefExpr #58 0x563d3b9dd658 <col:41> 'int' lvalue ParmVar 0x563d3b9dd500 'i' 'int'
如您所见,此版本中没有 MaterializeTemporaraExpr 节点。为什么这两个工具会产生不同的 AST?我错过了一些选择吗?
我尝试使用(自编译)版本 10.0.1 和 12.0.0。两种情况下的行为相同。
PS:这只发生在Linux下。我现在在 Win10 下尝试,这两个工具生成相同的输出。
解决方案
推荐阅读
- python-3.x - 将 '000111010010111' 拆分为 ['000','111','0',1','00','1','0','111']
- javascript - PhotoSwipe Base64 占位符进入画布和模糊
- node.js - nodejs中的路径和主机如何完全不同
- javascript - ReactJS - 仅在窗口对象(Spotify SDK)上完全加载第三方库时运行 useEffect
- python - 关于 Python 空列表的错误。UnboundLocalError
- quickbooks - QuickBooks 桌面 Web 连接器获取更新工作流程
- python - 通过以下方式创建 numpy 矩阵时有什么区别吗?
- c# - 单元测试:SetUp HtpContextAccessor.HttpContext.GetTokenAsync 返回错误:不支持的表达式异常 GetTokenAsync
- swift - 如何从 TestFlight 获取的 CrashLog 中确定错误的确切位置
- c++ - 如何在 tesseract 中使用 RGB 缓冲区?