[LLD][COFF] Emit tail merge pdata for delay load thunks on ARM64EC (#116810)
[llvm-project.git] / clang / unittests / Sema / CodeCompleteTest.cpp
blobbe611b330e501350044e7583e0b320b7d2df3988
1 //=== unittests/Sema/CodeCompleteTest.cpp - Code Complete tests ==============//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
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"
16 #include "llvm/Testing/Annotations/Annotations.h"
17 #include "gmock/gmock.h"
18 #include "gtest/gtest.h"
19 #include <cstddef>
20 #include <string>
22 namespace {
24 using namespace clang;
25 using namespace clang::tooling;
26 using ::testing::AllOf;
27 using ::testing::Contains;
28 using ::testing::Each;
29 using ::testing::UnorderedElementsAre;
31 const char TestCCName[] = "test.cc";
33 struct CompletionContext {
34 std::vector<std::string> VisitedNamespaces;
35 std::string PreferredType;
36 // String representation of std::ptrdiff_t on a given platform. This is a hack
37 // to properly account for different configurations of clang.
38 std::string PtrDiffType;
41 struct CompletedFunctionDecl {
42 std::string Name;
43 bool IsStatic;
44 bool CanBeCall;
46 MATCHER_P(named, name, "") { return arg.Name == name; }
47 MATCHER_P(isStatic, value, "") { return arg.IsStatic == value; }
48 MATCHER_P(canBeCall, value, "") { return arg.CanBeCall == value; }
50 class SaveCompletedFunctions : public CodeCompleteConsumer {
51 public:
52 SaveCompletedFunctions(std::vector<CompletedFunctionDecl> &CompletedFuncDecls)
53 : CodeCompleteConsumer(/*CodeCompleteOpts=*/{}),
54 CompletedFuncDecls(CompletedFuncDecls),
55 CCTUInfo(std::make_shared<GlobalCodeCompletionAllocator>()) {}
57 void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context,
58 CodeCompletionResult *Results,
59 unsigned NumResults) override {
60 for (unsigned I = 0; I < NumResults; ++I) {
61 auto R = Results[I];
62 if (R.Kind == CodeCompletionResult::RK_Declaration) {
63 auto *ND = R.getDeclaration();
64 if (auto *Template = llvm::dyn_cast<FunctionTemplateDecl>(ND))
65 ND = Template->getTemplatedDecl();
66 if (const auto *FD = llvm::dyn_cast<FunctionDecl>(ND)) {
67 CompletedFunctionDecl D;
68 D.Name = FD->getNameAsString();
69 D.CanBeCall = R.FunctionCanBeCall;
70 D.IsStatic = FD->isStatic();
71 CompletedFuncDecls.emplace_back(std::move(D));
77 private:
78 CodeCompletionAllocator &getAllocator() override {
79 return CCTUInfo.getAllocator();
82 CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; }
84 std::vector<CompletedFunctionDecl> &CompletedFuncDecls;
86 CodeCompletionTUInfo CCTUInfo;
89 class VisitedContextFinder : public CodeCompleteConsumer {
90 public:
91 VisitedContextFinder(CompletionContext &ResultCtx)
92 : CodeCompleteConsumer(/*CodeCompleteOpts=*/{}), ResultCtx(ResultCtx),
93 CCTUInfo(std::make_shared<GlobalCodeCompletionAllocator>()) {}
95 void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context,
96 CodeCompletionResult *Results,
97 unsigned NumResults) override {
98 ResultCtx.VisitedNamespaces =
99 getVisitedNamespace(Context.getVisitedContexts());
100 ResultCtx.PreferredType = Context.getPreferredType().getAsString();
101 ResultCtx.PtrDiffType =
102 S.getASTContext().getPointerDiffType().getAsString();
105 CodeCompletionAllocator &getAllocator() override {
106 return CCTUInfo.getAllocator();
109 CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; }
111 private:
112 std::vector<std::string> getVisitedNamespace(
113 CodeCompletionContext::VisitedContextSet VisitedContexts) const {
114 std::vector<std::string> NSNames;
115 for (const auto *Context : VisitedContexts)
116 if (const auto *NS = llvm::dyn_cast<NamespaceDecl>(Context))
117 NSNames.push_back(NS->getQualifiedNameAsString());
118 return NSNames;
121 CompletionContext &ResultCtx;
122 CodeCompletionTUInfo CCTUInfo;
125 class CodeCompleteAction : public SyntaxOnlyAction {
126 public:
127 CodeCompleteAction(ParsedSourceLocation P, CodeCompleteConsumer *Consumer)
128 : CompletePosition(std::move(P)), Consumer(Consumer) {}
130 bool BeginInvocation(CompilerInstance &CI) override {
131 CI.getFrontendOpts().CodeCompletionAt = CompletePosition;
132 CI.setCodeCompletionConsumer(Consumer);
133 return true;
136 private:
137 // 1-based code complete position <Line, Col>;
138 ParsedSourceLocation CompletePosition;
139 CodeCompleteConsumer *Consumer;
142 ParsedSourceLocation offsetToPosition(llvm::StringRef Code, size_t Offset) {
143 Offset = std::min(Code.size(), Offset);
144 StringRef Before = Code.substr(0, Offset);
145 int Lines = Before.count('\n');
146 size_t PrevNL = Before.rfind('\n');
147 size_t StartOfLine = (PrevNL == StringRef::npos) ? 0 : (PrevNL + 1);
148 return {TestCCName, static_cast<unsigned>(Lines + 1),
149 static_cast<unsigned>(Offset - StartOfLine + 1)};
152 CompletionContext runCompletion(StringRef Code, size_t Offset) {
153 CompletionContext ResultCtx;
154 clang::tooling::runToolOnCodeWithArgs(
155 std::make_unique<CodeCompleteAction>(offsetToPosition(Code, Offset),
156 new VisitedContextFinder(ResultCtx)),
157 Code, {"-std=c++11"}, TestCCName);
158 return ResultCtx;
161 CompletionContext runCodeCompleteOnCode(StringRef AnnotatedCode) {
162 llvm::Annotations A(AnnotatedCode);
163 return runCompletion(A.code(), A.point());
166 std::vector<std::string>
167 collectPreferredTypes(StringRef AnnotatedCode,
168 std::string *PtrDiffType = nullptr) {
169 llvm::Annotations A(AnnotatedCode);
170 std::vector<std::string> Types;
171 for (size_t Point : A.points()) {
172 auto Results = runCompletion(A.code(), Point);
173 if (PtrDiffType) {
174 assert(PtrDiffType->empty() || *PtrDiffType == Results.PtrDiffType);
175 *PtrDiffType = Results.PtrDiffType;
177 Types.push_back(Results.PreferredType);
179 return Types;
182 std::vector<CompletedFunctionDecl>
183 CollectCompletedFunctions(StringRef Code, std::size_t Point) {
184 std::vector<CompletedFunctionDecl> Result;
185 clang::tooling::runToolOnCodeWithArgs(
186 std::make_unique<CodeCompleteAction>(offsetToPosition(Code, Point),
187 new SaveCompletedFunctions(Result)),
188 Code, {"-std=c++11"}, TestCCName);
189 return Result;
192 TEST(SemaCodeCompleteTest, FunctionCanBeCall) {
193 llvm::Annotations Code(R"cpp(
194 struct Foo {
195 static int staticMethod();
196 int method() const;
197 template <typename T, typename U, typename V = int>
198 T generic(U, V);
199 template <typename T, int U = 3>
200 static T staticGeneric();
201 Foo() {
202 this->$canBeCall^
203 $canBeCall^
204 Foo::$canBeCall^
208 struct Derived : Foo {
209 using Foo::method;
210 using Foo::generic;
211 Derived() {
212 Foo::$canBeCall^
216 struct OtherClass {
217 OtherClass() {
218 Foo f;
219 Derived d;
220 f.$canBeCall^
221 ; // Prevent parsing as 'f.f'
222 f.Foo::$canBeCall^
223 &Foo::$cannotBeCall^
225 d.Foo::$canBeCall^
227 d.Derived::$canBeCall^
231 int main() {
232 Foo f;
233 Derived d;
234 f.$canBeCall^
235 ; // Prevent parsing as 'f.f'
236 f.Foo::$canBeCall^
237 &Foo::$cannotBeCall^
239 d.Foo::$canBeCall^
241 d.Derived::$canBeCall^
243 )cpp");
245 for (const auto &P : Code.points("canBeCall")) {
246 auto Results = CollectCompletedFunctions(Code.code(), P);
247 EXPECT_THAT(Results, Contains(AllOf(named("method"), isStatic(false),
248 canBeCall(true))));
249 EXPECT_THAT(Results, Contains(AllOf(named("generic"), isStatic(false),
250 canBeCall(true))));
253 for (const auto &P : Code.points("cannotBeCall")) {
254 auto Results = CollectCompletedFunctions(Code.code(), P);
255 EXPECT_THAT(Results, Contains(AllOf(named("method"), isStatic(false),
256 canBeCall(false))));
257 EXPECT_THAT(Results, Contains(AllOf(named("generic"), isStatic(false),
258 canBeCall(false))));
261 // static method can always be a call
262 for (const auto &P : Code.points()) {
263 auto Results = CollectCompletedFunctions(Code.code(), P);
264 EXPECT_THAT(Results, Contains(AllOf(named("staticMethod"), isStatic(true),
265 canBeCall(true))));
266 EXPECT_THAT(Results, Contains(AllOf(named("staticGeneric"), isStatic(true),
267 canBeCall(true))));
271 TEST(SemaCodeCompleteTest, VisitedNSForValidQualifiedId) {
272 auto VisitedNS = runCodeCompleteOnCode(R"cpp(
273 namespace ns1 {}
274 namespace ns2 {}
275 namespace ns3 {}
276 namespace ns3 { namespace nns3 {} }
278 namespace foo {
279 using namespace ns1;
280 namespace ns4 {} // not visited
281 namespace { using namespace ns2; }
282 inline namespace bar { using namespace ns3::nns3; }
283 } // foo
284 namespace ns { foo::^ }
285 )cpp")
286 .VisitedNamespaces;
287 EXPECT_THAT(VisitedNS, UnorderedElementsAre("foo", "ns1", "ns2", "ns3::nns3",
288 "foo::(anonymous)"));
291 TEST(SemaCodeCompleteTest, VisitedNSForInvalidQualifiedId) {
292 auto VisitedNS = runCodeCompleteOnCode(R"cpp(
293 namespace na {}
294 namespace ns1 {
295 using namespace na;
296 foo::^
298 )cpp")
299 .VisitedNamespaces;
300 EXPECT_THAT(VisitedNS, UnorderedElementsAre("ns1", "na"));
303 TEST(SemaCodeCompleteTest, VisitedNSWithoutQualifier) {
304 auto VisitedNS = runCodeCompleteOnCode(R"cpp(
305 namespace n1 {
306 namespace n2 {
307 void f(^) {}
310 )cpp")
311 .VisitedNamespaces;
312 EXPECT_THAT(VisitedNS, UnorderedElementsAre("n1", "n1::n2"));
315 TEST(PreferredTypeTest, BinaryExpr) {
316 // Check various operations for arithmetic types.
317 StringRef Code = R"cpp(
318 void test(int x) {
319 x = ^10;
320 x += ^10; x -= ^10; x *= ^10; x /= ^10; x %= ^10;
321 x + ^10; x - ^10; x * ^10; x / ^10; x % ^10;
322 })cpp";
323 EXPECT_THAT(collectPreferredTypes(Code), Each("int"));
325 Code = R"cpp(
326 void test(float x) {
327 x = ^10;
328 x += ^10; x -= ^10; x *= ^10; x /= ^10; x %= ^10;
329 x + ^10; x - ^10; x * ^10; x / ^10; x % ^10;
330 })cpp";
331 EXPECT_THAT(collectPreferredTypes(Code), Each("float"));
333 // Pointer types.
334 Code = R"cpp(
335 void test(int *ptr) {
336 ptr - ^ptr;
337 ptr = ^ptr;
338 })cpp";
339 EXPECT_THAT(collectPreferredTypes(Code), Each("int *"));
341 Code = R"cpp(
342 void test(int *ptr) {
343 ptr + ^10;
344 ptr += ^10;
345 ptr -= ^10;
346 })cpp";
348 std::string PtrDiff;
349 auto Types = collectPreferredTypes(Code, &PtrDiff);
350 EXPECT_THAT(Types, Each(PtrDiff));
353 // Comparison operators.
354 Code = R"cpp(
355 void test(int i) {
356 i <= ^1; i < ^1; i >= ^1; i > ^1; i == ^1; i != ^1;
358 )cpp";
359 EXPECT_THAT(collectPreferredTypes(Code), Each("int"));
361 Code = R"cpp(
362 void test(int *ptr) {
363 ptr <= ^ptr; ptr < ^ptr; ptr >= ^ptr; ptr > ^ptr;
364 ptr == ^ptr; ptr != ^ptr;
366 )cpp";
367 EXPECT_THAT(collectPreferredTypes(Code), Each("int *"));
369 // Relational operations.
370 Code = R"cpp(
371 void test(int i, int *ptr) {
372 i && ^1; i || ^1;
373 ptr && ^1; ptr || ^1;
375 )cpp";
376 EXPECT_THAT(collectPreferredTypes(Code), Each("_Bool"));
378 // Bitwise operations.
379 Code = R"cpp(
380 void test(long long ll) {
381 ll | ^1; ll & ^1;
383 )cpp";
384 EXPECT_THAT(collectPreferredTypes(Code), Each("long long"));
386 Code = R"cpp(
387 enum A {};
388 void test(A a) {
389 a | ^1; a & ^1;
391 )cpp";
392 EXPECT_THAT(collectPreferredTypes(Code), Each("A"));
394 Code = R"cpp(
395 enum class A {};
396 void test(A a) {
397 // This is technically illegal with the 'enum class' without overloaded
398 // operators, but we pretend it's fine.
399 a | ^a; a & ^a;
401 )cpp";
402 EXPECT_THAT(collectPreferredTypes(Code), Each("A"));
404 // Binary shifts.
405 Code = R"cpp(
406 void test(int i, long long ll) {
407 i << ^1; ll << ^1;
408 i <<= ^1; i <<= ^1;
409 i >> ^1; ll >> ^1;
410 i >>= ^1; i >>= ^1;
412 )cpp";
413 EXPECT_THAT(collectPreferredTypes(Code), Each("int"));
415 // Comma does not provide any useful information.
416 Code = R"cpp(
417 class Cls {};
418 void test(int i, int* ptr, Cls x) {
419 (i, ^i);
420 (ptr, ^ptr);
421 (x, ^x);
423 )cpp";
424 EXPECT_THAT(collectPreferredTypes(Code), Each("NULL TYPE"));
426 // User-defined types do not take operator overloading into account.
427 // However, they provide heuristics for some common cases.
428 Code = R"cpp(
429 class Cls {};
430 void test(Cls c) {
431 // we assume arithmetic and comparions ops take the same type.
432 c + ^c; c - ^c; c * ^c; c / ^c; c % ^c;
433 c == ^c; c != ^c; c < ^c; c <= ^c; c > ^c; c >= ^c;
434 // same for the assignments.
435 c = ^c; c += ^c; c -= ^c; c *= ^c; c /= ^c; c %= ^c;
437 )cpp";
438 EXPECT_THAT(collectPreferredTypes(Code), Each("Cls"));
440 Code = R"cpp(
441 class Cls {};
442 void test(Cls c) {
443 // we assume relational ops operate on bools.
444 c && ^c; c || ^c;
446 )cpp";
447 EXPECT_THAT(collectPreferredTypes(Code), Each("_Bool"));
449 Code = R"cpp(
450 class Cls {};
451 void test(Cls c) {
452 // we make no assumptions about the following operators, since they are
453 // often overloaded with a non-standard meaning.
454 c << ^c; c >> ^c; c | ^c; c & ^c;
455 c <<= ^c; c >>= ^c; c |= ^c; c &= ^c;
457 )cpp";
458 EXPECT_THAT(collectPreferredTypes(Code), Each("NULL TYPE"));
461 TEST(PreferredTypeTest, Members) {
462 StringRef Code = R"cpp(
463 struct vector {
464 int *begin();
465 vector clone();
468 void test(int *a) {
469 a = ^vector().^clone().^begin();
471 )cpp";
472 EXPECT_THAT(collectPreferredTypes(Code), Each("int *"));
475 TEST(PreferredTypeTest, Conditions) {
476 StringRef Code = R"cpp(
477 struct vector {
478 bool empty();
481 void test() {
482 if (^vector().^empty()) {}
483 while (^vector().^empty()) {}
484 for (; ^vector().^empty();) {}
486 )cpp";
487 EXPECT_THAT(collectPreferredTypes(Code), Each("_Bool"));
490 TEST(PreferredTypeTest, InitAndAssignment) {
491 StringRef Code = R"cpp(
492 struct vector {
493 int* begin();
496 void test() {
497 const int* x = ^vector().^begin();
498 x = ^vector().^begin();
500 if (const int* y = ^vector().^begin()) {}
502 )cpp";
503 EXPECT_THAT(collectPreferredTypes(Code), Each("const int *"));
506 TEST(PreferredTypeTest, UnaryExprs) {
507 StringRef Code = R"cpp(
508 void test(long long a) {
509 a = +^a;
510 a = -^a
511 a = ++^a;
512 a = --^a;
514 )cpp";
515 EXPECT_THAT(collectPreferredTypes(Code), Each("long long"));
517 Code = R"cpp(
518 void test(int a, int *ptr) {
519 !^a;
520 !^ptr;
521 !!!^a;
523 a = !^a;
524 a = !^ptr;
525 a = !!!^a;
527 )cpp";
528 EXPECT_THAT(collectPreferredTypes(Code), Each("_Bool"));
530 Code = R"cpp(
531 void test(int a) {
532 const int* x = &^a;
534 )cpp";
535 EXPECT_THAT(collectPreferredTypes(Code), Each("const int"));
537 Code = R"cpp(
538 void test(int *a) {
539 int x = *^a;
540 int &r = *^a;
542 )cpp";
543 EXPECT_THAT(collectPreferredTypes(Code), Each("int *"));
545 Code = R"cpp(
546 void test(int a) {
547 *^a;
548 &^a;
551 )cpp";
554 TEST(PreferredTypeTest, ParenExpr) {
555 StringRef Code = R"cpp(
556 const int *i = ^(^(^(^10)));
557 )cpp";
558 EXPECT_THAT(collectPreferredTypes(Code), Each("const int *"));
561 TEST(PreferredTypeTest, FunctionArguments) {
562 StringRef Code = R"cpp(
563 void foo(const int*);
565 void bar(const int*);
566 void bar(const int*, int b);
568 struct vector {
569 const int *data();
571 void test() {
572 foo(^(^(^(^vec^tor^().^da^ta^()))));
573 bar(^(^(^(^vec^tor^().^da^ta^()))));
575 )cpp";
576 EXPECT_THAT(collectPreferredTypes(Code), Each("const int *"));
578 Code = R"cpp(
579 void bar(int, volatile double *);
580 void bar(int, volatile double *, int, int);
582 struct vector {
583 double *data();
586 struct class_members {
587 void bar(int, volatile double *);
588 void bar(int, volatile double *, int, int);
590 void test() {
591 bar(10, ^(^(^(^vec^tor^().^da^ta^()))));
592 class_members().bar(10, ^(^(^(^vec^tor^().^da^ta^()))));
594 )cpp";
595 EXPECT_THAT(collectPreferredTypes(Code), Each("volatile double *"));
597 Code = R"cpp(
598 namespace ns {
599 struct vector {
602 void accepts_vector(ns::vector);
604 void test() {
605 accepts_vector(^::^ns::^vector());
607 )cpp";
608 EXPECT_THAT(collectPreferredTypes(Code), Each("ns::vector"));
610 Code = R"cpp(
611 template <class T>
612 struct vector { using self = vector; };
614 void accepts_vector(vector<int>);
615 int foo(int);
617 void test() {
618 accepts_vector(^::^vector<decltype(foo(1))>::^self);
620 )cpp";
621 EXPECT_THAT(collectPreferredTypes(Code), Each("vector<int>"));
624 TEST(PreferredTypeTest, NoCrashOnInvalidTypes) {
625 StringRef Code = R"cpp(
626 auto x = decltype(&1)(^);
627 auto y = new decltype(&1)(^);
628 // GNU decimal type extension is not supported in clang.
629 auto z = new _Decimal128(^);
630 void foo() { (void)(foo)(^); }
631 )cpp";
632 EXPECT_THAT(collectPreferredTypes(Code), Each("NULL TYPE"));
635 } // namespace