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 @@ -47,6 +47,7 @@ IntegerLiteralExpression, BoolLiteralExpression, CharacterLiteralExpression, + StringLiteralExpression, IdExpression, // Statements. @@ -287,6 +288,16 @@ 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(); +}; + /// 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 @@ -667,6 +667,12 @@ new (allocator()) syntax::CharacterLiteralExpression, S); return true; } + bool WalkUpFromStringLiteral(StringLiteral *S) { + Builder.markChildToken(S->getBeginLoc(), syntax::NodeRole::LiteralToken); + Builder.foldNode(Builder.getExprRange(S), + new (allocator()) syntax::StringLiteralExpression, S); + return true; + } bool WalkUpFromCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *S) { Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken); 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 @@ -26,6 +26,8 @@ return OS << "BoolLiteralExpression"; case NodeKind::CharacterLiteralExpression: return OS << "CharacterLiteralExpression"; + case NodeKind::StringLiteralExpression: + return OS << "StringLiteralExpression"; case NodeKind::PrefixUnaryOperatorExpression: return OS << "PrefixUnaryOperatorExpression"; case NodeKind::PostfixUnaryOperatorExpression: @@ -214,6 +216,11 @@ findChild(syntax::NodeRole::LiteralToken)); } +syntax::Leaf *syntax::StringLiteralExpression::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 --- a/clang/unittests/Tooling/Syntax/TreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/TreeTest.cpp @@ -1399,6 +1399,109 @@ )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( @@ -2730,7 +2833,7 @@ | |-BoolLiteralExpression | | `-true | |-, -| |-UnknownExpression +| |-StringLiteralExpression | | `-"message" | |-) | `-;