[clang] d1211fd - [SyntaxTree] Split tests for expressions

Eduardo Caldas via cfe-commits cfe-commits at lists.llvm.org
Thu Aug 13 01:18:35 PDT 2020


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<typename T>
-void f(T&);
 void test(X x) {
-  x;                      // identifier
-  operator+(x, x);        // operator-function-id
-  f<X>(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
+| | |-""
+| | |-_w
+| | `-ParametersAndQualifiers
+| |   |-(
+| |   |-SimpleDeclaration
+| |   | `-char
+| |   `-)
+| `-;
+`-SimpleDeclaration
+  |-void
+  |-SimpleDeclarator
+  | |-test
+  | `-ParametersAndQualifiers
+  |   |-(
+  |   `-)
+  `-CompoundStatement
+    |-{
+    |-ExpressionStatement
+    | |-UnknownExpression
+    | | |-IdExpression
+    | | | `-UnqualifiedId
+    | | |   |-operator
+    | | |   |-""
+    | | |   `-_w
+    | | |-(
+    | | |-CharacterLiteralExpression
+    | | | `-'1'
+    | | `-)
+    | `-;
+    `-}
+)txt"));
+}
+
+TEST_P(SyntaxTreeTest, UnqualifiedIdDestructor) {
+  if (!GetParam().isCXX()) {
+    return;
+  }
+  EXPECT_TRUE(treeDumpEqual(
+      R"cpp(
+struct X { };
+void test(X x) {
+  // TODO: Expose `id-expression` from `MemberExpr`
+  x.~X();
+}
+)cpp",
+      R"txt(
+*: TranslationUnit
+|-SimpleDeclaration
+| |-struct
+| |-X
+| |-{
+| |-}
+| `-;
+`-SimpleDeclaration
+  |-void
+  |-SimpleDeclarator
+  | |-test
+  | `-ParametersAndQualifiers
+  |   |-(
+  |   |-SimpleDeclaration
+  |   | |-X
+  |   | `-SimpleDeclarator
+  |   |   `-x
+  |   `-)
+  `-CompoundStatement
+    |-{
     |-ExpressionStatement
     | |-UnknownExpression
     | | |-UnknownExpression
@@ -787,18 +897,16 @@ void test(X x) {
 )txt"));
 }
 
-TEST_P(SyntaxTreeTest, UnqualifiedIdCxx11OrLater) {
+TEST_P(SyntaxTreeTest, UnqualifiedIdDecltypeDestructor) {
   if (!GetParam().isCXX11OrLater()) {
     return;
   }
   EXPECT_TRUE(treeDumpEqual(
       R"cpp(
 struct X { };
-unsigned operator "" _w(long long unsigned);
 void test(X x) {
-  operator "" _w(1llu);   // literal-operator-id
   // TODO: Expose `id-expression` from `MemberExpr`
-  x.~decltype(x)();       // ~decltype-specifier
+  x.~decltype(x)();
 }
 )cpp",
       R"txt(
@@ -809,20 +917,6 @@ void test(X x) {
 | |-{
 | |-}
 | `-;
-|-SimpleDeclaration
-| |-unsigned
-| |-SimpleDeclarator
-| | |-operator
-| | |-""
-| | |-_w
-| | `-ParametersAndQualifiers
-| |   |-(
-| |   |-SimpleDeclaration
-| |   | |-long
-| |   | |-long
-| |   | `-unsigned
-| |   `-)
-| `-;
 `-SimpleDeclaration
   |-void
   |-SimpleDeclarator
@@ -838,18 +932,6 @@ void test(X x) {
     |-{
     |-ExpressionStatement
     | |-UnknownExpression
-    | | |-IdExpression
-    | | | `-UnqualifiedId
-    | | |   |-operator
-    | | |   |-""
-    | | |   `-_w
-    | | |-(
-    | | |-IntegerLiteralExpression
-    | | | `-1llu
-    | | `-)
-    | `-;
-    |-ExpressionStatement
-    | |-UnknownExpression
     | | |-UnknownExpression
     | | | |-IdExpression
     | | | | `-UnqualifiedId
@@ -867,83 +949,20 @@ void test(X x) {
 )txt"));
 }
 
-TEST_P(SyntaxTreeTest, QualifiedId) {
+TEST_P(SyntaxTreeTest, UnqualifiedIdTemplateId) {
   if (!GetParam().isCXX()) {
     return;
   }
   EXPECT_TRUE(treeDumpEqual(
       R"cpp(
-namespace n {
-  struct S {
-    template<typename T>
-    struct ST {
-      static void f();
-    };
-  };
-}
 template<typename T>
-struct ST {
-  struct S {
-    template<typename U>
-    static U f();
-  };
-};
+T f();
 void test() {
-  ::                 // global-namespace-specifier
-  n::                // namespace-specifier
-  S::                // type-name-specifier
-  template ST<int>:: // type-template-instantiation-specifier
-  f();
-
-  n::                // namespace-specifier
-  S::                // type-name-specifier
-  ST<int>::          // type-template-instantiation-specifier
-  f();
-
-  ST<int>::         // type-name-specifier
-  S::               // type-name-specifier
   f<int>();
-
-  ST<int>::         // type-name-specifier
-  S::               // type-name-specifier
-  template f<int>();
 }
 )cpp",
       R"txt(
 *: TranslationUnit
-|-NamespaceDefinition
-| |-namespace
-| |-n
-| |-{
-| |-SimpleDeclaration
-| | |-struct
-| | |-S
-| | |-{
-| | |-TemplateDeclaration
-| | | |-template
-| | | |-<
-| | | |-UnknownDeclaration
-| | | | |-typename
-| | | | `-T
-| | | |->
-| | | `-SimpleDeclaration
-| | |   |-struct
-| | |   |-ST
-| | |   |-{
-| | |   |-SimpleDeclaration
-| | |   | |-static
-| | |   | |-void
-| | |   | |-SimpleDeclarator
-| | |   | | |-f
-| | |   | | `-ParametersAndQualifiers
-| | |   | |   |-(
-| | |   | |   `-)
-| | |   | `-;
-| | |   |-}
-| | |   `-;
-| | |-}
-| | `-;
-| `-}
 |-TemplateDeclaration
 | |-template
 | |-<
@@ -952,36 +971,16 @@ void test() {
 | | `-T
 | |->
 | `-SimpleDeclaration
-|   |-struct
-|   |-ST
-|   |-{
-|   |-SimpleDeclaration
-|   | |-struct
-|   | |-S
-|   | |-{
-|   | |-TemplateDeclaration
-|   | | |-template
-|   | | |-<
-|   | | |-UnknownDeclaration
-|   | | | |-typename
-|   | | | `-U
-|   | | |->
-|   | | `-SimpleDeclaration
-|   | |   |-static
-|   | |   |-U
-|   | |   |-SimpleDeclarator
-|   | |   | |-f
-|   | |   | `-ParametersAndQualifiers
-|   | |   |   |-(
-|   | |   |   `-)
-|   | |   `-;
-|   | |-}
-|   | `-;
-|   |-}
-|   `-;
-`-SimpleDeclaration
-  |-void
-  |-SimpleDeclarator
+|   |-T
+|   |-SimpleDeclarator
+|   | |-f
+|   | `-ParametersAndQualifiers
+|   |   |-(
+|   |   `-)
+|   `-;
+`-SimpleDeclaration
+  |-void
+  |-SimpleDeclarator
   | |-test
   | `-ParametersAndQualifiers
   |   |-(
@@ -991,44 +990,221 @@ void test() {
     |-ExpressionStatement
     | |-UnknownExpression
     | | |-IdExpression
-    | | | |-NestedNameSpecifier
-    | | | | |-::
-    | | | | |-IdentifierNameSpecifier
-    | | | | | `-n
-    | | | | |-::
-    | | | | |-IdentifierNameSpecifier
-    | | | | | `-S
-    | | | | |-::
-    | | | | |-SimpleTemplateNameSpecifier
-    | | | | | |-template
-    | | | | | |-ST
-    | | | | | |-<
-    | | | | | |-int
-    | | | | | `->
-    | | | | `-::
     | | | `-UnqualifiedId
-    | | |   `-f
+    | | |   |-f
+    | | |   |-<
+    | | |   |-int
+    | | |   `->
     | | |-(
     | | `-)
     | `-;
+    `-}
+)txt"));
+}
+
+TEST_P(SyntaxTreeTest, QualifiedIdWithNamespace) {
+  if (!GetParam().isCXX()) {
+    return;
+  }
+  EXPECT_TRUE(treeDumpEqual(
+      R"cpp(
+namespace n {
+  struct S { };
+}
+void test() {
+  ::n::S s1;
+  n::S s2;
+}
+)cpp",
+      R"txt(
+*: TranslationUnit
+|-NamespaceDefinition
+| |-namespace
+| |-n
+| |-{
+| |-SimpleDeclaration
+| | |-struct
+| | |-S
+| | |-{
+| | |-}
+| | `-;
+| `-}
+`-SimpleDeclaration
+  |-void
+  |-SimpleDeclarator
+  | |-test
+  | `-ParametersAndQualifiers
+  |   |-(
+  |   `-)
+  `-CompoundStatement
+    |-{
+    |-DeclarationStatement
+    | |-SimpleDeclaration
+    | | |-NestedNameSpecifier
+    | | | |-::
+    | | | |-IdentifierNameSpecifier
+    | | | | `-n
+    | | | `-::
+    | | |-S
+    | | `-SimpleDeclarator
+    | |   `-UnknownExpression
+    | |     `-s1
+    | `-;
+    |-DeclarationStatement
+    | |-SimpleDeclaration
+    | | |-NestedNameSpecifier
+    | | | |-IdentifierNameSpecifier
+    | | | | `-n
+    | | | `-::
+    | | |-S
+    | | `-SimpleDeclarator
+    | |   `-UnknownExpression
+    | |     `-s2
+    | `-;
+    `-}
+)txt"));
+}
+
+TEST_P(SyntaxTreeTest, QualifiedIdWithTemplateSpecifier) {
+  if (!GetParam().isCXX()) {
+    return;
+  }
+  EXPECT_TRUE(treeDumpEqual(
+      R"cpp(
+template<typename T>
+struct ST {
+  struct S { };
+};
+void test() {
+  ::template ST<int>::S s1;
+  ::ST<int>::S s2;
+}
+)cpp",
+      R"txt(
+*: TranslationUnit
+|-TemplateDeclaration
+| |-template
+| |-<
+| |-UnknownDeclaration
+| | |-typename
+| | `-T
+| |->
+| `-SimpleDeclaration
+|   |-struct
+|   |-ST
+|   |-{
+|   |-SimpleDeclaration
+|   | |-struct
+|   | |-S
+|   | |-{
+|   | |-}
+|   | `-;
+|   |-}
+|   `-;
+`-SimpleDeclaration
+  |-void
+  |-SimpleDeclarator
+  | |-test
+  | `-ParametersAndQualifiers
+  |   |-(
+  |   `-)
+  `-CompoundStatement
+    |-{
+    |-DeclarationStatement
+    | |-SimpleDeclaration
+    | | |-NestedNameSpecifier
+    | | | |-::
+    | | | |-SimpleTemplateNameSpecifier
+    | | | | |-template
+    | | | | |-ST
+    | | | | |-<
+    | | | | |-int
+    | | | | `->
+    | | | `-::
+    | | |-S
+    | | `-SimpleDeclarator
+    | |   `-UnknownExpression
+    | |     `-s1
+    | `-;
+    |-DeclarationStatement
+    | |-SimpleDeclaration
+    | | |-NestedNameSpecifier
+    | | | |-::
+    | | | |-SimpleTemplateNameSpecifier
+    | | | | |-ST
+    | | | | |-<
+    | | | | |-int
+    | | | | `->
+    | | | `-::
+    | | |-S
+    | | `-SimpleDeclarator
+    | |   `-UnknownExpression
+    | |     `-s2
+    | `-;
+    `-}
+)txt"));
+}
+
+TEST_P(SyntaxTreeTest, QualifiedIdWithOptionalTemplateKw) {
+  if (!GetParam().isCXX()) {
+    return;
+  }
+  EXPECT_TRUE(treeDumpEqual(
+      R"cpp(
+struct S {
+  template<typename U>
+  static U f();
+};
+void test() {
+  S::f<int>();
+  S::template f<int>();
+}
+)cpp",
+      R"txt(
+*: TranslationUnit
+|-SimpleDeclaration
+| |-struct
+| |-S
+| |-{
+| |-TemplateDeclaration
+| | |-template
+| | |-<
+| | |-UnknownDeclaration
+| | | |-typename
+| | | `-U
+| | |->
+| | `-SimpleDeclaration
+| |   |-static
+| |   |-U
+| |   |-SimpleDeclarator
+| |   | |-f
+| |   | `-ParametersAndQualifiers
+| |   |   |-(
+| |   |   `-)
+| |   `-;
+| |-}
+| `-;
+`-SimpleDeclaration
+  |-void
+  |-SimpleDeclarator
+  | |-test
+  | `-ParametersAndQualifiers
+  |   |-(
+  |   `-)
+  `-CompoundStatement
+    |-{
     |-ExpressionStatement
     | |-UnknownExpression
     | | |-IdExpression
     | | | |-NestedNameSpecifier
     | | | | |-IdentifierNameSpecifier
-    | | | | | `-n
-    | | | | |-::
-    | | | | |-IdentifierNameSpecifier
     | | | | | `-S
-    | | | | |-::
-    | | | | |-SimpleTemplateNameSpecifier
-    | | | | | |-ST
-    | | | | | |-<
-    | | | | | |-int
-    | | | | | `->
     | | | | `-::
     | | | `-UnqualifiedId
-    | | |   `-f
+    | | |   |-f
+    | | |   |-<
+    | | |   |-int
+    | | |   `->
     | | |-(
     | | `-)
     | `-;
@@ -1036,15 +1212,10 @@ void test() {
     | |-UnknownExpression
     | | |-IdExpression
     | | | |-NestedNameSpecifier
-    | | | | |-SimpleTemplateNameSpecifier
-    | | | | | |-ST
-    | | | | | |-<
-    | | | | | |-int
-    | | | | | `->
-    | | | | |-::
     | | | | |-IdentifierNameSpecifier
     | | | | | `-S
     | | | | `-::
+    | | | |-template
     | | | `-UnqualifiedId
     | | |   |-f
     | | |   |-<
@@ -1053,18 +1224,86 @@ void test() {
     | | |-(
     | | `-)
     | `-;
+    `-}
+)txt"));
+}
+
+TEST_P(SyntaxTreeTest, QualifiedIdComplex) {
+  if (!GetParam().isCXX()) {
+    return;
+  }
+  EXPECT_TRUE(treeDumpEqual(
+      R"cpp(
+namespace n {
+    template<typename T>
+    struct ST {
+      template<typename U>
+      static U f();
+    };
+}
+void test() {
+  ::n::template ST<int>::template f<int>();
+}
+)cpp",
+      R"txt(
+*: TranslationUnit
+|-NamespaceDefinition
+| |-namespace
+| |-n
+| |-{
+| |-TemplateDeclaration
+| | |-template
+| | |-<
+| | |-UnknownDeclaration
+| | | |-typename
+| | | `-T
+| | |->
+| | `-SimpleDeclaration
+| |   |-struct
+| |   |-ST
+| |   |-{
+| |   |-TemplateDeclaration
+| |   | |-template
+| |   | |-<
+| |   | |-UnknownDeclaration
+| |   | | |-typename
+| |   | | `-U
+| |   | |->
+| |   | `-SimpleDeclaration
+| |   |   |-static
+| |   |   |-U
+| |   |   |-SimpleDeclarator
+| |   |   | |-f
+| |   |   | `-ParametersAndQualifiers
+| |   |   |   |-(
+| |   |   |   `-)
+| |   |   `-;
+| |   |-}
+| |   `-;
+| `-}
+`-SimpleDeclaration
+  |-void
+  |-SimpleDeclarator
+  | |-test
+  | `-ParametersAndQualifiers
+  |   |-(
+  |   `-)
+  `-CompoundStatement
+    |-{
     |-ExpressionStatement
     | |-UnknownExpression
     | | |-IdExpression
     | | | |-NestedNameSpecifier
+    | | | | |-::
+    | | | | |-IdentifierNameSpecifier
+    | | | | | `-n
+    | | | | |-::
     | | | | |-SimpleTemplateNameSpecifier
+    | | | | | |-template
     | | | | | |-ST
     | | | | | |-<
     | | | | | |-int
     | | | | | `->
-    | | | | |-::
-    | | | | |-IdentifierNameSpecifier
-    | | | | | `-S
     | | | | `-::
     | | | |-template
     | | | `-UnqualifiedId
@@ -1093,9 +1332,7 @@ TEST_P(SyntaxTreeTest, QualifiedIdWithDependentType) {
 template <typename T>
 void test() {
   T::template U<int>::f();
-
   T::U::f();
-
   T::template f<0>();
 }
 )cpp",
@@ -1182,8 +1419,7 @@ struct S {
   static void f(){}
 };
 void test(S s) {
-  decltype(s)::   // decltype-specifier
-      f();
+  decltype(s)::f();
 }
 )cpp",
       R"txt(
@@ -1294,47 +1530,75 @@ void test() {
 )txt"));
 }
 
