1 //===-- ExpandDeducedTypeTests.cpp ------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "TweakTesting.h"
10 #include "gmock/gmock.h"
11 #include "gtest/gtest.h"
13 using ::testing::StartsWith
;
19 TWEAK_TEST(ExpandDeducedType
);
21 TEST_F(ExpandDeducedTypeTest
, Test
) {
29 inline namespace inl_ns {
36 EXPECT_AVAILABLE("^a^u^t^o^ i = 0;");
37 EXPECT_UNAVAILABLE("auto ^i^ ^=^ ^0^;^");
39 // check primitive type
40 EXPECT_EQ(apply("[[auto]] i = 0;"), "int i = 0;");
41 EXPECT_EQ(apply("au^to i = 0;"), "int i = 0;");
42 // check classes and namespaces
43 EXPECT_EQ(apply("^auto C = ns::Class::Nested();"),
44 "ns::Class::Nested C = ns::Class::Nested();");
45 // check that namespaces are shortened
46 EXPECT_EQ(apply("namespace ns { void f() { ^auto C = Class(); } }"),
47 "namespace ns { void f() { Class C = Class(); } }");
48 // undefined functions should not be replaced
49 EXPECT_THAT(apply("au^to x = doesnt_exist(); // error-ok"),
50 StartsWith("fail: Could not deduce type for 'auto' type"));
51 // function pointers should not be replaced
52 EXPECT_THAT(apply("au^to x = &ns::Func;"),
53 StartsWith("fail: Could not expand type"));
54 // function references should not be replaced
55 EXPECT_THAT(apply("au^to &x = ns::Func;"),
56 StartsWith("fail: Could not expand type"));
57 // lambda types are not replaced
58 EXPECT_UNAVAILABLE("au^to x = []{};");
60 EXPECT_EQ(apply("au^to x = inl_ns::Visible();"),
61 "inl_ns::Visible x = inl_ns::Visible();");
63 EXPECT_EQ(apply("namespace x { void y() { struct S{}; ^auto z = S(); } }"),
64 "namespace x { void y() { struct S{}; S z = S(); } }");
66 EXPECT_EQ(apply(R
"cpp(au^to x = "test
";)cpp"),
67 R
"cpp(const char * x = "test
";)cpp");
68 // pointers to an array are not replaced
69 EXPECT_THAT(apply(R
"cpp(au^to s = &"foobar
";)cpp"),
70 StartsWith("fail: Could not expand type"));
72 EXPECT_EQ(apply("ns::Class * foo() { au^to c = foo(); }"),
73 "ns::Class * foo() { ns::Class * c = foo(); }");
75 apply("void ns::Func() { au^to x = new ns::Class::Nested{}; }"),
76 "void ns::Func() { ns::Class::Nested * x = new ns::Class::Nested{}; }");
78 EXPECT_EQ(apply("dec^ltype(auto) x = 10;"), "int x = 10;");
79 EXPECT_EQ(apply("decltype(au^to) x = 10;"), "int x = 10;");
80 // references to array types are not replaced
81 EXPECT_THAT(apply(R
"cpp(decl^type(auto) s = "foobar
"; // error-ok)cpp"),
82 StartsWith("fail: Could not expand type"));
83 // array types are not replaced
84 EXPECT_THAT(apply("int arr[10]; decl^type(auto) foobar = arr; // error-ok"),
85 StartsWith("fail: Could not expand type"));
86 // pointers to an array are not replaced
87 EXPECT_THAT(apply(R
"cpp(decl^type(auto) s = &"foobar
";)cpp"),
88 StartsWith("fail: Could not expand type"));
89 // expanding types in structured bindings is syntactically invalid.
90 EXPECT_UNAVAILABLE("const ^auto &[x,y] = (int[]){1,2};");
92 // unknown types in a template should not be replaced
93 EXPECT_THAT(apply("template <typename T> void x() { ^auto y = T::z(); }"),
94 StartsWith("fail: Could not deduce type for 'auto' type"));
96 // check primitive type
97 EXPECT_EQ(apply("decl^type(0) i;"), "int i;");
98 // function should not be replaced
99 EXPECT_THAT(apply("void f(); decl^type(f) g;"),
100 StartsWith("fail: Could not expand type"));
101 // check return type in function proto
102 EXPECT_EQ(apply("decl^type(0) f();"), "int f();");
103 // check trailing return type
104 EXPECT_EQ(apply("auto f() -> decl^type(0) { return 0; }"),
105 "auto f() -> int { return 0; }");
106 // check function parameter type
107 EXPECT_EQ(apply("void f(decl^type(0));"), "void f(int);");
108 // check template parameter type
109 EXPECT_EQ(apply("template <decl^type(0)> struct Foobar {};"),
110 "template <int> struct Foobar {};");
111 // check default template argument
112 EXPECT_EQ(apply("template <class = decl^type(0)> class Foo {};"),
113 "template <class = int> class Foo {};");
114 // check template argument
115 EXPECT_EQ(apply("template <class> class Bar {}; Bar<decl^type(0)> b;"),
116 "template <class> class Bar {}; Bar<int> b;");
117 // dependent types are not replaced
118 EXPECT_THAT(apply("template <class T> struct Foobar { decl^type(T{}) t; };"),
119 StartsWith("fail: Could not expand a dependent type"));
120 // references to array types are not replaced
121 EXPECT_THAT(apply(R
"cpp(decl^type("foobar
") s; // error-ok)cpp"),
122 StartsWith("fail: Could not expand type"));
123 // array types are not replaced
124 EXPECT_THAT(apply("int arr[10]; decl^type(arr) foobar;"),
125 StartsWith("fail: Could not expand type"));
126 // pointers to an array are not replaced
127 EXPECT_THAT(apply(R
"cpp(decl^type(&"foobar
") s;)cpp"),
128 StartsWith("fail: Could not expand type"));
130 ExtraArgs
.push_back("-std=c++20");
131 EXPECT_UNAVAILABLE("template <au^to X> class Y;");
133 EXPECT_THAT(apply("auto X = [](^auto){};"),
134 StartsWith("fail: Could not deduce"));
135 EXPECT_EQ(apply("auto X = [](^auto){return 0;}; int Y = X(42);"),
136 "auto X = [](int){return 0;}; int Y = X(42);");
137 EXPECT_THAT(apply("auto X = [](^auto){return 0;}; int Y = X(42) + X('c');"),
138 StartsWith("fail: Could not deduce"));
139 // FIXME: should work on constrained auto params, once SourceRange is fixed.
140 EXPECT_UNAVAILABLE("template<class> concept C = true;"
141 "auto X = [](C ^auto *){return 0;};");
143 // lambda should not be replaced
144 EXPECT_UNAVAILABLE("auto f = [](){}; decl^type(f) g;");
145 EXPECT_UNAVAILABLE("decl^type([]{}) f;");
149 } // namespace clangd