aboutsummaryrefslogtreecommitdiff
path: root/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/unittests/Tooling/Syntax/BuildTreeTest.cpp')
-rw-r--r--clang/unittests/Tooling/Syntax/BuildTreeTest.cpp395
1 files changed, 384 insertions, 11 deletions
diff --git a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp
index fd858df..2692c1f 100644
--- a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp
+++ b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp
@@ -491,19 +491,20 @@ struct X {
operator int();
};
void test(X x) {
- // TODO: Expose `id-expression` from `MemberExpr`
[[x.operator int()]];
}
)cpp",
{R"txt(
UnknownExpression
-|-UnknownExpression
+|-MemberExpression
| |-IdExpression
| | `-UnqualifiedId
| | `-x
| |-.
-| |-operator
-| `-int
+| `-IdExpression
+| `-UnqualifiedId
+| |-operator
+| `-int
|-(
`-)
)txt"}));
@@ -542,19 +543,20 @@ TEST_P(SyntaxTreeTest, UnqualifiedId_Destructor) {
R"cpp(
struct X { };
void test(X x) {
- // TODO: Expose `id-expression` from `MemberExpr`
[[x.~X()]];
}
)cpp",
{R"txt(
UnknownExpression
-|-UnknownExpression
+|-MemberExpression
| |-IdExpression
| | `-UnqualifiedId
| | `-x
| |-.
-| |-~
-| `-X
+| `-IdExpression
+| `-UnqualifiedId
+| |-~
+| `-X
|-(
`-)
)txt"}));
@@ -568,18 +570,23 @@ TEST_P(SyntaxTreeTest, UnqualifiedId_DecltypeDestructor) {
R"cpp(
struct X { };
void test(X x) {
- // TODO: Expose `id-expression` from `MemberExpr`
+ // FIXME: Make `decltype(x)` a child of `MemberExpression`. It is currently
+ // not because `Expr::getSourceRange()` returns the range of `x.~` for the
+ // `MemberExpr` instead of the expected `x.~decltype(x)`, this is a bug in
+ // clang.
[[x.~decltype(x)()]];
}
)cpp",
{R"txt(
UnknownExpression
-|-UnknownExpression
+|-MemberExpression
| |-IdExpression
| | `-UnqualifiedId
| | `-x
| |-.
-| `-~
+| `-IdExpression
+| `-UnqualifiedId
+| `-~
|-decltype
|-(
|-x
@@ -624,6 +631,9 @@ 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]];
}
@@ -1756,6 +1766,9 @@ 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]];
}
@@ -1961,6 +1974,366 @@ PostfixUnaryOperatorExpression
)txt"}));
}
+TEST_P(SyntaxTreeTest, MemberExpression_SimpleWithDot) {
+ EXPECT_TRUE(treeDumpEqualOnAnnotations(
+ R"cpp(
+struct S {
+ int a;
+};
+void test(struct S s) {
+ [[s.a]];
+}
+)cpp",
+ {R"txt(
+MemberExpression
+|-IdExpression
+| `-UnqualifiedId
+| `-s
+|-.
+`-IdExpression
+ `-UnqualifiedId
+ `-a
+)txt"}));
+}
+
+TEST_P(SyntaxTreeTest, MemberExpression_StaticDataMember) {
+ if (!GetParam().isCXX()) {
+ return;
+ }
+ EXPECT_TRUE(treeDumpEqualOnAnnotations(
+ R"cpp(
+struct S {
+ static int a;
+};
+void test(S s) {
+ [[s.a]];
+}
+)cpp",
+ {R"txt(
+MemberExpression
+|-IdExpression
+| `-UnqualifiedId
+| `-s
+|-.
+`-IdExpression
+ `-UnqualifiedId
+ `-a
+)txt"}));
+}
+
+TEST_P(SyntaxTreeTest, MemberExpression_SimpleWithArrow) {
+ EXPECT_TRUE(treeDumpEqualOnAnnotations(
+ R"cpp(
+struct S {
+ int a;
+};
+void test(struct S* sp) {
+ [[sp->a]];
+}
+)cpp",
+ {R"txt(
+MemberExpression
+|-IdExpression
+| `-UnqualifiedId
+| `-sp
+|-->
+`-IdExpression
+ `-UnqualifiedId
+ `-a
+)txt"}));
+}
+
+TEST_P(SyntaxTreeTest, MemberExpression_Chaining) {
+ EXPECT_TRUE(treeDumpEqualOnAnnotations(
+ R"cpp(
+struct S {
+ struct S* next;
+};
+void test(struct S s){
+ [[s.next->next]];
+}
+)cpp",
+ {R"txt(
+MemberExpression
+|-MemberExpression
+| |-IdExpression
+| | `-UnqualifiedId
+| | `-s
+| |-.
+| `-IdExpression
+| `-UnqualifiedId
+| `-next
+|-->
+`-IdExpression
+ `-UnqualifiedId
+ `-next
+)txt"}));
+}
+
+TEST_P(SyntaxTreeTest, MemberExpression_OperatorFunction) {
+ if (!GetParam().isCXX()) {
+ return;
+ }
+ EXPECT_TRUE(treeDumpEqualOnAnnotations(
+ R"cpp(
+struct S {
+ bool operator!();
+};
+void test(S s) {
+ [[s.operator!()]];
+}
+)cpp",
+ {R"txt(
+UnknownExpression
+|-MemberExpression
+| |-IdExpression
+| | `-UnqualifiedId
+| | `-s
+| |-.
+| `-IdExpression
+| `-UnqualifiedId
+| |-operator
+| `-!
+|-(
+`-)
+)txt"}));
+}
+
+TEST_P(SyntaxTreeTest, MemberExpression_Implicit) {
+ if (!GetParam().isCXX()) {
+ return;
+ }
+ EXPECT_TRUE(treeDumpEqualOnAnnotations(
+ R"cpp(
+struct S {
+ int a;
+ int test(){
+ // FIXME: Remove the `UnknownExpression` wrapping `a`. This
+ // `UnknownExpression` comes from an implicit leaf `CXXThisExpr`.
+ [[a]];
+ }
+};
+)cpp",
+ {R"txt(
+IdExpression
+`-UnqualifiedId
+ `-UnknownExpression
+ `-a
+)txt"}));
+}
+
+TEST_P(SyntaxTreeTest, MemberExpression_VariableTemplate) {
+ if (!GetParam().isCXX14OrLater()) {
+ return;
+ }
+ EXPECT_TRUE(treeDumpEqualOnAnnotations(
+ R"cpp(
+struct S {
+ template<typename T>
+ static constexpr T x = 42;
+};
+// FIXME: `<int>` should be a child of `MemberExpression` and `;` of
+// `ExpressionStatement`. This is a bug in clang, in `getSourceRange` methods.
+void test(S s) [[{
+ s.x<int>;
+}]]
+)cpp",
+ {R"txt(
+CompoundStatement
+|-{
+|-ExpressionStatement
+| `-MemberExpression
+| |-IdExpression
+| | `-UnqualifiedId
+| | `-s
+| |-.
+| `-IdExpression
+| `-UnqualifiedId
+| `-x
+|-<
+|-int
+|->
+|-;
+`-}
+)txt"}));
+}
+
+TEST_P(SyntaxTreeTest, MemberExpression_FunctionTemplate) {
+ if (!GetParam().isCXX()) {
+ return;
+ }
+ EXPECT_TRUE(treeDumpEqualOnAnnotations(
+ R"cpp(
+struct S {
+ template<typename T>
+ T f();
+};
+void test(S* sp){
+ [[sp->f<int>()]];
+}
+)cpp",
+ {R"txt(
+UnknownExpression
+|-MemberExpression
+| |-IdExpression
+| | `-UnqualifiedId
+| | `-sp
+| |-->
+| `-IdExpression
+| `-UnqualifiedId
+| |-f
+| |-<
+| |-int
+| `->
+|-(
+`-)
+)txt"}));
+}
+
+TEST_P(SyntaxTreeTest, MemberExpression_FunctionTemplateWithTemplateKeyword) {
+ if (!GetParam().isCXX()) {
+ return;
+ }
+ EXPECT_TRUE(treeDumpEqualOnAnnotations(
+ R"cpp(
+struct S {
+ template<typename T>
+ T f();
+};
+void test(S s){
+ [[s.template f<int>()]];
+}
+)cpp",
+ {R"txt(
+UnknownExpression
+|-MemberExpression
+| |-IdExpression
+| | `-UnqualifiedId
+| | `-s
+| |-.
+| |-template
+| `-IdExpression
+| `-UnqualifiedId
+| |-f
+| |-<
+| |-int
+| `->
+|-(
+`-)
+)txt"}));
+}
+
+TEST_P(SyntaxTreeTest, MemberExpression_WithQualifier) {
+ if (!GetParam().isCXX()) {
+ return;
+ }
+ EXPECT_TRUE(treeDumpEqualOnAnnotations(
+ R"cpp(
+struct Base {
+ void f();
+};
+struct S : public Base {};
+void test(S s){
+ [[s.Base::f()]];
+ [[s.::S::~S()]];
+}
+)cpp",
+ {R"txt(
+UnknownExpression
+|-MemberExpression
+| |-IdExpression
+| | `-UnqualifiedId
+| | `-s
+| |-.
+| `-IdExpression
+| |-NestedNameSpecifier
+| | |-IdentifierNameSpecifier
+| | | `-Base
+| | `-::
+| `-UnqualifiedId
+| `-f
+|-(
+`-)
+ )txt",
+ R"txt(
+UnknownExpression
+|-MemberExpression
+| |-IdExpression
+| | `-UnqualifiedId
+| | `-s
+| |-.
+| `-IdExpression
+| |-NestedNameSpecifier
+| | |-::
+| | |-IdentifierNameSpecifier
+| | | `-S
+| | `-::
+| `-UnqualifiedId
+| |-~
+| `-S
+|-(
+`-)
+)txt"}));
+}
+
+TEST_P(SyntaxTreeTest, MemberExpression_Complex) {
+ if (!GetParam().isCXX()) {
+ return;
+ }
+ EXPECT_TRUE(treeDumpEqualOnAnnotations(
+ R"cpp(
+template<typename T>
+struct U {
+ template<typename U>
+ U f();
+};
+struct S {
+ U<int> getU();
+};
+void test(S* sp) {
+ // FIXME: The first 'template' keyword is a child of `NestedNameSpecifier`,
+ // but it should be a child of `MemberExpression` according to the grammar.
+ // However one might argue that the 'template' keyword fits better inside
+ // `NestedNameSpecifier` because if we change `U<int>` to `UI` we would like
+ // equally to change the `NameSpecifier` `template U<int>` to just `UI`.
+ [[sp->getU().template U<int>::template f<int>()]];
+}
+)cpp",
+ {R"txt(
+UnknownExpression
+|-MemberExpression
+| |-UnknownExpression
+| | |-MemberExpression
+| | | |-IdExpression
+| | | | `-UnqualifiedId
+| | | | `-sp
+| | | |-->
+| | | `-IdExpression
+| | | `-UnqualifiedId
+| | | `-getU
+| | |-(
+| | `-)
+| |-.
+| `-IdExpression
+| |-NestedNameSpecifier
+| | |-SimpleTemplateNameSpecifier
+| | | |-template
+| | | |-U
+| | | |-<
+| | | |-int
+| | | `->
+| | `-::
+| |-template
+| `-UnqualifiedId
+| |-f
+| |-<
+| |-int
+| `->
+|-(
+`-)
+)txt"}));
+}
+
TEST_P(SyntaxTreeTest, MultipleDeclaratorsGrouping) {
EXPECT_TRUE(treeDumpEqual(
R"cpp(