blob: d8b303d77bb9643de67de960071b50ef211fbf73 [file] [log] [blame]
Haojian Wu10d95c52018-01-17 14:29:25 +00001//=== unittests/Sema/CodeCompleteTest.cpp - Code Complete tests ==============//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Haojian Wu10d95c52018-01-17 14:29:25 +00006//
7//===----------------------------------------------------------------------===//
8
9#include "clang/Frontend/CompilerInstance.h"
10#include "clang/Frontend/FrontendActions.h"
11#include "clang/Lex/Preprocessor.h"
12#include "clang/Parse/ParseAST.h"
13#include "clang/Sema/Sema.h"
14#include "clang/Sema/SemaDiagnostic.h"
15#include "clang/Tooling/Tooling.h"
Ilya Biryukov6fae38e2019-04-25 10:08:31 +000016#include "llvm/Testing/Support/Annotations.h"
Haojian Wu10d95c52018-01-17 14:29:25 +000017#include "gmock/gmock.h"
Ilya Biryukov4974d75d2018-12-13 16:06:11 +000018#include "gtest/gtest.h"
19#include <cstddef>
20#include <string>
Haojian Wu10d95c52018-01-17 14:29:25 +000021
22namespace {
23
24using namespace clang;
25using namespace clang::tooling;
Ilya Biryukov4974d75d2018-12-13 16:06:11 +000026using ::testing::Each;
Haojian Wu10d95c52018-01-17 14:29:25 +000027using ::testing::UnorderedElementsAre;
28
29const char TestCCName[] = "test.cc";
Haojian Wu10d95c52018-01-17 14:29:25 +000030
Ilya Biryukov4974d75d2018-12-13 16:06:11 +000031struct CompletionContext {
32 std::vector<std::string> VisitedNamespaces;
33 std::string PreferredType;
Ilya Biryukov1d7ba832018-12-17 16:37:52 +000034 // String representation of std::ptrdiff_t on a given platform. This is a hack
35 // to properly account for different configurations of clang.
36 std::string PtrDiffType;
Ilya Biryukov4974d75d2018-12-13 16:06:11 +000037};
38
39class VisitedContextFinder : public CodeCompleteConsumer {
Haojian Wu10d95c52018-01-17 14:29:25 +000040public:
Ilya Biryukov4974d75d2018-12-13 16:06:11 +000041 VisitedContextFinder(CompletionContext &ResultCtx)
Sam McCall3a753302019-04-18 17:35:55 +000042 : CodeCompleteConsumer(/*CodeCompleteOpts=*/{}), ResultCtx(ResultCtx),
Haojian Wu10d95c52018-01-17 14:29:25 +000043 CCTUInfo(std::make_shared<GlobalCodeCompletionAllocator>()) {}
44
45 void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context,
46 CodeCompletionResult *Results,
47 unsigned NumResults) override {
Ilya Biryukov4974d75d2018-12-13 16:06:11 +000048 ResultCtx.VisitedNamespaces =
49 getVisitedNamespace(Context.getVisitedContexts());
50 ResultCtx.PreferredType = Context.getPreferredType().getAsString();
Ilya Biryukov1d7ba832018-12-17 16:37:52 +000051 ResultCtx.PtrDiffType =
52 S.getASTContext().getPointerDiffType().getAsString();
Haojian Wu10d95c52018-01-17 14:29:25 +000053 }
54
55 CodeCompletionAllocator &getAllocator() override {
56 return CCTUInfo.getAllocator();
57 }
58
59 CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; }
60
Ilya Biryukov4974d75d2018-12-13 16:06:11 +000061private:
62 std::vector<std::string> getVisitedNamespace(
63 CodeCompletionContext::VisitedContextSet VisitedContexts) const {
Haojian Wu10d95c52018-01-17 14:29:25 +000064 std::vector<std::string> NSNames;
65 for (const auto *Context : VisitedContexts)
66 if (const auto *NS = llvm::dyn_cast<NamespaceDecl>(Context))
67 NSNames.push_back(NS->getQualifiedNameAsString());
68 return NSNames;
69 }
70
Ilya Biryukov4974d75d2018-12-13 16:06:11 +000071 CompletionContext &ResultCtx;
Haojian Wu10d95c52018-01-17 14:29:25 +000072 CodeCompletionTUInfo CCTUInfo;
Haojian Wu10d95c52018-01-17 14:29:25 +000073};
74
75class CodeCompleteAction : public SyntaxOnlyAction {
76public:
Ilya Biryukov4974d75d2018-12-13 16:06:11 +000077 CodeCompleteAction(ParsedSourceLocation P, CompletionContext &ResultCtx)
78 : CompletePosition(std::move(P)), ResultCtx(ResultCtx) {}
Haojian Wu10d95c52018-01-17 14:29:25 +000079
80 bool BeginInvocation(CompilerInstance &CI) override {
81 CI.getFrontendOpts().CodeCompletionAt = CompletePosition;
Ilya Biryukov4974d75d2018-12-13 16:06:11 +000082 CI.setCodeCompletionConsumer(new VisitedContextFinder(ResultCtx));
Haojian Wu10d95c52018-01-17 14:29:25 +000083 return true;
84 }
85
86private:
87 // 1-based code complete position <Line, Col>;
88 ParsedSourceLocation CompletePosition;
Ilya Biryukov4974d75d2018-12-13 16:06:11 +000089 CompletionContext &ResultCtx;
Haojian Wu10d95c52018-01-17 14:29:25 +000090};
91
92ParsedSourceLocation offsetToPosition(llvm::StringRef Code, size_t Offset) {
93 Offset = std::min(Code.size(), Offset);
94 StringRef Before = Code.substr(0, Offset);
95 int Lines = Before.count('\n');
96 size_t PrevNL = Before.rfind('\n');
97 size_t StartOfLine = (PrevNL == StringRef::npos) ? 0 : (PrevNL + 1);
98 return {TestCCName, static_cast<unsigned>(Lines + 1),
99 static_cast<unsigned>(Offset - StartOfLine + 1)};
100}
101
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000102CompletionContext runCompletion(StringRef Code, size_t Offset) {
103 CompletionContext ResultCtx;
Dmitri Gribenkob22804b2019-08-30 09:29:34 +0000104 clang::tooling::runToolOnCodeWithArgs(
105 std::make_unique<CodeCompleteAction>(offsetToPosition(Code, Offset),
106 ResultCtx),
107 Code, {"-std=c++11"}, TestCCName);
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000108 return ResultCtx;
109}
110
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000111CompletionContext runCodeCompleteOnCode(StringRef AnnotatedCode) {
Ilya Biryukov6fae38e2019-04-25 10:08:31 +0000112 llvm::Annotations A(AnnotatedCode);
113 return runCompletion(A.code(), A.point());
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000114}
115
Ilya Biryukov1d7ba832018-12-17 16:37:52 +0000116std::vector<std::string>
117collectPreferredTypes(StringRef AnnotatedCode,
118 std::string *PtrDiffType = nullptr) {
Ilya Biryukov6fae38e2019-04-25 10:08:31 +0000119 llvm::Annotations A(AnnotatedCode);
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000120 std::vector<std::string> Types;
Ilya Biryukov6fae38e2019-04-25 10:08:31 +0000121 for (size_t Point : A.points()) {
122 auto Results = runCompletion(A.code(), Point);
Ilya Biryukov1d7ba832018-12-17 16:37:52 +0000123 if (PtrDiffType) {
124 assert(PtrDiffType->empty() || *PtrDiffType == Results.PtrDiffType);
125 *PtrDiffType = Results.PtrDiffType;
126 }
127 Types.push_back(Results.PreferredType);
128 }
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000129 return Types;
Haojian Wu10d95c52018-01-17 14:29:25 +0000130}
131
132TEST(SemaCodeCompleteTest, VisitedNSForValidQualifiedId) {
133 auto VisitedNS = runCodeCompleteOnCode(R"cpp(
134 namespace ns1 {}
135 namespace ns2 {}
136 namespace ns3 {}
137 namespace ns3 { namespace nns3 {} }
138
139 namespace foo {
140 using namespace ns1;
141 namespace ns4 {} // not visited
142 namespace { using namespace ns2; }
143 inline namespace bar { using namespace ns3::nns3; }
144 } // foo
145 namespace ns { foo::^ }
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000146 )cpp")
147 .VisitedNamespaces;
Haojian Wu10d95c52018-01-17 14:29:25 +0000148 EXPECT_THAT(VisitedNS, UnorderedElementsAre("foo", "ns1", "ns2", "ns3::nns3",
149 "foo::(anonymous)"));
150}
151
Eric Liu206740e2019-02-21 11:22:58 +0000152TEST(SemaCodeCompleteTest, VisitedNSForInvalidQualifiedId) {
Haojian Wu10d95c52018-01-17 14:29:25 +0000153 auto VisitedNS = runCodeCompleteOnCode(R"cpp(
Eric Liu206740e2019-02-21 11:22:58 +0000154 namespace na {}
155 namespace ns1 {
156 using namespace na;
157 foo::^
158 }
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000159 )cpp")
160 .VisitedNamespaces;
Eric Liu206740e2019-02-21 11:22:58 +0000161 EXPECT_THAT(VisitedNS, UnorderedElementsAre("ns1", "na"));
Haojian Wu10d95c52018-01-17 14:29:25 +0000162}
163
Eric Liuf5ba09f2018-07-04 10:01:18 +0000164TEST(SemaCodeCompleteTest, VisitedNSWithoutQualifier) {
165 auto VisitedNS = runCodeCompleteOnCode(R"cpp(
166 namespace n1 {
167 namespace n2 {
168 void f(^) {}
169 }
170 }
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000171 )cpp")
172 .VisitedNamespaces;
Eric Liuf5ba09f2018-07-04 10:01:18 +0000173 EXPECT_THAT(VisitedNS, UnorderedElementsAre("n1", "n1::n2"));
174}
175
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000176TEST(PreferredTypeTest, BinaryExpr) {
177 // Check various operations for arithmetic types.
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000178 StringRef Code = R"cpp(
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000179 void test(int x) {
180 x = ^10;
181 x += ^10; x -= ^10; x *= ^10; x /= ^10; x %= ^10;
182 x + ^10; x - ^10; x * ^10; x / ^10; x % ^10;
David Green0250e292018-12-13 17:20:06 +0000183 })cpp";
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000184 EXPECT_THAT(collectPreferredTypes(Code), Each("int"));
185
186 Code = R"cpp(
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000187 void test(float x) {
188 x = ^10;
189 x += ^10; x -= ^10; x *= ^10; x /= ^10; x %= ^10;
190 x + ^10; x - ^10; x * ^10; x / ^10; x % ^10;
David Green0250e292018-12-13 17:20:06 +0000191 })cpp";
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000192 EXPECT_THAT(collectPreferredTypes(Code), Each("float"));
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000193
194 // Pointer types.
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000195 Code = R"cpp(
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000196 void test(int *ptr) {
197 ptr - ^ptr;
198 ptr = ^ptr;
David Green0250e292018-12-13 17:20:06 +0000199 })cpp";
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000200 EXPECT_THAT(collectPreferredTypes(Code), Each("int *"));
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000201
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000202 Code = R"cpp(
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000203 void test(int *ptr) {
204 ptr + ^10;
205 ptr += ^10;
206 ptr -= ^10;
David Green0250e292018-12-13 17:20:06 +0000207 })cpp";
Ilya Biryukov1d7ba832018-12-17 16:37:52 +0000208 {
209 std::string PtrDiff;
210 auto Types = collectPreferredTypes(Code, &PtrDiff);
211 EXPECT_THAT(Types, Each(PtrDiff));
212 }
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000213
214 // Comparison operators.
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000215 Code = R"cpp(
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000216 void test(int i) {
217 i <= ^1; i < ^1; i >= ^1; i > ^1; i == ^1; i != ^1;
218 }
David Green0250e292018-12-13 17:20:06 +0000219 )cpp";
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000220 EXPECT_THAT(collectPreferredTypes(Code), Each("int"));
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000221
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000222 Code = R"cpp(
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000223 void test(int *ptr) {
224 ptr <= ^ptr; ptr < ^ptr; ptr >= ^ptr; ptr > ^ptr;
225 ptr == ^ptr; ptr != ^ptr;
226 }
David Green0250e292018-12-13 17:20:06 +0000227 )cpp";
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000228 EXPECT_THAT(collectPreferredTypes(Code), Each("int *"));
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000229
230 // Relational operations.
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000231 Code = R"cpp(
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000232 void test(int i, int *ptr) {
233 i && ^1; i || ^1;
234 ptr && ^1; ptr || ^1;
235 }
David Green0250e292018-12-13 17:20:06 +0000236 )cpp";
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000237 EXPECT_THAT(collectPreferredTypes(Code), Each("_Bool"));
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000238
239 // Bitwise operations.
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000240 Code = R"cpp(
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000241 void test(long long ll) {
242 ll | ^1; ll & ^1;
243 }
David Green0250e292018-12-13 17:20:06 +0000244 )cpp";
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000245 EXPECT_THAT(collectPreferredTypes(Code), Each("long long"));
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000246
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000247 Code = R"cpp(
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000248 enum A {};
249 void test(A a) {
250 a | ^1; a & ^1;
251 }
David Green0250e292018-12-13 17:20:06 +0000252 )cpp";
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000253 EXPECT_THAT(collectPreferredTypes(Code), Each("enum A"));
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000254
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000255 Code = R"cpp(
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000256 enum class A {};
257 void test(A a) {
258 // This is technically illegal with the 'enum class' without overloaded
259 // operators, but we pretend it's fine.
260 a | ^a; a & ^a;
261 }
David Green0250e292018-12-13 17:20:06 +0000262 )cpp";
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000263 EXPECT_THAT(collectPreferredTypes(Code), Each("enum A"));
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000264
265 // Binary shifts.
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000266 Code = R"cpp(
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000267 void test(int i, long long ll) {
268 i << ^1; ll << ^1;
269 i <<= ^1; i <<= ^1;
270 i >> ^1; ll >> ^1;
271 i >>= ^1; i >>= ^1;
272 }
David Green0250e292018-12-13 17:20:06 +0000273 )cpp";
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000274 EXPECT_THAT(collectPreferredTypes(Code), Each("int"));
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000275
276 // Comma does not provide any useful information.
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000277 Code = R"cpp(
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000278 class Cls {};
279 void test(int i, int* ptr, Cls x) {
280 (i, ^i);
281 (ptr, ^ptr);
282 (x, ^x);
283 }
David Green0250e292018-12-13 17:20:06 +0000284 )cpp";
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000285 EXPECT_THAT(collectPreferredTypes(Code), Each("NULL TYPE"));
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000286
287 // User-defined types do not take operator overloading into account.
288 // However, they provide heuristics for some common cases.
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000289 Code = R"cpp(
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000290 class Cls {};
291 void test(Cls c) {
292 // we assume arithmetic and comparions ops take the same type.
293 c + ^c; c - ^c; c * ^c; c / ^c; c % ^c;
294 c == ^c; c != ^c; c < ^c; c <= ^c; c > ^c; c >= ^c;
295 // same for the assignments.
296 c = ^c; c += ^c; c -= ^c; c *= ^c; c /= ^c; c %= ^c;
297 }
David Green0250e292018-12-13 17:20:06 +0000298 )cpp";
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000299 EXPECT_THAT(collectPreferredTypes(Code), Each("class Cls"));
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000300
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000301 Code = R"cpp(
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000302 class Cls {};
303 void test(Cls c) {
304 // we assume relational ops operate on bools.
305 c && ^c; c || ^c;
306 }
David Green0250e292018-12-13 17:20:06 +0000307 )cpp";
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000308 EXPECT_THAT(collectPreferredTypes(Code), Each("_Bool"));
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000309
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000310 Code = R"cpp(
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000311 class Cls {};
312 void test(Cls c) {
313 // we make no assumptions about the following operators, since they are
314 // often overloaded with a non-standard meaning.
315 c << ^c; c >> ^c; c | ^c; c & ^c;
316 c <<= ^c; c >>= ^c; c |= ^c; c &= ^c;
317 }
David Green0250e292018-12-13 17:20:06 +0000318 )cpp";
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000319 EXPECT_THAT(collectPreferredTypes(Code), Each("NULL TYPE"));
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000320}
321
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000322TEST(PreferredTypeTest, Members) {
323 StringRef Code = R"cpp(
324 struct vector {
325 int *begin();
326 vector clone();
327 };
328
329 void test(int *a) {
330 a = ^vector().^clone().^begin();
331 }
332 )cpp";
333 EXPECT_THAT(collectPreferredTypes(Code), Each("int *"));
334}
335
336TEST(PreferredTypeTest, Conditions) {
337 StringRef Code = R"cpp(
338 struct vector {
339 bool empty();
340 };
341
342 void test() {
343 if (^vector().^empty()) {}
344 while (^vector().^empty()) {}
345 for (; ^vector().^empty();) {}
346 }
347 )cpp";
348 EXPECT_THAT(collectPreferredTypes(Code), Each("_Bool"));
349}
350
351TEST(PreferredTypeTest, InitAndAssignment) {
352 StringRef Code = R"cpp(
353 struct vector {
354 int* begin();
355 };
356
357 void test() {
358 const int* x = ^vector().^begin();
359 x = ^vector().^begin();
360
361 if (const int* y = ^vector().^begin()) {}
362 }
363 )cpp";
364 EXPECT_THAT(collectPreferredTypes(Code), Each("const int *"));
365}
366
367TEST(PreferredTypeTest, UnaryExprs) {
368 StringRef Code = R"cpp(
369 void test(long long a) {
370 a = +^a;
371 a = -^a
372 a = ++^a;
373 a = --^a;
374 }
375 )cpp";
376 EXPECT_THAT(collectPreferredTypes(Code), Each("long long"));
377
378 Code = R"cpp(
379 void test(int a, int *ptr) {
380 !^a;
381 !^ptr;
382 !!!^a;
383
384 a = !^a;
385 a = !^ptr;
386 a = !!!^a;
387 }
388 )cpp";
389 EXPECT_THAT(collectPreferredTypes(Code), Each("_Bool"));
390
391 Code = R"cpp(
392 void test(int a) {
393 const int* x = &^a;
394 }
395 )cpp";
396 EXPECT_THAT(collectPreferredTypes(Code), Each("const int"));
397
398 Code = R"cpp(
399 void test(int *a) {
400 int x = *^a;
401 int &r = *^a;
402 }
403 )cpp";
404 EXPECT_THAT(collectPreferredTypes(Code), Each("int *"));
405
406 Code = R"cpp(
407 void test(int a) {
408 *^a;
409 &^a;
410 }
411
412 )cpp";
413}
414
415TEST(PreferredTypeTest, ParenExpr) {
416 StringRef Code = R"cpp(
417 const int *i = ^(^(^(^10)));
418 )cpp";
419 EXPECT_THAT(collectPreferredTypes(Code), Each("const int *"));
420}
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000421
422TEST(PreferredTypeTest, FunctionArguments) {
423 StringRef Code = R"cpp(
424 void foo(const int*);
425
426 void bar(const int*);
427 void bar(const int*, int b);
428
429 struct vector {
430 const int *data();
431 };
432 void test() {
433 foo(^(^(^(^vec^tor^().^da^ta^()))));
434 bar(^(^(^(^vec^tor^().^da^ta^()))));
435 }
436 )cpp";
437 EXPECT_THAT(collectPreferredTypes(Code), Each("const int *"));
438
439 Code = R"cpp(
440 void bar(int, volatile double *);
441 void bar(int, volatile double *, int, int);
442
443 struct vector {
444 double *data();
445 };
446
447 struct class_members {
448 void bar(int, volatile double *);
449 void bar(int, volatile double *, int, int);
450 };
451 void test() {
452 bar(10, ^(^(^(^vec^tor^().^da^ta^()))));
453 class_members().bar(10, ^(^(^(^vec^tor^().^da^ta^()))));
454 }
455 )cpp";
456 EXPECT_THAT(collectPreferredTypes(Code), Each("volatile double *"));
Ilya Biryukovb1296fa2019-05-28 15:21:03 +0000457
458 Code = R"cpp(
459 namespace ns {
460 struct vector {
461 };
462 }
463 void accepts_vector(ns::vector);
464
465 void test() {
466 accepts_vector(^::^ns::^vector());
467 }
468 )cpp";
469 EXPECT_THAT(collectPreferredTypes(Code), Each("ns::vector"));
470
471 Code = R"cpp(
472 template <class T>
473 struct vector { using self = vector; };
474
475 void accepts_vector(vector<int>);
476 int foo(int);
477
478 void test() {
479 accepts_vector(^::^vector<decltype(foo(1))>::^self);
480 }
481 )cpp";
482 EXPECT_THAT(collectPreferredTypes(Code), Each("vector<int>"));
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000483}
Ilya Biryukovf7c8ace42019-12-11 09:38:14 +0100484
485TEST(PreferredTypeTest, NoCrashOnInvalidTypes) {
486 StringRef Code = R"cpp(
487 auto x = decltype(&1)(^);
488 auto y = new decltype(&1)(^);
Haojian Wu6f428e02020-03-27 16:21:36 +0100489 // GNU decimal type extension is not supported in clang.
490 auto z = new _Decimal128(^);
Ilya Biryukovf7c8ace42019-12-11 09:38:14 +0100491 )cpp";
Haojian Wu62dea6e2020-03-26 16:07:50 +0100492 EXPECT_THAT(collectPreferredTypes(Code), Each("NULL TYPE"));
Ilya Biryukovf7c8ace42019-12-11 09:38:14 +0100493}
Haojian Wu6f428e02020-03-27 16:21:36 +0100494
Haojian Wu10d95c52018-01-17 14:29:25 +0000495} // namespace