Mercurial > hg > CbC > CbC_llvm
comparison clang-tools-extra/clangd/unittests/FindTargetTests.cpp @ 221:79ff65ed7e25
LLVM12 Original
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 15 Jun 2021 19:15:29 +0900 |
parents | 0572611fdcc8 |
children | 5f17cb93ff66 |
comparison
equal
deleted
inserted
replaced
220:42394fc6a535 | 221:79ff65ed7e25 |
---|---|
84 return {}; | 84 return {}; |
85 } | 85 } |
86 EXPECT_EQ(N->kind(), NodeType) << Selection; | 86 EXPECT_EQ(N->kind(), NodeType) << Selection; |
87 | 87 |
88 std::vector<PrintedDecl> ActualDecls; | 88 std::vector<PrintedDecl> ActualDecls; |
89 for (const auto &Entry : allTargetDecls(N->ASTNode)) | 89 for (const auto &Entry : |
90 allTargetDecls(N->ASTNode, AST.getHeuristicResolver())) | |
90 ActualDecls.emplace_back(Entry.first, Entry.second); | 91 ActualDecls.emplace_back(Entry.first, Entry.second); |
91 return ActualDecls; | 92 return ActualDecls; |
92 } | 93 } |
93 }; | 94 }; |
94 | 95 |
146 } | 147 } |
147 )cpp"; | 148 )cpp"; |
148 EXPECT_DECLS("LabelStmt", "label:"); | 149 EXPECT_DECLS("LabelStmt", "label:"); |
149 } | 150 } |
150 | 151 |
152 TEST_F(TargetDeclTest, RecoveryForC) { | |
153 Flags = {"-xc", "-Xclang", "-frecovery-ast"}; | |
154 Code = R"cpp( | |
155 // error-ok: testing behavior on broken code | |
156 // int f(); | |
157 int f(int); | |
158 int x = [[f]](); | |
159 )cpp"; | |
160 EXPECT_DECLS("DeclRefExpr", "int f(int)"); | |
161 } | |
162 | |
151 TEST_F(TargetDeclTest, Recovery) { | 163 TEST_F(TargetDeclTest, Recovery) { |
152 Code = R"cpp( | 164 Code = R"cpp( |
153 // error-ok: testing behavior on broken code | 165 // error-ok: testing behavior on broken code |
154 int f(); | 166 int f(); |
155 int f(int, int); | 167 int f(int, int); |
179 } | 191 } |
180 using foo::f; | 192 using foo::f; |
181 int x = [[f]](42); | 193 int x = [[f]](42); |
182 )cpp"; | 194 )cpp"; |
183 // f(char) is not referenced! | 195 // f(char) is not referenced! |
184 EXPECT_DECLS("DeclRefExpr", {"using foo::f", Rel::Alias}, | 196 EXPECT_DECLS("DeclRefExpr", {"using foo::f", Rel::Alias}, {"int f(int)"}); |
185 {"int f(int)", Rel::Underlying}); | |
186 | 197 |
187 Code = R"cpp( | 198 Code = R"cpp( |
188 namespace foo { | 199 namespace foo { |
189 int f(int); | 200 int f(int); |
190 int f(char); | 201 int f(char); |
191 } | 202 } |
192 [[using foo::f]]; | 203 [[using foo::f]]; |
193 )cpp"; | 204 )cpp"; |
194 // All overloads are referenced. | 205 // All overloads are referenced. |
195 EXPECT_DECLS("UsingDecl", {"using foo::f", Rel::Alias}, | 206 EXPECT_DECLS("UsingDecl", {"using foo::f", Rel::Alias}, {"int f(int)"}, |
196 {"int f(int)", Rel::Underlying}, | 207 {"int f(char)"}); |
197 {"int f(char)", Rel::Underlying}); | |
198 | 208 |
199 Code = R"cpp( | 209 Code = R"cpp( |
200 struct X { | 210 struct X { |
201 int foo(); | 211 int foo(); |
202 }; | 212 }; |
203 struct Y : X { | 213 struct Y : X { |
204 using X::foo; | 214 using X::foo; |
205 }; | 215 }; |
206 int x = Y().[[foo]](); | 216 int x = Y().[[foo]](); |
207 )cpp"; | 217 )cpp"; |
208 EXPECT_DECLS("MemberExpr", {"using X::foo", Rel::Alias}, | 218 EXPECT_DECLS("MemberExpr", {"using X::foo", Rel::Alias}, {"int foo()"}); |
209 {"int foo()", Rel::Underlying}); | 219 |
220 Code = R"cpp( | |
221 template <typename T> | |
222 struct Base { | |
223 void waldo() {} | |
224 }; | |
225 template <typename T> | |
226 struct Derived : Base<T> { | |
227 using Base<T>::[[waldo]]; | |
228 }; | |
229 )cpp"; | |
230 EXPECT_DECLS("UnresolvedUsingValueDecl", {"using Base<T>::waldo", Rel::Alias}, | |
231 {"void waldo()"}); | |
232 } | |
233 | |
234 TEST_F(TargetDeclTest, BaseSpecifier) { | |
235 Code = R"cpp( | |
236 struct X {}; | |
237 struct Y : [[private]] X {}; | |
238 )cpp"; | |
239 EXPECT_DECLS("CXXBaseSpecifier", "struct X"); | |
240 Code = R"cpp( | |
241 struct X {}; | |
242 struct Y : [[private X]] {}; | |
243 )cpp"; | |
244 EXPECT_DECLS("CXXBaseSpecifier", "struct X"); | |
245 Code = R"cpp( | |
246 struct X {}; | |
247 struct Y : private [[X]] {}; | |
248 )cpp"; | |
249 EXPECT_DECLS("RecordTypeLoc", "struct X"); | |
210 } | 250 } |
211 | 251 |
212 TEST_F(TargetDeclTest, ConstructorInitList) { | 252 TEST_F(TargetDeclTest, ConstructorInitList) { |
213 Code = R"cpp( | 253 Code = R"cpp( |
214 struct X { | 254 struct X { |
285 [[X]] x; | 325 [[X]] x; |
286 )cpp"; | 326 )cpp"; |
287 EXPECT_DECLS("TypedefTypeLoc", {"typedef ns::S X", Rel::Alias}, | 327 EXPECT_DECLS("TypedefTypeLoc", {"typedef ns::S X", Rel::Alias}, |
288 {"struct S", Rel::Underlying}); | 328 {"struct S", Rel::Underlying}); |
289 | 329 |
290 // FIXME: Auto-completion in a template requires disabling delayed template | |
291 // parsing. | |
292 Flags = {"-fno-delayed-template-parsing"}; | |
293 Code = R"cpp( | 330 Code = R"cpp( |
294 template<class T> | 331 template<class T> |
295 void foo() { [[T]] x; } | 332 void foo() { [[T]] x; } |
296 )cpp"; | 333 )cpp"; |
297 EXPECT_DECLS("TemplateTypeParmTypeLoc", "class T"); | 334 EXPECT_DECLS("TemplateTypeParmTypeLoc", "class T"); |
298 Flags.clear(); | 335 Flags.clear(); |
299 | 336 |
300 // FIXME: Auto-completion in a template requires disabling delayed template | |
301 // parsing. | |
302 Flags = {"-fno-delayed-template-parsing"}; | |
303 Code = R"cpp( | 337 Code = R"cpp( |
304 template<template<typename> class T> | 338 template<template<typename> class T> |
305 void foo() { [[T<int>]] x; } | 339 void foo() { [[T<int>]] x; } |
306 )cpp"; | 340 )cpp"; |
307 EXPECT_DECLS("TemplateSpecializationTypeLoc", "template <typename> class T"); | 341 EXPECT_DECLS("TemplateSpecializationTypeLoc", "template <typename> class T"); |
373 [[Foo<int*>]] B; | 407 [[Foo<int*>]] B; |
374 )cpp"; | 408 )cpp"; |
375 EXPECT_DECLS("TemplateSpecializationTypeLoc", | 409 EXPECT_DECLS("TemplateSpecializationTypeLoc", |
376 {"template<> class Foo<int *>", Rel::TemplateInstantiation}, | 410 {"template<> class Foo<int *>", Rel::TemplateInstantiation}, |
377 {"template <typename T> class Foo<T *>", Rel::TemplatePattern}); | 411 {"template <typename T> class Foo<T *>", Rel::TemplatePattern}); |
412 | |
413 Code = R"cpp( | |
414 // Template template argument. | |
415 template<typename T> struct Vector {}; | |
416 template <template <typename> class Container> | |
417 struct A {}; | |
418 A<[[Vector]]> a; | |
419 )cpp"; | |
420 EXPECT_DECLS("TemplateArgumentLoc", {"template <typename T> struct Vector"}); | |
421 | |
422 Flags.push_back("-std=c++17"); // for CTAD tests | |
378 | 423 |
379 Code = R"cpp( | 424 Code = R"cpp( |
380 // Class template argument deduction | 425 // Class template argument deduction |
381 template <typename T> | 426 template <typename T> |
382 struct Test { | 427 struct Test { |
384 }; | 429 }; |
385 void foo() { | 430 void foo() { |
386 [[Test]] a(5); | 431 [[Test]] a(5); |
387 } | 432 } |
388 )cpp"; | 433 )cpp"; |
389 Flags.push_back("-std=c++17"); | |
390 EXPECT_DECLS("DeducedTemplateSpecializationTypeLoc", | 434 EXPECT_DECLS("DeducedTemplateSpecializationTypeLoc", |
391 {"struct Test", Rel::TemplatePattern}); | 435 {"struct Test", Rel::TemplatePattern}); |
436 | |
437 Code = R"cpp( | |
438 // Deduction guide | |
439 template <typename T> | |
440 struct Test { | |
441 template <typename I> | |
442 Test(I, I); | |
443 }; | |
444 template <typename I> | |
445 [[Test]](I, I) -> Test<typename I::type>; | |
446 )cpp"; | |
447 EXPECT_DECLS("CXXDeductionGuideDecl", {"template <typename T> struct Test"}); | |
392 } | 448 } |
393 | 449 |
394 TEST_F(TargetDeclTest, Concept) { | 450 TEST_F(TargetDeclTest, Concept) { |
451 Flags.push_back("-std=c++20"); | |
452 | |
453 // FIXME: Should we truncate the pretty-printed form of a concept decl | |
454 // somewhere? | |
455 | |
395 Code = R"cpp( | 456 Code = R"cpp( |
396 template <typename T> | 457 template <typename T> |
397 concept Fooable = requires (T t) { t.foo(); }; | 458 concept Fooable = requires (T t) { t.foo(); }; |
398 | 459 |
399 template <typename T> requires [[Fooable]]<T> | 460 template <typename T> requires [[Fooable]]<T> |
400 void bar(T t) { | 461 void bar(T t) { |
401 t.foo(); | 462 t.foo(); |
402 } | 463 } |
403 )cpp"; | 464 )cpp"; |
404 Flags.push_back("-std=c++2a"); | |
405 EXPECT_DECLS( | 465 EXPECT_DECLS( |
406 "ConceptSpecializationExpr", | 466 "ConceptSpecializationExpr", |
407 // FIXME: Should we truncate the pretty-printed form of a concept decl | |
408 // somewhere? | |
409 {"template <typename T> concept Fooable = requires (T t) { t.foo(); };"}); | 467 {"template <typename T> concept Fooable = requires (T t) { t.foo(); };"}); |
468 | |
469 // trailing requires clause | |
470 Code = R"cpp( | |
471 template <typename T> | |
472 concept Fooable = true; | |
473 | |
474 template <typename T> | |
475 void foo() requires [[Fooable]]<T>; | |
476 )cpp"; | |
477 EXPECT_DECLS("ConceptSpecializationExpr", | |
478 {"template <typename T> concept Fooable = true;"}); | |
479 | |
480 // constrained-parameter | |
481 Code = R"cpp( | |
482 template <typename T> | |
483 concept Fooable = true; | |
484 | |
485 template <[[Fooable]] T> | |
486 void bar(T t); | |
487 )cpp"; | |
488 EXPECT_DECLS("ConceptSpecializationExpr", | |
489 {"template <typename T> concept Fooable = true;"}); | |
490 | |
491 // partial-concept-id | |
492 Code = R"cpp( | |
493 template <typename T, typename U> | |
494 concept Fooable = true; | |
495 | |
496 template <[[Fooable]]<int> T> | |
497 void bar(T t); | |
498 )cpp"; | |
499 EXPECT_DECLS("ConceptSpecializationExpr", | |
500 {"template <typename T, typename U> concept Fooable = true;"}); | |
410 } | 501 } |
411 | 502 |
412 TEST_F(TargetDeclTest, FunctionTemplate) { | 503 TEST_F(TargetDeclTest, FunctionTemplate) { |
413 Code = R"cpp( | 504 Code = R"cpp( |
414 // Implicit specialization. | 505 // Implicit specialization. |
517 // FIXME: why both auto and int? | 608 // FIXME: why both auto and int? |
518 EXPECT_DECLS("DeclRefExpr", "auto int x = 1"); | 609 EXPECT_DECLS("DeclRefExpr", "auto int x = 1"); |
519 } | 610 } |
520 | 611 |
521 TEST_F(TargetDeclTest, OverloadExpr) { | 612 TEST_F(TargetDeclTest, OverloadExpr) { |
522 // FIXME: Auto-completion in a template requires disabling delayed template | 613 Flags.push_back("--target=x86_64-pc-linux-gnu"); |
523 // parsing. | |
524 Flags = {"-fno-delayed-template-parsing"}; | |
525 | 614 |
526 Code = R"cpp( | 615 Code = R"cpp( |
527 void func(int*); | 616 void func(int*); |
528 void func(char*); | 617 void func(char*); |
529 | 618 |
544 void foo(X x, T t) { | 633 void foo(X x, T t) { |
545 x.[[func]](t); | 634 x.[[func]](t); |
546 }; | 635 }; |
547 )cpp"; | 636 )cpp"; |
548 EXPECT_DECLS("UnresolvedMemberExpr", "void func(int *)", "void func(char *)"); | 637 EXPECT_DECLS("UnresolvedMemberExpr", "void func(int *)", "void func(char *)"); |
638 | |
639 Code = R"cpp( | |
640 struct X { | |
641 static void *operator new(unsigned long); | |
642 }; | |
643 auto* k = [[new]] X(); | |
644 )cpp"; | |
645 EXPECT_DECLS("CXXNewExpr", "static void *operator new(unsigned long)"); | |
646 Code = R"cpp( | |
647 void *operator new(unsigned long); | |
648 auto* k = [[new]] int(); | |
649 )cpp"; | |
650 EXPECT_DECLS("CXXNewExpr", "void *operator new(unsigned long)"); | |
651 | |
652 Code = R"cpp( | |
653 struct X { | |
654 static void operator delete(void *) noexcept; | |
655 }; | |
656 void k(X* x) { | |
657 [[delete]] x; | |
658 } | |
659 )cpp"; | |
660 EXPECT_DECLS("CXXDeleteExpr", "static void operator delete(void *) noexcept"); | |
661 Code = R"cpp( | |
662 void operator delete(void *) noexcept; | |
663 void k(int* x) { | |
664 [[delete]] x; | |
665 } | |
666 )cpp"; | |
667 EXPECT_DECLS("CXXDeleteExpr", "void operator delete(void *) noexcept"); | |
668 } | |
669 | |
670 TEST_F(TargetDeclTest, DependentExprs) { | |
671 // Heuristic resolution of method of dependent field | |
672 Code = R"cpp( | |
673 struct A { void foo() {} }; | |
674 template <typename T> | |
675 struct B { | |
676 A a; | |
677 void bar() { | |
678 this->a.[[foo]](); | |
679 } | |
680 }; | |
681 )cpp"; | |
682 EXPECT_DECLS("CXXDependentScopeMemberExpr", "void foo()"); | |
683 | |
684 // Similar to above but base expression involves a function call. | |
685 Code = R"cpp( | |
686 struct A { | |
687 void foo() {} | |
688 }; | |
689 struct B { | |
690 A getA(); | |
691 }; | |
692 template <typename T> | |
693 struct C { | |
694 B c; | |
695 void bar() { | |
696 this->c.getA().[[foo]](); | |
697 } | |
698 }; | |
699 )cpp"; | |
700 EXPECT_DECLS("CXXDependentScopeMemberExpr", "void foo()"); | |
701 | |
702 // Similar to above but uses a function pointer. | |
703 Code = R"cpp( | |
704 struct A { | |
705 void foo() {} | |
706 }; | |
707 struct B { | |
708 using FPtr = A(*)(); | |
709 FPtr fptr; | |
710 }; | |
711 template <typename T> | |
712 struct C { | |
713 B c; | |
714 void bar() { | |
715 this->c.fptr().[[foo]](); | |
716 } | |
717 }; | |
718 )cpp"; | |
719 EXPECT_DECLS("CXXDependentScopeMemberExpr", "void foo()"); | |
720 | |
721 // Base expression involves a member access into this. | |
722 Code = R"cpp( | |
723 struct Bar { | |
724 int aaaa; | |
725 }; | |
726 template <typename T> struct Foo { | |
727 Bar func(int); | |
728 void test() { | |
729 func(1).[[aaaa]]; | |
730 } | |
731 }; | |
732 )cpp"; | |
733 EXPECT_DECLS("CXXDependentScopeMemberExpr", "int aaaa"); | |
734 | |
735 Code = R"cpp( | |
736 class Foo { | |
737 public: | |
738 static Foo k(int); | |
739 template <typename T> T convert() const; | |
740 }; | |
741 template <typename T> | |
742 void test() { | |
743 Foo::k(T()).template [[convert]]<T>(); | |
744 } | |
745 )cpp"; | |
746 EXPECT_DECLS("CXXDependentScopeMemberExpr", | |
747 "template <typename T> T convert() const"); | |
748 } | |
749 | |
750 TEST_F(TargetDeclTest, DependentTypes) { | |
751 // Heuristic resolution of dependent type name | |
752 Code = R"cpp( | |
753 template <typename> | |
754 struct A { struct B {}; }; | |
755 | |
756 template <typename T> | |
757 void foo(typename A<T>::[[B]]); | |
758 )cpp"; | |
759 EXPECT_DECLS("DependentNameTypeLoc", "struct B"); | |
760 | |
761 // Heuristic resolution of dependent type name which doesn't get a TypeLoc | |
762 Code = R"cpp( | |
763 template <typename> | |
764 struct A { struct B { struct C {}; }; }; | |
765 | |
766 template <typename T> | |
767 void foo(typename A<T>::[[B]]::C); | |
768 )cpp"; | |
769 EXPECT_DECLS("NestedNameSpecifierLoc", "struct B"); | |
770 | |
771 // Heuristic resolution of dependent type name whose qualifier is also | |
772 // dependent | |
773 Code = R"cpp( | |
774 template <typename> | |
775 struct A { struct B { struct C {}; }; }; | |
776 | |
777 template <typename T> | |
778 void foo(typename A<T>::B::[[C]]); | |
779 )cpp"; | |
780 EXPECT_DECLS("DependentNameTypeLoc", "struct C"); | |
781 | |
782 // Heuristic resolution of dependent template name | |
783 Code = R"cpp( | |
784 template <typename> | |
785 struct A { | |
786 template <typename> struct B {}; | |
787 }; | |
788 | |
789 template <typename T> | |
790 void foo(typename A<T>::template [[B]]<int>); | |
791 )cpp"; | |
792 EXPECT_DECLS("DependentTemplateSpecializationTypeLoc", | |
793 "template <typename> struct B"); | |
794 } | |
795 | |
796 TEST_F(TargetDeclTest, TypedefCascade) { | |
797 Code = R"cpp( | |
798 struct C { | |
799 using type = int; | |
800 }; | |
801 struct B { | |
802 using type = C::type; | |
803 }; | |
804 struct A { | |
805 using type = B::type; | |
806 }; | |
807 A::[[type]] waldo; | |
808 )cpp"; | |
809 EXPECT_DECLS("TypedefTypeLoc", | |
810 {"using type = int", Rel::Alias | Rel::Underlying}, | |
811 {"using type = C::type", Rel::Alias | Rel::Underlying}, | |
812 {"using type = B::type", Rel::Alias}); | |
813 } | |
814 | |
815 TEST_F(TargetDeclTest, RecursiveTemplate) { | |
816 Flags.push_back("-std=c++20"); // the test case uses concepts | |
817 | |
818 Code = R"cpp( | |
819 template <typename T> | |
820 concept Leaf = false; | |
821 | |
822 template <typename Tree> | |
823 struct descend_left { | |
824 using type = typename descend_left<typename Tree::left>::[[type]]; | |
825 }; | |
826 | |
827 template <Leaf Tree> | |
828 struct descend_left<Tree> { | |
829 using type = typename Tree::value; | |
830 }; | |
831 )cpp"; | |
832 EXPECT_DECLS("DependentNameTypeLoc", | |
833 {"using type = typename descend_left<typename Tree::left>::type", | |
834 Rel::Alias | Rel::Underlying}); | |
549 } | 835 } |
550 | 836 |
551 TEST_F(TargetDeclTest, ObjC) { | 837 TEST_F(TargetDeclTest, ObjC) { |
552 Flags = {"-xobjective-c"}; | 838 Flags = {"-xobjective-c"}; |
553 Code = R"cpp( | 839 Code = R"cpp( |
591 )cpp"; | 877 )cpp"; |
592 EXPECT_DECLS("ObjCPropertyRefExpr", | 878 EXPECT_DECLS("ObjCPropertyRefExpr", |
593 "@property(atomic, retain, readwrite) I *x"); | 879 "@property(atomic, retain, readwrite) I *x"); |
594 | 880 |
595 Code = R"cpp( | 881 Code = R"cpp( |
882 @interface MYObject | |
883 @end | |
884 @interface Interface | |
885 @property(retain) [[MYObject]] *x; | |
886 @end | |
887 )cpp"; | |
888 EXPECT_DECLS("ObjCInterfaceTypeLoc", "@interface MYObject"); | |
889 | |
890 Code = R"cpp( | |
891 @interface MYObject2 | |
892 @end | |
893 @interface Interface | |
894 @property(retain, nonnull) [[MYObject2]] *x; | |
895 @end | |
896 )cpp"; | |
897 EXPECT_DECLS("ObjCInterfaceTypeLoc", "@interface MYObject2"); | |
898 | |
899 Code = R"cpp( | |
596 @protocol Foo | 900 @protocol Foo |
597 @end | 901 @end |
598 id test() { | 902 id test() { |
599 return [[@protocol(Foo)]]; | 903 return [[@protocol(Foo)]]; |
600 } | 904 } |
606 @end | 910 @end |
607 void test([[Foo]] *p); | 911 void test([[Foo]] *p); |
608 )cpp"; | 912 )cpp"; |
609 EXPECT_DECLS("ObjCInterfaceTypeLoc", "@interface Foo"); | 913 EXPECT_DECLS("ObjCInterfaceTypeLoc", "@interface Foo"); |
610 | 914 |
915 Code = R"cpp(// Don't consider implicit interface as the target. | |
916 @implementation [[Implicit]] | |
917 @end | |
918 )cpp"; | |
919 EXPECT_DECLS("ObjCImplementationDecl", "@implementation Implicit"); | |
920 | |
921 Code = R"cpp( | |
922 @interface Foo | |
923 @end | |
924 @implementation [[Foo]] | |
925 @end | |
926 )cpp"; | |
927 EXPECT_DECLS("ObjCImplementationDecl", "@interface Foo"); | |
928 | |
929 Code = R"cpp( | |
930 @interface Foo | |
931 @end | |
932 @interface Foo (Ext) | |
933 @end | |
934 @implementation [[Foo]] (Ext) | |
935 @end | |
936 )cpp"; | |
937 EXPECT_DECLS("ObjCCategoryImplDecl", "@interface Foo(Ext)"); | |
938 | |
611 Code = R"cpp( | 939 Code = R"cpp( |
612 @protocol Foo | 940 @protocol Foo |
613 @end | 941 @end |
614 void test([[id<Foo>]] p); | 942 void test([[id<Foo>]] p); |
615 )cpp"; | 943 )cpp"; |
617 | 945 |
618 Code = R"cpp( | 946 Code = R"cpp( |
619 @class C; | 947 @class C; |
620 @protocol Foo | 948 @protocol Foo |
621 @end | 949 @end |
950 void test([[C]]<Foo> *p); | |
951 )cpp"; | |
952 EXPECT_DECLS("ObjCInterfaceTypeLoc", "@class C;"); | |
953 | |
954 Code = R"cpp( | |
955 @class C; | |
956 @protocol Foo | |
957 @end | |
622 void test(C<[[Foo]]> *p); | 958 void test(C<[[Foo]]> *p); |
623 )cpp"; | 959 )cpp"; |
624 // FIXME: there's no AST node corresponding to 'Foo', so we're stuck. | 960 EXPECT_DECLS("ObjCObjectTypeLoc", "@protocol Foo"); |
625 EXPECT_DECLS("ObjCObjectTypeLoc"); | 961 |
962 Code = R"cpp( | |
963 @class C; | |
964 @protocol Foo | |
965 @end | |
966 @protocol Bar | |
967 @end | |
968 void test(C<[[Foo]], Bar> *p); | |
969 )cpp"; | |
970 // FIXME: We currently can't disambiguate between multiple protocols. | |
971 EXPECT_DECLS("ObjCObjectTypeLoc", "@protocol Foo", "@protocol Bar"); | |
972 | |
973 Code = R"cpp( | |
974 @interface Foo | |
975 + (id)sharedInstance; | |
976 @end | |
977 @implementation Foo | |
978 + (id)sharedInstance { return 0; } | |
979 @end | |
980 void test() { | |
981 id value = [[Foo]].sharedInstance; | |
982 } | |
983 )cpp"; | |
984 EXPECT_DECLS("ObjCInterfaceTypeLoc", "@interface Foo"); | |
985 | |
986 Code = R"cpp( | |
987 @interface Foo | |
988 + (id)sharedInstance; | |
989 @end | |
990 @implementation Foo | |
991 + (id)sharedInstance { return 0; } | |
992 @end | |
993 void test() { | |
994 id value = Foo.[[sharedInstance]]; | |
995 } | |
996 )cpp"; | |
997 EXPECT_DECLS("ObjCPropertyRefExpr", "+ (id)sharedInstance"); | |
626 } | 998 } |
627 | 999 |
628 class FindExplicitReferencesTest : public ::testing::Test { | 1000 class FindExplicitReferencesTest : public ::testing::Test { |
629 protected: | 1001 protected: |
630 struct AllRefs { | 1002 struct AllRefs { |
639 TestTU TU; | 1011 TestTU TU; |
640 TU.Code = std::string(Code); | 1012 TU.Code = std::string(Code); |
641 | 1013 |
642 // FIXME: Auto-completion in a template requires disabling delayed template | 1014 // FIXME: Auto-completion in a template requires disabling delayed template |
643 // parsing. | 1015 // parsing. |
644 TU.ExtraArgs.push_back("-fno-delayed-template-parsing"); | 1016 TU.ExtraArgs.push_back("-std=c++20"); |
645 TU.ExtraArgs.push_back("-std=c++2a"); | |
646 TU.ExtraArgs.push_back("-xobjective-c++"); | 1017 TU.ExtraArgs.push_back("-xobjective-c++"); |
647 | 1018 |
648 auto AST = TU.build(); | 1019 auto AST = TU.build(); |
649 auto *TestDecl = &findDecl(AST, "foo"); | 1020 auto *TestDecl = &findDecl(AST, "foo"); |
650 if (auto *T = llvm::dyn_cast<FunctionTemplateDecl>(TestDecl)) | 1021 if (auto *T = llvm::dyn_cast<FunctionTemplateDecl>(TestDecl)) |
651 TestDecl = T->getTemplatedDecl(); | 1022 TestDecl = T->getTemplatedDecl(); |
652 | 1023 |
653 std::vector<ReferenceLoc> Refs; | 1024 std::vector<ReferenceLoc> Refs; |
654 if (const auto *Func = llvm::dyn_cast<FunctionDecl>(TestDecl)) | 1025 if (const auto *Func = llvm::dyn_cast<FunctionDecl>(TestDecl)) |
655 findExplicitReferences(Func->getBody(), [&Refs](ReferenceLoc R) { | 1026 findExplicitReferences( |
656 Refs.push_back(std::move(R)); | 1027 Func->getBody(), |
657 }); | 1028 [&Refs](ReferenceLoc R) { Refs.push_back(std::move(R)); }, |
1029 AST.getHeuristicResolver()); | |
658 else if (const auto *NS = llvm::dyn_cast<NamespaceDecl>(TestDecl)) | 1030 else if (const auto *NS = llvm::dyn_cast<NamespaceDecl>(TestDecl)) |
659 findExplicitReferences(NS, [&Refs, &NS](ReferenceLoc R) { | 1031 findExplicitReferences( |
660 // Avoid adding the namespace foo decl to the results. | 1032 NS, |
661 if (R.Targets.size() == 1 && R.Targets.front() == NS) | 1033 [&Refs, &NS](ReferenceLoc R) { |
662 return; | 1034 // Avoid adding the namespace foo decl to the results. |
663 Refs.push_back(std::move(R)); | 1035 if (R.Targets.size() == 1 && R.Targets.front() == NS) |
664 }); | 1036 return; |
1037 Refs.push_back(std::move(R)); | |
1038 }, | |
1039 AST.getHeuristicResolver()); | |
665 else | 1040 else |
666 ADD_FAILURE() << "Failed to find ::foo decl for test"; | 1041 ADD_FAILURE() << "Failed to find ::foo decl for test"; |
667 | 1042 |
668 auto &SM = AST.getSourceManager(); | 1043 auto &SM = AST.getSourceManager(); |
669 llvm::sort(Refs, [&](const ReferenceLoc &L, const ReferenceLoc &R) { | 1044 llvm::sort(Refs, [&](const ReferenceLoc &L, const ReferenceLoc &R) { |
790 void foo() { | 1165 void foo() { |
791 $0^ten: // PRINT "HELLO WORLD!" | 1166 $0^ten: // PRINT "HELLO WORLD!" |
792 goto $1^ten; | 1167 goto $1^ten; |
793 } | 1168 } |
794 )cpp", | 1169 )cpp", |
795 "0: targets = {ten}, decl\n" | 1170 "0: targets = {ten}, decl\n" |
796 "1: targets = {ten}\n"}, | 1171 "1: targets = {ten}\n"}, |
797 // Simple templates. | 1172 // Simple templates. |
798 {R"cpp( | 1173 {R"cpp( |
799 template <class T> struct vector { using value_type = T; }; | 1174 template <class T> struct vector { using value_type = T; }; |
800 template <> struct vector<bool> { using value_type = bool; }; | 1175 template <> struct vector<bool> { using value_type = bool; }; |
801 void foo() { | 1176 void foo() { |
1229 "3: targets = {foo::bar}, decl\n" | 1604 "3: targets = {foo::bar}, decl\n" |
1230 "4: targets = {T}\n" | 1605 "4: targets = {T}\n" |
1231 "5: targets = {t}, decl\n" | 1606 "5: targets = {t}, decl\n" |
1232 "6: targets = {t}\n" | 1607 "6: targets = {t}\n" |
1233 "7: targets = {}\n"}, | 1608 "7: targets = {}\n"}, |
1609 // Objective-C: instance variables | |
1610 { | |
1611 R"cpp( | |
1612 @interface I { | |
1613 @public | |
1614 I *_z; | |
1615 } | |
1616 @end | |
1617 I *f; | |
1618 void foo() { | |
1619 $0^f->$1^_z = 0; | |
1620 } | |
1621 )cpp", | |
1622 "0: targets = {f}\n" | |
1623 "1: targets = {I::_z}\n"}, | |
1234 // Objective-C: properties | 1624 // Objective-C: properties |
1235 { | 1625 { |
1236 R"cpp( | 1626 R"cpp( |
1237 @interface I {} | 1627 @interface I {} |
1238 @property(retain) I* x; | 1628 @property(retain) I* x; |
1259 } | 1649 } |
1260 )cpp", | 1650 )cpp", |
1261 "0: targets = {f}\n" | 1651 "0: targets = {f}\n" |
1262 "1: targets = {I::x}\n" | 1652 "1: targets = {I::x}\n" |
1263 "2: targets = {I::setY:}\n"}, | 1653 "2: targets = {I::setY:}\n"}, |
1654 // Objective-C: class properties | |
1655 { | |
1656 R"cpp( | |
1657 @interface I {} | |
1658 @property(class) I *x; | |
1659 @end | |
1660 id local; | |
1661 void foo() { | |
1662 $0^I.$1^x = 0; | |
1663 $2^local = $3^I.$4^x; | |
1664 } | |
1665 )cpp", | |
1666 "0: targets = {I}\n" | |
1667 "1: targets = {I::setX:}\n" | |
1668 "2: targets = {local}\n" | |
1669 "3: targets = {I}\n" | |
1670 "4: targets = {I::x}\n"}, | |
1671 // Objective-C: implicit class properties | |
1672 { | |
1673 R"cpp( | |
1674 @interface I {} | |
1675 +(I*)x; | |
1676 +(void)setX:(I*)x; | |
1677 @end | |
1678 id local; | |
1679 void foo() { | |
1680 $0^I.$1^x = 0; | |
1681 $2^local = $3^I.$4^x; | |
1682 } | |
1683 )cpp", | |
1684 "0: targets = {I}\n" | |
1685 "1: targets = {I::setX:}\n" | |
1686 "2: targets = {local}\n" | |
1687 "3: targets = {I}\n" | |
1688 "4: targets = {I::x}\n"}, | |
1689 {// Objective-C: methods | |
1690 R"cpp( | |
1691 @interface I | |
1692 -(void) a:(int)x b:(int)y; | |
1693 @end | |
1694 void foo(I *i) { | |
1695 [$0^i $1^a:1 b:2]; | |
1696 } | |
1697 )cpp", | |
1698 "0: targets = {i}\n" | |
1699 "1: targets = {I::a:b:}\n"}, | |
1700 {// Objective-C: protocols | |
1701 R"cpp( | |
1702 @interface I | |
1703 @end | |
1704 @protocol P | |
1705 @end | |
1706 void foo() { | |
1707 $0^I<$1^P> *$2^x; | |
1708 } | |
1709 )cpp", | |
1710 "0: targets = {I}\n" | |
1711 "1: targets = {P}\n" | |
1712 "2: targets = {x}, decl\n"}, | |
1713 | |
1264 // Designated initializers. | 1714 // Designated initializers. |
1265 {R"cpp( | 1715 {R"cpp( |
1266 void foo() { | 1716 void foo() { |
1267 struct $0^Foo { | 1717 struct $0^Foo { |
1268 int $1^Bar; | 1718 int $1^Bar; |
1293 "4: targets = {foo()::Bar::Foo}, decl\n" | 1743 "4: targets = {foo()::Bar::Foo}, decl\n" |
1294 "5: targets = {Bar}\n" | 1744 "5: targets = {Bar}\n" |
1295 "6: targets = {bar}, decl\n" | 1745 "6: targets = {bar}, decl\n" |
1296 "7: targets = {foo()::Bar::Foo}\n" | 1746 "7: targets = {foo()::Bar::Foo}\n" |
1297 "8: targets = {foo()::Baz::Field}\n"}, | 1747 "8: targets = {foo()::Baz::Field}\n"}, |
1298 {R"cpp( | 1748 {R"cpp( |
1299 template<typename T> | 1749 template<typename T> |
1300 void crash(T); | 1750 void crash(T); |
1301 template<typename T> | 1751 template<typename T> |
1302 void foo() { | 1752 void foo() { |
1303 $0^crash({.$1^x = $2^T()}); | 1753 $0^crash({.$1^x = $2^T()}); |
1304 } | 1754 } |
1305 )cpp", | 1755 )cpp", |
1306 "0: targets = {crash}\n" | 1756 "0: targets = {crash}\n" |
1307 "1: targets = {}\n" | 1757 "1: targets = {}\n" |
1308 "2: targets = {T}\n" | 1758 "2: targets = {T}\n"}, |
1309 }, | 1759 // unknown template name should not crash. |
1310 // unknown template name should not crash. | 1760 {R"cpp( |
1311 {R"cpp( | |
1312 template <template <typename> typename T> | 1761 template <template <typename> typename T> |
1313 struct Base {}; | 1762 struct Base {}; |
1314 namespace foo { | 1763 namespace foo { |
1315 template <typename $0^T> | 1764 template <typename $0^T> |
1316 struct $1^Derive : $2^Base<$3^T::template $4^Unknown> {}; | 1765 struct $1^Derive : $2^Base<$3^T::template $4^Unknown> {}; |
1317 } | 1766 } |
1318 )cpp", | 1767 )cpp", |
1319 "0: targets = {foo::Derive::T}, decl\n" | 1768 "0: targets = {foo::Derive::T}, decl\n" |
1320 "1: targets = {foo::Derive}, decl\n" | 1769 "1: targets = {foo::Derive}, decl\n" |
1321 "2: targets = {Base}\n" | 1770 "2: targets = {Base}\n" |
1322 "3: targets = {foo::Derive::T}\n" | 1771 "3: targets = {foo::Derive::T}\n" |
1323 "4: targets = {}, qualifier = 'T::'\n"}, | 1772 "4: targets = {}, qualifier = 'T::'\n"}, |
1324 }; | 1773 // deduction guide |
1774 {R"cpp( | |
1775 namespace foo { | |
1776 template <typename $0^T> | |
1777 struct $1^Test { | |
1778 template <typename $2^I> | |
1779 $3^Test($4^I); | |
1780 }; | |
1781 template <typename $5^I> | |
1782 $6^Test($7^I) -> $8^Test<typename $9^I::$10^type>; | |
1783 } | |
1784 )cpp", | |
1785 "0: targets = {T}, decl\n" | |
1786 "1: targets = {foo::Test}, decl\n" | |
1787 "2: targets = {I}, decl\n" | |
1788 "3: targets = {foo::Test::Test<T>}, decl\n" | |
1789 "4: targets = {I}\n" | |
1790 "5: targets = {I}, decl\n" | |
1791 "6: targets = {foo::Test}\n" | |
1792 "7: targets = {I}\n" | |
1793 "8: targets = {foo::Test}\n" | |
1794 "9: targets = {I}\n" | |
1795 "10: targets = {}, qualifier = 'I::'\n"}}; | |
1325 | 1796 |
1326 for (const auto &C : Cases) { | 1797 for (const auto &C : Cases) { |
1327 llvm::StringRef ExpectedCode = C.first; | 1798 llvm::StringRef ExpectedCode = C.first; |
1328 llvm::StringRef ExpectedRefs = C.second; | 1799 llvm::StringRef ExpectedRefs = C.second; |
1329 | 1800 |