[clang] fdbd783 - Add parenthesized expression to SyntaxTree
Author: Eduardo Caldas Date: 2020-07-02T06:28:41Z New Revision: fdbd78333fc6f1deb3037d0961130f05dce059e7 URL: https://github.com/llvm/llvm-project/commit/fdbd78333fc6f1deb3037d0961130f05dce059e7 DIFF: https://github.com/llvm/llvm-project/commit/fdbd78333fc6f1deb3037d0961130f05dce059e7.diff LOG: Add parenthesized expression to SyntaxTree Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D82960 Added: Modified: clang/include/clang/Tooling/Syntax/Nodes.h clang/lib/Tooling/Syntax/BuildTree.cpp clang/lib/Tooling/Syntax/Nodes.cpp clang/unittests/Tooling/Syntax/TreeTest.cpp Removed: diff --git a/clang/include/clang/Tooling/Syntax/Nodes.h b/clang/include/clang/Tooling/Syntax/Nodes.h index 9446d911c18e..97605ceb76b7 100644 --- a/clang/include/clang/Tooling/Syntax/Nodes.h +++ b/clang/include/clang/Tooling/Syntax/Nodes.h @@ -43,6 +43,7 @@ enum class NodeKind : uint16_t { PrefixUnaryOperatorExpression, PostfixUnaryOperatorExpression, BinaryOperatorExpression, + ParenExpression, IntegerLiteralExpression, CharacterLiteralExpression, FloatingLiteralExpression, @@ -161,7 +162,8 @@ enum class NodeRole : uint8_t { ParametersAndQualifiers_trailingReturn, IdExpression_id, IdExpression_qualifier, - NestedNameSpecifier_specifier + NestedNameSpecifier_specifier, + ParenExpression_subExpression }; /// For debugging purposes. llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, NodeRole R); @@ -248,6 +250,19 @@ class UnknownExpression final : public Expression { } }; +/// Models a parenthesized expression `(E)`. C++ [expr.prim.paren] +/// e.g. `(3 + 2)` in `a = 1 + (3 + 2);` +class ParenExpression final : public Expression { +public: + ParenExpression() : Expression(NodeKind::ParenExpression) {} + static bool classof(const Node *N) { +return N->kind() == NodeKind::ParenExpression; + } + syntax::Leaf *openParen(); + syntax::Expression *subExpression(); + syntax::Leaf *closeParen(); +}; + /// Expression for integer literals. C++ [lex.icon] class IntegerLiteralExpression final : public Expression { public: diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp index 6f740b3ab146..8185af2a6cc7 100644 --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -647,6 +647,16 @@ class BuildTreeVisitor : public RecursiveASTVisitor { return true; } + bool WalkUpFromParenExpr(ParenExpr *S) { +Builder.markChildToken(S->getLParen(), syntax::NodeRole::OpenParen); +Builder.markExprChild(S->getSubExpr(), + syntax::NodeRole::ParenExpression_subExpression); +Builder.markChildToken(S->getRParen(), syntax::NodeRole::CloseParen); +Builder.foldNode(Builder.getExprRange(S), + new (allocator()) syntax::ParenExpression, S); +return true; + } + bool WalkUpFromIntegerLiteral(IntegerLiteral *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 1f601fdf180b..3d9b943d6db1 100644 --- a/clang/lib/Tooling/Syntax/Nodes.cpp +++ b/clang/lib/Tooling/Syntax/Nodes.cpp @@ -18,6 +18,8 @@ llvm::raw_ostream &syntax::operator<<(llvm::raw_ostream &OS, NodeKind K) { return OS << "TranslationUnit"; case NodeKind::UnknownExpression: return OS << "UnknownExpression"; + case NodeKind::ParenExpression: +return OS << "ParenExpression"; case NodeKind::IntegerLiteralExpression: return OS << "IntegerLiteralExpression"; case NodeKind::CharacterLiteralExpression: @@ -180,6 +182,8 @@ llvm::raw_ostream &syntax::operator<<(llvm::raw_ostream &OS, NodeRole R) { return OS << "IdExpression_qualifier"; case syntax::NodeRole::NestedNameSpecifier_specifier: return OS << "NestedNameSpecifier_specifier"; + case syntax::NodeRole::ParenExpression_subExpression: +return OS << "ParenExpression_subExpression"; } llvm_unreachable("invalid role"); } @@ -203,6 +207,21 @@ syntax::UnqualifiedId *syntax::IdExpression::unqualifiedId() { findChild(syntax::NodeRole::IdExpression_id)); } +syntax::Leaf *syntax::ParenExpression::openParen() { + return llvm::cast_or_null( + findChild(syntax::NodeRole::OpenParen)); +} + +syntax::Expression *syntax::ParenExpression::subExpression() { + return llvm::cast_or_null( + findChild(syntax::NodeRole::ParenExpression_subExpression)); +} + +syntax::Leaf *syntax::ParenExpression::closeParen() { + return llvm::cast_or_null( + findChild(syntax::NodeRole::CloseParen)); +} + syntax::Leaf *syntax::IntegerLiteralExpression::literalToken() { return llvm::cast_or_null( findChild(syntax::NodeRole::LiteralToken)); diff --git a/clang/unittests/Tooling/Syntax/Tre
[clang] ea8bba7 - Fix crash on overloaded postfix unary operators due to invalid sloc
Author: Eduardo Caldas Date: 2020-07-08T14:09:40Z New Revision: ea8bba7e8d0db3541a386ad649c4bf21d53e8380 URL: https://github.com/llvm/llvm-project/commit/ea8bba7e8d0db3541a386ad649c4bf21d53e8380 DIFF: https://github.com/llvm/llvm-project/commit/ea8bba7e8d0db3541a386ad649c4bf21d53e8380.diff LOG: Fix crash on overloaded postfix unary operators due to invalid sloc Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D82954 Added: Modified: clang/lib/Tooling/Syntax/BuildTree.cpp clang/unittests/Tooling/Syntax/TreeTest.cpp Removed: diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp index 4371a303bb9d..361455e69f5a 100644 --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -12,6 +12,7 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/Stmt.h" #include "clang/AST/TypeLoc.h" @@ -114,6 +115,85 @@ struct GetStartLoc : TypeLocVisitor { }; } // namespace +static syntax::NodeKind getOperatorNodeKind(const CXXOperatorCallExpr &E) { + switch (E.getOperator()) { + // Comparison + case OO_EqualEqual: + case OO_ExclaimEqual: + case OO_Greater: + case OO_GreaterEqual: + case OO_Less: + case OO_LessEqual: + case OO_Spaceship: + // Assignment + case OO_Equal: + case OO_SlashEqual: + case OO_PercentEqual: + case OO_CaretEqual: + case OO_PipeEqual: + case OO_LessLessEqual: + case OO_GreaterGreaterEqual: + case OO_PlusEqual: + case OO_MinusEqual: + case OO_StarEqual: + case OO_AmpEqual: + // Binary computation + case OO_Slash: + case OO_Percent: + case OO_Caret: + case OO_Pipe: + case OO_LessLess: + case OO_GreaterGreater: + case OO_AmpAmp: + case OO_PipePipe: + case OO_ArrowStar: + case OO_Comma: +return syntax::NodeKind::BinaryOperatorExpression; + case OO_Tilde: + case OO_Exclaim: +return syntax::NodeKind::PrefixUnaryOperatorExpression; + // Prefix/Postfix increment/decrement + case OO_PlusPlus: + case OO_MinusMinus: +switch (E.getNumArgs()) { +case 1: + return syntax::NodeKind::PrefixUnaryOperatorExpression; +case 2: + return syntax::NodeKind::PostfixUnaryOperatorExpression; +default: + llvm_unreachable("Invalid number of arguments for operator"); +} + // Operators that can be unary or binary + case OO_Plus: + case OO_Minus: + case OO_Star: + case OO_Amp: +switch (E.getNumArgs()) { +case 1: + return syntax::NodeKind::PrefixUnaryOperatorExpression; +case 2: + return syntax::NodeKind::BinaryOperatorExpression; +default: + llvm_unreachable("Invalid number of arguments for operator"); +} +return syntax::NodeKind::BinaryOperatorExpression; + // Not yet supported by SyntaxTree + case OO_New: + case OO_Delete: + case OO_Array_New: + case OO_Array_Delete: + case OO_Coawait: + case OO_Call: + case OO_Subscript: + case OO_Arrow: +return syntax::NodeKind::UnknownExpression; + case OO_Conditional: // not overloadable + case NUM_OVERLOADED_OPERATORS: + case OO_None: +llvm_unreachable("Not an overloadable operator"); + } +} + /// Gets the range of declarator as defined by the C++ grammar. E.g. /// `int a;` -> range of `a`, /// `int *a;` -> range of `*a`, @@ -733,8 +813,29 @@ class BuildTreeVisitor : public RecursiveASTVisitor { return true; } + bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *S) { +if (getOperatorNodeKind(*S) == +syntax::NodeKind::PostfixUnaryOperatorExpression) { + // A postfix unary operator is declared as taking two operands. The second + // operand is used to distinguish from its prefix counterpart. In the + // semantic AST this "phantom" operand is represented as a + // `IntegerLiteral` with invalid `SourceLocation`. We skip visiting this + // operand because it does not correspond to anything written in source + // code + for (auto *child : S->children()) { +if (child->getSourceRange().isInvalid()) + continue; +if (!TraverseStmt(child)) + return false; + } + return WalkUpFromCXXOperatorCallExpr(S); +} else + return RecursiveASTVisitor::TraverseCXXOperatorCallExpr(S); + } + bool WalkUpFromCXXOperatorCallExpr(CXXOperatorCallExpr *S) { -if (S->isInfixBinaryOp()) { +switch (getOperatorNodeKind(*S)) { +case syntax::NodeKind::BinaryOperatorExpression: Builder.markExprChild( S->getArg(0), syntax::NodeRole::BinaryOperatorExpression_leftHandSide); @@ -747,8 +848,31 @@ class BuildTreeVisitor : public RecursiveASTVisitor { Builder.foldNode(Builder.getExprRange(S), new (allocator()) syntax::BinaryOperato
[clang] 1db5b34 - Add kinded UDL for raw literal operator and numeric literal operator template
Author: Eduardo Caldas Date: 2020-07-10T16:21:11Z New Revision: 1db5b348c4c93b6610afb4fd515b389989efc302 URL: https://github.com/llvm/llvm-project/commit/1db5b348c4c93b6610afb4fd515b389989efc302 DIFF: https://github.com/llvm/llvm-project/commit/1db5b348c4c93b6610afb4fd515b389989efc302.diff LOG: Add kinded UDL for raw literal operator and numeric literal operator template Added: Modified: clang/include/clang/Tooling/Syntax/Nodes.h clang/lib/Tooling/Syntax/BuildTree.cpp clang/lib/Tooling/Syntax/Nodes.cpp clang/unittests/Tooling/Syntax/TreeTest.cpp Removed: diff --git a/clang/include/clang/Tooling/Syntax/Nodes.h b/clang/include/clang/Tooling/Syntax/Nodes.h index fb63c36bc4cc..d97b127638bb 100644 --- a/clang/include/clang/Tooling/Syntax/Nodes.h +++ b/clang/include/clang/Tooling/Syntax/Nodes.h @@ -50,7 +50,6 @@ enum class NodeKind : uint16_t { StringLiteralExpression, BoolLiteralExpression, CxxNullPtrExpression, - UnknownUserDefinedLiteralExpression, IntegerUserDefinedLiteralExpression, FloatUserDefinedLiteralExpression, CharUserDefinedLiteralExpression, @@ -340,8 +339,7 @@ class UserDefinedLiteralExpression : public Expression { public: UserDefinedLiteralExpression(NodeKind K) : Expression(K) {} static bool classof(const Node *N) { -return N->kind() == NodeKind::UnknownUserDefinedLiteralExpression || - N->kind() == NodeKind::IntegerUserDefinedLiteralExpression || +return N->kind() == NodeKind::IntegerUserDefinedLiteralExpression || N->kind() == NodeKind::FloatUserDefinedLiteralExpression || N->kind() == NodeKind::CharUserDefinedLiteralExpression || N->kind() == NodeKind::StringUserDefinedLiteralExpression; @@ -349,21 +347,6 @@ class UserDefinedLiteralExpression : public Expression { syntax::Leaf *literalToken(); }; -// We cannot yet distinguish between user-defined-integer-literal and -// user-defined-floating-point-literal, when using raw literal operator or -// numeric literal operator. C++ [lex.ext]p3, p4 -/// Expression for an unknown user-defined-literal. -class UnknownUserDefinedLiteralExpression final -: public UserDefinedLiteralExpression { -public: - UnknownUserDefinedLiteralExpression() - : UserDefinedLiteralExpression( -NodeKind::UnknownUserDefinedLiteralExpression) {} - static bool classof(const Node *N) { -return N->kind() == NodeKind::UnknownUserDefinedLiteralExpression; - } -}; - /// Expression for user-defined-integer-literal. C++ [lex.ext] class IntegerUserDefinedLiteralExpression final : public UserDefinedLiteralExpression { diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp index 8204d3fc66f3..5afe4965793a 100644 --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -23,6 +23,7 @@ #include "clang/Basic/Specifiers.h" #include "clang/Basic/TokenKinds.h" #include "clang/Lex/Lexer.h" +#include "clang/Lex/LiteralSupport.h" #include "clang/Tooling/Syntax/Nodes.h" #include "clang/Tooling/Syntax/Tokens.h" #include "clang/Tooling/Syntax/Tree.h" @@ -552,8 +553,8 @@ class syntax::TreeBuilder { namespace { class BuildTreeVisitor : public RecursiveASTVisitor { public: - explicit BuildTreeVisitor(ASTContext &Ctx, syntax::TreeBuilder &Builder) - : Builder(Builder), LangOpts(Ctx.getLangOpts()) {} + explicit BuildTreeVisitor(ASTContext &Context, syntax::TreeBuilder &Builder) + : Builder(Builder), Context(Context) {} bool shouldTraversePostOrder() const { return true; } @@ -718,30 +719,44 @@ class BuildTreeVisitor : public RecursiveASTVisitor { return WalkUpFromUserDefinedLiteral(S); } - syntax::NodeKind getUserDefinedLiteralKind(UserDefinedLiteral *S) { + syntax::UserDefinedLiteralExpression * + buildUserDefinedLiteral(UserDefinedLiteral *S) { switch (S->getLiteralOperatorKind()) { case clang::UserDefinedLiteral::LOK_Integer: - return syntax::NodeKind::IntegerUserDefinedLiteralExpression; + return new (allocator()) syntax::IntegerUserDefinedLiteralExpression; case clang::UserDefinedLiteral::LOK_Floating: - return syntax::NodeKind::FloatUserDefinedLiteralExpression; + return new (allocator()) syntax::FloatUserDefinedLiteralExpression; case clang::UserDefinedLiteral::LOK_Character: - return syntax::NodeKind::CharUserDefinedLiteralExpression; + return new (allocator()) syntax::CharUserDefinedLiteralExpression; case clang::UserDefinedLiteral::LOK_String: - return syntax::NodeKind::StringUserDefinedLiteralExpression; + return new (allocator()) syntax::StringUserDefinedLiteralExpression; case clang::UserDefinedLiteral::LOK_Raw: case clang::UserDefinedLiteral::LOK_Template: - // FIXME: Apply `NumericLiteralParser` to the underlying token to deduce - // the right UDL k
[clang] a474d5b - Use FileRange::text instead of Lexer::getSpelling
Author: Eduardo Caldas Date: 2020-07-10T16:21:12Z New Revision: a474d5bae4773782d50d4a5a62300c0f4a2dff28 URL: https://github.com/llvm/llvm-project/commit/a474d5bae4773782d50d4a5a62300c0f4a2dff28 DIFF: https://github.com/llvm/llvm-project/commit/a474d5bae4773782d50d4a5a62300c0f4a2dff28.diff LOG: Use FileRange::text instead of Lexer::getSpelling * as we are using them only for integer and floating literals they have the same behavior * FileRange::text is simpler to call and is within the context of syntax trees Added: Modified: clang/lib/Tooling/Syntax/BuildTree.cpp Removed: diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp index 5afe4965793a..6d13f1ace83b 100644 --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -737,20 +737,18 @@ class BuildTreeVisitor : public RecursiveASTVisitor { // information from the token. As integer and floating point have the same // token kind, we run `NumericLiteralParser` again to distinguish them. auto TokLoc = S->getBeginLoc(); - auto buffer = SmallVector(); - bool invalidSpelling = false; auto TokSpelling = - Lexer::getSpelling(TokLoc, buffer, Context.getSourceManager(), - Context.getLangOpts(), &invalidSpelling); - assert(!invalidSpelling); + Builder.findToken(TokLoc)->text(Context.getSourceManager()); auto Literal = NumericLiteralParser(TokSpelling, TokLoc, Context.getSourceManager(), Context.getLangOpts(), Context.getTargetInfo(), Context.getDiagnostics()); if (Literal.isIntegerLiteral()) return new (allocator()) syntax::IntegerUserDefinedLiteralExpression; - else + else { +assert(Literal.isFloatingLiteral()); return new (allocator()) syntax::FloatUserDefinedLiteralExpression; + } } } ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] f33c2c2 - Fix crash on `user defined literals`
Author: Eduardo Caldas Date: 2020-07-10T16:21:11Z New Revision: f33c2c27a8d4ea831aa7c2c2649066be91318d85 URL: https://github.com/llvm/llvm-project/commit/f33c2c27a8d4ea831aa7c2c2649066be91318d85 DIFF: https://github.com/llvm/llvm-project/commit/f33c2c27a8d4ea831aa7c2c2649066be91318d85.diff LOG: Fix crash on `user defined literals` Summary: Given an UserDefinedLiteral `1.2_w`: Problem: Lexer generates one Token for the literal, but ClangAST references two source locations Fix: Ignore the operator and interpret it as the underlying literal. e.g.: `1.2_w` token generates syntax node IntegerLiteral(1.2_w) Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D82157 Added: Modified: clang/include/clang/Tooling/Syntax/Nodes.h clang/lib/Tooling/Syntax/BuildTree.cpp clang/lib/Tooling/Syntax/Nodes.cpp clang/unittests/Tooling/Syntax/TreeTest.cpp Removed: diff --git a/clang/include/clang/Tooling/Syntax/Nodes.h b/clang/include/clang/Tooling/Syntax/Nodes.h index 97605ceb76b7..fb63c36bc4cc 100644 --- a/clang/include/clang/Tooling/Syntax/Nodes.h +++ b/clang/include/clang/Tooling/Syntax/Nodes.h @@ -50,6 +50,11 @@ enum class NodeKind : uint16_t { StringLiteralExpression, BoolLiteralExpression, CxxNullPtrExpression, + UnknownUserDefinedLiteralExpression, + IntegerUserDefinedLiteralExpression, + FloatUserDefinedLiteralExpression, + CharUserDefinedLiteralExpression, + StringUserDefinedLiteralExpression, IdExpression, // Statements. @@ -325,6 +330,88 @@ class CxxNullPtrExpression final : public Expression { syntax::Leaf *nullPtrKeyword(); }; +/// Expression for user-defined literal. C++ [lex.ext] +/// user-defined-literal: +/// user-defined-integer-literal +/// user-defined-floating-point-literal +/// user-defined-string-literal +/// user-defined-character-literal +class UserDefinedLiteralExpression : public Expression { +public: + UserDefinedLiteralExpression(NodeKind K) : Expression(K) {} + static bool classof(const Node *N) { +return N->kind() == NodeKind::UnknownUserDefinedLiteralExpression || + N->kind() == NodeKind::IntegerUserDefinedLiteralExpression || + N->kind() == NodeKind::FloatUserDefinedLiteralExpression || + N->kind() == NodeKind::CharUserDefinedLiteralExpression || + N->kind() == NodeKind::StringUserDefinedLiteralExpression; + } + syntax::Leaf *literalToken(); +}; + +// We cannot yet distinguish between user-defined-integer-literal and +// user-defined-floating-point-literal, when using raw literal operator or +// numeric literal operator. C++ [lex.ext]p3, p4 +/// Expression for an unknown user-defined-literal. +class UnknownUserDefinedLiteralExpression final +: public UserDefinedLiteralExpression { +public: + UnknownUserDefinedLiteralExpression() + : UserDefinedLiteralExpression( +NodeKind::UnknownUserDefinedLiteralExpression) {} + static bool classof(const Node *N) { +return N->kind() == NodeKind::UnknownUserDefinedLiteralExpression; + } +}; + +/// Expression for user-defined-integer-literal. C++ [lex.ext] +class IntegerUserDefinedLiteralExpression final +: public UserDefinedLiteralExpression { +public: + IntegerUserDefinedLiteralExpression() + : UserDefinedLiteralExpression( +NodeKind::IntegerUserDefinedLiteralExpression) {} + static bool classof(const Node *N) { +return N->kind() == NodeKind::IntegerUserDefinedLiteralExpression; + } +}; + +/// Expression for user-defined-floating-point-literal. C++ [lex.ext] +class FloatUserDefinedLiteralExpression final +: public UserDefinedLiteralExpression { +public: + FloatUserDefinedLiteralExpression() + : UserDefinedLiteralExpression( +NodeKind::FloatUserDefinedLiteralExpression) {} + static bool classof(const Node *N) { +return N->kind() == NodeKind::FloatUserDefinedLiteralExpression; + } +}; + +/// Expression for user-defined-character-literal. C++ [lex.ext] +class CharUserDefinedLiteralExpression final +: public UserDefinedLiteralExpression { +public: + CharUserDefinedLiteralExpression() + : UserDefinedLiteralExpression( +NodeKind::CharUserDefinedLiteralExpression) {} + static bool classof(const Node *N) { +return N->kind() == NodeKind::CharUserDefinedLiteralExpression; + } +}; + +/// Expression for user-defined-string-literal. C++ [lex.ext] +class StringUserDefinedLiteralExpression final +: public UserDefinedLiteralExpression { +public: + StringUserDefinedLiteralExpression() + : UserDefinedLiteralExpression( +NodeKind::StringUserDefinedLiteralExpression) {} + static bool classof(const Node *N) { +return N->kind() == NodeKind::StringUserDefinedLiteralExpression; + } +}; + /// An abstract class for prefix and postfix unary operators. class UnaryOperatorExpression : public Expression { pub
[clang] 7f7f856 - Add `BoolLiteralExpression` to SyntaxTree
Author: Eduardo Caldas Date: 2020-06-25T15:37:53Z New Revision: 7f7f8564808b51aa62744edf75c07c0df102056a URL: https://github.com/llvm/llvm-project/commit/7f7f8564808b51aa62744edf75c07c0df102056a DIFF: https://github.com/llvm/llvm-project/commit/7f7f8564808b51aa62744edf75c07c0df102056a.diff LOG: Add `BoolLiteralExpression` to SyntaxTree Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D82310 Added: Modified: clang/include/clang/Tooling/Syntax/Nodes.h clang/lib/Tooling/Syntax/BuildTree.cpp clang/lib/Tooling/Syntax/Nodes.cpp clang/unittests/Tooling/Syntax/TreeTest.cpp Removed: diff --git a/clang/include/clang/Tooling/Syntax/Nodes.h b/clang/include/clang/Tooling/Syntax/Nodes.h index 139ac9aa8eca..255a108133bc 100644 --- a/clang/include/clang/Tooling/Syntax/Nodes.h +++ b/clang/include/clang/Tooling/Syntax/Nodes.h @@ -45,6 +45,7 @@ enum class NodeKind : uint16_t { BinaryOperatorExpression, CxxNullPtrExpression, IntegerLiteralExpression, + BoolLiteralExpression, IdExpression, // Statements. @@ -264,6 +265,16 @@ class IntegerLiteralExpression final : public Expression { syntax::Leaf *literalToken(); }; +/// Expression for boolean literals. C++ [lex.bool] +class BoolLiteralExpression final : public Expression { +public: + BoolLiteralExpression() : Expression(NodeKind::BoolLiteralExpression) {} + static bool classof(const Node *N) { +return N->kind() == NodeKind::BoolLiteralExpression; + } + 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 index 3ee66aabfb6d..7ff603fbd33a 100644 --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -654,6 +654,13 @@ class BuildTreeVisitor : public RecursiveASTVisitor { 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 623391a7d844..498721d3a371 100644 --- a/clang/lib/Tooling/Syntax/Nodes.cpp +++ b/clang/lib/Tooling/Syntax/Nodes.cpp @@ -22,6 +22,8 @@ llvm::raw_ostream &syntax::operator<<(llvm::raw_ostream &OS, NodeKind K) { return OS << "CxxNullPtrExpression"; case NodeKind::IntegerLiteralExpression: return OS << "IntegerLiteralExpression"; + case NodeKind::BoolLiteralExpression: +return OS << "BoolLiteralExpression"; case NodeKind::PrefixUnaryOperatorExpression: return OS << "PrefixUnaryOperatorExpression"; case NodeKind::PostfixUnaryOperatorExpression: @@ -200,6 +202,11 @@ 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::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 5f48ef129988..d32ce6203913 100644 --- a/clang/unittests/Tooling/Syntax/TreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/TreeTest.cpp @@ -69,6 +69,10 @@ struct TestClangConfig { Language == Lang_CXX20; } + bool hasBoolType() const { +return Language == Lang_C89 || Language == Lang_C99; + } + bool supportsCXXDynamicExceptionSpecification() const { return Language == Lang_CXX03 || Language == Lang_CXX11 || Language == Lang_CXX14; @@ -1228,6 +1232,40 @@ void test() { )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, IntegerLiteral) { EXPECT_TRUE(treeDumpEqual( R"cpp( @@ -1691,18 +1729,18 @@ void test(int
[clang] 221d7bb - Add `CharLiteral` to SyntaxTree
Author: Eduardo Caldas Date: 2020-06-25T17:05:08Z New Revision: 221d7bbe49cceb0e408f0f46d9f8371e6c9fee2c URL: https://github.com/llvm/llvm-project/commit/221d7bbe49cceb0e408f0f46d9f8371e6c9fee2c DIFF: https://github.com/llvm/llvm-project/commit/221d7bbe49cceb0e408f0f46d9f8371e6c9fee2c.diff LOG: Add `CharLiteral` to SyntaxTree Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D82312 Added: Modified: clang/include/clang/Tooling/Syntax/Nodes.h clang/lib/Tooling/Syntax/BuildTree.cpp clang/lib/Tooling/Syntax/Nodes.cpp clang/unittests/Tooling/Syntax/TreeTest.cpp Removed: diff --git a/clang/include/clang/Tooling/Syntax/Nodes.h b/clang/include/clang/Tooling/Syntax/Nodes.h index 255a108133bc..4310bc5dc81c 100644 --- a/clang/include/clang/Tooling/Syntax/Nodes.h +++ b/clang/include/clang/Tooling/Syntax/Nodes.h @@ -46,6 +46,7 @@ enum class NodeKind : uint16_t { CxxNullPtrExpression, IntegerLiteralExpression, BoolLiteralExpression, + CharacterLiteralExpression, IdExpression, // Statements. @@ -255,6 +256,17 @@ class CxxNullPtrExpression final : public Expression { syntax::Leaf *nullPtrKeyword(); }; +/// Expression for character literals. C++ [lex.ccon] +class CharacterLiteralExpression final : public Expression { +public: + CharacterLiteralExpression() + : Expression(NodeKind::CharacterLiteralExpression) {} + static bool classof(const Node *N) { +return N->kind() == NodeKind::CharacterLiteralExpression; + } + 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 index 7ff603fbd33a..5912a54d1bee 100644 --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -661,6 +661,13 @@ class BuildTreeVisitor : public RecursiveASTVisitor { 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 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 498721d3a371..e6e280e9cb13 100644 --- a/clang/lib/Tooling/Syntax/Nodes.cpp +++ b/clang/lib/Tooling/Syntax/Nodes.cpp @@ -24,6 +24,8 @@ llvm::raw_ostream &syntax::operator<<(llvm::raw_ostream &OS, NodeKind K) { return OS << "IntegerLiteralExpression"; case NodeKind::BoolLiteralExpression: return OS << "BoolLiteralExpression"; + case NodeKind::CharacterLiteralExpression: +return OS << "CharacterLiteralExpression"; case NodeKind::PrefixUnaryOperatorExpression: return OS << "PrefixUnaryOperatorExpression"; case NodeKind::PostfixUnaryOperatorExpression: @@ -207,6 +209,11 @@ syntax::Leaf *syntax::BoolLiteralExpression::literalToken() { findChild(syntax::NodeRole::LiteralToken)); } +syntax::Leaf *syntax::CharacterLiteralExpression::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 d32ce6203913..0a20950458d6 100644 --- a/clang/unittests/Tooling/Syntax/TreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/TreeTest.cpp @@ -73,6 +73,10 @@ struct TestClangConfig { return Language == Lang_C89 || Language == Lang_C99; } + bool isCXX17OrLater() const { +return Language == Lang_CXX17 || Language == Lang_CXX20; + } + bool supportsCXXDynamicExceptionSpecification() const { return Language == Lang_CXX03 || Language == Lang_CXX11 || Language == Lang_CXX14; @@ -1232,6 +1236,135 @@ 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' +| `-; +|-ExpressionS
[clang] 466e8b7 - Add StringLiteral to SyntaxTree
Author: Eduardo Caldas Date: 2020-06-25T17:05:08Z New Revision: 466e8b7ea6e162d48cac42ccda210bdeb11080e3 URL: https://github.com/llvm/llvm-project/commit/466e8b7ea6e162d48cac42ccda210bdeb11080e3 DIFF: https://github.com/llvm/llvm-project/commit/466e8b7ea6e162d48cac42ccda210bdeb11080e3.diff LOG: Add StringLiteral to SyntaxTree Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D82360 Added: Modified: clang/include/clang/Tooling/Syntax/Nodes.h clang/lib/Tooling/Syntax/BuildTree.cpp clang/lib/Tooling/Syntax/Nodes.cpp clang/unittests/Tooling/Syntax/TreeTest.cpp Removed: diff --git a/clang/include/clang/Tooling/Syntax/Nodes.h b/clang/include/clang/Tooling/Syntax/Nodes.h index 4310bc5dc81c..e50e80ec1fc3 100644 --- a/clang/include/clang/Tooling/Syntax/Nodes.h +++ b/clang/include/clang/Tooling/Syntax/Nodes.h @@ -47,6 +47,7 @@ enum class NodeKind : uint16_t { IntegerLiteralExpression, BoolLiteralExpression, CharacterLiteralExpression, + StringLiteralExpression, IdExpression, // Statements. @@ -287,6 +288,16 @@ class BoolLiteralExpression final : public Expression { 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 index 5912a54d1bee..bd2f372e057b 100644 --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -667,6 +667,12 @@ class BuildTreeVisitor : public RecursiveASTVisitor { 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 index e6e280e9cb13..290b1e6bafa1 100644 --- a/clang/lib/Tooling/Syntax/Nodes.cpp +++ b/clang/lib/Tooling/Syntax/Nodes.cpp @@ -26,6 +26,8 @@ llvm::raw_ostream &syntax::operator<<(llvm::raw_ostream &OS, NodeKind K) { 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 @@ syntax::Leaf *syntax::CharacterLiteralExpression::literalToken() { 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 index 0a20950458d6..bc2a65b2dd07 100644 --- a/clang/unittests/Tooling/Syntax/TreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/TreeTest.cpp @@ -1399,6 +1399,109 @@ void test() { )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
[clang] 7b404b6 - Add `FloatingLiteral` to SyntaxTree
Author: Eduardo Caldas Date: 2020-06-25T17:05:08Z New Revision: 7b404b6d003181e990f53d27866ee98d5151c4f3 URL: https://github.com/llvm/llvm-project/commit/7b404b6d003181e990f53d27866ee98d5151c4f3 DIFF: https://github.com/llvm/llvm-project/commit/7b404b6d003181e990f53d27866ee98d5151c4f3.diff LOG: Add `FloatingLiteral` to SyntaxTree Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D82318 Added: Modified: clang/include/clang/Tooling/Syntax/Nodes.h clang/lib/Tooling/Syntax/BuildTree.cpp clang/lib/Tooling/Syntax/Nodes.cpp clang/unittests/Tooling/Syntax/TreeTest.cpp Removed: 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 @@ class UnknownExpression final : public Expression { } }; -/// 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 @@ class CharacterLiteralExpression final : public Expression { 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 @@ class BoolLiteralExpression final : public Expression { 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 @@ class BuildTreeVisitor : public RecursiveASTVisitor { return true; } - bool WalkUpFromCXXBoolLiteralExpr(CXXBoolLiteralExpr *S) { + bool WalkUpFromCharacterLiteral(CharacterLiteral *S) { Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken); Builder.foldNode(Builder.getExprRange(S), - new (allocator()) syntax::BoolLiteralExpression, S); + new (allocator()) syntax::CharacterLiteralExpression, S); return true; } - bool WalkUpFromCharacterLiteral(CharacterLiteral *S) { + bool WalkUpFromFloatingLiteral(FloatingLiteral *S) { Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken); Builder.foldNode(Builder.getExprR
[clang] 860cbbd - [SyntaxTree] Add support for `LiteralExpression`
Author: Eduardo Caldas Date: 2020-08-04T14:05:09Z New Revision: 860cbbdd6b84017e6d37e1752b0358a05da6b115 URL: https://github.com/llvm/llvm-project/commit/860cbbdd6b84017e6d37e1752b0358a05da6b115 DIFF: https://github.com/llvm/llvm-project/commit/860cbbdd6b84017e6d37e1752b0358a05da6b115.diff LOG: [SyntaxTree] Add support for `LiteralExpression` We use inheritance to model the grammar's disjunction rule: literal: integer-literal character-literal floating-point-literal string-literal boolean-literal pointer-literal user-defined-literal Differential Revision: https://reviews.llvm.org/D85186 Added: Modified: clang/include/clang/Tooling/Syntax/Nodes.h clang/lib/Tooling/Syntax/Nodes.cpp Removed: diff --git a/clang/include/clang/Tooling/Syntax/Nodes.h b/clang/include/clang/Tooling/Syntax/Nodes.h index d97b127638bb..8a873f9d5273 100644 --- a/clang/include/clang/Tooling/Syntax/Nodes.h +++ b/clang/include/clang/Tooling/Syntax/Nodes.h @@ -267,66 +267,82 @@ class ParenExpression final : public Expression { syntax::Leaf *closeParen(); }; +/// Expression for literals. C++ [lex.literal] +class LiteralExpression : public Expression { +public: + LiteralExpression(NodeKind K) : Expression(K) {} + static bool classof(const Node *N) { +return N->kind() == NodeKind::IntegerLiteralExpression || + N->kind() == NodeKind::CharacterLiteralExpression || + N->kind() == NodeKind::FloatingLiteralExpression || + N->kind() == NodeKind::StringLiteralExpression || + N->kind() == NodeKind::BoolLiteralExpression || + N->kind() == NodeKind::CxxNullPtrExpression || + N->kind() == NodeKind::IntegerUserDefinedLiteralExpression || + N->kind() == NodeKind::FloatUserDefinedLiteralExpression || + N->kind() == NodeKind::CharUserDefinedLiteralExpression || + N->kind() == NodeKind::StringUserDefinedLiteralExpression; + } + syntax::Leaf *literalToken(); +}; + /// Expression for integer literals. C++ [lex.icon] -class IntegerLiteralExpression final : public Expression { +class IntegerLiteralExpression final : public LiteralExpression { public: - IntegerLiteralExpression() : Expression(NodeKind::IntegerLiteralExpression) {} + IntegerLiteralExpression() + : LiteralExpression(NodeKind::IntegerLiteralExpression) {} static bool classof(const Node *N) { return N->kind() == NodeKind::IntegerLiteralExpression; } - syntax::Leaf *literalToken(); }; /// Expression for character literals. C++ [lex.ccon] -class CharacterLiteralExpression final : public Expression { +class CharacterLiteralExpression final : public LiteralExpression { public: CharacterLiteralExpression() - : Expression(NodeKind::CharacterLiteralExpression) {} + : LiteralExpression(NodeKind::CharacterLiteralExpression) {} static bool classof(const Node *N) { return N->kind() == NodeKind::CharacterLiteralExpression; } - syntax::Leaf *literalToken(); }; /// Expression for floating-point literals. C++ [lex.fcon] -class FloatingLiteralExpression final : public Expression { +class FloatingLiteralExpression final : public LiteralExpression { public: FloatingLiteralExpression() - : Expression(NodeKind::FloatingLiteralExpression) {} + : LiteralExpression(NodeKind::FloatingLiteralExpression) {} static bool classof(const Node *N) { return N->kind() == NodeKind::FloatingLiteralExpression; } - syntax::Leaf *literalToken(); }; /// Expression for string-literals. C++ [lex.string] -class StringLiteralExpression final : public Expression { +class StringLiteralExpression final : public LiteralExpression { public: - StringLiteralExpression() : Expression(NodeKind::StringLiteralExpression) {} + StringLiteralExpression() + : LiteralExpression(NodeKind::StringLiteralExpression) {} static bool classof(const Node *N) { return N->kind() == NodeKind::StringLiteralExpression; } - syntax::Leaf *literalToken(); }; /// Expression for boolean literals. C++ [lex.bool] -class BoolLiteralExpression final : public Expression { +class BoolLiteralExpression final : public LiteralExpression { public: - BoolLiteralExpression() : Expression(NodeKind::BoolLiteralExpression) {} + BoolLiteralExpression() + : LiteralExpression(NodeKind::BoolLiteralExpression) {} static bool classof(const Node *N) { return N->kind() == NodeKind::BoolLiteralExpression; } - syntax::Leaf *literalToken(); }; /// Expression for the `nullptr` literal. C++ [lex.nullptr] -class CxxNullPtrExpression final : public Expression { +class CxxNullPtrExpression final : public LiteralExpression { public: - CxxNullPtrExpression() : Expression(NodeKind::CxxNullPtrExpression) {} + CxxNullPtrExpression() : LiteralExpression(NodeKind::CxxNullPtrExpression) {} static bool classof(const Node *N) { return N->kind() =
[clang] 8ce15f7 - [SyntaxTree] Fix crash on pointer to member function
Author: Eduardo Caldas Date: 2020-08-04T14:31:12Z New Revision: 8ce15f7eeb122c0bba4b676d797217359dd57c30 URL: https://github.com/llvm/llvm-project/commit/8ce15f7eeb122c0bba4b676d797217359dd57c30 DIFF: https://github.com/llvm/llvm-project/commit/8ce15f7eeb122c0bba4b676d797217359dd57c30.diff LOG: [SyntaxTree] Fix crash on pointer to member function Differential Revision: https://reviews.llvm.org/D85146 Added: Modified: clang/lib/Tooling/Syntax/BuildTree.cpp clang/unittests/Tooling/Syntax/TreeTest.cpp Removed: diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp index 1f192180ec45..15b7c8fab198 100644 --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -939,6 +939,8 @@ class BuildTreeVisitor : public RecursiveASTVisitor { return true; } + // FIXME: Deleting the `TraverseParenTypeLoc` override doesn't change test + // results. Find test coverage or remove it. bool TraverseParenTypeLoc(ParenTypeLoc L) { // We reverse order of traversal to get the proper syntax structure. if (!WalkUpFromParenTypeLoc(L)) @@ -987,6 +989,16 @@ class BuildTreeVisitor : public RecursiveASTVisitor { return WalkUpFromFunctionTypeLoc(L); } + bool TraverseMemberPointerTypeLoc(MemberPointerTypeLoc L) { +// In the source code "void (Y::*mp)()" `MemberPointerTypeLoc` corresponds +// to "Y::*" but it points to a `ParenTypeLoc` that corresponds to +// "(Y::*mp)" We thus reverse the order of traversal to get the proper +// syntax structure. +if (!WalkUpFromMemberPointerTypeLoc(L)) + return false; +return TraverseTypeLoc(L.getPointeeLoc()); + } + bool WalkUpFromMemberPointerTypeLoc(MemberPointerTypeLoc L) { auto SR = L.getLocalSourceRange(); Builder.foldNode(Builder.getRange(SR), diff --git a/clang/unittests/Tooling/Syntax/TreeTest.cpp b/clang/unittests/Tooling/Syntax/TreeTest.cpp index a722ca2b1a45..3ccfabb95da9 100644 --- a/clang/unittests/Tooling/Syntax/TreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/TreeTest.cpp @@ -4074,6 +4074,99 @@ const int X::* b; )txt")); } +TEST_P(SyntaxTreeTest, MemberFunctionPointer) { + if (!GetParam().isCXX()) { +return; + } + EXPECT_TRUE(treeDumpEqual( + R"cpp( +struct X { + struct Y {}; +}; +void (X::*xp)(); +void (X::**xpp)(const int*); +// FIXME: Generate the right syntax tree for this type, +// i.e. create a syntax node for the outer member pointer +void (X::Y::*xyp)(const int*, char); +)cpp", + R"txt( +*: TranslationUnit +|-SimpleDeclaration +| |-struct +| |-X +| |-{ +| |-SimpleDeclaration +| | |-struct +| | |-Y +| | |-{ +| | |-} +| | `-; +| |-} +| `-; +|-SimpleDeclaration +| |-void +| |-SimpleDeclarator +| | |-ParenDeclarator +| | | |-( +| | | |-MemberPointer +| | | | |-X +| | | | |-:: +| | | | `-* +| | | |-xp +| | | `-) +| | `-ParametersAndQualifiers +| | |-( +| | `-) +| `-; +|-SimpleDeclaration +| |-void +| |-SimpleDeclarator +| | |-ParenDeclarator +| | | |-( +| | | |-MemberPointer +| | | | |-X +| | | | |-:: +| | | | `-* +| | | |-* +| | | |-xpp +| | | `-) +| | `-ParametersAndQualifiers +| | |-( +| | |-SimpleDeclaration +| | | |-const +| | | |-int +| | | `-SimpleDeclarator +| | | `-* +| | `-) +| `-; +`-SimpleDeclaration + |-void + |-SimpleDeclarator + | |-ParenDeclarator + | | |-( + | | |-X + | | |-:: + | | |-MemberPointer + | | | |-Y + | | | |-:: + | | | `-* + | | |-xyp + | | `-) + | `-ParametersAndQualifiers + | |-( + | |-SimpleDeclaration + | | |-const + | | |-int + | | `-SimpleDeclarator + | | `-* + | |-, + | |-SimpleDeclaration + | | `-char + | `-) + `-; +)txt")); +} + TEST_P(SyntaxTreeTest, ComplexDeclarator) { EXPECT_TRUE(treeDumpEqual( R"cpp( ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] c5cdc3e - [SyntaxTree] Add test coverage for `->*` operator
Author: Eduardo Caldas Date: 2020-08-05T07:36:39Z New Revision: c5cdc3e801ad1b0aceaf220d78a3ff3fab1e0fdb URL: https://github.com/llvm/llvm-project/commit/c5cdc3e801ad1b0aceaf220d78a3ff3fab1e0fdb DIFF: https://github.com/llvm/llvm-project/commit/c5cdc3e801ad1b0aceaf220d78a3ff3fab1e0fdb.diff LOG: [SyntaxTree] Add test coverage for `->*` operator This was the last binary operator that we supported but didn't have any test coverage. The recent fix in a crash in member pointers allowed us to add this test. Differential Revision: https://reviews.llvm.org/D85185 Added: Modified: clang/unittests/Tooling/Syntax/TreeTest.cpp Removed: diff --git a/clang/unittests/Tooling/Syntax/TreeTest.cpp b/clang/unittests/Tooling/Syntax/TreeTest.cpp index 3ccfabb95da9..e696be3dae7c 100644 --- a/clang/unittests/Tooling/Syntax/TreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/TreeTest.cpp @@ -2329,16 +2329,17 @@ struct X { friend bool operator<(const X&, const X&); friend X operator<<(X&, const X&); X operator,(X&); - // TODO: Fix crash on member function pointer and add a test for `->*` - // TODO: Unbox operators in syntax tree. + X operator->*(int); + // TODO: Unbox operators in syntax tree. // Represent operators by `+` instead of `IdExpression-UnqualifiedId-+` }; -void test(X x, X y) { +void test(X x, X y, X* xp, int X::* pmi) { x = y; x + y; x < y; x << y; x, y; + xp->*pmi; } )cpp", R"txt( @@ -2437,6 +2438,17 @@ void test(X x, X y) { | | | | `-& | | | `-) | | `-; +| |-SimpleDeclaration +| | |-X +| | |-SimpleDeclarator +| | | |-operator +| | | |-->* +| | | `-ParametersAndQualifiers +| | | |-( +| | | |-SimpleDeclaration +| | | | `-int +| | | `-) +| | `-; | |-} | `-; `-SimpleDeclaration @@ -2454,6 +2466,21 @@ void test(X x, X y) { | | |-X | | `-SimpleDeclarator | | `-y + | |-, + | |-SimpleDeclaration + | | |-X + | | `-SimpleDeclarator + | | |-* + | | `-xp + | |-, + | |-SimpleDeclaration + | | |-int + | | `-SimpleDeclarator + | | |-MemberPointer + | | | |-X + | | | |-:: + | | | `-* + | | `-pmi | `-) `-CompoundStatement |-{ @@ -2518,6 +2545,16 @@ void test(X x, X y) { | | `-UnqualifiedId | | `-y | `-; +|-ExpressionStatement +| |-BinaryOperatorExpression +| | |-IdExpression +| | | `-UnqualifiedId +| | | `-xp +| | |-->* +| | `-IdExpression +| | `-UnqualifiedId +| | `-pmi +| `-; `-} )txt")); } ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] ba41a0f - [SyntaxTree][NFC] remove redundant namespace-specifiers
Author: Eduardo Caldas Date: 2020-08-07T08:45:29Z New Revision: ba41a0f7339c8cbd065f032cc5f8c1d87a74e124 URL: https://github.com/llvm/llvm-project/commit/ba41a0f7339c8cbd065f032cc5f8c1d87a74e124 DIFF: https://github.com/llvm/llvm-project/commit/ba41a0f7339c8cbd065f032cc5f8c1d87a74e124.diff LOG: [SyntaxTree][NFC] remove redundant namespace-specifiers Differential Revision: https://reviews.llvm.org/D85427 Added: Modified: clang/include/clang/Tooling/Syntax/Nodes.h clang/include/clang/Tooling/Syntax/Tree.h clang/lib/Tooling/Syntax/BuildTree.cpp clang/lib/Tooling/Syntax/Nodes.cpp clang/lib/Tooling/Syntax/Tree.cpp clang/unittests/Tooling/Syntax/TreeTest.cpp Removed: diff --git a/clang/include/clang/Tooling/Syntax/Nodes.h b/clang/include/clang/Tooling/Syntax/Nodes.h index 8a873f9d5273..a5972a394583 100644 --- a/clang/include/clang/Tooling/Syntax/Nodes.h +++ b/clang/include/clang/Tooling/Syntax/Nodes.h @@ -100,7 +100,7 @@ enum class NodeKind : uint16_t { UnqualifiedId }; /// For debugging purposes. -llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, NodeKind K); +raw_ostream &operator<<(raw_ostream &OS, NodeKind K); /// A relation between a parent and child node, e.g. 'left-hand-side of /// a binary expression'. Used for implementing accessors. @@ -170,7 +170,7 @@ enum class NodeRole : uint8_t { ParenExpression_subExpression }; /// For debugging purposes. -llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, NodeRole R); +raw_ostream &operator<<(raw_ostream &OS, NodeRole R); class SimpleDeclarator; @@ -212,7 +212,7 @@ class NestedNameSpecifier final : public Tree { static bool classof(const Node *N) { return N->kind() <= NodeKind::NestedNameSpecifier; } - std::vector specifiers(); + std::vector specifiers(); }; /// Models an `unqualified-id`. C++ [expr.prim.id.unqual] @@ -238,10 +238,10 @@ class IdExpression final : public Expression { static bool classof(const Node *N) { return N->kind() == NodeKind::IdExpression; } - syntax::NestedNameSpecifier *qualifier(); + NestedNameSpecifier *qualifier(); // TODO after expose `id-expression` from `DependentScopeDeclRefExpr`: // Add accessor for `template_opt`. - syntax::UnqualifiedId *unqualifiedId(); + UnqualifiedId *unqualifiedId(); }; /// An expression of an unknown kind, i.e. one not currently handled by the @@ -262,9 +262,9 @@ class ParenExpression final : public Expression { static bool classof(const Node *N) { return N->kind() == NodeKind::ParenExpression; } - syntax::Leaf *openParen(); - syntax::Expression *subExpression(); - syntax::Leaf *closeParen(); + Leaf *openParen(); + Expression *subExpression(); + Leaf *closeParen(); }; /// Expression for literals. C++ [lex.literal] @@ -283,7 +283,7 @@ class LiteralExpression : public Expression { N->kind() == NodeKind::CharUserDefinedLiteralExpression || N->kind() == NodeKind::StringUserDefinedLiteralExpression; } - syntax::Leaf *literalToken(); + Leaf *literalToken(); }; /// Expression for integer literals. C++ [lex.icon] @@ -418,8 +418,8 @@ class UnaryOperatorExpression : public Expression { return N->kind() == NodeKind::PrefixUnaryOperatorExpression || N->kind() == NodeKind::PostfixUnaryOperatorExpression; } - syntax::Leaf *operatorToken(); - syntax::Expression *operand(); + Leaf *operatorToken(); + Expression *operand(); }; /// @@ -467,9 +467,9 @@ class BinaryOperatorExpression final : public Expression { static bool classof(const Node *N) { return N->kind() == NodeKind::BinaryOperatorExpression; } - syntax::Expression *lhs(); - syntax::Leaf *operatorToken(); - syntax::Expression *rhs(); + Expression *lhs(); + Leaf *operatorToken(); + Expression *rhs(); }; /// An abstract node for C++ statements, e.g. 'while', 'if', etc. @@ -518,8 +518,8 @@ class SwitchStatement final : public Statement { static bool classof(const Node *N) { return N->kind() == NodeKind::SwitchStatement; } - syntax::Leaf *switchKeyword(); - syntax::Statement *body(); + Leaf *switchKeyword(); + Statement *body(); }; /// case : @@ -529,9 +529,9 @@ class CaseStatement final : public Statement { static bool classof(const Node *N) { return N->kind() == NodeKind::CaseStatement; } - syntax::Leaf *caseKeyword(); - syntax::Expression *value(); - syntax::Statement *body(); + Leaf *caseKeyword(); + Expression *value(); + Statement *body(); }; /// default: @@ -541,8 +541,8 @@ class DefaultStatement final : public Statement { static bool classof(const Node *N) { return N->kind() == NodeKind::DefaultStatement; } - syntax::Leaf *defaultKeyword(); - syntax::Statement *body(); + Leaf *defaultKeyword(); + Statement *body(); }; /// if (cond) else @@ -553,10 +553,10 @@ class IfStatement final : public Statement {
[clang] 8abb5fb - [SyntaxTree] Use simplified grammar rule for `NestedNameSpecifier` grammar nodes
Author: Eduardo Caldas Date: 2020-08-07T18:05:47Z New Revision: 8abb5fb68f81b0e42d824bf080b1cef9a61559d6 URL: https://github.com/llvm/llvm-project/commit/8abb5fb68f81b0e42d824bf080b1cef9a61559d6 DIFF: https://github.com/llvm/llvm-project/commit/8abb5fb68f81b0e42d824bf080b1cef9a61559d6.diff LOG: [SyntaxTree] Use simplified grammar rule for `NestedNameSpecifier` grammar nodes This is our grammar rule for nested-name-specifiers: globalbal-specifier: /*empty*/ simple-template-specifier: template_opt simple-template-id name-specifier: global-specifier decltype-specifier identifier simple-template-specifier nested-name-specifier: list(name-specifier, ::, non-empty, terminated) It is a relaxed version of C++ [expr.prim.id] and quite simpler to map to our API. TODO: refine name specifiers, `simple-template-name-specifier` and decltype-name-specifier` are token soup for now. Added: Modified: clang/include/clang/Tooling/Syntax/Nodes.h clang/lib/Tooling/Syntax/BuildTree.cpp clang/lib/Tooling/Syntax/Nodes.cpp clang/unittests/Tooling/Syntax/TreeTest.cpp Removed: diff --git a/clang/include/clang/Tooling/Syntax/Nodes.h b/clang/include/clang/Tooling/Syntax/Nodes.h index a5972a394583..2273cb70307a 100644 --- a/clang/include/clang/Tooling/Syntax/Nodes.h +++ b/clang/include/clang/Tooling/Syntax/Nodes.h @@ -95,9 +95,13 @@ enum class NodeKind : uint16_t { TrailingReturnType, ParametersAndQualifiers, MemberPointer, + UnqualifiedId, + // Nested Name Specifiers. NestedNameSpecifier, - NameSpecifier, - UnqualifiedId + GlobalNameSpecifier, + DecltypeNameSpecifier, + IdentifierNameSpecifier, + SimpleTemplateNameSpecifier }; /// For debugging purposes. raw_ostream &operator<<(raw_ostream &OS, NodeKind K); @@ -138,6 +142,7 @@ enum class NodeRole : uint8_t { /// Tokens or Keywords ArrowToken, ExternKeyword, + TemplateKeyword, /// An inner statement for those that have only a single child of kind /// statement, e.g. loop body for while, for, etc; inner statement for case, /// default, etc. @@ -167,6 +172,7 @@ enum class NodeRole : uint8_t { IdExpression_id, IdExpression_qualifier, NestedNameSpecifier_specifier, + NestedNameSpecifier_delimiter, ParenExpression_subExpression }; /// For debugging purposes. @@ -195,12 +201,60 @@ class Expression : public Tree { }; /// A sequence of these specifiers make a `nested-name-specifier`. -/// e.g. the `std::` or `vector::` in `std::vector::size`. -class NameSpecifier final : public Tree { +/// e.g. the `std` or `vector` in `std::vector::size`. +class NameSpecifier : public Tree { public: - NameSpecifier() : Tree(NodeKind::NameSpecifier) {} + NameSpecifier(NodeKind K) : Tree(K) {} static bool classof(const Node *N) { -return N->kind() == NodeKind::NameSpecifier; +return N->kind() == NodeKind::GlobalNameSpecifier || + N->kind() == NodeKind::DecltypeNameSpecifier || + N->kind() == NodeKind::IdentifierNameSpecifier || + N->kind() == NodeKind::SimpleTemplateNameSpecifier; + } +}; + +/// The global namespace name specifier, this specifier doesn't correspond to a +/// token instead an absence of tokens before a `::` characterizes it, in +/// `::std::vector` it would be characterized by the absence of a token +/// before the first `::` +class GlobalNameSpecifier final : public NameSpecifier { +public: + GlobalNameSpecifier() : NameSpecifier(NodeKind::GlobalNameSpecifier) {} + static bool classof(const Node *N) { +return N->kind() == NodeKind::GlobalNameSpecifier; + } +}; + +/// A name specifier holding a decltype, of the form: `decltype ( expression ) ` +/// e.g. the `decltype(s)` in `decltype(s)::size`. +class DecltypeNameSpecifier final : public NameSpecifier { +public: + DecltypeNameSpecifier() : NameSpecifier(NodeKind::DecltypeNameSpecifier) {} + static bool classof(const Node *N) { +return N->kind() == NodeKind::DecltypeNameSpecifier; + } +}; + +/// A identifier name specifier, of the form `identifier` +/// e.g. the `std` in `std::vector::size`. +class IdentifierNameSpecifier final : public NameSpecifier { +public: + IdentifierNameSpecifier() + : NameSpecifier(NodeKind::IdentifierNameSpecifier) {} + static bool classof(const Node *N) { +return N->kind() == NodeKind::IdentifierNameSpecifier; + } +}; + +/// A name specifier with a simple-template-id, of the form `template_opt +/// identifier < template-args >` e.g. the `vector` in +/// `std::vector::size`. +class SimpleTemplateNameSpecifier final : public NameSpecifier { +public: + SimpleTemplateNameSpecifier() + : NameSpecifier(NodeKind::SimpleTemplateNameSpecifier) {} + static bool classof(const Node *N) { +return N->kind() == NodeKind::SimpleTemplateNameSpecifier; } }; @@ -213,6 +267,7 @@ class NestedNameSpecifier final : public Tree { return N->kind() <= Node
[clang] a90c78a - [SyntaxTree] Implement the List construct.
Author: Eduardo Caldas Date: 2020-08-10T10:32:28Z New Revision: a90c78ac52615d256142ecd64fbedabb612dc73f URL: https://github.com/llvm/llvm-project/commit/a90c78ac52615d256142ecd64fbedabb612dc73f DIFF: https://github.com/llvm/llvm-project/commit/a90c78ac52615d256142ecd64fbedabb612dc73f.diff LOG: [SyntaxTree] Implement the List construct. We defined a List construct to help with the implementation of list-like grammar rules. This is a first implementation of this API. Differential Revision: https://reviews.llvm.org/D85295 Added: Modified: clang/include/clang/Tooling/Syntax/Nodes.h clang/include/clang/Tooling/Syntax/Tree.h clang/lib/Tooling/Syntax/Nodes.cpp clang/lib/Tooling/Syntax/Tree.cpp Removed: diff --git a/clang/include/clang/Tooling/Syntax/Nodes.h b/clang/include/clang/Tooling/Syntax/Nodes.h index 2273cb70307a..fc44076621d6 100644 --- a/clang/include/clang/Tooling/Syntax/Nodes.h +++ b/clang/include/clang/Tooling/Syntax/Nodes.h @@ -147,6 +147,8 @@ enum class NodeRole : uint8_t { /// statement, e.g. loop body for while, for, etc; inner statement for case, /// default, etc. BodyStatement, + List_element, + List_delimiter, // Roles specific to particular node kinds. OperatorExpression_operatorToken, diff --git a/clang/include/clang/Tooling/Syntax/Tree.h b/clang/include/clang/Tooling/Syntax/Tree.h index d35bc6467bcc..fcd169cad3ec 100644 --- a/clang/include/clang/Tooling/Syntax/Tree.h +++ b/clang/include/clang/Tooling/Syntax/Tree.h @@ -191,6 +191,59 @@ class Tree : public Node { Node *FirstChild = nullptr; }; +/// A list of Elements separated or terminated by a fixed token. +/// +/// This type models the following grammar construct: +/// delimited-list(element, delimiter, termination, canBeEmpty) +class List : public Tree { +public: + template struct ElementAndDelimiter { +Element *element; +Leaf *delimiter; + }; + + enum class TerminationKind { +Terminated, +MaybeTerminated, +Separated, + }; + + using Tree::Tree; + /// Returns the elements and corresponding delimiters. Missing elements + /// and delimiters are represented as null pointers. + /// + /// For example, in a separated list: + /// "a, b, c" <=> [("a", ","), ("b", ","), ("c", null)] + /// "a, , c" <=> [("a", ","), (null, ","), ("c", ",)] + /// "a, b," <=> [("a", ","), ("b", ","), (null, null)] + /// + /// In a terminated or maybe-terminated list: + /// "a, b," <=> [("a", ","), ("b", ",")] + std::vector> getElementsAsNodesAndDelimiters(); + + /// Returns the elements of the list. Missing elements are represented + /// as null pointers in the same way as in the return value of + /// `getElementsAsNodesAndDelimiters()`. + std::vector getElementsAsNodes(); + + // These can't be implemented with the information we have! + + /// Returns the appropriate delimiter for this list. + /// + /// Useful for discovering the correct delimiter to use when adding + /// elements to empty or one-element lists. + clang::tok::TokenKind getDelimiterTokenKind(); + + TerminationKind getTerminationKind(); + + /// Whether this list can be empty in syntactically and semantically correct + /// code. + /// + /// This list may be empty when the source code has errors even if + /// canBeEmpty() returns false. + bool canBeEmpty(); +}; + } // namespace syntax } // namespace clang diff --git a/clang/lib/Tooling/Syntax/Nodes.cpp b/clang/lib/Tooling/Syntax/Nodes.cpp index b5a4c50b2875..5e8deb668352 100644 --- a/clang/lib/Tooling/Syntax/Nodes.cpp +++ b/clang/lib/Tooling/Syntax/Nodes.cpp @@ -152,6 +152,10 @@ raw_ostream &syntax::operator<<(raw_ostream &OS, NodeRole R) { return OS << "TemplateKeyword"; case syntax::NodeRole::BodyStatement: return OS << "BodyStatement"; + case syntax::NodeRole::List_element: +return OS << "List_element"; + case syntax::NodeRole::List_delimiter: +return OS << "List_delimiter"; case syntax::NodeRole::CaseStatement_value: return OS << "CaseStatement_value"; case syntax::NodeRole::IfStatement_thenStatement: diff --git a/clang/lib/Tooling/Syntax/Tree.cpp b/clang/lib/Tooling/Syntax/Tree.cpp index 6f9ee40a89f2..6070d1603eb8 100644 --- a/clang/lib/Tooling/Syntax/Tree.cpp +++ b/clang/lib/Tooling/Syntax/Tree.cpp @@ -268,3 +268,110 @@ syntax::Node *syntax::Tree::findChild(NodeRole R) { } return nullptr; } + +std::vector> +syntax::List::getElementsAsNodesAndDelimiters() { + if (!firstChild()) +return {}; + + auto children = std::vector>(); + syntax::Node *elementWithoutDelimiter = nullptr; + for (auto *C = firstChild(); C; C = C->nextSibling()) { +switch (C->role()) { +case syntax::NodeRole::List_element: { + if (elementWithoutDelimiter) { +children.push_back({elementWithoutDelimiter, nullptr}); + } + elementWithoutDelimiter = C; + break; +} +case syntax::NodeRol
[clang] fdbd599 - [SyntaxTree] Implement `NestedNameSpecifier` using the `List` base API
Author: Eduardo Caldas Date: 2020-08-10T13:43:21Z New Revision: fdbd5996533dad25f00687f27ce8e7a8b7573ba3 URL: https://github.com/llvm/llvm-project/commit/fdbd5996533dad25f00687f27ce8e7a8b7573ba3 DIFF: https://github.com/llvm/llvm-project/commit/fdbd5996533dad25f00687f27ce8e7a8b7573ba3.diff LOG: [SyntaxTree] Implement `NestedNameSpecifier` using the `List` base API Added: Modified: clang/include/clang/Tooling/Syntax/Nodes.h clang/lib/Tooling/Syntax/BuildTree.cpp clang/lib/Tooling/Syntax/Nodes.cpp clang/lib/Tooling/Syntax/Tree.cpp Removed: diff --git a/clang/include/clang/Tooling/Syntax/Nodes.h b/clang/include/clang/Tooling/Syntax/Nodes.h index fc44076621d6..8e65fa1d8923 100644 --- a/clang/include/clang/Tooling/Syntax/Nodes.h +++ b/clang/include/clang/Tooling/Syntax/Nodes.h @@ -173,8 +173,6 @@ enum class NodeRole : uint8_t { ParametersAndQualifiers_trailingReturn, IdExpression_id, IdExpression_qualifier, - NestedNameSpecifier_specifier, - NestedNameSpecifier_delimiter, ParenExpression_subExpression }; /// For debugging purposes. @@ -262,14 +260,15 @@ class SimpleTemplateNameSpecifier final : public NameSpecifier { /// Models a `nested-name-specifier`. C++ [expr.prim.id.qual] /// e.g. the `std::vector::` in `std::vector::size`. -class NestedNameSpecifier final : public Tree { +class NestedNameSpecifier final : public List { public: - NestedNameSpecifier() : Tree(NodeKind::NestedNameSpecifier) {} + NestedNameSpecifier() : List(NodeKind::NestedNameSpecifier) {} static bool classof(const Node *N) { return N->kind() <= NodeKind::NestedNameSpecifier; } std::vector specifiers(); - std::vector delimiters(); + std::vector> + specifiersAndDoubleColons(); }; /// Models an `unqualified-id`. C++ [expr.prim.id.unqual] diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp index 4e76b3825b6f..76b86ac6424d 100644 --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -809,9 +809,8 @@ class BuildTreeVisitor : public RecursiveASTVisitor { if (!isa(NS)) Builder.foldNode(Builder.getRange(getLocalSourceRange(it)).drop_back(), NS, it); - Builder.markChild(NS, syntax::NodeRole::NestedNameSpecifier_specifier); - Builder.markChildToken(it.getEndLoc(), - syntax::NodeRole::NestedNameSpecifier_delimiter); + Builder.markChild(NS, syntax::NodeRole::List_element); + Builder.markChildToken(it.getEndLoc(), syntax::NodeRole::List_delimiter); } auto *NNS = new (allocator()) syntax::NestedNameSpecifier; Builder.foldNode(Builder.getRange(QualifierLoc.getSourceRange()), NNS, diff --git a/clang/lib/Tooling/Syntax/Nodes.cpp b/clang/lib/Tooling/Syntax/Nodes.cpp index 5e8deb668352..bf3c3108cb69 100644 --- a/clang/lib/Tooling/Syntax/Nodes.cpp +++ b/clang/lib/Tooling/Syntax/Nodes.cpp @@ -200,30 +200,32 @@ raw_ostream &syntax::operator<<(raw_ostream &OS, NodeRole R) { return OS << "IdExpression_id"; case syntax::NodeRole::IdExpression_qualifier: return OS << "IdExpression_qualifier"; - case syntax::NodeRole::NestedNameSpecifier_specifier: -return OS << "NestedNameSpecifier_specifier"; - case syntax::NodeRole::NestedNameSpecifier_delimiter: -return OS << "NestedNameSpecifier_delimiter"; case syntax::NodeRole::ParenExpression_subExpression: return OS << "ParenExpression_subExpression"; } llvm_unreachable("invalid role"); } -std::vector syntax::NestedNameSpecifier::delimiters() { - std::vector Children; - for (auto *C = firstChild(); C; C = C->nextSibling()) { -assert(C->role() == syntax::NodeRole::NestedNameSpecifier_delimiter); -Children.push_back(llvm::cast(C)); +// We could have an interator in list to not pay memory costs of temporary +// vector +std::vector syntax::NestedNameSpecifier::specifiers() { + auto specifiersAsNodes = getElementsAsNodes(); + std::vector Children; + for (const auto &element : specifiersAsNodes) { +Children.push_back(llvm::cast(element)); } return Children; } -std::vector syntax::NestedNameSpecifier::specifiers() { - std::vector Children; - for (auto *C = firstChild(); C; C = C->nextSibling()) { -assert(C->role() == syntax::NodeRole::NestedNameSpecifier_specifier); -Children.push_back(cast(C)); +std::vector> +syntax::NestedNameSpecifier::specifiersAndDoubleColons() { + auto specifiersAsNodesAndDoubleColons = getElementsAsNodesAndDelimiters(); + std::vector> + Children; + for (const auto &specifierAndDoubleColon : specifiersAsNodesAndDoubleColons) { +Children.push_back( +{llvm::cast(specifierAndDoubleColon.element), + specifierAndDoubleColon.delimiter}); } return Children; } diff --git a/clang/lib/Tooling/Syntax/Tree.cpp b/clang/lib/Tooling/Syntax/Tree.cpp index
[clang] f9500cc - [SyntaxTree] Expand support for `NestedNameSpecifier`
Author: Eduardo Caldas Date: 2020-08-10T15:47:20Z New Revision: f9500cc487573c55ea37b4ee6e9162d115753a48 URL: https://github.com/llvm/llvm-project/commit/f9500cc487573c55ea37b4ee6e9162d115753a48 DIFF: https://github.com/llvm/llvm-project/commit/f9500cc487573c55ea37b4ee6e9162d115753a48.diff LOG: [SyntaxTree] Expand support for `NestedNameSpecifier` Summary: We want NestedNameSpecifier syntax nodes to be generally supported, not only for `DeclRefExpr` and `DependentScopedDeclRefExpr`. To achieve this we: * Use the `RecursiveASTVisitor`'s API to traverse `NestedNameSpecifierLoc`s and automatically create its syntax nodes * Add links from the `NestedNameSpecifierLoc`s to their syntax nodes. In this way, from any semantic construct that has a `NestedNameSpecifier`, we implicitly generate its syntax node via RAV and we can easily access this syntax node via the links we added. Added: Modified: clang/include/clang/AST/NestedNameSpecifier.h clang/lib/Tooling/Syntax/BuildTree.cpp clang/unittests/Tooling/Syntax/TreeTest.cpp Removed: diff --git a/clang/include/clang/AST/NestedNameSpecifier.h b/clang/include/clang/AST/NestedNameSpecifier.h index 540ac3df48fe..b11cb5f6b86d 100644 --- a/clang/include/clang/AST/NestedNameSpecifier.h +++ b/clang/include/clang/AST/NestedNameSpecifier.h @@ -17,6 +17,7 @@ #include "clang/AST/DependenceFlags.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/Support/Compiler.h" @@ -527,4 +528,33 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, } // namespace clang +namespace llvm { + +template <> struct DenseMapInfo { + using FirstInfo = DenseMapInfo; + using SecondInfo = DenseMapInfo; + + static clang::NestedNameSpecifierLoc getEmptyKey() { +return clang::NestedNameSpecifierLoc(FirstInfo::getEmptyKey(), + SecondInfo::getEmptyKey()); + } + + static clang::NestedNameSpecifierLoc getTombstoneKey() { +return clang::NestedNameSpecifierLoc(FirstInfo::getTombstoneKey(), + SecondInfo::getTombstoneKey()); + } + + static unsigned getHashValue(const clang::NestedNameSpecifierLoc &PairVal) { +return hash_combine( +FirstInfo::getHashValue(PairVal.getNestedNameSpecifier()), +SecondInfo::getHashValue(PairVal.getOpaqueData())); + } + + static bool isEqual(const clang::NestedNameSpecifierLoc &LHS, + const clang::NestedNameSpecifierLoc &RHS) { +return LHS == RHS; + } +}; +} // namespace llvm + #endif // LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp index 76b86ac6424d..90451539b3b4 100644 --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -241,10 +241,24 @@ class ASTToSyntaxMapping { assert(Added && "mapping added twice"); } + void add(NestedNameSpecifierLoc From, syntax::Tree *To) { +assert(To != nullptr); +assert(From.hasQualifier()); + +bool Added = NNSNodes.insert({From, To}).second; +(void)Added; +assert(Added && "mapping added twice"); + } + syntax::Tree *find(ASTPtr P) const { return Nodes.lookup(P); } + syntax::Tree *find(NestedNameSpecifierLoc P) const { +return NNSNodes.lookup(P); + } + private: llvm::DenseMap Nodes; + llvm::DenseMap NNSNodes; }; } // namespace @@ -281,16 +295,20 @@ class syntax::TreeBuilder { if (From) Mapping.add(From, New); } + void foldNode(ArrayRef Range, syntax::Tree *New, TypeLoc L) { // FIXME: add mapping for TypeLocs foldNode(Range, New, nullptr); } - void foldNode(ArrayRef Range, syntax::Tree *New, -NestedNameSpecifierLoc L) { -// FIXME: add mapping for NestedNameSpecifierLoc -foldNode(Range, New, nullptr); + void foldNode(llvm::ArrayRef Range, syntax::Tree *New, +NestedNameSpecifierLoc From) { +assert(New); +Pending.foldChildren(Arena, Range, New); +if (From) + Mapping.add(From, New); } + /// Notifies that we should not consume trailing semicolon when computing /// token range of \p D. void noticeDeclWithoutSemicolon(Decl *D); @@ -312,6 +330,8 @@ class syntax::TreeBuilder { void markChild(syntax::Node *N, NodeRole R); /// Set role for the syntax node matching \p N. void markChild(ASTPtr N, NodeRole R); + /// Set role for the syntax node matching \p N. + void markChild(NestedNameSpecifierLoc N, NodeRole R); /// Finish building the tree and consume the root node. syntax::TranslationUnit *finalize() && { @@ -744,45 +764,18 @@ class BuildTreeVisitor : public RecursiveASTVisitor { return true; } - syntax::NameSpecifier *Buil
[clang] ac37afa - [SyntaxTree] Unbox operators into tokens for nodes generated from `CXXOperatorCallExpr`
Author: Eduardo Caldas Date: 2020-08-12T08:01:18Z New Revision: ac37afa650271d8366b706d79ff8e217fc624cbb URL: https://github.com/llvm/llvm-project/commit/ac37afa650271d8366b706d79ff8e217fc624cbb DIFF: https://github.com/llvm/llvm-project/commit/ac37afa650271d8366b706d79ff8e217fc624cbb.diff LOG: [SyntaxTree] Unbox operators into tokens for nodes generated from `CXXOperatorCallExpr` For an user define `<`, `x < y` would yield the syntax tree: ``` BinaryOperatorExpression |-IdExpression | `-UnqualifiedId | `-x |-IdExpression | `-UnqualifiedId | `-< `-IdExpression `-UnqualifiedId `-y ``` But there is no syntatic difference at call site between call site or built-in `<`. As such they should generate the same syntax tree, namely: ``` BinaryOperatorExpression |-IdExpression | `-UnqualifiedId | `-x |-< `-IdExpression `-UnqualifiedId `-y ``` Differential Revision: https://reviews.llvm.org/D85750 Added: Modified: clang/lib/Tooling/Syntax/BuildTree.cpp clang/unittests/Tooling/Syntax/TreeTest.cpp Removed: diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp index 90451539b3b4..11d399730040 100644 --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -1007,23 +1007,26 @@ class BuildTreeVisitor : public RecursiveASTVisitor { } bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *S) { -if (getOperatorNodeKind(*S) == -syntax::NodeKind::PostfixUnaryOperatorExpression) { +// To construct a syntax tree of the same shape for calls to built-in and +// user-defined operators, ignore the `DeclRefExpr` that refers to the +// operator and treat it as a simple token. Do that by traversing +// arguments instead of children. +for (auto *child : S->arguments()) { // A postfix unary operator is declared as taking two operands. The // second operand is used to distinguish from its prefix counterpart. In // the semantic AST this "phantom" operand is represented as a // `IntegerLiteral` with invalid `SourceLocation`. We skip visiting this // operand because it does not correspond to anything written in source - // code - for (auto *child : S->children()) { -if (child->getSourceRange().isInvalid()) - continue; -if (!TraverseStmt(child)) - return false; + // code. + if (child->getSourceRange().isInvalid()) { +assert(getOperatorNodeKind(*S) == + syntax::NodeKind::PostfixUnaryOperatorExpression); +continue; } - return WalkUpFromCXXOperatorCallExpr(S); -} else - return RecursiveASTVisitor::TraverseCXXOperatorCallExpr(S); + if (!TraverseStmt(child)) +return false; +} +return WalkUpFromCXXOperatorCallExpr(S); } bool WalkUpFromCXXOperatorCallExpr(CXXOperatorCallExpr *S) { diff --git a/clang/unittests/Tooling/Syntax/TreeTest.cpp b/clang/unittests/Tooling/Syntax/TreeTest.cpp index 46101660df8e..a5d1a4bfcacf 100644 --- a/clang/unittests/Tooling/Syntax/TreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/TreeTest.cpp @@ -2592,9 +2592,7 @@ void test(X x, X y, X* xp, int X::* pmi) { | | |-IdExpression | | | `-UnqualifiedId | | | `-x -| | |-IdExpression -| | | `-UnqualifiedId -| | | `-= +| | |-= | | `-IdExpression | | `-UnqualifiedId | | `-y @@ -2605,9 +2603,7 @@ void test(X x, X y, X* xp, int X::* pmi) { | | | `-IdExpression | | | `-UnqualifiedId | | | `-x -| | |-IdExpression -| | | `-UnqualifiedId -| | | `-+ +| | |-+ | | `-IdExpression | | `-UnqualifiedId | | `-y @@ -2617,9 +2613,7 @@ void test(X x, X y, X* xp, int X::* pmi) { | | |-IdExpression | | | `-UnqualifiedId | | | `-x -| | |-IdExpression -| | | `-UnqualifiedId -| | | `-< +| | |-< | | `-IdExpression | | `-UnqualifiedId | | `-y @@ -2629,9 +2623,7 @@ void test(X x, X y, X* xp, int X::* pmi) { | | |-IdExpression | | | `-UnqualifiedId | | | `-x -| | |-IdExpression -| | | `-UnqualifiedId -| | | `-<< +| | |-<< | | `-IdExpression | | `-UnqualifiedId | | `-y @@ -2641,9 +2633,7 @@ void test(X x, X y, X* xp, int X::* pmi) { | | |-IdExpression | | | `-UnqualifiedId | | | `-x -| | |-IdExpression -| | | `-UnqualifiedId -| | | `-, +| | |-, | | `-IdExpression | | `-UnqualifiedId | | `-y @@ -2730,27 +2720,21 @@ void test(X x) { |-{ |-ExpressionStatement | |-PrefixUnaryOperatorExpression -| | |-IdExpression -| | | `-UnqualifiedId -| | | `-++ +| | |-++ | | `-IdExpression | | `-UnqualifiedId | | `-x | `-; |-ExpressionStatement | |-PrefixUnaryOperato
[clang] d1211fd - [SyntaxTree] Split tests for expressions
Author: Eduardo Caldas Date: 2020-08-13T08:18:14Z New Revision: d1211fd1ec037f88c2cc855bc850200948c76940 URL: https://github.com/llvm/llvm-project/commit/d1211fd1ec037f88c2cc855bc850200948c76940 DIFF: https://github.com/llvm/llvm-project/commit/d1211fd1ec037f88c2cc855bc850200948c76940.diff LOG: [SyntaxTree] Split tests for expressions We do that because: * Big tests generated big tree dumps that could hardly serve as documentation. * In most cases the tests didn't share setup, thus there was not much addition in lines of code. We split tests for: * `UserDefinedLiteral` * `NestedBinaryOperator` * `UserDefinedBinaryOperator` * `UserDefinedPrefixOperator` * `QualifiedId` Differential Revision: https://reviews.llvm.org/D85819 Added: Modified: clang/unittests/Tooling/Syntax/TreeTest.cpp Removed: diff --git a/clang/unittests/Tooling/Syntax/TreeTest.cpp b/clang/unittests/Tooling/Syntax/TreeTest.cpp index a5d1a4bfcacf..834496ce0082 100644 --- a/clang/unittests/Tooling/Syntax/TreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/TreeTest.cpp @@ -632,26 +632,48 @@ void test() { )txt")); } -TEST_P(SyntaxTreeTest, UnqualifiedId) { +TEST_P(SyntaxTreeTest, UnqualifiedIdIdentifier) { + EXPECT_TRUE(treeDumpEqual( + R"cpp( +void test(int a) { + a; +} +)cpp", + R"txt( +*: TranslationUnit +`-SimpleDeclaration + |-void + |-SimpleDeclarator + | |-test + | `-ParametersAndQualifiers + | |-( + | |-SimpleDeclaration + | | |-int + | | `-SimpleDeclarator + | | `-a + | `-) + `-CompoundStatement +|-{ +|-ExpressionStatement +| |-IdExpression +| | `-UnqualifiedId +| | `-a +| `-; +`-} +)txt")); +} + +TEST_P(SyntaxTreeTest, UnqualifiedIdOperatorFunctionId) { if (!GetParam().isCXX()) { return; } EXPECT_TRUE(treeDumpEqual( R"cpp( struct X { - // TODO: Expose `id-expression` from `Declarator` friend X operator+(const X&, const X&); - operator int(); }; -template -void f(T&); void test(X x) { - x; // identifier - operator+(x, x);// operator-function-id - f(x);// template-id - // TODO: Expose `id-expression` from `MemberExpr` - x.operator int(); // conversion-funtion-id - x.~X(); // ~type-name + operator+(x, x); } )cpp", R"txt( @@ -682,35 +704,8 @@ void test(X x) { | | | | `-& | | | `-) | | `-; -| |-SimpleDeclaration -| | |-SimpleDeclarator -| | | |-operator -| | | |-int -| | | `-ParametersAndQualifiers -| | | |-( -| | | `-) -| | `-; | |-} | `-; -|-TemplateDeclaration -| |-template -| |-< -| |-UnknownDeclaration -| | |-typename -| | `-T -| |-> -| `-SimpleDeclaration -| |-void -| |-SimpleDeclarator -| | |-f -| | `-ParametersAndQualifiers -| | |-( -| | |-SimpleDeclaration -| | | |-T -| | | `-SimpleDeclarator -| | | `-& -| | `-) -| `-; `-SimpleDeclaration |-void |-SimpleDeclarator @@ -725,11 +720,6 @@ void test(X x) { `-CompoundStatement |-{ |-ExpressionStatement -| |-IdExpression -| | `-UnqualifiedId -| | `-x -| `-; -|-ExpressionStatement | |-UnknownExpression | | |-IdExpression | | | `-UnqualifiedId @@ -745,20 +735,53 @@ void test(X x) { | | | `-x | | `-) | `-; -|-ExpressionStatement -| |-UnknownExpression -| | |-IdExpression -| | | `-UnqualifiedId -| | | |-f -| | | |-< -| | | |-X -| | | `-> -| | |-( -| | |-IdExpression -| | | `-UnqualifiedId -| | | `-x -| | `-) -| `-; +`-} +)txt")); +} + +TEST_P(SyntaxTreeTest, UnqualifiedIdConversionFunctionId) { + if (!GetParam().isCXX()) { +return; + } + EXPECT_TRUE(treeDumpEqual( + R"cpp( +struct X { + operator int(); +}; +void test(X x) { + // TODO: Expose `id-expression` from `MemberExpr` + x.operator int(); +} +)cpp", + R"txt( +*: TranslationUnit +|-SimpleDeclaration +| |-struct +| |-X +| |-{ +| |-SimpleDeclaration +| | |-SimpleDeclarator +| | | |-operator +| | | |-int +| | | `-ParametersAndQualifiers +| | | |-( +| | | `-) +| | `-; +| |-} +| `-; +`-SimpleDeclaration + |-void + |-SimpleDeclarator + | |-test + | `-ParametersAndQualifiers + | |-( + | |-SimpleDeclaration + | | |-X + | | `-SimpleDeclarator + | | `-x + | `-) + `-CompoundStatement +|-{ |-ExpressionStatement | |-UnknownExpression | | |-UnknownExpression @@ -771,6 +794,93 @@ void test(X x) { | | |-( | | `-) | `-; +`-} +)txt")); +} + +TEST_P(SyntaxTreeTest, UnqualifiedIdLiteralOperatorId) { + if (!GetParam().isCXX11OrLater()) { +return; + } + EXPECT_TRUE(treeDumpEqual( + R"cpp( +unsigned operator "" _w(char); +void test() { + operator "" _w('1'); +} +)cpp", + R"txt( +*: TranslationUnit +|-SimpleDeclaration +| |-unsigned +| |-SimpleDeclarator +| | |-operator +
[clang] 833c2b6 - [SyntaxTree] Rename tests following `TestSuite_TestCase` + nits
Author: Eduardo Caldas Date: 2020-08-13T08:18:14Z New Revision: 833c2b6be26bcdf90aac2f6de6e345bcd858149e URL: https://github.com/llvm/llvm-project/commit/833c2b6be26bcdf90aac2f6de6e345bcd858149e DIFF: https://github.com/llvm/llvm-project/commit/833c2b6be26bcdf90aac2f6de6e345bcd858149e.diff LOG: [SyntaxTree] Rename tests following `TestSuite_TestCase` + nits Added: Modified: clang/unittests/Tooling/Syntax/TreeTest.cpp Removed: diff --git a/clang/unittests/Tooling/Syntax/TreeTest.cpp b/clang/unittests/Tooling/Syntax/TreeTest.cpp index 834496ce0082..e266ef3f5870 100644 --- a/clang/unittests/Tooling/Syntax/TreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/TreeTest.cpp @@ -632,7 +632,7 @@ void test() { )txt")); } -TEST_P(SyntaxTreeTest, UnqualifiedIdIdentifier) { +TEST_P(SyntaxTreeTest, UnqualifiedId_Identifier) { EXPECT_TRUE(treeDumpEqual( R"cpp( void test(int a) { @@ -663,7 +663,7 @@ void test(int a) { )txt")); } -TEST_P(SyntaxTreeTest, UnqualifiedIdOperatorFunctionId) { +TEST_P(SyntaxTreeTest, UnqualifiedId_OperatorFunctionId) { if (!GetParam().isCXX()) { return; } @@ -739,7 +739,7 @@ void test(X x) { )txt")); } -TEST_P(SyntaxTreeTest, UnqualifiedIdConversionFunctionId) { +TEST_P(SyntaxTreeTest, UnqualifiedId_ConversionFunctionId) { if (!GetParam().isCXX()) { return; } @@ -798,7 +798,7 @@ void test(X x) { )txt")); } -TEST_P(SyntaxTreeTest, UnqualifiedIdLiteralOperatorId) { +TEST_P(SyntaxTreeTest, UnqualifiedId_LiteralOperatorId) { if (!GetParam().isCXX11OrLater()) { return; } @@ -848,7 +848,7 @@ void test() { )txt")); } -TEST_P(SyntaxTreeTest, UnqualifiedIdDestructor) { +TEST_P(SyntaxTreeTest, UnqualifiedId_Destructor) { if (!GetParam().isCXX()) { return; } @@ -897,7 +897,7 @@ void test(X x) { )txt")); } -TEST_P(SyntaxTreeTest, UnqualifiedIdDecltypeDestructor) { +TEST_P(SyntaxTreeTest, UnqualifiedId_DecltypeDestructor) { if (!GetParam().isCXX11OrLater()) { return; } @@ -949,7 +949,7 @@ void test(X x) { )txt")); } -TEST_P(SyntaxTreeTest, UnqualifiedIdTemplateId) { +TEST_P(SyntaxTreeTest, UnqualifiedId_TemplateId) { if (!GetParam().isCXX()) { return; } @@ -1002,7 +1002,7 @@ void test() { )txt")); } -TEST_P(SyntaxTreeTest, QualifiedIdWithNamespace) { +TEST_P(SyntaxTreeTest, QualifiedId_NamespaceSpecifier) { if (!GetParam().isCXX()) { return; } @@ -1065,7 +1065,7 @@ void test() { )txt")); } -TEST_P(SyntaxTreeTest, QualifiedIdWithTemplateSpecifier) { +TEST_P(SyntaxTreeTest, QualifiedId_TemplateSpecifier) { if (!GetParam().isCXX()) { return; } @@ -1145,7 +1145,73 @@ void test() { )txt")); } -TEST_P(SyntaxTreeTest, QualifiedIdWithOptionalTemplateKw) { +TEST_P(SyntaxTreeTest, QualifiedId_DecltypeSpecifier) { + if (!GetParam().isCXX11OrLater()) { +return; + } + EXPECT_TRUE(treeDumpEqual( + R"cpp( +struct S { + static void f(){} +}; +void test(S s) { + decltype(s)::f(); +} +)cpp", + R"txt( +*: TranslationUnit +|-SimpleDeclaration +| |-struct +| |-S +| |-{ +| |-SimpleDeclaration +| | |-static +| | |-void +| | |-SimpleDeclarator +| | | |-f +| | | `-ParametersAndQualifiers +| | | |-( +| | | `-) +| | `-CompoundStatement +| | |-{ +| | `-} +| |-} +| `-; +`-SimpleDeclaration + |-void + |-SimpleDeclarator + | |-test + | `-ParametersAndQualifiers + | |-( + | |-SimpleDeclaration + | | |-S + | | `-SimpleDeclarator + | | `-s + | `-) + `-CompoundStatement +|-{ +|-ExpressionStatement +| |-UnknownExpression +| | |-IdExpression +| | | |-NestedNameSpecifier +| | | | |-DecltypeNameSpecifier +| | | | | |-decltype +| | | | | |-( +| | | | | |-IdExpression +| | | | | | `-UnqualifiedId +| | | | | | `-s +| | | | | `-) +| | | | `-:: +| | | `-UnqualifiedId +| | | `-f +| | |-( +| | `-) +| `-; +`-} +)txt")); +} + +TEST_P(SyntaxTreeTest, QualifiedId_OptionalTemplateKw) { if (!GetParam().isCXX()) { return; } @@ -1228,18 +1294,18 @@ void test() { )txt")); } -TEST_P(SyntaxTreeTest, QualifiedIdComplex) { +TEST_P(SyntaxTreeTest, QualifiedId_Complex) { if (!GetParam().isCXX()) { return; } EXPECT_TRUE(treeDumpEqual( R"cpp( namespace n { -template -struct ST { - template - static U f(); -}; + template + struct ST { +template +static U f(); + }; } void test() { ::n::template ST::template f(); @@ -1318,7 +1384,7 @@ void test() { )txt")); } -TEST_P(SyntaxTreeTest, QualifiedIdWithDependentType) { +TEST_P(SyntaxTreeTest, QualifiedId_DependentType) { if (!GetParam().isCXX()) { return; } @@ -1409,72 +1475,6 @@ void test() { )txt")); } -TEST_P(SyntaxTreeTest, QualifiedIdDecltype) { - if (!GetParam().isCXX11OrLater()) { -return; - } - EXPECT_TRUE(treeDumpEqual( - R"cpp( -struct S { -
[clang] d17437d - [SyntaxTree] Split `TreeTest.cpp`
Author: Eduardo Caldas Date: 2020-08-13T13:30:57Z New Revision: d17437d2bd8e83baee96f2860276d615d216dfbc URL: https://github.com/llvm/llvm-project/commit/d17437d2bd8e83baee96f2860276d615d216dfbc DIFF: https://github.com/llvm/llvm-project/commit/d17437d2bd8e83baee96f2860276d615d216dfbc.diff LOG: [SyntaxTree] Split `TreeTest.cpp` We extract the test infrastructure into `TreeTestBase.h` and split the tests into `MutationsTest.cpp` and `BuildTreeTest.cpp` Added: clang/unittests/Tooling/Syntax/BuildTreeTest.cpp clang/unittests/Tooling/Syntax/MutationsTest.cpp clang/unittests/Tooling/Syntax/TreeTestBase.h Modified: clang/unittests/Tooling/Syntax/CMakeLists.txt Removed: clang/unittests/Tooling/Syntax/TreeTest.cpp diff --git a/clang/unittests/Tooling/Syntax/TreeTest.cpp b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp similarity index 88% rename from clang/unittests/Tooling/Syntax/TreeTest.cpp rename to clang/unittests/Tooling/Syntax/BuildTreeTest.cpp index e266ef3f5870..deffd48da085 100644 --- a/clang/unittests/Tooling/Syntax/TreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp @@ -1,217 +1,20 @@ -//===- TreeTest.cpp ---===// +//===- BuildTreeTest.cpp --===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===--===// +// +// This file tests the syntax tree generation from the ClangAST. +// +//===--===// -#include "clang/Tooling/Syntax/Tree.h" -#include "clang/AST/ASTConsumer.h" -#include "clang/AST/Decl.h" -#include "clang/AST/Stmt.h" -#include "clang/Basic/LLVM.h" -#include "clang/Basic/TokenKinds.h" -#include "clang/Frontend/CompilerInstance.h" -#include "clang/Frontend/CompilerInvocation.h" -#include "clang/Frontend/FrontendAction.h" -#include "clang/Frontend/TextDiagnosticPrinter.h" -#include "clang/Lex/PreprocessorOptions.h" -#include "clang/Testing/CommandLineArgs.h" -#include "clang/Testing/TestClangConfig.h" -#include "clang/Tooling/Core/Replacement.h" -#include "clang/Tooling/Syntax/BuildTree.h" -#include "clang/Tooling/Syntax/Mutations.h" -#include "clang/Tooling/Syntax/Nodes.h" -#include "clang/Tooling/Syntax/Tokens.h" -#include "clang/Tooling/Tooling.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/Error.h" -#include "llvm/Testing/Support/Annotations.h" -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include -#include - -using namespace clang; +#include "TreeTestBase.h" +namespace clang { +namespace syntax { namespace { -static ArrayRef tokens(syntax::Node *N) { - assert(N->isOriginal() && "tokens of modified nodes are not well-defined"); - if (auto *L = dyn_cast(N)) -return llvm::makeArrayRef(L->token(), 1); - auto *T = cast(N); - return llvm::makeArrayRef(T->firstLeaf()->token(), -T->lastLeaf()->token() + 1); -} - -class SyntaxTreeTest : public ::testing::Test, - public ::testing::WithParamInterface { -protected: - // Build a syntax tree for the code. - syntax::TranslationUnit *buildTree(StringRef Code, - const TestClangConfig &ClangConfig) { -// FIXME: this code is almost the identical to the one in TokensTest. Share -//it. -class BuildSyntaxTree : public ASTConsumer { -public: - BuildSyntaxTree(syntax::TranslationUnit *&Root, - std::unique_ptr &TB, - std::unique_ptr &Arena, - std::unique_ptr Tokens) - : Root(Root), TB(TB), Arena(Arena), Tokens(std::move(Tokens)) { -assert(this->Tokens); - } - - void HandleTranslationUnit(ASTContext &Ctx) override { -TB = - std::make_unique(std::move(*Tokens).consume()); -Tokens = nullptr; // make sure we fail if this gets called twice. -Arena = std::make_unique(Ctx.getSourceManager(), -Ctx.getLangOpts(), *TB); -Root = syntax::buildSyntaxTree(*Arena, *Ctx.getTranslationUnitDecl()); - } - -private: - syntax::TranslationUnit *&Root; - std::unique_ptr &TB; - std::unique_ptr &Arena; - std::unique_ptr Tokens; -}; - -class BuildSyntaxTreeAction : public ASTFrontendAction { -public: - BuildSyntaxTreeAction(syntax::TranslationUnit *&Root, -std::unique_ptr &TB, -std::unique_ptr &Arena)
[clang] 9c2e708 - [SyntaxTree] Clean `#includes` in `TreeTestBase.h`
Author: Eduardo Caldas Date: 2020-08-13T13:30:57Z New Revision: 9c2e708f0dc547d386ea528450a33ef4bd2a750b URL: https://github.com/llvm/llvm-project/commit/9c2e708f0dc547d386ea528450a33ef4bd2a750b DIFF: https://github.com/llvm/llvm-project/commit/9c2e708f0dc547d386ea528450a33ef4bd2a750b.diff LOG: [SyntaxTree] Clean `#includes` in `TreeTestBase.h` Differential Revision: https://reviews.llvm.org/D85898 Added: Modified: clang/unittests/Tooling/Syntax/MutationsTest.cpp clang/unittests/Tooling/Syntax/TreeTestBase.h Removed: diff --git a/clang/unittests/Tooling/Syntax/MutationsTest.cpp b/clang/unittests/Tooling/Syntax/MutationsTest.cpp index 30f8d523b781..088dbe3afbdc 100644 --- a/clang/unittests/Tooling/Syntax/MutationsTest.cpp +++ b/clang/unittests/Tooling/Syntax/MutationsTest.cpp @@ -10,6 +10,7 @@ // //===--===// +#include "clang/Tooling/Syntax/Mutations.h" #include "TreeTestBase.h" namespace clang { diff --git a/clang/unittests/Tooling/Syntax/TreeTestBase.h b/clang/unittests/Tooling/Syntax/TreeTestBase.h index 0e66a320d812..37b604dd5cd5 100644 --- a/clang/unittests/Tooling/Syntax/TreeTestBase.h +++ b/clang/unittests/Tooling/Syntax/TreeTestBase.h @@ -11,10 +11,7 @@ //===--===// #include "clang/AST/ASTConsumer.h" -#include "clang/AST/Decl.h" -#include "clang/AST/Stmt.h" #include "clang/Basic/LLVM.h" -#include "clang/Basic/TokenKinds.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/CompilerInvocation.h" #include "clang/Frontend/FrontendAction.h" @@ -22,23 +19,16 @@ #include "clang/Lex/PreprocessorOptions.h" #include "clang/Testing/CommandLineArgs.h" #include "clang/Testing/TestClangConfig.h" -#include "clang/Tooling/Core/Replacement.h" #include "clang/Tooling/Syntax/BuildTree.h" -#include "clang/Tooling/Syntax/Mutations.h" #include "clang/Tooling/Syntax/Nodes.h" #include "clang/Tooling/Syntax/Tokens.h" -#include "clang/Tooling/Tooling.h" +#include "clang/Tooling/Syntax/Tree.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Error.h" #include "llvm/Testing/Support/Annotations.h" -#include "gmock/gmock.h" #include "gtest/gtest.h" -#include -#include namespace clang { namespace syntax { ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 2e4a20f - [SyntaxTree] Split `TreeTestBase` into header and source
Author: Eduardo Caldas Date: 2020-08-14T07:29:07Z New Revision: 2e4a20fd7062f65c06b438953de3d340df00b7a7 URL: https://github.com/llvm/llvm-project/commit/2e4a20fd7062f65c06b438953de3d340df00b7a7 DIFF: https://github.com/llvm/llvm-project/commit/2e4a20fd7062f65c06b438953de3d340df00b7a7.diff LOG: [SyntaxTree] Split `TreeTestBase` into header and source * Switch to using directive on source files. * Remove unused `SyntaxTreeTest::addFile` Differential Revision: https://reviews.llvm.org/D85913 Added: clang/unittests/Tooling/Syntax/TreeTestBase.cpp Modified: clang/unittests/Tooling/Syntax/BuildTreeTest.cpp clang/unittests/Tooling/Syntax/CMakeLists.txt clang/unittests/Tooling/Syntax/MutationsTest.cpp clang/unittests/Tooling/Syntax/TreeTestBase.h Removed: diff --git a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp index deffd48da085..211e8b1ae901 100644 --- a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp @@ -12,8 +12,9 @@ #include "TreeTestBase.h" -namespace clang { -namespace syntax { +using namespace clang; +using namespace clang::syntax; + namespace { TEST_P(SyntaxTreeTest, Simple) { @@ -4836,26 +4837,4 @@ void x(char a, short (*b)(int), long (**c)(long long)); )txt")); } -static std::vector allTestClangConfigs() { - std::vector all_configs; - for (TestLanguage lang : {Lang_C89, Lang_C99, Lang_CXX03, Lang_CXX11, -Lang_CXX14, Lang_CXX17, Lang_CXX20}) { -TestClangConfig config; -config.Language = lang; -config.Target = "x86_64-pc-linux-gnu"; -all_configs.push_back(config); - -// Windows target is interesting to test because it enables -// `-fdelayed-template-parsing`. -config.Target = "x86_64-pc-win32-msvc"; -all_configs.push_back(config); - } - return all_configs; -} - -INSTANTIATE_TEST_CASE_P(SyntaxTreeTests, SyntaxTreeTest, -testing::ValuesIn(allTestClangConfigs()), ); - } // namespace -} // namespace syntax -} // namespace clang diff --git a/clang/unittests/Tooling/Syntax/CMakeLists.txt b/clang/unittests/Tooling/Syntax/CMakeLists.txt index c7634798fb2b..46ff4c9c3e27 100644 --- a/clang/unittests/Tooling/Syntax/CMakeLists.txt +++ b/clang/unittests/Tooling/Syntax/CMakeLists.txt @@ -3,6 +3,7 @@ set(LLVM_LINK_COMPONENTS ) add_clang_unittest(SyntaxTests + TreeTestBase.cpp BuildTreeTest.cpp MutationsTest.cpp TokensTest.cpp diff --git a/clang/unittests/Tooling/Syntax/MutationsTest.cpp b/clang/unittests/Tooling/Syntax/MutationsTest.cpp index 088dbe3afbdc..6ef71e3a8090 100644 --- a/clang/unittests/Tooling/Syntax/MutationsTest.cpp +++ b/clang/unittests/Tooling/Syntax/MutationsTest.cpp @@ -12,9 +12,11 @@ #include "clang/Tooling/Syntax/Mutations.h" #include "TreeTestBase.h" +#include "clang/Tooling/Syntax/BuildTree.h" + +using namespace clang; +using namespace clang::syntax; -namespace clang { -namespace syntax { namespace { TEST_P(SyntaxTreeTest, Mutations) { @@ -81,5 +83,3 @@ TEST_P(SyntaxTreeTest, SynthesizedNodes) { EXPECT_TRUE(S->isDetached()); } } // namespace -} // namespace syntax -} // namespace clang diff --git a/clang/unittests/Tooling/Syntax/TreeTestBase.cpp b/clang/unittests/Tooling/Syntax/TreeTestBase.cpp new file mode 100644 index ..6d2efeaaa8eb --- /dev/null +++ b/clang/unittests/Tooling/Syntax/TreeTestBase.cpp @@ -0,0 +1,200 @@ +//===- TreeTestBase.cpp ---===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// This file provides the test infrastructure for syntax trees. +// +//===--===// + +#include "TreeTestBase.h" +#include "clang/AST/ASTConsumer.h" +#include "clang/Basic/LLVM.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/CompilerInvocation.h" +#include "clang/Frontend/FrontendAction.h" +#include "clang/Frontend/TextDiagnosticPrinter.h" +#include "clang/Lex/PreprocessorOptions.h" +#include "clang/Testing/CommandLineArgs.h" +#include "clang/Testing/TestClangConfig.h" +#include "clang/Tooling/Syntax/BuildTree.h" +#include "clang/Tooling/Syntax/Nodes.h" +#include "clang/Tooling/Syntax/Tokens.h" +#include "clang/Tooling/Syntax/Tree.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Error.h" +#include "llvm/Testing/Support/Annotations.h" +#include "gtest/gtest.h" + +using namespace clang; +using namespace clang::syntax; + +namespace { +ArrayRef tokens(syntax::N
[clang] ab58c9e - [SyntaxTree] Implement annotation-based test infrastructure
Author: Eduardo Caldas Date: 2020-08-18T13:00:56Z New Revision: ab58c9ee8a6e9ace3a93198496b4d85e8cb2b5a9 URL: https://github.com/llvm/llvm-project/commit/ab58c9ee8a6e9ace3a93198496b4d85e8cb2b5a9 DIFF: https://github.com/llvm/llvm-project/commit/ab58c9ee8a6e9ace3a93198496b4d85e8cb2b5a9.diff LOG: [SyntaxTree] Implement annotation-based test infrastructure We add the method `SyntaxTreeTest::treeDumpEqualOnAnnotations`, which allows us to compare the treeDump of only annotated code. This will reduce a lot of noise from our `BuildTreeTest` and make them short and easier to read. Added: Modified: clang/unittests/Tooling/Syntax/TreeTestBase.cpp clang/unittests/Tooling/Syntax/TreeTestBase.h Removed: diff --git a/clang/unittests/Tooling/Syntax/TreeTestBase.cpp b/clang/unittests/Tooling/Syntax/TreeTestBase.cpp index 6d2efeaaa8eb..05fbac4f47e1 100644 --- a/clang/unittests/Tooling/Syntax/TreeTestBase.cpp +++ b/clang/unittests/Tooling/Syntax/TreeTestBase.cpp @@ -180,6 +180,35 @@ ::testing::AssertionResult SyntaxTreeTest::treeDumpEqual(StringRef Code, return ::testing::AssertionSuccess(); } +::testing::AssertionResult +SyntaxTreeTest::treeDumpEqualOnAnnotations(StringRef CodeWithAnnotations, + ArrayRef TreeDumps) { + SCOPED_TRACE(llvm::join(GetParam().getCommandLineArgs(), " ")); + + auto AnnotatedCode = llvm::Annotations(CodeWithAnnotations); + auto *Root = buildTree(AnnotatedCode.code(), GetParam()); + + if (Diags->getClient()->getNumErrors() != 0) { +return ::testing::AssertionFailure() + << "Source file has syntax errors, they were printed to the test " + "log"; + } + + bool failed = false; + auto AnnotatedRanges = AnnotatedCode.ranges(); + assert(AnnotatedRanges.size() == TreeDumps.size()); + for (auto i = 0ul; i < AnnotatedRanges.size(); i++) { +auto *AnnotatedNode = nodeByRange(AnnotatedRanges[i], Root); +assert(AnnotatedNode); +auto AnnotatedNodeDump = +std::string(StringRef(AnnotatedNode->dump(*Arena)).trim()); +// EXPECT_EQ shows the diff between the two strings if they are diff erent. +EXPECT_EQ(TreeDumps[i].trim().str(), AnnotatedNodeDump); +if (AnnotatedNodeDump != TreeDumps[i].trim().str()) + failed = true; + } + return failed ? ::testing::AssertionFailure() : ::testing::AssertionSuccess(); +} syntax::Node *SyntaxTreeTest::nodeByRange(llvm::Annotations::Range R, syntax::Node *Root) { ArrayRef Toks = tokens(Root); diff --git a/clang/unittests/Tooling/Syntax/TreeTestBase.h b/clang/unittests/Tooling/Syntax/TreeTestBase.h index bfa6ecd7909f..c282bbf45fd3 100644 --- a/clang/unittests/Tooling/Syntax/TreeTestBase.h +++ b/clang/unittests/Tooling/Syntax/TreeTestBase.h @@ -34,6 +34,9 @@ class SyntaxTreeTest : public ::testing::Test, ::testing::AssertionResult treeDumpEqual(StringRef Code, StringRef Tree); + ::testing::AssertionResult + treeDumpEqualOnAnnotations(StringRef CodeWithAnnotations, + ArrayRef TreeDumps); /// Finds the deepest node in the tree that covers exactly \p R. /// FIXME: implement this efficiently and move to public syntax tree API. syntax::Node *nodeByRange(llvm::Annotations::Range R, syntax::Node *Root); ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] c8c92b5 - [SyntaxTree] Use Annotations based tests for expressions
Author: Eduardo Caldas Date: 2020-08-18T13:00:56Z New Revision: c8c92b54d74c1b9256f9aed6ba89d66fbd1d01ae URL: https://github.com/llvm/llvm-project/commit/c8c92b54d74c1b9256f9aed6ba89d66fbd1d01ae DIFF: https://github.com/llvm/llvm-project/commit/c8c92b54d74c1b9256f9aed6ba89d66fbd1d01ae.diff LOG: [SyntaxTree] Use Annotations based tests for expressions In this process we also create some other tests, in order to not lose coverage when focusing on the annotated code Differential Revision: https://reviews.llvm.org/D85962 Added: Modified: clang/unittests/Tooling/Syntax/BuildTreeTest.cpp clang/unittests/Tooling/Syntax/TreeTestBase.cpp Removed: diff --git a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp index 211e8b1ae901..fd858dfba91f 100644 --- a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp @@ -437,672 +437,355 @@ void test() { } TEST_P(SyntaxTreeTest, UnqualifiedId_Identifier) { - EXPECT_TRUE(treeDumpEqual( + EXPECT_TRUE(treeDumpEqualOnAnnotations( R"cpp( void test(int a) { - a; + [[a]]; } )cpp", - R"txt( -*: TranslationUnit -`-SimpleDeclaration - |-void - |-SimpleDeclarator - | |-test - | `-ParametersAndQualifiers - | |-( - | |-SimpleDeclaration - | | |-int - | | `-SimpleDeclarator - | | `-a - | `-) - `-CompoundStatement -|-{ -|-ExpressionStatement -| |-IdExpression -| | `-UnqualifiedId -| | `-a -| `-; -`-} -)txt")); + {R"txt( +IdExpression +`-UnqualifiedId + `-a +)txt"})); } TEST_P(SyntaxTreeTest, UnqualifiedId_OperatorFunctionId) { if (!GetParam().isCXX()) { return; } - EXPECT_TRUE(treeDumpEqual( + EXPECT_TRUE(treeDumpEqualOnAnnotations( R"cpp( struct X { friend X operator+(const X&, const X&); }; void test(X x) { - operator+(x, x); -} -)cpp", - R"txt( -*: TranslationUnit -|-SimpleDeclaration -| |-struct -| |-X -| |-{ -| |-UnknownDeclaration -| | `-SimpleDeclaration -| | |-friend -| | |-X -| | |-SimpleDeclarator -| | | |-operator -| | | |-+ -| | | `-ParametersAndQualifiers -| | | |-( -| | | |-SimpleDeclaration -| | | | |-const -| | | | |-X -| | | | `-SimpleDeclarator -| | | | `-& -| | | |-, -| | | |-SimpleDeclaration -| | | | |-const -| | | | |-X -| | | | `-SimpleDeclarator -| | | | `-& -| | | `-) -| | `-; -| |-} -| `-; -`-SimpleDeclaration - |-void - |-SimpleDeclarator - | |-test - | `-ParametersAndQualifiers - | |-( - | |-SimpleDeclaration - | | |-X - | | `-SimpleDeclarator - | | `-x - | `-) - `-CompoundStatement -|-{ -|-ExpressionStatement -| |-UnknownExpression -| | |-IdExpression -| | | `-UnqualifiedId -| | | |-operator -| | | `-+ -| | |-( -| | |-IdExpression -| | | `-UnqualifiedId -| | | `-x -| | |-, -| | |-IdExpression -| | | `-UnqualifiedId -| | | `-x -| | `-) -| `-; -`-} -)txt")); + [[operator+(x, x)]]; +} +)cpp", + {R"txt( +UnknownExpression +|-IdExpression +| `-UnqualifiedId +| |-operator +| `-+ +|-( +|-IdExpression +| `-UnqualifiedId +| `-x +|-, +|-IdExpression +| `-UnqualifiedId +| `-x +`-) +)txt"})); } TEST_P(SyntaxTreeTest, UnqualifiedId_ConversionFunctionId) { if (!GetParam().isCXX()) { return; } - EXPECT_TRUE(treeDumpEqual( + EXPECT_TRUE(treeDumpEqualOnAnnotations( R"cpp( struct X { operator int(); }; void test(X x) { // TODO: Expose `id-expression` from `MemberExpr` - x.operator int(); + [[x.operator int()]]; } )cpp", - R"txt( -*: TranslationUnit -|-SimpleDeclaration -| |-struct -| |-X -| |-{ -| |-SimpleDeclaration -| | |-SimpleDeclarator -| | | |-operator -| | | |-int -| | | `-ParametersAndQualifiers -| | | |-( -| | | `-) -| | `-; -| |-} -| `-; -`-SimpleDeclaration - |-void - |-SimpleDeclarator - | |-test - | `-ParametersAndQualifiers - | |-( - | |-SimpleDeclaration - | | |-X - | | `-SimpleDeclarator - | | `-x - | `-) - `-CompoundStatement -|-{ -|-ExpressionStatement -| |-UnknownExpression -| | |-UnknownExpression -| | | |-IdExpression -| | | | `-UnqualifiedId -| | | | `-x -| | | |-. -| | | |-operator -| | | `-int -| | |-( -| | `-) -| `-; -`-} -)txt")); + {R"txt( +UnknownExpression +|-UnknownExpression +| |-IdExpression +| | `-UnqualifiedId +| | `-x +| |-. +| |-operator +| `-int +|-( +`-) +)txt"})); } TEST_P(SyntaxTreeTest, UnqualifiedId_LiteralOperatorId) { if (!GetParam().isCXX11OrLater()) { return; } - EXPECT_TRUE(treeDumpEqual( + EXPECT_TRUE(treeDumpEqualOnAnnotations( R"cpp( unsigned operator "" _w(char); void test() { - operator "" _w('1'); + [[operator "" _w('1')]]; } )cpp", - R"txt( -*:
[clang] 4c14ee6 - [SyntaxTree] Rename functions to start with verb
Author: Eduardo Caldas Date: 2020-09-11T14:54:18Z New Revision: 4c14ee61b73746b314d83e7c52e03d6527b78105 URL: https://github.com/llvm/llvm-project/commit/4c14ee61b73746b314d83e7c52e03d6527b78105 DIFF: https://github.com/llvm/llvm-project/commit/4c14ee61b73746b314d83e7c52e03d6527b78105.diff LOG: [SyntaxTree] Rename functions to start with verb According to LLVM coding standards: https://llvm.org/docs/CodingStandards.html#name-types-functions-variables-and-enumerators-properly Differential Revision: https://reviews.llvm.org/D87498 Added: Modified: clang/include/clang/Tooling/Syntax/Nodes.h clang/include/clang/Tooling/Syntax/Tree.h clang/lib/Tooling/Syntax/BuildTree.cpp clang/lib/Tooling/Syntax/ComputeReplacements.cpp clang/lib/Tooling/Syntax/Mutations.cpp clang/lib/Tooling/Syntax/Nodes.cpp clang/lib/Tooling/Syntax/Synthesis.cpp clang/lib/Tooling/Syntax/Tree.cpp clang/unittests/Tooling/Syntax/BuildTreeTest.cpp clang/unittests/Tooling/Syntax/SynthesisTest.cpp clang/unittests/Tooling/Syntax/TreeTestBase.cpp Removed: diff --git a/clang/include/clang/Tooling/Syntax/Nodes.h b/clang/include/clang/Tooling/Syntax/Nodes.h index a6505c8167ee..8b393c5423b4 100644 --- a/clang/include/clang/Tooling/Syntax/Nodes.h +++ b/clang/include/clang/Tooling/Syntax/Nodes.h @@ -190,7 +190,7 @@ class TranslationUnit final : public Tree { public: TranslationUnit() : Tree(NodeKind::TranslationUnit) {} static bool classof(const Node *N) { -return N->kind() == NodeKind::TranslationUnit; +return N->getKind() == NodeKind::TranslationUnit; } }; @@ -200,8 +200,8 @@ class Expression : public Tree { public: Expression(NodeKind K) : Tree(K) {} static bool classof(const Node *N) { -return NodeKind::UnknownExpression <= N->kind() && - N->kind() <= NodeKind::UnknownExpression; +return NodeKind::UnknownExpression <= N->getKind() && + N->getKind() <= NodeKind::UnknownExpression; } }; @@ -211,10 +211,10 @@ class NameSpecifier : public Tree { public: NameSpecifier(NodeKind K) : Tree(K) {} static bool classof(const Node *N) { -return N->kind() == NodeKind::GlobalNameSpecifier || - N->kind() == NodeKind::DecltypeNameSpecifier || - N->kind() == NodeKind::IdentifierNameSpecifier || - N->kind() == NodeKind::SimpleTemplateNameSpecifier; +return N->getKind() == NodeKind::GlobalNameSpecifier || + N->getKind() == NodeKind::DecltypeNameSpecifier || + N->getKind() == NodeKind::IdentifierNameSpecifier || + N->getKind() == NodeKind::SimpleTemplateNameSpecifier; } }; @@ -226,7 +226,7 @@ class GlobalNameSpecifier final : public NameSpecifier { public: GlobalNameSpecifier() : NameSpecifier(NodeKind::GlobalNameSpecifier) {} static bool classof(const Node *N) { -return N->kind() == NodeKind::GlobalNameSpecifier; +return N->getKind() == NodeKind::GlobalNameSpecifier; } }; @@ -236,7 +236,7 @@ class DecltypeNameSpecifier final : public NameSpecifier { public: DecltypeNameSpecifier() : NameSpecifier(NodeKind::DecltypeNameSpecifier) {} static bool classof(const Node *N) { -return N->kind() == NodeKind::DecltypeNameSpecifier; +return N->getKind() == NodeKind::DecltypeNameSpecifier; } }; @@ -247,7 +247,7 @@ class IdentifierNameSpecifier final : public NameSpecifier { IdentifierNameSpecifier() : NameSpecifier(NodeKind::IdentifierNameSpecifier) {} static bool classof(const Node *N) { -return N->kind() == NodeKind::IdentifierNameSpecifier; +return N->getKind() == NodeKind::IdentifierNameSpecifier; } }; @@ -259,7 +259,7 @@ class SimpleTemplateNameSpecifier final : public NameSpecifier { SimpleTemplateNameSpecifier() : NameSpecifier(NodeKind::SimpleTemplateNameSpecifier) {} static bool classof(const Node *N) { -return N->kind() == NodeKind::SimpleTemplateNameSpecifier; +return N->getKind() == NodeKind::SimpleTemplateNameSpecifier; } }; @@ -269,7 +269,7 @@ class NestedNameSpecifier final : public List { public: NestedNameSpecifier() : List(NodeKind::NestedNameSpecifier) {} static bool classof(const Node *N) { -return N->kind() <= NodeKind::NestedNameSpecifier; +return N->getKind() <= NodeKind::NestedNameSpecifier; } std::vector getSpecifiers(); std::vector> @@ -282,7 +282,7 @@ class UnqualifiedId final : public Tree { public: UnqualifiedId() : Tree(NodeKind::UnqualifiedId) {} static bool classof(const Node *N) { -return N->kind() == NodeKind::UnqualifiedId; +return N->getKind() == NodeKind::UnqualifiedId; } }; @@ -297,7 +297,7 @@ class IdExpression final : public Expression { public: IdExpression() : Expression(NodeKind::IdExpression) {} static bool classof(const Node *N) { -return N->kind() == NodeKind::IdExpression; +return N->getKind() =
[clang] 5d15212 - [SyntaxTree][Synthesis] Add support for simple Leafs and test based on tree dump
Author: Eduardo Caldas Date: 2020-09-11T18:22:00Z New Revision: 5d152127d48fbcf47a8d059aa68a84c365ae3cb9 URL: https://github.com/llvm/llvm-project/commit/5d152127d48fbcf47a8d059aa68a84c365ae3cb9 DIFF: https://github.com/llvm/llvm-project/commit/5d152127d48fbcf47a8d059aa68a84c365ae3cb9.diff LOG: [SyntaxTree][Synthesis] Add support for simple Leafs and test based on tree dump Differential Revision: https://reviews.llvm.org/D87495 Added: Modified: clang/include/clang/Tooling/Syntax/BuildTree.h clang/lib/Tooling/Syntax/Synthesis.cpp clang/unittests/Tooling/Syntax/SynthesisTest.cpp Removed: diff --git a/clang/include/clang/Tooling/Syntax/BuildTree.h b/clang/include/clang/Tooling/Syntax/BuildTree.h index b7ad50c941d1..c2ae4348bc16 100644 --- a/clang/include/clang/Tooling/Syntax/BuildTree.h +++ b/clang/include/clang/Tooling/Syntax/BuildTree.h @@ -24,8 +24,17 @@ syntax::TranslationUnit *buildSyntaxTree(Arena &A, // Create syntax trees from subtrees not backed by the source code. -clang::syntax::Leaf *createPunctuation(clang::syntax::Arena &A, - clang::tok::TokenKind K); +// Synthesis of Leafs +/// Create `Leaf` from token with `Spelling` and assert it has the desired +/// `TokenKind`. +syntax::Leaf *createLeaf(syntax::Arena &A, tok::TokenKind K, + StringRef Spelling); + +/// Infer the token spelling from its `TokenKind`, then create `Leaf` from +/// this token +syntax::Leaf *createLeaf(syntax::Arena &A, tok::TokenKind K); + +// Synthesis of Syntax Nodes clang::syntax::EmptyStatement *createEmptyStatement(clang::syntax::Arena &A); } // namespace syntax diff --git a/clang/lib/Tooling/Syntax/Synthesis.cpp b/clang/lib/Tooling/Syntax/Synthesis.cpp index 701a1e60a4f3..8d51325706fa 100644 --- a/clang/lib/Tooling/Syntax/Synthesis.cpp +++ b/clang/lib/Tooling/Syntax/Synthesis.cpp @@ -5,13 +5,14 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===--===// +#include "clang/Basic/TokenKinds.h" #include "clang/Tooling/Syntax/BuildTree.h" using namespace clang; /// Exposes private syntax tree APIs required to implement node synthesis. /// Should not be used for anything else. -class syntax::FactoryImpl { +class clang::syntax::FactoryImpl { public: static void setCanModify(syntax::Node *N) { N->CanModify = true; } @@ -21,24 +22,32 @@ class syntax::FactoryImpl { } }; -clang::syntax::Leaf *syntax::createPunctuation(clang::syntax::Arena &A, - clang::tok::TokenKind K) { - auto Tokens = A.lexBuffer(llvm::MemoryBuffer::getMemBuffer( -clang::tok::getPunctuatorSpelling(K))) -.second; +syntax::Leaf *clang::syntax::createLeaf(syntax::Arena &A, tok::TokenKind K, +StringRef Spelling) { + auto Tokens = A.lexBuffer(llvm::MemoryBuffer::getMemBuffer(Spelling)).second; assert(Tokens.size() == 1); - assert(Tokens.front().kind() == K); - auto *L = new (A.getAllocator()) clang::syntax::Leaf(Tokens.begin()); - FactoryImpl::setCanModify(L); - L->assertInvariants(); - return L; + assert(Tokens.front().kind() == K && + "spelling is not lexed into the expected kind of token"); + + auto *Leaf = new (A.getAllocator()) syntax::Leaf(Tokens.begin()); + syntax::FactoryImpl::setCanModify(Leaf); + Leaf->assertInvariants(); + return Leaf; +} + +syntax::Leaf *clang::syntax::createLeaf(syntax::Arena &A, tok::TokenKind K) { + const auto *Spelling = tok::getPunctuatorSpelling(K); + if (!Spelling) +Spelling = tok::getKeywordSpelling(K); + assert(Spelling && + "Cannot infer the spelling of the token from its token kind."); + return createLeaf(A, K, Spelling); } -clang::syntax::EmptyStatement * -syntax::createEmptyStatement(clang::syntax::Arena &A) { - auto *S = new (A.getAllocator()) clang::syntax::EmptyStatement; +syntax::EmptyStatement *clang::syntax::createEmptyStatement(syntax::Arena &A) { + auto *S = new (A.getAllocator()) syntax::EmptyStatement; FactoryImpl::setCanModify(S); - FactoryImpl::prependChildLowLevel(S, createPunctuation(A, clang::tok::semi), + FactoryImpl::prependChildLowLevel(S, createLeaf(A, tok::semi), NodeRole::Unknown); S->assertInvariants(); return S; diff --git a/clang/unittests/Tooling/Syntax/SynthesisTest.cpp b/clang/unittests/Tooling/Syntax/SynthesisTest.cpp index 884f3797edef..1c1aef8bd8c8 100644 --- a/clang/unittests/Tooling/Syntax/SynthesisTest.cpp +++ b/clang/unittests/Tooling/Syntax/SynthesisTest.cpp @@ -12,33 +12,81 @@ #include "TreeTestBase.h" #include "clang/Tooling/Syntax/BuildTree.h" +#include "gtest/gtest.h" using namespace clang; using namespace clang::syntax; namespace { -INSTANTIATE_TEST_CA
[clang] 515238d - [SyntaxTree] Reduce visibility of `Arena::lexBuffer`.
Author: Eduardo Caldas Date: 2020-09-11T18:32:38Z New Revision: 515238d5b1133f87f85445b9f35783ca2d3a2e7b URL: https://github.com/llvm/llvm-project/commit/515238d5b1133f87f85445b9f35783ca2d3a2e7b DIFF: https://github.com/llvm/llvm-project/commit/515238d5b1133f87f85445b9f35783ca2d3a2e7b.diff LOG: [SyntaxTree] Reduce visibility of `Arena::lexBuffer`. Differential Revision: https://reviews.llvm.org/D87523 Added: Modified: clang/include/clang/Tooling/Syntax/Tree.h clang/lib/Tooling/Syntax/Synthesis.cpp Removed: diff --git a/clang/include/clang/Tooling/Syntax/Tree.h b/clang/include/clang/Tooling/Syntax/Tree.h index aab904ab65d32..b49a09344c0fb 100644 --- a/clang/include/clang/Tooling/Syntax/Tree.h +++ b/clang/include/clang/Tooling/Syntax/Tree.h @@ -47,11 +47,13 @@ class Arena { const TokenBuffer &getTokenBuffer() const; llvm::BumpPtrAllocator &getAllocator() { return Allocator; } +private: /// Add \p Buffer to the underlying source manager, tokenize it and store the - /// resulting tokens. Useful when there is a need to materialize tokens that - /// were not written in user code. + /// resulting tokens. Used exclusively in `FactoryImpl` to materialize tokens + /// that were not written in user code. std::pair> lexBuffer(std::unique_ptr Buffer); + friend class FactoryImpl; private: SourceManager &SourceMgr; diff --git a/clang/lib/Tooling/Syntax/Synthesis.cpp b/clang/lib/Tooling/Syntax/Synthesis.cpp index 8d51325706fa0..772429ff4c466 100644 --- a/clang/lib/Tooling/Syntax/Synthesis.cpp +++ b/clang/lib/Tooling/Syntax/Synthesis.cpp @@ -7,6 +7,7 @@ //===--===// #include "clang/Basic/TokenKinds.h" #include "clang/Tooling/Syntax/BuildTree.h" +#include "clang/Tooling/Syntax/Tree.h" using namespace clang; @@ -20,11 +21,18 @@ class clang::syntax::FactoryImpl { syntax::NodeRole R) { T->prependChildLowLevel(Child, R); } + + static std::pair> + lexBuffer(syntax::Arena &A, std::unique_ptr Buffer) { +return A.lexBuffer(std::move(Buffer)); + } }; syntax::Leaf *clang::syntax::createLeaf(syntax::Arena &A, tok::TokenKind K, StringRef Spelling) { - auto Tokens = A.lexBuffer(llvm::MemoryBuffer::getMemBuffer(Spelling)).second; + auto Tokens = + FactoryImpl::lexBuffer(A, llvm::MemoryBuffer::getMemBuffer(Spelling)) + .second; assert(Tokens.size() == 1); assert(Tokens.front().kind() == K && "spelling is not lexed into the expected kind of token"); ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 238ae4e - [SyntaxTree] Add const qualifiers, from [llvm-qualified-auto]
Author: Eduardo Caldas Date: 2020-09-11T18:39:02Z New Revision: 238ae4eee05187758e42c00af237592612d585c2 URL: https://github.com/llvm/llvm-project/commit/238ae4eee05187758e42c00af237592612d585c2 DIFF: https://github.com/llvm/llvm-project/commit/238ae4eee05187758e42c00af237592612d585c2.diff LOG: [SyntaxTree] Add const qualifiers, from [llvm-qualified-auto] Differential Revision: https://reviews.llvm.org/D87522 Added: Modified: clang/lib/Tooling/Syntax/BuildTree.cpp clang/lib/Tooling/Syntax/ComputeReplacements.cpp clang/lib/Tooling/Syntax/Tree.cpp Removed: diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp index 8de50dd02162..dab1457fbdba 100644 --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -558,7 +558,7 @@ class syntax::TreeBuilder { assert(A.getTokenBuffer().expandedTokens().back().kind() == tok::eof); // Create all leaf nodes. // Note that we do not have 'eof' in the tree. - for (auto &T : A.getTokenBuffer().expandedTokens().drop_back()) { + for (const auto &T : A.getTokenBuffer().expandedTokens().drop_back()) { auto *L = new (A.getAllocator()) syntax::Leaf(&T); L->Original = true; L->CanModify = A.getTokenBuffer().spelledForExpanded(T).hasValue(); diff --git a/clang/lib/Tooling/Syntax/ComputeReplacements.cpp b/clang/lib/Tooling/Syntax/ComputeReplacements.cpp index 93b1c4416bf4..31e1a40c74b6 100644 --- a/clang/lib/Tooling/Syntax/ComputeReplacements.cpp +++ b/clang/lib/Tooling/Syntax/ComputeReplacements.cpp @@ -32,7 +32,7 @@ void enumerateTokenSpans(const syntax::Tree *Root, ProcessTokensFn Callback) { private: void process(const syntax::Node *N) { if (auto *T = dyn_cast(N)) { -for (auto *C = T->getFirstChild(); C != nullptr; +for (const auto *C = T->getFirstChild(); C != nullptr; C = C->getNextSibling()) process(C); return; @@ -64,8 +64,8 @@ void enumerateTokenSpans(const syntax::Tree *Root, ProcessTokensFn Callback) { syntax::FileRange rangeOfExpanded(const syntax::Arena &A, llvm::ArrayRef Expanded) { - auto &Buffer = A.getTokenBuffer(); - auto &SM = A.getSourceManager(); + const auto &Buffer = A.getTokenBuffer(); + const auto &SM = A.getSourceManager(); // Check that \p Expanded actually points into expanded tokens. assert(Buffer.expandedTokens().begin() <= Expanded.begin()); @@ -85,8 +85,8 @@ syntax::FileRange rangeOfExpanded(const syntax::Arena &A, tooling::Replacements syntax::computeReplacements(const syntax::Arena &A, const syntax::TranslationUnit &TU) { - auto &Buffer = A.getTokenBuffer(); - auto &SM = A.getSourceManager(); + const auto &Buffer = A.getTokenBuffer(); + const auto &SM = A.getSourceManager(); tooling::Replacements Replacements; // Text inserted by the replacement we are building now. diff --git a/clang/lib/Tooling/Syntax/Tree.cpp b/clang/lib/Tooling/Syntax/Tree.cpp index f9d1fa6110ff..ca1e2880af9f 100644 --- a/clang/lib/Tooling/Syntax/Tree.cpp +++ b/clang/lib/Tooling/Syntax/Tree.cpp @@ -19,7 +19,7 @@ namespace { static void traverse(const syntax::Node *N, llvm::function_ref Visit) { if (auto *T = dyn_cast(N)) { -for (auto *C = T->getFirstChild(); C; C = C->getNextSibling()) +for (const auto *C = T->getFirstChild(); C; C = C->getNextSibling()) traverse(C, Visit); } Visit(N); @@ -226,7 +226,7 @@ void syntax::Node::assertInvariants() const { auto *T = dyn_cast(this); if (!T) return; - for (auto *C = T->getFirstChild(); C; C = C->getNextSibling()) { + for (const auto *C = T->getFirstChild(); C; C = C->getNextSibling()) { if (T->isOriginal()) assert(C->isOriginal()); assert(!C->isDetached()); ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 7c37b82 - [SyntaxTree][Synthesis] Add support for Tree.
Author: Eduardo Caldas Date: 2020-09-11T20:37:23Z New Revision: 7c37b82f5ba5883b331608b0077c0b30bf301874 URL: https://github.com/llvm/llvm-project/commit/7c37b82f5ba5883b331608b0077c0b30bf301874 DIFF: https://github.com/llvm/llvm-project/commit/7c37b82f5ba5883b331608b0077c0b30bf301874.diff LOG: [SyntaxTree][Synthesis] Add support for Tree. In a future patch * Implement helper function to generate Trees for tests * and test Tree methods, namely `findFirstLeaf` and `findLastLeaf` Differential Revision: https://reviews.llvm.org/D87533 Added: Modified: clang/include/clang/Tooling/Syntax/BuildTree.h clang/lib/Tooling/Syntax/Synthesis.cpp clang/unittests/Tooling/Syntax/SynthesisTest.cpp Removed: diff --git a/clang/include/clang/Tooling/Syntax/BuildTree.h b/clang/include/clang/Tooling/Syntax/BuildTree.h index c2ae4348bc16..b9405167bf99 100644 --- a/clang/include/clang/Tooling/Syntax/BuildTree.h +++ b/clang/include/clang/Tooling/Syntax/BuildTree.h @@ -34,6 +34,12 @@ syntax::Leaf *createLeaf(syntax::Arena &A, tok::TokenKind K, /// this token syntax::Leaf *createLeaf(syntax::Arena &A, tok::TokenKind K); +// Synthesis of Trees +syntax::Tree * +createTree(Arena &A, + std::vector> Children, + syntax::NodeKind K); + // Synthesis of Syntax Nodes clang::syntax::EmptyStatement *createEmptyStatement(clang::syntax::Arena &A); diff --git a/clang/lib/Tooling/Syntax/Synthesis.cpp b/clang/lib/Tooling/Syntax/Synthesis.cpp index 772429ff4c46..6de3d5b5752d 100644 --- a/clang/lib/Tooling/Syntax/Synthesis.cpp +++ b/clang/lib/Tooling/Syntax/Synthesis.cpp @@ -52,6 +52,20 @@ syntax::Leaf *clang::syntax::createLeaf(syntax::Arena &A, tok::TokenKind K) { return createLeaf(A, K, Spelling); } +syntax::Tree *clang::syntax::createTree( +syntax::Arena &A, +std::vector> Children, +syntax::NodeKind K) { + auto *T = new (A.getAllocator()) syntax::Tree(K); + FactoryImpl::setCanModify(T); + for (auto ChildIt = Children.rbegin(); ChildIt != Children.rend(); + std::advance(ChildIt, 1)) +FactoryImpl::prependChildLowLevel(T, ChildIt->first, ChildIt->second); + + T->assertInvariants(); + return T; +} + syntax::EmptyStatement *clang::syntax::createEmptyStatement(syntax::Arena &A) { auto *S = new (A.getAllocator()) syntax::EmptyStatement; FactoryImpl::setCanModify(S); diff --git a/clang/unittests/Tooling/Syntax/SynthesisTest.cpp b/clang/unittests/Tooling/Syntax/SynthesisTest.cpp index 1c1aef8bd8c8..a882714ccf33 100644 --- a/clang/unittests/Tooling/Syntax/SynthesisTest.cpp +++ b/clang/unittests/Tooling/Syntax/SynthesisTest.cpp @@ -12,6 +12,7 @@ #include "TreeTestBase.h" #include "clang/Tooling/Syntax/BuildTree.h" +#include "clang/Tooling/Syntax/Nodes.h" #include "gtest/gtest.h" using namespace clang; @@ -80,6 +81,62 @@ TEST_P(SynthesisTest, Leaf_Number) { )txt")); } +TEST_P(SynthesisTest, Tree_Empty) { + buildTree("", GetParam()); + + auto *Tree = createTree(*Arena, {}, NodeKind::UnknownExpression); + + EXPECT_TRUE(treeDumpEqual(Tree, R"txt( +UnknownExpression Detached synthesized + )txt")); +} + +TEST_P(SynthesisTest, Tree_Flat) { + buildTree("", GetParam()); + + auto *LeafLParen = createLeaf(*Arena, tok::l_paren); + auto *LeafRParen = createLeaf(*Arena, tok::r_paren); + auto *TreeParen = createTree(*Arena, + {{LeafLParen, NodeRole::LeftHandSide}, +{LeafRParen, NodeRole::RightHandSide}}, + NodeKind::ParenExpression); + + EXPECT_TRUE(treeDumpEqual(TreeParen, R"txt( +ParenExpression Detached synthesized +|-'(' LeftHandSide synthesized +`-')' RightHandSide synthesized + )txt")); +} + +TEST_P(SynthesisTest, Tree_OfTree) { + buildTree("", GetParam()); + + auto *Leaf1 = createLeaf(*Arena, tok::numeric_constant, "1"); + auto *Int1 = createTree(*Arena, {{Leaf1, NodeRole::LiteralToken}}, + NodeKind::IntegerLiteralExpression); + + auto *LeafPlus = createLeaf(*Arena, tok::plus); + + auto *Leaf2 = createLeaf(*Arena, tok::numeric_constant, "2"); + auto *Int2 = createTree(*Arena, {{Leaf2, NodeRole::LiteralToken}}, + NodeKind::IntegerLiteralExpression); + + auto *TreeBinaryOperator = createTree(*Arena, +{{Int1, NodeRole::LeftHandSide}, + {LeafPlus, NodeRole::OperatorToken}, + {Int2, NodeRole::RightHandSide}}, +NodeKind::BinaryOperatorExpression); + + EXPECT_TRUE(treeDumpEqual(TreeBinaryOperator, R"txt( +BinaryOperatorExpression Detached synthesized +|-IntegerLiteralExpression LeftHandSide synthesized +| `-'1' LiteralToken synthesized +|-'+' OperatorToken synthesized +`-IntegerLiteralExpression RightHandSide synthesized + `-'2' LiteralToken synthesized
[clang] 12232dc - [SyntaxTree][List] Fix: `ParameterDeclarationList` is the `List` inside `ParametersAndQualifiers`
Author: Eduardo Caldas Date: 2020-09-14T10:35:41Z New Revision: 12232dc181cbe78fbd40a6ed1a89795a2c9a1154 URL: https://github.com/llvm/llvm-project/commit/12232dc181cbe78fbd40a6ed1a89795a2c9a1154 DIFF: https://github.com/llvm/llvm-project/commit/12232dc181cbe78fbd40a6ed1a89795a2c9a1154.diff LOG: [SyntaxTree][List] Fix: `ParameterDeclarationList` is the `List` inside `ParametersAndQualifiers` Differential Revision: https://reviews.llvm.org/D87598 Added: Modified: clang/lib/Tooling/Syntax/Tree.cpp Removed: diff --git a/clang/lib/Tooling/Syntax/Tree.cpp b/clang/lib/Tooling/Syntax/Tree.cpp index ca1e2880af9f..2bff159696c1 100644 --- a/clang/lib/Tooling/Syntax/Tree.cpp +++ b/clang/lib/Tooling/Syntax/Tree.cpp @@ -366,7 +366,7 @@ clang::tok::TokenKind syntax::List::getDelimiterTokenKind() { case NodeKind::NestedNameSpecifier: return clang::tok::coloncolon; case NodeKind::CallArguments: - case NodeKind::ParametersAndQualifiers: + case NodeKind::ParameterDeclarationList: return clang::tok::comma; default: llvm_unreachable("This is not a subclass of List, thus " @@ -379,7 +379,7 @@ syntax::List::TerminationKind syntax::List::getTerminationKind() { case NodeKind::NestedNameSpecifier: return TerminationKind::Terminated; case NodeKind::CallArguments: - case NodeKind::ParametersAndQualifiers: + case NodeKind::ParameterDeclarationList: return TerminationKind::Separated; default: llvm_unreachable("This is not a subclass of List, thus " @@ -393,7 +393,7 @@ bool syntax::List::canBeEmpty() { return false; case NodeKind::CallArguments: return true; - case NodeKind::ParametersAndQualifiers: + case NodeKind::ParameterDeclarationList: return true; default: llvm_unreachable("This is not a subclass of List, thus canBeEmpty() " ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 0f4cc64 - [SyntaxTree] Provide `List::classof`
Author: Eduardo Caldas Date: 2020-09-14T10:35:41Z New Revision: 0f4cc64fd747fbb33aeccfaccb8873762d2511f2 URL: https://github.com/llvm/llvm-project/commit/0f4cc64fd747fbb33aeccfaccb8873762d2511f2 DIFF: https://github.com/llvm/llvm-project/commit/0f4cc64fd747fbb33aeccfaccb8873762d2511f2.diff LOG: [SyntaxTree] Provide `List::classof` Differential Revision: https://reviews.llvm.org/D87599 Added: Modified: clang/include/clang/Tooling/Syntax/Tree.h clang/lib/Tooling/Syntax/Tree.cpp Removed: diff --git a/clang/include/clang/Tooling/Syntax/Tree.h b/clang/include/clang/Tooling/Syntax/Tree.h index b49a09344c0f..5a09d4564969 100644 --- a/clang/include/clang/Tooling/Syntax/Tree.h +++ b/clang/include/clang/Tooling/Syntax/Tree.h @@ -213,6 +213,7 @@ class List : public Tree { }; using Tree::Tree; + static bool classof(const Node *N); /// Returns the elements and corresponding delimiters. Missing elements /// and delimiters are represented as null pointers. /// diff --git a/clang/lib/Tooling/Syntax/Tree.cpp b/clang/lib/Tooling/Syntax/Tree.cpp index 2bff159696c1..1c705f6fd7cf 100644 --- a/clang/lib/Tooling/Syntax/Tree.cpp +++ b/clang/lib/Tooling/Syntax/Tree.cpp @@ -273,6 +273,17 @@ syntax::Node *syntax::Tree::findChild(NodeRole R) { return nullptr; } +bool classof(const syntax::Node *N) { + switch (N->getKind()) { + case syntax::NodeKind::NestedNameSpecifier: + case syntax::NodeKind::CallArguments: + case syntax::NodeKind::ParameterDeclarationList: +return true; + default: +return false; + } +} + std::vector> syntax::List::getElementsAsNodesAndDelimiters() { if (!getFirstChild()) ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] ceb0128 - [SyntaxTree][List] `assertInvariants` for `List`s
Author: Eduardo Caldas Date: 2020-09-14T10:36:11Z New Revision: ceb0128509c51100afbf804bda84d82b7ebe06b1 URL: https://github.com/llvm/llvm-project/commit/ceb0128509c51100afbf804bda84d82b7ebe06b1 DIFF: https://github.com/llvm/llvm-project/commit/ceb0128509c51100afbf804bda84d82b7ebe06b1.diff LOG: [SyntaxTree][List] `assertInvariants` for `List`s Differential Revision: https://reviews.llvm.org/D87600 Added: Modified: clang/include/clang/Tooling/Syntax/Tree.h clang/lib/Tooling/Syntax/Tree.cpp Removed: diff --git a/clang/include/clang/Tooling/Syntax/Tree.h b/clang/include/clang/Tooling/Syntax/Tree.h index 5a09d4564969..a544fc1827b7 100644 --- a/clang/include/clang/Tooling/Syntax/Tree.h +++ b/clang/include/clang/Tooling/Syntax/Tree.h @@ -237,16 +237,16 @@ class List : public Tree { /// /// Useful for discovering the correct delimiter to use when adding /// elements to empty or one-element lists. - clang::tok::TokenKind getDelimiterTokenKind(); + clang::tok::TokenKind getDelimiterTokenKind() const; - TerminationKind getTerminationKind(); + TerminationKind getTerminationKind() const; /// Whether this list can be empty in syntactically and semantically correct /// code. /// /// This list may be empty when the source code has errors even if /// canBeEmpty() returns false. - bool canBeEmpty(); + bool canBeEmpty() const; }; } // namespace syntax diff --git a/clang/lib/Tooling/Syntax/Tree.cpp b/clang/lib/Tooling/Syntax/Tree.cpp index 1c705f6fd7cf..1edd2583105a 100644 --- a/clang/lib/Tooling/Syntax/Tree.cpp +++ b/clang/lib/Tooling/Syntax/Tree.cpp @@ -223,7 +223,7 @@ void syntax::Node::assertInvariants() const { else assert(getParent() != nullptr); - auto *T = dyn_cast(this); + const auto *T = dyn_cast(this); if (!T) return; for (const auto *C = T->getFirstChild(); C; C = C->getNextSibling()) { @@ -232,6 +232,19 @@ void syntax::Node::assertInvariants() const { assert(!C->isDetached()); assert(C->getParent() == T); } + + const auto *L = dyn_cast(T); + if (!L) +return; + for (const auto *C = T->getFirstChild(); C; C = C->getNextSibling()) { +assert(C->getRole() == NodeRole::ListElement || + C->getRole() == NodeRole::ListDelimiter); +if (C->getRole() == NodeRole::ListDelimiter) { + assert(isa(C)); + assert(cast(C)->getToken()->kind() == L->getDelimiterTokenKind()); +} + } + #endif } @@ -273,7 +286,7 @@ syntax::Node *syntax::Tree::findChild(NodeRole R) { return nullptr; } -bool classof(const syntax::Node *N) { +bool syntax::List::classof(const syntax::Node *N) { switch (N->getKind()) { case syntax::NodeKind::NestedNameSpecifier: case syntax::NodeKind::CallArguments: @@ -372,7 +385,7 @@ std::vector syntax::List::getElementsAsNodes() { return children; } -clang::tok::TokenKind syntax::List::getDelimiterTokenKind() { +clang::tok::TokenKind syntax::List::getDelimiterTokenKind() const { switch (this->getKind()) { case NodeKind::NestedNameSpecifier: return clang::tok::coloncolon; @@ -385,7 +398,7 @@ clang::tok::TokenKind syntax::List::getDelimiterTokenKind() { } } -syntax::List::TerminationKind syntax::List::getTerminationKind() { +syntax::List::TerminationKind syntax::List::getTerminationKind() const { switch (this->getKind()) { case NodeKind::NestedNameSpecifier: return TerminationKind::Terminated; @@ -398,7 +411,7 @@ syntax::List::TerminationKind syntax::List::getTerminationKind() { } } -bool syntax::List::canBeEmpty() { +bool syntax::List::canBeEmpty() const { switch (this->getKind()) { case NodeKind::NestedNameSpecifier: return false; ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 1e19165 - [SyntaxTree][Synthesis] Fix allocation in `createTree` for more general use
Author: Eduardo Caldas Date: 2020-09-17T16:09:35Z New Revision: 1e19165bd89db6671a80e0b25b32d5c7ae79455c URL: https://github.com/llvm/llvm-project/commit/1e19165bd89db6671a80e0b25b32d5c7ae79455c DIFF: https://github.com/llvm/llvm-project/commit/1e19165bd89db6671a80e0b25b32d5c7ae79455c.diff LOG: [SyntaxTree][Synthesis] Fix allocation in `createTree` for more general use Prior to this change `createTree` could not create arbitrary syntax trees. Now it dispatches to the constructor of the concrete syntax tree according to the `NodeKind` passed as argument. This allows reuse inside the Synthesis API. # Please enter the commit message for your changes. Lines starting Differential Revision: https://reviews.llvm.org/D87820 Added: Modified: clang/include/clang/Tooling/Syntax/BuildTree.h clang/lib/Tooling/Syntax/Synthesis.cpp Removed: diff --git a/clang/include/clang/Tooling/Syntax/BuildTree.h b/clang/include/clang/Tooling/Syntax/BuildTree.h index b9405167bf99..452edf580ae1 100644 --- a/clang/include/clang/Tooling/Syntax/BuildTree.h +++ b/clang/include/clang/Tooling/Syntax/BuildTree.h @@ -35,13 +35,15 @@ syntax::Leaf *createLeaf(syntax::Arena &A, tok::TokenKind K, syntax::Leaf *createLeaf(syntax::Arena &A, tok::TokenKind K); // Synthesis of Trees +/// Creates the concrete syntax node according to the specified `NodeKind` `K`. +/// Returns it as a pointer to the base class `Tree`. syntax::Tree * -createTree(Arena &A, +createTree(syntax::Arena &A, std::vector> Children, syntax::NodeKind K); // Synthesis of Syntax Nodes -clang::syntax::EmptyStatement *createEmptyStatement(clang::syntax::Arena &A); +syntax::EmptyStatement *createEmptyStatement(syntax::Arena &A); } // namespace syntax } // namespace clang diff --git a/clang/lib/Tooling/Syntax/Synthesis.cpp b/clang/lib/Tooling/Syntax/Synthesis.cpp index 6de3d5b5752d..2fe95a40cb32 100644 --- a/clang/lib/Tooling/Syntax/Synthesis.cpp +++ b/clang/lib/Tooling/Syntax/Synthesis.cpp @@ -52,11 +52,144 @@ syntax::Leaf *clang::syntax::createLeaf(syntax::Arena &A, tok::TokenKind K) { return createLeaf(A, K, Spelling); } +namespace { +// Allocates the concrete syntax `Tree` according to its `NodeKind`. +syntax::Tree *allocateTree(syntax::Arena &A, syntax::NodeKind Kind) { + switch (Kind) { + case syntax::NodeKind::Leaf: +assert(false); + case syntax::NodeKind::TranslationUnit: +return new (A.getAllocator()) syntax::TranslationUnit; + case syntax::NodeKind::UnknownExpression: +return new (A.getAllocator()) syntax::UnknownExpression; + case syntax::NodeKind::ParenExpression: +return new (A.getAllocator()) syntax::ParenExpression; + case syntax::NodeKind::ThisExpression: +return new (A.getAllocator()) syntax::ThisExpression; + case syntax::NodeKind::IntegerLiteralExpression: +return new (A.getAllocator()) syntax::IntegerLiteralExpression; + case syntax::NodeKind::CharacterLiteralExpression: +return new (A.getAllocator()) syntax::CharacterLiteralExpression; + case syntax::NodeKind::FloatingLiteralExpression: +return new (A.getAllocator()) syntax::FloatingLiteralExpression; + case syntax::NodeKind::StringLiteralExpression: +return new (A.getAllocator()) syntax::StringLiteralExpression; + case syntax::NodeKind::BoolLiteralExpression: +return new (A.getAllocator()) syntax::BoolLiteralExpression; + case syntax::NodeKind::CxxNullPtrExpression: +return new (A.getAllocator()) syntax::CxxNullPtrExpression; + case syntax::NodeKind::IntegerUserDefinedLiteralExpression: +return new (A.getAllocator()) syntax::IntegerUserDefinedLiteralExpression; + case syntax::NodeKind::FloatUserDefinedLiteralExpression: +return new (A.getAllocator()) syntax::FloatUserDefinedLiteralExpression; + case syntax::NodeKind::CharUserDefinedLiteralExpression: +return new (A.getAllocator()) syntax::CharUserDefinedLiteralExpression; + case syntax::NodeKind::StringUserDefinedLiteralExpression: +return new (A.getAllocator()) syntax::StringUserDefinedLiteralExpression; + case syntax::NodeKind::PrefixUnaryOperatorExpression: +return new (A.getAllocator()) syntax::PrefixUnaryOperatorExpression; + case syntax::NodeKind::PostfixUnaryOperatorExpression: +return new (A.getAllocator()) syntax::PostfixUnaryOperatorExpression; + case syntax::NodeKind::BinaryOperatorExpression: +return new (A.getAllocator()) syntax::BinaryOperatorExpression; + case syntax::NodeKind::UnqualifiedId: +return new (A.getAllocator()) syntax::UnqualifiedId; + case syntax::NodeKind::IdExpression: +return new (A.getAllocator()) syntax::IdExpression; + case syntax::NodeKind::CallExpression: +return new (A.getAllocator()) syntax::CallExpression; + case syntax::NodeKind::UnknownStatement: +return new (A.getAllocator()) syntax::UnknownStatement; + case syntax::NodeKind::DeclarationStatement: +r
[clang] bb5b28f - [SyntaxTree][Synthesis] Improve testing `createLeaf`
Author: Eduardo Caldas Date: 2020-09-21T06:11:46Z New Revision: bb5b28f12fbd029773dc93d18a82ef42f4889b2a URL: https://github.com/llvm/llvm-project/commit/bb5b28f12fbd029773dc93d18a82ef42f4889b2a DIFF: https://github.com/llvm/llvm-project/commit/bb5b28f12fbd029773dc93d18a82ef42f4889b2a.diff LOG: [SyntaxTree][Synthesis] Improve testing `createLeaf` The new test shows that `createLeaf` depends on the C++ version. Differential Revision: https://reviews.llvm.org/D87896 Added: Modified: clang/unittests/Tooling/Syntax/SynthesisTest.cpp Removed: diff --git a/clang/unittests/Tooling/Syntax/SynthesisTest.cpp b/clang/unittests/Tooling/Syntax/SynthesisTest.cpp index a882714ccf33..8d9fb706eac3 100644 --- a/clang/unittests/Tooling/Syntax/SynthesisTest.cpp +++ b/clang/unittests/Tooling/Syntax/SynthesisTest.cpp @@ -51,6 +51,19 @@ TEST_P(SynthesisTest, Leaf_Punctuation) { )txt")); } +TEST_P(SynthesisTest, Leaf_Punctuation_CXX) { + if (!GetParam().isCXX()) +return; + + buildTree("", GetParam()); + + auto *Leaf = createLeaf(*Arena, tok::coloncolon); + + EXPECT_TRUE(treeDumpEqual(Leaf, R"txt( +'::' Detached synthesized + )txt")); +} + TEST_P(SynthesisTest, Leaf_Keyword) { buildTree("", GetParam()); @@ -61,6 +74,19 @@ TEST_P(SynthesisTest, Leaf_Keyword) { )txt")); } +TEST_P(SynthesisTest, Leaf_Keyword_CXX11) { + if (!GetParam().isCXX11OrLater()) +return; + + buildTree("", GetParam()); + + auto *Leaf = createLeaf(*Arena, tok::kw_nullptr); + + EXPECT_TRUE(treeDumpEqual(Leaf, R"txt( +'nullptr' Detached synthesized + )txt")); +} + TEST_P(SynthesisTest, Leaf_Identifier) { buildTree("", GetParam()); ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] e616a42 - [SyntaxTree] Test for '\' inside token.
Author: Eduardo Caldas Date: 2020-09-21T06:56:14Z New Revision: e616a4259889b55ed1bf5bf095f0e59658c6e311 URL: https://github.com/llvm/llvm-project/commit/e616a4259889b55ed1bf5bf095f0e59658c6e311 DIFF: https://github.com/llvm/llvm-project/commit/e616a4259889b55ed1bf5bf095f0e59658c6e311.diff LOG: [SyntaxTree] Test for '\' inside token. Differential Revision: https://reviews.llvm.org/D87895 Added: Modified: clang/unittests/Tooling/Syntax/BuildTreeTest.cpp Removed: diff --git a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp index 95ebeb2c5940..52bd5988b44e 100644 --- a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp @@ -167,6 +167,23 @@ TranslationUnit Detached )txt")); } +TEST_P(BuildSyntaxTreeTest, Simple_BackslashInsideToken) { + EXPECT_TRUE(treeDumpEqual( + R"cpp( +in\ +t a; +)cpp", + R"txt( +TranslationUnit Detached +`-SimpleDeclaration + |-'in\ +t' + |-SimpleDeclarator Declarator + | `-'a' + `-';' +)txt")); +} + TEST_P(BuildSyntaxTreeTest, If) { EXPECT_TRUE(treeDumpEqualOnAnnotations( R"cpp( ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 4a5cc38 - [SyntaxTree][Synthesis] Implement `deepCopy`
Author: Eduardo Caldas Date: 2020-09-21T09:27:15Z New Revision: 4a5cc389c51d267f39286a9a8c58c32f758b9d4b URL: https://github.com/llvm/llvm-project/commit/4a5cc389c51d267f39286a9a8c58c32f758b9d4b DIFF: https://github.com/llvm/llvm-project/commit/4a5cc389c51d267f39286a9a8c58c32f758b9d4b.diff LOG: [SyntaxTree][Synthesis] Implement `deepCopy` Differential Revision: https://reviews.llvm.org/D87749 Added: Modified: clang/include/clang/Tooling/Syntax/BuildTree.h clang/lib/Tooling/Syntax/Synthesis.cpp clang/unittests/Tooling/Syntax/SynthesisTest.cpp Removed: diff --git a/clang/include/clang/Tooling/Syntax/BuildTree.h b/clang/include/clang/Tooling/Syntax/BuildTree.h index 452edf580ae1..7b36dff123f6 100644 --- a/clang/include/clang/Tooling/Syntax/BuildTree.h +++ b/clang/include/clang/Tooling/Syntax/BuildTree.h @@ -45,6 +45,17 @@ createTree(syntax::Arena &A, // Synthesis of Syntax Nodes syntax::EmptyStatement *createEmptyStatement(syntax::Arena &A); +/// Creates a completely independent copy of `N` (a deep copy). +/// +/// The copy is: +/// * Detached, i.e. `Parent == NextSibling == nullptr` and +/// `Role == Detached`. +/// * Synthesized, i.e. `Original == false`. +/// +/// `N` might be backed by source code but if any descendants of `N` are +/// unmodifiable returns `nullptr`. +syntax::Node *deepCopy(syntax::Arena &A, const syntax::Node *N); + } // namespace syntax } // namespace clang #endif diff --git a/clang/lib/Tooling/Syntax/Synthesis.cpp b/clang/lib/Tooling/Syntax/Synthesis.cpp index f171d26512d9..c8fcac27e0d5 100644 --- a/clang/lib/Tooling/Syntax/Synthesis.cpp +++ b/clang/lib/Tooling/Syntax/Synthesis.cpp @@ -28,10 +28,12 @@ class clang::syntax::FactoryImpl { } }; +// FIXME: `createLeaf` is based on `syntax::tokenize` internally, as such it +// doesn't support digraphs or line continuations. syntax::Leaf *clang::syntax::createLeaf(syntax::Arena &A, tok::TokenKind K, StringRef Spelling) { auto Tokens = - FactoryImpl::lexBuffer(A, llvm::MemoryBuffer::getMemBuffer(Spelling)) + FactoryImpl::lexBuffer(A, llvm::MemoryBuffer::getMemBufferCopy(Spelling)) .second; assert(Tokens.size() == 1); assert(Tokens.front().kind() == K && @@ -192,14 +194,52 @@ syntax::Tree *clang::syntax::createTree( syntax::NodeKind K) { auto *T = allocateTree(A, K); FactoryImpl::setCanModify(T); - for (auto ChildIt = Children.rbegin(); ChildIt != Children.rend(); - std::advance(ChildIt, 1)) + for (auto ChildIt = Children.rbegin(); ChildIt != Children.rend(); ++ChildIt) FactoryImpl::prependChildLowLevel(T, ChildIt->first, ChildIt->second); T->assertInvariants(); return T; } +namespace { +bool canModifyAllDescendants(const syntax::Node *N) { + if (const auto *L = dyn_cast(N)) +return L->canModify(); + + const auto *T = cast(N); + + if (!T->canModify()) +return false; + for (const auto *Child = T->getFirstChild(); Child; + Child = Child->getNextSibling()) +if (!canModifyAllDescendants(Child)) + return false; + + return true; +} + +syntax::Node *deepCopyImpl(syntax::Arena &A, const syntax::Node *N) { + if (const auto *L = dyn_cast(N)) +return createLeaf(A, L->getToken()->kind(), + L->getToken()->text(A.getSourceManager())); + + const auto *T = cast(N); + std::vector> Children; + for (const auto *Child = T->getFirstChild(); Child; + Child = Child->getNextSibling()) +Children.push_back({deepCopyImpl(A, Child), Child->getRole()}); + + return createTree(A, Children, N->getKind()); +} +} // namespace + +syntax::Node *clang::syntax::deepCopy(syntax::Arena &A, const Node *N) { + if (!canModifyAllDescendants(N)) +return nullptr; + + return deepCopyImpl(A, N); +} + syntax::EmptyStatement *clang::syntax::createEmptyStatement(syntax::Arena &A) { return cast( createTree(A, {{createLeaf(A, tok::semi), NodeRole::Unknown}}, diff --git a/clang/unittests/Tooling/Syntax/SynthesisTest.cpp b/clang/unittests/Tooling/Syntax/SynthesisTest.cpp index 8d9fb706eac3..2af1fcf8f317 100644 --- a/clang/unittests/Tooling/Syntax/SynthesisTest.cpp +++ b/clang/unittests/Tooling/Syntax/SynthesisTest.cpp @@ -163,6 +163,63 @@ BinaryOperatorExpression Detached synthesized )txt")); } +TEST_P(SynthesisTest, DeepCopy_Synthesized) { + buildTree("", GetParam()); + + auto *LeafContinue = createLeaf(*Arena, tok::kw_continue); + auto *LeafSemiColon = createLeaf(*Arena, tok::semi); + auto *StatementContinue = createTree(*Arena, + {{LeafContinue, NodeRole::LiteralToken}, +{LeafSemiColon, NodeRole::Unknown}}, + NodeKind::ContinueStatement); + + auto *Copy = deepCopy(*Arena, StatementContinue); + EXPECT_TRUE( + treeDumpEqual(Copy, StatementCont
[clang] 87f0b51 - [SyntaxTree][NFC] follow naming convention + remove auto on empty vector declaration
Author: Eduardo Caldas Date: 2020-09-21T11:45:15Z New Revision: 87f0b51d68de40e7106be89d934b5191d983e3d5 URL: https://github.com/llvm/llvm-project/commit/87f0b51d68de40e7106be89d934b5191d983e3d5 DIFF: https://github.com/llvm/llvm-project/commit/87f0b51d68de40e7106be89d934b5191d983e3d5.diff LOG: [SyntaxTree][NFC] follow naming convention + remove auto on empty vector declaration Differential Revision: https://reviews.llvm.org/D88004 Added: Modified: clang/lib/Tooling/Syntax/BuildTree.cpp clang/lib/Tooling/Syntax/Nodes.cpp clang/lib/Tooling/Syntax/Tree.cpp Removed: diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp index 3e0573ac4ffc..4d365090abf1 100644 --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -155,10 +155,10 @@ struct GetStartLoc : TypeLocVisitor { } // namespace static CallExpr::arg_range dropDefaultArgs(CallExpr::arg_range Args) { - auto firstDefaultArg = std::find_if(Args.begin(), Args.end(), [](auto it) { -return isa(it); + auto FirstDefaultArg = std::find_if(Args.begin(), Args.end(), [](auto It) { +return isa(It); }); - return llvm::make_range(Args.begin(), firstDefaultArg); + return llvm::make_range(Args.begin(), FirstDefaultArg); } static syntax::NodeKind getOperatorNodeKind(const CXXOperatorCallExpr &E) { @@ -954,12 +954,12 @@ class BuildTreeVisitor : public RecursiveASTVisitor { bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc QualifierLoc) { if (!QualifierLoc) return true; -for (auto it = QualifierLoc; it; it = it.getPrefix()) { - auto *NS = buildNameSpecifier(it); +for (auto It = QualifierLoc; It; It = It.getPrefix()) { + auto *NS = buildNameSpecifier(It); if (!NS) return false; Builder.markChild(NS, syntax::NodeRole::ListElement); - Builder.markChildToken(it.getEndLoc(), syntax::NodeRole::ListDelimiter); + Builder.markChildToken(It.getEndLoc(), syntax::NodeRole::ListDelimiter); } Builder.foldNode(Builder.getRange(QualifierLoc.getSourceRange()), new (allocator()) syntax::NestedNameSpecifier, diff --git a/clang/lib/Tooling/Syntax/Nodes.cpp b/clang/lib/Tooling/Syntax/Nodes.cpp index bb63585cbd7c..24b7a8596382 100644 --- a/clang/lib/Tooling/Syntax/Nodes.cpp +++ b/clang/lib/Tooling/Syntax/Nodes.cpp @@ -226,23 +226,23 @@ raw_ostream &syntax::operator<<(raw_ostream &OS, NodeRole R) { // vector std::vector syntax::NestedNameSpecifier::getSpecifiers() { - auto specifiersAsNodes = getElementsAsNodes(); + auto SpecifiersAsNodes = getElementsAsNodes(); std::vector Children; - for (const auto &element : specifiersAsNodes) { -Children.push_back(llvm::cast(element)); + for (const auto &Element : SpecifiersAsNodes) { +Children.push_back(llvm::cast(Element)); } return Children; } std::vector> syntax::NestedNameSpecifier::getSpecifiersAndDoubleColons() { - auto specifiersAsNodesAndDoubleColons = getElementsAsNodesAndDelimiters(); + auto SpecifiersAsNodesAndDoubleColons = getElementsAsNodesAndDelimiters(); std::vector> Children; - for (const auto &specifierAndDoubleColon : specifiersAsNodesAndDoubleColons) { + for (const auto &SpecifierAndDoubleColon : SpecifiersAsNodesAndDoubleColons) { Children.push_back( -{llvm::cast(specifierAndDoubleColon.element), - specifierAndDoubleColon.delimiter}); +{llvm::cast(SpecifierAndDoubleColon.element), + SpecifierAndDoubleColon.delimiter}); } return Children; } diff --git a/clang/lib/Tooling/Syntax/Tree.cpp b/clang/lib/Tooling/Syntax/Tree.cpp index 1edd2583105a..2c77e8f64944 100644 --- a/clang/lib/Tooling/Syntax/Tree.cpp +++ b/clang/lib/Tooling/Syntax/Tree.cpp @@ -153,7 +153,7 @@ static void dumpLeaf(raw_ostream &OS, const syntax::Leaf *L, static void dumpNode(raw_ostream &OS, const syntax::Node *N, const SourceManager &SM, std::vector IndentMask) { - auto dumpExtraInfo = [&OS](const syntax::Node *N) { + auto DumpExtraInfo = [&OS](const syntax::Node *N) { if (N->getRole() != syntax::NodeRole::Unknown) OS << " " << N->getRole(); if (!N->isOriginal()) @@ -167,14 +167,14 @@ static void dumpNode(raw_ostream &OS, const syntax::Node *N, OS << "'"; dumpLeaf(OS, L, SM); OS << "'"; -dumpExtraInfo(N); +DumpExtraInfo(N); OS << "\n"; return; } const auto *T = cast(N); OS << T->getKind(); - dumpExtraInfo(N); + DumpExtraInfo(N); OS << "\n"; for (const auto *It = T->getFirstChild(); It; It = It->getNextSibling()) { @@ -302,20 +302,20 @@ syntax::List::getElementsAsNodesAndDelimiters() { if (!getFirstChild()) return {}; - auto children = std::vector>(); - syntax::Node *elementWithoutDelimiter = nullptr; + std::vector> Children; + syntax::Node *Elemen
[clang] af582c9 - [SyntaxTree] Test `findFirstLeaf` and `findLastLeaf`
Author: Eduardo Caldas Date: 2020-09-22T06:47:36Z New Revision: af582c9b0f3a09b6a1b5101fd30dcbcef5c188b0 URL: https://github.com/llvm/llvm-project/commit/af582c9b0f3a09b6a1b5101fd30dcbcef5c188b0 DIFF: https://github.com/llvm/llvm-project/commit/af582c9b0f3a09b6a1b5101fd30dcbcef5c188b0.diff LOG: [SyntaxTree] Test `findFirstLeaf` and `findLastLeaf` * Introduce `TreeTest.cpp` to unit test `Tree.h` * Add `generateAllTreesWithShape` to generating test cases * Add tests for `findFirstLeaf` and `findLastLeaf` * Fix implementations of `findFirstLeaf` and `findLastLeaf` that had been broken when empty `Tree` were present. Differential Revision: https://reviews.llvm.org/D87779 Added: clang/unittests/Tooling/Syntax/TreeTest.cpp Modified: clang/lib/Tooling/Syntax/Tree.cpp clang/unittests/Tooling/Syntax/CMakeLists.txt Removed: diff --git a/clang/lib/Tooling/Syntax/Tree.cpp b/clang/lib/Tooling/Syntax/Tree.cpp index 2c77e8f64944..b558e7ab9a1b 100644 --- a/clang/lib/Tooling/Syntax/Tree.cpp +++ b/clang/lib/Tooling/Syntax/Tree.cpp @@ -255,27 +255,24 @@ void syntax::Node::assertInvariantsRecursive() const { } syntax::Leaf *syntax::Tree::findFirstLeaf() { - auto *T = this; - while (auto *C = T->getFirstChild()) { + for (auto *C = getFirstChild(); C; C = C->getNextSibling()) { if (auto *L = dyn_cast(C)) return L; -T = cast(C); +if (auto *L = cast(C)->findFirstLeaf()) + return L; } return nullptr; } syntax::Leaf *syntax::Tree::findLastLeaf() { - auto *T = this; - while (auto *C = T->getFirstChild()) { -// Find the last child. -while (auto *Next = C->getNextSibling()) - C = Next; - + syntax::Leaf *Last = nullptr; + for (auto *C = getFirstChild(); C; C = C->getNextSibling()) { if (auto *L = dyn_cast(C)) - return L; -T = cast(C); + Last = L; +else if (auto *L = cast(C)->findLastLeaf()) + Last = L; } - return nullptr; + return Last; } syntax::Node *syntax::Tree::findChild(NodeRole R) { diff --git a/clang/unittests/Tooling/Syntax/CMakeLists.txt b/clang/unittests/Tooling/Syntax/CMakeLists.txt index 34a480503def..174f3e7bf573 100644 --- a/clang/unittests/Tooling/Syntax/CMakeLists.txt +++ b/clang/unittests/Tooling/Syntax/CMakeLists.txt @@ -7,6 +7,7 @@ add_clang_unittest(SyntaxTests BuildTreeTest.cpp MutationsTest.cpp SynthesisTest.cpp + TreeTest.cpp TokensTest.cpp ) diff --git a/clang/unittests/Tooling/Syntax/TreeTest.cpp b/clang/unittests/Tooling/Syntax/TreeTest.cpp new file mode 100644 index ..2448db36a465 --- /dev/null +++ b/clang/unittests/Tooling/Syntax/TreeTest.cpp @@ -0,0 +1,125 @@ +//===- TreeTest.cpp -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "clang/Tooling/Syntax/Tree.h" +#include "TreeTestBase.h" +#include "clang/Tooling/Syntax/BuildTree.h" +#include "gtest/gtest.h" + +using namespace clang; +using namespace clang::syntax; + +namespace { + +class TreeTest : public SyntaxTreeTest { +private: + Tree *createTree(ArrayRef Children) { +std::vector> ChildrenWithRoles; +ChildrenWithRoles.reserve(Children.size()); +for (const auto *Child : Children) { + ChildrenWithRoles.push_back( + std::make_pair(deepCopy(*Arena, Child), NodeRole::Unknown)); +} +return clang::syntax::createTree(*Arena, ChildrenWithRoles, + NodeKind::UnknownExpression); + } + + // Generate Forests by combining `Children` into `ParentCount` Trees. + // + // We do this recursively. + std::vector> + generateAllForests(ArrayRef Children, unsigned ParentCount) { +assert(ParentCount > 0); +// If there is only one Parent node, then combine `Children` under +// this Parent. +if (ParentCount == 1) + return {{createTree(Children)}}; + +// Otherwise, combine `ChildrenCount` children under the last parent and +// solve the smaller problem without these children and this parent. Do this +// for every `ChildrenCount` and combine the results. +std::vector> AllForests; +for (unsigned ChildrenCount = 0; ChildrenCount <= Children.size(); + ++ChildrenCount) { + auto *LastParent = createTree(Children.take_back(ChildrenCount)); + for (auto &Forest : generateAllForests(Children.drop_back(ChildrenCount), + ParentCount - 1)) { +Forest.push_back(LastParent); +AllForests.push_back(Forest); + } +} +return AllForests; + } + +protected: + // Generates all trees with a `Base` of `Node`s and `NodeCountPerLayer` + // `Node`s pe
[clang] 1dc7836 - [SyntaxTree][Nit] Take `ArrayRef` instead of `std::vector` as argument for `createTree`
Author: Eduardo Caldas Date: 2020-09-22T06:47:36Z New Revision: 1dc7836aed134b4543bad6aa54f15cc0e51a627f URL: https://github.com/llvm/llvm-project/commit/1dc7836aed134b4543bad6aa54f15cc0e51a627f DIFF: https://github.com/llvm/llvm-project/commit/1dc7836aed134b4543bad6aa54f15cc0e51a627f.diff LOG: [SyntaxTree][Nit] Take `ArrayRef` instead of `std::vector` as argument for `createTree` I also assured that there are no other functions unnecessarily using std::vector as argument. Differential Revision: https://reviews.llvm.org/D88024 Added: Modified: clang/include/clang/Tooling/Syntax/BuildTree.h clang/lib/Tooling/Syntax/Synthesis.cpp Removed: diff --git a/clang/include/clang/Tooling/Syntax/BuildTree.h b/clang/include/clang/Tooling/Syntax/BuildTree.h index 7b36dff123f6..ab4868747e69 100644 --- a/clang/include/clang/Tooling/Syntax/BuildTree.h +++ b/clang/include/clang/Tooling/Syntax/BuildTree.h @@ -39,7 +39,7 @@ syntax::Leaf *createLeaf(syntax::Arena &A, tok::TokenKind K); /// Returns it as a pointer to the base class `Tree`. syntax::Tree * createTree(syntax::Arena &A, - std::vector> Children, + ArrayRef> Children, syntax::NodeKind K); // Synthesis of Syntax Nodes diff --git a/clang/lib/Tooling/Syntax/Synthesis.cpp b/clang/lib/Tooling/Syntax/Synthesis.cpp index c8fcac27e0d5..9dc83f966d8c 100644 --- a/clang/lib/Tooling/Syntax/Synthesis.cpp +++ b/clang/lib/Tooling/Syntax/Synthesis.cpp @@ -190,7 +190,7 @@ syntax::Tree *allocateTree(syntax::Arena &A, syntax::NodeKind Kind) { syntax::Tree *clang::syntax::createTree( syntax::Arena &A, -std::vector> Children, +ArrayRef> Children, syntax::NodeKind K) { auto *T = allocateTree(A, K); FactoryImpl::setCanModify(T); ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 66bcb14 - [SyntaxTree][Synthesis] Fix: `deepCopy` -> `deepCopyExpandingMacros`.
Author: Eduardo Caldas Date: 2020-09-22T09:15:21Z New Revision: 66bcb14312a08b5d7e1197d23d748b2e23c4d852 URL: https://github.com/llvm/llvm-project/commit/66bcb14312a08b5d7e1197d23d748b2e23c4d852 DIFF: https://github.com/llvm/llvm-project/commit/66bcb14312a08b5d7e1197d23d748b2e23c4d852.diff LOG: [SyntaxTree][Synthesis] Fix: `deepCopy` -> `deepCopyExpandingMacros`. There can be Macros that are tagged with `modifiable`. Thus verifying `canModifyAllDescendants` is not sufficient to avoid macros when deep copying. We think the `TokenBuffer` could inform us whether a `Token` comes from a macro. We'll look into that when we can surface this information easily, for instance in unit tests for `ComputeReplacements`. Differential Revision: https://reviews.llvm.org/D88034 Added: Modified: clang/include/clang/Tooling/Syntax/BuildTree.h clang/lib/Tooling/Syntax/Synthesis.cpp clang/unittests/Tooling/Syntax/SynthesisTest.cpp clang/unittests/Tooling/Syntax/TreeTest.cpp Removed: diff --git a/clang/include/clang/Tooling/Syntax/BuildTree.h b/clang/include/clang/Tooling/Syntax/BuildTree.h index ab4868747e69..537ade4b7151 100644 --- a/clang/include/clang/Tooling/Syntax/BuildTree.h +++ b/clang/include/clang/Tooling/Syntax/BuildTree.h @@ -45,17 +45,13 @@ createTree(syntax::Arena &A, // Synthesis of Syntax Nodes syntax::EmptyStatement *createEmptyStatement(syntax::Arena &A); -/// Creates a completely independent copy of `N` (a deep copy). +/// Creates a completely independent copy of `N` with its macros expanded. /// /// The copy is: /// * Detached, i.e. `Parent == NextSibling == nullptr` and /// `Role == Detached`. /// * Synthesized, i.e. `Original == false`. -/// -/// `N` might be backed by source code but if any descendants of `N` are -/// unmodifiable returns `nullptr`. -syntax::Node *deepCopy(syntax::Arena &A, const syntax::Node *N); - +syntax::Node *deepCopyExpandingMacros(syntax::Arena &A, const syntax::Node *N); } // namespace syntax } // namespace clang #endif diff --git a/clang/lib/Tooling/Syntax/Synthesis.cpp b/clang/lib/Tooling/Syntax/Synthesis.cpp index 9dc83f966d8c..e197c8d35bde 100644 --- a/clang/lib/Tooling/Syntax/Synthesis.cpp +++ b/clang/lib/Tooling/Syntax/Synthesis.cpp @@ -201,25 +201,11 @@ syntax::Tree *clang::syntax::createTree( return T; } -namespace { -bool canModifyAllDescendants(const syntax::Node *N) { - if (const auto *L = dyn_cast(N)) -return L->canModify(); - - const auto *T = cast(N); - - if (!T->canModify()) -return false; - for (const auto *Child = T->getFirstChild(); Child; - Child = Child->getNextSibling()) -if (!canModifyAllDescendants(Child)) - return false; - - return true; -} - -syntax::Node *deepCopyImpl(syntax::Arena &A, const syntax::Node *N) { +syntax::Node *clang::syntax::deepCopyExpandingMacros(syntax::Arena &A, + const syntax::Node *N) { if (const auto *L = dyn_cast(N)) +// `L->getToken()` gives us the expanded token, thus we implicitly expand +// any macros here. return createLeaf(A, L->getToken()->kind(), L->getToken()->text(A.getSourceManager())); @@ -227,18 +213,10 @@ syntax::Node *deepCopyImpl(syntax::Arena &A, const syntax::Node *N) { std::vector> Children; for (const auto *Child = T->getFirstChild(); Child; Child = Child->getNextSibling()) -Children.push_back({deepCopyImpl(A, Child), Child->getRole()}); +Children.push_back({deepCopyExpandingMacros(A, Child), Child->getRole()}); return createTree(A, Children, N->getKind()); } -} // namespace - -syntax::Node *clang::syntax::deepCopy(syntax::Arena &A, const Node *N) { - if (!canModifyAllDescendants(N)) -return nullptr; - - return deepCopyImpl(A, N); -} syntax::EmptyStatement *clang::syntax::createEmptyStatement(syntax::Arena &A) { return cast( diff --git a/clang/unittests/Tooling/Syntax/SynthesisTest.cpp b/clang/unittests/Tooling/Syntax/SynthesisTest.cpp index 2af1fcf8f317..7f67b4e2e203 100644 --- a/clang/unittests/Tooling/Syntax/SynthesisTest.cpp +++ b/clang/unittests/Tooling/Syntax/SynthesisTest.cpp @@ -173,7 +173,7 @@ TEST_P(SynthesisTest, DeepCopy_Synthesized) { {LeafSemiColon, NodeRole::Unknown}}, NodeKind::ContinueStatement); - auto *Copy = deepCopy(*Arena, StatementContinue); + auto *Copy = deepCopyExpandingMacros(*Arena, StatementContinue); EXPECT_TRUE( treeDumpEqual(Copy, StatementContinue->dump(Arena->getSourceManager(; // FIXME: Test that copy is independent of original, once the Mutations API is @@ -183,7 +183,7 @@ TEST_P(SynthesisTest, DeepCopy_Synthesized) { TEST_P(SynthesisTest, DeepCopy_Original) { auto *OriginalTree = buildTree("int a;", GetParam()); - auto *Copy = deepCopy(*Arena, OriginalTree); + aut
[clang] 6dc06fa - [SyntaxTree] Add tests for the assignment of the `canModify` tag.
Author: Eduardo Caldas Date: 2020-09-22T13:17:33Z New Revision: 6dc06fa09d1a259df1f897dc821ba1544e2bcd24 URL: https://github.com/llvm/llvm-project/commit/6dc06fa09d1a259df1f897dc821ba1544e2bcd24 DIFF: https://github.com/llvm/llvm-project/commit/6dc06fa09d1a259df1f897dc821ba1544e2bcd24.diff LOG: [SyntaxTree] Add tests for the assignment of the `canModify` tag. Differential Revision: https://reviews.llvm.org/D88077 Added: Modified: clang/unittests/Tooling/Syntax/BuildTreeTest.cpp Removed: diff --git a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp index 52bd5988b44ec..ecb4a7ce73a50 100644 --- a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp @@ -3855,8 +3855,76 @@ TranslationUnit Detached )txt")); } -TEST_P(BuildSyntaxTreeTest, NonModifiableNodes) { - // Some nodes are non-modifiable, they are marked with 'I:'. +TEST_P(BuildSyntaxTreeTest, Macro_ObjectLike_Leaf) { + // All nodes can be mutated. + EXPECT_TRUE(treeDumpEqual( + R"cpp( +#define OPEN { +#define CLOSE } + +void test() { + OPEN +1; + CLOSE + + OPEN +2; + } +} +)cpp", + R"txt( +TranslationUnit Detached +`-SimpleDeclaration + |-'void' + |-SimpleDeclarator Declarator + | |-'test' + | `-ParametersAndQualifiers + | |-'(' OpenParen + | `-')' CloseParen + `-CompoundStatement +|-'{' OpenParen +|-CompoundStatement Statement +| |-'{' OpenParen +| |-ExpressionStatement Statement +| | |-IntegerLiteralExpression Expression +| | | `-'1' LiteralToken +| | `-';' +| `-'}' CloseParen +|-CompoundStatement Statement +| |-'{' OpenParen +| |-ExpressionStatement Statement +| | |-IntegerLiteralExpression Expression +| | | `-'2' LiteralToken +| | `-';' +| `-'}' CloseParen +`-'}' CloseParen +)txt")); +} + +TEST_P(BuildSyntaxTreeTest, Macro_ObjectLike_MatchTree) { + // Some nodes are unmodifiable, they are marked with 'unmodifiable'. + EXPECT_TRUE(treeDumpEqual( + R"cpp( +#define BRACES {} + +void test() BRACES +)cpp", + R"txt( +TranslationUnit Detached +`-SimpleDeclaration + |-'void' + |-SimpleDeclarator Declarator + | |-'test' + | `-ParametersAndQualifiers + | |-'(' OpenParen + | `-')' CloseParen + `-CompoundStatement +|-'{' OpenParen unmodifiable +`-'}' CloseParen unmodifiable +)txt")); +} + +TEST_P(BuildSyntaxTreeTest, Macro_ObjectLike_MismatchTree) { EXPECT_TRUE(treeDumpEqual( R"cpp( #define HALF_IF if (1+ @@ -3896,21 +3964,16 @@ TranslationUnit Detached )txt")); } -TEST_P(BuildSyntaxTreeTest, ModifiableNodes) { - // All nodes can be mutated. +TEST_P(BuildSyntaxTreeTest, Macro_FunctionLike_ModifiableArguments) { + // FIXME: Note that the substitutions for `X` and `Y` are marked modifiable. + // However we cannot change `X` freely. Indeed if we change its substitution + // in the condition we should also change it the then-branch. EXPECT_TRUE(treeDumpEqual( R"cpp( -#define OPEN { -#define CLOSE } +#define MIN(X,Y) X < Y ? X : Y void test() { - OPEN -1; - CLOSE - - OPEN -2; - } + MIN(1,2); } )cpp", R"txt( @@ -3924,24 +3987,109 @@ TranslationUnit Detached | `-')' CloseParen `-CompoundStatement |-'{' OpenParen -|-CompoundStatement Statement -| |-'{' OpenParen -| |-ExpressionStatement Statement -| | |-IntegerLiteralExpression Expression +|-ExpressionStatement Statement +| |-UnknownExpression Expression +| | |-BinaryOperatorExpression unmodifiable +| | | |-IntegerLiteralExpression LeftHandSide +| | | | `-'1' LiteralToken +| | | |-'<' OperatorToken unmodifiable +| | | `-IntegerLiteralExpression RightHandSide +| | | `-'2' LiteralToken +| | |-'?' unmodifiable +| | |-IntegerLiteralExpression | | | `-'1' LiteralToken -| | `-';' -| `-'}' CloseParen -|-CompoundStatement Statement -| |-'{' OpenParen -| |-ExpressionStatement Statement -| | |-IntegerLiteralExpression Expression -| | | `-'2' LiteralToken -| | `-';' -| `-'}' CloseParen +| | |-':' unmodifiable +| | `-IntegerLiteralExpression +| | `-'2' LiteralToken +| `-';' `-'}' CloseParen )txt")); } +TEST_P(BuildSyntaxTreeTest, Macro_FunctionLike_MismatchTree) { + EXPECT_TRUE(treeDumpEqual( + R"cpp( +#define HALF_IF(X) if (X && +#define HALF_IF_2(Y) Y) {} +void test() { + HALF_IF(1) HALF_IF_2(0) else {} +})cpp", + R"txt( +TranslationUnit Detached +`-SimpleDeclaration + |-'void' + |-SimpleDeclarator Declarator + | |-'test' + | `-ParametersAndQualifiers + | |-'(' OpenParen + | `-')' CloseParen + `-CompoundStatement +|-'{' OpenParen +|-IfStatement Statement +| |-'if' IntroducerKeyword unmodifiable +| |-'(' unmodifiable +| |-BinaryOperatorExpression unmodifiabl
[clang] c3c08bf - [SyntaxTree] Test the List API
Author: Eduardo Caldas Date: 2020-09-22T17:07:41Z New Revision: c3c08bfdfd6244e0429753ee56df39c90187d772 URL: https://github.com/llvm/llvm-project/commit/c3c08bfdfd6244e0429753ee56df39c90187d772 DIFF: https://github.com/llvm/llvm-project/commit/c3c08bfdfd6244e0429753ee56df39c90187d772.diff LOG: [SyntaxTree] Test the List API Differential Revision: https://reviews.llvm.org/D87839 Added: Modified: clang/include/clang/Tooling/Syntax/Tree.h clang/unittests/Tooling/Syntax/TreeTest.cpp Removed: diff --git a/clang/include/clang/Tooling/Syntax/Tree.h b/clang/include/clang/Tooling/Syntax/Tree.h index a544fc1827b7..5840a86199eb 100644 --- a/clang/include/clang/Tooling/Syntax/Tree.h +++ b/clang/include/clang/Tooling/Syntax/Tree.h @@ -218,12 +218,16 @@ class List : public Tree { /// and delimiters are represented as null pointers. /// /// For example, in a separated list: - /// "a, b, c" <=> [("a", ","), ("b", ","), ("c", null)] - /// "a, , c" <=> [("a", ","), (null, ","), ("c", ",)] - /// "a, b," <=> [("a", ","), ("b", ","), (null, null)] + /// "a, b, c" <=> [("a" , ","), ("b" , "," ), ("c" , null)] + /// "a, , c" <=> [("a" , ","), (null, "," ), ("c" , null)] + /// "a, b c" <=> [("a" , ","), ("b" , null), ("c" , null)] + /// "a, b,"<=> [("a" , ","), ("b" , "," ), (null, null)] /// /// In a terminated or maybe-terminated list: - /// "a, b," <=> [("a", ","), ("b", ",")] + /// "a; b; c;" <=> [("a" , ";"), ("b" , ";" ), ("c" , ";" )] + /// "a; ; c;" <=> [("a" , ";"), (null, ";" ), ("c" , ";" )] + /// "a; b c;" <=> [("a" , ";"), ("b" , null), ("c" , ";" )] + /// "a; b; c" <=> [("a" , ";"), ("b" , ";" ), ("c" , null)] std::vector> getElementsAsNodesAndDelimiters(); /// Returns the elements of the list. Missing elements are represented diff --git a/clang/unittests/Tooling/Syntax/TreeTest.cpp b/clang/unittests/Tooling/Syntax/TreeTest.cpp index 6e777b353b04..fba3164e5966 100644 --- a/clang/unittests/Tooling/Syntax/TreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/TreeTest.cpp @@ -9,6 +9,8 @@ #include "clang/Tooling/Syntax/Tree.h" #include "TreeTestBase.h" #include "clang/Tooling/Syntax/BuildTree.h" +#include "clang/Tooling/Syntax/Nodes.h" +#include "llvm/ADT/STLExtras.h" #include "gtest/gtest.h" using namespace clang; @@ -122,4 +124,231 @@ TEST_P(TreeTest, LastLeaf) { } } +class ListTest : public SyntaxTreeTest { +private: + std::string dumpQuotedTokensOrNull(const Node *N) { +return N ? "'" + + StringRef(N->dumpTokens(Arena->getSourceManager())) + .trim() + .str() + + "'" + : "null"; + } + +protected: + std::string + dumpElementsAndDelimiters(ArrayRef> EDs) { +std::string Storage; +llvm::raw_string_ostream OS(Storage); + +OS << "["; + +llvm::interleaveComma( +EDs, OS, [&OS, this](const List::ElementAndDelimiter &ED) { + OS << "(" << dumpQuotedTokensOrNull(ED.element) << ", " + << dumpQuotedTokensOrNull(ED.delimiter) << ")"; +}); + +OS << "]"; + +return OS.str(); + } + + std::string dumpNodes(ArrayRef Nodes) { +std::string Storage; +llvm::raw_string_ostream OS(Storage); + +OS << "["; + +llvm::interleaveComma(Nodes, OS, [&OS, this](const Node *N) { + OS << dumpQuotedTokensOrNull(N); +}); + +OS << "]"; + +return OS.str(); + } +}; + +INSTANTIATE_TEST_CASE_P(TreeTests, ListTest, +::testing::ValuesIn(allTestClangConfigs()), ); + +/// "a, b, c" <=> [("a", ","), ("b", ","), ("c", null)] +TEST_P(ListTest, List_Separated_WellFormed) { + buildTree("", GetParam()); + + // "a, b, c" + auto *List = dyn_cast(syntax::createTree( + *Arena, + { + {createLeaf(*Arena, tok::identifier, "a"), NodeRole::ListElement}, + {createLeaf(*Arena, tok::comma), NodeRole::ListDelimiter}, + {createLeaf(*Arena, tok::identifier, "b"), NodeRole::ListElement}, + {createLeaf(*Arena, tok::comma), NodeRole::ListDelimiter}, + {createLeaf(*Arena, tok::identifier, "c"), NodeRole::ListElement}, + }, + NodeKind::CallArguments)); + + EXPECT_EQ(dumpElementsAndDelimiters(List->getElementsAsNodesAndDelimiters()), +"[('a', ','), ('b', ','), ('c', null)]"); + EXPECT_EQ(dumpNodes(List->getElementsAsNodes()), "['a', 'b', 'c']"); +} + +/// "a, , c" <=> [("a", ","), (null, ","), ("c", null)] +TEST_P(ListTest, List_Separated_MissingElement) { + buildTree("", GetParam()); + + // "a, , c" + auto *List = dyn_cast(syntax::createTree( + *Arena, + { + {createLeaf(*Arena, tok::identifier, "a"), NodeRole::ListElement}, + {createLeaf(*Arena, tok::comma), NodeRole::ListDelimiter}, + {createLeaf(*Arena, tok::comma), NodeRole::ListDelimiter}, + {createLeaf(*Arena, tok::
[clang] ba32915 - [SyntaxTree] Add support for `MemberExpression`
Author: Eduardo Caldas Date: 2020-08-20T14:57:35Z New Revision: ba32915db2ce78256115a9db7b07bb3806e6364a URL: https://github.com/llvm/llvm-project/commit/ba32915db2ce78256115a9db7b07bb3806e6364a DIFF: https://github.com/llvm/llvm-project/commit/ba32915db2ce78256115a9db7b07bb3806e6364a.diff LOG: [SyntaxTree] Add support for `MemberExpression` Differential Revision: https://reviews.llvm.org/D86227 Added: Modified: clang/include/clang/Tooling/Syntax/Nodes.h clang/lib/Tooling/Syntax/BuildTree.cpp clang/lib/Tooling/Syntax/Nodes.cpp clang/unittests/Tooling/Syntax/BuildTreeTest.cpp Removed: diff --git a/clang/include/clang/Tooling/Syntax/Nodes.h b/clang/include/clang/Tooling/Syntax/Nodes.h index 8e65fa1d8923..8b499bc5ceb9 100644 --- a/clang/include/clang/Tooling/Syntax/Nodes.h +++ b/clang/include/clang/Tooling/Syntax/Nodes.h @@ -55,6 +55,7 @@ enum class NodeKind : uint16_t { CharUserDefinedLiteralExpression, StringUserDefinedLiteralExpression, IdExpression, + MemberExpression, // Statements. UnknownStatement, @@ -173,7 +174,10 @@ enum class NodeRole : uint8_t { ParametersAndQualifiers_trailingReturn, IdExpression_id, IdExpression_qualifier, - ParenExpression_subExpression + ParenExpression_subExpression, + MemberExpression_object, + MemberExpression_accessToken, + MemberExpression_member, }; /// For debugging purposes. raw_ostream &operator<<(raw_ostream &OS, NodeRole R); @@ -322,6 +326,26 @@ class ParenExpression final : public Expression { Leaf *closeParen(); }; +/// Models a class member access. C++ [expr.ref] +/// member-expression: +/// expression -> template_opt id-expression +/// expression . template_opt id-expression +/// e.g. `x.a`, `xp->a` +/// +/// Note: An implicit member access inside a class, i.e. `a` instead of +/// `this->a`, is an `id-expression`. +class MemberExpression final : public Expression { +public: + MemberExpression() : Expression(NodeKind::MemberExpression) {} + static bool classof(const Node *N) { +return N->kind() == NodeKind::MemberExpression; + } + Expression *object(); + Leaf *accessToken(); + Leaf *templateKeyword(); + IdExpression *member(); +}; + /// Expression for literals. C++ [lex.literal] class LiteralExpression : public Expression { public: diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp index 11d399730040..a77149d66207 100644 --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -881,6 +881,49 @@ class BuildTreeVisitor : public RecursiveASTVisitor { return true; } + bool WalkUpFromMemberExpr(MemberExpr *S) { +if (auto QualifierLoc = S->getQualifierLoc()) + Builder.markChild(QualifierLoc, syntax::NodeRole::IdExpression_qualifier); + +auto TemplateKeywordLoc = S->getTemplateKeywordLoc(); +if (TemplateKeywordLoc.isValid()) + Builder.markChildToken(TemplateKeywordLoc, + syntax::NodeRole::TemplateKeyword); + +auto *TheUnqualifiedId = new (allocator()) syntax::UnqualifiedId; +Builder.foldNode(Builder.getRange(S->getMemberLoc(), S->getEndLoc()), + TheUnqualifiedId, nullptr); + +Builder.markChild(TheUnqualifiedId, syntax::NodeRole::IdExpression_id); + +auto *TheIdExpression = new (allocator()) syntax::IdExpression; +auto MemberRange = +Builder.getRange(S->hasQualifier() ? S->getQualifierLoc().getBeginLoc() + : S->getMemberLoc(), + S->getEndLoc()); + +// For `MemberExpr` with implicit `this->` we generate a simple +// `id-expression` syntax node, beacuse an implicit `member-expression` is +// syntactically undistinguishable from an `id-expression` +if (S->isImplicitAccess()) { + Builder.foldNode(MemberRange, TheIdExpression, S); + return true; +} +Builder.foldNode(MemberRange, TheIdExpression, nullptr); + +Builder.markChild(TheIdExpression, + syntax::NodeRole::MemberExpression_member); + +Builder.markExprChild(S->getBase(), + syntax::NodeRole::MemberExpression_object); +Builder.markChildToken(S->getOperatorLoc(), + syntax::NodeRole::MemberExpression_accessToken); + +Builder.foldNode(Builder.getExprRange(S), + new (allocator()) syntax::MemberExpression, S); +return true; + } + bool WalkUpFromDeclRefExpr(DeclRefExpr *S) { if (auto QualifierLoc = S->getQualifierLoc()) Builder.markChild(QualifierLoc, syntax::NodeRole::IdExpression_qualifier); diff --git a/clang/lib/Tooling/Syntax/Nodes.cpp b/clang/lib/Tooling/Syntax/Nodes.cpp index bf3c3108cb69..e09c8f20f210 100644 --- a/clang/lib/Tooling/Syntax/Nodes.cpp +++ b/clang/lib/Tooling/Syntax/Nodes.cpp @@ -126,6 +126,8 @@ raw_ostream &synt
[clang] a4ef9e8 - [SyntaxTree] Unify logic for generating `id-expression`
Author: Eduardo Caldas Date: 2020-08-20T14:57:35Z New Revision: a4ef9e8643e2f3f8972e19c5b25f4dd81ba03508 URL: https://github.com/llvm/llvm-project/commit/a4ef9e8643e2f3f8972e19c5b25f4dd81ba03508 DIFF: https://github.com/llvm/llvm-project/commit/a4ef9e8643e2f3f8972e19c5b25f4dd81ba03508.diff LOG: [SyntaxTree] Unify logic for generating `id-expression` Added: Modified: clang/lib/Tooling/Syntax/BuildTree.cpp Removed: diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp index a77149d66207..37d29a270463 100644 --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -881,35 +881,46 @@ class BuildTreeVisitor : public RecursiveASTVisitor { return true; } - bool WalkUpFromMemberExpr(MemberExpr *S) { -if (auto QualifierLoc = S->getQualifierLoc()) + syntax::IdExpression *buildIdExpression(NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKeywordLoc, + SourceRange UnqualifiedIdLoc, + ASTPtr From) { +if (QualifierLoc) { Builder.markChild(QualifierLoc, syntax::NodeRole::IdExpression_qualifier); - -auto TemplateKeywordLoc = S->getTemplateKeywordLoc(); -if (TemplateKeywordLoc.isValid()) - Builder.markChildToken(TemplateKeywordLoc, - syntax::NodeRole::TemplateKeyword); + if (TemplateKeywordLoc.isValid()) +Builder.markChildToken(TemplateKeywordLoc, + syntax::NodeRole::TemplateKeyword); +} auto *TheUnqualifiedId = new (allocator()) syntax::UnqualifiedId; -Builder.foldNode(Builder.getRange(S->getMemberLoc(), S->getEndLoc()), - TheUnqualifiedId, nullptr); - +Builder.foldNode(Builder.getRange(UnqualifiedIdLoc), TheUnqualifiedId, + nullptr); Builder.markChild(TheUnqualifiedId, syntax::NodeRole::IdExpression_id); +auto IdExpressionBeginLoc = +QualifierLoc ? QualifierLoc.getBeginLoc() : UnqualifiedIdLoc.getBegin(); + auto *TheIdExpression = new (allocator()) syntax::IdExpression; -auto MemberRange = -Builder.getRange(S->hasQualifier() ? S->getQualifierLoc().getBeginLoc() - : S->getMemberLoc(), - S->getEndLoc()); +Builder.foldNode( +Builder.getRange(IdExpressionBeginLoc, UnqualifiedIdLoc.getEnd()), +TheIdExpression, From); +return TheIdExpression; + } + + bool WalkUpFromMemberExpr(MemberExpr *S) { // For `MemberExpr` with implicit `this->` we generate a simple // `id-expression` syntax node, beacuse an implicit `member-expression` is // syntactically undistinguishable from an `id-expression` if (S->isImplicitAccess()) { - Builder.foldNode(MemberRange, TheIdExpression, S); + buildIdExpression(S->getQualifierLoc(), S->getTemplateKeywordLoc(), +SourceRange(S->getMemberLoc(), S->getEndLoc()), S); return true; } -Builder.foldNode(MemberRange, TheIdExpression, nullptr); + +auto *TheIdExpression = buildIdExpression( +S->getQualifierLoc(), S->getTemplateKeywordLoc(), +SourceRange(S->getMemberLoc(), S->getEndLoc()), nullptr); Builder.markChild(TheIdExpression, syntax::NodeRole::MemberExpression_member); @@ -925,45 +936,17 @@ class BuildTreeVisitor : public RecursiveASTVisitor { } bool WalkUpFromDeclRefExpr(DeclRefExpr *S) { -if (auto QualifierLoc = S->getQualifierLoc()) - Builder.markChild(QualifierLoc, syntax::NodeRole::IdExpression_qualifier); +buildIdExpression(S->getQualifierLoc(), S->getTemplateKeywordLoc(), + SourceRange(S->getLocation(), S->getEndLoc()), S); -auto TemplateKeywordLoc = S->getTemplateKeywordLoc(); -if (TemplateKeywordLoc.isValid()) - Builder.markChildToken(TemplateKeywordLoc, - syntax::NodeRole::TemplateKeyword); - -auto *unqualifiedId = new (allocator()) syntax::UnqualifiedId; - -Builder.foldNode(Builder.getRange(S->getLocation(), S->getEndLoc()), - unqualifiedId, nullptr); - -Builder.markChild(unqualifiedId, syntax::NodeRole::IdExpression_id); - -Builder.foldNode(Builder.getExprRange(S), - new (allocator()) syntax::IdExpression, S); return true; } // Same logic as DeclRefExpr. bool WalkUpFromDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *S) { -if (auto QualifierLoc = S->getQualifierLoc()) - Builder.markChild(QualifierLoc, syntax::NodeRole::IdExpression_qualifier); +buildIdExpression(S->getQualifierLoc(), S->getTemplateKeywordLoc(), + SourceRange(S->getLocation(), S->getEndLoc()), S); -
[clang] e4e983e - [SyntaxTree] Split tests related to Namespace
Author: Eduardo Caldas Date: 2020-08-20T15:14:56Z New Revision: e4e983e240430b3a0dc92402cc940292bd0d263f URL: https://github.com/llvm/llvm-project/commit/e4e983e240430b3a0dc92402cc940292bd0d263f DIFF: https://github.com/llvm/llvm-project/commit/e4e983e240430b3a0dc92402cc940292bd0d263f.diff LOG: [SyntaxTree] Split tests related to Namespace Differential Revision: https://reviews.llvm.org/D86139 Added: Modified: clang/unittests/Tooling/Syntax/BuildTreeTest.cpp Removed: diff --git a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp index 2692c1f6ff58..a3e86dac50c5 100644 --- a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp @@ -2454,7 +2454,7 @@ typedef decltype(sizeof(void *)) size_t; )txt")); } -TEST_P(SyntaxTreeTest, Namespaces) { +TEST_P(SyntaxTreeTest, Namespace_Nested) { if (!GetParam().isCXX()) { return; } @@ -2462,9 +2462,6 @@ TEST_P(SyntaxTreeTest, Namespaces) { R"cpp( namespace a { namespace b {} } namespace a::b {} -namespace {} - -namespace foo = a; )cpp", R"txt( *: TranslationUnit @@ -2478,82 +2475,91 @@ namespace foo = a; | | |-{ | | `-} | `-} -|-NamespaceDefinition -| |-namespace -| |-a -| |-:: -| |-b -| |-{ -| `-} -|-NamespaceDefinition -| |-namespace -| |-{ -| `-} -`-NamespaceAliasDefinition +`-NamespaceDefinition |-namespace - |-foo - |-= |-a - `-; + |-:: + |-b + |-{ + `-} )txt")); } -TEST_P(SyntaxTreeTest, UsingDirective) { +TEST_P(SyntaxTreeTest, Namespace_Unnamed) { if (!GetParam().isCXX()) { return; } EXPECT_TRUE(treeDumpEqual( R"cpp( -namespace ns {} -using namespace ::ns; +namespace {} )cpp", R"txt( *: TranslationUnit -|-NamespaceDefinition -| |-namespace -| |-ns -| |-{ -| `-} -`-UsingNamespaceDirective - |-using +`-NamespaceDefinition |-namespace - |-NestedNameSpecifier - | `-:: - |-ns - `-; + |-{ + `-} )txt")); } +TEST_P(SyntaxTreeTest, Namespace_Alias) { + if (!GetParam().isCXX()) { +return; + } + EXPECT_TRUE(treeDumpEqualOnAnnotations( + R"cpp( +namespace a {} +[[namespace foo = a;]] +)cpp", + {R"txt( +NamespaceAliasDefinition +|-namespace +|-foo +|-= +|-a +`-; +)txt"})); +} + +TEST_P(SyntaxTreeTest, UsingDirective) { + if (!GetParam().isCXX()) { +return; + } + EXPECT_TRUE(treeDumpEqualOnAnnotations( + R"cpp( +namespace ns {} +[[using namespace ::ns;]] +)cpp", + {R"txt( +UsingNamespaceDirective +|-using +|-namespace +|-NestedNameSpecifier +| `-:: +|-ns +`-; +)txt"})); +} + TEST_P(SyntaxTreeTest, UsingDeclaration) { if (!GetParam().isCXX()) { return; } - EXPECT_TRUE(treeDumpEqual( + EXPECT_TRUE(treeDumpEqualOnAnnotations( R"cpp( namespace ns { int a; } -using ns::a; +[[using ns::a;]] )cpp", - R"txt( -*: TranslationUnit -|-NamespaceDefinition -| |-namespace -| |-ns -| |-{ -| |-SimpleDeclaration -| | |-int -| | |-SimpleDeclarator -| | | `-a -| | `-; -| `-} -`-UsingDeclaration - |-using - |-NestedNameSpecifier - | |-IdentifierNameSpecifier - | | `-ns - | `-:: - |-a - `-; -)txt")); + {R"txt( +UsingDeclaration +|-using +|-NestedNameSpecifier +| |-IdentifierNameSpecifier +| | `-ns +| `-:: +|-a +`-; +)txt"})); } TEST_P(SyntaxTreeTest, FreeStandingClasses) { ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 85c15f1 - [SyntaxTree] Add support for `this`
Author: Eduardo Caldas Date: 2020-08-21T08:01:29Z New Revision: 85c15f17cc684b35cdb4a5f3a76d45160de7b597 URL: https://github.com/llvm/llvm-project/commit/85c15f17cc684b35cdb4a5f3a76d45160de7b597 DIFF: https://github.com/llvm/llvm-project/commit/85c15f17cc684b35cdb4a5f3a76d45160de7b597.diff LOG: [SyntaxTree] Add support for `this` Differential Revision: https://reviews.llvm.org/D86298 Added: Modified: clang/include/clang/Tooling/Syntax/Nodes.h clang/lib/Tooling/Syntax/BuildTree.cpp clang/lib/Tooling/Syntax/Nodes.cpp clang/unittests/Tooling/Syntax/BuildTreeTest.cpp Removed: diff --git a/clang/include/clang/Tooling/Syntax/Nodes.h b/clang/include/clang/Tooling/Syntax/Nodes.h index 8b499bc5ceb9..0b3991768008 100644 --- a/clang/include/clang/Tooling/Syntax/Nodes.h +++ b/clang/include/clang/Tooling/Syntax/Nodes.h @@ -56,6 +56,7 @@ enum class NodeKind : uint16_t { StringUserDefinedLiteralExpression, IdExpression, MemberExpression, + ThisExpression, // Statements. UnknownStatement, @@ -313,6 +314,16 @@ class UnknownExpression final : public Expression { } }; +/// Models a this expression `this`. C++ [expr.prim.this] +class ThisExpression final : public Expression { +public: + ThisExpression() : Expression(NodeKind::ThisExpression) {} + static bool classof(const Node *N) { +return N->kind() == NodeKind::ThisExpression; + } + Leaf *thisKeyword(); +}; + /// Models a parenthesized expression `(E)`. C++ [expr.prim.paren] /// e.g. `(3 + 2)` in `a = 1 + (3 + 2);` class ParenExpression final : public Expression { diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp index 37d29a270463..3ab52ce5b7b4 100644 --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -950,6 +950,16 @@ class BuildTreeVisitor : public RecursiveASTVisitor { return true; } + bool WalkUpFromCXXThisExpr(CXXThisExpr *S) { +if (!S->isImplicit()) { + Builder.markChildToken(S->getLocation(), + syntax::NodeRole::IntroducerKeyword); + Builder.foldNode(Builder.getExprRange(S), + new (allocator()) syntax::ThisExpression, S); +} +return true; + } + bool WalkUpFromParenExpr(ParenExpr *S) { Builder.markChildToken(S->getLParen(), syntax::NodeRole::OpenParen); Builder.markExprChild(S->getSubExpr(), diff --git a/clang/lib/Tooling/Syntax/Nodes.cpp b/clang/lib/Tooling/Syntax/Nodes.cpp index e09c8f20f210..ecd4c4dac728 100644 --- a/clang/lib/Tooling/Syntax/Nodes.cpp +++ b/clang/lib/Tooling/Syntax/Nodes.cpp @@ -20,6 +20,8 @@ raw_ostream &syntax::operator<<(raw_ostream &OS, NodeKind K) { return OS << "UnknownExpression"; case NodeKind::ParenExpression: return OS << "ParenExpression"; + case NodeKind::ThisExpression: +return OS << "ThisExpression"; case NodeKind::IntegerLiteralExpression: return OS << "IntegerLiteralExpression"; case NodeKind::CharacterLiteralExpression: @@ -286,6 +288,11 @@ syntax::Leaf *syntax::ParenExpression::closeParen() { return cast_or_null(findChild(syntax::NodeRole::CloseParen)); } +syntax::Leaf *syntax::ThisExpression::thisKeyword() { + return cast_or_null( + findChild(syntax::NodeRole::IntroducerKeyword)); +} + syntax::Leaf *syntax::LiteralExpression::literalToken() { return cast_or_null(findChild(syntax::NodeRole::LiteralToken)); } diff --git a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp index a3e86dac50c5..d4e2684934f3 100644 --- a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp @@ -905,6 +905,68 @@ UnknownExpression )txt"})); } +TEST_P(SyntaxTreeTest, This_Simple) { + if (!GetParam().isCXX()) { +return; + } + EXPECT_TRUE(treeDumpEqualOnAnnotations( + R"cpp( +struct S { + S* test(){ +return [[this]]; + } +}; +)cpp", + {R"txt( +ThisExpression +`-this +)txt"})); +} + +TEST_P(SyntaxTreeTest, This_ExplicitMemberAccess) { + if (!GetParam().isCXX()) { +return; + } + EXPECT_TRUE(treeDumpEqualOnAnnotations( + R"cpp( +struct S { + int a; + void test(){ +[[this->a]]; + } +}; +)cpp", + {R"txt( +MemberExpression +|-ThisExpression +| `-this +|--> +`-IdExpression + `-UnqualifiedId +`-a +)txt"})); +} + +TEST_P(SyntaxTreeTest, This_ImplicitMemberAccess) { + if (!GetParam().isCXX()) { +return; + } + EXPECT_TRUE(treeDumpEqualOnAnnotations( + R"cpp( +struct S { + int a; + void test(){ +[[a]]; + } +}; +)cpp", + {R"txt( +IdExpression +`-UnqualifiedId + `-a +)txt"})); +} + TEST_P(SyntaxTreeTest, ParenExpr) { EXPECT_TRUE(treeDumpEqualOnAnnotations( R"cpp( @@ -2099,29 +2161,6 @@ UnknownExpression )txt"})); } -TEST_P(SyntaxTreeTest, MemberExpression_Implicit) { - if (!GetParam().isCX
[clang] 1beb11c - [SyntaxTree] Use annotations in Statement tests
Author: Eduardo Caldas Date: 2020-08-21T14:42:33Z New Revision: 1beb11c61ae4b0130cb87ed56b9e010ef6a06691 URL: https://github.com/llvm/llvm-project/commit/1beb11c61ae4b0130cb87ed56b9e010ef6a06691 DIFF: https://github.com/llvm/llvm-project/commit/1beb11c61ae4b0130cb87ed56b9e010ef6a06691.diff LOG: [SyntaxTree] Use annotations in Statement tests Differential Revision: https://reviews.llvm.org/D86345 Added: Modified: clang/unittests/Tooling/Syntax/BuildTreeTest.cpp Removed: diff --git a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp index d4e2684934f3..994dd68028ea 100644 --- a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp @@ -102,282 +102,196 @@ void foo(int a, int b) {} } TEST_P(SyntaxTreeTest, If) { - EXPECT_TRUE(treeDumpEqual( + EXPECT_TRUE(treeDumpEqualOnAnnotations( R"cpp( -int main() { - if (1) {} - if (1) {} else if (0) {} +void test() { + [[if (1) {}]] + [[if (1) {} else if (0) {}]] } )cpp", - R"txt( -*: TranslationUnit -`-SimpleDeclaration - |-int - |-SimpleDeclarator - | |-main - | `-ParametersAndQualifiers - | |-( - | `-) + {R"txt( +IfStatement +|-if +|-( +|-IntegerLiteralExpression +| `-1 +|-) +`-CompoundStatement + |-{ + `-} + )txt", + R"txt( +IfStatement +|-if +|-( +|-IntegerLiteralExpression +| `-1 +|-) +|-CompoundStatement +| |-{ +| `-} +|-else +`-IfStatement + |-if + |-( + |-IntegerLiteralExpression + | `-0 + |-) `-CompoundStatement |-{ -|-IfStatement -| |-if -| |-( -| |-IntegerLiteralExpression -| | `-1 -| |-) -| `-CompoundStatement -| |-{ -| `-} -|-IfStatement -| |-if -| |-( -| |-IntegerLiteralExpression -| | `-1 -| |-) -| |-CompoundStatement -| | |-{ -| | `-} -| |-else -| `-IfStatement -| |-if -| |-( -| |-IntegerLiteralExpression -| | `-0 -| |-) -| `-CompoundStatement -| |-{ -| `-} `-} -)txt")); +)txt"})); } TEST_P(SyntaxTreeTest, For) { - EXPECT_TRUE(treeDumpEqual( + EXPECT_TRUE(treeDumpEqualOnAnnotations( R"cpp( void test() { - for (;;) {} + [[for (;;) {}]] } )cpp", - R"txt( -*: TranslationUnit -`-SimpleDeclaration - |-void - |-SimpleDeclarator - | |-test - | `-ParametersAndQualifiers - | |-( - | `-) - `-CompoundStatement -|-{ -|-ForStatement -| |-for -| |-( -| |-; -| |-; -| |-) -| `-CompoundStatement -| |-{ -| `-} -`-} -)txt")); + {R"txt( +ForStatement +|-for +|-( +|-; +|-; +|-) +`-CompoundStatement + |-{ + `-} +)txt"})); } TEST_P(SyntaxTreeTest, RangeBasedFor) { if (!GetParam().isCXX11OrLater()) { return; } - EXPECT_TRUE(treeDumpEqual( + EXPECT_TRUE(treeDumpEqualOnAnnotations( R"cpp( void test() { int a[3]; - for (int x : a) -; + [[for (int x : a) +;]] } )cpp", - R"txt( -*: TranslationUnit -`-SimpleDeclaration - |-void - |-SimpleDeclarator - | |-test - | `-ParametersAndQualifiers - | |-( - | `-) - `-CompoundStatement -|-{ -|-DeclarationStatement -| |-SimpleDeclaration -| | |-int -| | `-SimpleDeclarator -| | |-a -| | `-ArraySubscript -| | |-[ -| | |-IntegerLiteralExpression -| | | `-3 -| | `-] -| `-; -|-RangeBasedForStatement -| |-for -| |-( -| |-SimpleDeclaration -| | |-int -| | |-SimpleDeclarator -| | | `-x -| | `-: -| |-IdExpression -| | `-UnqualifiedId -| | `-a -| |-) -| `-EmptyStatement -| `-; -`-} -)txt")); + {R"txt( +RangeBasedForStatement +|-for +|-( +|-SimpleDeclaration +| |-int +| |-SimpleDeclarator +| | `-x +| `-: +|-IdExpression +| `-UnqualifiedId +| `-a +|-) +`-EmptyStatement + `-; +)txt"})); } TEST_P(SyntaxTreeTest, DeclarationStatement) { - EXPECT_TRUE(treeDumpEqual( + EXPECT_TRUE(treeDumpEqualOnAnnotations( R"cpp( void test() { - int a = 10; + [[int a = 10;]] } )cpp", - R"txt( -*: TranslationUnit -`-SimpleDeclaration - |-void - |-SimpleDeclarator - | |-test - | `-ParametersAndQualifiers - | |-( - | `-) - `-CompoundStatement -|-{ -|-DeclarationStatement -| |-SimpleDeclaration -| | |-int -| | `-SimpleDeclarator -| | |-a -| | |-= -| | `-IntegerLiteralExpression -| | `-10 -| `-; -`-} -)txt")); + {R"txt( +DeclarationStatement +|-SimpleDeclaration +| |-int +| `-SimpleDeclarator +| |-a +| |-= +| `-IntegerLiteralExpression +| `-10 +`-; +)txt"})); } TEST_P(SyntaxTreeTest, Switch) { - EXPECT_TRUE(treeDumpEqual( + EXPECT_TRUE(treeDumpEqualOnAnnotations( R"cpp( void test() { - switch (1) { + [[switch (1) { case 0: default:; - } + }]] } )cpp", - R"txt(
[clang] 235f9f7 - [SyntaxTree] Split `DynamicExceptionSpecification` test
Author: Eduardo Caldas Date: 2020-08-24T14:31:46Z New Revision: 235f9f7fe94488904a60a8a1f5430183b0504945 URL: https://github.com/llvm/llvm-project/commit/235f9f7fe94488904a60a8a1f5430183b0504945 DIFF: https://github.com/llvm/llvm-project/commit/235f9f7fe94488904a60a8a1f5430183b0504945.diff LOG: [SyntaxTree] Split `DynamicExceptionSpecification` test Added: Modified: clang/unittests/Tooling/Syntax/BuildTreeTest.cpp Removed: diff --git a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp index 005f0a384d58..ce37a952ac1a 100644 --- a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp @@ -3800,79 +3800,72 @@ TEST_P(SyntaxTreeTest, DynamicExceptionSpecification) { if (!GetParam().supportsCXXDynamicExceptionSpecification()) { return; } - EXPECT_TRUE(treeDumpEqual( + EXPECT_TRUE(treeDumpEqualOnAnnotations( R"cpp( struct MyException1 {}; struct MyException2 {}; -int a() throw(); -int b() throw(...); -int c() throw(MyException1); -int d() throw(MyException1, MyException2); +[[int a() throw();]] +[[int b() throw(...);]] +[[int c() throw(MyException1);]] +[[int d() throw(MyException1, MyException2);]] )cpp", - R"txt( -*: TranslationUnit -|-SimpleDeclaration -| |-struct -| |-MyException1 -| |-{ -| |-} -| `-; -|-SimpleDeclaration -| |-struct -| |-MyException2 -| |-{ -| |-} -| `-; -|-SimpleDeclaration -| |-int -| |-SimpleDeclarator -| | |-a -| | `-ParametersAndQualifiers -| | |-( -| | |-) -| | |-throw -| | |-( -| | `-) -| `-; -|-SimpleDeclaration -| |-int -| |-SimpleDeclarator -| | |-b -| | `-ParametersAndQualifiers -| | |-( -| | |-) -| | |-throw -| | |-( -| | |-... -| | `-) -| `-; -|-SimpleDeclaration -| |-int -| |-SimpleDeclarator -| | |-c -| | `-ParametersAndQualifiers -| | |-( -| | |-) -| | |-throw -| | |-( -| | |-MyException1 -| | `-) -| `-; -`-SimpleDeclaration - |-int - |-SimpleDeclarator - | |-d - | `-ParametersAndQualifiers - | |-( - | |-) - | |-throw - | |-( - | |-MyException1 - | |-, - | |-MyException2 - | `-) - `-; -)txt")); + {R"txt( +SimpleDeclaration +|-int +|-SimpleDeclarator +| |-a +| `-ParametersAndQualifiers +| |-( +| |-) +| |-throw +| |-( +| `-) +`-; +)txt", + R"txt( +SimpleDeclaration +|-int +|-SimpleDeclarator +| |-b +| `-ParametersAndQualifiers +| |-( +| |-) +| |-throw +| |-( +| |-... +| `-) +`-; +)txt", + R"txt( +SimpleDeclaration +|-int +|-SimpleDeclarator +| |-c +| `-ParametersAndQualifiers +| |-( +| |-) +| |-throw +| |-( +| |-MyException1 +| `-) +`-; +)txt", + R"txt( +SimpleDeclaration +|-int +|-SimpleDeclarator +| |-d +| `-ParametersAndQualifiers +| |-( +| |-) +| |-throw +| |-( +| |-MyException1 +| |-, +| |-MyException2 +| `-) +`-; +)txt"})); } TEST_P(SyntaxTreeTest, NoexceptExceptionSpecification) { ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] ed83095 - [SyntaxTree] Use annotations to reduce noise on member function tests
Author: Eduardo Caldas Date: 2020-08-24T14:31:45Z New Revision: ed83095254a3e212d14b293a6a0e6c85d1f3331c URL: https://github.com/llvm/llvm-project/commit/ed83095254a3e212d14b293a6a0e6c85d1f3331c DIFF: https://github.com/llvm/llvm-project/commit/ed83095254a3e212d14b293a6a0e6c85d1f3331c.diff LOG: [SyntaxTree] Use annotations to reduce noise on member function tests Differential Revision: https://reviews.llvm.org/D86439 Added: Modified: clang/unittests/Tooling/Syntax/BuildTreeTest.cpp Removed: diff --git a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp index a8e675468257..93f510e0a890 100644 --- a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp @@ -2570,61 +2570,47 @@ TEST_P(SyntaxTreeTest, StaticMemberFunction) { if (!GetParam().isCXX11OrLater()) { return; } - EXPECT_TRUE(treeDumpEqual( + EXPECT_TRUE(treeDumpEqualOnAnnotations( R"cpp( struct S { - static void f(){} + [[static void f(){}]] }; )cpp", - R"txt( -*: TranslationUnit -`-SimpleDeclaration - |-struct - |-S + {R"txt( +SimpleDeclaration +|-static +|-void +|-SimpleDeclarator +| |-f +| `-ParametersAndQualifiers +| |-( +| `-) +`-CompoundStatement |-{ - |-SimpleDeclaration - | |-static - | |-void - | |-SimpleDeclarator - | | |-f - | | `-ParametersAndQualifiers - | | |-( - | | `-) - | `-CompoundStatement - | |-{ - | `-} - |-} - `-; -)txt")); + `-} +)txt"})); } TEST_P(SyntaxTreeTest, ConversionMemberFunction) { if (!GetParam().isCXX()) { return; } - EXPECT_TRUE(treeDumpEqual( + EXPECT_TRUE(treeDumpEqualOnAnnotations( R"cpp( struct X { - operator int(); + [[operator int();]] }; )cpp", - R"txt( -*: TranslationUnit -`-SimpleDeclaration - |-struct - |-X - |-{ - |-SimpleDeclaration - | |-SimpleDeclarator - | | |-operator - | | |-int - | | `-ParametersAndQualifiers - | | |-( - | | `-) - | `-; - |-} - `-; -)txt")); + {R"txt( +SimpleDeclaration +|-SimpleDeclarator +| |-operator +| |-int +| `-ParametersAndQualifiers +| |-( +| `-) +`-; +)txt"})); } TEST_P(SyntaxTreeTest, LiteralOperatorDeclaration) { @@ -2687,76 +2673,62 @@ TEST_P(SyntaxTreeTest, OverloadedOperatorDeclaration) { if (!GetParam().isCXX()) { return; } - EXPECT_TRUE(treeDumpEqual( + EXPECT_TRUE(treeDumpEqualOnAnnotations( R"cpp( struct X { - X& operator=(const X&); + [[X& operator=(const X&);]] }; )cpp", - R"txt( -*: TranslationUnit -`-SimpleDeclaration - |-struct - |-X - |-{ - |-SimpleDeclaration - | |-X - | |-SimpleDeclarator - | | |-& - | | |-operator - | | |-= - | | `-ParametersAndQualifiers - | | |-( - | | |-SimpleDeclaration - | | | |-const - | | | |-X - | | | `-SimpleDeclarator - | | | `-& - | | `-) - | `-; - |-} - `-; -)txt")); + {R"txt( +SimpleDeclaration +|-X +|-SimpleDeclarator +| |-& +| |-operator +| |-= +| `-ParametersAndQualifiers +| |-( +| |-SimpleDeclaration +| | |-const +| | |-X +| | `-SimpleDeclarator +| | `-& +| `-) +`-; +)txt"})); } TEST_P(SyntaxTreeTest, OverloadedOperatorFriendDeclarataion) { if (!GetParam().isCXX()) { return; } - EXPECT_TRUE(treeDumpEqual( + EXPECT_TRUE(treeDumpEqualOnAnnotations( R"cpp( struct X { - friend X operator+(X, const X&); + [[friend X operator+(X, const X&);]] }; )cpp", - R"txt( -*: TranslationUnit + {R"txt( +UnknownDeclaration `-SimpleDeclaration - |-struct + |-friend |-X - |-{ - |-UnknownDeclaration - | `-SimpleDeclaration - | |-friend - | |-X - | |-SimpleDeclarator - | | |-operator - | | |-+ - | | `-ParametersAndQualifiers - | | |-( - | | |-SimpleDeclaration - | | | `-X - | | |-, - | | |-SimpleDeclaration - | | | |-const - | | | |-X - | | | `-SimpleDeclarator - | | | `-& - | | `-) - | `-; - |-} + |-SimpleDeclarator + | |-operator + | |-+ + | `-ParametersAndQualifiers + | |-( + | |-SimpleDeclaration + | | `-X + | |-, + | |-SimpleDeclaration + | | |-const + | | |-X + | | `-SimpleDeclarator + | | `-& + | `-) `-; -)txt")); +)txt"})); } TEST_P(SyntaxTreeTest, ClassTemplateDeclaration) { @@ -2847,38 +2819,31 @@ TEST_P(SyntaxTreeTest, StaticMemberFunctionTemplate) { if (!GetParam().isCXX()) { return; } - EXPECT_TRUE(treeDumpEqual( + EXPECT_TRUE(treeDumpEqualOnAnnotations( R"cpp( struct S { - template - static U f(); + [[template + static U f();]] }; )cpp", - R"txt( -*: TranslationUnit + {R"txt( +TemplateDeclaration +|-template +|-< +|-UnknownDeclaration +| |-typename +| `-U +|-> `-SimpleDeclaration - |-struct - |-S - |-{ - |-TemplateDeclaration - | |-template - | |-< - | |-UnknownDeclaration - | | |-typename - | | `-U - |
[clang] 90f85df - [SyntaxTree] Group tests related to `using`
Author: Eduardo Caldas Date: 2020-08-24T14:31:46Z New Revision: 90f85dfc14bc6020486eb2d2c6399f8207ef3625 URL: https://github.com/llvm/llvm-project/commit/90f85dfc14bc6020486eb2d2c6399f8207ef3625 DIFF: https://github.com/llvm/llvm-project/commit/90f85dfc14bc6020486eb2d2c6399f8207ef3625.diff LOG: [SyntaxTree] Group tests related to `using` Differential Revision: https://reviews.llvm.org/D86443 Added: Modified: clang/unittests/Tooling/Syntax/BuildTreeTest.cpp Removed: diff --git a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp index 4fc648df90b3..acbe90526fcb 100644 --- a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp @@ -2494,7 +2494,7 @@ UsingNamespaceDirective )txt"})); } -TEST_P(SyntaxTreeTest, UsingDeclaration) { +TEST_P(SyntaxTreeTest, UsingDeclaration_Namespace) { if (!GetParam().isCXX()) { return; } @@ -2515,6 +2515,59 @@ UsingDeclaration )txt"})); } +TEST_P(SyntaxTreeTest, UsingDeclaration_ClassMember) { + if (!GetParam().isCXX()) { +return; + } + EXPECT_TRUE(treeDumpEqualOnAnnotations( + R"cpp( +template struct X { + [[using T::foo;]] + [[using typename T::bar;]] +}; +)cpp", + {R"txt( +UsingDeclaration +|-using +|-NestedNameSpecifier +| |-IdentifierNameSpecifier +| | `-T +| `-:: +|-foo +`-; +)txt", + R"txt( +UsingDeclaration +|-using +|-typename +|-NestedNameSpecifier +| |-IdentifierNameSpecifier +| | `-T +| `-:: +|-bar +`-; +)txt"})); +} + +TEST_P(SyntaxTreeTest, UsingTypeAlias) { + if (!GetParam().isCXX()) { +return; + } + EXPECT_TRUE(treeDumpEqual( + R"cpp( +using type = int; +)cpp", + R"txt( +*: TranslationUnit +`-TypeAliasDeclaration + |-using + |-type + |-= + |-int + `-; +)txt")); +} + TEST_P(SyntaxTreeTest, FreeStandingClass_ForwardDeclaration) { EXPECT_TRUE(treeDumpEqualOnAnnotations( R"cpp( @@ -3005,52 +3058,6 @@ template struct X::Y {}; )txt")); } -TEST_P(SyntaxTreeTest, TemplatesUsingUsing) { - if (!GetParam().isCXX()) { -return; - } - EXPECT_TRUE(treeDumpEqual( - R"cpp( -template struct X { - using T::foo; - using typename T::bar; -}; -)cpp", - R"txt( -*: TranslationUnit -`-TemplateDeclaration - |-template - |-< - |-UnknownDeclaration - | |-class - | `-T - |-> - `-SimpleDeclaration -|-struct -|-X -|-{ -|-UsingDeclaration -| |-using -| |-NestedNameSpecifier -| | |-IdentifierNameSpecifier -| | | `-T -| | `-:: -| |-foo -| `-; -|-UsingDeclaration -| |-using -| |-typename -| |-NestedNameSpecifier -| | |-IdentifierNameSpecifier -| | | `-T -| | `-:: -| |-bar -| `-; -|-} -`-; -)txt")); -} - TEST_P(SyntaxTreeTest, ExplicitClassTemplateInstantation_Definition) { if (!GetParam().isCXX()) { return; @@ -3152,25 +3159,6 @@ TemplateDeclaration )txt"})); } -TEST_P(SyntaxTreeTest, UsingType) { - if (!GetParam().isCXX()) { -return; - } - EXPECT_TRUE(treeDumpEqual( - R"cpp( -using type = int; -)cpp", - R"txt( -*: TranslationUnit -`-TypeAliasDeclaration - |-using - |-type - |-= - |-int - `-; -)txt")); -} - TEST_P(SyntaxTreeTest, EmptyDeclaration) { EXPECT_TRUE(treeDumpEqual( R"cpp( ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 4baa163 - [SyntaxTree] Split `ParametersAndQualifiers` tests
Author: Eduardo Caldas Date: 2020-08-24T14:31:46Z New Revision: 4baa163c74237b30c5094c1fafd7ed355575bcfa URL: https://github.com/llvm/llvm-project/commit/4baa163c74237b30c5094c1fafd7ed355575bcfa DIFF: https://github.com/llvm/llvm-project/commit/4baa163c74237b30c5094c1fafd7ed355575bcfa.diff LOG: [SyntaxTree] Split `ParametersAndQualifiers` tests Differential Revision: https://reviews.llvm.org/D86459 Added: Modified: clang/unittests/Tooling/Syntax/BuildTreeTest.cpp Removed: diff --git a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp index acbe90526fcb..005f0a384d58 100644 --- a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp @@ -3438,19 +3438,30 @@ void f(int xs[static 10]); )txt")); } -TEST_P(SyntaxTreeTest, ParametersAndQualifiersInFreeFunctions) { - if (!GetParam().isCXX()) { -return; - } +TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Empty) { + EXPECT_TRUE(treeDumpEqual( + R"cpp( +int func(); +)cpp", + R"txt( +*: TranslationUnit +`-SimpleDeclaration + |-int + |-SimpleDeclarator + | |-func + | `-ParametersAndQualifiers + | |-( + | `-) + `-; +)txt")); +} + +TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Named) { EXPECT_TRUE(treeDumpEqual( R"cpp( -int func1(); -int func2a(int a); -int func2b(int); -int func3a(int *ap); -int func3b(int *); -int func4a(int a, float b); -int func4b(int, float); +int func1(int a); +int func2(int *ap); +int func3(int a, float b); )cpp", R"txt( *: TranslationUnit @@ -3460,14 +3471,6 @@ int func4b(int, float); | | |-func1 | | `-ParametersAndQualifiers | | |-( -| | `-) -| `-; -|-SimpleDeclaration -| |-int -| |-SimpleDeclarator -| | |-func2a -| | `-ParametersAndQualifiers -| | |-( | | |-SimpleDeclaration | | | |-int | | | `-SimpleDeclarator @@ -3477,17 +3480,7 @@ int func4b(int, float); |-SimpleDeclaration | |-int | |-SimpleDeclarator -| | |-func2b -| | `-ParametersAndQualifiers -| | |-( -| | |-SimpleDeclaration -| | | `-int -| | `-) -| `-; -|-SimpleDeclaration -| |-int -| |-SimpleDeclarator -| | |-func3a +| | |-func2 | | `-ParametersAndQualifiers | | |-( | | |-SimpleDeclaration @@ -3497,39 +3490,61 @@ int func4b(int, float); | | | `-ap | | `-) | `-; +`-SimpleDeclaration + |-int + |-SimpleDeclarator + | |-func3 + | `-ParametersAndQualifiers + | |-( + | |-SimpleDeclaration + | | |-int + | | `-SimpleDeclarator + | | `-a + | |-, + | |-SimpleDeclaration + | | |-float + | | `-SimpleDeclarator + | | `-b + | `-) + `-; +)txt")); +} + +TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Unnamed) { + EXPECT_TRUE(treeDumpEqual( + R"cpp( +int func1(int); +int func2(int *); +int func3(int, float); +)cpp", + R"txt( +*: TranslationUnit |-SimpleDeclaration | |-int | |-SimpleDeclarator -| | |-func3b +| | |-func1 | | `-ParametersAndQualifiers | | |-( | | |-SimpleDeclaration -| | | |-int -| | | `-SimpleDeclarator -| | | `-* +| | | `-int | | `-) | `-; |-SimpleDeclaration | |-int | |-SimpleDeclarator -| | |-func4a +| | |-func2 | | `-ParametersAndQualifiers | | |-( | | |-SimpleDeclaration | | | |-int | | | `-SimpleDeclarator -| | | `-a -| | |-, -| | |-SimpleDeclaration -| | | |-float -| | | `-SimpleDeclarator -| | | `-b +| | | `-* | | `-) | `-; `-SimpleDeclaration |-int |-SimpleDeclarator - | |-func4b + | |-func3 | `-ParametersAndQualifiers | |-( | |-SimpleDeclaration @@ -3542,47 +3557,60 @@ int func4b(int, float); )txt")); } -TEST_P(SyntaxTreeTest, ParametersAndQualifiersInFreeFunctionsCxx) { +TEST_P(SyntaxTreeTest, + ParametersAndQualifiers_InFreeFunctions_Cxx_CvQualifiers) { if (!GetParam().isCXX()) { return; } EXPECT_TRUE(treeDumpEqual( R"cpp( -int func1(const int a, volatile int b, const volatile int c); -int func2(int& a); +int func(const int a, volatile int b, const volatile int c); )cpp", R"txt( *: TranslationUnit -|-SimpleDeclaration -| |-int -| |-SimpleDeclarator -| | |-func1 -| | `-ParametersAndQualifiers -| | |-( -| | |-SimpleDeclaration -| | | |-const -| | | |-int -| | | `-SimpleDeclarator -| | | `-a -| | |-, -| | |-SimpleDeclaration -| | | |-volatile -| | | |-int -| | | `-SimpleDeclarator -| | | `-b -| | |-, -| | |-SimpleDeclaration -| | | |-const -| | | |-volatile -| | | |-int -| | | `-SimpleDeclarator -| | | `-c -| | `-) -| `-; `-SimpleDeclaration |-int |-SimpleDeclarator - | |-func2 + | |-func + | `-ParametersAndQualifiers + | |-( + | |-SimpleDeclaration + | | |-const + | | |-int + | | `-SimpleDeclarator + | | `-a + | |-, + | |-SimpleDeclaration + | | |-volatile + | | |-in
[clang] a722d6a - [SyntaxTree] Split ExplicitTemplateInstantiation test
Author: Eduardo Caldas Date: 2020-08-24T14:31:45Z New Revision: a722d6a197c7a4f7a1afb72b4732b8ebe8272628 URL: https://github.com/llvm/llvm-project/commit/a722d6a197c7a4f7a1afb72b4732b8ebe8272628 DIFF: https://github.com/llvm/llvm-project/commit/a722d6a197c7a4f7a1afb72b4732b8ebe8272628.diff LOG: [SyntaxTree] Split ExplicitTemplateInstantiation test Differential Revision: https://reviews.llvm.org/D86441 Added: Modified: clang/unittests/Tooling/Syntax/BuildTreeTest.cpp Removed: diff --git a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp index 8dbf99c32db8..4fc648df90b3 100644 --- a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp @@ -3051,84 +3051,105 @@ template struct X { )txt")); } -TEST_P(SyntaxTreeTest, ExplicitTemplateInstantations) { +TEST_P(SyntaxTreeTest, ExplicitClassTemplateInstantation_Definition) { if (!GetParam().isCXX()) { return; } - EXPECT_TRUE(treeDumpEqual( + EXPECT_TRUE(treeDumpEqualOnAnnotations( R"cpp( template struct X {}; -template struct X {}; -template <> struct X {}; +[[template struct X;]] +)cpp", + {R"txt( +ExplicitTemplateInstantiation +|-template +`-SimpleDeclaration + |-struct + |-X + |-< + |-double + |-> + `-; +)txt"})); +} -template struct X; -extern template struct X; +TEST_P(SyntaxTreeTest, ExplicitClassTemplateInstantation_Declaration) { + if (!GetParam().isCXX()) { +return; + } + EXPECT_TRUE(treeDumpEqualOnAnnotations( + R"cpp( +template struct X {}; +[[extern template struct X;]] )cpp", - R"txt( -*: TranslationUnit -|-TemplateDeclaration -| |-template -| |-< -| |-UnknownDeclaration -| | |-class -| | `-T -| |-> -| `-SimpleDeclaration -| |-struct -| |-X -| |-{ -| |-} -| `-; -|-TemplateDeclaration -| |-template -| |-< -| |-UnknownDeclaration -| | |-class -| | `-T -| |-> -| `-SimpleDeclaration -| |-struct -| |-X -| |-< -| |-T -| |-* -| |-> -| |-{ -| |-} -| `-; -|-TemplateDeclaration -| |-template -| |-< -| |-> -| `-SimpleDeclaration -| |-struct -| |-X -| |-< -| |-int -| |-> -| |-{ -| |-} -| `-; -|-ExplicitTemplateInstantiation -| |-template -| `-SimpleDeclaration -| |-struct -| |-X -| |-< -| |-double -| |-> -| `-; -`-ExplicitTemplateInstantiation - |-extern - |-template - `-SimpleDeclaration -|-struct -|-X -|-< -|-float -|-> -`-; -)txt")); + {R"txt( +ExplicitTemplateInstantiation +|-extern +|-template +`-SimpleDeclaration + |-struct + |-X + |-< + |-float + |-> + `-; +)txt"})); +} + +TEST_P(SyntaxTreeTest, ClassTemplateSpecialization_Partial) { + if (!GetParam().isCXX()) { +return; + } + EXPECT_TRUE(treeDumpEqualOnAnnotations( + R"cpp( +template struct X {}; +[[template struct X {};]] +)cpp", + {R"txt( +TemplateDeclaration +|-template +|-< +|-UnknownDeclaration +| |-class +| `-T +|-> +`-SimpleDeclaration + |-struct + |-X + |-< + |-T + |-* + |-> + |-{ + |-} + `-; +)txt"})); +} + +TEST_P(SyntaxTreeTest, ClassTemplateSpecialization_Full) { + if (!GetParam().isCXX()) { +return; + } + EXPECT_TRUE(treeDumpEqualOnAnnotations( + R"cpp( +template struct X {}; +[[template <> struct X {};]] +)cpp", + {R"txt( +TemplateDeclaration +|-template +|-< +|-> +`-SimpleDeclaration + |-struct + |-X + |-< + |-int + |-> + |-{ + |-} + `-; +)txt"})); } TEST_P(SyntaxTreeTest, UsingType) { ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 4e8dd50 - [SyntaxTree] Split array declarator tests
Author: Eduardo Caldas Date: 2020-08-24T14:31:45Z New Revision: 4e8dd506e66642329dcd530524f43b0d2b528521 URL: https://github.com/llvm/llvm-project/commit/4e8dd506e66642329dcd530524f43b0d2b528521 DIFF: https://github.com/llvm/llvm-project/commit/4e8dd506e66642329dcd530524f43b0d2b528521.diff LOG: [SyntaxTree] Split array declarator tests Differential Revision: https://reviews.llvm.org/D86437 Added: Modified: clang/unittests/Tooling/Syntax/BuildTreeTest.cpp Removed: diff --git a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp index 994dd68028ea..a8e675468257 100644 --- a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp @@ -3342,45 +3342,63 @@ void test() { )txt")); } -TEST_P(SyntaxTreeTest, ArraySubscriptsInDeclarators) { +TEST_P(SyntaxTreeTest, ArrayDeclarator_Simple) { EXPECT_TRUE(treeDumpEqual( R"cpp( int a[10]; +)cpp", + R"txt( +*: TranslationUnit +`-SimpleDeclaration + |-int + |-SimpleDeclarator + | |-a + | `-ArraySubscript + | |-[ + | |-IntegerLiteralExpression + | | `-10 + | `-] + `-; +)txt")); +} + +TEST_P(SyntaxTreeTest, ArrayDeclarator_Multidimensional) { + EXPECT_TRUE(treeDumpEqual( + R"cpp( int b[1][2][3]; +)cpp", + R"txt( +*: TranslationUnit +`-SimpleDeclaration + |-int + |-SimpleDeclarator + | |-b + | |-ArraySubscript + | | |-[ + | | |-IntegerLiteralExpression + | | | `-1 + | | `-] + | |-ArraySubscript + | | |-[ + | | |-IntegerLiteralExpression + | | | `-2 + | | `-] + | `-ArraySubscript + | |-[ + | |-IntegerLiteralExpression + | | `-3 + | `-] + `-; +)txt")); +} + +TEST_P(SyntaxTreeTest, ArrayDeclarator_UnknownBound) { + EXPECT_TRUE(treeDumpEqual( + R"cpp( int c[] = {1,2,3}; )cpp", R"txt( *: TranslationUnit -|-SimpleDeclaration -| |-int -| |-SimpleDeclarator -| | |-a -| | `-ArraySubscript -| | |-[ -| | |-IntegerLiteralExpression -| | | `-10 -| | `-] -| `-; -|-SimpleDeclaration -| |-int -| |-SimpleDeclarator -| | |-b -| | |-ArraySubscript -| | | |-[ -| | | |-IntegerLiteralExpression -| | | | `-1 -| | | `-] -| | |-ArraySubscript -| | | |-[ -| | | |-IntegerLiteralExpression -| | | | `-2 -| | | `-] -| | `-ArraySubscript -| | |-[ -| | |-IntegerLiteralExpression -| | | `-3 -| | `-] -| `-; `-SimpleDeclaration |-int |-SimpleDeclarator @@ -3405,7 +3423,7 @@ int c[] = {1,2,3}; )txt")); } -TEST_P(SyntaxTreeTest, StaticArraySubscriptsInDeclarators) { +TEST_P(SyntaxTreeTest, ArrayDeclarator_Static) { if (!GetParam().isC99OrLater()) { return; } ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] b4093d6 - [SyntaxTree] Split FreeStandingClass tests
Author: Eduardo Caldas Date: 2020-08-24T14:31:45Z New Revision: b4093d663f8377b3ca3746ff104c83c9c5510c0a URL: https://github.com/llvm/llvm-project/commit/b4093d663f8377b3ca3746ff104c83c9c5510c0a DIFF: https://github.com/llvm/llvm-project/commit/b4093d663f8377b3ca3746ff104c83c9c5510c0a.diff LOG: [SyntaxTree] Split FreeStandingClass tests Differential Revision: https://reviews.llvm.org/D86440 Added: Modified: clang/unittests/Tooling/Syntax/BuildTreeTest.cpp Removed: diff --git a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp index 93f510e0a890..8dbf99c32db8 100644 --- a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp @@ -2515,55 +2515,65 @@ UsingDeclaration )txt"})); } -TEST_P(SyntaxTreeTest, FreeStandingClasses) { - // Free-standing classes, must live inside a SimpleDeclaration. - EXPECT_TRUE(treeDumpEqual( +TEST_P(SyntaxTreeTest, FreeStandingClass_ForwardDeclaration) { + EXPECT_TRUE(treeDumpEqualOnAnnotations( R"cpp( -struct X; -struct X {}; - -struct Y *y1; -struct Y {} *y2; +[[struct X;]] +[[struct Y *y1;]] +)cpp", + {R"txt( +SimpleDeclaration +|-struct +|-X +`-; +)txt", + R"txt( +SimpleDeclaration +|-struct +|-Y +|-SimpleDeclarator +| |-* +| `-y1 +`-; +)txt"})); +} -struct {} *a1; +TEST_P(SyntaxTreeTest, FreeStandingClasses_Definition) { + EXPECT_TRUE(treeDumpEqualOnAnnotations( + R"cpp( +[[struct X {};]] +[[struct Y {} *y2;]] +[[struct {} *a1;]] )cpp", - R"txt( -*: TranslationUnit -|-SimpleDeclaration -| |-struct -| |-X -| `-; -|-SimpleDeclaration -| |-struct -| |-X -| |-{ -| |-} -| `-; -|-SimpleDeclaration -| |-struct -| |-Y -| |-SimpleDeclarator -| | |-* -| | `-y1 -| `-; -|-SimpleDeclaration -| |-struct -| |-Y -| |-{ -| |-} -| |-SimpleDeclarator -| | |-* -| | `-y2 -| `-; -`-SimpleDeclaration - |-struct - |-{ - |-} - |-SimpleDeclarator - | |-* - | `-a1 - `-; -)txt")); + {R"txt( +SimpleDeclaration +|-struct +|-X +|-{ +|-} +`-; +)txt", + R"txt( +SimpleDeclaration +|-struct +|-Y +|-{ +|-} +|-SimpleDeclarator +| |-* +| `-y2 +`-; +)txt", + R"txt( +SimpleDeclaration +|-struct +|-{ +|-} +|-SimpleDeclarator +| |-* +| `-a1 +`-; +)txt"})); } TEST_P(SyntaxTreeTest, StaticMemberFunction) { ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 61273f2 - [SyntaxTree] Split `MemberPointer` tests with annotations
Author: Eduardo Caldas Date: 2020-08-25T06:07:40Z New Revision: 61273f298f2ccca5a474013ff59a94eef0371efb URL: https://github.com/llvm/llvm-project/commit/61273f298f2ccca5a474013ff59a94eef0371efb DIFF: https://github.com/llvm/llvm-project/commit/61273f298f2ccca5a474013ff59a94eef0371efb.diff LOG: [SyntaxTree] Split `MemberPointer` tests with annotations Differential Revision: https://reviews.llvm.org/D86467 Added: Modified: clang/unittests/Tooling/Syntax/BuildTreeTest.cpp Removed: diff --git a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp index ce37a952ac1a..8ce83e927672 100644 --- a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp @@ -4059,133 +4059,119 @@ TEST_P(SyntaxTreeTest, MemberPointers) { if (!GetParam().isCXX()) { return; } - EXPECT_TRUE(treeDumpEqual( + EXPECT_TRUE(treeDumpEqualOnAnnotations( R"cpp( struct X {}; -int X::* a; -const int X::* b; +[[int X::* a;]] +[[const int X::* b;]] )cpp", - R"txt( -*: TranslationUnit -|-SimpleDeclaration -| |-struct -| |-X -| |-{ -| |-} -| `-; -|-SimpleDeclaration -| |-int -| |-SimpleDeclarator -| | |-MemberPointer -| | | |-X -| | | |-:: -| | | `-* -| | `-a -| `-; -`-SimpleDeclaration - |-const - |-int - |-SimpleDeclarator - | |-MemberPointer - | | |-X - | | |-:: - | | `-* - | `-b - `-; -)txt")); + {R"txt( +SimpleDeclaration +|-int +|-SimpleDeclarator +| |-MemberPointer +| | |-X +| | |-:: +| | `-* +| `-a +`-; +)txt", + R"txt( +SimpleDeclaration +|-const +|-int +|-SimpleDeclarator +| |-MemberPointer +| | |-X +| | |-:: +| | `-* +| `-b +`-; +)txt"})); } TEST_P(SyntaxTreeTest, MemberFunctionPointer) { if (!GetParam().isCXX()) { return; } - EXPECT_TRUE(treeDumpEqual( + EXPECT_TRUE(treeDumpEqualOnAnnotations( R"cpp( struct X { struct Y {}; }; -void (X::*xp)(); -void (X::**xpp)(const int*); +[[void (X::*xp)();]] +[[void (X::**xpp)(const int*);]] // FIXME: Generate the right syntax tree for this type, // i.e. create a syntax node for the outer member pointer -void (X::Y::*xyp)(const int*, char); +[[void (X::Y::*xyp)(const int*, char);]] )cpp", - R"txt( -*: TranslationUnit -|-SimpleDeclaration -| |-struct -| |-X -| |-{ -| |-SimpleDeclaration -| | |-struct -| | |-Y -| | |-{ -| | |-} -| | `-; -| |-} -| `-; -|-SimpleDeclaration -| |-void -| |-SimpleDeclarator -| | |-ParenDeclarator -| | | |-( -| | | |-MemberPointer -| | | | |-X -| | | | |-:: -| | | | `-* -| | | |-xp -| | | `-) -| | `-ParametersAndQualifiers -| | |-( -| | `-) -| `-; -|-SimpleDeclaration -| |-void -| |-SimpleDeclarator -| | |-ParenDeclarator -| | | |-( -| | | |-MemberPointer -| | | | |-X -| | | | |-:: -| | | | `-* -| | | |-* -| | | |-xpp -| | | `-) -| | `-ParametersAndQualifiers -| | |-( -| | |-SimpleDeclaration -| | | |-const -| | | |-int -| | | `-SimpleDeclarator -| | | `-* -| | `-) -| `-; -`-SimpleDeclaration - |-void - |-SimpleDeclarator - | |-ParenDeclarator - | | |-( - | | |-X - | | |-:: - | | |-MemberPointer - | | | |-Y - | | | |-:: - | | | `-* - | | |-xyp - | | `-) - | `-ParametersAndQualifiers - | |-( - | |-SimpleDeclaration - | | |-const - | | |-int - | | `-SimpleDeclarator - | | `-* - | |-, - | |-SimpleDeclaration - | | `-char - | `-) - `-; -)txt")); + {R"txt( +SimpleDeclaration +|-void +|-SimpleDeclarator +| |-ParenDeclarator +| | |-( +| | |-MemberPointer +| | | |-X +| | | |-:: +| | | `-* +| | |-xp +| | `-) +| `-ParametersAndQualifiers +| |-( +| `-) +`-; +)txt", + R"txt( +SimpleDeclaration +|-void +|-SimpleDeclarator +| |-ParenDeclarator +| | |-( +| | |-MemberPointer +| | | |-X +| | | |-:: +| | | `-* +| | |-* +| | |-xpp +| | `-) +| `-ParametersAndQualifiers +| |-( +| |-SimpleDeclaration +| | |-const +| | |-int +| | `-SimpleDeclarator +| | `-* +| `-) +`-; +)txt", + R"txt( +SimpleDeclaration +|-void +|-SimpleDeclarator +| |-ParenDeclarator +| | |-( +| | |-X +| | |-:: +| | |-MemberPointer +| | | |-Y +| | | |-:: +| | | `-* +| | |-xyp +| | `-) +| `-ParametersAndQualifiers +| |-( +| |-SimpleDeclaration +| | |-const +| | |-int +| | `-SimpleDeclarator +| | `-* +| |-, +| |-SimpleDeclaration +| | `-char +| `-) +`-; +)txt"})); } TEST_P(SyntaxTreeTest, ComplexDeclarator) { ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 7f426c6 - [SyntaxTree] Use annotations on ClassTemplate_MemberClassDefinition test
Author: Eduardo Caldas Date: 2020-08-25T06:07:40Z New Revision: 7f426c65b06f2d19546b2d50fccc15de9dde3d85 URL: https://github.com/llvm/llvm-project/commit/7f426c65b06f2d19546b2d50fccc15de9dde3d85 DIFF: https://github.com/llvm/llvm-project/commit/7f426c65b06f2d19546b2d50fccc15de9dde3d85.diff LOG: [SyntaxTree] Use annotations on ClassTemplate_MemberClassDefinition test Differential Revision: https://reviews.llvm.org/D86470 Added: Modified: clang/unittests/Tooling/Syntax/BuildTreeTest.cpp Removed: diff --git a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp index 2ad01f09596e..0d24432115cc 100644 --- a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp @@ -3007,55 +3007,37 @@ namespace n { )txt")); } -TEST_P(SyntaxTreeTest, Templates2) { +TEST_P(SyntaxTreeTest, ClassTemplate_MemberClassDefinition) { if (!GetParam().isCXX()) { return; } - EXPECT_TRUE(treeDumpEqual( + EXPECT_TRUE(treeDumpEqualOnAnnotations( R"cpp( template struct X { struct Y; }; -template struct X::Y {}; +[[template struct X::Y {};]] )cpp", - R"txt( -*: TranslationUnit -|-TemplateDeclaration -| |-template -| |-< -| |-UnknownDeclaration -| | |-class -| | `-T -| |-> -| `-SimpleDeclaration -| |-struct -| |-X -| |-{ -| |-SimpleDeclaration -| | |-struct -| | |-Y -| | `-; -| |-} -| `-; -`-TemplateDeclaration - |-template - |-< - |-UnknownDeclaration - | |-class - | `-T - |-> - `-SimpleDeclaration -|-struct -|-NestedNameSpecifier -| |-SimpleTemplateNameSpecifier -| | |-X -| | |-< -| | |-T -| | `-> -| `-:: -|-Y -|-{ -|-} -`-; -)txt")); + {R"txt( +TemplateDeclaration +|-template +|-< +|-UnknownDeclaration +| |-class +| `-T +|-> +`-SimpleDeclaration + |-struct + |-NestedNameSpecifier + | |-SimpleTemplateNameSpecifier + | | |-X + | | |-< + | | |-T + | | `-> + | `-:: + |-Y + |-{ + |-} + `-; +)txt"})); } TEST_P(SyntaxTreeTest, ExplicitClassTemplateInstantation_Definition) { ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] b493e4c - [SyntaxTree] Split ConstVolatileQualifiers tests
Author: Eduardo Caldas Date: 2020-08-25T06:07:40Z New Revision: b493e4cb3e37401d4fe5c0b2ba1adf7e66758bb0 URL: https://github.com/llvm/llvm-project/commit/b493e4cb3e37401d4fe5c0b2ba1adf7e66758bb0 DIFF: https://github.com/llvm/llvm-project/commit/b493e4cb3e37401d4fe5c0b2ba1adf7e66758bb0.diff LOG: [SyntaxTree] Split ConstVolatileQualifiers tests Differential Revision: https://reviews.llvm.org/D86469 Added: Modified: clang/unittests/Tooling/Syntax/BuildTreeTest.cpp Removed: diff --git a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp index 8ce83e927672..2ad01f09596e 100644 --- a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp @@ -3962,13 +3962,11 @@ int *(d)(int); )txt")); } -TEST_P(SyntaxTreeTest, ConstVolatileQualifiers) { +TEST_P(SyntaxTreeTest, Declaration_ConstVolatileQualifiers_SimpleConst) { EXPECT_TRUE(treeDumpEqual( R"cpp( const int west = -1; int const east = 1; -const int const universal = 0; -const int const *const *volatile b; )cpp", R"txt( *: TranslationUnit @@ -3983,25 +3981,45 @@ const int const *const *volatile b; | | `-IntegerLiteralExpression | | `-1 | `-; -|-SimpleDeclaration -| |-int -| |-const -| |-SimpleDeclarator -| | |-east -| | |-= -| | `-IntegerLiteralExpression -| | `-1 -| `-; -|-SimpleDeclaration -| |-const -| |-int -| |-const -| |-SimpleDeclarator -| | |-universal -| | |-= -| | `-IntegerLiteralExpression -| | `-0 -| `-; +`-SimpleDeclaration + |-int + |-const + |-SimpleDeclarator + | |-east + | |-= + | `-IntegerLiteralExpression + | `-1 + `-; +)txt")); +} + +TEST_P(SyntaxTreeTest, Declaration_ConstVolatileQualifiers_MultipleConst) { + EXPECT_TRUE(treeDumpEqual( + R"cpp( +const int const universal = 0; +)cpp", + R"txt( +*: TranslationUnit +`-SimpleDeclaration + |-const + |-int + |-const + |-SimpleDeclarator + | |-universal + | |-= + | `-IntegerLiteralExpression + | `-0 + `-; +)txt")); +} + +TEST_P(SyntaxTreeTest, Declaration_ConstVolatileQualifiers_ConstAndVolatile) { + EXPECT_TRUE(treeDumpEqual( + R"cpp( +const int const *const *volatile b; +)cpp", + R"txt( +*: TranslationUnit `-SimpleDeclaration |-const |-int ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 5c11c08 - [SyntaxTree] Update `Declaration` tests to dump `NodeRole`
Author: Eduardo Caldas Date: 2020-08-25T06:34:47Z New Revision: 5c11c08d86f3ae45ec3b2b2766c48a3dc572d05e URL: https://github.com/llvm/llvm-project/commit/5c11c08d86f3ae45ec3b2b2766c48a3dc572d05e DIFF: https://github.com/llvm/llvm-project/commit/5c11c08d86f3ae45ec3b2b2766c48a3dc572d05e.diff LOG: [SyntaxTree] Update `Declaration` tests to dump `NodeRole` Added: Modified: clang/unittests/Tooling/Syntax/BuildTreeTest.cpp Removed: diff --git a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp index 04954c4ab73a..6fa4ff9b1094 100644 --- a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp @@ -2294,25 +2294,25 @@ int *a, b; int *c, d; )cpp", R"txt( -*: TranslationUnit +TranslationUnit Detached |-SimpleDeclaration -| |-int -| |-SimpleDeclarator -| | |-* -| | `-a -| |-, -| |-SimpleDeclarator -| | `-b -| `-; +| |-'int' +| |-SimpleDeclarator SimpleDeclaration_declarator +| | |-'*' +| | `-'a' +| |-',' +| |-SimpleDeclarator SimpleDeclaration_declarator +| | `-'b' +| `-';' `-SimpleDeclaration - |-int - |-SimpleDeclarator - | |-* - | `-c - |-, - |-SimpleDeclarator - | `-d - `-; + |-'int' + |-SimpleDeclarator SimpleDeclaration_declarator + | |-'*' + | `-'c' + |-',' + |-SimpleDeclarator SimpleDeclaration_declarator + | `-'d' + `-';' )txt")); } @@ -2322,17 +2322,17 @@ TEST_P(SyntaxTreeTest, MultipleDeclaratorsGroupingTypedef) { typedef int *a, b; )cpp", R"txt( -*: TranslationUnit +TranslationUnit Detached `-SimpleDeclaration - |-typedef - |-int - |-SimpleDeclarator - | |-* - | `-a - |-, - |-SimpleDeclarator - | `-b - `-; + |-'typedef' + |-'int' + |-SimpleDeclarator SimpleDeclaration_declarator + | |-'*' + | `-'a' + |-',' + |-SimpleDeclarator SimpleDeclaration_declarator + | `-'b' + `-';' )txt")); } @@ -2345,38 +2345,38 @@ void foo() { } )cpp", R"txt( -*: TranslationUnit +TranslationUnit Detached `-SimpleDeclaration - |-void - |-SimpleDeclarator - | |-foo + |-'void' + |-SimpleDeclarator SimpleDeclaration_declarator + | |-'foo' | `-ParametersAndQualifiers - | |-( - | `-) + | |-'(' OpenParen + | `-')' CloseParen `-CompoundStatement -|-{ -|-DeclarationStatement +|-'{' OpenParen +|-DeclarationStatement CompoundStatement_statement | |-SimpleDeclaration -| | |-int -| | |-SimpleDeclarator -| | | |-* -| | | `-a -| | |-, -| | `-SimpleDeclarator -| | `-b -| `-; -|-DeclarationStatement +| | |-'int' +| | |-SimpleDeclarator SimpleDeclaration_declarator +| | | |-'*' +| | | `-'a' +| | |-',' +| | `-SimpleDeclarator SimpleDeclaration_declarator +| | `-'b' +| `-';' +|-DeclarationStatement CompoundStatement_statement | |-SimpleDeclaration -| | |-typedef -| | |-int -| | |-SimpleDeclarator -| | | |-* -| | | `-ta -| | |-, -| | `-SimpleDeclarator -| | `-tb -| `-; -`-} +| | |-'typedef' +| | |-'int' +| | |-SimpleDeclarator SimpleDeclaration_declarator +| | | |-'*' +| | | `-'ta' +| | |-',' +| | `-SimpleDeclarator SimpleDeclaration_declarator +| | `-'tb' +| `-';' +`-'}' CloseParen )txt")); } @@ -2389,21 +2389,21 @@ TEST_P(SyntaxTreeTest, SizeTTypedef) { typedef decltype(sizeof(void *)) size_t; )cpp", R"txt( -*: TranslationUnit +TranslationUnit Detached `-SimpleDeclaration - |-typedef - |-decltype - |-( + |-'typedef' + |-'decltype' + |-'(' |-UnknownExpression - | |-sizeof - | |-( - | |-void - | |-* - | `-) - |-) - |-SimpleDeclarator - | `-size_t - `-; + | |-'sizeof' + | |-'(' + | |-'void' + | |-'*' + | `-')' + |-')' + |-SimpleDeclarator SimpleDeclaration_declarator + | `-'size_t' + `-';' )txt")); } @@ -2417,24 +2417,24 @@ namespace a { namespace b {} } namespace a::b {} )cpp", R"txt( -*: TranslationUnit +TranslationUnit Detached |-NamespaceDefinition -| |-namespace -| |-a -| |-{ +| |-'namespace' +| |-'a' +| |-'{' | |-NamespaceDefinition -| | |-namespace -| | |-b -| | |-{ -| | `-} -| `-} +| | |-'namespace' +| | |-'b' +| | |-'{' +| | `-'}' +| `-'}' `-NamespaceDefinition - |-namespace - |-a - |-:: - |-b - |-{ - `-} + |-'namespace' + |-'a' + |-'::' + |-'b' + |-'{' + `-'}' )txt")); } @@ -2447,11 +2447,11 @@ TEST_P(SyntaxTreeTest, Namespace_Unnamed) { namespace {} )cpp", R"txt( -*: TranslationUnit +TranslationUnit Detached `-NamespaceDefinition - |-namespace - |-{ - `-} + |-'namespace' + |-'{' + `-'}' )txt")); } @@ -2466,11 +2466,11 @@ namespace a {} )cpp", {R"txt( NamespaceAliasDefinition -|-namespace -|-foo -|-= -|-a -`-; +|-'namespace' +|-'foo' +|-'=' +|-'a' +`-';' )txt"})); } @@ -2485,12 +2485,12 @@ namespace ns {} )cpp", {R"txt( UsingNamespaceDirect
[clang] 6118ce7 - [SyntaxTree] Update `Expression` tests to dump `NodeRole`
Author: Eduardo Caldas Date: 2020-08-25T06:34:47Z New Revision: 6118ce79a3d3832c8bcbd985fbd2bf0bee4ea8a2 URL: https://github.com/llvm/llvm-project/commit/6118ce79a3d3832c8bcbd985fbd2bf0bee4ea8a2 DIFF: https://github.com/llvm/llvm-project/commit/6118ce79a3d3832c8bcbd985fbd2bf0bee4ea8a2.diff LOG: [SyntaxTree] Update `Expression` tests to dump `NodeRole` Added: Modified: clang/unittests/Tooling/Syntax/BuildTreeTest.cpp Removed: diff --git a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp index 2e84e78e4ac4..04954c4ab73a 100644 --- a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp @@ -305,48 +305,48 @@ void test() { } )cpp", R"txt( -*: TranslationUnit +TranslationUnit Detached `-SimpleDeclaration - |-void - |-SimpleDeclarator - | |-test + |-'void' + |-SimpleDeclarator SimpleDeclaration_declarator + | |-'test' | `-ParametersAndQualifiers - | |-( - | `-) + | |-'(' OpenParen + | `-')' CloseParen `-CompoundStatement -|-{ -|-ExpressionStatement -| |-UnknownExpression +|-'{' OpenParen +|-ExpressionStatement CompoundStatement_statement +| |-UnknownExpression ExpressionStatement_expression | | |-IdExpression -| | | `-UnqualifiedId -| | | `-test -| | |-( -| | `-) -| `-; -|-IfStatement -| |-if -| |-( +| | | `-UnqualifiedId IdExpression_id +| | | `-'test' +| | |-'(' +| | `-')' +| `-';' +|-IfStatement CompoundStatement_statement +| |-'if' IntroducerKeyword +| |-'(' | |-IntegerLiteralExpression -| | `-1 -| |-) -| |-ExpressionStatement -| | |-UnknownExpression +| | `-'1' LiteralToken +| |-')' +| |-ExpressionStatement IfStatement_thenStatement +| | |-UnknownExpression ExpressionStatement_expression | | | |-IdExpression -| | | | `-UnqualifiedId -| | | | `-test -| | | |-( -| | | `-) -| | `-; -| |-else -| `-ExpressionStatement -| |-UnknownExpression +| | | | `-UnqualifiedId IdExpression_id +| | | | `-'test' +| | | |-'(' +| | | `-')' +| | `-';' +| |-'else' IfStatement_elseKeyword +| `-ExpressionStatement IfStatement_elseStatement +| |-UnknownExpression ExpressionStatement_expression | | |-IdExpression -| | | `-UnqualifiedId -| | | `-test -| | |-( -| | `-) -| `-; -`-} +| | | `-UnqualifiedId IdExpression_id +| | | `-'test' +| | |-'(' +| | `-')' +| `-';' +`-'}' CloseParen )txt")); } @@ -358,9 +358,9 @@ void test(int a) { } )cpp", {R"txt( -IdExpression -`-UnqualifiedId - `-a +IdExpression ExpressionStatement_expression +`-UnqualifiedId IdExpression_id + `-'a' )txt"})); } @@ -378,20 +378,20 @@ void test(X x) { } )cpp", {R"txt( -UnknownExpression +UnknownExpression ExpressionStatement_expression |-IdExpression -| `-UnqualifiedId -| |-operator -| `-+ -|-( +| `-UnqualifiedId IdExpression_id +| |-'operator' +| `-'+' +|-'(' |-IdExpression -| `-UnqualifiedId -| `-x -|-, +| `-UnqualifiedId IdExpression_id +| `-'x' +|-',' |-IdExpression -| `-UnqualifiedId -| `-x -`-) +| `-UnqualifiedId IdExpression_id +| `-'x' +`-')' )txt"})); } @@ -409,18 +409,18 @@ void test(X x) { } )cpp", {R"txt( -UnknownExpression +UnknownExpression ExpressionStatement_expression |-MemberExpression -| |-IdExpression -| | `-UnqualifiedId -| | `-x -| |-. -| `-IdExpression -| `-UnqualifiedId -| |-operator -| `-int -|-( -`-) +| |-IdExpression MemberExpression_object +| | `-UnqualifiedId IdExpression_id +| | `-'x' +| |-'.' MemberExpression_accessToken +| `-IdExpression MemberExpression_member +| `-UnqualifiedId IdExpression_id +| |-'operator' +| `-'int' +|-'(' +`-')' )txt"})); } @@ -436,16 +436,16 @@ void test() { } )cpp", {R"txt( -UnknownExpression +UnknownExpression ExpressionStatement_expression |-IdExpression -| `-UnqualifiedId -| |-operator -| |-"" -| `-_w -|-( +| `-UnqualifiedId IdExpression_id +| |-'operator' +| |-'""' +| `-'_w' +|-'(' |-CharacterLiteralExpression -| `-'1' -`-) +| `-''1'' LiteralToken +`-')' )txt"})); } @@ -461,18 +461,18 @@ void test(X x) { } )cpp", {R"txt( -UnknownExpression +UnknownExpression ExpressionStatement_expression |-MemberExpression -| |-IdExpression -| | `-UnqualifiedId -| | `-x -| |-. -| `-IdExpression -| `-UnqualifiedId -| |-~ -| `-X -|-( -`-) +| |-IdExpression MemberExpression_object +| | `-UnqualifiedId IdExpression_id +| | `-'x' +| |-'.' MemberExpression_accessToken +| `-IdExpression MemberExpression_member +| `-UnqualifiedId IdExpression_id +| |-'~' +| `-'X' +|-'(' +`-')' )txt"})); } @@ -492,21 +492,21 @@ void test(X x) { } )cpp", {R"txt( -U
[clang] c655d80 - [SyntaxTree] Extend the syntax tree dump to also cover `NodeRole`
Author: Eduardo Caldas Date: 2020-08-25T06:34:40Z New Revision: c655d8081570336dda109502ed1e7a2eff1b26e2 URL: https://github.com/llvm/llvm-project/commit/c655d8081570336dda109502ed1e7a2eff1b26e2 DIFF: https://github.com/llvm/llvm-project/commit/c655d8081570336dda109502ed1e7a2eff1b26e2.diff LOG: [SyntaxTree] Extend the syntax tree dump to also cover `NodeRole` We should see `NodeRole` information in the dump because that exposes how the accessors will behave. Functional changes in the dump: * Surround Leaf tokens with `'` * Append `Node` dumps with `NodeRole` information, except for unknown roles * Append marks to `Node` dumps, instead of prepending Non-functional changes: * `::dumpTokens(llvm::raw_ostream, ArrayRef, const SourceManager &SM)` always received as parameter a `syntax::Token *` pointing to `Leaf::token()`. Changed the function to `dumpLeaf(llvm::raw_ostream, syntax::Leaf *, const SourceManager&)` * `dumpTree` acted on a Node, rename to `dumpNode` Differential Revision: https://reviews.llvm.org/D85330 Added: Modified: clang/include/clang/Tooling/Syntax/Tree.h clang/lib/Tooling/Syntax/BuildTree.cpp clang/lib/Tooling/Syntax/Tree.cpp clang/unittests/Tooling/Syntax/TreeTestBase.cpp Removed: diff --git a/clang/include/clang/Tooling/Syntax/Tree.h b/clang/include/clang/Tooling/Syntax/Tree.h index fcd169cad3ec..f7f9e6bdc5a0 100644 --- a/clang/include/clang/Tooling/Syntax/Tree.h +++ b/clang/include/clang/Tooling/Syntax/Tree.h @@ -106,9 +106,9 @@ class Node { Node *nextSibling() { return NextSibling; } /// Dumps the structure of a subtree. For debugging and testing purposes. - std::string dump(const Arena &A) const; + std::string dump(const SourceManager &SM) const; /// Dumps the tokens forming this subtree. - std::string dumpTokens(const Arena &A) const; + std::string dumpTokens(const SourceManager &SM) const; /// Asserts invariants on this node of the tree and its immediate children. /// Will not recurse into the subtree. No-op if NDEBUG is set. diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp index 3ab52ce5b7b4..f027a60030b7 100644 --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -546,7 +546,7 @@ class syntax::TreeBuilder { R += std::string( formatv("- '{0}' covers '{1}'+{2} tokens\n", It->second->kind(), It->first->text(A.sourceManager()), CoveredTokens)); -R += It->second->dump(A); +R += It->second->dump(A.sourceManager()); } return R; } diff --git a/clang/lib/Tooling/Syntax/Tree.cpp b/clang/lib/Tooling/Syntax/Tree.cpp index 70e3c8e02783..7dbceedfb48f 100644 --- a/clang/lib/Tooling/Syntax/Tree.cpp +++ b/clang/lib/Tooling/Syntax/Tree.cpp @@ -133,46 +133,45 @@ void syntax::Tree::replaceChildRangeLowLevel(Node *BeforeBegin, Node *End, } namespace { -static void dumpTokens(raw_ostream &OS, ArrayRef Tokens, - const SourceManager &SM) { - assert(!Tokens.empty()); - bool First = true; - for (const auto &T : Tokens) { -if (!First) - OS << " "; -else - First = false; -// Handle 'eof' separately, calling text() on it produces an empty string. -if (T.kind() == tok::eof) { - OS << ""; - continue; -} -OS << T.text(SM); - } +static void dumpLeaf(raw_ostream &OS, const syntax::Leaf *L, + const SourceManager &SM) { + assert(L); + const auto *Token = L->token(); + assert(Token); + // Handle 'eof' separately, calling text() on it produces an empty string. + if (Token->kind() == tok::eof) +OS << ""; + else +OS << Token->text(SM); } -static void dumpTree(raw_ostream &OS, const syntax::Node *N, - const syntax::Arena &A, std::vector IndentMask) { - std::string Marks; - if (!N->isOriginal()) -Marks += "M"; - if (N->role() == syntax::NodeRole::Detached) -Marks += "*"; // FIXME: find a nice way to print other roles. - if (!N->canModify()) -Marks += "I"; - if (!Marks.empty()) -OS << Marks << ": "; - - if (auto *L = dyn_cast(N)) { -dumpTokens(OS, *L->token(), A.sourceManager()); +static void dumpNode(raw_ostream &OS, const syntax::Node *N, + const SourceManager &SM, std::vector IndentMask) { + auto dumpExtraInfo = [&OS](const syntax::Node *N) { +if (N->role() != syntax::NodeRole::Unknown) + OS << " " << N->role(); +if (!N->isOriginal()) + OS << " synthesized"; +if (!N->canModify()) + OS << " unmodifiable"; + }; + + assert(N); + if (const auto *L = dyn_cast(N)) { +OS << "'"; +dumpLeaf(OS, L, SM); +OS << "'"; +dumpExtraInfo(N); OS << "\n"; return; } - auto *T = cast(N); - OS << T->kind() << "\n"; + const auto *T = cast(N); + OS << T->kind(); + dumpExtraInfo(N); + OS << "\n
[clang] 02a9f8a - [SyntaxTree] Update `Statement` tests to dump `NodeRole`
Author: Eduardo Caldas Date: 2020-08-25T06:34:47Z New Revision: 02a9f8a27b7f22e4a499c5511142bd2650defad1 URL: https://github.com/llvm/llvm-project/commit/02a9f8a27b7f22e4a499c5511142bd2650defad1 DIFF: https://github.com/llvm/llvm-project/commit/02a9f8a27b7f22e4a499c5511142bd2650defad1.diff LOG: [SyntaxTree] Update `Statement` tests to dump `NodeRole` Added: Modified: clang/unittests/Tooling/Syntax/BuildTreeTest.cpp Removed: diff --git a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp index 0d24432115cc..2e84e78e4ac4 100644 --- a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp @@ -24,27 +24,27 @@ int main() {} void foo() {} )cpp", R"txt( -*: TranslationUnit +TranslationUnit Detached |-SimpleDeclaration -| |-int -| |-SimpleDeclarator -| | |-main +| |-'int' +| |-SimpleDeclarator SimpleDeclaration_declarator +| | |-'main' | | `-ParametersAndQualifiers -| | |-( -| | `-) +| | |-'(' OpenParen +| | `-')' CloseParen | `-CompoundStatement -| |-{ -| `-} +| |-'{' OpenParen +| `-'}' CloseParen `-SimpleDeclaration - |-void - |-SimpleDeclarator - | |-foo + |-'void' + |-SimpleDeclarator SimpleDeclaration_declarator + | |-'foo' | `-ParametersAndQualifiers - | |-( - | `-) + | |-'(' OpenParen + | `-')' CloseParen `-CompoundStatement -|-{ -`-} +|-'{' OpenParen +`-'}' CloseParen )txt")); } @@ -55,20 +55,20 @@ int a; int b = 42; )cpp", R"txt( -*: TranslationUnit +TranslationUnit Detached |-SimpleDeclaration -| |-int -| |-SimpleDeclarator -| | `-a -| `-; +| |-'int' +| |-SimpleDeclarator SimpleDeclaration_declarator +| | `-'a' +| `-';' `-SimpleDeclaration - |-int - |-SimpleDeclarator - | |-b - | |-= + |-'int' + |-SimpleDeclarator SimpleDeclaration_declarator + | |-'b' + | |-'=' | `-IntegerLiteralExpression - | `-42 - `-; + | `-'42' LiteralToken + `-';' )txt")); } @@ -78,26 +78,26 @@ TEST_P(SyntaxTreeTest, SimpleFunction) { void foo(int a, int b) {} )cpp", R"txt( -*: TranslationUnit +TranslationUnit Detached `-SimpleDeclaration - |-void - |-SimpleDeclarator - | |-foo + |-'void' + |-SimpleDeclarator SimpleDeclaration_declarator + | |-'foo' | `-ParametersAndQualifiers - | |-( - | |-SimpleDeclaration - | | |-int - | | `-SimpleDeclarator - | | `-a - | |-, - | |-SimpleDeclaration - | | |-int - | | `-SimpleDeclarator - | | `-b - | `-) + | |-'(' OpenParen + | |-SimpleDeclaration ParametersAndQualifiers_parameter + | | |-'int' + | | `-SimpleDeclarator SimpleDeclaration_declarator + | | `-'a' + | |-',' + | |-SimpleDeclaration ParametersAndQualifiers_parameter + | | |-'int' + | | `-SimpleDeclarator SimpleDeclaration_declarator + | | `-'b' + | `-')' CloseParen `-CompoundStatement -|-{ -`-} +|-'{' OpenParen +`-'}' CloseParen )txt")); } @@ -110,36 +110,36 @@ void test() { } )cpp", {R"txt( -IfStatement -|-if -|-( +IfStatement CompoundStatement_statement +|-'if' IntroducerKeyword +|-'(' |-IntegerLiteralExpression -| `-1 -|-) -`-CompoundStatement - |-{ - `-} +| `-'1' LiteralToken +|-')' +`-CompoundStatement IfStatement_thenStatement + |-'{' OpenParen + `-'}' CloseParen )txt", R"txt( -IfStatement -|-if -|-( +IfStatement CompoundStatement_statement +|-'if' IntroducerKeyword +|-'(' |-IntegerLiteralExpression -| `-1 -|-) -|-CompoundStatement -| |-{ -| `-} -|-else -`-IfStatement - |-if - |-( +| `-'1' LiteralToken +|-')' +|-CompoundStatement IfStatement_thenStatement +| |-'{' OpenParen +| `-'}' CloseParen +|-'else' IfStatement_elseKeyword +`-IfStatement IfStatement_elseStatement + |-'if' IntroducerKeyword + |-'(' |-IntegerLiteralExpression - | `-0 - |-) - `-CompoundStatement -|-{ -`-} + | `-'0' LiteralToken + |-')' + `-CompoundStatement IfStatement_thenStatement +|-'{' OpenParen +`-'}' CloseParen )txt"})); } @@ -151,15 +151,15 @@ void test() { } )cpp", {R"txt( -ForStatement -|-for -|-( -|-; -|-; -|-) -`-CompoundStatement - |-{ - `-} +ForStatement CompoundStatement_statement +|-'for' IntroducerKeyword +|-'(' +|-';' +|-';' +|-')' +`-CompoundStatement BodyStatement + |-'{' OpenParen + `-'}' CloseParen )txt"})); } @@ -176,20 +176,20 @@ void test() { } )cpp", {R"txt( -RangeBasedForStatement -|-for -|-( +RangeBasedForStatement CompoundStatement_statement +|-'for' IntroducerKeyword +|-'(' |-SimpleDeclaration -| |-int -| |-SimpleDeclarator -| | `-x -| `-: +| |-'int' +| |-SimpleDeclarator SimpleDeclaration_declarator +| | `-'x' +| `-':' |-IdExpression -| `-UnqualifiedId -| `-a -|-) -`-EmptyStatement - `-; +| `-UnqualifiedId IdExpression_id +| `-'a' +|-')' +`-EmptyStatement BodyStatement + `-';' )txt"})); } @@ -201,15 +201,15 @@ void
[clang] be2bc7d - [SyntaxTree] Update `Modifiable` tests to dump `NodeRole` and `unmodifiable` tag
Author: Eduardo Caldas Date: 2020-08-25T06:34:48Z New Revision: be2bc7d4cef2edd66c7fb74b70adf62fc68754db URL: https://github.com/llvm/llvm-project/commit/be2bc7d4cef2edd66c7fb74b70adf62fc68754db DIFF: https://github.com/llvm/llvm-project/commit/be2bc7d4cef2edd66c7fb74b70adf62fc68754db.diff LOG: [SyntaxTree] Update `Modifiable` tests to dump `NodeRole` and `unmodifiable` tag Added: Modified: clang/unittests/Tooling/Syntax/BuildTreeTest.cpp Removed: diff --git a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp index 6fa4ff9b1094..398f12c45081 100644 --- a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp @@ -3231,34 +3231,34 @@ void test() { HALF_IF HALF_IF_2 else {} })cpp", R"txt( -*: TranslationUnit +TranslationUnit Detached `-SimpleDeclaration - |-void - |-SimpleDeclarator - | |-test + |-'void' + |-SimpleDeclarator SimpleDeclaration_declarator + | |-'test' | `-ParametersAndQualifiers - | |-( - | `-) + | |-'(' OpenParen + | `-')' CloseParen `-CompoundStatement -|-{ -|-IfStatement -| |-I: if -| |-I: ( -| |-I: BinaryOperatorExpression -| | |-I: IntegerLiteralExpression -| | | `-I: 1 -| | |-I: + -| | `-I: IntegerLiteralExpression -| | `-I: 1 -| |-I: ) -| |-I: CompoundStatement -| | |-I: { -| | `-I: } -| |-else -| `-CompoundStatement -| |-{ -| `-} -`-} +|-'{' OpenParen +|-IfStatement CompoundStatement_statement +| |-'if' IntroducerKeyword unmodifiable +| |-'(' unmodifiable +| |-BinaryOperatorExpression unmodifiable +| | |-IntegerLiteralExpression BinaryOperatorExpression_leftHandSide unmodifiable +| | | `-'1' LiteralToken unmodifiable +| | |-'+' OperatorExpression_operatorToken unmodifiable +| | `-IntegerLiteralExpression BinaryOperatorExpression_rightHandSide unmodifiable +| | `-'1' LiteralToken unmodifiable +| |-')' unmodifiable +| |-CompoundStatement IfStatement_thenStatement unmodifiable +| | |-'{' OpenParen unmodifiable +| | `-'}' CloseParen unmodifiable +| |-'else' IfStatement_elseKeyword +| `-CompoundStatement IfStatement_elseStatement +| |-'{' OpenParen +| `-'}' CloseParen +`-'}' CloseParen )txt")); } @@ -3280,31 +3280,31 @@ void test() { } )cpp", R"txt( -*: TranslationUnit +TranslationUnit Detached `-SimpleDeclaration - |-void - |-SimpleDeclarator - | |-test + |-'void' + |-SimpleDeclarator SimpleDeclaration_declarator + | |-'test' | `-ParametersAndQualifiers - | |-( - | `-) + | |-'(' OpenParen + | `-')' CloseParen `-CompoundStatement -|-{ -|-CompoundStatement -| |-{ -| |-ExpressionStatement -| | |-IntegerLiteralExpression -| | | `-1 -| | `-; -| `-} -|-CompoundStatement -| |-{ -| |-ExpressionStatement -| | |-IntegerLiteralExpression -| | | `-2 -| | `-; -| `-} -`-} +|-'{' OpenParen +|-CompoundStatement CompoundStatement_statement +| |-'{' OpenParen +| |-ExpressionStatement CompoundStatement_statement +| | |-IntegerLiteralExpression ExpressionStatement_expression +| | | `-'1' LiteralToken +| | `-';' +| `-'}' CloseParen +|-CompoundStatement CompoundStatement_statement +| |-'{' OpenParen +| |-ExpressionStatement CompoundStatement_statement +| | |-IntegerLiteralExpression ExpressionStatement_expression +| | | `-'2' LiteralToken +| | `-';' +| `-'}' CloseParen +`-'}' CloseParen )txt")); } ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 2de2ca3 - [SyntaxTree] Add support for `CallExpression`
Author: Eduardo Caldas Date: 2020-08-26T07:03:49Z New Revision: 2de2ca348dfa09963eb33ddf71c9cbb59612c16a URL: https://github.com/llvm/llvm-project/commit/2de2ca348dfa09963eb33ddf71c9cbb59612c16a DIFF: https://github.com/llvm/llvm-project/commit/2de2ca348dfa09963eb33ddf71c9cbb59612c16a.diff LOG: [SyntaxTree] Add support for `CallExpression` * Generate `CallExpression` syntax node for all semantic nodes inheriting from `CallExpr` with call-expression syntax - except `CUDAKernelCallExpr`. * Implement all the accessors * Arguments of `CallExpression` have their own syntax node which is based on the `List` base API Differential Revision: https://reviews.llvm.org/D86544 Added: Modified: clang/include/clang/Tooling/Syntax/Nodes.h clang/lib/Tooling/Syntax/BuildTree.cpp clang/lib/Tooling/Syntax/Nodes.cpp clang/unittests/Tooling/Syntax/BuildTreeTest.cpp Removed: diff --git a/clang/include/clang/Tooling/Syntax/Nodes.h b/clang/include/clang/Tooling/Syntax/Nodes.h index 0b3991768008..9a14aac130b4 100644 --- a/clang/include/clang/Tooling/Syntax/Nodes.h +++ b/clang/include/clang/Tooling/Syntax/Nodes.h @@ -57,6 +57,7 @@ enum class NodeKind : uint16_t { IdExpression, MemberExpression, ThisExpression, + CallExpression, // Statements. UnknownStatement, @@ -103,7 +104,8 @@ enum class NodeKind : uint16_t { GlobalNameSpecifier, DecltypeNameSpecifier, IdentifierNameSpecifier, - SimpleTemplateNameSpecifier + SimpleTemplateNameSpecifier, + CallArguments }; /// For debugging purposes. raw_ostream &operator<<(raw_ostream &OS, NodeKind K); @@ -179,6 +181,8 @@ enum class NodeRole : uint8_t { MemberExpression_object, MemberExpression_accessToken, MemberExpression_member, + CallExpression_callee, + CallExpression_arguments, }; /// For debugging purposes. raw_ostream &operator<<(raw_ostream &OS, NodeRole R); @@ -324,6 +328,37 @@ class ThisExpression final : public Expression { Leaf *thisKeyword(); }; +/// Models arguments of a function call. +/// call-arguments: +/// delimited_list(expression, ',') +/// Note: This construct is a simplification of the grammar rule for +/// `expression-list`, that is used in the definition of `call-expression` +class CallArguments final : public List { +public: + CallArguments() : List(NodeKind::CallArguments) {} + static bool classof(const Node *N) { +return N->kind() <= NodeKind::CallArguments; + } + std::vector arguments(); + std::vector> argumentsAndCommas(); +}; + +/// A function call. C++ [expr.call] +/// call-expression: +/// expression '(' call-arguments ')' +/// e.g `f(1, '2')` or `this->Base::f()` +class CallExpression final : public Expression { +public: + CallExpression() : Expression(NodeKind::CallExpression) {} + static bool classof(const Node *N) { +return N->kind() == NodeKind::CallExpression; + } + Expression *callee(); + Leaf *openParen(); + CallArguments *arguments(); + Leaf *closeParen(); +}; + /// Models a parenthesized expression `(E)`. C++ [expr.prim.paren] /// e.g. `(3 + 2)` in `a = 1 + (3 + 2);` class ParenExpression final : public Expression { diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp index f027a60030b7..2e3dbc6c6fbd 100644 --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -184,10 +184,11 @@ static syntax::NodeKind getOperatorNodeKind(const CXXOperatorCallExpr &E) { case OO_Array_New: case OO_Array_Delete: case OO_Coawait: - case OO_Call: case OO_Subscript: case OO_Arrow: return syntax::NodeKind::UnknownExpression; + case OO_Call: +return syntax::NodeKind::CallExpression; case OO_Conditional: // not overloadable case NUM_OVERLOADED_OPERATORS: case OO_None: @@ -1042,6 +1043,46 @@ class BuildTreeVisitor : public RecursiveASTVisitor { return true; } + syntax::CallArguments *buildCallArguments(CallExpr::arg_range Args) { +for (const auto &Arg : Args) { + Builder.markExprChild(Arg, syntax::NodeRole::List_element); + const auto *DelimiterToken = + std::next(Builder.findToken(Arg->getEndLoc())); + if (DelimiterToken->kind() == clang::tok::TokenKind::comma) +Builder.markChildToken(DelimiterToken, + syntax::NodeRole::List_delimiter); +} + +auto *Arguments = new (allocator()) syntax::CallArguments; +if (!Args.empty()) + Builder.foldNode(Builder.getRange((*Args.begin())->getBeginLoc(), +(*(Args.end() - 1))->getEndLoc()), + Arguments, nullptr); + +return Arguments; + } + + bool WalkUpFromCallExpr(CallExpr *S) { +Builder.markExprChild(S->getCallee(), + syntax::NodeRole::CallExpression_callee); + +const auto *LParenToken = +std::next(Builder.findToken(S->getCa
[clang] 3b75f65 - [SyntaxTree] Fix C++ versions on tests of `BuildTreeTest.cpp`
Author: Eduardo Caldas Date: 2020-08-26T07:19:49Z New Revision: 3b75f65e6ba4862977fd193ddb4918c4fc380fa5 URL: https://github.com/llvm/llvm-project/commit/3b75f65e6ba4862977fd193ddb4918c4fc380fa5 DIFF: https://github.com/llvm/llvm-project/commit/3b75f65e6ba4862977fd193ddb4918c4fc380fa5.diff LOG: [SyntaxTree] Fix C++ versions on tests of `BuildTreeTest.cpp` Differential Revision: https://reviews.llvm.org/D86591 Added: Modified: clang/unittests/Tooling/Syntax/BuildTreeTest.cpp Removed: diff --git a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp index 6ab01e8f65f0..e386646ee667 100644 --- a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp @@ -2870,20 +2870,32 @@ TEST_P(SyntaxTreeTest, Namespace_Nested) { EXPECT_TRUE(treeDumpEqual( R"cpp( namespace a { namespace b {} } +)cpp", + R"txt( +TranslationUnit Detached +`-NamespaceDefinition + |-'namespace' + |-'a' + |-'{' + |-NamespaceDefinition + | |-'namespace' + | |-'b' + | |-'{' + | `-'}' + `-'}' +)txt")); +} + +TEST_P(SyntaxTreeTest, Namespace_NestedDefinition) { + if (!GetParam().isCXX17OrLater()) { +return; + } + EXPECT_TRUE(treeDumpEqual( + R"cpp( namespace a::b {} )cpp", R"txt( TranslationUnit Detached -|-NamespaceDefinition -| |-'namespace' -| |-'a' -| |-'{' -| |-NamespaceDefinition -| | |-'namespace' -| | |-'b' -| | |-'{' -| | `-'}' -| `-'}' `-NamespaceDefinition |-'namespace' |-'a' @@ -3006,7 +3018,7 @@ UsingDeclaration } TEST_P(SyntaxTreeTest, UsingTypeAlias) { - if (!GetParam().isCXX()) { + if (!GetParam().isCXX11OrLater()) { return; } EXPECT_TRUE(treeDumpEqual( @@ -3307,7 +3319,7 @@ TranslationUnit Detached } TEST_P(SyntaxTreeTest, VariableTemplateDeclaration) { - if (!GetParam().isCXX()) { + if (!GetParam().isCXX14OrLater()) { return; } EXPECT_TRUE(treeDumpEqual( @@ -3616,20 +3628,32 @@ TEST_P(SyntaxTreeTest, StaticAssert) { EXPECT_TRUE(treeDumpEqual( R"cpp( static_assert(true, "message"); +)cpp", + R"txt( +TranslationUnit Detached +`-StaticAssertDeclaration + |-'static_assert' + |-'(' + |-BoolLiteralExpression StaticAssertDeclaration_condition + | `-'true' LiteralToken + |-',' + |-StringLiteralExpression StaticAssertDeclaration_message + | `-'"message"' LiteralToken + |-')' + `-';' +)txt")); +} + +TEST_P(SyntaxTreeTest, StaticAssert_WithoutMessage) { + if (!GetParam().isCXX17OrLater()) { +return; + } + EXPECT_TRUE(treeDumpEqual( + R"cpp( static_assert(true); )cpp", R"txt( TranslationUnit Detached -|-StaticAssertDeclaration -| |-'static_assert' -| |-'(' -| |-BoolLiteralExpression StaticAssertDeclaration_condition -| | `-'true' LiteralToken -| |-',' -| |-StringLiteralExpression StaticAssertDeclaration_message -| | `-'"message"' LiteralToken -| |-')' -| `-';' `-StaticAssertDeclaration |-'static_assert' |-'(' @@ -4165,7 +4189,7 @@ SimpleDeclaration } TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InMemberFunctions_Ref) { - if (!GetParam().isCXX()) { + if (!GetParam().isCXX11OrLater()) { return; } EXPECT_TRUE(treeDumpEqualOnAnnotations( ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] dc3d474 - [SyntaxTree] Migrate `ParamatersAndQualifiers` to use the new List API
Author: Eduardo Caldas Date: 2020-08-26T16:46:19Z New Revision: dc3d4743277b47c0bc8cddbeb4b5e265252ee304 URL: https://github.com/llvm/llvm-project/commit/dc3d4743277b47c0bc8cddbeb4b5e265252ee304 DIFF: https://github.com/llvm/llvm-project/commit/dc3d4743277b47c0bc8cddbeb4b5e265252ee304.diff LOG: [SyntaxTree] Migrate `ParamatersAndQualifiers` to use the new List API Fix: Add missing `List::getTerminationKind()`, `List::canBeEmpty()`, `List::getDelimiterTokenKind()` for `CallArguments`. Differential Revision: https://reviews.llvm.org/D86600 Added: Modified: clang/include/clang/Tooling/Syntax/Nodes.h clang/lib/Tooling/Syntax/BuildTree.cpp clang/lib/Tooling/Syntax/Nodes.cpp clang/lib/Tooling/Syntax/Tree.cpp clang/unittests/Tooling/Syntax/BuildTreeTest.cpp Removed: diff --git a/clang/include/clang/Tooling/Syntax/Nodes.h b/clang/include/clang/Tooling/Syntax/Nodes.h index 9a14aac130b4..38f936f603dd 100644 --- a/clang/include/clang/Tooling/Syntax/Nodes.h +++ b/clang/include/clang/Tooling/Syntax/Nodes.h @@ -99,6 +99,7 @@ enum class NodeKind : uint16_t { ParametersAndQualifiers, MemberPointer, UnqualifiedId, + ParameterDeclarationList, // Nested Name Specifiers. NestedNameSpecifier, GlobalNameSpecifier, @@ -173,7 +174,7 @@ enum class NodeRole : uint8_t { ExplicitTemplateInstantiation_declaration, ArraySubscript_sizeExpression, TrailingReturnType_declarator, - ParametersAndQualifiers_parameter, + ParametersAndQualifiers_parameters, ParametersAndQualifiers_trailingReturn, IdExpression_id, IdExpression_qualifier, @@ -988,6 +989,19 @@ class TrailingReturnType final : public Tree { SimpleDeclarator *declarator(); }; +/// Models a `parameter-declaration-list` which appears within +/// `parameters-and-qualifiers`. See C++ [dcl.fct] +class ParameterDeclarationList final : public List { +public: + ParameterDeclarationList() : List(NodeKind::ParameterDeclarationList) {} + static bool classof(const Node *N) { +return N->kind() == NodeKind::ParameterDeclarationList; + } + std::vector parameterDeclarations(); + std::vector> + parametersAndCommas(); +}; + /// Parameter list for a function type and a trailing return type, if the /// function has one. /// E.g.: @@ -1006,8 +1020,7 @@ class ParametersAndQualifiers final : public Tree { return N->kind() == NodeKind::ParametersAndQualifiers; } Leaf *lparen(); - /// FIXME: use custom iterator instead of 'vector'. - std::vector parameters(); + ParameterDeclarationList *parameters(); Leaf *rparen(); TrailingReturnType *trailingReturn(); }; diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp index 2e3dbc6c6fbd..deae46d58eee 100644 --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -1209,11 +1209,29 @@ class BuildTreeVisitor : public RecursiveASTVisitor { return true; } + syntax::ParameterDeclarationList * + buildParameterDeclarationList(ArrayRef Params) { +for (auto *P : Params) { + Builder.markChild(P, syntax::NodeRole::List_element); + const auto *DelimiterToken = std::next(Builder.findToken(P->getEndLoc())); + if (DelimiterToken->kind() == clang::tok::TokenKind::comma) +Builder.markChildToken(DelimiterToken, + syntax::NodeRole::List_delimiter); +} +auto *Parameters = new (allocator()) syntax::ParameterDeclarationList; +if (!Params.empty()) + Builder.foldNode(Builder.getRange(Params.front()->getBeginLoc(), +Params.back()->getEndLoc()), + Parameters, nullptr); +return Parameters; + } + bool WalkUpFromFunctionTypeLoc(FunctionTypeLoc L) { Builder.markChildToken(L.getLParenLoc(), syntax::NodeRole::OpenParen); -for (auto *P : L.getParams()) { - Builder.markChild(P, syntax::NodeRole::ParametersAndQualifiers_parameter); -} + +Builder.markChild(buildParameterDeclarationList(L.getParams()), + syntax::NodeRole::ParametersAndQualifiers_parameters); + Builder.markChildToken(L.getRParenLoc(), syntax::NodeRole::CloseParen); Builder.foldNode(Builder.getRange(L.getLParenLoc(), L.getEndLoc()), new (allocator()) syntax::ParametersAndQualifiers, L); diff --git a/clang/lib/Tooling/Syntax/Nodes.cpp b/clang/lib/Tooling/Syntax/Nodes.cpp index 6a7be0f0ea79..984cc5d1f1fc 100644 --- a/clang/lib/Tooling/Syntax/Nodes.cpp +++ b/clang/lib/Tooling/Syntax/Nodes.cpp @@ -134,6 +134,8 @@ raw_ostream &syntax::operator<<(raw_ostream &OS, NodeKind K) { return OS << "MemberExpression"; case NodeKind::CallArguments: return OS << "CallArguments"; + case NodeKind::ParameterDeclarationList: +return OS << "ParameterDeclarationList"; } llvm_unreachable("unknown node kind"); } @@ -200,8 +
[clang] ac87a0b - [SyntaxTree][NFC][Style] Functions start with lowercase
Author: Eduardo Caldas Date: 2020-08-27T12:55:24Z New Revision: ac87a0b5873cc14b23eeb25a0586b26cc5c2c33f URL: https://github.com/llvm/llvm-project/commit/ac87a0b5873cc14b23eeb25a0586b26cc5c2c33f DIFF: https://github.com/llvm/llvm-project/commit/ac87a0b5873cc14b23eeb25a0586b26cc5c2c33f.diff LOG: [SyntaxTree][NFC][Style] Functions start with lowercase Differential Revision: https://reviews.llvm.org/D86682 Added: Modified: clang/lib/Tooling/Syntax/BuildTree.cpp Removed: diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp index 9e2f8178df90..b07e9c3faf9d 100644 --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -820,7 +820,7 @@ class BuildTreeVisitor : public RecursiveASTVisitor { } syntax::NameSpecifier * - BuildNameSpecifier(const NestedNameSpecifierLoc &NNSLoc) { + buildNameSpecifier(const NestedNameSpecifierLoc &NNSLoc) { assert(NNSLoc.hasQualifier()); auto NameSpecifierTokens = Builder.getRange(getLocalSourceRange(NNSLoc)).drop_back(); @@ -870,7 +870,7 @@ class BuildTreeVisitor : public RecursiveASTVisitor { if (!QualifierLoc) return true; for (auto it = QualifierLoc; it; it = it.getPrefix()) { - auto *NS = BuildNameSpecifier(it); + auto *NS = buildNameSpecifier(it); if (!NS) return false; Builder.markChild(NS, syntax::NodeRole::ListElement); @@ -1221,7 +1221,7 @@ class BuildTreeVisitor : public RecursiveASTVisitor { if (!L.getTypePtr()->hasTrailingReturn()) return WalkUpFromFunctionTypeLoc(L); -auto *TrailingReturnTokens = BuildTrailingReturn(L); +auto *TrailingReturnTokens = buildTrailingReturn(L); // Finish building the node for parameters. Builder.markChild(TrailingReturnTokens, syntax::NodeRole::TrailingReturn); return WalkUpFromFunctionTypeLoc(L); @@ -1459,7 +1459,7 @@ class BuildTreeVisitor : public RecursiveASTVisitor { } /// Returns the range of the built node. - syntax::TrailingReturnType *BuildTrailingReturn(FunctionProtoTypeLoc L) { + syntax::TrailingReturnType *buildTrailingReturn(FunctionProtoTypeLoc L) { assert(L.getTypePtr()->hasTrailingReturn()); auto ReturnedType = L.getReturnLoc(); ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] fda3fa8 - [SyntaxTree][NFC] Append "get" to syntax Nodes accessor names
Author: Eduardo Caldas Date: 2020-08-27T12:55:23Z New Revision: fda3fa822cb6812c8db63f7cee4a8387e71e66ff URL: https://github.com/llvm/llvm-project/commit/fda3fa822cb6812c8db63f7cee4a8387e71e66ff DIFF: https://github.com/llvm/llvm-project/commit/fda3fa822cb6812c8db63f7cee4a8387e71e66ff.diff LOG: [SyntaxTree][NFC] Append "get" to syntax Nodes accessor names Differential Revision: https://reviews.llvm.org/D86679 Added: Modified: clang/include/clang/Tooling/Syntax/Nodes.h clang/lib/Tooling/Syntax/Nodes.cpp Removed: diff --git a/clang/include/clang/Tooling/Syntax/Nodes.h b/clang/include/clang/Tooling/Syntax/Nodes.h index 4a483111aad3..a6505c8167ee 100644 --- a/clang/include/clang/Tooling/Syntax/Nodes.h +++ b/clang/include/clang/Tooling/Syntax/Nodes.h @@ -271,9 +271,9 @@ class NestedNameSpecifier final : public List { static bool classof(const Node *N) { return N->kind() <= NodeKind::NestedNameSpecifier; } - std::vector specifiers(); + std::vector getSpecifiers(); std::vector> - specifiersAndDoubleColons(); + getSpecifiersAndDoubleColons(); }; /// Models an `unqualified-id`. C++ [expr.prim.id.unqual] @@ -299,9 +299,9 @@ class IdExpression final : public Expression { static bool classof(const Node *N) { return N->kind() == NodeKind::IdExpression; } - NestedNameSpecifier *qualifier(); - Leaf *templateKeyword(); - UnqualifiedId *unqualifiedId(); + NestedNameSpecifier *getQualifier(); + Leaf *getTemplateKeyword(); + UnqualifiedId *getUnqualifiedId(); }; /// An expression of an unknown kind, i.e. one not currently handled by the @@ -321,7 +321,7 @@ class ThisExpression final : public Expression { static bool classof(const Node *N) { return N->kind() == NodeKind::ThisExpression; } - Leaf *thisKeyword(); + Leaf *getThisKeyword(); }; /// Models arguments of a function call. @@ -335,8 +335,8 @@ class CallArguments final : public List { static bool classof(const Node *N) { return N->kind() <= NodeKind::CallArguments; } - std::vector arguments(); - std::vector> argumentsAndCommas(); + std::vector getArguments(); + std::vector> getArgumentsAndCommas(); }; /// A function call. C++ [expr.call] @@ -349,10 +349,10 @@ class CallExpression final : public Expression { static bool classof(const Node *N) { return N->kind() == NodeKind::CallExpression; } - Expression *callee(); - Leaf *openParen(); - CallArguments *arguments(); - Leaf *closeParen(); + Expression *getCallee(); + Leaf *getOpenParen(); + CallArguments *getArguments(); + Leaf *getCloseParen(); }; /// Models a parenthesized expression `(E)`. C++ [expr.prim.paren] @@ -363,9 +363,9 @@ class ParenExpression final : public Expression { static bool classof(const Node *N) { return N->kind() == NodeKind::ParenExpression; } - Leaf *openParen(); - Expression *subExpression(); - Leaf *closeParen(); + Leaf *getOpenParen(); + Expression *getSubExpression(); + Leaf *getCloseParen(); }; /// Models a class member access. C++ [expr.ref] @@ -382,10 +382,10 @@ class MemberExpression final : public Expression { static bool classof(const Node *N) { return N->kind() == NodeKind::MemberExpression; } - Expression *object(); - Leaf *accessToken(); - Leaf *templateKeyword(); - IdExpression *member(); + Expression *getObject(); + Leaf *getAccessToken(); + Leaf *getTemplateKeyword(); + IdExpression *getMember(); }; /// Expression for literals. C++ [lex.literal] @@ -404,7 +404,7 @@ class LiteralExpression : public Expression { N->kind() == NodeKind::CharUserDefinedLiteralExpression || N->kind() == NodeKind::StringUserDefinedLiteralExpression; } - Leaf *literalToken(); + Leaf *getLiteralToken(); }; /// Expression for integer literals. C++ [lex.icon] @@ -539,8 +539,8 @@ class UnaryOperatorExpression : public Expression { return N->kind() == NodeKind::PrefixUnaryOperatorExpression || N->kind() == NodeKind::PostfixUnaryOperatorExpression; } - Leaf *operatorToken(); - Expression *operand(); + Leaf *getOperatorToken(); + Expression *getOperand(); }; /// @@ -588,9 +588,9 @@ class BinaryOperatorExpression final : public Expression { static bool classof(const Node *N) { return N->kind() == NodeKind::BinaryOperatorExpression; } - Expression *lhs(); - Leaf *operatorToken(); - Expression *rhs(); + Expression *getLhs(); + Leaf *getOperatorToken(); + Expression *getRhs(); }; /// An abstract node for C++ statements, e.g. 'while', 'if', etc. @@ -639,8 +639,8 @@ class SwitchStatement final : public Statement { static bool classof(const Node *N) { return N->kind() == NodeKind::SwitchStatement; } - Leaf *switchKeyword(); - Statement *body(); + Leaf *getSwitchKeyword(); + Statement *getBody(); }; /// case : @@ -650,9 +650,9 @@ class CaseStatement final : public
[clang] 38bc006 - [SyntaxTree][NFC] Refactor function templates into functions taking base class
Author: Eduardo Caldas Date: 2020-08-28T12:19:38Z New Revision: 38bc0060e60fef5395c23b8b75163e5bdee23af6 URL: https://github.com/llvm/llvm-project/commit/38bc0060e60fef5395c23b8b75163e5bdee23af6 DIFF: https://github.com/llvm/llvm-project/commit/38bc0060e60fef5395c23b8b75163e5bdee23af6.diff LOG: [SyntaxTree][NFC] Refactor function templates into functions taking base class The refactored functions were * `isReponsibleForCreatingDeclaration` * `getQualifiedNameStart` Differential Revision: https://reviews.llvm.org/D86719 Added: Modified: clang/lib/Tooling/Syntax/BuildTree.cpp Removed: diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp index b07e9c3faf9d..2e9e74401e71 100644 --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -197,18 +197,57 @@ static syntax::NodeKind getOperatorNodeKind(const CXXOperatorCallExpr &E) { llvm_unreachable("Unknown OverloadedOperatorKind enum"); } +/// Get the start of the qualified name. In the examples below it gives the +/// location of the `^`: +/// `int ^a;` +/// `int ^a::S::f(){}` +static SourceLocation getQualifiedNameStart(NamedDecl *D) { + assert((isa(D)) && + "only DeclaratorDecl and TypedefNameDecl are supported."); + + auto DN = D->getDeclName(); + bool IsAnonymous = DN.isIdentifier() && !DN.getAsIdentifierInfo(); + if (IsAnonymous) +return SourceLocation(); + + if (const auto *DD = dyn_cast(D)) { +if (DD->getQualifierLoc()) { + return DD->getQualifierLoc().getBeginLoc(); +} + } + + return D->getLocation(); +} + +/// Gets the range of the initializer inside an init-declarator C++ [dcl.decl]. +/// `int a;` -> range of ``, +/// `int *a = nullptr` -> range of `= nullptr`. +/// `int a{}` -> range of `{}`. +/// `int a()` -> range of `()`. +static SourceRange getInitializerRange(Decl *D) { + if (auto *V = dyn_cast(D)) { +auto *I = V->getInit(); +// Initializers in range-based-for are not part of the declarator +if (I && !V->isCXXForRangeDecl()) + return I->getSourceRange(); + } + + return SourceRange(); +} + /// Gets the range of declarator as defined by the C++ grammar. E.g. /// `int a;` -> range of `a`, /// `int *a;` -> range of `*a`, /// `int a[10];` -> range of `a[10]`, /// `int a[1][2][3];` -> range of `a[1][2][3]`, /// `int *a = nullptr` -> range of `*a = nullptr`. -/// FIMXE: \p Name must be a source range, e.g. for `operator+`. +/// `int S::f(){}` -> range of `S::f()`. +/// FIXME: \p Name must be a source range, e.g. for `operator+`. static SourceRange getDeclaratorRange(const SourceManager &SM, TypeLoc T, SourceLocation Name, SourceRange Initializer) { SourceLocation Start = GetStartLoc().Visit(T); - SourceLocation End = T.getSourceRange().getEnd(); + SourceLocation End = T.getEndLoc(); assert(End.isValid()); if (Name.isValid()) { if (Start.isInvalid()) @@ -378,11 +417,9 @@ class syntax::TreeBuilder { /// Returns true if \p D is the last declarator in a chain and is thus /// reponsible for creating SimpleDeclaration for the whole chain. - template - bool isResponsibleForCreatingDeclaration(const T *D) const { -static_assert((std::is_base_of::value || - std::is_base_of::value), - "only DeclaratorDecl and TypedefNameDecl are supported."); + bool isResponsibleForCreatingDeclaration(const Decl *D) const { +assert((isa(D)) && + "only DeclaratorDecl and TypedefNameDecl are supported."); const Decl *Next = D->getNextDeclInContext(); @@ -390,15 +427,14 @@ class syntax::TreeBuilder { if (Next == nullptr) { return true; } -const auto *NextT = dyn_cast(Next); // Next sibling is not the same type, this one is responsible. -if (NextT == nullptr) { +if (D->getKind() != Next->getKind()) { return true; } // Next sibling doesn't begin at the same loc, it must be a diff erent // declaration, so this declarator is responsible. -if (NextT->getBeginLoc() != D->getBeginLoc()) { +if (Next->getBeginLoc() != D->getBeginLoc()) { return true; } @@ -1405,43 +1441,12 @@ class BuildTreeVisitor : public RecursiveASTVisitor { } private: - template SourceLocation getQualifiedNameStart(T *D) { -static_assert((std::is_base_of::value || - std::is_base_of::value), - "only DeclaratorDecl and TypedefNameDecl are supported."); - -auto DN = D->getDeclName(); -bool IsAnonymous = DN.isIdentifier() && !DN.getAsIdentifierInfo(); -if (IsAnonymous) - return SourceLocation(); - -if (const auto *DD = dyn_cast(D)) { - if (DD->getQualifierLoc()) { -return DD->getQualifierLoc().getBeginL
[clang] a146195 - [SyntaxTree] Add coverage for declarators and init-declarators
Author: Eduardo Caldas Date: 2020-08-28T12:19:38Z New Revision: a1461953f4efe574e3fdecfbae68bd18707748fb URL: https://github.com/llvm/llvm-project/commit/a1461953f4efe574e3fdecfbae68bd18707748fb DIFF: https://github.com/llvm/llvm-project/commit/a1461953f4efe574e3fdecfbae68bd18707748fb.diff LOG: [SyntaxTree] Add coverage for declarators and init-declarators Added: Modified: clang/lib/Tooling/Syntax/BuildTree.cpp clang/unittests/Tooling/Syntax/BuildTreeTest.cpp Removed: diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp index 2e9e74401e71..a9f326439a2a 100644 --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -200,6 +200,7 @@ static syntax::NodeKind getOperatorNodeKind(const CXXOperatorCallExpr &E) { /// Get the start of the qualified name. In the examples below it gives the /// location of the `^`: /// `int ^a;` +/// `int *^a;` /// `int ^a::S::f(){}` static SourceLocation getQualifiedNameStart(NamedDecl *D) { assert((isa(D)) && @@ -242,7 +243,7 @@ static SourceRange getInitializerRange(Decl *D) { /// `int a[1][2][3];` -> range of `a[1][2][3]`, /// `int *a = nullptr` -> range of `*a = nullptr`. /// `int S::f(){}` -> range of `S::f()`. -/// FIXME: \p Name must be a source range, e.g. for `operator+`. +/// FIXME: \p Name must be a source range. static SourceRange getDeclaratorRange(const SourceManager &SM, TypeLoc T, SourceLocation Name, SourceRange Initializer) { diff --git a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp index a07187e22e93..aab20008a497 100644 --- a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp @@ -3123,6 +3123,35 @@ SimpleDeclaration )txt"})); } +TEST_P(SyntaxTreeTest, OutOfLineMemberFunctionDefinition) { + if (!GetParam().isCXX11OrLater()) { +return; + } + EXPECT_TRUE(treeDumpEqualOnAnnotations( + R"cpp( +struct S { + void f(); +}; +[[void S::f(){}]] +)cpp", + {R"txt( +SimpleDeclaration +|-'void' +|-SimpleDeclarator Declarator +| |-NestedNameSpecifier +| | |-IdentifierNameSpecifier ListElement +| | | `-'S' +| | `-'::' ListDelimiter +| |-'f' +| `-ParametersAndQualifiers +| |-'(' OpenParen +| `-')' CloseParen +`-CompoundStatement + |-'{' OpenParen + `-'}' CloseParen +)txt"})); +} + TEST_P(SyntaxTreeTest, ConversionMemberFunction) { if (!GetParam().isCXX()) { return; @@ -3792,6 +3821,53 @@ TranslationUnit Detached )txt")); } +TEST_P(SyntaxTreeTest, InitDeclarator_Brace) { + if (!GetParam().isCXX11OrLater()) { +return; + } + EXPECT_TRUE(treeDumpEqual( + R"cpp( +int a {}; +)cpp", + R"txt( +TranslationUnit Detached +`-SimpleDeclaration + |-'int' + |-SimpleDeclarator Declarator + | |-'a' + | `-UnknownExpression + | `-UnknownExpression + | |-'{' + | `-'}' + `-';' +)txt")); +} + +TEST_P(SyntaxTreeTest, InitDeclarator_Paren) { + if (!GetParam().isCXX()) { +return; + } + EXPECT_TRUE(treeDumpEqualOnAnnotations( + R"cpp( +struct S { + S(int); +}; +[[S s(1);]] +)cpp", + {R"txt( +SimpleDeclaration +|-'S' +|-SimpleDeclarator Declarator +| `-UnknownExpression +| |-'s' +| |-'(' +| |-IntegerLiteralExpression +| | `-'1' LiteralToken +| `-')' +`-';' +)txt"})); +} + TEST_P(SyntaxTreeTest, ArrayDeclarator_Simple) { EXPECT_TRUE(treeDumpEqual( R"cpp( ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] 1a7a2cd - [Ignore Expressions][NFC] Refactor to better use `IgnoreExpr.h` and nits
Author: Eduardo Caldas Date: 2020-09-07T09:32:30Z New Revision: 1a7a2cd7474e6d321120ffe7ca9c52163eb228f0 URL: https://github.com/llvm/llvm-project/commit/1a7a2cd7474e6d321120ffe7ca9c52163eb228f0 DIFF: https://github.com/llvm/llvm-project/commit/1a7a2cd7474e6d321120ffe7ca9c52163eb228f0.diff LOG: [Ignore Expressions][NFC] Refactor to better use `IgnoreExpr.h` and nits This change groups * Rename: `ignoreParenBaseCasts` -> `IgnoreParenBaseCasts` for uniformity * Rename: `IgnoreConversionOperator` -> `IgnoreConversionOperatorSingleStep` for uniformity * Inline `IgnoreNoopCastsSingleStep` into a lambda inside `IgnoreNoopCasts` * Refactor `IgnoreUnlessSpelledInSource` to make adequate use of `IgnoreExprNodes` Differential Revision: https://reviews.llvm.org/D86880 Added: Modified: clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.cpp clang/include/clang/AST/Expr.h clang/lib/AST/Expr.cpp clang/lib/CodeGen/CGExprCXX.cpp clang/lib/Sema/SemaExpr.cpp clang/lib/StaticAnalyzer/Core/CallEvent.cpp Removed: diff --git a/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp index 04dc61f02df1..44ae380b63b2 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp @@ -338,7 +338,7 @@ void UseAutoCheck::replaceIterators(const DeclStmt *D, ASTContext *Context) { // Drill down to the as-written initializer. const Expr *E = (*Construct->arg_begin())->IgnoreParenImpCasts(); -if (E != E->IgnoreConversionOperator()) { +if (E != E->IgnoreConversionOperatorSingleStep()) { // We hit a conversion operator. Early-out now as they imply an implicit // conversion from a diff erent type. Could also mean an explicit // conversion from the same type but that's pretty rare. diff --git a/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.cpp b/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.cpp index 9dcb10b9d20c..7e8ba4eb90c6 100644 --- a/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.cpp @@ -205,7 +205,7 @@ std::string compareExpressionToZero(const MatchFinder::MatchResult &Result, std::string replacementExpression(const MatchFinder::MatchResult &Result, bool Negated, const Expr *E) { - E = E->ignoreParenBaseCasts(); + E = E->IgnoreParenBaseCasts(); if (const auto *EC = dyn_cast(E)) E = EC->getSubExpr(); diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 5edca2593789..26e52ad367f8 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -867,9 +867,9 @@ class Expr : public ValueStmt { /// Skip conversion operators. If this Expr is a call to a conversion /// operator, return the argument. - Expr *IgnoreConversionOperator() LLVM_READONLY; - const Expr *IgnoreConversionOperator() const { -return const_cast(this)->IgnoreConversionOperator(); + Expr *IgnoreConversionOperatorSingleStep() LLVM_READONLY; + const Expr *IgnoreConversionOperatorSingleStep() const { +return const_cast(this)->IgnoreConversionOperatorSingleStep(); } /// Skip past any parentheses and lvalue casts which might surround this @@ -901,9 +901,9 @@ class Expr : public ValueStmt { /// * What IgnoreParens() skips /// * CastExpr which represent a derived-to-base cast (CK_DerivedToBase, /// CK_UncheckedDerivedToBase and CK_NoOp) - Expr *ignoreParenBaseCasts() LLVM_READONLY; - const Expr *ignoreParenBaseCasts() const { -return const_cast(this)->ignoreParenBaseCasts(); + Expr *IgnoreParenBaseCasts() LLVM_READONLY; + const Expr *IgnoreParenBaseCasts() const { +return const_cast(this)->IgnoreParenBaseCasts(); } /// Determine whether this expression is a default function argument. diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 1029acbf68cd..15f3df0fd216 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -40,7 +40,7 @@ using namespace clang; const Expr *Expr::getBestDynamicClassTypeExpr() const { const Expr *E = this; while (true) { -E = E->ignoreParenBaseCasts(); +E = E->IgnoreParenBaseCasts(); // Follow the RHS of a comma operator. if (auto *BO = dyn_cast(E)) { @@ -2780,29 +2780,6 @@ QualType Expr::findBoundMemberType(const Expr *expr) { return QualType(); } -static Expr *IgnoreNoopCastsSingleStep(const ASTContext &Ctx, Expr *E) { - if (auto *CE = dyn_cast(E)) { -// We ignore integer <-> casts that are of the same width, ptr<->ptr and -// ptr<->int casts of the same width. We also ignore all identity casts. -Expr *SubExpr = CE->g
[clang] 81aa66f - Extract infrastructure to ignore intermediate expressions into `clang/AST/IgnoreExpr.h`
Author: Eduardo Caldas Date: 2020-09-07T09:32:30Z New Revision: 81aa66f65f504af18982baa078a5f3f7d2aa88fa URL: https://github.com/llvm/llvm-project/commit/81aa66f65f504af18982baa078a5f3f7d2aa88fa DIFF: https://github.com/llvm/llvm-project/commit/81aa66f65f504af18982baa078a5f3f7d2aa88fa.diff LOG: Extract infrastructure to ignore intermediate expressions into `clang/AST/IgnoreExpr.h` Rationale: This allows users to use `IgnoreExprNodes` and `Ignore*SingleStep` outside of `clang/AST/Expr.cpp`. Minor: Rename `IgnoreImp...SingleStep` into `IgnoreImplicit...SingleStep`. Differential Revision: https://reviews.llvm.org/D86778 Added: clang/include/clang/AST/IgnoreExpr.h clang/lib/AST/IgnoreExpr.cpp Modified: clang/lib/AST/CMakeLists.txt clang/lib/AST/Expr.cpp Removed: diff --git a/clang/include/clang/AST/IgnoreExpr.h b/clang/include/clang/AST/IgnoreExpr.h new file mode 100644 index ..15d31f3af995 --- /dev/null +++ b/clang/include/clang/AST/IgnoreExpr.h @@ -0,0 +1,61 @@ +//===--- IgnoreExpr.h - Ignore intermediate Expressions -===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// This file defines common functions to ignore intermediate expression nodes +// +//===--===// + +#ifndef LLVM_CLANG_AST_IGNOREEXPR_H +#define LLVM_CLANG_AST_IGNOREEXPR_H + +#include "clang/AST/Expr.h" + +namespace clang { +namespace detail { +/// Given an expression E and functions Fn_1,...,Fn_n : Expr * -> Expr *, +/// Return Fn_n(...(Fn_1(E))) +inline Expr *IgnoreExprNodesImpl(Expr *E) { return E; }; +template +Expr *IgnoreExprNodesImpl(Expr *E, FnTy &&Fn, FnTys &&... Fns) { + return IgnoreExprNodesImpl(Fn(E), std::forward(Fns)...); +} +} // namespace detail + +/// Given an expression E and functions Fn_1,...,Fn_n : Expr * -> Expr *, +/// Recursively apply each of the functions to E until reaching a fixed point. +/// Note that a null E is valid; in this case nothing is done. +template Expr *IgnoreExprNodes(Expr *E, FnTys &&... Fns) { + Expr *LastE = nullptr; + while (E != LastE) { +LastE = E; +E = detail::IgnoreExprNodesImpl(E, std::forward(Fns)...); + } + return E; +} + +Expr *IgnoreImplicitCastsSingleStep(Expr *E); + +Expr *IgnoreImplicitCastsExtraSingleStep(Expr *E); + +Expr *IgnoreCastsSingleStep(Expr *E); + +Expr *IgnoreLValueCastsSingleStep(Expr *E); + +Expr *IgnoreBaseCastsSingleStep(Expr *E); + +Expr *IgnoreImplicitSingleStep(Expr *E); + +Expr *IgnoreImplicitAsWrittenSingleStep(Expr *E); + +Expr *IgnoreParensOnlySingleStep(Expr *E); + +Expr *IgnoreParensSingleStep(Expr *E); + +} // namespace clang + +#endif // LLVM_CLANG_AST_IGNOREEXPR_H diff --git a/clang/lib/AST/CMakeLists.txt b/clang/lib/AST/CMakeLists.txt index 35099fd0dacf..dfd26fd97bc6 100644 --- a/clang/lib/AST/CMakeLists.txt +++ b/clang/lib/AST/CMakeLists.txt @@ -55,6 +55,7 @@ add_clang_library(clangAST ExternalASTMerger.cpp ExternalASTSource.cpp FormatString.cpp + IgnoreExpr.cpp InheritViz.cpp Interp/ByteCodeEmitter.cpp Interp/ByteCodeExprGen.cpp diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 8efd6837c541..1029acbf68cd 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -21,6 +21,7 @@ #include "clang/AST/DependenceFlags.h" #include "clang/AST/EvaluatedExprVisitor.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/IgnoreExpr.h" #include "clang/AST/Mangle.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/StmtVisitor.h" @@ -2779,118 +2780,6 @@ QualType Expr::findBoundMemberType(const Expr *expr) { return QualType(); } -static Expr *IgnoreImpCastsSingleStep(Expr *E) { - if (auto *ICE = dyn_cast(E)) -return ICE->getSubExpr(); - - if (auto *FE = dyn_cast(E)) -return FE->getSubExpr(); - - return E; -} - -static Expr *IgnoreImpCastsExtraSingleStep(Expr *E) { - // FIXME: Skip MaterializeTemporaryExpr and SubstNonTypeTemplateParmExpr in - // addition to what IgnoreImpCasts() skips to account for the current - // behaviour of IgnoreParenImpCasts(). - Expr *SubE = IgnoreImpCastsSingleStep(E); - if (SubE != E) -return SubE; - - if (auto *MTE = dyn_cast(E)) -return MTE->getSubExpr(); - - if (auto *NTTP = dyn_cast(E)) -return NTTP->getReplacement(); - - return E; -} - -static Expr *IgnoreCastsSingleStep(Expr *E) { - if (auto *CE = dyn_cast(E)) -return CE->getSubExpr(); - - if (auto *FE = dyn_cast(E)) -return FE->getSubExpr(); - - if (auto *MTE = dyn_cast(E)) -return MTE->getSubExpr(); - - if (auto *NTTP = dyn_cast(E)) -return NTTP->getReplacement(); - - return E; -} - -static
[clang] 46f4439 - [SyntaxTree] Ignore implicit leaf `CXXConstructExpr`
Author: Eduardo Caldas Date: 2020-09-08T09:44:23Z New Revision: 46f4439dc9bf9b8cfee0001b6752c3d074c83b00 URL: https://github.com/llvm/llvm-project/commit/46f4439dc9bf9b8cfee0001b6752c3d074c83b00 DIFF: https://github.com/llvm/llvm-project/commit/46f4439dc9bf9b8cfee0001b6752c3d074c83b00.diff LOG: [SyntaxTree] Ignore implicit leaf `CXXConstructExpr` Differential Revision: https://reviews.llvm.org/D86700 Added: Modified: clang/lib/Tooling/Syntax/BuildTree.cpp clang/unittests/Tooling/Syntax/BuildTreeTest.cpp Removed: diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp index e5389ae4eff4..72083eeefa31 100644 --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -1132,6 +1132,14 @@ class BuildTreeVisitor : public RecursiveASTVisitor { return true; } + bool WalkUpFromCXXConstructExpr(CXXConstructExpr *S) { +// Ignore the implicit calls to default constructors. +if ((S->getNumArgs() == 0 || isa(S->getArg(0))) && +S->getParenOrBraceRange().isInvalid()) + return true; +return RecursiveASTVisitor::WalkUpFromCXXConstructExpr(S); + } + bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *S) { // To construct a syntax tree of the same shape for calls to built-in and // user-defined operators, ignore the `DeclRefExpr` that refers to the diff --git a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp index fe89e0d7d1a2..00e18057d7be 100644 --- a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp @@ -548,9 +548,6 @@ namespace n { struct S { }; } void test() { - // FIXME: Remove the `UnknownExpression` wrapping `s1` and `s2`. This - // `UnknownExpression` comes from a leaf `CXXConstructExpr` in the - // ClangAST. We need to ignore leaf implicit nodes. [[::n::S s1]]; [[n::S s2]]; } @@ -564,8 +561,7 @@ SimpleDeclaration | `-'::' ListDelimiter |-'S' `-SimpleDeclarator Declarator - `-UnknownExpression -`-'s1' + `-'s1' )txt", R"txt( SimpleDeclaration @@ -575,8 +571,7 @@ SimpleDeclaration | `-'::' ListDelimiter |-'S' `-SimpleDeclarator Declarator - `-UnknownExpression -`-'s2' + `-'s2' )txt"})); } @@ -608,8 +603,7 @@ SimpleDeclaration | `-'::' ListDelimiter |-'S' `-SimpleDeclarator Declarator - `-UnknownExpression -`-'s1' + `-'s1' )txt", R"txt( SimpleDeclaration @@ -623,8 +617,7 @@ SimpleDeclaration | `-'::' ListDelimiter |-'S' `-SimpleDeclarator Declarator - `-UnknownExpression -`-'s2' + `-'s2' )txt"})); } ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 134455a - [SyntaxTree] Ignore implicit `CXXFunctionalCastExpr` wrapping constructor
Author: Eduardo Caldas Date: 2020-09-08T09:44:23Z New Revision: 134455a07c1f1de4cff62a6afb4ccd98b98343ec URL: https://github.com/llvm/llvm-project/commit/134455a07c1f1de4cff62a6afb4ccd98b98343ec DIFF: https://github.com/llvm/llvm-project/commit/134455a07c1f1de4cff62a6afb4ccd98b98343ec.diff LOG: [SyntaxTree] Ignore implicit `CXXFunctionalCastExpr` wrapping constructor Differential Revision: https://reviews.llvm.org/D87229 Added: Modified: clang/lib/Tooling/Syntax/BuildTree.cpp clang/unittests/Tooling/Syntax/BuildTreeTest.cpp Removed: diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp index 72083eeefa31..bb2b1494793a 100644 --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -14,6 +14,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/IgnoreExpr.h" +#include "clang/AST/OperationKinds.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/Stmt.h" #include "clang/AST/TypeLoc.h" @@ -60,9 +61,25 @@ static Expr *IgnoreImplicitConstructorSingleStep(Expr *E) { return E; } +// In: +// struct X { +// X(int) +// }; +// X x = X(1); +// Ignores the implicit `CXXFunctionalCastExpr` that wraps +// `CXXConstructExpr X(1)`. +static Expr *IgnoreCXXFunctionalCastExprWrappingConstructor(Expr *E) { + if (auto *F = dyn_cast(E)) { +if (F->getCastKind() == CK_ConstructorConversion) + return F->getSubExpr(); + } + return E; +} + static Expr *IgnoreImplicit(Expr *E) { return IgnoreExprNodes(E, IgnoreImplicitSingleStep, - IgnoreImplicitConstructorSingleStep); + IgnoreImplicitConstructorSingleStep, + IgnoreCXXFunctionalCastExprWrappingConstructor); } LLVM_ATTRIBUTE_UNUSED diff --git a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp index 00e18057d7be..7a106e9297b9 100644 --- a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp @@ -4069,7 +4069,6 @@ struct X { X(int); }; X test() { - // FIXME: Remove `UnknownExpression` due to implicit `CXXFunctionalCastExpr` [[return X(1);]] } )cpp", @@ -4077,12 +4076,11 @@ X test() { ReturnStatement Statement |-'return' IntroducerKeyword |-UnknownExpression ReturnValue -| `-UnknownExpression -| |-'X' -| |-'(' -| |-IntegerLiteralExpression -| | `-'1' LiteralToken -| `-')' +| |-'X' +| |-'(' +| |-IntegerLiteralExpression +| | `-'1' LiteralToken +| `-')' `-';' )txt"})); } ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 2325d6b - [SyntaxTree] Ignore implicit non-leaf `CXXConstructExpr`
Author: Eduardo Caldas Date: 2020-09-08T09:44:23Z New Revision: 2325d6b42f096bf93d2ab0bed7096759e5c96ce8 URL: https://github.com/llvm/llvm-project/commit/2325d6b42f096bf93d2ab0bed7096759e5c96ce8 DIFF: https://github.com/llvm/llvm-project/commit/2325d6b42f096bf93d2ab0bed7096759e5c96ce8.diff LOG: [SyntaxTree] Ignore implicit non-leaf `CXXConstructExpr` Differential Revision: https://reviews.llvm.org/D86699 Added: Modified: clang/lib/Tooling/Syntax/BuildTree.cpp clang/unittests/Tooling/Syntax/BuildTreeTest.cpp Removed: diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp index a9f326439a2a..e5389ae4eff4 100644 --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -13,6 +13,7 @@ #include "clang/AST/DeclarationName.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/IgnoreExpr.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/Stmt.h" #include "clang/AST/TypeLoc.h" @@ -44,8 +45,28 @@ using namespace clang; +// Ignores the implicit `CXXConstructExpr` for copy/move constructor calls +// generated by the compiler, as well as in implicit conversions like the one +// wrapping `1` in `X x = 1;`. +static Expr *IgnoreImplicitConstructorSingleStep(Expr *E) { + if (auto *C = dyn_cast(E)) { +auto NumArgs = C->getNumArgs(); +if (NumArgs == 1 || (NumArgs > 1 && isa(C->getArg(1 { + Expr *A = C->getArg(0); + if (C->getParenOrBraceRange().isInvalid()) +return A; +} + } + return E; +} + +static Expr *IgnoreImplicit(Expr *E) { + return IgnoreExprNodes(E, IgnoreImplicitSingleStep, + IgnoreImplicitConstructorSingleStep); +} + LLVM_ATTRIBUTE_UNUSED -static bool isImplicitExpr(Expr *E) { return E->IgnoreImplicit() != E; } +static bool isImplicitExpr(Expr *E) { return IgnoreImplicit(E) != E; } namespace { /// Get start location of the Declarator from the TypeLoc. @@ -740,7 +761,7 @@ class BuildTreeVisitor : public RecursiveASTVisitor { for (auto *D : DS->decls()) Builder.noticeDeclWithoutSemicolon(D); } else if (auto *E = dyn_cast_or_null(S)) { - return RecursiveASTVisitor::TraverseStmt(E->IgnoreImplicit()); + return RecursiveASTVisitor::TraverseStmt(IgnoreImplicit(E)); } return RecursiveASTVisitor::TraverseStmt(S); } @@ -1579,7 +1600,7 @@ void syntax::TreeBuilder::markStmtChild(Stmt *Child, NodeRole Role) { void syntax::TreeBuilder::markExprChild(Expr *Child, NodeRole Role) { if (!Child) return; - Child = Child->IgnoreImplicit(); + Child = IgnoreImplicit(Child); syntax::Tree *ChildNode = Mapping.find(Child); assert(ChildNode != nullptr); diff --git a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp index aab20008a497..fe89e0d7d1a2 100644 --- a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp @@ -1745,19 +1745,15 @@ TEST_P(SyntaxTreeTest, OverloadedOperator_Plus) { struct X { friend X operator+(X, const X&); }; -// FIXME: Remove additional `UnknownExpression` wrapping `x`. For that, ignore -// implicit copy constructor called on `x`. This should've been ignored already, -// as we `IgnoreImplicit` when traversing an `Stmt`. void test(X x, X y) { [[x + y]]; } )cpp", {R"txt( BinaryOperatorExpression Expression -|-UnknownExpression LeftHandSide -| `-IdExpression -| `-UnqualifiedId UnqualifiedId -| `-'x' +|-IdExpression LeftHandSide +| `-UnqualifiedId UnqualifiedId +| `-'x' |-'+' OperatorToken `-IdExpression RightHandSide `-UnqualifiedId UnqualifiedId @@ -3821,26 +3817,137 @@ TranslationUnit Detached )txt")); } +TEST_P(SyntaxTreeTest, InitDeclarator_Equal) { + if (!GetParam().isCXX()) { +return; + } + EXPECT_TRUE(treeDumpEqualOnAnnotations( + R"cpp( +struct S { S(int);}; +void test() { + [[S s = 1]]; +} +)cpp", + {R"txt( +SimpleDeclaration +|-'S' +`-SimpleDeclarator Declarator + |-'s' + |-'=' + `-IntegerLiteralExpression +`-'1' LiteralToken +)txt"})); +} + TEST_P(SyntaxTreeTest, InitDeclarator_Brace) { if (!GetParam().isCXX11OrLater()) { return; } - EXPECT_TRUE(treeDumpEqual( + EXPECT_TRUE(treeDumpEqualOnAnnotations( R"cpp( -int a {}; +struct S { + S(); + S(int); + S(int, float); +}; +void test(){ + // FIXME: 's...' is a declarator and '{...}' is initializer + [[S s0{}]]; + [[S s1{1}]]; + [[S s2{1, 2.}]]; +} )cpp", - R"txt( -TranslationUnit Detached -`-SimpleDeclaration - |-'int' - |-SimpleDeclarator Declarator - | |-'a' - | `-UnknownExpression - | `-UnknownExpression - | |-'{' - | `-'}' - `-';' -)txt")); + {R"txt( +SimpleDeclaration +|-'S' +`-SimpleDeclarator Declarator + `-UnknownExpression +|-'s0' +|-'{' +`-'}' + )txt",
[clang] f5087d5 - [SyntaxTree] Fix crash on functions with default arguments.
Author: Eduardo Caldas Date: 2020-09-08T09:49:30Z New Revision: f5087d5c7248104b6580c7b079ed5f227332c2ef URL: https://github.com/llvm/llvm-project/commit/f5087d5c7248104b6580c7b079ed5f227332c2ef DIFF: https://github.com/llvm/llvm-project/commit/f5087d5c7248104b6580c7b079ed5f227332c2ef.diff LOG: [SyntaxTree] Fix crash on functions with default arguments. * Do not visit `CXXDefaultArgExpr` * To build `CallArguments` nodes, just go through non-default arguments Differential Revision: https://reviews.llvm.org/D87249 Added: Modified: clang/lib/Tooling/Syntax/BuildTree.cpp clang/unittests/Tooling/Syntax/BuildTreeTest.cpp Removed: diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp index bb2b1494793a..1942290b5abc 100644 --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -154,6 +154,13 @@ struct GetStartLoc : TypeLocVisitor { }; } // namespace +static CallExpr::arg_range dropDefaultArgs(CallExpr::arg_range Args) { + auto firstDefaultArg = std::find_if(Args.begin(), Args.end(), [](auto it) { +return isa(it); + }); + return llvm::make_range(Args.begin(), firstDefaultArg); +} + static syntax::NodeKind getOperatorNodeKind(const CXXOperatorCallExpr &E) { switch (E.getOperator()) { // Comparison @@ -,7 +1118,11 @@ class BuildTreeVisitor : public RecursiveASTVisitor { return true; } - syntax::CallArguments *buildCallArguments(CallExpr::arg_range Args) { + /// Builds `CallArguments` syntax node from arguments that appear in source + /// code, i.e. not default arguments. + syntax::CallArguments * + buildCallArguments(CallExpr::arg_range ArgsAndDefaultArgs) { +auto Args = dropDefaultArgs(ArgsAndDefaultArgs); for (const auto &Arg : Args) { Builder.markExprChild(Arg, syntax::NodeRole::ListElement); const auto *DelimiterToken = @@ -1233,6 +1244,8 @@ class BuildTreeVisitor : public RecursiveASTVisitor { } } + bool WalkUpFromCXXDefaultArgExpr(CXXDefaultArgExpr *S) { return true; } + bool WalkUpFromNamespaceDecl(NamespaceDecl *S) { auto Tokens = Builder.getDeclarationRange(S); if (Tokens.front().kind() == tok::coloncolon) { diff --git a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp index 7a106e9297b9..225885437267 100644 --- a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp @@ -2733,6 +2733,54 @@ CallExpression Expression )txt"})); } +TEST_P(SyntaxTreeTest, CallExpression_DefaultArguments) { + if (!GetParam().isCXX11OrLater()) { +return; + } + EXPECT_TRUE(treeDumpEqualOnAnnotations( + R"cpp( +void f(int i = 1, char c = '2'); +void test() { + [[f()]]; + [[f(1)]]; + [[f(1, '2')]]; +} +)cpp", + {R"txt( +CallExpression Expression +|-IdExpression Callee +| `-UnqualifiedId UnqualifiedId +| `-'f' +|-'(' OpenParen +`-')' CloseParen + )txt", + R"txt( +CallExpression Expression +|-IdExpression Callee +| `-UnqualifiedId UnqualifiedId +| `-'f' +|-'(' OpenParen +|-CallArguments Arguments +| `-IntegerLiteralExpression ListElement +| `-'1' LiteralToken +`-')' CloseParen + )txt", + R"txt( +CallExpression Expression +|-IdExpression Callee +| `-UnqualifiedId UnqualifiedId +| `-'f' +|-'(' OpenParen +|-CallArguments Arguments +| |-IntegerLiteralExpression ListElement +| | `-'1' LiteralToken +| |-',' ListDelimiter +| `-CharacterLiteralExpression ListElement +| `-''2'' LiteralToken +`-')' CloseParen +)txt"})); +} + TEST_P(SyntaxTreeTest, MultipleDeclaratorsGrouping) { EXPECT_TRUE(treeDumpEqual( R"cpp( @@ -3986,6 +4034,56 @@ SimpleDeclaration )txt"})); } +TEST_P(SyntaxTreeTest, InitDeclarator_Paren_DefaultArguments) { + if (!GetParam().isCXX()) { +return; + } + EXPECT_TRUE(treeDumpEqualOnAnnotations( + R"cpp( +struct S { + S(int i = 1, float = 2.); +}; +[[S s0;]] +// FIXME: 's...' is a declarator and '(...)' is initializer +[[S s1(1);]] +[[S s2(1, 2.);]] +)cpp", + {R"txt( +SimpleDeclaration +|-'S' +|-SimpleDeclarator Declarator +| `-'s0' +`-';' + )txt", + R"txt( +SimpleDeclaration +|-'S' +|-SimpleDeclarator Declarator +| `-UnknownExpression +| |-'s1' +| |-'(' +| |-IntegerLiteralExpression +| | `-'1' LiteralToken +| `-')' +`-';' + )txt", + R"txt( +SimpleDeclaration +|-'S' +|-SimpleDeclarator Declarator +| `-UnknownExpression +| |-'s2' +| |-'(' +| |-IntegerLiteralExpression +| | `-'1' LiteralToken +| |-',' +| |-FloatingLiteralExpression +| | `-'2.' LiteralToken +| `-')' +`-';' +)txt"})); +} + TEST_P(SyntaxTreeTest, ImplicitConversion_Argument) { if (!GetParam().isCXX()) { return; @@ -4114,6 +4212,48 @@ ReturnStatement Statement )txt"})); } +TEST_P(SyntaxTreeTest, ConstructorCall_DefaultArguments) { + if (!GetParam().isCXX(
[clang] c0e5e3f - [Ignore Expressions] Fix performance regression by inlining `Ignore*SingleStep`
Author: Eduardo Caldas Date: 2020-09-09T07:32:40Z New Revision: c0e5e3fbfa504c3792023d0db9008b08caa6b6d7 URL: https://github.com/llvm/llvm-project/commit/c0e5e3fbfa504c3792023d0db9008b08caa6b6d7 DIFF: https://github.com/llvm/llvm-project/commit/c0e5e3fbfa504c3792023d0db9008b08caa6b6d7.diff LOG: [Ignore Expressions] Fix performance regression by inlining `Ignore*SingleStep` We also add a `const` versions of `IgnoreExprNodes` Differential Revision: https://reviews.llvm.org/D87278 Added: Modified: clang/include/clang/AST/IgnoreExpr.h clang/lib/AST/CMakeLists.txt Removed: clang/lib/AST/IgnoreExpr.cpp diff --git a/clang/include/clang/AST/IgnoreExpr.h b/clang/include/clang/AST/IgnoreExpr.h index 0aeb547606a2..1c2b538e5b63 100644 --- a/clang/include/clang/AST/IgnoreExpr.h +++ b/clang/include/clang/AST/IgnoreExpr.h @@ -14,6 +14,7 @@ #define LLVM_CLANG_AST_IGNOREEXPR_H #include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" namespace clang { namespace detail { @@ -38,23 +39,122 @@ template Expr *IgnoreExprNodes(Expr *E, FnTys &&... Fns) { return E; } -Expr *IgnoreImplicitCastsSingleStep(Expr *E); +template +const Expr *IgnoreExprNodes(const Expr *E, FnTys &&...Fns) { + return const_cast(IgnoreExprNodes(E, std::forward(Fns)...)); +} + +inline Expr *IgnoreImplicitCastsSingleStep(Expr *E) { + if (auto *ICE = dyn_cast(E)) +return ICE->getSubExpr(); + + if (auto *FE = dyn_cast(E)) +return FE->getSubExpr(); + + return E; +} + +inline Expr *IgnoreImplicitCastsExtraSingleStep(Expr *E) { + // FIXME: Skip MaterializeTemporaryExpr and SubstNonTypeTemplateParmExpr in + // addition to what IgnoreImpCasts() skips to account for the current + // behaviour of IgnoreParenImpCasts(). + Expr *SubE = IgnoreImplicitCastsSingleStep(E); + if (SubE != E) +return SubE; + + if (auto *MTE = dyn_cast(E)) +return MTE->getSubExpr(); + + if (auto *NTTP = dyn_cast(E)) +return NTTP->getReplacement(); + + return E; +} + +inline Expr *IgnoreCastsSingleStep(Expr *E) { + if (auto *CE = dyn_cast(E)) +return CE->getSubExpr(); + + if (auto *FE = dyn_cast(E)) +return FE->getSubExpr(); + + if (auto *MTE = dyn_cast(E)) +return MTE->getSubExpr(); + + if (auto *NTTP = dyn_cast(E)) +return NTTP->getReplacement(); + + return E; +} + +inline Expr *IgnoreLValueCastsSingleStep(Expr *E) { + // Skip what IgnoreCastsSingleStep skips, except that only + // lvalue-to-rvalue casts are skipped. + if (auto *CE = dyn_cast(E)) +if (CE->getCastKind() != CK_LValueToRValue) + return E; -Expr *IgnoreImplicitCastsExtraSingleStep(Expr *E); + return IgnoreCastsSingleStep(E); +} + +inline Expr *IgnoreBaseCastsSingleStep(Expr *E) { + if (auto *CE = dyn_cast(E)) +if (CE->getCastKind() == CK_DerivedToBase || +CE->getCastKind() == CK_UncheckedDerivedToBase || +CE->getCastKind() == CK_NoOp) + return CE->getSubExpr(); + + return E; +} + +inline Expr *IgnoreImplicitSingleStep(Expr *E) { + Expr *SubE = IgnoreImplicitCastsSingleStep(E); + if (SubE != E) +return SubE; + + if (auto *MTE = dyn_cast(E)) +return MTE->getSubExpr(); + + if (auto *BTE = dyn_cast(E)) +return BTE->getSubExpr(); + + return E; +} + +inline Expr *IgnoreImplicitAsWrittenSingleStep(Expr *E) { + if (auto *ICE = dyn_cast(E)) +return ICE->getSubExprAsWritten(); -Expr *IgnoreCastsSingleStep(Expr *E); + return IgnoreImplicitSingleStep(E); +} -Expr *IgnoreLValueCastsSingleStep(Expr *E); +inline Expr *IgnoreParensOnlySingleStep(Expr *E) { + if (auto *PE = dyn_cast(E)) +return PE->getSubExpr(); + return E; +} -Expr *IgnoreBaseCastsSingleStep(Expr *E); +inline Expr *IgnoreParensSingleStep(Expr *E) { + if (auto *PE = dyn_cast(E)) +return PE->getSubExpr(); -Expr *IgnoreImplicitSingleStep(Expr *E); + if (auto *UO = dyn_cast(E)) { +if (UO->getOpcode() == UO_Extension) + return UO->getSubExpr(); + } -Expr *IgnoreImplicitAsWrittenSingleStep(Expr *E); + else if (auto *GSE = dyn_cast(E)) { +if (!GSE->isResultDependent()) + return GSE->getResultExpr(); + } -Expr *IgnoreParensOnlySingleStep(Expr *E); + else if (auto *CE = dyn_cast(E)) { +if (!CE->isConditionDependent()) + return CE->getChosenSubExpr(); + } -Expr *IgnoreParensSingleStep(Expr *E); + return E; +} } // namespace clang diff --git a/clang/lib/AST/CMakeLists.txt b/clang/lib/AST/CMakeLists.txt index dfd26fd97bc6..35099fd0dacf 100644 --- a/clang/lib/AST/CMakeLists.txt +++ b/clang/lib/AST/CMakeLists.txt @@ -55,7 +55,6 @@ add_clang_library(clangAST ExternalASTMerger.cpp ExternalASTSource.cpp FormatString.cpp - IgnoreExpr.cpp InheritViz.cpp Interp/ByteCodeEmitter.cpp Interp/ByteCodeExprGen.cpp diff --git a/clang/lib/AST/IgnoreExpr.cpp b/clang/lib/AST/IgnoreExpr.cpp deleted file mode 100644 index 65aaaeb6a1ed.. --- a/clang/lib/AST/IgnoreEx
[clang] c01d28d - [SyntaxTree] Specialize `TreeTestBase` for `BuildTreeTest`, `MutationsTest` and `SynthesisTest`
Author: Eduardo Caldas Date: 2020-09-10T16:44:14Z New Revision: c01d28dc51bdd33404828a327320e3307a51bb22 URL: https://github.com/llvm/llvm-project/commit/c01d28dc51bdd33404828a327320e3307a51bb22 DIFF: https://github.com/llvm/llvm-project/commit/c01d28dc51bdd33404828a327320e3307a51bb22.diff LOG: [SyntaxTree] Specialize `TreeTestBase` for `BuildTreeTest`, `MutationsTest` and `SynthesisTest` Differential Revision: https://reviews.llvm.org/D87374 Added: clang/unittests/Tooling/Syntax/SynthesisTest.cpp Modified: clang/unittests/Tooling/Syntax/BuildTreeTest.cpp clang/unittests/Tooling/Syntax/CMakeLists.txt clang/unittests/Tooling/Syntax/MutationsTest.cpp clang/unittests/Tooling/Syntax/TreeTestBase.cpp clang/unittests/Tooling/Syntax/TreeTestBase.h Removed: diff --git a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp index 225885437267..6fcc74ba55d0 100644 --- a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp @@ -17,7 +17,70 @@ using namespace clang::syntax; namespace { -TEST_P(SyntaxTreeTest, Simple) { +class BuildSyntaxTreeTest : public SyntaxTreeTest { +protected: + ::testing::AssertionResult treeDumpEqual(StringRef Code, StringRef Tree) { +SCOPED_TRACE(llvm::join(GetParam().getCommandLineArgs(), " ")); + +auto *Root = buildTree(Code, GetParam()); +if (Diags->getClient()->getNumErrors() != 0) { + return ::testing::AssertionFailure() + << "Source file has syntax errors, they were printed to the test " +"log"; +} +auto Actual = StringRef(Root->dump(Arena->sourceManager())).trim().str(); +// EXPECT_EQ shows the diff between the two strings if they are diff erent. +EXPECT_EQ(Tree.trim().str(), Actual); +if (Actual != Tree.trim().str()) { + return ::testing::AssertionFailure(); +} +return ::testing::AssertionSuccess(); + } + + ::testing::AssertionResult + treeDumpEqualOnAnnotations(StringRef CodeWithAnnotations, + ArrayRef TreeDumps) { +SCOPED_TRACE(llvm::join(GetParam().getCommandLineArgs(), " ")); + +auto AnnotatedCode = llvm::Annotations(CodeWithAnnotations); +auto *Root = buildTree(AnnotatedCode.code(), GetParam()); + +if (Diags->getClient()->getNumErrors() != 0) { + return ::testing::AssertionFailure() + << "Source file has syntax errors, they were printed to the test " +"log"; +} + +auto AnnotatedRanges = AnnotatedCode.ranges(); +if (AnnotatedRanges.size() != TreeDumps.size()) { + return ::testing::AssertionFailure() + << "The number of annotated ranges in the source code is " +" diff erent " +"to the number of their corresponding tree dumps."; +} +bool Failed = false; +for (unsigned i = 0; i < AnnotatedRanges.size(); i++) { + auto *AnnotatedNode = nodeByRange(AnnotatedRanges[i], Root); + assert(AnnotatedNode); + auto AnnotatedNodeDump = + StringRef(AnnotatedNode->dump(Arena->sourceManager())).trim().str(); + // EXPECT_EQ shows the diff between the two strings if they are diff erent. + EXPECT_EQ(TreeDumps[i].trim().str(), AnnotatedNodeDump) + << "Dumps diverged for the code:\n" + << AnnotatedCode.code().slice(AnnotatedRanges[i].Begin, +AnnotatedRanges[i].End); + if (AnnotatedNodeDump != TreeDumps[i].trim().str()) +Failed = true; +} +return Failed ? ::testing::AssertionFailure() + : ::testing::AssertionSuccess(); + } +}; + +INSTANTIATE_TEST_CASE_P(SyntaxTreeTests, BuildSyntaxTreeTest, +testing::ValuesIn(allTestClangConfigs()), ); + +TEST_P(BuildSyntaxTreeTest, Simple) { EXPECT_TRUE(treeDumpEqual( R"cpp( int main() {} @@ -48,7 +111,7 @@ TranslationUnit Detached )txt")); } -TEST_P(SyntaxTreeTest, SimpleVariable) { +TEST_P(BuildSyntaxTreeTest, SimpleVariable) { EXPECT_TRUE(treeDumpEqual( R"cpp( int a; @@ -72,7 +135,7 @@ TranslationUnit Detached )txt")); } -TEST_P(SyntaxTreeTest, SimpleFunction) { +TEST_P(BuildSyntaxTreeTest, SimpleFunction) { EXPECT_TRUE(treeDumpEqual( R"cpp( void foo(int a, int b) {} @@ -102,7 +165,7 @@ TranslationUnit Detached )txt")); } -TEST_P(SyntaxTreeTest, If) { +TEST_P(BuildSyntaxTreeTest, If) { EXPECT_TRUE(treeDumpEqualOnAnnotations( R"cpp( void test() { @@ -144,7 +207,7 @@ IfStatement Statement )txt"})); } -TEST_P(SyntaxTreeTest, For) { +TEST_P(BuildSyntaxTreeTest, For) { EXPECT_TRUE(treeDumpEqualOnAnnotations( R"cpp( void test() { @@ -164,7 +227,7 @@ ForStatement Statement )txt"})); } -TEST_P(SyntaxTreeTest, RangeBasedFor) { +TEST_P(BuildSyntaxTreeTest, RangeBasedFor) { if (!GetParam().isC
[clang] 23657d9 - [SyntaxTree] Add reverse links to syntax Nodes.
Author: Eduardo Caldas Date: 2020-11-05T09:33:53Z New Revision: 23657d9cc33282208bdac074abccd73bd4d4f8be URL: https://github.com/llvm/llvm-project/commit/23657d9cc33282208bdac074abccd73bd4d4f8be DIFF: https://github.com/llvm/llvm-project/commit/23657d9cc33282208bdac074abccd73bd4d4f8be.diff LOG: [SyntaxTree] Add reverse links to syntax Nodes. Rationale: Children of a syntax tree had forward links only, because there was no need for reverse links. This need appeared when we started mutating the syntax tree. On a forward list, to remove a target node in O(1) we need a pointer to the node before the target. If we don't have this "before" pointer, we have to find it, and that requires O(n). So in order to remove a syntax node from a tree, we would similarly need to find the node before to then remove. This is both not ergonomic nor does it have a good complexity. Differential Revision: https://reviews.llvm.org/D90240 Added: Modified: clang/include/clang/Tooling/Syntax/Tree.h clang/lib/Tooling/Syntax/BuildTree.cpp clang/lib/Tooling/Syntax/Mutations.cpp clang/lib/Tooling/Syntax/Synthesis.cpp clang/lib/Tooling/Syntax/Tree.cpp Removed: diff --git a/clang/include/clang/Tooling/Syntax/Tree.h b/clang/include/clang/Tooling/Syntax/Tree.h index 4bfa15517ba4..b92e92305417 100644 --- a/clang/include/clang/Tooling/Syntax/Tree.h +++ b/clang/include/clang/Tooling/Syntax/Tree.h @@ -118,6 +118,8 @@ class Node { const Node *getNextSibling() const { return NextSibling; } Node *getNextSibling() { return NextSibling; } + const Node *getPreviousSibling() const { return PreviousSibling; } + Node *getPreviousSibling() { return PreviousSibling; } /// Dumps the structure of a subtree. For debugging and testing purposes. std::string dump(const SourceManager &SM) const; @@ -144,6 +146,7 @@ class Node { Tree *Parent; Node *NextSibling; + Node *PreviousSibling; unsigned Kind : 16; unsigned Role : 8; unsigned Original : 1; @@ -197,6 +200,8 @@ class Tree : public Node { Node *getFirstChild() { return FirstChild; } const Node *getFirstChild() const { return FirstChild; } + Node *getLastChild() { return LastChild; } + const Node *getLastChild() const { return LastChild; } const Leaf *findFirstLeaf() const; Leaf *findFirstLeaf() { @@ -236,25 +241,32 @@ class Tree : public Node { using Node::Node; private: - /// Prepend \p Child to the list of children and and sets the parent pointer. + /// Append \p Child to the list of children and sets the parent pointer. /// A very low-level operation that does not check any invariants, only used /// by TreeBuilder and FactoryImpl. /// EXPECTS: Role != Detached. + void appendChildLowLevel(Node *Child, NodeRole Role); + /// Similar but prepends. void prependChildLowLevel(Node *Child, NodeRole Role); - /// Like the previous overload, but does not set role for \p Child. + + /// Like the previous overloads, but does not set role for \p Child. /// EXPECTS: Child->Role != Detached + void appendChildLowLevel(Node *Child); void prependChildLowLevel(Node *Child); friend class TreeBuilder; friend class FactoryImpl; - /// Replace a range of children [BeforeBegin->NextSibling, End) with a list of + /// Replace a range of children [Begin, End) with a list of /// new nodes starting at \p New. /// Only used by MutationsImpl to implement higher-level mutation operations. /// (!) \p New can be null to model removal of the child range. - void replaceChildRangeLowLevel(Node *BeforeBegin, Node *End, Node *New); + /// (!) \p End can be null to model one past the end. + /// (!) \p Begin can be null to model an append. + void replaceChildRangeLowLevel(Node *Begin, Node *End, Node *New); friend class MutationsImpl; Node *FirstChild = nullptr; + Node *LastChild = nullptr; }; // Provide missing non_const == const overload. diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp index 197590522e36..682e070d 100644 --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -636,12 +636,11 @@ class syntax::TreeBuilder { (EndChildren == Trees.end() || EndChildren->first == Tokens.end()) && "fold crosses boundaries of existing subtrees"); - // We need to go in reverse order, because we can only prepend. - for (auto It = EndChildren; It != BeginChildren; --It) { -auto *C = std::prev(It)->second; + for (auto It = BeginChildren; It != EndChildren; ++It) { +auto *C = It->second; if (C->getRole() == NodeRole::Detached) C->setRole(NodeRole::Unknown); -Node->prependChildLowLevel(C); +Node->appendChildLowLevel(C); } // Mark that this node came from the AST and is backed by the source code. diff --git a/clang/lib/
[clang] 5011d43 - Migrate Declarators to use the List API
Author: Eduardo Caldas Date: 2020-10-01T13:56:31Z New Revision: 5011d43108d1de30a056d66e73fa19062e0e84b7 URL: https://github.com/llvm/llvm-project/commit/5011d43108d1de30a056d66e73fa19062e0e84b7 DIFF: https://github.com/llvm/llvm-project/commit/5011d43108d1de30a056d66e73fa19062e0e84b7.diff LOG: Migrate Declarators to use the List API After this change all nodes that have a delimited-list are using the `List` API. Implementation details: Let's look at a declaration with multiple declarators: `int a, b;` To generate a declarator list node we need to have the range of declarators: `a, b`: However, the `ClangAST` actually stores them as separate declarations: `int a ;` `intb;` We solve that by appropriately marking the declarators on each separate declaration in the `ClangAST` and then for the final declarator `int b`, shrinking its range to fit to the already marked declarators. Differential Revision: https://reviews.llvm.org/D88403 Added: Modified: clang/include/clang/Tooling/Syntax/Nodes.h clang/lib/Tooling/Syntax/BuildTree.cpp clang/lib/Tooling/Syntax/Nodes.cpp clang/lib/Tooling/Syntax/Synthesis.cpp clang/unittests/Tooling/Syntax/BuildTreeTest.cpp clang/unittests/Tooling/Syntax/SynthesisTest.cpp Removed: diff --git a/clang/include/clang/Tooling/Syntax/Nodes.h b/clang/include/clang/Tooling/Syntax/Nodes.h index 8b393c5423b4..ed4449adb0f0 100644 --- a/clang/include/clang/Tooling/Syntax/Nodes.h +++ b/clang/include/clang/Tooling/Syntax/Nodes.h @@ -99,10 +99,14 @@ enum class NodeKind : uint16_t { ParametersAndQualifiers, MemberPointer, UnqualifiedId, + + // Lists + DeclaratorList, ParameterDeclarationList, CallArguments, - // Nested Name Specifiers. NestedNameSpecifier, + + // Name Specifiers. GlobalNameSpecifier, DecltypeNameSpecifier, IdentifierNameSpecifier, @@ -179,6 +183,7 @@ enum class NodeRole : uint8_t { Member, Callee, Arguments, + Declarators }; /// For debugging purposes. raw_ostream &operator<<(raw_ostream &OS, NodeRole R); @@ -823,6 +828,17 @@ class LinkageSpecificationDeclaration final : public Declaration { } }; +class DeclaratorList final : public List { +public: + DeclaratorList() : List(NodeKind::DeclaratorList) {} + static bool classof(const Node *N) { +return N->getKind() == NodeKind::DeclaratorList; + } + std::vector getDeclarators(); + std::vector> + getDeclaratorsAndCommas(); +}; + /// Groups multiple declarators (e.g. variables, typedefs, etc.) together. All /// grouped declarators share the same declaration specifiers (e.g. 'int' or /// 'typedef'). diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp index 4d365090abf1..e1ed55f2e4eb 100644 --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -397,6 +397,17 @@ class syntax::TreeBuilder { Mapping.add(From, New); } + /// Populate children for \p New list, assuming it covers tokens from a + /// subrange of \p SuperRange. + void foldList(ArrayRef SuperRange, syntax::List *New, +ASTPtr From) { +assert(New); +auto ListRange = Pending.shrinkToFitList(SuperRange); +Pending.foldChildren(Arena, ListRange, New); +if (From) + Mapping.add(From, New); + } + /// Notifies that we should not consume trailing semicolon when computing /// token range of \p D. void noticeDeclWithoutSemicolon(Decl *D); @@ -579,6 +590,35 @@ class syntax::TreeBuilder { It->second->setRole(Role); } +/// Shrink \p Range to a subrange that only contains tokens of a list. +/// List elements and delimiters should already have correct roles. +ArrayRef shrinkToFitList(ArrayRef Range) { + auto BeginChildren = Trees.lower_bound(Range.begin()); + assert((BeginChildren == Trees.end() || + BeginChildren->first == Range.begin()) && + "Range crosses boundaries of existing subtrees"); + + auto EndChildren = Trees.lower_bound(Range.end()); + assert( + (EndChildren == Trees.end() || EndChildren->first == Range.end()) && + "Range crosses boundaries of existing subtrees"); + + auto BelongsToList = [](decltype(Trees)::value_type KV) { +auto Role = KV.second->getRole(); +return Role == syntax::NodeRole::ListElement || + Role == syntax::NodeRole::ListDelimiter; + }; + + auto BeginListChildren = + std::find_if(BeginChildren, EndChildren, BelongsToList); + + auto EndListChildren = + std::find_if_not(BeginListChildren, EndChildren, BelongsToList); + + return ArrayRef(BeginListChildren->first, + EndListChildren->first); +} + /// Add \p Node to the forest and attach child nodes based on \p Tokens. void foldChildren(const syntax::Arena &A, ArrayRef Tokens,
[clang] a8f1790 - [SyntaxTree] Fix rtti for `Expression`.
Author: Eduardo Caldas Date: 2020-10-13T14:47:43Z New Revision: a8f1790fdb8ce1c53f024870cd51f32724d4c55f URL: https://github.com/llvm/llvm-project/commit/a8f1790fdb8ce1c53f024870cd51f32724d4c55f DIFF: https://github.com/llvm/llvm-project/commit/a8f1790fdb8ce1c53f024870cd51f32724d4c55f.diff LOG: [SyntaxTree] Fix rtti for `Expression`. Differential Revision: https://reviews.llvm.org/D89146 Added: Modified: clang/include/clang/Tooling/Syntax/Nodes.h Removed: diff --git a/clang/include/clang/Tooling/Syntax/Nodes.h b/clang/include/clang/Tooling/Syntax/Nodes.h index ed4449adb0f0..33ed2ec5c349 100644 --- a/clang/include/clang/Tooling/Syntax/Nodes.h +++ b/clang/include/clang/Tooling/Syntax/Nodes.h @@ -206,7 +206,7 @@ class Expression : public Tree { Expression(NodeKind K) : Tree(K) {} static bool classof(const Node *N) { return NodeKind::UnknownExpression <= N->getKind() && - N->getKind() <= NodeKind::UnknownExpression; + N->getKind() <= NodeKind::CallExpression; } }; ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 4178f8f - [SyntaxTree] Improve safety of `replaceChildRangeLowLevel`
Author: Eduardo Caldas Date: 2020-10-14T09:18:32Z New Revision: 4178f8f2f08e14abb341fb32dd0f4cc9320df072 URL: https://github.com/llvm/llvm-project/commit/4178f8f2f08e14abb341fb32dd0f4cc9320df072 DIFF: https://github.com/llvm/llvm-project/commit/4178f8f2f08e14abb341fb32dd0f4cc9320df072.diff LOG: [SyntaxTree] Improve safety of `replaceChildRangeLowLevel` * Add assertions for other preconditions. * If nothing is modified, don't mark it. Differential Revision: https://reviews.llvm.org/D89303 Added: Modified: clang/lib/Tooling/Syntax/Tree.cpp Removed: diff --git a/clang/lib/Tooling/Syntax/Tree.cpp b/clang/lib/Tooling/Syntax/Tree.cpp index b558e7ab9a1b..74cd3c1f68b1 100644 --- a/clang/lib/Tooling/Syntax/Tree.cpp +++ b/clang/lib/Tooling/Syntax/Tree.cpp @@ -94,48 +94,65 @@ void syntax::Tree::prependChildLowLevel(Node *Child) { void syntax::Tree::replaceChildRangeLowLevel(Node *BeforeBegin, Node *End, Node *New) { - assert(!BeforeBegin || BeforeBegin->Parent == this); + assert((!BeforeBegin || BeforeBegin->Parent == this) && + "`BeforeBegin` is not a child of `this`."); + assert((!End || End->Parent == this) && "`End` is not a child of `this`."); + assert(canModify() && "Cannot modify `this`."); #ifndef NDEBUG - for (auto *N = New; N; N = N->getNextSibling()) { + for (auto *N = New; N; N = N->NextSibling) { assert(N->Parent == nullptr); assert(N->getRole() != NodeRole::Detached && "Roles must be set"); // FIXME: sanity-check the role. } + + auto Reachable = [](Node *From, Node *N) { +if (!N) + return true; +for (auto *It = From; It; It = It->NextSibling) + if (It == N) +return true; +return false; + }; + assert(Reachable(FirstChild, BeforeBegin) && + "`BeforeBegin` is not reachable."); + assert(Reachable(BeforeBegin ? BeforeBegin->NextSibling : FirstChild, End) && + "`End` is not after `BeforeBegin`."); #endif + Node *&Begin = BeforeBegin ? BeforeBegin->NextSibling : FirstChild; + + if (!New && Begin == End) +return; + + // Mark modification. + for (auto *T = this; T && T->Original; T = T->Parent) +T->Original = false; // Detach old nodes. - for (auto *N = !BeforeBegin ? FirstChild : BeforeBegin->getNextSibling(); - N != End;) { + for (auto *N = Begin; N != End;) { auto *Next = N->NextSibling; N->setRole(NodeRole::Detached); N->Parent = nullptr; N->NextSibling = nullptr; if (N->Original) - traverse(N, [&](Node *C) { C->Original = false; }); + traverse(N, [](Node *C) { C->Original = false; }); N = Next; } + if (!New) { +Begin = End; +return; + } // Attach new nodes. - if (BeforeBegin) -BeforeBegin->NextSibling = New ? New : End; - else -FirstChild = New ? New : End; - - if (New) { -auto *Last = New; -for (auto *N = New; N != nullptr; N = N->getNextSibling()) { - Last = N; - N->Parent = this; -} -Last->NextSibling = End; + Begin = New; + auto *Last = New; + for (auto *N = New; N != nullptr; N = N->NextSibling) { +Last = N; +N->Parent = this; } - - // Mark the node as modified. - for (auto *T = this; T && T->Original; T = T->Parent) -T->Original = false; + Last->NextSibling = End; } namespace { ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 72732ac - [SyntaxTree] Bug fix in `MutationsImpl::addAfter`.
Author: Eduardo Caldas Date: 2020-10-14T09:22:01Z New Revision: 72732acade77d5ee55a818e2da77a2c5b7033ccb URL: https://github.com/llvm/llvm-project/commit/72732acade77d5ee55a818e2da77a2c5b7033ccb DIFF: https://github.com/llvm/llvm-project/commit/72732acade77d5ee55a818e2da77a2c5b7033ccb.diff LOG: [SyntaxTree] Bug fix in `MutationsImpl::addAfter`. * Add assertions to other `MutationsImpl` member functions * `findPrevious` is a free function Differential Revision: https://reviews.llvm.org/D89314 Added: Modified: clang/lib/Tooling/Syntax/Mutations.cpp Removed: diff --git a/clang/lib/Tooling/Syntax/Mutations.cpp b/clang/lib/Tooling/Syntax/Mutations.cpp index bf1bcda26455..8def1c729689 100644 --- a/clang/lib/Tooling/Syntax/Mutations.cpp +++ b/clang/lib/Tooling/Syntax/Mutations.cpp @@ -23,6 +23,19 @@ using namespace clang; +static syntax::Node *findPrevious(syntax::Node *N) { + assert(N); + assert(N->getParent()); + if (N->getParent()->getFirstChild() == N) +return nullptr; + for (syntax::Node *C = N->getParent()->getFirstChild(); C != nullptr; + C = C->getNextSibling()) { +if (C->getNextSibling() == N) + return C; + } + llvm_unreachable("could not find a child node"); +} + // This class has access to the internals of tree nodes. Its sole purpose is to // define helpers that allow implementing the high-level mutation operations. class syntax::MutationsImpl { @@ -30,14 +43,15 @@ class syntax::MutationsImpl { /// Add a new node with a specified role. static void addAfter(syntax::Node *Anchor, syntax::Node *New, NodeRole Role) { assert(Anchor != nullptr); +assert(Anchor->Parent != nullptr); assert(New->Parent == nullptr); assert(New->NextSibling == nullptr); -assert(!New->isDetached()); +assert(New->isDetached()); assert(Role != NodeRole::Detached); New->setRole(Role); auto *P = Anchor->getParent(); -P->replaceChildRangeLowLevel(Anchor, Anchor, New); +P->replaceChildRangeLowLevel(Anchor, Anchor->getNextSibling(), New); P->assertInvariants(); } @@ -60,6 +74,10 @@ class syntax::MutationsImpl { /// Completely remove the node from its parent. static void remove(syntax::Node *N) { +assert(N != nullptr); +assert(N->Parent != nullptr); +assert(N->canModify()); + auto *P = N->getParent(); P->replaceChildRangeLowLevel(findPrevious(N), N->getNextSibling(), /*New=*/nullptr); @@ -67,18 +85,6 @@ class syntax::MutationsImpl { P->assertInvariants(); N->assertInvariants(); } - -private: - static syntax::Node *findPrevious(syntax::Node *N) { -if (N->getParent()->getFirstChild() == N) - return nullptr; -for (syntax::Node *C = N->getParent()->getFirstChild(); C != nullptr; - C = C->getNextSibling()) { - if (C->getNextSibling() == N) -return C; -} -llvm_unreachable("could not find a child node"); - } }; void syntax::removeStatement(syntax::Arena &A, syntax::Statement *S) { ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 6fbad9b - [SyntaxTree][NFC] Nit on `replaceChildRangeLowLevel`
Author: Eduardo Caldas Date: 2020-10-14T09:40:37Z New Revision: 6fbad9bf304c05d37454420f7d5a1c2ab3adab20 URL: https://github.com/llvm/llvm-project/commit/6fbad9bf304c05d37454420f7d5a1c2ab3adab20 DIFF: https://github.com/llvm/llvm-project/commit/6fbad9bf304c05d37454420f7d5a1c2ab3adab20.diff LOG: [SyntaxTree][NFC] Nit on `replaceChildRangeLowLevel` Added: Modified: clang/lib/Tooling/Syntax/Tree.cpp Removed: diff --git a/clang/lib/Tooling/Syntax/Tree.cpp b/clang/lib/Tooling/Syntax/Tree.cpp index 74cd3c1f68b1..87526ad7a976 100644 --- a/clang/lib/Tooling/Syntax/Tree.cpp +++ b/clang/lib/Tooling/Syntax/Tree.cpp @@ -99,6 +99,8 @@ void syntax::Tree::replaceChildRangeLowLevel(Node *BeforeBegin, Node *End, assert((!End || End->Parent == this) && "`End` is not a child of `this`."); assert(canModify() && "Cannot modify `this`."); + Node *&Begin = BeforeBegin ? BeforeBegin->NextSibling : FirstChild; + #ifndef NDEBUG for (auto *N = New; N; N = N->NextSibling) { assert(N->Parent == nullptr); @@ -116,10 +118,8 @@ void syntax::Tree::replaceChildRangeLowLevel(Node *BeforeBegin, Node *End, }; assert(Reachable(FirstChild, BeforeBegin) && "`BeforeBegin` is not reachable."); - assert(Reachable(BeforeBegin ? BeforeBegin->NextSibling : FirstChild, End) && - "`End` is not after `BeforeBegin`."); + assert(Reachable(Begin, End) && "`End` is not after `BeforeBegin`."); #endif - Node *&Begin = BeforeBegin ? BeforeBegin->NextSibling : FirstChild; if (!New && Begin == End) return; ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits