eduucaldas updated this revision to Diff 276361.
eduucaldas added a comment.

Reflect fix on RecursiveASTVisitor


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D82157/new/

https://reviews.llvm.org/D82157

Files:
  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

Index: clang/unittests/Tooling/Syntax/TreeTest.cpp
===================================================================
--- clang/unittests/Tooling/Syntax/TreeTest.cpp
+++ clang/unittests/Tooling/Syntax/TreeTest.cpp
@@ -1184,6 +1184,93 @@
 )txt"));
 }
 
+TEST_P(SyntaxTreeTest, UserDefinedLiteral) {
+  if (!GetParam().isCXX11OrLater()) {
+    return;
+  }
+  EXPECT_TRUE(treeDumpEqual(
+      R"cpp(
+long double operator "" _w(long double);
+unsigned operator "" _w(const char*);
+template <char...> unsigned operator "" _x();
+int main() {
+    1.2_w; // calls operator "" _w(1.2L)
+    12_w;  // calls operator "" _w("12")
+    12_x;  // calls operator<'1', '2'> "" _x()
+}
+    )cpp",
+      R"txt(
+*: TranslationUnit
+|-SimpleDeclaration
+| |-long
+| |-double
+| |-SimpleDeclarator
+| | |-operator
+| | |-""
+| | |-_w
+| | `-ParametersAndQualifiers
+| |   |-(
+| |   |-SimpleDeclaration
+| |   | |-long
+| |   | `-double
+| |   `-)
+| `-;
+|-SimpleDeclaration
+| |-unsigned
+| |-SimpleDeclarator
+| | |-operator
+| | |-""
+| | |-_w
+| | `-ParametersAndQualifiers
+| |   |-(
+| |   |-SimpleDeclaration
+| |   | |-const
+| |   | |-char
+| |   | `-SimpleDeclarator
+| |   |   `-*
+| |   `-)
+| `-;
+|-TemplateDeclaration
+| |-template
+| |-<
+| |-SimpleDeclaration
+| | `-char
+| |-...
+| |->
+| `-SimpleDeclaration
+|   |-unsigned
+|   |-SimpleDeclarator
+|   | |-operator
+|   | |-""
+|   | |-_x
+|   | `-ParametersAndQualifiers
+|   |   |-(
+|   |   `-)
+|   `-;
+`-SimpleDeclaration
+  |-int
+  |-SimpleDeclarator
+  | |-main
+  | `-ParametersAndQualifiers
+  |   |-(
+  |   `-)
+  `-CompoundStatement
+    |-{
+    |-ExpressionStatement
+    | |-UserDefinedLiteralExpression
+    | | `-1.2_w
+    | `-;
+    |-ExpressionStatement
+    | |-UserDefinedLiteralExpression
+    | | `-12_w
+    | `-;
+    |-ExpressionStatement
+    | |-UserDefinedLiteralExpression
+    | | `-12_x
+    | `-;
+    `-}
+)txt"));
+}
 TEST_P(SyntaxTreeTest, IntegerLiteral) {
   EXPECT_TRUE(treeDumpEqual(
       R"cpp(
Index: clang/lib/Tooling/Syntax/Nodes.cpp
===================================================================
--- clang/lib/Tooling/Syntax/Nodes.cpp
+++ clang/lib/Tooling/Syntax/Nodes.cpp
@@ -32,6 +32,8 @@
     return OS << "BoolLiteralExpression";
   case NodeKind::CxxNullPtrExpression:
     return OS << "CxxNullPtrExpression";
+  case NodeKind::UserDefinedLiteralExpression:
+    return OS << "UserDefinedLiteralExpression";
   case NodeKind::PrefixUnaryOperatorExpression:
     return OS << "PrefixUnaryOperatorExpression";
   case NodeKind::PostfixUnaryOperatorExpression:
@@ -252,6 +254,11 @@
       findChild(syntax::NodeRole::LiteralToken));
 }
 
+syntax::Leaf *syntax::UserDefinedLiteralExpression::literalToken() {
+  return llvm::cast_or_null<syntax::Leaf>(
+      findChild(syntax::NodeRole::LiteralToken));
+}
+
 syntax::Expression *syntax::BinaryOperatorExpression::lhs() {
   return llvm::cast_or_null<syntax::Expression>(
       findChild(syntax::NodeRole::BinaryOperatorExpression_leftHandSide));
Index: clang/lib/Tooling/Syntax/BuildTree.cpp
===================================================================
--- clang/lib/Tooling/Syntax/BuildTree.cpp
+++ clang/lib/Tooling/Syntax/BuildTree.cpp
@@ -627,6 +627,26 @@
     return NNS;
   }
 
+  bool TraverseUserDefinedLiteral(UserDefinedLiteral *S) {
+    // The user-defined literal `1.2_w` corresponds to *one* token. The semantic
+    // node for it however may have two children nodes, both with valid
+    // `SourceLocation`s. As a result one of these nodes has a valid
+    // `SourceLocation` that doesn't point to a token.
+    //
+    // If we traverse the children of a user-defined literal, we then arrive to
+    // a semantic node that doesn't have a token, and that breaks an invariant
+    // of the syntax tree. For that reason we skip traversing user-defined
+    // literal children.
+
+    return WalkUpFromUserDefinedLiteral(S);
+  }
+
+  bool WalkUpFromUserDefinedLiteral(UserDefinedLiteral *S) {
+    Builder.markChildToken(S->getBeginLoc(), syntax::NodeRole::LiteralToken);
+    Builder.foldNode(Builder.getExprRange(S),
+                     new (allocator()) syntax::UserDefinedLiteralExpression, S);
+    return true;
+  }
   bool WalkUpFromDeclRefExpr(DeclRefExpr *S) {
     if (auto *NNS = BuildNestedNameSpecifier(S->getQualifierLoc()))
       Builder.markChild(NNS, syntax::NodeRole::IdExpression_qualifier);
Index: clang/include/clang/Tooling/Syntax/Nodes.h
===================================================================
--- clang/include/clang/Tooling/Syntax/Nodes.h
+++ clang/include/clang/Tooling/Syntax/Nodes.h
@@ -50,6 +50,7 @@
   StringLiteralExpression,
   BoolLiteralExpression,
   CxxNullPtrExpression,
+  UserDefinedLiteralExpression,
   IdExpression,
 
   // Statements.
@@ -325,6 +326,17 @@
   syntax::Leaf *nullPtrKeyword();
 };
 
+/// Expression for user-defined literal. C++ [lex.ext]
+class UserDefinedLiteralExpression final : public Expression {
+public:
+  UserDefinedLiteralExpression()
+      : Expression(NodeKind::UserDefinedLiteralExpression) {}
+  static bool classof(const Node *N) {
+    return N->kind() == NodeKind::UserDefinedLiteralExpression;
+  }
+  syntax::Leaf *literalToken();
+};
+
 /// An abstract class for prefix and postfix unary operators.
 class UnaryOperatorExpression : public Expression {
 public:
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to