blob: a6368550986d9ae8dc4d64c75c1da981b76b42e4 [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"
Haojian Wu10d95c52018-01-17 14:29:25 +000016#include "gmock/gmock.h"
Ilya Biryukov4974d75d2018-12-13 16:06:11 +000017#include "gtest/gtest.h"
18#include <cstddef>
19#include <string>
Haojian Wu10d95c52018-01-17 14:29:25 +000020
21namespace {
22
23using namespace clang;
24using namespace clang::tooling;
Ilya Biryukov4974d75d2018-12-13 16:06:11 +000025using ::testing::Each;
Haojian Wu10d95c52018-01-17 14:29:25 +000026using ::testing::UnorderedElementsAre;
27
28const char TestCCName[] = "test.cc";
Haojian Wu10d95c52018-01-17 14:29:25 +000029
Ilya Biryukov4974d75d2018-12-13 16:06:11 +000030struct CompletionContext {
31 std::vector<std::string> VisitedNamespaces;
32 std::string PreferredType;
Ilya Biryukov1d7ba832018-12-17 16:37:52 +000033 // String representation of std::ptrdiff_t on a given platform. This is a hack
34 // to properly account for different configurations of clang.
35 std::string PtrDiffType;
Ilya Biryukov4974d75d2018-12-13 16:06:11 +000036};
37
38class VisitedContextFinder : public CodeCompleteConsumer {
Haojian Wu10d95c52018-01-17 14:29:25 +000039public:
Ilya Biryukov4974d75d2018-12-13 16:06:11 +000040 VisitedContextFinder(CompletionContext &ResultCtx)
Sam McCall3a753302019-04-18 17:35:55 +000041 : CodeCompleteConsumer(/*CodeCompleteOpts=*/{}), ResultCtx(ResultCtx),
Haojian Wu10d95c52018-01-17 14:29:25 +000042 CCTUInfo(std::make_shared<GlobalCodeCompletionAllocator>()) {}
43
44 void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context,
45 CodeCompletionResult *Results,
46 unsigned NumResults) override {
Ilya Biryukov4974d75d2018-12-13 16:06:11 +000047 ResultCtx.VisitedNamespaces =
48 getVisitedNamespace(Context.getVisitedContexts());
49 ResultCtx.PreferredType = Context.getPreferredType().getAsString();
Ilya Biryukov1d7ba832018-12-17 16:37:52 +000050 ResultCtx.PtrDiffType =
51 S.getASTContext().getPointerDiffType().getAsString();
Haojian Wu10d95c52018-01-17 14:29:25 +000052 }
53
54 CodeCompletionAllocator &getAllocator() override {
55 return CCTUInfo.getAllocator();
56 }
57
58 CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; }
59
Ilya Biryukov4974d75d2018-12-13 16:06:11 +000060private:
61 std::vector<std::string> getVisitedNamespace(
62 CodeCompletionContext::VisitedContextSet VisitedContexts) const {
Haojian Wu10d95c52018-01-17 14:29:25 +000063 std::vector<std::string> NSNames;
64 for (const auto *Context : VisitedContexts)
65 if (const auto *NS = llvm::dyn_cast<NamespaceDecl>(Context))
66 NSNames.push_back(NS->getQualifiedNameAsString());
67 return NSNames;
68 }
69
Ilya Biryukov4974d75d2018-12-13 16:06:11 +000070 CompletionContext &ResultCtx;
Haojian Wu10d95c52018-01-17 14:29:25 +000071 CodeCompletionTUInfo CCTUInfo;
Haojian Wu10d95c52018-01-17 14:29:25 +000072};
73
74class CodeCompleteAction : public SyntaxOnlyAction {
75public:
Ilya Biryukov4974d75d2018-12-13 16:06:11 +000076 CodeCompleteAction(ParsedSourceLocation P, CompletionContext &ResultCtx)
77 : CompletePosition(std::move(P)), ResultCtx(ResultCtx) {}
Haojian Wu10d95c52018-01-17 14:29:25 +000078
79 bool BeginInvocation(CompilerInstance &CI) override {
80 CI.getFrontendOpts().CodeCompletionAt = CompletePosition;
Ilya Biryukov4974d75d2018-12-13 16:06:11 +000081 CI.setCodeCompletionConsumer(new VisitedContextFinder(ResultCtx));
Haojian Wu10d95c52018-01-17 14:29:25 +000082 return true;
83 }
84
85private:
86 // 1-based code complete position <Line, Col>;
87 ParsedSourceLocation CompletePosition;
Ilya Biryukov4974d75d2018-12-13 16:06:11 +000088 CompletionContext &ResultCtx;
Haojian Wu10d95c52018-01-17 14:29:25 +000089};
90
91ParsedSourceLocation offsetToPosition(llvm::StringRef Code, size_t Offset) {
92 Offset = std::min(Code.size(), Offset);
93 StringRef Before = Code.substr(0, Offset);
94 int Lines = Before.count('\n');
95 size_t PrevNL = Before.rfind('\n');
96 size_t StartOfLine = (PrevNL == StringRef::npos) ? 0 : (PrevNL + 1);
97 return {TestCCName, static_cast<unsigned>(Lines + 1),
98 static_cast<unsigned>(Offset - StartOfLine + 1)};
99}
100
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000101CompletionContext runCompletion(StringRef Code, size_t Offset) {
102 CompletionContext ResultCtx;
Haojian Wu10d95c52018-01-17 14:29:25 +0000103 auto Action = llvm::make_unique<CodeCompleteAction>(
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000104 offsetToPosition(Code, Offset), ResultCtx);
Roman Lebedev497fd982018-02-27 15:54:55 +0000105 clang::tooling::runToolOnCodeWithArgs(Action.release(), Code, {"-std=c++11"},
Haojian Wu10d95c52018-01-17 14:29:25 +0000106 TestCCName);
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000107 return ResultCtx;
108}
109
110struct ParsedAnnotations {
111 std::vector<size_t> Points;
112 std::string Code;
113};
114
115ParsedAnnotations parseAnnotations(StringRef AnnotatedCode) {
116 ParsedAnnotations R;
117 while (!AnnotatedCode.empty()) {
118 size_t NextPoint = AnnotatedCode.find('^');
119 if (NextPoint == StringRef::npos) {
120 R.Code += AnnotatedCode;
121 AnnotatedCode = "";
122 break;
123 }
124 R.Code += AnnotatedCode.substr(0, NextPoint);
125 R.Points.push_back(R.Code.size());
126
127 AnnotatedCode = AnnotatedCode.substr(NextPoint + 1);
128 }
129 return R;
130}
131
132CompletionContext runCodeCompleteOnCode(StringRef AnnotatedCode) {
133 ParsedAnnotations P = parseAnnotations(AnnotatedCode);
134 assert(P.Points.size() == 1 && "expected exactly one annotation point");
135 return runCompletion(P.Code, P.Points.front());
136}
137
Ilya Biryukov1d7ba832018-12-17 16:37:52 +0000138std::vector<std::string>
139collectPreferredTypes(StringRef AnnotatedCode,
140 std::string *PtrDiffType = nullptr) {
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000141 ParsedAnnotations P = parseAnnotations(AnnotatedCode);
142 std::vector<std::string> Types;
Ilya Biryukov1d7ba832018-12-17 16:37:52 +0000143 for (size_t Point : P.Points) {
144 auto Results = runCompletion(P.Code, Point);
145 if (PtrDiffType) {
146 assert(PtrDiffType->empty() || *PtrDiffType == Results.PtrDiffType);
147 *PtrDiffType = Results.PtrDiffType;
148 }
149 Types.push_back(Results.PreferredType);
150 }
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000151 return Types;
Haojian Wu10d95c52018-01-17 14:29:25 +0000152}
153
154TEST(SemaCodeCompleteTest, VisitedNSForValidQualifiedId) {
155 auto VisitedNS = runCodeCompleteOnCode(R"cpp(
156 namespace ns1 {}
157 namespace ns2 {}
158 namespace ns3 {}
159 namespace ns3 { namespace nns3 {} }
160
161 namespace foo {
162 using namespace ns1;
163 namespace ns4 {} // not visited
164 namespace { using namespace ns2; }
165 inline namespace bar { using namespace ns3::nns3; }
166 } // foo
167 namespace ns { foo::^ }
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000168 )cpp")
169 .VisitedNamespaces;
Haojian Wu10d95c52018-01-17 14:29:25 +0000170 EXPECT_THAT(VisitedNS, UnorderedElementsAre("foo", "ns1", "ns2", "ns3::nns3",
171 "foo::(anonymous)"));
172}
173
Eric Liu206740e2019-02-21 11:22:58 +0000174TEST(SemaCodeCompleteTest, VisitedNSForInvalidQualifiedId) {
Haojian Wu10d95c52018-01-17 14:29:25 +0000175 auto VisitedNS = runCodeCompleteOnCode(R"cpp(
Eric Liu206740e2019-02-21 11:22:58 +0000176 namespace na {}
177 namespace ns1 {
178 using namespace na;
179 foo::^
180 }
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000181 )cpp")
182 .VisitedNamespaces;
Eric Liu206740e2019-02-21 11:22:58 +0000183 EXPECT_THAT(VisitedNS, UnorderedElementsAre("ns1", "na"));
Haojian Wu10d95c52018-01-17 14:29:25 +0000184}
185
Eric Liuf5ba09f2018-07-04 10:01:18 +0000186TEST(SemaCodeCompleteTest, VisitedNSWithoutQualifier) {
187 auto VisitedNS = runCodeCompleteOnCode(R"cpp(
188 namespace n1 {
189 namespace n2 {
190 void f(^) {}
191 }
192 }
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000193 )cpp")
194 .VisitedNamespaces;
Eric Liuf5ba09f2018-07-04 10:01:18 +0000195 EXPECT_THAT(VisitedNS, UnorderedElementsAre("n1", "n1::n2"));
196}
197
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000198TEST(PreferredTypeTest, BinaryExpr) {
199 // Check various operations for arithmetic types.
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000200 StringRef Code = R"cpp(
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000201 void test(int x) {
202 x = ^10;
203 x += ^10; x -= ^10; x *= ^10; x /= ^10; x %= ^10;
204 x + ^10; x - ^10; x * ^10; x / ^10; x % ^10;
David Green0250e292018-12-13 17:20:06 +0000205 })cpp";
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000206 EXPECT_THAT(collectPreferredTypes(Code), Each("int"));
207
208 Code = R"cpp(
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000209 void test(float x) {
210 x = ^10;
211 x += ^10; x -= ^10; x *= ^10; x /= ^10; x %= ^10;
212 x + ^10; x - ^10; x * ^10; x / ^10; x % ^10;
David Green0250e292018-12-13 17:20:06 +0000213 })cpp";
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000214 EXPECT_THAT(collectPreferredTypes(Code), Each("float"));
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000215
216 // Pointer types.
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000217 Code = R"cpp(
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000218 void test(int *ptr) {
219 ptr - ^ptr;
220 ptr = ^ptr;
David Green0250e292018-12-13 17:20:06 +0000221 })cpp";
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000222 EXPECT_THAT(collectPreferredTypes(Code), Each("int *"));
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000223
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000224 Code = R"cpp(
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000225 void test(int *ptr) {
226 ptr + ^10;
227 ptr += ^10;
228 ptr -= ^10;
David Green0250e292018-12-13 17:20:06 +0000229 })cpp";
Ilya Biryukov1d7ba832018-12-17 16:37:52 +0000230 {
231 std::string PtrDiff;
232 auto Types = collectPreferredTypes(Code, &PtrDiff);
233 EXPECT_THAT(Types, Each(PtrDiff));
234 }
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000235
236 // Comparison operators.
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000237 Code = R"cpp(
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000238 void test(int i) {
239 i <= ^1; i < ^1; i >= ^1; i > ^1; i == ^1; i != ^1;
240 }
David Green0250e292018-12-13 17:20:06 +0000241 )cpp";
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000242 EXPECT_THAT(collectPreferredTypes(Code), Each("int"));
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000243
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000244 Code = R"cpp(
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000245 void test(int *ptr) {
246 ptr <= ^ptr; ptr < ^ptr; ptr >= ^ptr; ptr > ^ptr;
247 ptr == ^ptr; ptr != ^ptr;
248 }
David Green0250e292018-12-13 17:20:06 +0000249 )cpp";
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000250 EXPECT_THAT(collectPreferredTypes(Code), Each("int *"));
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000251
252 // Relational operations.
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000253 Code = R"cpp(
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000254 void test(int i, int *ptr) {
255 i && ^1; i || ^1;
256 ptr && ^1; ptr || ^1;
257 }
David Green0250e292018-12-13 17:20:06 +0000258 )cpp";
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000259 EXPECT_THAT(collectPreferredTypes(Code), Each("_Bool"));
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000260
261 // Bitwise operations.
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000262 Code = R"cpp(
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000263 void test(long long ll) {
264 ll | ^1; ll & ^1;
265 }
David Green0250e292018-12-13 17:20:06 +0000266 )cpp";
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000267 EXPECT_THAT(collectPreferredTypes(Code), Each("long long"));
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000268
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000269 Code = R"cpp(
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000270 enum A {};
271 void test(A a) {
272 a | ^1; a & ^1;
273 }
David Green0250e292018-12-13 17:20:06 +0000274 )cpp";
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000275 EXPECT_THAT(collectPreferredTypes(Code), Each("enum A"));
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000276
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000277 Code = R"cpp(
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000278 enum class A {};
279 void test(A a) {
280 // This is technically illegal with the 'enum class' without overloaded
281 // operators, but we pretend it's fine.
282 a | ^a; a & ^a;
283 }
David Green0250e292018-12-13 17:20:06 +0000284 )cpp";
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000285 EXPECT_THAT(collectPreferredTypes(Code), Each("enum A"));
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000286
287 // Binary shifts.
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000288 Code = R"cpp(
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000289 void test(int i, long long ll) {
290 i << ^1; ll << ^1;
291 i <<= ^1; i <<= ^1;
292 i >> ^1; ll >> ^1;
293 i >>= ^1; i >>= ^1;
294 }
David Green0250e292018-12-13 17:20:06 +0000295 )cpp";
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000296 EXPECT_THAT(collectPreferredTypes(Code), Each("int"));
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000297
298 // Comma does not provide any useful information.
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000299 Code = R"cpp(
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000300 class Cls {};
301 void test(int i, int* ptr, Cls x) {
302 (i, ^i);
303 (ptr, ^ptr);
304 (x, ^x);
305 }
David Green0250e292018-12-13 17:20:06 +0000306 )cpp";
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000307 EXPECT_THAT(collectPreferredTypes(Code), Each("NULL TYPE"));
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000308
309 // User-defined types do not take operator overloading into account.
310 // However, they provide heuristics for some common cases.
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000311 Code = R"cpp(
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000312 class Cls {};
313 void test(Cls c) {
314 // we assume arithmetic and comparions ops take the same type.
315 c + ^c; c - ^c; c * ^c; c / ^c; c % ^c;
316 c == ^c; c != ^c; c < ^c; c <= ^c; c > ^c; c >= ^c;
317 // same for the assignments.
318 c = ^c; c += ^c; c -= ^c; c *= ^c; c /= ^c; c %= ^c;
319 }
David Green0250e292018-12-13 17:20:06 +0000320 )cpp";
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000321 EXPECT_THAT(collectPreferredTypes(Code), Each("class Cls"));
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000322
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000323 Code = R"cpp(
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000324 class Cls {};
325 void test(Cls c) {
326 // we assume relational ops operate on bools.
327 c && ^c; c || ^c;
328 }
David Green0250e292018-12-13 17:20:06 +0000329 )cpp";
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000330 EXPECT_THAT(collectPreferredTypes(Code), Each("_Bool"));
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000331
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000332 Code = R"cpp(
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000333 class Cls {};
334 void test(Cls c) {
335 // we make no assumptions about the following operators, since they are
336 // often overloaded with a non-standard meaning.
337 c << ^c; c >> ^c; c | ^c; c & ^c;
338 c <<= ^c; c >>= ^c; c |= ^c; c &= ^c;
339 }
David Green0250e292018-12-13 17:20:06 +0000340 )cpp";
Ilya Biryukov69e181d2018-12-13 17:32:38 +0000341 EXPECT_THAT(collectPreferredTypes(Code), Each("NULL TYPE"));
Ilya Biryukov4974d75d2018-12-13 16:06:11 +0000342}
343
Ilya Biryukov4f9543b2019-01-31 20:20:32 +0000344TEST(PreferredTypeTest, Members) {
345 StringRef Code = R"cpp(
346 struct vector {
347 int *begin();
348 vector clone();
349 };
350
351 void test(int *a) {
352 a = ^vector().^clone().^begin();
353 }
354 )cpp";
355 EXPECT_THAT(collectPreferredTypes(Code), Each("int *"));
356}
357
358TEST(PreferredTypeTest, Conditions) {
359 StringRef Code = R"cpp(
360 struct vector {
361 bool empty();
362 };
363
364 void test() {
365 if (^vector().^empty()) {}
366 while (^vector().^empty()) {}
367 for (; ^vector().^empty();) {}
368 }
369 )cpp";
370 EXPECT_THAT(collectPreferredTypes(Code), Each("_Bool"));
371}
372
373TEST(PreferredTypeTest, InitAndAssignment) {
374 StringRef Code = R"cpp(
375 struct vector {
376 int* begin();
377 };
378
379 void test() {
380 const int* x = ^vector().^begin();
381 x = ^vector().^begin();
382
383 if (const int* y = ^vector().^begin()) {}
384 }
385 )cpp";
386 EXPECT_THAT(collectPreferredTypes(Code), Each("const int *"));
387}
388
389TEST(PreferredTypeTest, UnaryExprs) {
390 StringRef Code = R"cpp(
391 void test(long long a) {
392 a = +^a;
393 a = -^a
394 a = ++^a;
395 a = --^a;
396 }
397 )cpp";
398 EXPECT_THAT(collectPreferredTypes(Code), Each("long long"));
399
400 Code = R"cpp(
401 void test(int a, int *ptr) {
402 !^a;
403 !^ptr;
404 !!!^a;
405
406 a = !^a;
407 a = !^ptr;
408 a = !!!^a;
409 }
410 )cpp";
411 EXPECT_THAT(collectPreferredTypes(Code), Each("_Bool"));
412
413 Code = R"cpp(
414 void test(int a) {
415 const int* x = &^a;
416 }
417 )cpp";
418 EXPECT_THAT(collectPreferredTypes(Code), Each("const int"));
419
420 Code = R"cpp(
421 void test(int *a) {
422 int x = *^a;
423 int &r = *^a;
424 }
425 )cpp";
426 EXPECT_THAT(collectPreferredTypes(Code), Each("int *"));
427
428 Code = R"cpp(
429 void test(int a) {
430 *^a;
431 &^a;
432 }
433
434 )cpp";
435}
436
437TEST(PreferredTypeTest, ParenExpr) {
438 StringRef Code = R"cpp(
439 const int *i = ^(^(^(^10)));
440 )cpp";
441 EXPECT_THAT(collectPreferredTypes(Code), Each("const int *"));
442}
Ilya Biryukovff2a9972019-02-26 11:01:50 +0000443
444TEST(PreferredTypeTest, FunctionArguments) {
445 StringRef Code = R"cpp(
446 void foo(const int*);
447
448 void bar(const int*);
449 void bar(const int*, int b);
450
451 struct vector {
452 const int *data();
453 };
454 void test() {
455 foo(^(^(^(^vec^tor^().^da^ta^()))));
456 bar(^(^(^(^vec^tor^().^da^ta^()))));
457 }
458 )cpp";
459 EXPECT_THAT(collectPreferredTypes(Code), Each("const int *"));
460
461 Code = R"cpp(
462 void bar(int, volatile double *);
463 void bar(int, volatile double *, int, int);
464
465 struct vector {
466 double *data();
467 };
468
469 struct class_members {
470 void bar(int, volatile double *);
471 void bar(int, volatile double *, int, int);
472 };
473 void test() {
474 bar(10, ^(^(^(^vec^tor^().^da^ta^()))));
475 class_members().bar(10, ^(^(^(^vec^tor^().^da^ta^()))));
476 }
477 )cpp";
478 EXPECT_THAT(collectPreferredTypes(Code), Each("volatile double *"));
479}
Haojian Wu10d95c52018-01-17 14:29:25 +0000480} // namespace