diff --git a/clang/include/clang/Tooling/Syntax/Nodes.h b/clang/include/clang/Tooling/Syntax/Nodes.h --- a/clang/include/clang/Tooling/Syntax/Nodes.h +++ b/clang/include/clang/Tooling/Syntax/Nodes.h @@ -40,6 +40,8 @@ // Expressions. UnknownExpression, + PrefixUnaryOperatorExpression, + PostfixUnaryOperatorExpression, BinaryOperatorExpression, // Statements. @@ -105,6 +107,8 @@ BodyStatement, // Roles specific to particular node kinds. + UnaryOperatorExpression_operatorToken, + UnaryOperatorExpression_operand, BinaryOperatorExpression_leftHandSide, BinaryOperatorExpression_operatorToken, BinaryOperatorExpression_rightHandSide, @@ -162,6 +166,50 @@ } }; +/// 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(); +}; + +/// +/// +/// 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; + } +}; + +/// +/// +/// 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; + } +}; + /// /// /// For example: diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -608,6 +608,25 @@ 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); diff --git a/clang/lib/Tooling/Syntax/Nodes.cpp b/clang/lib/Tooling/Syntax/Nodes.cpp --- a/clang/lib/Tooling/Syntax/Nodes.cpp +++ b/clang/lib/Tooling/Syntax/Nodes.cpp @@ -18,6 +18,10 @@ 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: @@ -112,6 +116,10 @@ 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: @@ -155,6 +163,16 @@ findChild(syntax::NodeRole::BinaryOperatorExpression_leftHandSide)); } +syntax::Leaf *syntax::UnaryOperatorExpression::operatorToken() { + return llvm::cast_or_null( + findChild(syntax::NodeRole::UnaryOperatorExpression_operatorToken)); +} + +syntax::Expression *syntax::UnaryOperatorExpression::operand() { + return llvm::cast_or_null( + findChild(syntax::NodeRole::UnaryOperatorExpression_operand)); +} + syntax::Leaf *syntax::BinaryOperatorExpression::operatorToken() { return llvm::cast_or_null( findChild(syntax::NodeRole::BinaryOperatorExpression_operatorToken)); diff --git a/clang/unittests/Tooling/Syntax/TreeTest.cpp b/clang/unittests/Tooling/Syntax/TreeTest.cpp --- a/clang/unittests/Tooling/Syntax/TreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/TreeTest.cpp @@ -594,6 +594,161 @@ )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( @@ -1866,7 +2021,7 @@ | |-SimpleDeclarator | | |-west | | |-= -| | `-UnknownExpression +| | `-PrefixUnaryOperatorExpression | | |-- | | `-UnknownExpression | | `-1