diff options
author | Eduardo Caldas <ecaldas@google.com> | 2020-08-11 16:28:00 +0000 |
---|---|---|
committer | Eduardo Caldas <ecaldas@google.com> | 2020-08-12 08:01:18 +0000 |
commit | ac37afa650271d8366b706d79ff8e217fc624cbb (patch) | |
tree | 6848e400e41e103513e6d9ad3dccaa80cfe4fd86 /clang/lib/Tooling/Syntax/BuildTree.cpp | |
parent | 88bbd30736561190a6733d0ad60aec21446b914c (diff) | |
download | llvm-ac37afa650271d8366b706d79ff8e217fc624cbb.zip llvm-ac37afa650271d8366b706d79ff8e217fc624cbb.tar.gz llvm-ac37afa650271d8366b706d79ff8e217fc624cbb.tar.bz2 |
[SyntaxTree] Unbox operators into tokens for nodes generated from `CXXOperatorCallExpr`
For an user define `<`, `x < y` would yield the syntax tree:
```
BinaryOperatorExpression
|-IdExpression
| `-UnqualifiedId
| `-x
|-IdExpression
| `-UnqualifiedId
| `-<
`-IdExpression
`-UnqualifiedId
`-y
```
But there is no syntatic difference at call site between call site or
built-in `<`. As such they should generate the same syntax tree, namely:
```
BinaryOperatorExpression
|-IdExpression
| `-UnqualifiedId
| `-x
|-<
`-IdExpression
`-UnqualifiedId
`-y
```
Differential Revision: https://reviews.llvm.org/D85750
Diffstat (limited to 'clang/lib/Tooling/Syntax/BuildTree.cpp')
-rw-r--r-- | clang/lib/Tooling/Syntax/BuildTree.cpp | 25 |
1 files changed, 14 insertions, 11 deletions
diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp index 9045153..11d3997 100644 --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -1007,23 +1007,26 @@ public: } bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *S) { - if (getOperatorNodeKind(*S) == - syntax::NodeKind::PostfixUnaryOperatorExpression) { + // To construct a syntax tree of the same shape for calls to built-in and + // user-defined operators, ignore the `DeclRefExpr` that refers to the + // operator and treat it as a simple token. Do that by traversing + // arguments instead of children. + for (auto *child : S->arguments()) { // A postfix unary operator is declared as taking two operands. The // second operand is used to distinguish from its prefix counterpart. In // the semantic AST this "phantom" operand is represented as a // `IntegerLiteral` with invalid `SourceLocation`. We skip visiting this // operand because it does not correspond to anything written in source - // code - for (auto *child : S->children()) { - if (child->getSourceRange().isInvalid()) - continue; - if (!TraverseStmt(child)) - return false; + // code. + if (child->getSourceRange().isInvalid()) { + assert(getOperatorNodeKind(*S) == + syntax::NodeKind::PostfixUnaryOperatorExpression); + continue; } - return WalkUpFromCXXOperatorCallExpr(S); - } else - return RecursiveASTVisitor::TraverseCXXOperatorCallExpr(S); + if (!TraverseStmt(child)) + return false; + } + return WalkUpFromCXXOperatorCallExpr(S); } bool WalkUpFromCXXOperatorCallExpr(CXXOperatorCallExpr *S) { |