-TEST_P(SyntaxTreeTest, UserDefinedLiteral) {
+TEST_P(SyntaxTreeTest, CharUserDefinedLiteral) {
   if (!GetParam().isCXX11OrLater()) {
     return;
   }
   EXPECT_TRUE(treeDumpEqual(
       R"cpp(
-typedef decltype(sizeof(void *)) size_t;
-
-unsigned operator "" _i(unsigned long long);
-unsigned operator "" _f(long double);
 unsigned operator "" _c(char);
-unsigned operator "" _s(const char*, size_t);
-unsigned operator "" _r(const char*);
-template <char...>
-unsigned operator "" _t();
-
 void test() {
-  12_i;   // call: operator "" _i(12uLL)      | kind: integer
-  1.2_f;  // call: operator "" _f(1.2L)       | kind: float
-  '2'_c;  // call: operator "" _c('2')        | kind: char
-  "12"_s; // call: operator "" _s("12")       | kind: string
-
-  12_r;   // call: operator "" _r("12")       | kind: integer
-  1.2_r;  // call: operator "" _i("1.2")      | kind: float
-  12_t;   // call: operator<'1', '2'> "" _x() | kind: integer
-  1.2_t;  // call: operator<'1', '2'> "" _x() | kind: float
+  '2'_c;
 }
     )cpp",
       R"txt(
 *: TranslationUnit
 |-SimpleDeclaration
-| |-typedef
-| |-decltype
-| |-(
-| |-UnknownExpression
-| | |-sizeof
-| | |-(
-| | |-void
-| | |-*
-| | `-)
-| |-)
+| |-unsigned
+| |-SimpleDeclarator
+| | |-operator
+| | |-""
+| | |-_c
+| | `-ParametersAndQualifiers
+| |   |-(
+| |   |-SimpleDeclaration
+| |   | `-char
+| |   `-)
+| `-;
+`-SimpleDeclaration
+  |-void
+  |-SimpleDeclarator
+  | |-test
+  | `-ParametersAndQualifiers
+  |   |-(
+  |   `-)
+  `-CompoundStatement
+    |-{
+    |-ExpressionStatement
+    | |-CharUserDefinedLiteralExpression
+    | | `-'2'_c
+    | `-;
+    `-}
+)txt"));
+}
+
+TEST_P(SyntaxTreeTest, StringUserDefinedLiteral) {
+  if (!GetParam().isCXX11OrLater()) {
+    return;
+  }
+  EXPECT_TRUE(treeDumpEqual(
+      R"cpp(
+typedef decltype(sizeof(void *)) size_t;
+
+unsigned operator "" _s(const char*, size_t);
+
+void test() {
+  "12"_s;
+}
+    )cpp",
+      R"txt(
+*: TranslationUnit
+|-SimpleDeclaration
+| |-typedef
+| |-decltype
+| |-(
+| |-UnknownExpression
+| | |-sizeof
+| | |-(
+| | |-void
+| | |-*
+| | `-)
+| |-)
 | |-SimpleDeclarator
 | | `-size_t
 | `-;
@@ -1343,26 +1607,67 @@ void test() {
 | |-SimpleDeclarator
 | | |-operator
 | | |-""
-| | |-_i
+| | |-_s
 | | `-ParametersAndQualifiers
 | |   |-(
 | |   |-SimpleDeclaration
-| |   | |-unsigned
-| |   | |-long
-| |   | `-long
+| |   | |-const
+| |   | |-char
+| |   | `-SimpleDeclarator
+| |   |   `-*
+| |   |-,
+| |   |-SimpleDeclaration
+| |   | `-size_t
 | |   `-)
 | `-;
+`-SimpleDeclaration
+  |-void
+  |-SimpleDeclarator
+  | |-test
+  | `-ParametersAndQualifiers
+  |   |-(
+  |   `-)
+  `-CompoundStatement
+    |-{
+    |-ExpressionStatement
+    | |-StringUserDefinedLiteralExpression
+    | | `-"12"_s
+    | `-;
+    `-}
+)txt"));
+}
+
+TEST_P(SyntaxTreeTest, IntegerUserDefinedLiteral) {
+  if (!GetParam().isCXX11OrLater()) {
+    return;
+  }
+  EXPECT_TRUE(treeDumpEqual(
+      R"cpp(
+unsigned operator "" _i(unsigned long long);
+unsigned operator "" _r(const char*);
+template <char...>
+unsigned operator "" _t();
+
+void test() {
+  12_i;
+  12_r;
+  12_t;
+}
+    )cpp",
+      R"txt(
+*: TranslationUnit
 |-SimpleDeclaration
 | |-unsigned
 | |-SimpleDeclarator
 | | |-operator
 | | |-""
-| | |-_f
+| | |-_i
 | | `-ParametersAndQualifiers
 | |   |-(
 | |   |-SimpleDeclaration
+| |   | |-unsigned
 | |   | |-long
-| |   | `-double
+| |   | `-long
 | |   `-)
 | `-;
 |-SimpleDeclaration
@@ -1370,29 +1675,88 @@ void test() {
 | |-SimpleDeclarator
 | | |-operator
 | | |-""
-| | |-_c
+| | |-_r
 | | `-ParametersAndQualifiers
 | |   |-(
 | |   |-SimpleDeclaration
-| |   | `-char
+| |   | |-const
+| |   | |-char
+| |   | `-SimpleDeclarator
+| |   |   `-*
 | |   `-)
 | `-;
+|-TemplateDeclaration
+| |-template
+| |-<
+| |-SimpleDeclaration
+| | `-char
+| |-...
+| |->
+| `-SimpleDeclaration
+|   |-unsigned
+|   |-SimpleDeclarator
+|   | |-operator
+|   | |-""
+|   | |-_t
+|   | `-ParametersAndQualifiers
+|   |   |-(
+|   |   `-)
+|   `-;
+`-SimpleDeclaration
+  |-void
+  |-SimpleDeclarator
+  | |-test
+  | `-ParametersAndQualifiers
+  |   |-(
+  |   `-)
+  `-CompoundStatement
+    |-{
+    |-ExpressionStatement
+    | |-IntegerUserDefinedLiteralExpression
+    | | `-12_i
+    | `-;
+    |-ExpressionStatement
+    | |-IntegerUserDefinedLiteralExpression
+    | | `-12_r
+    | `-;
+    |-ExpressionStatement
+    | |-IntegerUserDefinedLiteralExpression
+    | | `-12_t
+    | `-;
+    `-}
+)txt"));
+}
+
+TEST_P(SyntaxTreeTest, FloatUserDefinedLiteral) {
+  if (!GetParam().isCXX11OrLater()) {
+    return;
+  }
+  EXPECT_TRUE(treeDumpEqual(
+      R"cpp(
+unsigned operator "" _f(long double);
+unsigned operator "" _r(const char*);
+template <char...>
+unsigned operator "" _t();
+
+void test() {
+  1.2_f;  // call: operator "" _f(1.2L)       | kind: float
+  1.2_r;  // call: operator "" _i("1.2")      | kind: float
+  1.2_t;  // call: operator<'1', '2'> "" _x() | kind: float
+}
+    )cpp",
+      R"txt(
+*: TranslationUnit
 |-SimpleDeclaration
 | |-unsigned
 | |-SimpleDeclarator
 | | |-operator
 | | |-""
-| | |-_s
+| | |-_f
 | | `-ParametersAndQualifiers
 | |   |-(
 | |   |-SimpleDeclaration
-| |   | |-const
-| |   | |-char
-| |   | `-SimpleDeclarator
-| |   |   `-*
-| |   |-,
-| |   |-SimpleDeclaration
-| |   | `-size_t
+| |   | |-long
+| |   | `-double
 | |   `-)
 | `-;
 |-SimpleDeclaration
@@ -1437,34 +1801,14 @@ void test() {
   `-CompoundStatement
     |-{
     |-ExpressionStatement
-    | |-IntegerUserDefinedLiteralExpression
-    | | `-12_i
-    | `-;
-    |-ExpressionStatement
     | |-FloatUserDefinedLiteralExpression
     | | `-1.2_f
     | `-;
     |-ExpressionStatement
-    | |-CharUserDefinedLiteralExpression
-    | | `-'2'_c
-    | `-;
-    |-ExpressionStatement
-    | |-StringUserDefinedLiteralExpression
-    | | `-"12"_s
-    | `-;
-    |-ExpressionStatement
-    | |-IntegerUserDefinedLiteralExpression
-    | | `-12_r
-    | `-;
-    |-ExpressionStatement
     | |-FloatUserDefinedLiteralExpression
     | | `-1.2_r
     | `-;
     |-ExpressionStatement
-    | |-IntegerUserDefinedLiteralExpression
-    | | `-12_t
-    | `-;
-    |-ExpressionStatement
     | |-FloatUserDefinedLiteralExpression
     | | `-1.2_t
     | `-;
@@ -2299,15 +2643,11 @@ void test(int a) {
 )txt"));
 }
 
-TEST_P(SyntaxTreeTest, NestedBinaryOperator) {
+TEST_P(SyntaxTreeTest, NestedBinaryOperatorWithParenthesis) {
   EXPECT_TRUE(treeDumpEqual(
       R"cpp(
-void test(int a, int b) {
+void test() {
   (1 + 2) * (4 / 2);
-  a + b + 42;
-  a = b = 42;
-  a + b * 4 + 2;
-  a % 2 + b * 42;
 }
 )cpp",
       R"txt(
@@ -2318,15 +2658,6 @@ void test(int a, int b) {
   | |-test
   | `-ParametersAndQualifiers
   |   |-(
-  |   |-SimpleDeclaration
-  |   | |-int
-  |   | `-SimpleDeclarator
-  |   |   `-a
-  |   |-,
-  |   |-SimpleDeclaration
-  |   | |-int
-  |   | `-SimpleDeclarator
-  |   |   `-b
   |   `-)
   `-CompoundStatement
     |-{
@@ -2352,6 +2683,38 @@ void test(int a, int b) {
     | |   |   `-2
     | |   `-)
     | `-;
+    `-}
+)txt"));
+}
+
+TEST_P(SyntaxTreeTest, NestedBinaryOperatorWithAssociativity) {
+  EXPECT_TRUE(treeDumpEqual(
+      R"cpp(
+void test(int a, int b) {
+  a + b + 42;
+  a = b = 42;
+}
+)cpp",
+      R"txt(
+*: TranslationUnit
+`-SimpleDeclaration
+  |-void
+  |-SimpleDeclarator
+  | |-test
+  | `-ParametersAndQualifiers
+  |   |-(
+  |   |-SimpleDeclaration
+  |   | |-int
+  |   | `-SimpleDeclarator
+  |   |   `-a
+  |   |-,
+  |   |-SimpleDeclaration
+  |   | |-int
+  |   | `-SimpleDeclarator
+  |   |   `-b
+  |   `-)
+  `-CompoundStatement
+    |-{
     |-ExpressionStatement
     | |-BinaryOperatorExpression
     | | |-BinaryOperatorExpression
@@ -2380,47 +2743,66 @@ void test(int a, int b) {
     | |   `-IntegerLiteralExpression
     | |     `-42
     | `-;
-    |-ExpressionStatement
-    | |-BinaryOperatorExpression
-    | | |-BinaryOperatorExpression
-    | | | |-IdExpression
-    | | | | `-UnqualifiedId
-    | | | |   `-a
-    | | | |-+
-    | | | `-BinaryOperatorExpression
-    | | |   |-IdExpression
-    | | |   | `-UnqualifiedId
-    | | |   |   `-b
-    | | |   |-*
-    | | |   `-IntegerLiteralExpression
-    | | |     `-4
-    | | |-+
-    | | `-IntegerLiteralExpression
-    | |   `-2
+    `-}
+)txt"));
+}
+
+TEST_P(SyntaxTreeTest, NestedBinaryOperatorWithPrecedence) {
+  EXPECT_TRUE(treeDumpEqual(
+      R"cpp(
+void test() {
+  1 + 2 * 3 + 4;
+  1 % 2 + 3 * 4;
+}
+)cpp",
+      R"txt(
+*: TranslationUnit
+`-SimpleDeclaration
+  |-void
+  |-SimpleDeclarator
+  | |-test
+  | `-ParametersAndQualifiers
+  |   |-(
+  |   `-)
+  `-CompoundStatement
+    |-{
+    |-ExpressionStatement
+    | |-BinaryOperatorExpression
+    | | |-BinaryOperatorExpression
+    | | | |-IntegerLiteralExpression
+    | | | | `-1
+    | | | |-+
+    | | | `-BinaryOperatorExpression
+    | | |   |-IntegerLiteralExpression
+    | | |   | `-2
+    | | |   |-*
+    | | |   `-IntegerLiteralExpression
+    | | |     `-3
+    | | |-+
+    | | `-IntegerLiteralExpression
+    | |   `-4
     | `-;
     |-ExpressionStatement
     | |-BinaryOperatorExpression
     | | |-BinaryOperatorExpression
-    | | | |-IdExpression
-    | | | | `-UnqualifiedId
-    | | | |   `-a
+    | | | |-IntegerLiteralExpression
+    | | | | `-1
     | | | |-%
     | | | `-IntegerLiteralExpression
     | | |   `-2
     | | |-+
     | | `-BinaryOperatorExpression
-    | |   |-IdExpression
-    | |   | `-UnqualifiedId
-    | |   |   `-b
+    | |   |-IntegerLiteralExpression
+    | |   | `-3
     | |   |-*
     | |   `-IntegerLiteralExpression
-    | |     `-42
+    | |     `-4
     | `-;
     `-}
 )txt"));
 }
 
-TEST_P(SyntaxTreeTest, UserDefinedBinaryOperator) {
+TEST_P(SyntaxTreeTest, UserDefinedAssignmentOperator) {
   if (!GetParam().isCXX()) {
     return;
   }
@@ -2428,21 +2810,9 @@ TEST_P(SyntaxTreeTest, UserDefinedBinaryOperator) {
       R"cpp(
 struct X {
   X& operator=(const X&);
-  friend X operator+(X, const X&);
-  friend bool operator<(const X&, const X&);
-  friend X operator<<(X&, const X&);
-  X operator,(X&);
-  X operator->*(int);
-  // TODO: Unbox operators in syntax tree.
-  // Represent operators by `+` instead of `IdExpression-UnqualifiedId-+`
 };
-void test(X x, X y, X* xp, int X::* pmi) {
+void test(X x, X y) {
   x = y;
-  x + y;
-  x < y;
-  x << y;
-  x, y;
-  xp->*pmi;
 }
 )cpp",
       R"txt(
@@ -2466,6 +2836,59 @@ void test(X x, X y, X* xp, int X::* pmi) {
 | | |   |   `-&
 | | |   `-)
 | | `-;
+| |-}
+| `-;
+`-SimpleDeclaration
+  |-void
+  |-SimpleDeclarator
+  | |-test
+  | `-ParametersAndQualifiers
+  |   |-(
+  |   |-SimpleDeclaration
+  |   | |-X
+  |   | `-SimpleDeclarator
+  |   |   `-x
+  |   |-,
+  |   |-SimpleDeclaration
+  |   | |-X
+  |   | `-SimpleDeclarator
+  |   |   `-y
+  |   `-)
+  `-CompoundStatement
+    |-{
+    |-ExpressionStatement
+    | |-BinaryOperatorExpression
+    | | |-IdExpression
+    | | | `-UnqualifiedId
+    | | |   `-x
+    | | |-=
+    | | `-IdExpression
+    | |   `-UnqualifiedId
+    | |     `-y
+    | `-;
+    `-}
+)txt"));
+}
+
+TEST_P(SyntaxTreeTest, UserDefinedPlusOperator) {
+  if (!GetParam().isCXX()) {
+    return;
+  }
+  EXPECT_TRUE(treeDumpEqual(
+      R"cpp(
+struct X {
+  friend X operator+(X, const X&);
+};
+void test(X x, X y) {
+  x + y;
+}
+)cpp",
+      R"txt(
+*: TranslationUnit
+|-SimpleDeclaration
+| |-struct
+| |-X
+| |-{
 | |-UnknownDeclaration
 | | `-SimpleDeclaration
 | |   |-friend
@@ -2485,6 +2908,60 @@ void test(X x, X y, X* xp, int X::* pmi) {
 | |   |   |   `-&
 | |   |   `-)
 | |   `-;
+| |-}
+| `-;
+`-SimpleDeclaration
+  |-void
+  |-SimpleDeclarator
+  | |-test
+  | `-ParametersAndQualifiers
+  |   |-(
+  |   |-SimpleDeclaration
+  |   | |-X
+  |   | `-SimpleDeclarator
+  |   |   `-x
+  |   |-,
+  |   |-SimpleDeclaration
+  |   | |-X
+  |   | `-SimpleDeclarator
+  |   |   `-y
+  |   `-)
+  `-CompoundStatement
+    |-{
+    |-ExpressionStatement
+    | |-BinaryOperatorExpression
+    | | |-UnknownExpression
+    | | | `-IdExpression
+    | | |   `-UnqualifiedId
+    | | |     `-x
+    | | |-+
+    | | `-IdExpression
+    | |   `-UnqualifiedId
+    | |     `-y
+    | `-;
+    `-}
+)txt"));
+}
+
+TEST_P(SyntaxTreeTest, UserDefinedLessOperator) {
+  if (!GetParam().isCXX()) {
+    return;
+  }
+  EXPECT_TRUE(treeDumpEqual(
+      R"cpp(
+struct X {
+  friend bool operator<(const X&, const X&);
+};
+void test(X x, X y) {
+  x < y;
+}
+)cpp",
+      R"txt(
+*: TranslationUnit
+|-SimpleDeclaration
+| |-struct
+| |-X
+| |-{
 | |-UnknownDeclaration
 | | `-SimpleDeclaration
 | |   |-friend
@@ -2507,6 +2984,59 @@ void test(X x, X y, X* xp, int X::* pmi) {
 | |   |   |   `-&
 | |   |   `-)
 | |   `-;
+| |-}
+| `-;
+`-SimpleDeclaration
+  |-void
+  |-SimpleDeclarator
+  | |-test
+  | `-ParametersAndQualifiers
+  |   |-(
+  |   |-SimpleDeclaration
+  |   | |-X
+  |   | `-SimpleDeclarator
+  |   |   `-x
+  |   |-,
+  |   |-SimpleDeclaration
+  |   | |-X
+  |   | `-SimpleDeclarator
+  |   |   `-y
+  |   `-)
+  `-CompoundStatement
+    |-{
+    |-ExpressionStatement
+    | |-BinaryOperatorExpression
+    | | |-IdExpression
+    | | | `-UnqualifiedId
+    | | |   `-x
+    | | |-<
+    | | `-IdExpression
+    | |   `-UnqualifiedId
+    | |     `-y
+    | `-;
+    `-}
+)txt"));
+}
+
+TEST_P(SyntaxTreeTest, UserDefinedShiftOperator) {
+  if (!GetParam().isCXX()) {
+    return;
+  }
+  EXPECT_TRUE(treeDumpEqual(
+      R"cpp(
+struct X {
+  friend X operator<<(X&, const X&);
+};
+void test(X x, X y) {
+  x << y;
+}
+)cpp",
+      R"txt(
+*: TranslationUnit
+|-SimpleDeclaration
+| |-struct
+| |-X
+| |-{
 | |-UnknownDeclaration
 | | `-SimpleDeclaration
 | |   |-friend
@@ -2528,6 +3058,59 @@ void test(X x, X y, X* xp, int X::* pmi) {
 | |   |   |   `-&
 | |   |   `-)
 | |   `-;
+| |-}
+| `-;
+`-SimpleDeclaration
+  |-void
+  |-SimpleDeclarator
+  | |-test
+  | `-ParametersAndQualifiers
+  |   |-(
+  |   |-SimpleDeclaration
+  |   | |-X
+  |   | `-SimpleDeclarator
+  |   |   `-x
+  |   |-,
+  |   |-SimpleDeclaration
+  |   | |-X
+  |   | `-SimpleDeclarator
+  |   |   `-y
+  |   `-)
+  `-CompoundStatement
+    |-{
+    |-ExpressionStatement
+    | |-BinaryOperatorExpression
+    | | |-IdExpression
+    | | | `-UnqualifiedId
+    | | |   `-x
+    | | |-<<
+    | | `-IdExpression
+    | |   `-UnqualifiedId
+    | |     `-y
+    | `-;
+    `-}
+)txt"));
+}
+
+TEST_P(SyntaxTreeTest, UserDefinedCommaOperator) {
+  if (!GetParam().isCXX()) {
+    return;
+  }
+  EXPECT_TRUE(treeDumpEqual(
+      R"cpp(
+struct X {
+  X operator,(X&);
+};
+void test(X x, X y) {
+  x, y;
+}
+)cpp",
+      R"txt(
+*: TranslationUnit
+|-SimpleDeclaration
+| |-struct
+| |-X
+| |-{
 | |-SimpleDeclaration
 | | |-X
 | | |-SimpleDeclarator
@@ -2541,6 +3124,59 @@ void test(X x, X y, X* xp, int X::* pmi) {
 | | |   |   `-&
 | | |   `-)
 | | `-;
+| |-}
+| `-;
+`-SimpleDeclaration
+  |-void
+  |-SimpleDeclarator
+  | |-test
+  | `-ParametersAndQualifiers
+  |   |-(
+  |   |-SimpleDeclaration
+  |   | |-X
+  |   | `-SimpleDeclarator
+  |   |   `-x
+  |   |-,
+  |   |-SimpleDeclaration
+  |   | |-X
+  |   | `-SimpleDeclarator
+  |   |   `-y
+  |   `-)
+  `-CompoundStatement
+    |-{
+    |-ExpressionStatement
+    | |-BinaryOperatorExpression
+    | | |-IdExpression
+    | | | `-UnqualifiedId
+    | | |   `-x
+    | | |-,
+    | | `-IdExpression
+    | |   `-UnqualifiedId
+    | |     `-y
+    | `-;
+    `-}
+)txt"));
+}
+
+TEST_P(SyntaxTreeTest, UserDefinedArrowPointerOperator) {
+  if (!GetParam().isCXX()) {
+    return;
+  }
+  EXPECT_TRUE(treeDumpEqual(
+      R"cpp(
+struct X {
+  X operator->*(int);
+};
+void test(X* xp, int X::* pmi) {
+  xp->*pmi;
+}
+)cpp",
+      R"txt(
+*: TranslationUnit
+|-SimpleDeclaration
+| |-struct
+| |-X
+| |-{
 | |-SimpleDeclaration
 | | |-X
 | | |-SimpleDeclarator
@@ -2563,16 +3199,6 @@ void test(X x, X y, X* xp, int X::* pmi) {
   |   |-SimpleDeclaration
   |   | |-X
   |   | `-SimpleDeclarator
-  |   |   `-x
-  |   |-,
-  |   |-SimpleDeclaration
-  |   | |-X
-  |   | `-SimpleDeclarator
-  |   |   `-y
-  |   |-,
-  |   |-SimpleDeclaration
-  |   | |-X
-  |   | `-SimpleDeclarator
   |   |   |-*
   |   |   `-xp
   |   |-,
@@ -2591,57 +3217,6 @@ void test(X x, X y, X* xp, int X::* pmi) {
     | |-BinaryOperatorExpression
     | | |-IdExpression
     | | | `-UnqualifiedId
-    | | |   `-x
-    | | |-=
-    | | `-IdExpression
-    | |   `-UnqualifiedId
-    | |     `-y
-    | `-;
-    |-ExpressionStatement
-    | |-BinaryOperatorExpression
-    | | |-UnknownExpression
-    | | | `-IdExpression
-    | | |   `-UnqualifiedId
-    | | |     `-x
-    | | |-+
-    | | `-IdExpression
-    | |   `-UnqualifiedId
-    | |     `-y
-    | `-;
-    |-ExpressionStatement
-    | |-BinaryOperatorExpression
-    | | |-IdExpression
-    | | | `-UnqualifiedId
-    | | |   `-x
-    | | |-<
-    | | `-IdExpression
-    | |   `-UnqualifiedId
-    | |     `-y
-    | `-;
-    |-ExpressionStatement
-    | |-BinaryOperatorExpression
-    | | |-IdExpression
-    | | | `-UnqualifiedId
-    | | |   `-x
-    | | |-<<
-    | | `-IdExpression
-    | |   `-UnqualifiedId
-    | |     `-y
-    | `-;
-    |-ExpressionStatement
-    | |-BinaryOperatorExpression
-    | | |-IdExpression
-    | | | `-UnqualifiedId
-    | | |   `-x
-    | | |-,
-    | | `-IdExpression
-    | |   `-UnqualifiedId
-    | |     `-y
-    | `-;
-    |-ExpressionStatement
-    | |-BinaryOperatorExpression
-    | | |-IdExpression
-    | | | `-UnqualifiedId
     | | |   `-xp
     | | |-->*
     | | `-IdExpression
@@ -2652,7 +3227,7 @@ void test(X x, X y, X* xp, int X::* pmi) {
 )txt"));
 }
 
-TEST_P(SyntaxTreeTest, UserDefinedUnaryPrefixOperator) {
+TEST_P(SyntaxTreeTest, UserDefinedPrefixIncrOperator) {
   if (!GetParam().isCXX()) {
     return;
   }
@@ -2660,13 +3235,9 @@ TEST_P(SyntaxTreeTest, UserDefinedUnaryPrefixOperator) {
       R"cpp(
 struct X {
   X operator++();
-  bool operator!();
-  X* operator&();
 };
 void test(X x) {
   ++x;
-  !x;
-  &x;
 }
 )cpp",
       R"txt(
@@ -2684,6 +3255,51 @@ void test(X x) {
 | | |   |-(
 | | |   `-)
 | | `-;
+| |-}
+| `-;
+`-SimpleDeclaration
+  |-void
+  |-SimpleDeclarator
+  | |-test
+  | `-ParametersAndQualifiers
+  |   |-(
+  |   |-SimpleDeclaration
+  |   | |-X
+  |   | `-SimpleDeclarator
+  |   |   `-x
+  |   `-)
+  `-CompoundStatement
+    |-{
+    |-ExpressionStatement
+    | |-PrefixUnaryOperatorExpression
+    | | |-++
+    | | `-IdExpression
+    | |   `-UnqualifiedId
+    | |     `-x
+    | `-;
+    `-}
+)txt"));
+}
+
+TEST_P(SyntaxTreeTest, UserDefinedExclamOperator) {
+  if (!GetParam().isCXX()) {
+    return;
+  }
+  EXPECT_TRUE(treeDumpEqual(
+      R"cpp(
+struct X {
+  bool operator!();
+};
+void test(X x) {
+  !x;
+}
+)cpp",
+      R"txt(
+*: TranslationUnit
+|-SimpleDeclaration
+| |-struct
+| |-X
+| |-{
 | |-SimpleDeclaration
 | | |-bool
 | | |-SimpleDeclarator
@@ -2693,6 +3309,51 @@ void test(X x) {
 | | |   |-(
 | | |   `-)
 | | `-;
+| |-}
+| `-;
+`-SimpleDeclaration
+  |-void
+  |-SimpleDeclarator
+  | |-test
+  | `-ParametersAndQualifiers
+  |   |-(
+  |   |-SimpleDeclaration
+  |   | |-X
+  |   | `-SimpleDeclarator
+  |   |   `-x
+  |   `-)
+  `-CompoundStatement
+    |-{
+    |-ExpressionStatement
+    | |-PrefixUnaryOperatorExpression
+    | | |-!
+    | | `-IdExpression
+    | |   `-UnqualifiedId
+    | |     `-x
+    | `-;
+    `-}
+)txt"));
+}
+
+TEST_P(SyntaxTreeTest, UserDefinedReferenceOperator) {
+  if (!GetParam().isCXX()) {
+    return;
+  }
+  EXPECT_TRUE(treeDumpEqual(
+      R"cpp(
+struct X {
+  X* operator&();
+};
+void test(X x) {
+  &x;
+}
+)cpp",
+      R"txt(
+*: TranslationUnit
+|-SimpleDeclaration
+| |-struct
+| |-X
+| |-{
 | |-SimpleDeclaration
 | | |-X
 | | |-SimpleDeclarator
@@ -2720,20 +3381,6 @@ void test(X x) {
     |-{
     |-ExpressionStatement
     | |-PrefixUnaryOperatorExpression
-    | | |-++
-    | | `-IdExpression
-    | |   `-UnqualifiedId
-    | |     `-x
-    | `-;
-    |-ExpressionStatement
-    | |-PrefixUnaryOperatorExpression
-    | | |-!
-    | | `-IdExpression
-    | |   `-UnqualifiedId
-    | |     `-x
-    | `-;
-    |-ExpressionStatement
-    | |-PrefixUnaryOperatorExpression
     | | |-&
     | | `-IdExpression
     | |   `-UnqualifiedId


        


More information about the cfe-commits mailing list