[clang] 3785eb8 - Add support for binary operators in Syntax Trees
Dmitri Gribenko via cfe-commits
cfe-commits at lists.llvm.org
Tue May 26 03:28:23 PDT 2020
Author: Eduardo Caldas
Date: 2020-05-26T12:25:58+02:00
New Revision: 3785eb83af4161bd52ed993ef3a2184c998071e6
URL: https://github.com/llvm/llvm-project/commit/3785eb83af4161bd52ed993ef3a2184c998071e6
DIFF: https://github.com/llvm/llvm-project/commit/3785eb83af4161bd52ed993ef3a2184c998071e6.diff
LOG: Add support for binary operators in Syntax Trees
Reviewers: gribozavr2
Reviewed By: gribozavr2
Subscribers: cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D80540
Added:
Modified:
clang/include/clang/Tooling/Syntax/Nodes.h
clang/lib/Tooling/Syntax/BuildTree.cpp
clang/lib/Tooling/Syntax/Nodes.cpp
clang/unittests/Tooling/Syntax/TreeTest.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Tooling/Syntax/Nodes.h b/clang/include/clang/Tooling/Syntax/Nodes.h
index f4d482bb848c..5db99d4b9e35 100644
--- a/clang/include/clang/Tooling/Syntax/Nodes.h
+++ b/clang/include/clang/Tooling/Syntax/Nodes.h
@@ -40,6 +40,7 @@ enum class NodeKind : uint16_t {
// Expressions.
UnknownExpression,
+ BinaryOperatorExpression,
// Statements.
UnknownStatement,
@@ -104,6 +105,9 @@ enum class NodeRole : uint8_t {
BodyStatement,
// Roles specific to particular node kinds.
+ BinaryOperatorExpression_leftHandSide,
+ BinaryOperatorExpression_operatorToken,
+ BinaryOperatorExpression_rightHandSide,
CaseStatement_value,
IfStatement_thenStatement,
IfStatement_elseKeyword,
@@ -158,6 +162,24 @@ class UnknownExpression final : public Expression {
}
};
+/// <lhs> <operator> <rhs>
+///
+/// For example:
+/// a + b
+/// a bitor 1
+/// a |= b
+/// a and_eq b
+class BinaryOperatorExpression final : public Expression {
+public:
+ BinaryOperatorExpression() : Expression(NodeKind::BinaryOperatorExpression) {}
+ static bool classof(const Node *N) {
+ return N->kind() == NodeKind::BinaryOperatorExpression;
+ }
+ syntax::Expression *lhs();
+ syntax::Leaf *operatorToken();
+ syntax::Expression *rhs();
+};
+
/// An abstract node for C++ statements, e.g. 'while', 'if', etc.
/// FIXME: add accessors for semicolon of statements that have it.
class Statement : public Tree {
diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp
index 11058edec615..8fee44cdbf10 100644
--- a/clang/lib/Tooling/Syntax/BuildTree.cpp
+++ b/clang/lib/Tooling/Syntax/BuildTree.cpp
@@ -11,6 +11,7 @@
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclarationName.h"
+#include "clang/AST/Expr.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/TypeLoc.h"
@@ -594,10 +595,7 @@ class BuildTreeVisitor : public RecursiveASTVisitor<BuildTreeVisitor> {
for (auto *D : DS->decls())
Builder.noticeDeclWithoutSemicolon(D);
} else if (auto *E = llvm::dyn_cast_or_null<Expr>(S)) {
- // Do not recurse into subexpressions.
- // We do not have syntax trees for expressions yet, so we only want to see
- // the first top-level expression.
- return WalkUpFromExpr(E->IgnoreImplicit());
+ return RecursiveASTVisitor::TraverseStmt(E->IgnoreImplicit());
}
return RecursiveASTVisitor::TraverseStmt(S);
}
@@ -610,6 +608,19 @@ class BuildTreeVisitor : public RecursiveASTVisitor<BuildTreeVisitor> {
return true;
}
+ bool WalkUpFromBinaryOperator(BinaryOperator *S) {
+ Builder.markExprChild(
+ S->getLHS(), syntax::NodeRole::BinaryOperatorExpression_leftHandSide);
+ Builder.markChildToken(
+ S->getOperatorLoc(),
+ syntax::NodeRole::BinaryOperatorExpression_operatorToken);
+ Builder.markExprChild(
+ S->getRHS(), syntax::NodeRole::BinaryOperatorExpression_rightHandSide);
+ Builder.foldNode(Builder.getExprRange(S),
+ new (allocator()) syntax::BinaryOperatorExpression, S);
+ return true;
+ }
+
bool WalkUpFromNamespaceDecl(NamespaceDecl *S) {
auto Tokens = Builder.getDeclarationRange(S);
if (Tokens.front().kind() == tok::coloncolon) {
diff --git a/clang/lib/Tooling/Syntax/Nodes.cpp b/clang/lib/Tooling/Syntax/Nodes.cpp
index 75f025e5f853..84c0143db81d 100644
--- a/clang/lib/Tooling/Syntax/Nodes.cpp
+++ b/clang/lib/Tooling/Syntax/Nodes.cpp
@@ -18,6 +18,8 @@ llvm::raw_ostream &syntax::operator<<(llvm::raw_ostream &OS, NodeKind K) {
return OS << "TranslationUnit";
case NodeKind::UnknownExpression:
return OS << "UnknownExpression";
+ case NodeKind::BinaryOperatorExpression:
+ return OS << "BinaryOperatorExpression";
case NodeKind::UnknownStatement:
return OS << "UnknownStatement";
case NodeKind::DeclarationStatement:
@@ -110,6 +112,12 @@ llvm::raw_ostream &syntax::operator<<(llvm::raw_ostream &OS, NodeRole R) {
return OS << "IfStatement_elseKeyword";
case syntax::NodeRole::IfStatement_elseStatement:
return OS << "IfStatement_elseStatement";
+ case syntax::NodeRole::BinaryOperatorExpression_leftHandSide:
+ return OS << "BinaryOperatorExpression_leftHandSide";
+ case syntax::NodeRole::BinaryOperatorExpression_operatorToken:
+ return OS << "BinaryOperatorExpression_operatorToken";
+ case syntax::NodeRole::BinaryOperatorExpression_rightHandSide:
+ return OS << "BinaryOperatorExpression_rightHandSide";
case syntax::NodeRole::ReturnStatement_value:
return OS << "ReturnStatement_value";
case syntax::NodeRole::ExpressionStatement_expression:
@@ -142,6 +150,21 @@ llvm::raw_ostream &syntax::operator<<(llvm::raw_ostream &OS, NodeRole R) {
llvm_unreachable("invalid role");
}
+syntax::Expression *syntax::BinaryOperatorExpression::lhs() {
+ return llvm::cast_or_null<syntax::Expression>(
+ findChild(syntax::NodeRole::BinaryOperatorExpression_leftHandSide));
+}
+
+syntax::Leaf *syntax::BinaryOperatorExpression::operatorToken() {
+ return llvm::cast_or_null<syntax::Leaf>(
+ findChild(syntax::NodeRole::BinaryOperatorExpression_operatorToken));
+}
+
+syntax::Expression *syntax::BinaryOperatorExpression::rhs() {
+ return llvm::cast_or_null<syntax::Expression>(
+ findChild(syntax::NodeRole::BinaryOperatorExpression_rightHandSide));
+}
+
syntax::Leaf *syntax::SwitchStatement::switchKeyword() {
return llvm::cast_or_null<syntax::Leaf>(
findChild(syntax::NodeRole::IntroducerKeyword));
diff --git a/clang/unittests/Tooling/Syntax/TreeTest.cpp b/clang/unittests/Tooling/Syntax/TreeTest.cpp
index d11a3652c8e1..634f99f7c395 100644
--- a/clang/unittests/Tooling/Syntax/TreeTest.cpp
+++ b/clang/unittests/Tooling/Syntax/TreeTest.cpp
@@ -564,7 +564,8 @@ void test() {
|-{
|-ExpressionStatement
| |-UnknownExpression
- | | |-test
+ | | |-UnknownExpression
+ | | | `-test
| | |-(
| | `-)
| `-;
@@ -576,14 +577,16 @@ void test() {
| |-)
| |-ExpressionStatement
| | |-UnknownExpression
- | | | |-test
+ | | | |-UnknownExpression
+ | | | | `-test
| | | |-(
| | | `-)
| | `-;
| |-else
| `-ExpressionStatement
| |-UnknownExpression
- | | |-test
+ | | |-UnknownExpression
+ | | | `-test
| | |-(
| | `-)
| `-;
@@ -591,6 +594,237 @@ void test() {
)txt");
}
+TEST_F(SyntaxTreeTest, BinaryOperator) {
+ expectTreeDumpEqual(
+ R"cpp(
+void test(int a) {
+ 1 - 2;
+ 1 == 2;
+ a = 1;
+ a <<= 1;
+
+ true || false;
+ true or false;
+
+ 1 & 2;
+ 1 bitand 2;
+
+ a ^= 3;
+ a xor_eq 3;
+}
+ )cpp",
+ R"txt(
+*: TranslationUnit
+`-SimpleDeclaration
+ |-void
+ |-SimpleDeclarator
+ | |-test
+ | `-ParametersAndQualifiers
+ | |-(
+ | |-SimpleDeclaration
+ | | |-int
+ | | `-SimpleDeclarator
+ | | `-a
+ | `-)
+ `-CompoundStatement
+ |-{
+ |-ExpressionStatement
+ | |-BinaryOperatorExpression
+ | | |-UnknownExpression
+ | | | `-1
+ | | |--
+ | | `-UnknownExpression
+ | | `-2
+ | `-;
+ |-ExpressionStatement
+ | |-BinaryOperatorExpression
+ | | |-UnknownExpression
+ | | | `-1
+ | | |-==
+ | | `-UnknownExpression
+ | | `-2
+ | `-;
+ |-ExpressionStatement
+ | |-BinaryOperatorExpression
+ | | |-UnknownExpression
+ | | | `-a
+ | | |-=
+ | | `-UnknownExpression
+ | | `-1
+ | `-;
+ |-ExpressionStatement
+ | |-BinaryOperatorExpression
+ | | |-UnknownExpression
+ | | | `-a
+ | | |-<<=
+ | | `-UnknownExpression
+ | | `-1
+ | `-;
+ |-ExpressionStatement
+ | |-BinaryOperatorExpression
+ | | |-UnknownExpression
+ | | | `-true
+ | | |-||
+ | | `-UnknownExpression
+ | | `-false
+ | `-;
+ |-ExpressionStatement
+ | |-BinaryOperatorExpression
+ | | |-UnknownExpression
+ | | | `-true
+ | | |-or
+ | | `-UnknownExpression
+ | | `-false
+ | `-;
+ |-ExpressionStatement
+ | |-BinaryOperatorExpression
+ | | |-UnknownExpression
+ | | | `-1
+ | | |-&
+ | | `-UnknownExpression
+ | | `-2
+ | `-;
+ |-ExpressionStatement
+ | |-BinaryOperatorExpression
+ | | |-UnknownExpression
+ | | | `-1
+ | | |-bitand
+ | | `-UnknownExpression
+ | | `-2
+ | `-;
+ |-ExpressionStatement
+ | |-BinaryOperatorExpression
+ | | |-UnknownExpression
+ | | | `-a
+ | | |-^=
+ | | `-UnknownExpression
+ | | `-3
+ | `-;
+ |-ExpressionStatement
+ | |-BinaryOperatorExpression
+ | | |-UnknownExpression
+ | | | `-a
+ | | |-xor_eq
+ | | `-UnknownExpression
+ | | `-3
+ | `-;
+ `-}
+)txt");
+}
+
+TEST_F(SyntaxTreeTest, NestedBinaryOperator) {
+ expectTreeDumpEqual(
+ R"cpp(
+void test(int a, int b) {
+ (1 + 2) * (4 / 2);
+ a + b + 42;
+ a = b = 42;
+ a + b * 4 + 2;
+ a % 2 + b * 42;
+}
+ )cpp",
+ R"txt(
+*: TranslationUnit
+`-SimpleDeclaration
+ |-void
+ |-SimpleDeclarator
+ | |-test
+ | `-ParametersAndQualifiers
+ | |-(
+ | |-SimpleDeclaration
+ | | |-int
+ | | `-SimpleDeclarator
+ | | `-a
+ | |-,
+ | |-SimpleDeclaration
+ | | |-int
+ | | `-SimpleDeclarator
+ | | `-b
+ | `-)
+ `-CompoundStatement
+ |-{
+ |-ExpressionStatement
+ | |-BinaryOperatorExpression
+ | | |-UnknownExpression
+ | | | |-(
+ | | | |-BinaryOperatorExpression
+ | | | | |-UnknownExpression
+ | | | | | `-1
+ | | | | |-+
+ | | | | `-UnknownExpression
+ | | | | `-2
+ | | | `-)
+ | | |-*
+ | | `-UnknownExpression
+ | | |-(
+ | | |-BinaryOperatorExpression
+ | | | |-UnknownExpression
+ | | | | `-4
+ | | | |-/
+ | | | `-UnknownExpression
+ | | | `-2
+ | | `-)
+ | `-;
+ |-ExpressionStatement
+ | |-BinaryOperatorExpression
+ | | |-BinaryOperatorExpression
+ | | | |-UnknownExpression
+ | | | | `-a
+ | | | |-+
+ | | | `-UnknownExpression
+ | | | `-b
+ | | |-+
+ | | `-UnknownExpression
+ | | `-42
+ | `-;
+ |-ExpressionStatement
+ | |-BinaryOperatorExpression
+ | | |-UnknownExpression
+ | | | `-a
+ | | |-=
+ | | `-BinaryOperatorExpression
+ | | |-UnknownExpression
+ | | | `-b
+ | | |-=
+ | | `-UnknownExpression
+ | | `-42
+ | `-;
+ |-ExpressionStatement
+ | |-BinaryOperatorExpression
+ | | |-BinaryOperatorExpression
+ | | | |-UnknownExpression
+ | | | | `-a
+ | | | |-+
+ | | | `-BinaryOperatorExpression
+ | | | |-UnknownExpression
+ | | | | `-b
+ | | | |-*
+ | | | `-UnknownExpression
+ | | | `-4
+ | | |-+
+ | | `-UnknownExpression
+ | | `-2
+ | `-;
+ |-ExpressionStatement
+ | |-BinaryOperatorExpression
+ | | |-BinaryOperatorExpression
+ | | | |-UnknownExpression
+ | | | | `-a
+ | | | |-%
+ | | | `-UnknownExpression
+ | | | `-2
+ | | |-+
+ | | `-BinaryOperatorExpression
+ | | |-UnknownExpression
+ | | | `-b
+ | | |-*
+ | | `-UnknownExpression
+ | | `-42
+ | `-;
+ `-}
+)txt");
+}
+
TEST_F(SyntaxTreeTest, MultipleDeclaratorsGrouping) {
expectTreeDumpEqual(
R"cpp(
@@ -1201,10 +1435,12 @@ void test() {
|-IfStatement
| |-I: if
| |-I: (
- | |-I: UnknownExpression
- | | |-I: 1
+ | |-I: BinaryOperatorExpression
+ | | |-I: UnknownExpression
+ | | | `-I: 1
| | |-I: +
- | | `-I: 1
+ | | `-I: UnknownExpression
+ | | `-I: 1
| |-I: )
| |-I: CompoundStatement
| | |-I: {
@@ -1312,13 +1548,17 @@ void f(int xs[static 10]);
| | | `-]
| | |-=
| | `-UnknownExpression
-| | |-{
-| | |-1
-| | |-,
-| | |-2
-| | |-,
-| | |-3
-| | `-}
+| | `-UnknownExpression
+| | |-{
+| | |-UnknownExpression
+| | | `-1
+| | |-,
+| | |-UnknownExpression
+| | | `-2
+| | |-,
+| | |-UnknownExpression
+| | | `-3
+| | `-}
| `-;
`-SimpleDeclaration
|-void
@@ -1628,7 +1868,8 @@ const int const *const *volatile b;
| | |-=
| | `-UnknownExpression
| | |--
-| | `-1
+| | `-UnknownExpression
+| | `-1
| `-;
|-SimpleDeclaration
| |-int
More information about the cfe-commits
mailing list