diff --git a/clang/include/clang/Tooling/Syntax/Nodes.h b/clang/include/clang/Tooling/Syntax/Nodes.h index e50e80ec1fc3..9446d911c18e 100644 --- a/clang/include/clang/Tooling/Syntax/Nodes.h +++ b/clang/include/clang/Tooling/Syntax/Nodes.h @@ -43,11 +43,12 @@ enum class NodeKind : uint16_t { PrefixUnaryOperatorExpression, PostfixUnaryOperatorExpression, BinaryOperatorExpression, - CxxNullPtrExpression, IntegerLiteralExpression, - BoolLiteralExpression, CharacterLiteralExpression, + FloatingLiteralExpression, StringLiteralExpression, + BoolLiteralExpression, + CxxNullPtrExpression, IdExpression, // Statements. @@ -247,14 +248,14 @@ public: } }; -/// C++11 'nullptr' expression. -class CxxNullPtrExpression final : public Expression { +/// Expression for integer literals. C++ [lex.icon] +class IntegerLiteralExpression final : public Expression { public: - CxxNullPtrExpression() : Expression(NodeKind::CxxNullPtrExpression) {} + IntegerLiteralExpression() : Expression(NodeKind::IntegerLiteralExpression) {} static bool classof(const Node *N) { - return N->kind() == NodeKind::CxxNullPtrExpression; + return N->kind() == NodeKind::IntegerLiteralExpression; } - syntax::Leaf *nullPtrKeyword(); + syntax::Leaf *literalToken(); }; /// Expression for character literals. C++ [lex.ccon] @@ -268,12 +269,23 @@ public: syntax::Leaf *literalToken(); }; -/// Expression for integer literals. -class IntegerLiteralExpression final : public Expression { +/// Expression for floating-point literals. C++ [lex.fcon] +class FloatingLiteralExpression final : public Expression { public: - IntegerLiteralExpression() : Expression(NodeKind::IntegerLiteralExpression) {} + FloatingLiteralExpression() + : Expression(NodeKind::FloatingLiteralExpression) {} static bool classof(const Node *N) { - return N->kind() == NodeKind::IntegerLiteralExpression; + return N->kind() == NodeKind::FloatingLiteralExpression; + } + syntax::Leaf *literalToken(); +}; + +/// Expression for string-literals. C++ [lex.string] +class StringLiteralExpression final : public Expression { +public: + StringLiteralExpression() : Expression(NodeKind::StringLiteralExpression) {} + static bool classof(const Node *N) { + return N->kind() == NodeKind::StringLiteralExpression; } syntax::Leaf *literalToken(); }; @@ -288,14 +300,14 @@ public: syntax::Leaf *literalToken(); }; -/// Expression for string-literals. C++ [lex.string] -class StringLiteralExpression final : public Expression { +/// Expression for the `nullptr` literal. C++ [lex.nullptr] +class CxxNullPtrExpression final : public Expression { public: - StringLiteralExpression() : Expression(NodeKind::StringLiteralExpression) {} + CxxNullPtrExpression() : Expression(NodeKind::CxxNullPtrExpression) {} static bool classof(const Node *N) { - return N->kind() == NodeKind::StringLiteralExpression; + return N->kind() == NodeKind::CxxNullPtrExpression; } - syntax::Leaf *literalToken(); + syntax::Leaf *nullPtrKeyword(); }; /// An abstract class for prefix and postfix unary operators. diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp index bd2f372e057b..6f740b3ab146 100644 --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -654,19 +654,20 @@ public: return true; } - bool WalkUpFromCXXBoolLiteralExpr(CXXBoolLiteralExpr *S) { - Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken); - Builder.foldNode(Builder.getExprRange(S), - new (allocator()) syntax::BoolLiteralExpression, S); - return true; - } - bool WalkUpFromCharacterLiteral(CharacterLiteral *S) { Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken); Builder.foldNode(Builder.getExprRange(S), new (allocator()) syntax::CharacterLiteralExpression, S); 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 WalkUpFromStringLiteral(StringLiteral *S) { Builder.markChildToken(S->getBeginLoc(), syntax::NodeRole::LiteralToken); Builder.foldNode(Builder.getExprRange(S), @@ -674,6 +675,13 @@ public: return true; } + bool WalkUpFromCXXBoolLiteralExpr(CXXBoolLiteralExpr *S) { + Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken); + Builder.foldNode(Builder.getExprRange(S), + new (allocator()) syntax::BoolLiteralExpression, 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 index 290b1e6bafa1..1f601fdf180b 100644 --- a/clang/lib/Tooling/Syntax/Nodes.cpp +++ b/clang/lib/Tooling/Syntax/Nodes.cpp @@ -18,16 +18,18 @@ llvm::raw_ostream &syntax::operator<<(llvm::raw_ostream &OS, NodeKind K) { return OS << "TranslationUnit"; case NodeKind::UnknownExpression: return OS << "UnknownExpression"; - case NodeKind::CxxNullPtrExpression: - return OS << "CxxNullPtrExpression"; case NodeKind::IntegerLiteralExpression: return OS << "IntegerLiteralExpression"; - case NodeKind::BoolLiteralExpression: - return OS << "BoolLiteralExpression"; case NodeKind::CharacterLiteralExpression: return OS << "CharacterLiteralExpression"; + case NodeKind::FloatingLiteralExpression: + return OS << "FloatingLiteralExpression"; case NodeKind::StringLiteralExpression: return OS << "StringLiteralExpression"; + case NodeKind::BoolLiteralExpression: + return OS << "BoolLiteralExpression"; + case NodeKind::CxxNullPtrExpression: + return OS << "CxxNullPtrExpression"; case NodeKind::PrefixUnaryOperatorExpression: return OS << "PrefixUnaryOperatorExpression"; case NodeKind::PostfixUnaryOperatorExpression: @@ -206,21 +208,26 @@ syntax::Leaf *syntax::IntegerLiteralExpression::literalToken() { findChild(syntax::NodeRole::LiteralToken)); } -syntax::Leaf *syntax::BoolLiteralExpression::literalToken() { - return llvm::cast_or_null( - findChild(syntax::NodeRole::LiteralToken)); -} - syntax::Leaf *syntax::CharacterLiteralExpression::literalToken() { return llvm::cast_or_null( findChild(syntax::NodeRole::LiteralToken)); } +syntax::Leaf *syntax::FloatingLiteralExpression::literalToken() { + return llvm::cast_or_null( + findChild(syntax::NodeRole::LiteralToken)); +} + syntax::Leaf *syntax::StringLiteralExpression::literalToken() { return llvm::cast_or_null( findChild(syntax::NodeRole::LiteralToken)); } +syntax::Leaf *syntax::BoolLiteralExpression::literalToken() { + return llvm::cast_or_null( + findChild(syntax::NodeRole::LiteralToken)); +} + syntax::Leaf *syntax::CxxNullPtrExpression::nullPtrKeyword() { 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 index bc2a65b2dd07..5dd6cc747628 100644 --- a/clang/unittests/Tooling/Syntax/TreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/TreeTest.cpp @@ -53,6 +53,8 @@ struct TestClangConfig { bool isC99OrLater() const { return Language == Lang_C99; } + bool isC() const { return Language == Lang_C89 || Language == Lang_C99; } + bool isCXX() const { return Language == Lang_CXX03 || Language == Lang_CXX11 || Language == Lang_CXX14 || Language == Lang_CXX17 || @@ -69,10 +71,6 @@ struct TestClangConfig { Language == Lang_CXX20; } - bool hasBoolType() const { - return Language == Lang_C89 || Language == Lang_C99; - } - bool isCXX17OrLater() const { return Language == Lang_CXX17 || Language == Lang_CXX20; } @@ -1207,301 +1205,6 @@ void test(S s) { )txt")); } -TEST_P(SyntaxTreeTest, CxxNullPtrLiteral) { - if (!GetParam().isCXX11OrLater()) { - return; - } - EXPECT_TRUE(treeDumpEqual( - R"cpp( -void test() { - nullptr; -} -)cpp", - R"txt( -*: TranslationUnit -`-SimpleDeclaration - |-void - |-SimpleDeclarator - | |-test - | `-ParametersAndQualifiers - | |-( - | `-) - `-CompoundStatement - |-{ - |-ExpressionStatement - | |-CxxNullPtrExpression - | | `-nullptr - | `-; - `-} -)txt")); -} - -TEST_P(SyntaxTreeTest, CharacterLiteral) { - EXPECT_TRUE(treeDumpEqual( - R"cpp( -void test() { - 'a'; - '\n'; - '\x20'; - '\0'; - L'a'; - L'α'; -} -)cpp", - R"txt( -*: TranslationUnit -`-SimpleDeclaration - |-void - |-SimpleDeclarator - | |-test - | `-ParametersAndQualifiers - | |-( - | `-) - `-CompoundStatement - |-{ - |-ExpressionStatement - | |-CharacterLiteralExpression - | | `-'a' - | `-; - |-ExpressionStatement - | |-CharacterLiteralExpression - | | `-'\n' - | `-; - |-ExpressionStatement - | |-CharacterLiteralExpression - | | `-'\x20' - | `-; - |-ExpressionStatement - | |-CharacterLiteralExpression - | | `-'\0' - | `-; - |-ExpressionStatement - | |-CharacterLiteralExpression - | | `-L'a' - | `-; - |-ExpressionStatement - | |-CharacterLiteralExpression - | | `-L'α' - | `-; - `-} -)txt")); -} - -TEST_P(SyntaxTreeTest, CharacterLiteralUtf) { - if (!GetParam().isCXX11OrLater()) { - return; - } - EXPECT_TRUE(treeDumpEqual( - R"cpp( -void test() { - u'a'; - u'構'; - U'a'; - U'🌲'; -} -)cpp", - R"txt( -*: TranslationUnit -`-SimpleDeclaration - |-void - |-SimpleDeclarator - | |-test - | `-ParametersAndQualifiers - | |-( - | `-) - `-CompoundStatement - |-{ - |-ExpressionStatement - | |-CharacterLiteralExpression - | | `-u'a' - | `-; - |-ExpressionStatement - | |-CharacterLiteralExpression - | | `-u'構' - | `-; - |-ExpressionStatement - | |-CharacterLiteralExpression - | | `-U'a' - | `-; - |-ExpressionStatement - | |-CharacterLiteralExpression - | | `-U'🌲' - | `-; - `-} -)txt")); -} - -TEST_P(SyntaxTreeTest, CharacterLiteralUtf8) { - if (!GetParam().isCXX17OrLater()) { - return; - } - EXPECT_TRUE(treeDumpEqual( - R"cpp( -void test() { - u8'a'; - u8'\x7f'; -} -)cpp", - R"txt( -*: TranslationUnit -`-SimpleDeclaration - |-void - |-SimpleDeclarator - | |-test - | `-ParametersAndQualifiers - | |-( - | `-) - `-CompoundStatement - |-{ - |-ExpressionStatement - | |-CharacterLiteralExpression - | | `-u8'a' - | `-; - |-ExpressionStatement - | |-CharacterLiteralExpression - | | `-u8'\x7f' - | `-; - `-} -)txt")); -} - -TEST_P(SyntaxTreeTest, BoolLiteral) { - if (GetParam().hasBoolType()) { - return; - } - EXPECT_TRUE(treeDumpEqual( - R"cpp( -void test() { - true; - false; -} -)cpp", - R"txt( -*: TranslationUnit -`-SimpleDeclaration - |-void - |-SimpleDeclarator - | |-test - | `-ParametersAndQualifiers - | |-( - | `-) - `-CompoundStatement - |-{ - |-ExpressionStatement - | |-BoolLiteralExpression - | | `-true - | `-; - |-ExpressionStatement - | |-BoolLiteralExpression - | | `-false - | `-; - `-} -)txt")); -} - -TEST_P(SyntaxTreeTest, StringLiteral) { - EXPECT_TRUE(treeDumpEqual( - R"cpp( -void test() { - "a\n\0\x20"; - L"αβ"; -} -)cpp", - R"txt( -*: TranslationUnit -`-SimpleDeclaration - |-void - |-SimpleDeclarator - | |-test - | `-ParametersAndQualifiers - | |-( - | `-) - `-CompoundStatement - |-{ - |-ExpressionStatement - | |-StringLiteralExpression - | | `-"a\n\0\x20" - | `-; - |-ExpressionStatement - | |-StringLiteralExpression - | | `-L"αβ" - | `-; - `-} -)txt")); -} - -TEST_P(SyntaxTreeTest, StringLiteralUtf) { - if (!GetParam().isCXX11OrLater()) { - return; - } - EXPECT_TRUE(treeDumpEqual( - R"cpp( -void test() { - u8"a\x1f\x05"; - u"C++抽象構文木"; - U"📖🌲\n"; -} -)cpp", - R"txt( -*: TranslationUnit -`-SimpleDeclaration - |-void - |-SimpleDeclarator - | |-test - | `-ParametersAndQualifiers - | |-( - | `-) - `-CompoundStatement - |-{ - |-ExpressionStatement - | |-StringLiteralExpression - | | `-u8"a\x1f\x05" - | `-; - |-ExpressionStatement - | |-StringLiteralExpression - | | `-u"C++抽象構文木" - | `-; - |-ExpressionStatement - | |-StringLiteralExpression - | | `-U"📖🌲\n" - | `-; - `-} -)txt")); -} - -TEST_P(SyntaxTreeTest, StringLiteralRaw) { - if (!GetParam().isCXX11OrLater()) { - return; - } - EXPECT_TRUE(treeDumpEqual( - R"cpp( -void test() { - R"SyntaxTree( - Hello "Syntax" \" - )SyntaxTree"; -} -)cpp", - R"txt( -*: TranslationUnit -`-SimpleDeclaration - |-void - |-SimpleDeclarator - | |-test - | `-ParametersAndQualifiers - | |-( - | `-) - `-CompoundStatement - |-{ - |-ExpressionStatement - | |-StringLiteralExpression - | | `-R"SyntaxTree( - Hello "Syntax" \" - )SyntaxTree" - | `-; - `-} -)txt")); -} - TEST_P(SyntaxTreeTest, IntegerLiteral) { EXPECT_TRUE(treeDumpEqual( R"cpp( @@ -1645,6 +1348,386 @@ void test() { )txt")); } +TEST_P(SyntaxTreeTest, CharacterLiteral) { + EXPECT_TRUE(treeDumpEqual( + R"cpp( +void test() { + 'a'; + '\n'; + '\x20'; + '\0'; + L'a'; + L'α'; +} +)cpp", + R"txt( +*: TranslationUnit +`-SimpleDeclaration + |-void + |-SimpleDeclarator + | |-test + | `-ParametersAndQualifiers + | |-( + | `-) + `-CompoundStatement + |-{ + |-ExpressionStatement + | |-CharacterLiteralExpression + | | `-'a' + | `-; + |-ExpressionStatement + | |-CharacterLiteralExpression + | | `-'\n' + | `-; + |-ExpressionStatement + | |-CharacterLiteralExpression + | | `-'\x20' + | `-; + |-ExpressionStatement + | |-CharacterLiteralExpression + | | `-'\0' + | `-; + |-ExpressionStatement + | |-CharacterLiteralExpression + | | `-L'a' + | `-; + |-ExpressionStatement + | |-CharacterLiteralExpression + | | `-L'α' + | `-; + `-} +)txt")); +} + +TEST_P(SyntaxTreeTest, CharacterLiteralUtf) { + if (!GetParam().isCXX11OrLater()) { + return; + } + EXPECT_TRUE(treeDumpEqual( + R"cpp( +void test() { + u'a'; + u'構'; + U'a'; + U'🌲'; +} +)cpp", + R"txt( +*: TranslationUnit +`-SimpleDeclaration + |-void + |-SimpleDeclarator + | |-test + | `-ParametersAndQualifiers + | |-( + | `-) + `-CompoundStatement + |-{ + |-ExpressionStatement + | |-CharacterLiteralExpression + | | `-u'a' + | `-; + |-ExpressionStatement + | |-CharacterLiteralExpression + | | `-u'構' + | `-; + |-ExpressionStatement + | |-CharacterLiteralExpression + | | `-U'a' + | `-; + |-ExpressionStatement + | |-CharacterLiteralExpression + | | `-U'🌲' + | `-; + `-} +)txt")); +} + +TEST_P(SyntaxTreeTest, CharacterLiteralUtf8) { + if (!GetParam().isCXX17OrLater()) { + return; + } + EXPECT_TRUE(treeDumpEqual( + R"cpp( +void test() { + u8'a'; + u8'\x7f'; +} +)cpp", + R"txt( +*: TranslationUnit +`-SimpleDeclaration + |-void + |-SimpleDeclarator + | |-test + | `-ParametersAndQualifiers + | |-( + | `-) + `-CompoundStatement + |-{ + |-ExpressionStatement + | |-CharacterLiteralExpression + | | `-u8'a' + | `-; + |-ExpressionStatement + | |-CharacterLiteralExpression + | | `-u8'\x7f' + | `-; + `-} +)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, StringLiteral) { + EXPECT_TRUE(treeDumpEqual( + R"cpp( +void test() { + "a\n\0\x20"; + L"αβ"; +} +)cpp", + R"txt( +*: TranslationUnit +`-SimpleDeclaration + |-void + |-SimpleDeclarator + | |-test + | `-ParametersAndQualifiers + | |-( + | `-) + `-CompoundStatement + |-{ + |-ExpressionStatement + | |-StringLiteralExpression + | | `-"a\n\0\x20" + | `-; + |-ExpressionStatement + | |-StringLiteralExpression + | | `-L"αβ" + | `-; + `-} +)txt")); +} + +TEST_P(SyntaxTreeTest, StringLiteralUtf) { + if (!GetParam().isCXX11OrLater()) { + return; + } + EXPECT_TRUE(treeDumpEqual( + R"cpp( +void test() { + u8"a\x1f\x05"; + u"C++抽象構文木"; + U"📖🌲\n"; +} +)cpp", + R"txt( +*: TranslationUnit +`-SimpleDeclaration + |-void + |-SimpleDeclarator + | |-test + | `-ParametersAndQualifiers + | |-( + | `-) + `-CompoundStatement + |-{ + |-ExpressionStatement + | |-StringLiteralExpression + | | `-u8"a\x1f\x05" + | `-; + |-ExpressionStatement + | |-StringLiteralExpression + | | `-u"C++抽象構文木" + | `-; + |-ExpressionStatement + | |-StringLiteralExpression + | | `-U"📖🌲\n" + | `-; + `-} +)txt")); +} + +TEST_P(SyntaxTreeTest, StringLiteralRaw) { + if (!GetParam().isCXX11OrLater()) { + return; + } + EXPECT_TRUE(treeDumpEqual( + R"cpp( +void test() { + R"SyntaxTree( + Hello "Syntax" \" + )SyntaxTree"; +} +)cpp", + R"txt( +*: TranslationUnit +`-SimpleDeclaration + |-void + |-SimpleDeclarator + | |-test + | `-ParametersAndQualifiers + | |-( + | `-) + `-CompoundStatement + |-{ + |-ExpressionStatement + | |-StringLiteralExpression + | | `-R"SyntaxTree( + Hello "Syntax" \" + )SyntaxTree" + | `-; + `-} +)txt")); +} + +TEST_P(SyntaxTreeTest, BoolLiteral) { + if (GetParam().isC()) { + return; + } + EXPECT_TRUE(treeDumpEqual( + R"cpp( +void test() { + true; + false; +} +)cpp", + R"txt( +*: TranslationUnit +`-SimpleDeclaration + |-void + |-SimpleDeclarator + | |-test + | `-ParametersAndQualifiers + | |-( + | `-) + `-CompoundStatement + |-{ + |-ExpressionStatement + | |-BoolLiteralExpression + | | `-true + | `-; + |-ExpressionStatement + | |-BoolLiteralExpression + | | `-false + | `-; + `-} +)txt")); +} + +TEST_P(SyntaxTreeTest, CxxNullPtrLiteral) { + if (!GetParam().isCXX11OrLater()) { + return; + } + EXPECT_TRUE(treeDumpEqual( + R"cpp( +void test() { + nullptr; +} +)cpp", + R"txt( +*: TranslationUnit +`-SimpleDeclaration + |-void + |-SimpleDeclarator + | |-test + | `-ParametersAndQualifiers + | |-( + | `-) + `-CompoundStatement + |-{ + |-ExpressionStatement + | |-CxxNullPtrExpression + | | `-nullptr + | `-; + `-} +)txt")); +} + TEST_P(SyntaxTreeTest, PostfixUnaryOperator) { EXPECT_TRUE(treeDumpEqual( R"cpp(