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 @@ -43,6 +43,7 @@ PrefixUnaryOperatorExpression, PostfixUnaryOperatorExpression, BinaryOperatorExpression, + CxxNullPtrExpression, // Statements. UnknownStatement, @@ -112,6 +113,7 @@ BinaryOperatorExpression_leftHandSide, BinaryOperatorExpression_operatorToken, BinaryOperatorExpression_rightHandSide, + CxxNullPtrExpression_keyword, CaseStatement_value, IfStatement_thenStatement, IfStatement_elseKeyword, @@ -166,6 +168,16 @@ } }; +/// C++11 'nullptr' expression. +class CxxNullPtrExpression final : public Expression { +public: + CxxNullPtrExpression() : Expression(NodeKind::CxxNullPtrExpression) {} + static bool classof(const Node *N) { + return N->kind() == NodeKind::CxxNullPtrExpression; + } + syntax::Leaf *nullPtrKeyword(); +}; + /// An abstract class for prefix and postfix unary operators. class UnaryOperatorExpression : public Expression { public: 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,14 @@ return true; } + bool WalkUpFromCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *S) { + Builder.markChildToken(S->getLocation(), + syntax::NodeRole::CxxNullPtrExpression_keyword); + Builder.foldNode(Builder.getExprRange(S), + new (allocator()) syntax::CxxNullPtrExpression, S); + return true; + } + bool WalkUpFromUnaryOperator(UnaryOperator *S) { Builder.markChildToken( S->getOperatorLoc(), 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,8 @@ return OS << "TranslationUnit"; case NodeKind::UnknownExpression: return OS << "UnknownExpression"; + case NodeKind::CxxNullPtrExpression: + return OS << "CxxNullPtrExpression"; case NodeKind::PrefixUnaryOperatorExpression: return OS << "PrefixUnaryOperatorExpression"; case NodeKind::PostfixUnaryOperatorExpression: @@ -116,6 +118,8 @@ return OS << "IfStatement_elseKeyword"; case syntax::NodeRole::IfStatement_elseStatement: return OS << "IfStatement_elseStatement"; + case syntax::NodeRole::CxxNullPtrExpression_keyword: + return OS << "CxxNullPtrExpression_keyword"; case syntax::NodeRole::UnaryOperatorExpression_operatorToken: return OS << "UnaryOperatorExpression_operatorToken"; case syntax::NodeRole::UnaryOperatorExpression_operand: @@ -158,6 +162,11 @@ llvm_unreachable("invalid role"); } +syntax::Leaf *syntax::CxxNullPtrExpression::nullPtrKeyword() { + return llvm::cast_or_null( + findChild(syntax::NodeRole::CxxNullPtrExpression_keyword)); +} + syntax::Expression *syntax::BinaryOperatorExpression::lhs() { return llvm::cast_or_null( findChild(syntax::NodeRole::BinaryOperatorExpression_leftHandSide)); 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 @@ -670,6 +670,35 @@ )txt"); } +TEST_P(SyntaxTreeTest, CxxNullPtrLiteral) { + if (!GetParam().isCXX11OrLater()) { + return; + } + expectTreeDumpEqual( + R"cpp( +void test() { + nullptr; +} + )cpp", + R"txt( +*: TranslationUnit +`-SimpleDeclaration + |-void + |-SimpleDeclarator + | |-test + | `-ParametersAndQualifiers + | |-( + | `-) + `-CompoundStatement + |-{ + |-ExpressionStatement + | |-CxxNullPtrExpression + | | `-nullptr + | `-; + `-} +)txt"); +} + TEST_P(SyntaxTreeTest, PostfixUnaryOperator) { expectTreeDumpEqual( R"cpp(