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 @@ -45,6 +45,7 @@ BinaryOperatorExpression, CxxNullPtrExpression, IntegerLiteralExpression, + FloatingLiteralExpression, IdExpression, // Statements. @@ -254,6 +255,17 @@ syntax::Leaf *nullPtrKeyword(); }; +/// Expression for floating-point literals. C++ [lex.fcon] +class FloatingLiteralExpression final : public Expression { +public: + FloatingLiteralExpression() + : Expression(NodeKind::FloatingLiteralExpression) {} + static bool classof(const Node *N) { + return N->kind() == NodeKind::FloatingLiteralExpression; + } + syntax::Leaf *literalToken(); +}; + /// Expression for integer literals. class IntegerLiteralExpression final : 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 @@ -654,6 +654,13 @@ return true; } + bool WalkUpFromFloatingLiteral(FloatingLiteral *S) { + Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken); + Builder.foldNode(Builder.getExprRange(S), + new (allocator()) syntax::FloatingLiteralExpression, S); + return true; + } + bool WalkUpFromCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *S) { Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken); Builder.foldNode(Builder.getExprRange(S), 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 @@ -22,6 +22,8 @@ return OS << "CxxNullPtrExpression"; case NodeKind::IntegerLiteralExpression: return OS << "IntegerLiteralExpression"; + case NodeKind::FloatingLiteralExpression: + return OS << "FloatingLiteralExpression"; case NodeKind::PrefixUnaryOperatorExpression: return OS << "PrefixUnaryOperatorExpression"; case NodeKind::PostfixUnaryOperatorExpression: @@ -195,6 +197,11 @@ findChild(syntax::NodeRole::IdExpression_id)); } +syntax::Leaf *syntax::FloatingLiteralExpression::literalToken() { + return llvm::cast_or_null( + findChild(syntax::NodeRole::LiteralToken)); +} + syntax::Leaf *syntax::IntegerLiteralExpression::literalToken() { return llvm::cast_or_null( findChild(syntax::NodeRole::LiteralToken)); 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 @@ -69,6 +69,10 @@ Language == Lang_CXX20; } + bool isCXX17OrLater() const { + return Language == Lang_CXX17 || Language == Lang_CXX20; + } + bool supportsCXXDynamicExceptionSpecification() const { return Language == Lang_CXX03 || Language == Lang_CXX11 || Language == Lang_CXX14; @@ -1228,6 +1232,91 @@ )txt")); } +TEST_P(SyntaxTreeTest, FloatingLiteral) { + EXPECT_TRUE(treeDumpEqual( + R"cpp( +void test() { + 1e-2; + 2.; + .2; + 2.f; +} +)cpp", + R"txt( +*: TranslationUnit +`-SimpleDeclaration + |-void + |-SimpleDeclarator + | |-test + | `-ParametersAndQualifiers + | |-( + | `-) + `-CompoundStatement + |-{ + |-ExpressionStatement + | |-FloatingLiteralExpression + | | `-1e-2 + | `-; + |-ExpressionStatement + | |-FloatingLiteralExpression + | | `-2. + | `-; + |-ExpressionStatement + | |-FloatingLiteralExpression + | | `-.2 + | `-; + |-ExpressionStatement + | |-FloatingLiteralExpression + | | `-2.f + | `-; + `-} +)txt")); +} + +TEST_P(SyntaxTreeTest, FloatingLiteralHexadecimal) { + if (!GetParam().isCXX17OrLater()) { + return; + } + EXPECT_TRUE(treeDumpEqual( + R"cpp( +void test() { + 0xfp1; + 0xf.p1; + 0x.fp1; + 0xf.fp1f; +} +)cpp", + R"txt( +*: TranslationUnit +`-SimpleDeclaration + |-void + |-SimpleDeclarator + | |-test + | `-ParametersAndQualifiers + | |-( + | `-) + `-CompoundStatement + |-{ + |-ExpressionStatement + | |-FloatingLiteralExpression + | | `-0xfp1 + | `-; + |-ExpressionStatement + | |-FloatingLiteralExpression + | | `-0xf.p1 + | `-; + |-ExpressionStatement + | |-FloatingLiteralExpression + | | `-0x.fp1 + | `-; + |-ExpressionStatement + | |-FloatingLiteralExpression + | | `-0xf.fp1f + | `-; + `-} +)txt")); +} + TEST_P(SyntaxTreeTest, IntegerLiteral) { EXPECT_TRUE(treeDumpEqual( R"cpp(