Skip to content

Commit

Permalink
Add support for UnaryOperator in SyntaxTree
Browse files Browse the repository at this point in the history
Reviewers: gribozavr2

Reviewed By: gribozavr2

Subscribers: cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D80624
  • Loading branch information
Eduardo Caldas authored and gribozavr committed May 27, 2020
1 parent b5b0087 commit 461af57
Show file tree
Hide file tree
Showing 4 changed files with 241 additions and 1 deletion.
48 changes: 48 additions & 0 deletions clang/include/clang/Tooling/Syntax/Nodes.h
Expand Up @@ -40,6 +40,8 @@ enum class NodeKind : uint16_t {

// Expressions.
UnknownExpression,
PrefixUnaryOperatorExpression,
PostfixUnaryOperatorExpression,
BinaryOperatorExpression,

// Statements.
Expand Down Expand Up @@ -105,6 +107,8 @@ enum class NodeRole : uint8_t {
BodyStatement,

// Roles specific to particular node kinds.
UnaryOperatorExpression_operatorToken,
UnaryOperatorExpression_operand,
BinaryOperatorExpression_leftHandSide,
BinaryOperatorExpression_operatorToken,
BinaryOperatorExpression_rightHandSide,
Expand Down Expand Up @@ -162,6 +166,50 @@ class UnknownExpression final : public Expression {
}
};

/// An abstract class for prefix and postfix unary operators.
class UnaryOperatorExpression : public Expression {
public:
UnaryOperatorExpression(NodeKind K) : Expression(K) {}
static bool classof(const Node *N) {
return N->kind() == NodeKind::PrefixUnaryOperatorExpression ||
N->kind() == NodeKind::PostfixUnaryOperatorExpression;
}
syntax::Leaf *operatorToken();
syntax::Expression *operand();
};

/// <operator> <operand>
///
/// For example:
/// +a -b
/// !c not c
/// ~d compl d
/// *e &f
/// ++h --h
/// __real i __imag i
class PrefixUnaryOperatorExpression final : public UnaryOperatorExpression {
public:
PrefixUnaryOperatorExpression()
: UnaryOperatorExpression(NodeKind::PrefixUnaryOperatorExpression) {}
static bool classof(const Node *N) {
return N->kind() == NodeKind::PrefixUnaryOperatorExpression;
}
};

/// <operand> <operator>
///
/// For example:
/// a++
/// b--
class PostfixUnaryOperatorExpression final : public UnaryOperatorExpression {
public:
PostfixUnaryOperatorExpression()
: UnaryOperatorExpression(NodeKind::PostfixUnaryOperatorExpression) {}
static bool classof(const Node *N) {
return N->kind() == NodeKind::PostfixUnaryOperatorExpression;
}
};

/// <lhs> <operator> <rhs>
///
/// For example:
Expand Down
19 changes: 19 additions & 0 deletions clang/lib/Tooling/Syntax/BuildTree.cpp
Expand Up @@ -608,6 +608,25 @@ class BuildTreeVisitor : public RecursiveASTVisitor<BuildTreeVisitor> {
return true;
}

bool WalkUpFromUnaryOperator(UnaryOperator *S) {
Builder.markChildToken(
S->getOperatorLoc(),
syntax::NodeRole::UnaryOperatorExpression_operatorToken);
Builder.markExprChild(S->getSubExpr(),
syntax::NodeRole::UnaryOperatorExpression_operand);

if (S->isPostfix())
Builder.foldNode(Builder.getExprRange(S),
new (allocator()) syntax::PostfixUnaryOperatorExpression,
S);
else
Builder.foldNode(Builder.getExprRange(S),
new (allocator()) syntax::PrefixUnaryOperatorExpression,
S);

return true;
}

bool WalkUpFromBinaryOperator(BinaryOperator *S) {
Builder.markExprChild(
S->getLHS(), syntax::NodeRole::BinaryOperatorExpression_leftHandSide);
Expand Down
18 changes: 18 additions & 0 deletions clang/lib/Tooling/Syntax/Nodes.cpp
Expand Up @@ -18,6 +18,10 @@ llvm::raw_ostream &syntax::operator<<(llvm::raw_ostream &OS, NodeKind K) {
return OS << "TranslationUnit";
case NodeKind::UnknownExpression:
return OS << "UnknownExpression";
case NodeKind::PrefixUnaryOperatorExpression:
return OS << "PrefixUnaryOperatorExpression";
case NodeKind::PostfixUnaryOperatorExpression:
return OS << "PostfixUnaryOperatorExpression";
case NodeKind::BinaryOperatorExpression:
return OS << "BinaryOperatorExpression";
case NodeKind::UnknownStatement:
Expand Down Expand Up @@ -112,6 +116,10 @@ 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::UnaryOperatorExpression_operatorToken:
return OS << "UnaryOperatorExpression_operatorToken";
case syntax::NodeRole::UnaryOperatorExpression_operand:
return OS << "UnaryOperatorExpression_operand";
case syntax::NodeRole::BinaryOperatorExpression_leftHandSide:
return OS << "BinaryOperatorExpression_leftHandSide";
case syntax::NodeRole::BinaryOperatorExpression_operatorToken:
Expand Down Expand Up @@ -155,6 +163,16 @@ syntax::Expression *syntax::BinaryOperatorExpression::lhs() {
findChild(syntax::NodeRole::BinaryOperatorExpression_leftHandSide));
}

syntax::Leaf *syntax::UnaryOperatorExpression::operatorToken() {
return llvm::cast_or_null<syntax::Leaf>(
findChild(syntax::NodeRole::UnaryOperatorExpression_operatorToken));
}

syntax::Expression *syntax::UnaryOperatorExpression::operand() {
return llvm::cast_or_null<syntax::Expression>(
findChild(syntax::NodeRole::UnaryOperatorExpression_operand));
}

syntax::Leaf *syntax::BinaryOperatorExpression::operatorToken() {
return llvm::cast_or_null<syntax::Leaf>(
findChild(syntax::NodeRole::BinaryOperatorExpression_operatorToken));
Expand Down
157 changes: 156 additions & 1 deletion clang/unittests/Tooling/Syntax/TreeTest.cpp
Expand Up @@ -594,6 +594,161 @@ void test() {
)txt");
}

TEST_F(SyntaxTreeTest, PostfixUnaryOperator) {
expectTreeDumpEqual(
R"cpp(
void test(int a) {
a++;
a--;
}
)cpp",
R"txt(
*: TranslationUnit
`-SimpleDeclaration
|-void
|-SimpleDeclarator
| |-test
| `-ParametersAndQualifiers
| |-(
| |-SimpleDeclaration
| | |-int
| | `-SimpleDeclarator
| | `-a
| `-)
`-CompoundStatement
|-{
|-ExpressionStatement
| |-PostfixUnaryOperatorExpression
| | |-UnknownExpression
| | | `-a
| | `-++
| `-;
|-ExpressionStatement
| |-PostfixUnaryOperatorExpression
| | |-UnknownExpression
| | | `-a
| | `---
| `-;
`-}
)txt");
}

TEST_F(SyntaxTreeTest, PrefixUnaryOperator) {
expectTreeDumpEqual(
R"cpp(
void test(int a, int *ap, bool b) {
--a; ++a;
~a; compl a;
-a;
+a;
&a;
*ap;
!b; not b;
__real a; __imag a;
}
)cpp",
R"txt(
*: TranslationUnit
`-SimpleDeclaration
|-void
|-SimpleDeclarator
| |-test
| `-ParametersAndQualifiers
| |-(
| |-SimpleDeclaration
| | |-int
| | `-SimpleDeclarator
| | `-a
| |-,
| |-SimpleDeclaration
| | |-int
| | `-SimpleDeclarator
| | |-*
| | `-ap
| |-,
| |-SimpleDeclaration
| | |-bool
| | `-SimpleDeclarator
| | `-b
| `-)
`-CompoundStatement
|-{
|-ExpressionStatement
| |-PrefixUnaryOperatorExpression
| | |---
| | `-UnknownExpression
| | `-a
| `-;
|-ExpressionStatement
| |-PrefixUnaryOperatorExpression
| | |-++
| | `-UnknownExpression
| | `-a
| `-;
|-ExpressionStatement
| |-PrefixUnaryOperatorExpression
| | |-~
| | `-UnknownExpression
| | `-a
| `-;
|-ExpressionStatement
| |-PrefixUnaryOperatorExpression
| | |-compl
| | `-UnknownExpression
| | `-a
| `-;
|-ExpressionStatement
| |-PrefixUnaryOperatorExpression
| | |--
| | `-UnknownExpression
| | `-a
| `-;
|-ExpressionStatement
| |-PrefixUnaryOperatorExpression
| | |-+
| | `-UnknownExpression
| | `-a
| `-;
|-ExpressionStatement
| |-PrefixUnaryOperatorExpression
| | |-&
| | `-UnknownExpression
| | `-a
| `-;
|-ExpressionStatement
| |-PrefixUnaryOperatorExpression
| | |-*
| | `-UnknownExpression
| | `-ap
| `-;
|-ExpressionStatement
| |-PrefixUnaryOperatorExpression
| | |-!
| | `-UnknownExpression
| | `-b
| `-;
|-ExpressionStatement
| |-PrefixUnaryOperatorExpression
| | |-not
| | `-UnknownExpression
| | `-b
| `-;
|-ExpressionStatement
| |-PrefixUnaryOperatorExpression
| | |-__real
| | `-UnknownExpression
| | `-a
| `-;
|-ExpressionStatement
| |-PrefixUnaryOperatorExpression
| | |-__imag
| | `-UnknownExpression
| | `-a
| `-;
`-}
)txt");
}

TEST_F(SyntaxTreeTest, BinaryOperator) {
expectTreeDumpEqual(
R"cpp(
Expand Down Expand Up @@ -1866,7 +2021,7 @@ const int const *const *volatile b;
| |-SimpleDeclarator
| | |-west
| | |-=
| | `-UnknownExpression
| | `-PrefixUnaryOperatorExpression
| | |--
| | `-UnknownExpression
| | `-1
Expand Down

0 comments on commit 461af57

Please sign in to comment.