1 //===-- FindTargetTests.cpp --------------------------*- C++ -*------------===//
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
7 //===----------------------------------------------------------------------===//
8 #include "FindTarget.h"
10 #include "Selection.h"
12 #include "clang/AST/Decl.h"
13 #include "clang/AST/DeclTemplate.h"
14 #include "clang/Basic/SourceLocation.h"
15 #include "llvm/ADT/StringRef.h"
16 #include "llvm/Support/Casting.h"
17 #include "llvm/Support/raw_ostream.h"
18 #include "llvm/Testing/Annotations/Annotations.h"
19 #include "gmock/gmock.h"
20 #include "gtest/gtest.h"
21 #include <initializer_list>
27 // A referenced Decl together with its DeclRelationSet, for assertions.
29 // There's no great way to assert on the "content" of a Decl in the general case
30 // that's both expressive and unambiguous (e.g. clearly distinguishes between
31 // templated decls and their specializations).
33 // We use the result of pretty-printing the decl, with the {body} truncated.
35 PrintedDecl(const char *Name
, DeclRelationSet Relations
= {})
36 : Name(Name
), Relations(Relations
) {}
37 PrintedDecl(const NamedDecl
*D
, DeclRelationSet Relations
= {})
38 : Relations(Relations
) {
40 llvm::raw_string_ostream
OS(S
);
42 llvm::StringRef FirstLine
=
43 llvm::StringRef(OS
.str()).take_until([](char C
) { return C
== '\n'; });
44 FirstLine
= FirstLine
.rtrim(" {");
45 Name
= std::string(FirstLine
.rtrim(" {"));
49 DeclRelationSet Relations
;
51 bool operator==(const PrintedDecl
&L
, const PrintedDecl
&R
) {
52 return std::tie(L
.Name
, L
.Relations
) == std::tie(R
.Name
, R
.Relations
);
54 llvm::raw_ostream
&operator<<(llvm::raw_ostream
&OS
, const PrintedDecl
&D
) {
55 return OS
<< D
.Name
<< " Rel=" << D
.Relations
;
58 // The test cases in for targetDecl() take the form
59 // - a piece of code (Code = "...")
60 // - Code should have a single AST node marked as a [[range]]
61 // - an EXPECT_DECLS() assertion that verify the type of node selected, and
62 // all the decls that targetDecl() considers it to reference
63 // Despite the name, these cases actually test allTargetDecls() for brevity.
64 class TargetDeclTest
: public ::testing::Test
{
66 using Rel
= DeclRelation
;
68 std::vector
<std::string
> Flags
;
70 // Asserts that `Code` has a marked selection of a node `NodeType`,
71 // and returns allTargetDecls() as PrintedDecl structs.
72 // Use via EXPECT_DECLS().
73 std::vector
<PrintedDecl
> assertNodeAndPrintDecls(const char *NodeType
) {
74 llvm::Annotations
A(Code
);
75 auto TU
= TestTU::withCode(A
.code());
77 auto AST
= TU
.build();
78 llvm::Annotations::Range R
= A
.range();
79 auto Selection
= SelectionTree::createRight(
80 AST
.getASTContext(), AST
.getTokens(), R
.Begin
, R
.End
);
81 const SelectionTree::Node
*N
= Selection
.commonAncestor();
83 ADD_FAILURE() << "No node selected!\n" << Code
;
86 EXPECT_EQ(N
->kind(), NodeType
) << Selection
;
88 std::vector
<PrintedDecl
> ActualDecls
;
89 for (const auto &Entry
:
90 allTargetDecls(N
->ASTNode
, AST
.getHeuristicResolver()))
91 ActualDecls
.emplace_back(Entry
.first
, Entry
.second
);
96 // This is a macro to preserve line numbers in assertion failures.
97 // It takes the expected decls as varargs to work around comma-in-macro issues.
98 #define EXPECT_DECLS(NodeType, ...) \
99 EXPECT_THAT(assertNodeAndPrintDecls(NodeType), \
100 ::testing::UnorderedElementsAreArray( \
101 std::vector<PrintedDecl>({__VA_ARGS__}))) \
103 using ExpectedDecls
= std::vector
<PrintedDecl
>;
105 TEST_F(TargetDeclTest
, Exprs
) {
110 EXPECT_DECLS("DeclRefExpr", "int f()");
113 struct S { S operator+(S) const; };
114 auto X = S() [[+]] S();
116 EXPECT_DECLS("DeclRefExpr", "S operator+(S) const");
122 EXPECT_DECLS("CallExpr", "int foo()");
126 void operator()(int n);
133 EXPECT_DECLS("CXXOperatorCallExpr", "void operator()(int n)");
142 EXPECT_DECLS("GotoStmt", "label:");
149 EXPECT_DECLS("LabelStmt", "label:");
152 TEST_F(TargetDeclTest
, RecoveryForC
) {
153 Flags
= {"-xc", "-Xclang", "-frecovery-ast"};
155 // error-ok: testing behavior on broken code
160 EXPECT_DECLS("DeclRefExpr", "int f(int)");
163 TEST_F(TargetDeclTest
, Recovery
) {
165 // error-ok: testing behavior on broken code
170 EXPECT_DECLS("UnresolvedLookupExpr", "int f()", "int f(int, int)");
173 TEST_F(TargetDeclTest
, RecoveryType
) {
175 // error-ok: testing behavior on broken code
176 struct S { int member; };
179 // No overload matches, but we have recovery-expr with the correct type.
180 overloaded().[[member]];
183 EXPECT_DECLS("MemberExpr", "int member");
186 TEST_F(TargetDeclTest
, UsingDecl
) {
195 // f(char) is not referenced!
196 EXPECT_DECLS("DeclRefExpr", {"using foo::f", Rel::Alias
}, {"int f(int)"});
205 // All overloads are referenced.
206 EXPECT_DECLS("UsingDecl", {"using foo::f", Rel::Alias
}, {"int f(int)"},
216 int x = Y().[[foo]]();
218 EXPECT_DECLS("MemberExpr", {"using X::foo", Rel::Alias
}, {"int foo()"});
221 template <typename T>
225 template <typename T>
226 struct Derived : Base<T> {
227 using Base<T>::[[waldo]];
230 EXPECT_DECLS("UnresolvedUsingValueDecl", {"using Base<T>::waldo", Rel::Alias
},
235 template<typename T> class S {};
243 EXPECT_DECLS("TemplateSpecializationTypeLoc", {"using ns::S", Rel::Alias
},
244 {"template <typename T> class S"},
245 {"class S", Rel::TemplatePattern
});
249 template<typename T> class S {};
253 template <template <typename> class T> class X {};
256 EXPECT_DECLS("TemplateArgumentLoc", {"using ns::S", Rel::Alias
},
257 {"template <typename T> class S"});
261 template<typename T> class S { public: S(T); };
267 Flags
.push_back("-std=c++17"); // For CTAD feature.
268 EXPECT_DECLS("DeducedTemplateSpecializationTypeLoc",
269 {"using ns::S", Rel::Alias
}, {"template <typename T> class S"},
270 {"class S", Rel::TemplatePattern
});
274 class Foo { public: class foo {}; };
275 template <class T> class A : public Foo<T> {
276 using typename Foo<T>::foo;
280 EXPECT_DECLS("UnresolvedUsingTypeLoc",
281 {"using typename Foo<T>::foo", Rel::Alias
});
284 Flags
.push_back("-std=c++20");
286 namespace ns { enum class A { X }; }
287 [[using enum ns::A]];
289 EXPECT_DECLS("UsingEnumDecl", "enum class A : int");
292 namespace ns { enum class A { X }; }
296 EXPECT_DECLS("DeclRefExpr", "X");
299 TEST_F(TargetDeclTest
, BaseSpecifier
) {
302 struct Y : [[private]] X {};
304 EXPECT_DECLS("CXXBaseSpecifier", "struct X");
307 struct Y : [[private X]] {};
309 EXPECT_DECLS("CXXBaseSpecifier", "struct X");
312 struct Y : private [[X]] {};
314 EXPECT_DECLS("RecordTypeLoc", "struct X");
317 TEST_F(TargetDeclTest
, ConstructorInitList
) {
324 EXPECT_DECLS("CXXCtorInitializer", "int a");
332 EXPECT_DECLS("RecordTypeLoc", "struct X");
335 TEST_F(TargetDeclTest
, DesignatedInit
) {
336 Flags
= {"-xc"}; // array designators are a C99 extension.
339 struct Y { int b; struct X c[2]; };
340 struct Y y = { .c[0].[[a]] = 1 };
342 EXPECT_DECLS("DesignatedInitExpr", "int a");
345 TEST_F(TargetDeclTest
, NestedNameSpecifier
) {
347 namespace a { namespace b { int c; } }
350 EXPECT_DECLS("NestedNameSpecifierLoc", "namespace b");
353 namespace a { struct X { enum { y }; }; }
356 EXPECT_DECLS("NestedNameSpecifierLoc", "struct X");
359 template <typename T>
362 EXPECT_DECLS("NestedNameSpecifierLoc", "typename T");
365 namespace a { int x; }
369 EXPECT_DECLS("NestedNameSpecifierLoc", {"namespace b = a", Rel::Alias
},
370 {"namespace a", Rel::Underlying
});
373 TEST_F(TargetDeclTest
, Types
) {
378 EXPECT_DECLS("RecordTypeLoc", "struct X");
385 EXPECT_DECLS("TypedefTypeLoc", {"typedef S X", Rel::Alias
},
386 {"struct S", Rel::Underlying
});
388 namespace ns { struct S{}; }
392 EXPECT_DECLS("TypedefTypeLoc", {"typedef ns::S X", Rel::Alias
},
393 {"struct S", Rel::Underlying
});
397 void foo() { [[T]] x; }
399 EXPECT_DECLS("TemplateTypeParmTypeLoc", "class T");
403 template<template<typename> class T>
404 void foo() { [[T<int>]] x; }
406 EXPECT_DECLS("TemplateSpecializationTypeLoc", "template <typename> class T");
410 template<template<typename> class ...T>
415 EXPECT_DECLS("TemplateArgumentLoc", {"template <typename> class ...T"});
423 EXPECT_DECLS("DecltypeTypeLoc", {"struct S", Rel::Underlying
});
429 // FIXME: deduced type missing in AST. https://llvm.org/PR42914
430 EXPECT_DECLS("AutoTypeLoc", );
433 template <typename... E>
435 static const int size = sizeof...([[E]]);
438 EXPECT_DECLS("SizeOfPackExpr", "typename ...E");
441 template <typename T>
446 EXPECT_DECLS("InjectedClassNameTypeLoc", "class Foo");
449 TEST_F(TargetDeclTest
, ClassTemplate
) {
451 // Implicit specialization.
452 template<int x> class Foo{};
455 EXPECT_DECLS("TemplateSpecializationTypeLoc",
456 {"template<> class Foo<42>", Rel::TemplateInstantiation
},
457 {"class Foo", Rel::TemplatePattern
});
460 template<typename T> class Foo {};
461 // The "Foo
<int>" SpecializationDecl is incomplete, there is no
462 // instantiation happening.
463 void func([[Foo<int>]] *);
465 EXPECT_DECLS("TemplateSpecializationTypeLoc",
466 {"class Foo", Rel::TemplatePattern
},
467 {"template<> class Foo<int>", Rel::TemplateInstantiation
});
470 // Explicit specialization.
471 template<int x> class Foo{};
472 template<> class Foo<42>{};
475 EXPECT_DECLS("TemplateSpecializationTypeLoc", "template<> class Foo<42>");
478 // Partial specialization.
479 template<typename T> class Foo{};
480 template<typename T> class Foo<T*>{};
483 EXPECT_DECLS("TemplateSpecializationTypeLoc",
484 {"template<> class Foo<int *>", Rel::TemplateInstantiation
},
485 {"template <typename T> class Foo<T *>", Rel::TemplatePattern
});
488 // Template template argument.
489 template<typename T> struct Vector {};
490 template <template <typename> class Container>
494 EXPECT_DECLS("TemplateArgumentLoc", {"template <typename T> struct Vector"});
496 Flags
.push_back("-std=c++17"); // for CTAD tests
499 // Class template argument deduction
500 template <typename T>
508 EXPECT_DECLS("DeducedTemplateSpecializationTypeLoc",
509 {"struct Test", Rel::TemplatePattern
});
513 template <typename T>
515 template <typename I>
518 template <typename I>
519 [[Test]](I, I) -> Test<typename I::type>;
521 EXPECT_DECLS("CXXDeductionGuideDecl", {"template <typename T> struct Test"});
524 TEST_F(TargetDeclTest
, Concept
) {
525 Flags
.push_back("-std=c++20");
527 // FIXME: Should we truncate the pretty-printed form of a concept decl
531 template <typename T>
532 concept Fooable = requires (T t) { t.foo(); };
534 template <typename T> requires [[Fooable]]<T>
541 {"template <typename T> concept Fooable = requires (T t) { t.foo(); }"});
543 // trailing requires clause
545 template <typename T>
546 concept Fooable = true;
548 template <typename T>
549 void foo() requires [[Fooable]]<T>;
551 EXPECT_DECLS("ConceptReference",
552 {"template <typename T> concept Fooable = true"});
554 // constrained-parameter
556 template <typename T>
557 concept Fooable = true;
559 template <[[Fooable]] T>
562 EXPECT_DECLS("ConceptReference",
563 {"template <typename T> concept Fooable = true"});
565 // partial-concept-id
567 template <typename T, typename U>
568 concept Fooable = true;
570 template <[[Fooable]]<int> T>
573 EXPECT_DECLS("ConceptReference",
574 {"template <typename T, typename U> concept Fooable = true"});
577 TEST_F(TargetDeclTest
, Coroutine
) {
578 Flags
.push_back("-std=c++20");
582 template <typename, typename...> struct coroutine_traits;
583 template <typename> struct coroutine_handle {
584 template <typename U>
585 coroutine_handle(coroutine_handle<U>&&) noexcept;
586 static coroutine_handle from_address(void* __addr) noexcept;
592 struct awaitable_frame {
593 awaitable get_return_object();
595 void unhandled_exception();
598 bool await_ready() const noexcept;
599 void await_suspend(std::coroutine_handle<void>) noexcept;
600 void await_resume() const noexcept;
602 result_t initial_suspend() noexcept;
603 result_t final_suspend() noexcept;
604 result_t await_transform(executor) noexcept;
609 struct coroutine_traits<awaitable> {
610 typedef awaitable_frame promise_type;
615 co_await [[executor]]();
618 EXPECT_DECLS("RecordTypeLoc", "struct executor");
621 TEST_F(TargetDeclTest
, RewrittenBinaryOperator
) {
622 Flags
.push_back("-std=c++20");
626 struct strong_ordering {
628 constexpr operator int() const { return n; }
629 static const strong_ordering equal, greater, less;
631 constexpr strong_ordering strong_ordering::equal = {0};
632 constexpr strong_ordering strong_ordering::greater = {1};
633 constexpr strong_ordering strong_ordering::less = {-1};
639 auto operator<=>(const Foo&) const = default;
642 bool x = (Foo(1) [[!=]] Foo(2));
644 EXPECT_DECLS("CXXRewrittenBinaryOperator",
645 {"bool operator==(const Foo &) const noexcept = default"});
648 TEST_F(TargetDeclTest
, FunctionTemplate
) {
650 // Implicit specialization.
651 template<typename T> bool foo(T) { return false; };
652 bool x = [[foo]](42);
654 EXPECT_DECLS("DeclRefExpr",
655 {"template<> bool foo<int>(int)", Rel::TemplateInstantiation
},
656 {"bool foo(T)", Rel::TemplatePattern
});
659 // Explicit specialization.
660 template<typename T> bool foo(T) { return false; };
661 template<> bool foo<int>(int) { return false; };
662 bool x = [[foo]](42);
664 EXPECT_DECLS("DeclRefExpr", "template<> bool foo<int>(int)");
667 TEST_F(TargetDeclTest
, VariableTemplate
) {
668 // Pretty-printer doesn't do a very good job of variable templates :-(
670 // Implicit specialization.
671 template<typename T> int foo;
672 int x = [[foo]]<char>;
674 EXPECT_DECLS("DeclRefExpr", {"int foo", Rel::TemplateInstantiation
},
675 {"int foo", Rel::TemplatePattern
});
678 // Explicit specialization.
679 template<typename T> int foo;
680 template <> bool foo<char>;
681 int x = [[foo]]<char>;
683 EXPECT_DECLS("DeclRefExpr", "bool foo");
686 // Partial specialization.
687 template<typename T> int foo;
688 template<typename T> bool foo<T*>;
689 bool x = [[foo]]<char*>;
691 EXPECT_DECLS("DeclRefExpr", {"bool foo", Rel::TemplateInstantiation
},
692 {"bool foo", Rel::TemplatePattern
});
695 TEST_F(TargetDeclTest
, TypeAliasTemplate
) {
697 template<typename T, int X> class SmallVector {};
698 template<typename U> using TinyVector = SmallVector<U, 1>;
699 [[TinyVector<int>]] X;
701 EXPECT_DECLS("TemplateSpecializationTypeLoc",
702 {"template<> class SmallVector<int, 1>",
703 Rel::TemplateInstantiation
| Rel::Underlying
},
704 {"class SmallVector", Rel::TemplatePattern
| Rel::Underlying
},
705 {"using TinyVector = SmallVector<U, 1>",
706 Rel::Alias
| Rel::TemplatePattern
});
709 TEST_F(TargetDeclTest
, BuiltinTemplates
) {
711 template <class T, T... Index> struct integer_sequence {};
712 [[__make_integer_seq]]<integer_sequence, int, 3> X;
715 "TemplateSpecializationTypeLoc",
716 {"struct integer_sequence", Rel::TemplatePattern
| Rel::Underlying
},
717 {"template<> struct integer_sequence<int, <0, 1, 2>>",
718 Rel::TemplateInstantiation
| Rel::Underlying
});
720 // Dependent context.
722 template <class T, T... Index> struct integer_sequence;
724 template <class T, int N>
725 using make_integer_sequence = [[__make_integer_seq]]<integer_sequence, T, N>;
727 EXPECT_DECLS("TemplateSpecializationTypeLoc", );
730 template <int N, class... Pack>
731 using type_pack_element = [[__type_pack_element]]<N, Pack...>;
733 EXPECT_DECLS("TemplateSpecializationTypeLoc", );
736 TEST_F(TargetDeclTest
, MemberOfTemplate
) {
738 template <typename T> struct Foo {
741 int y = Foo<int>().[[x]](42);
743 EXPECT_DECLS("MemberExpr", {"int x(int)", Rel::TemplateInstantiation
},
744 {"int x(T)", Rel::TemplatePattern
});
747 template <typename T> struct Foo {
748 template <typename U>
751 int y = Foo<char>().[[x]]('c', 42);
753 EXPECT_DECLS("MemberExpr",
754 {"template<> int x<int>(char, int)", Rel::TemplateInstantiation
},
755 {"int x(T, U)", Rel::TemplatePattern
});
758 TEST_F(TargetDeclTest
, Lambda
) {
760 void foo(int x = 42) {
761 auto l = [ [[x]] ]{ return x + 1; };
764 EXPECT_DECLS("DeclRefExpr", "int x = 42");
766 // It seems like this should refer to another var, with the outer param being
767 // an underlying decl. But it doesn't seem to exist.
769 void foo(int x = 42) {
770 auto l = [x]{ return [[x]] + 1; };
773 EXPECT_DECLS("DeclRefExpr", "int x = 42");
777 auto l = [x = 1]{ return [[x]] + 1; };
780 // FIXME: why both auto and int?
781 EXPECT_DECLS("DeclRefExpr", "auto int x = 1");
784 TEST_F(TargetDeclTest
, OverloadExpr
) {
785 Flags
.push_back("--target=x86_64-pc-linux-gnu");
796 EXPECT_DECLS("UnresolvedLookupExpr", "void func(int *)", "void func(char *)");
809 EXPECT_DECLS("UnresolvedMemberExpr", "void func(int *)", "void func(char *)");
813 static void *operator new(unsigned long);
815 auto* k = [[new]] X();
817 EXPECT_DECLS("CXXNewExpr", "static void *operator new(unsigned long)");
819 void *operator new(unsigned long);
820 auto* k = [[new]] int();
822 EXPECT_DECLS("CXXNewExpr", "void *operator new(unsigned long)");
826 static void operator delete(void *) noexcept;
832 EXPECT_DECLS("CXXDeleteExpr", "static void operator delete(void *) noexcept");
834 void operator delete(void *) noexcept;
839 // Sized deallocation is enabled by default in C++14 onwards.
840 EXPECT_DECLS("CXXDeleteExpr",
841 "void operator delete(void *, unsigned long) noexcept");
844 TEST_F(TargetDeclTest
, DependentExprs
) {
845 // Heuristic resolution of method of dependent field
847 struct A { void foo() {} };
848 template <typename T>
856 EXPECT_DECLS("MemberExpr", "void foo()");
858 // Similar to above but base expression involves a function call.
866 template <typename T>
870 this->c.getA().[[foo]]();
874 EXPECT_DECLS("MemberExpr", "void foo()");
876 // Similar to above but uses a function pointer.
885 template <typename T>
889 this->c.fptr().[[foo]]();
893 EXPECT_DECLS("MemberExpr", "void foo()");
895 // Base expression involves a member access into this.
900 template <typename T> struct Foo {
907 EXPECT_DECLS("CXXDependentScopeMemberExpr", "int aaaa");
913 template <typename T> T convert() const;
915 template <typename T>
917 Foo::k(T()).template [[convert]]<T>();
920 EXPECT_DECLS("CXXDependentScopeMemberExpr",
921 "template <typename T> T convert() const");
924 template <typename T>
928 template <typename T>
929 using Wally = Waldo<T>;
930 template <typename T>
931 void foo(Wally<T> w) {
935 EXPECT_DECLS("CXXDependentScopeMemberExpr", "void find()");
938 template <typename T>
942 template <typename T>
944 using Type = Waldo<T>;
946 template <typename T>
947 void foo(typename MetaWaldo<T>::Type w) {
951 EXPECT_DECLS("CXXDependentScopeMemberExpr", "void find()");
957 template <typename T>
960 struct S : Wally<int> {
961 void Foo() { this->[[find]](); }
964 EXPECT_DECLS("MemberExpr", "void find()");
967 TEST_F(TargetDeclTest
, DependentTypes
) {
968 // Heuristic resolution of dependent type name
971 struct A { struct B {}; };
973 template <typename T>
974 void foo(typename A<T>::[[B]]);
976 EXPECT_DECLS("DependentNameTypeLoc", "struct B");
978 // Heuristic resolution of dependent type name which doesn't get a TypeLoc
981 struct A { struct B { struct C {}; }; };
983 template <typename T>
984 void foo(typename A<T>::[[B]]::C);
986 EXPECT_DECLS("NestedNameSpecifierLoc", "struct B");
988 // Heuristic resolution of dependent type name whose qualifier is also
992 struct A { struct B { struct C {}; }; };
994 template <typename T>
995 void foo(typename A<T>::B::[[C]]);
997 EXPECT_DECLS("DependentNameTypeLoc", "struct C");
999 // Heuristic resolution of dependent template name
1003 template <typename> struct B {};
1006 template <typename T>
1007 void foo(typename A<T>::template [[B]]<int>);
1009 EXPECT_DECLS("DependentTemplateSpecializationTypeLoc",
1010 "template <typename> struct B");
1012 // Dependent name with recursive definition. We don't expect a
1013 // result, but we shouldn't get into a stack overflow either.
1017 typedef typename waldo<N - 1>::type::[[next]] type;
1020 EXPECT_DECLS("DependentNameTypeLoc", );
1022 // Similar to above but using mutually recursive templates.
1029 using type = typename odd<N - 1>::type::next;
1034 using type = typename even<N - 1>::type::[[next]];
1037 EXPECT_DECLS("DependentNameTypeLoc", );
1040 TEST_F(TargetDeclTest
, TypedefCascade
) {
1046 using type = C::type;
1049 using type = B::type;
1053 EXPECT_DECLS("TypedefTypeLoc",
1054 {"using type = int", Rel::Alias
| Rel::Underlying
},
1055 {"using type = C::type", Rel::Alias
| Rel::Underlying
},
1056 {"using type = B::type", Rel::Alias
});
1059 TEST_F(TargetDeclTest
, RecursiveTemplate
) {
1060 Flags
.push_back("-std=c++20"); // the test case uses concepts
1063 template <typename T>
1064 concept Leaf = false;
1066 template <typename Tree>
1067 struct descend_left {
1068 using type = typename descend_left<typename Tree::left>::[[type]];
1071 template <Leaf Tree>
1072 struct descend_left<Tree> {
1073 using type = typename Tree::value;
1076 EXPECT_DECLS("DependentNameTypeLoc",
1077 {"using type = typename descend_left<typename Tree::left>::type",
1078 Rel::Alias
| Rel::Underlying
});
1081 TEST_F(TargetDeclTest
, ObjC
) {
1082 Flags
= {"-xobjective-c"};
1091 EXPECT_DECLS("ObjCMessageExpr", "- (void)bar");
1094 @interface Foo { @public int bar; }
1100 EXPECT_DECLS("ObjCIvarRefExpr", "int bar");
1105 -(void) setX:(int)x;
1111 EXPECT_DECLS("ObjCPropertyRefExpr", "- (void)setX:(int)x");
1115 @property(retain) I* x;
1116 @property(retain) I* y;
1122 EXPECT_DECLS("ObjCPropertyRefExpr",
1123 "@property(atomic, retain, readwrite) I *x");
1128 @interface Interface
1129 @property(retain) [[MYObject]] *x;
1132 EXPECT_DECLS("ObjCInterfaceTypeLoc", "@interface MYObject");
1135 @interface MYObject2
1137 @interface Interface
1138 @property(retain, nonnull) [[MYObject2]] *x;
1141 EXPECT_DECLS("ObjCInterfaceTypeLoc", "@interface MYObject2");
1147 return [[@protocol(Foo)]];
1150 EXPECT_DECLS("ObjCProtocolExpr", "@protocol Foo");
1155 void test([[Foo]] *p);
1157 EXPECT_DECLS("ObjCInterfaceTypeLoc", "@interface Foo");
1159 Code
= R
"cpp(// Don't consider implicit interface as the target.
1160 @implementation [[Implicit]]
1163 EXPECT_DECLS("ObjCImplementationDecl", "@implementation Implicit");
1168 @implementation [[Foo]]
1171 EXPECT_DECLS("ObjCImplementationDecl", "@interface Foo");
1176 @interface Foo (Ext)
1178 @implementation [[Foo]] (Ext)
1181 EXPECT_DECLS("ObjCCategoryImplDecl", "@interface Foo(Ext)");
1186 @interface Foo (Ext)
1188 @implementation Foo ([[Ext]])
1191 EXPECT_DECLS("ObjCCategoryImplDecl", "@interface Foo(Ext)");
1194 void test(id</*error-ok*/[[InvalidProtocol]]> p);
1196 EXPECT_DECLS("ParmVarDecl", "id p");
1202 void test([[C]]<Foo> *p);
1204 EXPECT_DECLS("ObjCInterfaceTypeLoc", "@class C;");
1210 void test(C<[[Foo]]> *p);
1212 EXPECT_DECLS("ObjCProtocolLoc", "@protocol Foo");
1220 void test(C<[[Foo]], Bar> *p);
1222 EXPECT_DECLS("ObjCProtocolLoc", "@protocol Foo");
1230 void test(C<Foo, [[Bar]]> *p);
1232 EXPECT_DECLS("ObjCProtocolLoc", "@protocol Bar");
1236 + (id)sharedInstance;
1239 + (id)sharedInstance { return 0; }
1242 id value = [[Foo]].sharedInstance;
1245 EXPECT_DECLS("ObjCInterfaceTypeLoc", "@interface Foo");
1249 + (id)sharedInstance;
1252 + (id)sharedInstance { return 0; }
1255 id value = Foo.[[sharedInstance]];
1258 EXPECT_DECLS("ObjCPropertyRefExpr", "+ (id)sharedInstance");
1262 + ([[id]])sharedInstance;
1265 EXPECT_DECLS("TypedefTypeLoc", );
1269 + ([[instancetype]])sharedInstance;
1272 EXPECT_DECLS("TypedefTypeLoc", );
1275 class FindExplicitReferencesTest
: public ::testing::Test
{
1278 std::string AnnotatedCode
;
1279 std::string DumpedReferences
;
1282 TestTU
newTU(llvm::StringRef Code
) {
1284 TU
.Code
= std::string(Code
);
1286 // FIXME: Auto-completion in a template requires disabling delayed template
1288 TU
.ExtraArgs
.push_back("-std=c++20");
1289 TU
.ExtraArgs
.push_back("-xobjective-c++");
1294 AllRefs
annotatedReferences(llvm::StringRef Code
, ParsedAST
&AST
,
1295 std::vector
<ReferenceLoc
> Refs
) {
1296 auto &SM
= AST
.getSourceManager();
1297 llvm::stable_sort(Refs
, [&](const ReferenceLoc
&L
, const ReferenceLoc
&R
) {
1298 return SM
.isBeforeInTranslationUnit(L
.NameLoc
, R
.NameLoc
);
1301 std::string AnnotatedCode
;
1302 unsigned NextCodeChar
= 0;
1303 for (unsigned I
= 0; I
< Refs
.size(); ++I
) {
1306 SourceLocation Pos
= R
.NameLoc
;
1307 assert(Pos
.isValid());
1308 if (Pos
.isMacroID()) // FIXME: figure out how to show macro locations.
1309 Pos
= SM
.getExpansionLoc(Pos
);
1310 assert(Pos
.isFileID());
1314 std::tie(File
, Offset
) = SM
.getDecomposedLoc(Pos
);
1315 if (File
== SM
.getMainFileID()) {
1316 // Print the reference in a source code.
1317 assert(NextCodeChar
<= Offset
);
1318 AnnotatedCode
+= Code
.substr(NextCodeChar
, Offset
- NextCodeChar
);
1319 AnnotatedCode
+= "$" + std::to_string(I
) + "^";
1321 NextCodeChar
= Offset
;
1324 AnnotatedCode
+= Code
.substr(NextCodeChar
);
1326 std::string DumpedReferences
;
1327 for (unsigned I
= 0; I
< Refs
.size(); ++I
)
1328 DumpedReferences
+= std::string(llvm::formatv("{0}: {1}\n", I
, Refs
[I
]));
1330 return AllRefs
{std::move(AnnotatedCode
), std::move(DumpedReferences
)};
1333 /// Parses \p Code, and annotates its body with results of
1334 /// findExplicitReferences on all top level decls.
1335 /// See actual tests for examples of annotation format.
1336 AllRefs
annotateAllReferences(llvm::StringRef Code
) {
1337 TestTU TU
= newTU(Code
);
1338 auto AST
= TU
.build();
1340 std::vector
<ReferenceLoc
> Refs
;
1341 for (auto *TopLevel
: AST
.getLocalTopLevelDecls())
1342 findExplicitReferences(
1343 TopLevel
, [&Refs
](ReferenceLoc R
) { Refs
.push_back(std::move(R
)); },
1344 AST
.getHeuristicResolver());
1345 return annotatedReferences(Code
, AST
, std::move(Refs
));
1348 /// Parses \p Code, finds function or namespace '::foo' and annotates its body
1349 /// with results of findExplicitReferences.
1350 /// See actual tests for examples of annotation format.
1351 AllRefs
annotateReferencesInFoo(llvm::StringRef Code
) {
1352 TestTU TU
= newTU(Code
);
1353 auto AST
= TU
.build();
1354 auto *TestDecl
= &findDecl(AST
, "foo");
1355 if (auto *T
= llvm::dyn_cast
<FunctionTemplateDecl
>(TestDecl
))
1356 TestDecl
= T
->getTemplatedDecl();
1358 std::vector
<ReferenceLoc
> Refs
;
1359 if (const auto *Func
= llvm::dyn_cast
<FunctionDecl
>(TestDecl
))
1360 findExplicitReferences(
1362 [&Refs
](ReferenceLoc R
) { Refs
.push_back(std::move(R
)); },
1363 AST
.getHeuristicResolver());
1364 else if (const auto *NS
= llvm::dyn_cast
<NamespaceDecl
>(TestDecl
))
1365 findExplicitReferences(
1367 [&Refs
, &NS
](ReferenceLoc R
) {
1368 // Avoid adding the namespace foo decl to the results.
1369 if (R
.Targets
.size() == 1 && R
.Targets
.front() == NS
)
1371 Refs
.push_back(std::move(R
));
1373 AST
.getHeuristicResolver());
1374 else if (const auto *OC
= llvm::dyn_cast
<ObjCContainerDecl
>(TestDecl
))
1375 findExplicitReferences(
1376 OC
, [&Refs
](ReferenceLoc R
) { Refs
.push_back(std::move(R
)); },
1377 AST
.getHeuristicResolver());
1379 ADD_FAILURE() << "Failed to find ::foo decl for test";
1381 return annotatedReferences(Code
, AST
, std::move(Refs
));
1385 TEST_F(FindExplicitReferencesTest
, AllRefsInFoo
) {
1386 std::pair
</*Code*/ llvm::StringRef
, /*References*/ llvm::StringRef
> Cases
[] =
1387 {// Simple expressions.
1391 void foo(int param) {
1392 $0^global = $1^param + $2^func();
1395 "0: targets = {global}\n"
1396 "1: targets = {param}\n"
1397 "2: targets = {func}\n"},
1399 struct X { int a; };
1404 "0: targets = {x}\n"
1405 "1: targets = {X::a}\n"},
1407 // error-ok: testing with broken code
1410 return $0^bar() + $1^bar(42);
1413 "0: targets = {bar}\n"
1414 "1: targets = {bar}\n"},
1415 // Namespaces and aliases.
1418 namespace alias = ns;
1420 using namespace $0^ns;
1421 using namespace $1^alias;
1424 "0: targets = {ns}\n"
1425 "1: targets = {alias}\n"},
1426 // Using declarations.
1428 namespace ns { int global; }
1430 using $0^ns::$1^global;
1433 "0: targets = {ns}\n"
1434 "1: targets = {ns::global}, qualifier = 'ns::'\n"},
1435 // Using enum declarations.
1437 namespace ns { enum class A {}; }
1439 using enum $0^ns::$1^A;
1442 "0: targets = {ns}\n"
1443 "1: targets = {ns::A}, qualifier = 'ns::'\n"},
1446 struct Struct { int a; };
1447 using Typedef = int;
1451 static_cast<$4^Struct*>(0);
1454 "0: targets = {Struct}\n"
1455 "1: targets = {x}, decl\n"
1456 "2: targets = {Typedef}\n"
1457 "3: targets = {y}, decl\n"
1458 "4: targets = {Struct}\n"},
1461 namespace a { namespace b { struct S { typedef int type; }; } }
1463 $0^a::$1^b::$2^S $3^x;
1464 using namespace $4^a::$5^b;
1468 "0: targets = {a}\n"
1469 "1: targets = {a::b}, qualifier = 'a::'\n"
1470 "2: targets = {a::b::S}, qualifier = 'a::b::'\n"
1471 "3: targets = {x}, decl\n"
1472 "4: targets = {a}\n"
1473 "5: targets = {a::b}, qualifier = 'a::'\n"
1474 "6: targets = {a::b::S}\n"
1475 "7: targets = {a::b::S::type}, qualifier = 'struct S::'\n"
1476 "8: targets = {y}, decl\n"},
1479 $0^ten: // PRINT "HELLO WORLD
!"
1483 "0: targets = {ten}, decl\n"
1484 "1: targets = {ten}\n"},
1485 // Simple templates.
1487 template <class T> struct vector { using value_type = T; };
1488 template <> struct vector<bool> { using value_type = bool; };
1490 $0^vector<int> $1^vi;
1491 $2^vector<bool> $3^vb;
1494 "0: targets = {vector<int>}\n"
1495 "1: targets = {vi}, decl\n"
1496 "2: targets = {vector<bool>}\n"
1497 "3: targets = {vb}, decl\n"},
1498 // Template type aliases.
1500 template <class T> struct vector { using value_type = T; };
1501 template <> struct vector<bool> { using value_type = bool; };
1502 template <class T> using valias = vector<T>;
1504 $0^valias<int> $1^vi;
1505 $2^valias<bool> $3^vb;
1508 "0: targets = {valias}\n"
1509 "1: targets = {vi}, decl\n"
1510 "2: targets = {valias}\n"
1511 "3: targets = {vb}, decl\n"},
1512 // Injected class name.
1515 template <typename $0^T>
1522 "0: targets = {foo::Bar::T}, decl\n"
1523 "1: targets = {foo::Bar}, decl\n"
1524 "2: targets = {foo::Bar}\n"
1525 "3: targets = {foo::Bar::f}, decl\n"
1526 "4: targets = {foo::Bar}\n"},
1527 // MemberExpr should know their using declaration.
1529 struct X { void func(int); };
1537 "0: targets = {y}\n"
1538 "1: targets = {Y::func}\n"},
1539 // DeclRefExpr should know their using declaration.
1541 namespace ns { void bar(int); }
1548 "0: targets = {bar}\n"},
1549 // References from a macro.
1554 void foo(int a, int b) {
1558 "0: targets = {a}\n"
1559 "1: targets = {b}\n"},
1560 // No references from implicit nodes.
1568 for (int $0^x : $1^vector()) {
1573 "0: targets = {x}, decl\n"
1574 "1: targets = {vector}\n"
1575 "2: targets = {x}\n"},
1576 // Handle UnresolvedLookupExpr.
1578 namespace ns1 { void func(char*); }
1579 namespace ns2 { void func(int*); }
1580 using namespace ns1;
1581 using namespace ns2;
1588 "0: targets = {ns1::func, ns2::func}\n"
1589 "1: targets = {t}\n"},
1590 // Handle UnresolvedMemberExpr.
1598 void foo(X x, T t) {
1602 "0: targets = {x}\n"
1603 "1: targets = {X::func, X::func}\n"
1604 "2: targets = {t}\n"},
1605 // Handle DependentScopeDeclRefExpr.
1614 $0^S<$1^T>::$2^value;
1617 "0: targets = {S}\n"
1618 "1: targets = {T}\n"
1619 "2: targets = {S::value}, qualifier = 'S<T>::'\n"},
1620 // Handle CXXDependentScopeMemberExpr.
1632 "0: targets = {t}\n"
1633 "1: targets = {S::value}\n"},
1634 // Type template parameters.
1638 static_cast<$0^T>(0);
1643 "0: targets = {T}\n"
1644 "1: targets = {T}\n"
1645 "2: targets = {T}\n"
1646 "3: targets = {t}, decl\n"},
1647 // Non-type template parameters.
1654 "0: targets = {x}, decl\n"
1655 "1: targets = {I}\n"},
1656 // Template template parameters.
1658 template <class T> struct vector {};
1660 template <template<class> class TT, template<class> class ...TP>
1664 $4^foo<$5^vector>();
1668 "0: targets = {TT}\n"
1669 "1: targets = {x}, decl\n"
1670 "2: targets = {foo}\n"
1671 "3: targets = {TT}\n"
1672 "4: targets = {foo}\n"
1673 "5: targets = {vector}\n"
1674 "6: targets = {foo}\n"
1675 "7: targets = {TP}\n"},
1676 // Non-type template parameters with declarations.
1679 template <int(*)()> struct wrapper {};
1681 template <int(*FuncParam)()>
1683 $0^wrapper<$1^func> $2^w;
1687 "0: targets = {wrapper<&func>}\n"
1688 "1: targets = {func}\n"
1689 "2: targets = {w}, decl\n"
1690 "3: targets = {FuncParam}\n"},
1691 // declaration references.
1696 class $0^Foo { $1^Foo(); ~$2^Foo(); int $3^field; };
1698 enum $5^E { $6^ABC };
1700 using $8^INT2 = int;
1701 namespace $9^NS = $10^ns;
1704 "0: targets = {Foo}, decl\n"
1705 "1: targets = {foo()::Foo::Foo}, decl\n"
1706 "2: targets = {Foo}\n"
1707 "3: targets = {foo()::Foo::field}, decl\n"
1708 "4: targets = {Var}, decl\n"
1709 "5: targets = {E}, decl\n"
1710 "6: targets = {foo()::ABC}, decl\n"
1711 "7: targets = {INT}, decl\n"
1712 "8: targets = {INT2}, decl\n"
1713 "9: targets = {NS}, decl\n"
1714 "10: targets = {ns}\n"},
1715 // User-defined conversion operator.
1721 // FIXME: This should have only one reference to Bar.
1722 $2^operator $3^$4^Bar();
1726 $7^f.$8^operator $9^Bar();
1729 "0: targets = {Bar}, decl\n"
1730 "1: targets = {Foo}, decl\n"
1731 "2: targets = {foo()::Foo::operator Bar}, decl\n"
1732 "3: targets = {Bar}\n"
1733 "4: targets = {Bar}\n"
1734 "5: targets = {Foo}\n"
1735 "6: targets = {f}, decl\n"
1736 "7: targets = {f}\n"
1737 "8: targets = {foo()::Foo::operator Bar}\n"
1738 "9: targets = {Bar}\n"},
1746 void $2^destructMe() {
1752 $6^f.~ /*...*/ $7^Foo();
1755 "0: targets = {Foo}, decl\n"
1756 // FIXME: It's better to target destructor's FunctionDecl instead of
1757 // the type itself (similar to constructor).
1758 "1: targets = {Foo}\n"
1759 "2: targets = {foo()::Foo::destructMe}, decl\n"
1760 "3: targets = {Foo}\n"
1761 "4: targets = {Foo}\n"
1762 "5: targets = {f}, decl\n"
1763 "6: targets = {f}\n"
1764 "7: targets = {Foo}\n"},
1765 // cxx constructor initializer.
1769 // member initializer
1775 class $4^Derived : public $5^Base {
1777 $8^Derived() : $9^Base() {}
1779 // delegating initializer
1782 $12^Foo(): $13^Foo(111) {}
1786 "0: targets = {X}, decl\n"
1787 "1: targets = {foo()::X::abc}, decl\n"
1788 "2: targets = {foo()::X::X}, decl\n"
1789 "3: targets = {foo()::X::abc}\n"
1790 "4: targets = {Derived}, decl\n"
1791 "5: targets = {Base}\n"
1792 "6: targets = {Base}\n"
1793 "7: targets = {foo()::Derived::B}, decl\n"
1794 "8: targets = {foo()::Derived::Derived}, decl\n"
1795 "9: targets = {Base}\n"
1796 "10: targets = {Foo}, decl\n"
1797 "11: targets = {foo()::Foo::Foo}, decl\n"
1798 "12: targets = {foo()::Foo::Foo}, decl\n"
1799 "13: targets = {Foo}\n"},
1800 // Anonymous entities should not be reported.
1805 int (*$2^fptr)(int $3^a, int) = nullptr;
1808 "0: targets = {(unnamed)}\n"
1809 "1: targets = {x}, decl\n"
1810 "2: targets = {fptr}, decl\n"
1811 "3: targets = {a}, decl\n"},
1812 // Namespace aliases should be handled properly.
1815 namespace ns { struct Type {}; }
1816 namespace alias = ns;
1817 namespace rec_alias = alias;
1820 $0^ns::$1^Type $2^a;
1821 $3^alias::$4^Type $5^b;
1822 $6^rec_alias::$7^Type $8^c;
1825 "0: targets = {ns}\n"
1826 "1: targets = {ns::Type}, qualifier = 'ns::'\n"
1827 "2: targets = {a}, decl\n"
1828 "3: targets = {alias}\n"
1829 "4: targets = {ns::Type}, qualifier = 'alias::'\n"
1830 "5: targets = {b}, decl\n"
1831 "6: targets = {rec_alias}\n"
1832 "7: targets = {ns::Type}, qualifier = 'rec_alias::'\n"
1833 "8: targets = {c}, decl\n"},
1834 // Handle SizeOfPackExpr.
1837 template <typename... E>
1839 constexpr int $0^size = sizeof...($1^E);
1842 "0: targets = {size}, decl\n"
1843 "1: targets = {E}\n"},
1844 // Class template argument deduction
1847 template <typename T>
1855 "0: targets = {Test}\n"
1856 "1: targets = {a}, decl\n"},
1860 template <typename $0^T>
1864 "0: targets = {foo::Bar::T}, decl\n"
1865 "1: targets = {foo::Bar}, decl\n"},
1869 template <typename $0^T>
1873 "0: targets = {T}, decl\n"
1874 "1: targets = {foo::func}, decl\n"},
1878 template <typename $0^T>
1882 "0: targets = {foo::T}, decl\n"
1883 "1: targets = {foo::T}\n"
1884 "2: targets = {foo::x}, decl\n"},
1887 template<typename T> class vector {};
1889 template <typename $0^T>
1890 using $1^V = $2^vector<$3^T>;
1893 "0: targets = {foo::T}, decl\n"
1894 "1: targets = {foo::V}, decl\n"
1895 "2: targets = {vector}\n"
1896 "3: targets = {foo::T}\n"},
1900 template <typename T>
1901 concept Drawable = requires (T t) { t.draw(); };
1904 template <typename $0^T> requires $1^Drawable<$2^T>
1905 void $3^bar($4^T $5^t) {
1910 "0: targets = {T}, decl\n"
1911 "1: targets = {Drawable}\n"
1912 "2: targets = {T}\n"
1913 "3: targets = {foo::bar}, decl\n"
1914 "4: targets = {T}\n"
1915 "5: targets = {t}, decl\n"
1916 "6: targets = {t}\n"
1917 "7: targets = {}\n"},
1918 // Objective-C: instance variables
1931 "0: targets = {f}\n"
1932 "1: targets = {I::_z}\n"},
1933 // Objective-C: properties
1937 @property(retain) I* x;
1938 @property(retain) I* y;
1945 "0: targets = {f}\n"
1946 "1: targets = {I::x}\n"
1947 "2: targets = {I::y}\n"},
1948 // Objective-C: implicit properties
1960 "0: targets = {f}\n"
1961 "1: targets = {I::x}\n"
1962 "2: targets = {I::setY:}\n"},
1963 // Objective-C: class properties
1967 @property(class) I *x;
1972 $2^local = $3^I.$4^x;
1975 "0: targets = {I}\n"
1976 "1: targets = {I::setX:}\n"
1977 "2: targets = {local}\n"
1978 "3: targets = {I}\n"
1979 "4: targets = {I::x}\n"},
1980 // Objective-C: implicit class properties
1990 $2^local = $3^I.$4^x;
1993 "0: targets = {I}\n"
1994 "1: targets = {I::setX:}\n"
1995 "2: targets = {local}\n"
1996 "3: targets = {I}\n"
1997 "4: targets = {I::x}\n"},
1998 {// Objective-C: methods
2001 -(void) a:(int)x b:(int)y;
2007 "0: targets = {i}\n"
2008 "1: targets = {I::a:b:}\n"},
2009 {// Objective-C: protocols
2019 "0: targets = {I}\n"
2020 "1: targets = {P}\n"
2021 "2: targets = {x}, decl\n"},
2023 // Designated initializers.
2029 $2^Foo $3^f { .$4^Bar = 42 };
2032 "0: targets = {Foo}, decl\n"
2033 "1: targets = {foo()::Foo::Bar}, decl\n"
2034 "2: targets = {Foo}\n"
2035 "3: targets = {f}, decl\n"
2036 "4: targets = {foo()::Foo::Bar}\n"},
2045 $5^Bar $6^bar { .$7^Foo.$8^Field = 42 };
2048 "0: targets = {Baz}, decl\n"
2049 "1: targets = {foo()::Baz::Field}, decl\n"
2050 "2: targets = {Bar}, decl\n"
2051 "3: targets = {Baz}\n"
2052 "4: targets = {foo()::Bar::Foo}, decl\n"
2053 "5: targets = {Bar}\n"
2054 "6: targets = {bar}, decl\n"
2055 "7: targets = {foo()::Bar::Foo}\n"
2056 "8: targets = {foo()::Baz::Field}\n"},
2058 template<typename T>
2060 template<typename T>
2062 $0^crash({.$1^x = $2^T()});
2065 "0: targets = {crash}\n"
2067 "2: targets = {T}\n"},
2068 // unknown template name should not crash.
2070 template <template <typename> typename T>
2073 template <typename $0^T>
2074 struct $1^Derive : $2^Base<$3^T::template $4^Unknown> {};
2077 "0: targets = {foo::Derive::T}, decl\n"
2078 "1: targets = {foo::Derive}, decl\n"
2079 "2: targets = {Base}\n"
2080 "3: targets = {foo::Derive::T}\n"
2081 "4: targets = {}, qualifier = 'T::'\n"},
2085 template <typename $0^T>
2087 template <typename $2^I>
2090 template <typename $5^I>
2091 $6^Test($7^I) -> $8^Test<typename $9^I::$10^type>;
2094 "0: targets = {T}, decl\n"
2095 "1: targets = {foo::Test}, decl\n"
2096 "2: targets = {I}, decl\n"
2097 "3: targets = {foo::Test::Test<T>}, decl\n"
2098 "4: targets = {I}\n"
2099 "5: targets = {I}, decl\n"
2100 "6: targets = {foo::Test}\n"
2101 "7: targets = {I}\n"
2102 "8: targets = {foo::Test}\n"
2103 "9: targets = {I}\n"
2104 "10: targets = {}, qualifier = 'I::'\n"}};
2106 for (const auto &C
: Cases
) {
2107 llvm::StringRef ExpectedCode
= C
.first
;
2108 llvm::StringRef ExpectedRefs
= C
.second
;
2111 annotateReferencesInFoo(llvm::Annotations(ExpectedCode
).code());
2112 EXPECT_EQ(ExpectedCode
, Actual
.AnnotatedCode
);
2113 EXPECT_EQ(ExpectedRefs
, Actual
.DumpedReferences
) << ExpectedCode
;
2117 TEST_F(FindExplicitReferencesTest
, AllRefs
) {
2118 std::pair
</*Code*/ llvm::StringRef
, /*References*/ llvm::StringRef
> Cases
[] =
2120 @interface $0^MyClass
2122 @implementation $1^$2^MyClass
2125 "0: targets = {MyClass}, decl\n"
2126 "1: targets = {MyClass}\n"
2127 "2: targets = {MyClass}, decl\n"},
2129 @interface $0^MyClass
2131 @interface $1^MyClass ($2^Category)
2133 @implementation $3^MyClass ($4^$5^Category)
2136 "0: targets = {MyClass}, decl\n"
2137 "1: targets = {MyClass}\n"
2138 "2: targets = {Category}, decl\n"
2139 "3: targets = {MyClass}\n"
2140 "4: targets = {Category}\n"
2141 "5: targets = {Category}, decl\n"}};
2143 for (const auto &C
: Cases
) {
2144 llvm::StringRef ExpectedCode
= C
.first
;
2145 llvm::StringRef ExpectedRefs
= C
.second
;
2147 auto Actual
= annotateAllReferences(llvm::Annotations(ExpectedCode
).code());
2148 EXPECT_EQ(ExpectedCode
, Actual
.AnnotatedCode
);
2149 EXPECT_EQ(ExpectedRefs
, Actual
.DumpedReferences
) << ExpectedCode
;
2154 } // namespace clangd
2155 } // namespace clang