Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
Code that reproduces the crash
Notice that when using a postfix unary operator ++ one argument is introduced to differ it from its prefix counterpart, but that argument is not used. This phantom argument shows up in the ClangAST in the form of an IntegerLiteral with invalid sloc. This invalid sloc in a valid AST node was causing the SyntaxTree generation to crash.
We can address this problems at two different levels:
- At the TraverseCXXOperatorCallExpr, by overriding it and replacing the children iteration to not iterate over this phantom argument.
- At the WalkUpFromIntegerLiteral, by skipping the visitation of the phantom node.
We preferred the latter.
- Cons: We would have to duplicate the implementation of RecursiveASTVisitor in BuildTree, to handle this subtle change in traversal. That would add code complexity.
- Cons: We are handling a problem of CXXOperatorCallExpr in IntegerLiteral.
We chose the latter as, anyways, if an AST node has an invalid sloc, it was either a problem with parsing or the node is supposed to be ignored
clang/include/clang/AST/ExprCXX.h | ||
---|---|---|
143–148 ↗ | (On Diff #274771) | Should new additions to CXXOperatorCallExpr go on a different patch? |
clang/lib/AST/ExprCXX.cpp | ||
---|---|---|
82 ↗ | (On Diff #274771) | This will be true for operator->. |
clang/lib/AST/ExprCXX.cpp | ||
---|---|---|
82 ↗ | (On Diff #274771) | Thank you ! I had missed that! I'll propose a more robust solution. I'll probably split this patch. But I'll take care to subscribe you to anything related |
- Remove predicates in CXXOperatorCallExpr.
- Implement getOperatorNodeKind to dispatch from CXXOperatorCallExpr to syntax constructs like BinaryOperatorExpression, PrefixUnaryOperatorExpression...
clang/lib/Tooling/Syntax/BuildTree.cpp | ||
---|---|---|
118 | Where to put this logic?The pro of having this function inside BuildTree.cpp is that it is closer to it's *only* usage. And also for now BuildTree.cpp agglomerates everything that takes a semantic AST as an input, so it would be coherent. Another option is to put it in Nodes, as it might serve as documentation for *OperatorExpressions. Another option is to add put this function as a lambda inside WalkUpFromCXXOperatorCallExpr as probably it will only be used there. |
clang/lib/Tooling/Syntax/BuildTree.cpp | ||
---|---|---|
118 | Placing this helper here makes sense to me. However, please mark it static. | |
178 | "Not supported by syntax tree *yet*" | |
741 | WDYT about overriding TraverseCXXOperatorCallExpr, so that we don't even visit the synthetic argument of the postfix unary ++? I would prefer to not introduce blanket "if invalid then ignore" checks in the code. | |
852 | "getOperatorNodeKind() does not return this value" | |
clang/unittests/Tooling/Syntax/TreeTest.cpp | ||
2553 | Could you also add tests for a prefix unary operator? | |
2596 | I'm not sure about this part where ++ is wrapped in IdExpression -- shouldn't the syntax tree look identical to a builtin postfix ++ (see another test in this file)? |
clang/lib/Tooling/Syntax/BuildTree.cpp | ||
---|---|---|
741 | I've explained my reasoning in my first comment for this patch. But as it was a long time ago, I guess it got lost, even by me. I'll sketch how the Traverse solution would look like, to be able to give more concrete arguments. | |
clang/unittests/Tooling/Syntax/TreeTest.cpp | ||
2596 | This comes back to a discussion we had a month ago about operators ( +, !, etc) |
clang/lib/Tooling/Syntax/BuildTree.cpp | ||
---|---|---|
149 | Please drop this comment, I don't think it helps understand the code. | |
clang/unittests/Tooling/Syntax/TreeTest.cpp | ||
2192 | I don't think we need a separate class to show the left shift operator. The declaration below can be: friend X operator<<(X&, const X&); | |
2198 | "TODO: Fix the crash on ->* and add a test for it." | |
2596 | SGTM. Please just leave a FIXME or TODO in this patch that shows that certain parts of tests are not final. |
answering minor comments
clang/unittests/Tooling/Syntax/TreeTest.cpp | ||
---|---|---|
2192 | If we don't bother much about "realistic" operator declarations we could drop all the friend and declare every operator in their most concise form. WDYT |
clang/unittests/Tooling/Syntax/TreeTest.cpp | ||
---|---|---|
2192 | I think we shouldn't try to make tests realistic in terms of function names etc., but we should try to cover as many different AST shapes as possible. In the case of binary operators, we have three cases -- free function, friend function, member function, that all generate slightly different ASTs, so I believe we should try to cover them all. |
clang/unittests/Tooling/Syntax/TreeTest.cpp | ||
---|---|---|
2192 | But those all regard the operators declaration. I think we should test friend function declarations when we add support for them in the tree, and then we add tests for declaration of friend operators, friend member functions and whatnot. |
clang/unittests/Tooling/Syntax/TreeTest.cpp | ||
---|---|---|
2192 | The call expression AST node can be meaningfully different between calls to member and non-member functions. |
Where to put this logic?
The pro of having this function inside BuildTree.cpp is that it is closer to it's *only* usage. And also for now BuildTree.cpp agglomerates everything that takes a semantic AST as an input, so it would be coherent.
Another option is to put it in Nodes, as it might serve as documentation for *OperatorExpressions.
For example, it would document that the semantic node CXXOperatorCallExpr can also generate the syntax node BinaryOperatorExpression, which was previously only generated by a semantic BinaryOperator
Another option is to add put this function as a lambda inside WalkUpFromCXXOperatorCallExpr as probably it will only be used there.