1 //===-- DefineInlineTests.cpp -----------------------------------*- C++ -*-===//
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 //===----------------------------------------------------------------------===//
8
9 #include "TestTU.h"
10 #include "TweakTesting.h"
11 #include "gmock/gmock-matchers.h"
12 #include "gmock/gmock.h"
13 #include "gtest/gtest.h"
14
15 using ::testing::ElementsAre;
16
17 namespace clang {
18 namespace clangd {
19 namespace {
20
21 TWEAK_TEST(DefineInline);
22
TEST_F(DefineInlineTest,TriggersOnFunctionDecl)23 TEST_F(DefineInlineTest, TriggersOnFunctionDecl) {
24 // Basic check for function body and signature.
25 EXPECT_AVAILABLE(R"cpp(
26 class Bar {
27 void baz();
28 };
29
30 [[void [[Bar::[[b^a^z]]]]() [[{
31 return;
32 }]]]]
33
34 void foo();
35 [[void [[f^o^o]]() [[{
36 return;
37 }]]]]
38 )cpp");
39
40 EXPECT_UNAVAILABLE(R"cpp(
41 // Not a definition
42 vo^i[[d^ ^f]]^oo();
43
44 [[vo^id ]]foo[[()]] {[[
45 [[(void)(5+3);
46 return;]]
47 }]]
48
49 // Definition with no body.
50 class Bar { Bar() = def^ault; };
51 )cpp");
52 }
53
TEST_F(DefineInlineTest,NoForwardDecl)54 TEST_F(DefineInlineTest, NoForwardDecl) {
55 Header = "void bar();";
56 EXPECT_UNAVAILABLE(R"cpp(
57 void bar() {
58 return;
59 }
60 // FIXME: Generate a decl in the header.
61 void fo^o() {
62 return;
63 })cpp");
64 }
65
TEST_F(DefineInlineTest,ReferencedDecls)66 TEST_F(DefineInlineTest, ReferencedDecls) {
67 EXPECT_AVAILABLE(R"cpp(
68 void bar();
69 void foo(int test);
70
71 void fo^o(int baz) {
72 int x = 10;
73 bar();
74 })cpp");
75
76 // Internal symbol usage.
77 Header = "void foo(int test);";
78 EXPECT_UNAVAILABLE(R"cpp(
79 void bar();
80 void fo^o(int baz) {
81 int x = 10;
82 bar();
83 })cpp");
84
85 // Becomes available after making symbol visible.
86 Header = "void bar();" + Header;
87 EXPECT_AVAILABLE(R"cpp(
88 void fo^o(int baz) {
89 int x = 10;
90 bar();
91 })cpp");
92
93 // FIXME: Move declaration below bar to make it visible.
94 Header.clear();
95 EXPECT_UNAVAILABLE(R"cpp(
96 void foo();
97 void bar();
98
99 void fo^o() {
100 bar();
101 })cpp");
102
103 // Order doesn't matter within a class.
104 EXPECT_AVAILABLE(R"cpp(
105 class Bar {
106 void foo();
107 void bar();
108 };
109
110 void Bar::fo^o() {
111 bar();
112 })cpp");
113
114 // FIXME: Perform include insertion to make symbol visible.
115 ExtraFiles["a.h"] = "void bar();";
116 Header = "void foo(int test);";
117 EXPECT_UNAVAILABLE(R"cpp(
118 #include "a.h"
119 void fo^o(int baz) {
120 int x = 10;
121 bar();
122 })cpp");
123 }
124
TEST_F(DefineInlineTest,TemplateSpec)125 TEST_F(DefineInlineTest, TemplateSpec) {
126 EXPECT_UNAVAILABLE(R"cpp(
127 template <typename T> void foo();
128 template<> void foo<char>();
129
130 template<> void f^oo<int>() {
131 })cpp");
132 EXPECT_UNAVAILABLE(R"cpp(
133 template <typename T> void foo();
134
135 template<> void f^oo<int>() {
136 })cpp");
137 EXPECT_UNAVAILABLE(R"cpp(
138 template <typename T> struct Foo { void foo(); };
139
140 template <typename T> void Foo<T>::f^oo() {
141 })cpp");
142 EXPECT_AVAILABLE(R"cpp(
143 template <typename T> void foo();
144 void bar();
145 template <> void foo<int>();
146
147 template<> void f^oo<int>() {
148 bar();
149 })cpp");
150 EXPECT_UNAVAILABLE(R"cpp(
151 namespace bar {
152 template <typename T> void f^oo() {}
153 template void foo<int>();
154 })cpp");
155 }
156
TEST_F(DefineInlineTest,CheckForCanonDecl)157 TEST_F(DefineInlineTest, CheckForCanonDecl) {
158 EXPECT_UNAVAILABLE(R"cpp(
159 void foo();
160
161 void bar() {}
162 void f^oo() {
163 // This bar normally refers to the definition just above, but it is not
164 // visible from the forward declaration of foo.
165 bar();
166 })cpp");
167 // Make it available with a forward decl.
168 EXPECT_AVAILABLE(R"cpp(
169 void bar();
170 void foo();
171
172 void bar() {}
173 void f^oo() {
174 bar();
175 })cpp");
176 }
177
TEST_F(DefineInlineTest,UsingShadowDecls)178 TEST_F(DefineInlineTest, UsingShadowDecls) {
179 // Template body is not parsed until instantiation time on windows, which
180 // results in arbitrary failures as function body becomes NULL.
181 ExtraArgs.push_back("-fno-delayed-template-parsing");
182 EXPECT_UNAVAILABLE(R"cpp(
183 namespace ns1 { void foo(int); }
184 namespace ns2 { void foo(int*); }
185 template <typename T>
186 void bar();
187
188 using ns1::foo;
189 using ns2::foo;
190
191 template <typename T>
192 void b^ar() {
193 foo(T());
194 })cpp");
195 }
196
TEST_F(DefineInlineTest,TransformNestedNamespaces)197 TEST_F(DefineInlineTest, TransformNestedNamespaces) {
198 auto Test = R"cpp(
199 namespace a {
200 void bar();
201 namespace b {
202 void baz();
203 namespace c {
204 void aux();
205 }
206 }
207 }
208
209 void foo();
210 using namespace a;
211 using namespace b;
212 using namespace c;
213 void f^oo() {
214 bar();
215 a::bar();
216
217 baz();
218 b::baz();
219 a::b::baz();
220
221 aux();
222 c::aux();
223 b::c::aux();
224 a::b::c::aux();
225 })cpp";
226 auto Expected = R"cpp(
227 namespace a {
228 void bar();
229 namespace b {
230 void baz();
231 namespace c {
232 void aux();
233 }
234 }
235 }
236
237 void foo(){
238 a::bar();
239 a::bar();
240
241 a::b::baz();
242 a::b::baz();
243 a::b::baz();
244
245 a::b::c::aux();
246 a::b::c::aux();
247 a::b::c::aux();
248 a::b::c::aux();
249 }
250 using namespace a;
251 using namespace b;
252 using namespace c;
253 )cpp";
254 EXPECT_EQ(apply(Test), Expected);
255 }
256
TEST_F(DefineInlineTest,TransformUsings)257 TEST_F(DefineInlineTest, TransformUsings) {
258 auto Test = R"cpp(
259 namespace a { namespace b { namespace c { void aux(); } } }
260
261 void foo();
262 void f^oo() {
263 using namespace a;
264 using namespace b;
265 using namespace c;
266 using c::aux;
267 namespace d = c;
268 })cpp";
269 auto Expected = R"cpp(
270 namespace a { namespace b { namespace c { void aux(); } } }
271
272 void foo(){
273 using namespace a;
274 using namespace a::b;
275 using namespace a::b::c;
276 using a::b::c::aux;
277 namespace d = a::b::c;
278 }
279 )cpp";
280 EXPECT_EQ(apply(Test), Expected);
281 }
282
TEST_F(DefineInlineTest,TransformDecls)283 TEST_F(DefineInlineTest, TransformDecls) {
284 auto Test = R"cpp(
285 void foo();
286 void f^oo() {
287 class Foo {
288 public:
289 void foo();
290 int x;
291 };
292
293 enum En { Zero, One };
294 En x = Zero;
295
296 enum class EnClass { Zero, One };
297 EnClass y = EnClass::Zero;
298 })cpp";
299 auto Expected = R"cpp(
300 void foo(){
301 class Foo {
302 public:
303 void foo();
304 int x;
305 };
306
307 enum En { Zero, One };
308 En x = Zero;
309
310 enum class EnClass { Zero, One };
311 EnClass y = EnClass::Zero;
312 }
313 )cpp";
314 EXPECT_EQ(apply(Test), Expected);
315 }
316
TEST_F(DefineInlineTest,TransformTemplDecls)317 TEST_F(DefineInlineTest, TransformTemplDecls) {
318 auto Test = R"cpp(
319 namespace a {
320 template <typename T> class Bar {
321 public:
322 void bar();
323 };
324 template <typename T> T bar;
325 template <typename T> void aux() {}
326 }
327
328 void foo();
329
330 using namespace a;
331 void f^oo() {
332 bar<Bar<int>>.bar();
333 aux<Bar<int>>();
334 })cpp";
335 auto Expected = R"cpp(
336 namespace a {
337 template <typename T> class Bar {
338 public:
339 void bar();
340 };
341 template <typename T> T bar;
342 template <typename T> void aux() {}
343 }
344
345 void foo(){
346 a::bar<a::Bar<int>>.bar();
347 a::aux<a::Bar<int>>();
348 }
349
350 using namespace a;
351 )cpp";
352 EXPECT_EQ(apply(Test), Expected);
353 }
354
TEST_F(DefineInlineTest,TransformMembers)355 TEST_F(DefineInlineTest, TransformMembers) {
356 auto Test = R"cpp(
357 class Foo {
358 void foo();
359 };
360
361 void Foo::f^oo() {
362 return;
363 })cpp";
364 auto Expected = R"cpp(
365 class Foo {
366 void foo(){
367 return;
368 }
369 };
370
371 )cpp";
372 EXPECT_EQ(apply(Test), Expected);
373
374 ExtraFiles["a.h"] = R"cpp(
375 class Foo {
376 void foo();
377 };)cpp";
378
379 llvm::StringMap<std::string> EditedFiles;
380 Test = R"cpp(
381 #include "a.h"
382 void Foo::f^oo() {
383 return;
384 })cpp";
385 Expected = R"cpp(
386 #include "a.h"
387 )cpp";
388 EXPECT_EQ(apply(Test, &EditedFiles), Expected);
389
390 Expected = R"cpp(
391 class Foo {
392 void foo(){
393 return;
394 }
395 };)cpp";
396 EXPECT_THAT(EditedFiles,
397 ElementsAre(FileWithContents(testPath("a.h"), Expected)));
398 }
399
TEST_F(DefineInlineTest,TransformDependentTypes)400 TEST_F(DefineInlineTest, TransformDependentTypes) {
401 auto Test = R"cpp(
402 namespace a {
403 template <typename T> class Bar {};
404 }
405
406 template <typename T>
407 void foo();
408
409 using namespace a;
410 template <typename T>
411 void f^oo() {
412 Bar<T> B;
413 Bar<Bar<T>> q;
414 })cpp";
415 auto Expected = R"cpp(
416 namespace a {
417 template <typename T> class Bar {};
418 }
419
420 template <typename T>
421 void foo(){
422 a::Bar<T> B;
423 a::Bar<a::Bar<T>> q;
424 }
425
426 using namespace a;
427 )cpp";
428
429 // Template body is not parsed until instantiation time on windows, which
430 // results in arbitrary failures as function body becomes NULL.
431 ExtraArgs.push_back("-fno-delayed-template-parsing");
432 EXPECT_EQ(apply(Test), Expected);
433 }
434
TEST_F(DefineInlineTest,TransformFunctionTempls)435 TEST_F(DefineInlineTest, TransformFunctionTempls) {
436 // Check we select correct specialization decl.
437 std::pair<llvm::StringRef, llvm::StringRef> Cases[] = {
438 {R"cpp(
439 template <typename T>
440 void foo(T p);
441
442 template <>
443 void foo<int>(int p);
444
445 template <>
446 void foo<char>(char p);
447
448 template <>
449 void fo^o<int>(int p) {
450 return;
451 })cpp",
452 R"cpp(
453 template <typename T>
454 void foo(T p);
455
456 template <>
457 void foo<int>(int p){
458 return;
459 }
460
461 template <>
462 void foo<char>(char p);
463
464 )cpp"},
465 {// Make sure we are not selecting the first specialization all the time.
466 R"cpp(
467 template <typename T>
468 void foo(T p);
469
470 template <>
471 void foo<int>(int p);
472
473 template <>
474 void foo<char>(char p);
475
476 template <>
477 void fo^o<char>(char p) {
478 return;
479 })cpp",
480 R"cpp(
481 template <typename T>
482 void foo(T p);
483
484 template <>
485 void foo<int>(int p);
486
487 template <>
488 void foo<char>(char p){
489 return;
490 }
491
492 )cpp"},
493 {R"cpp(
494 template <typename T>
495 void foo(T p);
496
497 template <>
498 void foo<int>(int p);
499
500 template <typename T>
501 void fo^o(T p) {
502 return;
503 })cpp",
504 R"cpp(
505 template <typename T>
506 void foo(T p){
507 return;
508 }
509
510 template <>
511 void foo<int>(int p);
512
513 )cpp"},
514 };
515 // Template body is not parsed until instantiation time on windows, which
516 // results in arbitrary failures as function body becomes NULL.
517 ExtraArgs.push_back("-fno-delayed-template-parsing");
518 for (const auto &Case : Cases)
519 EXPECT_EQ(apply(Case.first), Case.second) << Case.first;
520 }
521
TEST_F(DefineInlineTest,TransformTypeLocs)522 TEST_F(DefineInlineTest, TransformTypeLocs) {
523 auto Test = R"cpp(
524 namespace a {
525 template <typename T> class Bar {
526 public:
527 template <typename Q> class Baz {};
528 };
529 class Foo{};
530 }
531
532 void foo();
533
534 using namespace a;
535 void f^oo() {
536 Bar<int> B;
537 Foo foo;
538 a::Bar<Bar<int>>::Baz<Bar<int>> q;
539 })cpp";
540 auto Expected = R"cpp(
541 namespace a {
542 template <typename T> class Bar {
543 public:
544 template <typename Q> class Baz {};
545 };
546 class Foo{};
547 }
548
549 void foo(){
550 a::Bar<int> B;
551 a::Foo foo;
552 a::Bar<a::Bar<int>>::Baz<a::Bar<int>> q;
553 }
554
555 using namespace a;
556 )cpp";
557 EXPECT_EQ(apply(Test), Expected);
558 }
559
TEST_F(DefineInlineTest,TransformDeclRefs)560 TEST_F(DefineInlineTest, TransformDeclRefs) {
561 auto Test = R"cpp(
562 namespace a {
563 template <typename T> class Bar {
564 public:
565 void foo();
566 static void bar();
567 int x;
568 static int y;
569 };
570 void bar();
571 void test();
572 }
573
574 void foo();
575 using namespace a;
576 void f^oo() {
577 a::Bar<int> B;
578 B.foo();
579 a::bar();
580 Bar<Bar<int>>::bar();
581 a::Bar<int>::bar();
582 B.x = Bar<int>::y;
583 Bar<int>::y = 3;
584 bar();
585 a::test();
586 })cpp";
587 auto Expected = R"cpp(
588 namespace a {
589 template <typename T> class Bar {
590 public:
591 void foo();
592 static void bar();
593 int x;
594 static int y;
595 };
596 void bar();
597 void test();
598 }
599
600 void foo(){
601 a::Bar<int> B;
602 B.foo();
603 a::bar();
604 a::Bar<a::Bar<int>>::bar();
605 a::Bar<int>::bar();
606 B.x = a::Bar<int>::y;
607 a::Bar<int>::y = 3;
608 a::bar();
609 a::test();
610 }
611 using namespace a;
612 )cpp";
613 EXPECT_EQ(apply(Test), Expected);
614 }
615
TEST_F(DefineInlineTest,StaticMembers)616 TEST_F(DefineInlineTest, StaticMembers) {
617 auto Test = R"cpp(
618 namespace ns { class X { static void foo(); void bar(); }; }
619 void ns::X::b^ar() {
620 foo();
621 })cpp";
622 auto Expected = R"cpp(
623 namespace ns { class X { static void foo(); void bar(){
624 foo();
625 } }; }
626 )cpp";
627 EXPECT_EQ(apply(Test), Expected);
628 }
629
TEST_F(DefineInlineTest,TransformParamNames)630 TEST_F(DefineInlineTest, TransformParamNames) {
631 std::pair<llvm::StringRef, llvm::StringRef> Cases[] = {
632 {R"cpp(
633 void foo(int, bool b, int T\
634 est);
635 void ^foo(int f, bool x, int z) {})cpp",
636 R"cpp(
637 void foo(int f, bool x, int z){}
638 )cpp"},
639 {R"cpp(
640 #define PARAM int Z
641 void foo(PARAM);
642
643 void ^foo(int X) {})cpp",
644 "fail: Cant rename parameter inside macro body."},
645 {R"cpp(
646 #define TYPE int
647 #define PARAM TYPE Z
648 #define BODY(x) 5 * (x) + 2
649 template <int P>
650 void foo(PARAM, TYPE Q, TYPE, TYPE W = BODY(P));
651 template <int x>
652 void ^foo(int Z, int b, int c, int d) {})cpp",
653 R"cpp(
654 #define TYPE int
655 #define PARAM TYPE Z
656 #define BODY(x) 5 * (x) + 2
657 template <int x>
658 void foo(PARAM, TYPE b, TYPE c, TYPE d = BODY(x)){}
659 )cpp"},
660 };
661 ExtraArgs.push_back("-fno-delayed-template-parsing");
662 for (const auto &Case : Cases)
663 EXPECT_EQ(apply(Case.first), Case.second) << Case.first;
664 }
665
TEST_F(DefineInlineTest,TransformTemplParamNames)666 TEST_F(DefineInlineTest, TransformTemplParamNames) {
667 auto Test = R"cpp(
668 struct Foo {
669 struct Bar {
670 template <class, class X,
671 template<typename> class, template<typename> class Y,
672 int, int Z>
673 void foo(X, Y<X>, int W = 5 * Z + 2);
674 };
675 };
676
677 template <class T, class U,
678 template<typename> class V, template<typename> class W,
679 int X, int Y>
680 void Foo::Bar::f^oo(U, W<U>, int Q) {})cpp";
681 auto Expected = R"cpp(
682 struct Foo {
683 struct Bar {
684 template <class T, class U,
685 template<typename> class V, template<typename> class W,
686 int X, int Y>
687 void foo(U, W<U>, int Q = 5 * Y + 2){}
688 };
689 };
690
691 )cpp";
692 ExtraArgs.push_back("-fno-delayed-template-parsing");
693 EXPECT_EQ(apply(Test), Expected);
694 }
695
TEST_F(DefineInlineTest,TransformInlineNamespaces)696 TEST_F(DefineInlineTest, TransformInlineNamespaces) {
697 auto Test = R"cpp(
698 namespace a { inline namespace b { namespace { struct Foo{}; } } }
699 void foo();
700
701 using namespace a;
702 void ^foo() {Foo foo;})cpp";
703 auto Expected = R"cpp(
704 namespace a { inline namespace b { namespace { struct Foo{}; } } }
705 void foo(){a::Foo foo;}
706
707 using namespace a;
708 )cpp";
709 EXPECT_EQ(apply(Test), Expected);
710 }
711
TEST_F(DefineInlineTest,TokensBeforeSemicolon)712 TEST_F(DefineInlineTest, TokensBeforeSemicolon) {
713 std::pair<llvm::StringRef, llvm::StringRef> Cases[] = {
714 {R"cpp(
715 void foo() /*Comment -_-*/ /*Com 2*/ ;
716 void fo^o() { return ; })cpp",
717 R"cpp(
718 void foo() /*Comment -_-*/ /*Com 2*/ { return ; }
719 )cpp"},
720
721 {R"cpp(
722 void foo();
723 void fo^o() { return ; })cpp",
724 R"cpp(
725 void foo(){ return ; }
726 )cpp"},
727
728 {R"cpp(
729 #define SEMI ;
730 void foo() SEMI
731 void fo^o() { return ; })cpp",
732 "fail: Couldn't find semicolon for target declaration."},
733 };
734 for (const auto &Case : Cases)
735 EXPECT_EQ(apply(Case.first), Case.second) << Case.first;
736 }
737
TEST_F(DefineInlineTest,HandleMacros)738 TEST_F(DefineInlineTest, HandleMacros) {
739 EXPECT_UNAVAILABLE(R"cpp(
740 #define BODY { return; }
741 void foo();
742 void f^oo()BODY)cpp");
743
744 EXPECT_UNAVAILABLE(R"cpp(
745 #define BODY void foo(){ return; }
746 void foo();
747 [[BODY]])cpp");
748
749 std::pair<llvm::StringRef, llvm::StringRef> Cases[] = {
750 // We don't qualify declarations coming from macros.
751 {R"cpp(
752 #define BODY Foo
753 namespace a { class Foo{}; }
754 void foo();
755 using namespace a;
756 void f^oo(){BODY();})cpp",
757 R"cpp(
758 #define BODY Foo
759 namespace a { class Foo{}; }
760 void foo(){BODY();}
761 using namespace a;
762 )cpp"},
763
764 // Macro is not visible at declaration location, but we proceed.
765 {R"cpp(
766 void foo();
767 #define BODY return;
768 void f^oo(){BODY})cpp",
769 R"cpp(
770 void foo(){BODY}
771 #define BODY return;
772 )cpp"},
773
774 {R"cpp(
775 #define TARGET void foo()
776 TARGET;
777 void f^oo(){ return; })cpp",
778 R"cpp(
779 #define TARGET void foo()
780 TARGET{ return; }
781 )cpp"},
782
783 {R"cpp(
784 #define TARGET foo
785 void TARGET();
786 void f^oo(){ return; })cpp",
787 R"cpp(
788 #define TARGET foo
789 void TARGET(){ return; }
790 )cpp"},
791 };
792 for (const auto &Case : Cases)
793 EXPECT_EQ(apply(Case.first), Case.second) << Case.first;
794 }
795
TEST_F(DefineInlineTest,DropCommonNameSpecifiers)796 TEST_F(DefineInlineTest, DropCommonNameSpecifiers) {
797 struct {
798 llvm::StringRef Test;
799 llvm::StringRef Expected;
800 } Cases[] = {
801 {R"cpp(
802 namespace a { namespace b { void aux(); } }
803 namespace ns1 {
804 void foo();
805 namespace qq { void test(); }
806 namespace ns2 {
807 void bar();
808 namespace ns3 { void baz(); }
809 }
810 }
811
812 using namespace a;
813 using namespace a::b;
814 using namespace ns1::qq;
815 void ns1::ns2::ns3::b^az() {
816 foo();
817 bar();
818 baz();
819 ns1::ns2::ns3::baz();
820 aux();
821 test();
822 })cpp",
823 R"cpp(
824 namespace a { namespace b { void aux(); } }
825 namespace ns1 {
826 void foo();
827 namespace qq { void test(); }
828 namespace ns2 {
829 void bar();
830 namespace ns3 { void baz(){
831 foo();
832 bar();
833 baz();
834 ns1::ns2::ns3::baz();
835 a::b::aux();
836 qq::test();
837 } }
838 }
839 }
840
841 using namespace a;
842 using namespace a::b;
843 using namespace ns1::qq;
844 )cpp"},
845 {R"cpp(
846 namespace ns1 {
847 namespace qq { struct Foo { struct Bar {}; }; using B = Foo::Bar; }
848 namespace ns2 { void baz(); }
849 }
850
851 using namespace ns1::qq;
852 void ns1::ns2::b^az() { Foo f; B b; })cpp",
853 R"cpp(
854 namespace ns1 {
855 namespace qq { struct Foo { struct Bar {}; }; using B = Foo::Bar; }
856 namespace ns2 { void baz(){ qq::Foo f; qq::B b; } }
857 }
858
859 using namespace ns1::qq;
860 )cpp"},
861 {R"cpp(
862 namespace ns1 {
863 namespace qq {
864 template<class T> struct Foo { template <class U> struct Bar {}; };
865 template<class T, class U>
866 using B = typename Foo<T>::template Bar<U>;
867 }
868 namespace ns2 { void baz(); }
869 }
870
871 using namespace ns1::qq;
872 void ns1::ns2::b^az() { B<int, bool> b; })cpp",
873 R"cpp(
874 namespace ns1 {
875 namespace qq {
876 template<class T> struct Foo { template <class U> struct Bar {}; };
877 template<class T, class U>
878 using B = typename Foo<T>::template Bar<U>;
879 }
880 namespace ns2 { void baz(){ qq::B<int, bool> b; } }
881 }
882
883 using namespace ns1::qq;
884 )cpp"},
885 };
886 for (const auto &Case : Cases)
887 EXPECT_EQ(apply(Case.Test), Case.Expected) << Case.Test;
888 }
889
TEST_F(DefineInlineTest,QualifyWithUsingDirectives)890 TEST_F(DefineInlineTest, QualifyWithUsingDirectives) {
891 llvm::StringRef Test = R"cpp(
892 namespace a {
893 void bar();
894 namespace b { struct Foo{}; void aux(); }
895 namespace c { void cux(); }
896 }
897 using namespace a;
898 using X = b::Foo;
899 void foo();
900
901 using namespace b;
902 using namespace c;
903 void ^foo() {
904 cux();
905 bar();
906 X x;
907 aux();
908 using namespace c;
909 // FIXME: The last reference to cux() in body of foo should not be
910 // qualified, since there is a using directive inside the function body.
911 cux();
912 })cpp";
913 llvm::StringRef Expected = R"cpp(
914 namespace a {
915 void bar();
916 namespace b { struct Foo{}; void aux(); }
917 namespace c { void cux(); }
918 }
919 using namespace a;
920 using X = b::Foo;
921 void foo(){
922 c::cux();
923 bar();
924 X x;
925 b::aux();
926 using namespace c;
927 // FIXME: The last reference to cux() in body of foo should not be
928 // qualified, since there is a using directive inside the function body.
929 c::cux();
930 }
931
932 using namespace b;
933 using namespace c;
934 )cpp";
935 EXPECT_EQ(apply(Test), Expected) << Test;
936 }
937
TEST_F(DefineInlineTest,AddInline)938 TEST_F(DefineInlineTest, AddInline) {
939 ExtraArgs.push_back("-fno-delayed-template-parsing");
940 llvm::StringMap<std::string> EditedFiles;
941 ExtraFiles["a.h"] = "void foo();";
942 apply(R"cpp(#include "a.h"
943 void fo^o() {})cpp",
944 &EditedFiles);
945 EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents(
946 testPath("a.h"), "inline void foo(){}")));
947
948 // Check we put inline before cv-qualifiers.
949 ExtraFiles["a.h"] = "const int foo();";
950 apply(R"cpp(#include "a.h"
951 const int fo^o() {})cpp",
952 &EditedFiles);
953 EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents(
954 testPath("a.h"), "inline const int foo(){}")));
955
956 // No double inline.
957 ExtraFiles["a.h"] = "inline void foo();";
958 apply(R"cpp(#include "a.h"
959 inline void fo^o() {})cpp",
960 &EditedFiles);
961 EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents(
962 testPath("a.h"), "inline void foo(){}")));
963
964 // Constexprs don't need "inline".
965 ExtraFiles["a.h"] = "constexpr void foo();";
966 apply(R"cpp(#include "a.h"
967 constexpr void fo^o() {})cpp",
968 &EditedFiles);
969 EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents(
970 testPath("a.h"), "constexpr void foo(){}")));
971
972 // Class members don't need "inline".
973 ExtraFiles["a.h"] = "struct Foo { void foo(); };";
974 apply(R"cpp(#include "a.h"
975 void Foo::fo^o() {})cpp",
976 &EditedFiles);
977 EXPECT_THAT(EditedFiles,
978 testing::ElementsAre(FileWithContents(
979 testPath("a.h"), "struct Foo { void foo(){} };")));
980
981 // Function template doesn't need to be "inline"d.
982 ExtraFiles["a.h"] = "template <typename T> void foo();";
983 apply(R"cpp(#include "a.h"
984 template <typename T>
985 void fo^o() {})cpp",
986 &EditedFiles);
987 EXPECT_THAT(EditedFiles,
988 testing::ElementsAre(FileWithContents(
989 testPath("a.h"), "template <typename T> void foo(){}")));
990
991 // Specializations needs to be marked "inline".
992 ExtraFiles["a.h"] = R"cpp(
993 template <typename T> void foo();
994 template <> void foo<int>();)cpp";
995 apply(R"cpp(#include "a.h"
996 template <>
997 void fo^o<int>() {})cpp",
998 &EditedFiles);
999 EXPECT_THAT(EditedFiles,
1000 testing::ElementsAre(FileWithContents(testPath("a.h"),
1001 R"cpp(
1002 template <typename T> void foo();
1003 template <> inline void foo<int>(){})cpp")));
1004 }
1005
1006 } // namespace
1007 } // namespace clangd
1008 } // namespace clang
1009