2178 lines · cpp
1//===-- FindTargetTests.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-exception6//7//===----------------------------------------------------------------------===//8#include "FindTarget.h"9 10#include "Selection.h"11#include "TestTU.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>22 23namespace clang {24namespace clangd {25namespace {26 27// A referenced Decl together with its DeclRelationSet, for assertions.28//29// There's no great way to assert on the "content" of a Decl in the general case30// that's both expressive and unambiguous (e.g. clearly distinguishes between31// templated decls and their specializations).32//33// We use the result of pretty-printing the decl, with the {body} truncated.34struct PrintedDecl {35 PrintedDecl(const char *Name, DeclRelationSet Relations = {})36 : Name(Name), Relations(Relations) {}37 PrintedDecl(const NamedDecl *D, DeclRelationSet Relations = {})38 : Relations(Relations) {39 std::string S;40 llvm::raw_string_ostream OS(S);41 D->print(OS);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(" {"));46 }47 48 std::string Name;49 DeclRelationSet Relations;50};51bool operator==(const PrintedDecl &L, const PrintedDecl &R) {52 return std::tie(L.Name, L.Relations) == std::tie(R.Name, R.Relations);53}54llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const PrintedDecl &D) {55 return OS << D.Name << " Rel=" << D.Relations;56}57 58// The test cases in for targetDecl() take the form59// - 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, and62// all the decls that targetDecl() considers it to reference63// Despite the name, these cases actually test allTargetDecls() for brevity.64class TargetDeclTest : public ::testing::Test {65protected:66 using Rel = DeclRelation;67 std::string Code;68 std::vector<std::string> Flags;69 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());76 TU.ExtraArgs = Flags;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();82 if (!N) {83 ADD_FAILURE() << "No node selected!\n" << Code;84 return {};85 }86 EXPECT_EQ(N->kind(), NodeType) << Selection;87 88 std::vector<PrintedDecl> ActualDecls;89 for (const auto &Entry :90 allTargetDecls(N->ASTNode, AST.getHeuristicResolver()))91 ActualDecls.emplace_back(Entry.first, Entry.second);92 return ActualDecls;93 }94};95 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__}))) \102 << Code103using ExpectedDecls = std::vector<PrintedDecl>;104 105TEST_F(TargetDeclTest, Exprs) {106 Code = R"cpp(107 int f();108 int x = [[f]]();109 )cpp";110 EXPECT_DECLS("DeclRefExpr", "int f()");111 112 Code = R"cpp(113 struct S { S operator+(S) const; };114 auto X = S() [[+]] S();115 )cpp";116 EXPECT_DECLS("DeclRefExpr", "S operator+(S) const");117 118 Code = R"cpp(119 int foo();120 int s = foo[[()]];121 )cpp";122 EXPECT_DECLS("CallExpr", "int foo()");123 124 Code = R"cpp(125 struct X {126 void operator()(int n);127 };128 void test() {129 X x;130 x[[(123)]];131 }132 )cpp";133 EXPECT_DECLS("CXXOperatorCallExpr", "void operator()(int n)");134 135 Code = R"cpp(136 void test() {137 goto [[label]];138 label:139 return;140 }141 )cpp";142 EXPECT_DECLS("GotoStmt", "label:");143 Code = R"cpp(144 void test() {145 [[label]]:146 return;147 }148 )cpp";149 EXPECT_DECLS("LabelStmt", "label:");150}151 152TEST_F(TargetDeclTest, RecoveryForC) {153 Flags = {"-xc", "-Xclang", "-frecovery-ast"};154 Code = R"cpp(155 // error-ok: testing behavior on broken code156 // int f();157 int f(int);158 int x = [[f]]();159 )cpp";160 EXPECT_DECLS("DeclRefExpr", "int f(int)");161}162 163TEST_F(TargetDeclTest, Recovery) {164 Code = R"cpp(165 // error-ok: testing behavior on broken code166 int f();167 int f(int, int);168 int x = [[f]](42);169 )cpp";170 EXPECT_DECLS("UnresolvedLookupExpr", "int f()", "int f(int, int)");171}172 173TEST_F(TargetDeclTest, RecoveryType) {174 Code = R"cpp(175 // error-ok: testing behavior on broken code176 struct S { int member; };177 S overloaded(int);178 void foo() {179 // No overload matches, but we have recovery-expr with the correct type.180 overloaded().[[member]];181 }182 )cpp";183 EXPECT_DECLS("MemberExpr", "int member");184}185 186TEST_F(TargetDeclTest, UsingDecl) {187 Code = R"cpp(188 namespace foo {189 int f(int);190 int f(char);191 }192 using foo::f;193 int x = [[f]](42);194 )cpp";195 // f(char) is not referenced!196 EXPECT_DECLS("DeclRefExpr", {"using foo::f", Rel::Alias}, {"int f(int)"});197 198 Code = R"cpp(199 namespace foo {200 int f(int);201 int f(char);202 }203 [[using foo::f]];204 )cpp";205 // All overloads are referenced.206 EXPECT_DECLS("UsingDecl", {"using foo::f", Rel::Alias}, {"int f(int)"},207 {"int f(char)"});208 209 Code = R"cpp(210 struct X {211 int foo();212 };213 struct Y : X {214 using X::foo;215 };216 int x = Y().[[foo]]();217 )cpp";218 EXPECT_DECLS("MemberExpr", {"using X::foo", Rel::Alias}, {"int foo()"});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 Code = R"cpp(234 namespace ns {235 template<typename T> class S {};236 }237 238 using ns::S;239 240 template<typename T>241 using A = [[S]]<T>;242 )cpp";243 EXPECT_DECLS("TemplateSpecializationTypeLoc", {"using ns::S", Rel::Alias},244 {"template <typename T> class S"},245 {"class S", Rel::TemplatePattern});246 247 Code = R"cpp(248 namespace ns {249 template<typename T> class S {};250 }251 252 using ns::S;253 template <template <typename> class T> class X {};254 using B = X<[[S]]>;255 )cpp";256 EXPECT_DECLS("TemplateArgumentLoc", {"using ns::S", Rel::Alias},257 {"template <typename T> class S"});258 259 Code = R"cpp(260 namespace ns {261 template<typename T> class S { public: S(T); };262 }263 264 using ns::S;265 [[S]] s(123);266 )cpp";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});271 272 Code = R"cpp(273 template<typename T>274 class Foo { public: class foo {}; };275 template <class T> class A : public Foo<T> {276 using typename Foo<T>::foo;277 [[foo]] abc;278 };279 )cpp";280 EXPECT_DECLS("UnresolvedUsingTypeLoc",281 {"using typename Foo<T>::foo", Rel::Alias});282 283 // Using enum.284 Flags.push_back("-std=c++20");285 Code = R"cpp(286 namespace ns { enum class A { X }; }287 [[using enum ns::A]];288 )cpp";289 EXPECT_DECLS("UsingEnumDecl", "enum class A : int");290 291 Code = R"cpp(292 namespace ns { enum class A { X }; }293 using enum ns::A;294 auto m = [[X]];295 )cpp";296 EXPECT_DECLS("DeclRefExpr", "X");297}298 299TEST_F(TargetDeclTest, BaseSpecifier) {300 Code = R"cpp(301 struct X {};302 struct Y : [[private]] X {};303 )cpp";304 EXPECT_DECLS("CXXBaseSpecifier", "struct X");305 Code = R"cpp(306 struct X {};307 struct Y : [[private X]] {};308 )cpp";309 EXPECT_DECLS("CXXBaseSpecifier", "struct X");310 Code = R"cpp(311 struct X {};312 struct Y : private [[X]] {};313 )cpp";314 EXPECT_DECLS("RecordTypeLoc", "struct X");315}316 317TEST_F(TargetDeclTest, ConstructorInitList) {318 Code = R"cpp(319 struct X {320 int a;321 X() : [[a]](42) {}322 };323 )cpp";324 EXPECT_DECLS("CXXCtorInitializer", "int a");325 326 Code = R"cpp(327 struct X {328 X() : [[X]](1) {}329 X(int);330 };331 )cpp";332 EXPECT_DECLS("RecordTypeLoc", "struct X");333}334 335TEST_F(TargetDeclTest, DesignatedInit) {336 Flags = {"-xc"}; // array designators are a C99 extension.337 Code = R"c(338 struct X { int a; };339 struct Y { int b; struct X c[2]; };340 struct Y y = { .c[0].[[a]] = 1 };341 )c";342 EXPECT_DECLS("DesignatedInitExpr", "int a");343}344 345TEST_F(TargetDeclTest, NestedNameSpecifier) {346 Code = R"cpp(347 namespace a { namespace b { int c; } }348 int x = a::[[b::]]c;349 )cpp";350 EXPECT_DECLS("NestedNameSpecifierLoc", "namespace b");351 352 Code = R"cpp(353 namespace a { struct X { enum { y }; }; }354 int x = a::[[X::]]y;355 )cpp";356 EXPECT_DECLS("NestedNameSpecifierLoc", "struct X");357 358 Code = R"cpp(359 template <typename T>360 int x = [[T::]]y;361 )cpp";362 EXPECT_DECLS("NestedNameSpecifierLoc", "typename T");363 364 Code = R"cpp(365 namespace a { int x; }366 namespace b = a;367 int y = [[b]]::x;368 )cpp";369 EXPECT_DECLS("NestedNameSpecifierLoc", {"namespace b = a", Rel::Alias},370 {"namespace a", Rel::Underlying});371}372 373TEST_F(TargetDeclTest, Types) {374 Code = R"cpp(375 struct X{};376 [[X]] x;377 )cpp";378 EXPECT_DECLS("RecordTypeLoc", "struct X");379 380 Code = R"cpp(381 struct S{};382 typedef S X;383 [[X]] x;384 )cpp";385 EXPECT_DECLS("TypedefTypeLoc", {"typedef S X", Rel::Alias},386 {"struct S", Rel::Underlying});387 Code = R"cpp(388 namespace ns { struct S{}; }389 typedef ns::S X;390 [[X]] x;391 )cpp";392 EXPECT_DECLS("TypedefTypeLoc", {"typedef ns::S X", Rel::Alias},393 {"struct S", Rel::Underlying});394 395 Code = R"cpp(396 template<class T>397 void foo() { [[T]] x; }398 )cpp";399 EXPECT_DECLS("TemplateTypeParmTypeLoc", "class T");400 Flags.clear();401 402 Code = R"cpp(403 template<template<typename> class T>404 void foo() { [[T<int>]] x; }405 )cpp";406 EXPECT_DECLS("TemplateSpecializationTypeLoc", "template <typename> class T");407 Flags.clear();408 409 Code = R"cpp(410 template<template<typename> class ...T>411 class C {412 C<[[T...]]> foo;413 };414 )cpp";415 EXPECT_DECLS("TemplateArgumentLoc", {"template <typename> class ...T"});416 Flags.clear();417 418 Code = R"cpp(419 struct S{};420 S X;421 [[decltype]](X) Y;422 )cpp";423 EXPECT_DECLS("DecltypeTypeLoc", {"struct S", Rel::Underlying});424 425 Code = R"cpp(426 struct S{};427 [[auto]] X = S{};428 )cpp";429 // FIXME: deduced type missing in AST. https://llvm.org/PR42914430 EXPECT_DECLS("AutoTypeLoc", );431 432 Code = R"cpp(433 template <typename... E>434 struct S {435 static const int size = sizeof...([[E]]);436 };437 )cpp";438 EXPECT_DECLS("SizeOfPackExpr", "typename ...E");439 440 Code = R"cpp(441 template <typename T>442 class Foo {443 void f([[Foo]] x);444 };445 )cpp";446 EXPECT_DECLS("InjectedClassNameTypeLoc", "class Foo");447}448 449TEST_F(TargetDeclTest, ClassTemplate) {450 Code = R"cpp(451 // Implicit specialization.452 template<int x> class Foo{};453 [[Foo<42>]] B;454 )cpp";455 EXPECT_DECLS("TemplateSpecializationTypeLoc",456 {"template<> class Foo<42>", Rel::TemplateInstantiation},457 {"class Foo", Rel::TemplatePattern});458 459 Code = R"cpp(460 template<typename T> class Foo {};461 // The "Foo<int>" SpecializationDecl is incomplete, there is no462 // instantiation happening.463 void func([[Foo<int>]] *);464 )cpp";465 EXPECT_DECLS("TemplateSpecializationTypeLoc",466 {"class Foo", Rel::TemplatePattern},467 {"template<> class Foo<int>", Rel::TemplateInstantiation});468 469 Code = R"cpp(470 // Explicit specialization.471 template<int x> class Foo{};472 template<> class Foo<42>{};473 [[Foo<42>]] B;474 )cpp";475 EXPECT_DECLS("TemplateSpecializationTypeLoc", "template<> class Foo<42>");476 477 Code = R"cpp(478 // Partial specialization.479 template<typename T> class Foo{};480 template<typename T> class Foo<T*>{};481 [[Foo<int*>]] B;482 )cpp";483 EXPECT_DECLS("TemplateSpecializationTypeLoc",484 {"template<> class Foo<int *>", Rel::TemplateInstantiation},485 {"template <typename T> class Foo<T *>", Rel::TemplatePattern});486 487 Code = R"cpp(488 // Template template argument.489 template<typename T> struct Vector {};490 template <template <typename> class Container>491 struct A {};492 A<[[Vector]]> a;493 )cpp";494 EXPECT_DECLS("TemplateArgumentLoc", {"template <typename T> struct Vector"});495 496 Flags.push_back("-std=c++17"); // for CTAD tests497 498 Code = R"cpp(499 // Class template argument deduction500 template <typename T>501 struct Test {502 Test(T);503 };504 void foo() {505 [[Test]] a(5);506 }507 )cpp";508 EXPECT_DECLS("DeducedTemplateSpecializationTypeLoc",509 {"struct Test", Rel::TemplatePattern});510 511 Code = R"cpp(512 // Deduction guide513 template <typename T>514 struct Test {515 template <typename I>516 Test(I, I);517 };518 template <typename I>519 [[Test]](I, I) -> Test<typename I::type>;520 )cpp";521 EXPECT_DECLS("CXXDeductionGuideDecl", {"template <typename T> struct Test"});522}523 524TEST_F(TargetDeclTest, Concept) {525 Flags.push_back("-std=c++20");526 527 // FIXME: Should we truncate the pretty-printed form of a concept decl528 // somewhere?529 530 Code = R"cpp(531 template <typename T>532 concept Fooable = requires (T t) { t.foo(); };533 534 template <typename T> requires [[Fooable]]<T>535 void bar(T t) {536 t.foo();537 }538 )cpp";539 EXPECT_DECLS(540 "ConceptReference",541 {"template <typename T> concept Fooable = requires (T t) { t.foo(); }"});542 543 // trailing requires clause544 Code = R"cpp(545 template <typename T>546 concept Fooable = true;547 548 template <typename T>549 void foo() requires [[Fooable]]<T>;550 )cpp";551 EXPECT_DECLS("ConceptReference",552 {"template <typename T> concept Fooable = true"});553 554 // constrained-parameter555 Code = R"cpp(556 template <typename T>557 concept Fooable = true;558 559 template <[[Fooable]] T>560 void bar(T t);561 )cpp";562 EXPECT_DECLS("ConceptReference",563 {"template <typename T> concept Fooable = true"});564 565 // partial-concept-id566 Code = R"cpp(567 template <typename T, typename U>568 concept Fooable = true;569 570 template <[[Fooable]]<int> T>571 void bar(T t);572 )cpp";573 EXPECT_DECLS("ConceptReference",574 {"template <typename T, typename U> concept Fooable = true"});575}576 577TEST_F(TargetDeclTest, Coroutine) {578 Flags.push_back("-std=c++20");579 580 Code = R"cpp(581 namespace std {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;587 };588 } // namespace std589 590 struct executor {};591 struct awaitable {};592 struct awaitable_frame {593 awaitable get_return_object();594 void return_void();595 void unhandled_exception();596 struct result_t {597 ~result_t();598 bool await_ready() const noexcept;599 void await_suspend(std::coroutine_handle<void>) noexcept;600 void await_resume() const noexcept;601 };602 result_t initial_suspend() noexcept;603 result_t final_suspend() noexcept;604 result_t await_transform(executor) noexcept;605 };606 607 namespace std {608 template <>609 struct coroutine_traits<awaitable> {610 typedef awaitable_frame promise_type;611 };612 } // namespace std613 614 awaitable foo() {615 co_await [[executor]]();616 }617 )cpp";618 EXPECT_DECLS("RecordTypeLoc", "struct executor");619}620 621TEST_F(TargetDeclTest, RewrittenBinaryOperator) {622 Flags.push_back("-std=c++20");623 624 Code = R"cpp(625 namespace std {626 struct strong_ordering {627 int n;628 constexpr operator int() const { return n; }629 static const strong_ordering equal, greater, less;630 };631 constexpr strong_ordering strong_ordering::equal = {0};632 constexpr strong_ordering strong_ordering::greater = {1};633 constexpr strong_ordering strong_ordering::less = {-1};634 }635 636 struct Foo637 {638 int x;639 auto operator<=>(const Foo&) const = default;640 };641 642 bool x = (Foo(1) [[!=]] Foo(2));643 )cpp";644 EXPECT_DECLS("CXXRewrittenBinaryOperator",645 {"bool operator==(const Foo &) const noexcept = default"});646}647 648TEST_F(TargetDeclTest, FunctionTemplate) {649 Code = R"cpp(650 // Implicit specialization.651 template<typename T> bool foo(T) { return false; };652 bool x = [[foo]](42);653 )cpp";654 EXPECT_DECLS("DeclRefExpr",655 {"template<> bool foo<int>(int)", Rel::TemplateInstantiation},656 {"bool foo(T)", Rel::TemplatePattern});657 658 Code = R"cpp(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);663 )cpp";664 EXPECT_DECLS("DeclRefExpr", "template<> bool foo<int>(int)");665}666 667TEST_F(TargetDeclTest, VariableTemplate) {668 // Pretty-printer doesn't do a very good job of variable templates :-(669 Code = R"cpp(670 // Implicit specialization.671 template<typename T> int foo;672 int x = [[foo]]<char>;673 )cpp";674 EXPECT_DECLS("DeclRefExpr", {"int foo", Rel::TemplateInstantiation},675 {"int foo", Rel::TemplatePattern});676 677 Code = R"cpp(678 // Explicit specialization.679 template<typename T> int foo;680 template <> bool foo<char>;681 int x = [[foo]]<char>;682 )cpp";683 EXPECT_DECLS("DeclRefExpr", "bool foo");684 685 Code = R"cpp(686 // Partial specialization.687 template<typename T> int foo;688 template<typename T> bool foo<T*>;689 bool x = [[foo]]<char*>;690 )cpp";691 EXPECT_DECLS("DeclRefExpr", {"bool foo", Rel::TemplateInstantiation},692 {"bool foo", Rel::TemplatePattern});693}694 695TEST_F(TargetDeclTest, TypeAliasTemplate) {696 Code = R"cpp(697 template<typename T, int X> class SmallVector {};698 template<typename U> using TinyVector = SmallVector<U, 1>;699 [[TinyVector<int>]] X;700 )cpp";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});707}708 709TEST_F(TargetDeclTest, BuiltinTemplates) {710 Code = R"cpp(711 template <class T, T... Index> struct integer_sequence {};712 [[__make_integer_seq]]<integer_sequence, int, 3> X;713 )cpp";714 EXPECT_DECLS(715 "TemplateSpecializationTypeLoc",716 {"struct integer_sequence", Rel::TemplatePattern | Rel::Underlying},717 {"template<> struct integer_sequence<int, <0, 1, 2>>",718 Rel::TemplateInstantiation | Rel::Underlying});719 720 // Dependent context.721 Code = R"cpp(722 template <class T, T... Index> struct integer_sequence;723 724 template <class T, int N>725 using make_integer_sequence = [[__make_integer_seq]]<integer_sequence, T, N>;726 )cpp";727 EXPECT_DECLS("TemplateSpecializationTypeLoc", );728 729 Code = R"cpp(730 template <int N, class... Pack>731 using type_pack_element = [[__type_pack_element]]<N, Pack...>;732 )cpp";733 EXPECT_DECLS("TemplateSpecializationTypeLoc", );734 735 Code = R"cpp(736 template <template <class...> class Templ, class... Types>737 using dedup_types = Templ<[[__builtin_dedup_pack]]<Types...>...>;738 )cpp";739 EXPECT_DECLS("TemplateSpecializationTypeLoc", );740}741 742TEST_F(TargetDeclTest, MemberOfTemplate) {743 Code = R"cpp(744 template <typename T> struct Foo {745 int x(T);746 };747 int y = Foo<int>().[[x]](42);748 )cpp";749 EXPECT_DECLS("MemberExpr", {"int x(int)", Rel::TemplateInstantiation},750 {"int x(T)", Rel::TemplatePattern});751 752 Code = R"cpp(753 template <typename T> struct Foo {754 template <typename U>755 int x(T, U);756 };757 int y = Foo<char>().[[x]]('c', 42);758 )cpp";759 EXPECT_DECLS("MemberExpr",760 {"template<> int x<int>(char, int)", Rel::TemplateInstantiation},761 {"int x(T, U)", Rel::TemplatePattern});762}763 764TEST_F(TargetDeclTest, Lambda) {765 Code = R"cpp(766 void foo(int x = 42) {767 auto l = [ [[x]] ]{ return x + 1; };768 };769 )cpp";770 EXPECT_DECLS("DeclRefExpr", "int x = 42");771 772 // It seems like this should refer to another var, with the outer param being773 // an underlying decl. But it doesn't seem to exist.774 Code = R"cpp(775 void foo(int x = 42) {776 auto l = [x]{ return [[x]] + 1; };777 };778 )cpp";779 EXPECT_DECLS("DeclRefExpr", "int x = 42");780 781 Code = R"cpp(782 void foo() {783 auto l = [x = 1]{ return [[x]] + 1; };784 };785 )cpp";786 // FIXME: why both auto and int?787 EXPECT_DECLS("DeclRefExpr", "auto int x = 1");788}789 790TEST_F(TargetDeclTest, OverloadExpr) {791 Flags.push_back("--target=x86_64-pc-linux-gnu");792 793 Code = R"cpp(794 void func(int*);795 void func(char*);796 797 template <class T>798 void foo(T t) {799 [[func]](t);800 };801 )cpp";802 EXPECT_DECLS("UnresolvedLookupExpr", "void func(int *)", "void func(char *)");803 804 Code = R"cpp(805 struct X {806 void func(int*);807 void func(char*);808 };809 810 template <class T>811 void foo(X x, T t) {812 x.[[func]](t);813 };814 )cpp";815 EXPECT_DECLS("UnresolvedMemberExpr", "void func(int *)", "void func(char *)");816 817 Code = R"cpp(818 struct X {819 static void *operator new(unsigned long);820 };821 auto* k = [[new]] X();822 )cpp";823 EXPECT_DECLS("CXXNewExpr", "static void *operator new(unsigned long)");824 Code = R"cpp(825 void *operator new(unsigned long);826 auto* k = [[new]] int();827 )cpp";828 EXPECT_DECLS("CXXNewExpr", "void *operator new(unsigned long)");829 830 Code = R"cpp(831 struct X {832 static void operator delete(void *) noexcept;833 };834 void k(X* x) {835 [[delete]] x;836 }837 )cpp";838 EXPECT_DECLS("CXXDeleteExpr", "static void operator delete(void *) noexcept");839 Code = R"cpp(840 void operator delete(void *) noexcept;841 void k(int* x) {842 [[delete]] x;843 }844 )cpp";845 // Sized deallocation is enabled by default in C++14 onwards.846 EXPECT_DECLS("CXXDeleteExpr",847 "void operator delete(void *, __size_t) noexcept");848}849 850TEST_F(TargetDeclTest, DependentExprs) {851 Flags.push_back("--std=c++20");852 853 // Heuristic resolution of method of dependent field854 Code = R"cpp(855 struct A { void foo() {} };856 template <typename T>857 struct B {858 A a;859 void bar() {860 this->a.[[foo]]();861 }862 };863 )cpp";864 EXPECT_DECLS("MemberExpr", "void foo()");865 866 // Similar to above but base expression involves a function call.867 Code = R"cpp(868 struct A {869 void foo() {}870 };871 struct B {872 A getA();873 };874 template <typename T>875 struct C {876 B c;877 void bar() {878 this->c.getA().[[foo]]();879 }880 };881 )cpp";882 EXPECT_DECLS("MemberExpr", "void foo()");883 884 // Similar to above but uses a function pointer.885 Code = R"cpp(886 struct A {887 void foo() {}888 };889 struct B {890 using FPtr = A(*)();891 FPtr fptr;892 };893 template <typename T>894 struct C {895 B c;896 void bar() {897 this->c.fptr().[[foo]]();898 }899 };900 )cpp";901 EXPECT_DECLS("MemberExpr", "void foo()");902 903 // Base expression involves a member access into this.904 Code = R"cpp(905 struct Bar {906 int aaaa;907 };908 template <typename T> struct Foo {909 Bar func(int);910 void test() {911 func(1).[[aaaa]];912 }913 };914 )cpp";915 EXPECT_DECLS("CXXDependentScopeMemberExpr", "int aaaa");916 917 Code = R"cpp(918 class Foo {919 public:920 static Foo k(int);921 template <typename T> T convert() const;922 };923 template <typename T>924 void test() {925 Foo::k(T()).template [[convert]]<T>();926 }927 )cpp";928 EXPECT_DECLS("CXXDependentScopeMemberExpr",929 "template <typename T> T convert() const");930 931 Code = R"cpp(932 template <typename T>933 struct Waldo {934 void find();935 };936 template <typename T>937 using Wally = Waldo<T>;938 template <typename T>939 void foo(Wally<T> w) {940 w.[[find]]();941 }942 )cpp";943 EXPECT_DECLS("CXXDependentScopeMemberExpr", "void find()");944 945 Code = R"cpp(946 template <typename T>947 struct Waldo {948 void find();949 };950 template <typename T>951 struct MetaWaldo {952 using Type = Waldo<T>;953 };954 template <typename T>955 void foo(typename MetaWaldo<T>::Type w) {956 w.[[find]]();957 }958 )cpp";959 EXPECT_DECLS("CXXDependentScopeMemberExpr", "void find()");960 961 Code = R"cpp(962 struct Waldo {963 void find();964 };965 template <typename T>966 using Wally = Waldo;967 template <typename>968 struct S : Wally<int> {969 void Foo() { this->[[find]](); }970 };971 )cpp";972 EXPECT_DECLS("MemberExpr", "void find()");973 974 // Base expression is the type of a non-type template parameter975 // which is deduced using CTAD.976 Code = R"cpp(977 template <int N>978 struct Waldo {979 const int found = N;980 };981 982 template <Waldo W>983 int test() {984 return W.[[found]];985 }986 )cpp";987 EXPECT_DECLS("CXXDependentScopeMemberExpr", "const int found = N");988}989 990TEST_F(TargetDeclTest, DependentTypes) {991 // Heuristic resolution of dependent type name992 Code = R"cpp(993 template <typename>994 struct A { struct B {}; };995 996 template <typename T>997 void foo(typename A<T>::[[B]]);998 )cpp";999 EXPECT_DECLS("DependentNameTypeLoc", "struct B");1000 1001 // Heuristic resolution of dependent type name within a NestedNameSpecifierLoc1002 Code = R"cpp(1003 template <typename>1004 struct A { struct B { struct C {}; }; };1005 1006 template <typename T>1007 void foo(typename A<T>::[[B]]::C);1008 )cpp";1009 EXPECT_DECLS("DependentNameTypeLoc", "struct B");1010 1011 // Heuristic resolution of dependent type name whose qualifier is also1012 // dependent1013 Code = R"cpp(1014 template <typename>1015 struct A { struct B { struct C {}; }; };1016 1017 template <typename T>1018 void foo(typename A<T>::B::[[C]]);1019 )cpp";1020 EXPECT_DECLS("DependentNameTypeLoc", "struct C");1021 1022 // Heuristic resolution of dependent template name1023 Code = R"cpp(1024 template <typename>1025 struct A {1026 template <typename> struct B {};1027 };1028 1029 template <typename T>1030 void foo(typename A<T>::template [[B]]<int>);1031 )cpp";1032 EXPECT_DECLS("TemplateSpecializationTypeLoc", "template <typename> struct B");1033 1034 // Dependent name with recursive definition. We don't expect a1035 // result, but we shouldn't get into a stack overflow either.1036 Code = R"cpp(1037 template <int N>1038 struct waldo {1039 typedef typename waldo<N - 1>::type::[[next]] type;1040 };1041 )cpp";1042 EXPECT_DECLS("DependentNameTypeLoc", );1043 1044 // Similar to above but using mutually recursive templates.1045 Code = R"cpp(1046 template <int N>1047 struct odd;1048 1049 template <int N>1050 struct even {1051 using type = typename odd<N - 1>::type::next;1052 };1053 1054 template <int N>1055 struct odd {1056 using type = typename even<N - 1>::type::[[next]];1057 };1058 )cpp";1059 EXPECT_DECLS("DependentNameTypeLoc", );1060}1061 1062TEST_F(TargetDeclTest, TypedefCascade) {1063 Code = R"cpp(1064 struct C {1065 using type = int;1066 };1067 struct B {1068 using type = C::type;1069 };1070 struct A {1071 using type = B::type;1072 };1073 A::[[type]] waldo;1074 )cpp";1075 EXPECT_DECLS("TypedefTypeLoc",1076 {"using type = int", Rel::Alias | Rel::Underlying},1077 {"using type = C::type", Rel::Alias | Rel::Underlying},1078 {"using type = B::type", Rel::Alias});1079}1080 1081TEST_F(TargetDeclTest, RecursiveTemplate) {1082 Flags.push_back("-std=c++20"); // the test case uses concepts1083 1084 Code = R"cpp(1085 template <typename T>1086 concept Leaf = false;1087 1088 template <typename Tree>1089 struct descend_left {1090 using type = typename descend_left<typename Tree::left>::[[type]];1091 };1092 1093 template <Leaf Tree>1094 struct descend_left<Tree> {1095 using type = typename Tree::value;1096 };1097 )cpp";1098 EXPECT_DECLS("DependentNameTypeLoc",1099 {"using type = typename descend_left<typename Tree::left>::type",1100 Rel::Alias | Rel::Underlying});1101}1102 1103TEST_F(TargetDeclTest, ObjC) {1104 Flags = {"-xobjective-c"};1105 Code = R"cpp(1106 @interface Foo {}1107 -(void)bar;1108 @end1109 void test(Foo *f) {1110 [f [[bar]] ];1111 }1112 )cpp";1113 EXPECT_DECLS("ObjCMessageExpr", "- (void)bar");1114 1115 Code = R"cpp(1116 @interface Foo { @public int bar; }1117 @end1118 int test(Foo *f) {1119 return [[f->bar]];1120 }1121 )cpp";1122 EXPECT_DECLS("ObjCIvarRefExpr", "int bar");1123 1124 Code = R"cpp(1125 @interface Foo {}1126 -(int) x;1127 -(void) setX:(int)x;1128 @end1129 void test(Foo *f) {1130 [[f.x]] = 42;1131 }1132 )cpp";1133 EXPECT_DECLS("ObjCPropertyRefExpr", "- (void)setX:(int)x");1134 1135 Code = R"cpp(1136 @interface I {}1137 @property(retain) I* x;1138 @property(retain) I* y;1139 @end1140 void test(I *f) {1141 [[f.x]].y = 0;1142 }1143 )cpp";1144 EXPECT_DECLS("ObjCPropertyRefExpr",1145 "@property(atomic, retain, readwrite) I *x");1146 1147 Code = R"cpp(1148 @interface MYObject1149 @end1150 @interface Interface1151 @property(retain) [[MYObject]] *x;1152 @end1153 )cpp";1154 EXPECT_DECLS("ObjCInterfaceTypeLoc", "@interface MYObject");1155 1156 Code = R"cpp(1157 @interface MYObject21158 @end1159 @interface Interface1160 @property(retain, nonnull) [[MYObject2]] *x;1161 @end1162 )cpp";1163 EXPECT_DECLS("ObjCInterfaceTypeLoc", "@interface MYObject2");1164 1165 Code = R"cpp(1166 @protocol Foo1167 @end1168 id test() {1169 return [[@protocol(Foo)]];1170 }1171 )cpp";1172 EXPECT_DECLS("ObjCProtocolExpr", "@protocol Foo");1173 1174 Code = R"cpp(1175 @interface Foo1176 @end1177 void test([[Foo]] *p);1178 )cpp";1179 EXPECT_DECLS("ObjCInterfaceTypeLoc", "@interface Foo");1180 1181 Code = R"cpp(// Don't consider implicit interface as the target.1182 @implementation [[Implicit]]1183 @end1184 )cpp";1185 EXPECT_DECLS("ObjCImplementationDecl", "@implementation Implicit");1186 1187 Code = R"cpp(1188 @interface Foo1189 @end1190 @implementation [[Foo]]1191 @end1192 )cpp";1193 EXPECT_DECLS("ObjCImplementationDecl", "@interface Foo");1194 1195 Code = R"cpp(1196 @interface Foo1197 @end1198 @interface Foo (Ext)1199 @end1200 @implementation [[Foo]] (Ext)1201 @end1202 )cpp";1203 EXPECT_DECLS("ObjCCategoryImplDecl", "@interface Foo(Ext)");1204 1205 Code = R"cpp(1206 @interface Foo1207 @end1208 @interface Foo (Ext)1209 @end1210 @implementation Foo ([[Ext]])1211 @end1212 )cpp";1213 EXPECT_DECLS("ObjCCategoryImplDecl", "@interface Foo(Ext)");1214 1215 Code = R"cpp(1216 void test(id</*error-ok*/[[InvalidProtocol]]> p);1217 )cpp";1218 EXPECT_DECLS("ParmVarDecl", "id p");1219 1220 Code = R"cpp(1221 @class C;1222 @protocol Foo1223 @end1224 void test([[C]]<Foo> *p);1225 )cpp";1226 EXPECT_DECLS("ObjCInterfaceTypeLoc", "@class C;");1227 1228 Code = R"cpp(1229 @class C;1230 @protocol Foo1231 @end1232 void test(C<[[Foo]]> *p);1233 )cpp";1234 EXPECT_DECLS("ObjCProtocolLoc", "@protocol Foo");1235 1236 Code = R"cpp(1237 @class C;1238 @protocol Foo1239 @end1240 @protocol Bar1241 @end1242 void test(C<[[Foo]], Bar> *p);1243 )cpp";1244 EXPECT_DECLS("ObjCProtocolLoc", "@protocol Foo");1245 1246 Code = R"cpp(1247 @class C;1248 @protocol Foo1249 @end1250 @protocol Bar1251 @end1252 void test(C<Foo, [[Bar]]> *p);1253 )cpp";1254 EXPECT_DECLS("ObjCProtocolLoc", "@protocol Bar");1255 1256 Code = R"cpp(1257 @interface Foo1258 + (id)sharedInstance;1259 @end1260 @implementation Foo1261 + (id)sharedInstance { return 0; }1262 @end1263 void test() {1264 id value = [[Foo]].sharedInstance;1265 }1266 )cpp";1267 EXPECT_DECLS("ObjCInterfaceTypeLoc", "@interface Foo");1268 1269 Code = R"cpp(1270 @interface Foo1271 + (id)sharedInstance;1272 @end1273 @implementation Foo1274 + (id)sharedInstance { return 0; }1275 @end1276 void test() {1277 id value = Foo.[[sharedInstance]];1278 }1279 )cpp";1280 EXPECT_DECLS("ObjCPropertyRefExpr", "+ (id)sharedInstance");1281 1282 Code = R"cpp(1283 @interface Foo1284 + ([[id]])sharedInstance;1285 @end1286 )cpp";1287 EXPECT_DECLS("TypedefTypeLoc", );1288 1289 Code = R"cpp(1290 @interface Foo1291 + ([[instancetype]])sharedInstance;1292 @end1293 )cpp";1294 EXPECT_DECLS("TypedefTypeLoc", );1295}1296 1297class FindExplicitReferencesTest : public ::testing::Test {1298protected:1299 struct AllRefs {1300 std::string AnnotatedCode;1301 std::string DumpedReferences;1302 };1303 1304 TestTU newTU(llvm::StringRef Code) {1305 TestTU TU;1306 TU.Code = std::string(Code);1307 1308 // FIXME: Auto-completion in a template requires disabling delayed template1309 // parsing.1310 TU.ExtraArgs.push_back("-std=c++20");1311 TU.ExtraArgs.push_back("-xobjective-c++");1312 1313 return TU;1314 }1315 1316 AllRefs annotatedReferences(llvm::StringRef Code, ParsedAST &AST,1317 std::vector<ReferenceLoc> Refs) {1318 auto &SM = AST.getSourceManager();1319 llvm::stable_sort(Refs, [&](const ReferenceLoc &L, const ReferenceLoc &R) {1320 return SM.isBeforeInTranslationUnit(L.NameLoc, R.NameLoc);1321 });1322 1323 std::string AnnotatedCode;1324 unsigned NextCodeChar = 0;1325 for (unsigned I = 0; I < Refs.size(); ++I) {1326 auto &R = Refs[I];1327 1328 SourceLocation Pos = R.NameLoc;1329 assert(Pos.isValid());1330 if (Pos.isMacroID()) // FIXME: figure out how to show macro locations.1331 Pos = SM.getExpansionLoc(Pos);1332 assert(Pos.isFileID());1333 1334 FileID File;1335 unsigned Offset;1336 std::tie(File, Offset) = SM.getDecomposedLoc(Pos);1337 if (File == SM.getMainFileID()) {1338 // Print the reference in a source code.1339 assert(NextCodeChar <= Offset);1340 AnnotatedCode += Code.substr(NextCodeChar, Offset - NextCodeChar);1341 AnnotatedCode += "$" + std::to_string(I) + "^";1342 1343 NextCodeChar = Offset;1344 }1345 }1346 AnnotatedCode += Code.substr(NextCodeChar);1347 1348 std::string DumpedReferences;1349 for (unsigned I = 0; I < Refs.size(); ++I)1350 DumpedReferences += std::string(llvm::formatv("{0}: {1}\n", I, Refs[I]));1351 1352 return AllRefs{std::move(AnnotatedCode), std::move(DumpedReferences)};1353 }1354 1355 /// Parses \p Code, and annotates its body with results of1356 /// findExplicitReferences on all top level decls.1357 /// See actual tests for examples of annotation format.1358 AllRefs annotateAllReferences(llvm::StringRef Code) {1359 TestTU TU = newTU(Code);1360 auto AST = TU.build();1361 1362 std::vector<ReferenceLoc> Refs;1363 for (auto *TopLevel : AST.getLocalTopLevelDecls())1364 findExplicitReferences(1365 TopLevel, [&Refs](ReferenceLoc R) { Refs.push_back(std::move(R)); },1366 AST.getHeuristicResolver());1367 return annotatedReferences(Code, AST, std::move(Refs));1368 }1369 1370 /// Parses \p Code, finds function or namespace '::foo' and annotates its body1371 /// with results of findExplicitReferences.1372 /// See actual tests for examples of annotation format.1373 AllRefs annotateReferencesInFoo(llvm::StringRef Code) {1374 TestTU TU = newTU(Code);1375 auto AST = TU.build();1376 auto *TestDecl = &findDecl(AST, "foo");1377 if (auto *T = llvm::dyn_cast<FunctionTemplateDecl>(TestDecl))1378 TestDecl = T->getTemplatedDecl();1379 1380 std::vector<ReferenceLoc> Refs;1381 if (const auto *Func = llvm::dyn_cast<FunctionDecl>(TestDecl))1382 findExplicitReferences(1383 Func->getBody(),1384 [&Refs](ReferenceLoc R) { Refs.push_back(std::move(R)); },1385 AST.getHeuristicResolver());1386 else if (const auto *NS = llvm::dyn_cast<NamespaceDecl>(TestDecl))1387 findExplicitReferences(1388 NS,1389 [&Refs, &NS](ReferenceLoc R) {1390 // Avoid adding the namespace foo decl to the results.1391 if (R.Targets.size() == 1 && R.Targets.front() == NS)1392 return;1393 Refs.push_back(std::move(R));1394 },1395 AST.getHeuristicResolver());1396 else if (const auto *OC = llvm::dyn_cast<ObjCContainerDecl>(TestDecl))1397 findExplicitReferences(1398 OC, [&Refs](ReferenceLoc R) { Refs.push_back(std::move(R)); },1399 AST.getHeuristicResolver());1400 else1401 ADD_FAILURE() << "Failed to find ::foo decl for test";1402 1403 return annotatedReferences(Code, AST, std::move(Refs));1404 }1405};1406 1407TEST_F(FindExplicitReferencesTest, AllRefsInFoo) {1408 std::pair</*Code*/ llvm::StringRef, /*References*/ llvm::StringRef> Cases[] =1409 {// Simple expressions.1410 {R"cpp(1411 int global;1412 int func();1413 void foo(int param) {1414 $0^global = $1^param + $2^func();1415 }1416 )cpp",1417 "0: targets = {global}\n"1418 "1: targets = {param}\n"1419 "2: targets = {func}\n"},1420 {R"cpp(1421 struct X { int a; };1422 void foo(X x) {1423 $0^x.$1^a = 10;1424 }1425 )cpp",1426 "0: targets = {x}\n"1427 "1: targets = {X::a}\n"},1428 {R"cpp(1429 // error-ok: testing with broken code1430 int bar();1431 int foo() {1432 return $0^bar() + $1^bar(42);1433 }1434 )cpp",1435 "0: targets = {bar}\n"1436 "1: targets = {bar}\n"},1437 // Namespaces and aliases.1438 {R"cpp(1439 namespace ns {}1440 namespace alias = ns;1441 void foo() {1442 using namespace $0^ns;1443 using namespace $1^alias;1444 }1445 )cpp",1446 "0: targets = {ns}\n"1447 "1: targets = {alias}\n"},1448 // Using declarations.1449 {R"cpp(1450 namespace ns { int global; }1451 void foo() {1452 using $0^ns::$1^global;1453 }1454 )cpp",1455 "0: targets = {ns}\n"1456 "1: targets = {ns::global}, qualifier = 'ns::'\n"},1457 // Using enum declarations.1458 {R"cpp(1459 namespace ns { enum class A {}; }1460 void foo() {1461 using enum $0^ns::$1^A;1462 }1463 )cpp",1464 "0: targets = {ns}\n"1465 "1: targets = {ns::A}, qualifier = 'ns::'\n"},1466 // Simple types.1467 {R"cpp(1468 struct Struct { int a; };1469 using Typedef = int;1470 void foo() {1471 $0^Struct $1^x;1472 $2^Typedef $3^y;1473 static_cast<$4^Struct*>(0);1474 }1475 )cpp",1476 "0: targets = {Struct}\n"1477 "1: targets = {x}, decl\n"1478 "2: targets = {Typedef}\n"1479 "3: targets = {y}, decl\n"1480 "4: targets = {Struct}\n"},1481 // Name qualifiers.1482 {R"cpp(1483 namespace a { namespace b { struct S { typedef int type; }; } }1484 void foo() {1485 $0^a::$1^b::$2^S $3^x;1486 using namespace $4^a::$5^b;1487 $6^S::$7^type $8^y;1488 }1489 )cpp",1490 "0: targets = {a}\n"1491 "1: targets = {a::b}, qualifier = 'a::'\n"1492 "2: targets = {a::b::S}, qualifier = 'a::b::'\n"1493 "3: targets = {x}, decl\n"1494 "4: targets = {a}\n"1495 "5: targets = {a::b}, qualifier = 'a::'\n"1496 "6: targets = {a::b::S}\n"1497 "7: targets = {a::b::S::type}, qualifier = 'S::'\n"1498 "8: targets = {y}, decl\n"},1499 {R"cpp(1500 void foo() {1501 $0^ten: // PRINT "HELLO WORLD!"1502 goto $1^ten;1503 }1504 )cpp",1505 "0: targets = {ten}, decl\n"1506 "1: targets = {ten}\n"},1507 // Simple templates.1508 {R"cpp(1509 template <class T> struct vector { using value_type = T; };1510 template <> struct vector<bool> { using value_type = bool; };1511 void foo() {1512 $0^vector<int> $1^vi;1513 $2^vector<bool> $3^vb;1514 }1515 )cpp",1516 "0: targets = {vector<int>}\n"1517 "1: targets = {vi}, decl\n"1518 "2: targets = {vector<bool>}\n"1519 "3: targets = {vb}, decl\n"},1520 // Template type aliases.1521 {R"cpp(1522 template <class T> struct vector { using value_type = T; };1523 template <> struct vector<bool> { using value_type = bool; };1524 template <class T> using valias = vector<T>;1525 void foo() {1526 $0^valias<int> $1^vi;1527 $2^valias<bool> $3^vb;1528 }1529 )cpp",1530 "0: targets = {valias}\n"1531 "1: targets = {vi}, decl\n"1532 "2: targets = {valias}\n"1533 "3: targets = {vb}, decl\n"},1534 // Injected class name.1535 {R"cpp(1536 namespace foo {1537 template <typename $0^T>1538 class $1^Bar {1539 ~$2^Bar();1540 void $3^f($4^Bar);1541 };1542 }1543 )cpp",1544 "0: targets = {foo::Bar::T}, decl\n"1545 "1: targets = {foo::Bar}, decl\n"1546 "2: targets = {foo::Bar}\n"1547 "3: targets = {foo::Bar::f}, decl\n"1548 "4: targets = {foo::Bar}\n"},1549 // MemberExpr should know their using declaration.1550 {R"cpp(1551 struct X { void func(int); };1552 struct Y : X {1553 using X::func;1554 };1555 void foo(Y y) {1556 $0^y.$1^func(1);1557 }1558 )cpp",1559 "0: targets = {y}\n"1560 "1: targets = {Y::func}\n"},1561 // DeclRefExpr should know their using declaration.1562 {R"cpp(1563 namespace ns { void bar(int); }1564 using ns::bar;1565 1566 void foo() {1567 $0^bar(10);1568 }1569 )cpp",1570 "0: targets = {bar}\n"},1571 // References from a macro.1572 {R"cpp(1573 #define FOO a1574 #define BAR b1575 1576 void foo(int a, int b) {1577 $0^FOO+$1^BAR;1578 }1579 )cpp",1580 "0: targets = {a}\n"1581 "1: targets = {b}\n"},1582 // No references from implicit nodes.1583 {R"cpp(1584 struct vector {1585 int *begin();1586 int *end();1587 };1588 1589 void foo() {1590 for (int $0^x : $1^vector()) {1591 $2^x = 10;1592 }1593 }1594 )cpp",1595 "0: targets = {x}, decl\n"1596 "1: targets = {vector}\n"1597 "2: targets = {x}\n"},1598 // Handle UnresolvedLookupExpr.1599 {R"cpp(1600 namespace ns1 { void func(char*); }1601 namespace ns2 { void func(int*); }1602 using namespace ns1;1603 using namespace ns2;1604 1605 template <class T>1606 void foo(T t) {1607 $0^func($1^t);1608 }1609 )cpp",1610 "0: targets = {ns1::func, ns2::func}\n"1611 "1: targets = {t}\n"},1612 // Handle UnresolvedMemberExpr.1613 {R"cpp(1614 struct X {1615 void func(char*);1616 void func(int*);1617 };1618 1619 template <class T>1620 void foo(X x, T t) {1621 $0^x.$1^func($2^t);1622 }1623 )cpp",1624 "0: targets = {x}\n"1625 "1: targets = {X::func, X::func}\n"1626 "2: targets = {t}\n"},1627 // Handle DependentScopeDeclRefExpr.1628 {R"cpp(1629 template <class T>1630 struct S {1631 static int value;1632 };1633 1634 template <class T>1635 void foo() {1636 $0^S<$1^T>::$2^value;1637 }1638 )cpp",1639 "0: targets = {S}\n"1640 "1: targets = {T}\n"1641 "2: targets = {S::value}, qualifier = 'S<T>::'\n"},1642 // Handle CXXDependentScopeMemberExpr.1643 {R"cpp(1644 template <class T>1645 struct S {1646 int value;1647 };1648 1649 template <class T>1650 void foo(S<T> t) {1651 $0^t.$1^value;1652 }1653 )cpp",1654 "0: targets = {t}\n"1655 "1: targets = {S::value}\n"},1656 // Type template parameters.1657 {R"cpp(1658 template <class T>1659 void foo() {1660 static_cast<$0^T>(0);1661 $1^T();1662 $2^T $3^t;1663 }1664 )cpp",1665 "0: targets = {T}\n"1666 "1: targets = {T}\n"1667 "2: targets = {T}\n"1668 "3: targets = {t}, decl\n"},1669 // Non-type template parameters.1670 {R"cpp(1671 template <int I>1672 void foo() {1673 int $0^x = $1^I;1674 }1675 )cpp",1676 "0: targets = {x}, decl\n"1677 "1: targets = {I}\n"},1678 // Template template parameters.1679 {R"cpp(1680 template <class T> struct vector {};1681 1682 template <template<class> class TT, template<class> class ...TP>1683 void foo() {1684 $0^TT<int> $1^x;1685 $2^foo<$3^TT>();1686 $4^foo<$5^vector>();1687 $6^foo<$7^TP...>();1688 }1689 )cpp",1690 "0: targets = {TT}\n"1691 "1: targets = {x}, decl\n"1692 "2: targets = {foo}\n"1693 "3: targets = {TT}\n"1694 "4: targets = {foo}\n"1695 "5: targets = {vector}\n"1696 "6: targets = {foo}\n"1697 "7: targets = {TP}\n"},1698 // Non-type template parameters with declarations.1699 {R"cpp(1700 int func();1701 template <int(*)()> struct wrapper {};1702 1703 template <int(*FuncParam)()>1704 void foo() {1705 $0^wrapper<$1^func> $2^w;1706 $3^FuncParam();1707 }1708 )cpp",1709 "0: targets = {wrapper<&func>}\n"1710 "1: targets = {func}\n"1711 "2: targets = {w}, decl\n"1712 "3: targets = {FuncParam}\n"},1713 // declaration references.1714 {R"cpp(1715 namespace ns {}1716 class S {};1717 void foo() {1718 class $0^Foo { $1^Foo(); ~$2^Foo(); int $3^field; };1719 int $4^Var;1720 enum $5^E { $6^ABC };1721 typedef int $7^INT;1722 using $8^INT2 = int;1723 namespace $9^NS = $10^ns;1724 }1725 )cpp",1726 "0: targets = {Foo}, decl\n"1727 "1: targets = {foo()::Foo::Foo}, decl\n"1728 "2: targets = {Foo}\n"1729 "3: targets = {foo()::Foo::field}, decl\n"1730 "4: targets = {Var}, decl\n"1731 "5: targets = {E}, decl\n"1732 "6: targets = {foo()::ABC}, decl\n"1733 "7: targets = {INT}, decl\n"1734 "8: targets = {INT2}, decl\n"1735 "9: targets = {NS}, decl\n"1736 "10: targets = {ns}\n"},1737 // User-defined conversion operator.1738 {R"cpp(1739 void foo() {1740 class $0^Bar {};1741 class $1^Foo {1742 public:1743 // FIXME: This should have only one reference to Bar.1744 $2^operator $3^$4^Bar();1745 };1746 1747 $5^Foo $6^f;1748 $7^f.$8^operator $9^Bar();1749 }1750 )cpp",1751 "0: targets = {Bar}, decl\n"1752 "1: targets = {Foo}, decl\n"1753 "2: targets = {foo()::Foo::operator Bar}, decl\n"1754 "3: targets = {Bar}\n"1755 "4: targets = {Bar}\n"1756 "5: targets = {Foo}\n"1757 "6: targets = {f}, decl\n"1758 "7: targets = {f}\n"1759 "8: targets = {foo()::Foo::operator Bar}\n"1760 "9: targets = {Bar}\n"},1761 // Destructor.1762 {R"cpp(1763 void foo() {1764 class $0^Foo {1765 public:1766 ~$1^Foo() {}1767 1768 void $2^destructMe() {1769 this->~$3^Foo();1770 }1771 };1772 1773 $4^Foo $5^f;1774 $6^f.~ /*...*/ $7^Foo();1775 }1776 )cpp",1777 "0: targets = {Foo}, decl\n"1778 // FIXME: It's better to target destructor's FunctionDecl instead of1779 // the type itself (similar to constructor).1780 "1: targets = {Foo}\n"1781 "2: targets = {foo()::Foo::destructMe}, decl\n"1782 "3: targets = {Foo}\n"1783 "4: targets = {Foo}\n"1784 "5: targets = {f}, decl\n"1785 "6: targets = {f}\n"1786 "7: targets = {Foo}\n"},1787 // cxx constructor initializer.1788 {R"cpp(1789 class Base {};1790 void foo() {1791 // member initializer1792 class $0^X {1793 int $1^abc;1794 $2^X(): $3^abc() {}1795 };1796 // base initializer1797 class $4^Derived : public $5^Base {1798 $6^Base $7^B;1799 $8^Derived() : $9^Base() {}1800 };1801 // delegating initializer1802 class $10^Foo {1803 $11^Foo(int);1804 $12^Foo(): $13^Foo(111) {}1805 };1806 }1807 )cpp",1808 "0: targets = {X}, decl\n"1809 "1: targets = {foo()::X::abc}, decl\n"1810 "2: targets = {foo()::X::X}, decl\n"1811 "3: targets = {foo()::X::abc}\n"1812 "4: targets = {Derived}, decl\n"1813 "5: targets = {Base}\n"1814 "6: targets = {Base}\n"1815 "7: targets = {foo()::Derived::B}, decl\n"1816 "8: targets = {foo()::Derived::Derived}, decl\n"1817 "9: targets = {Base}\n"1818 "10: targets = {Foo}, decl\n"1819 "11: targets = {foo()::Foo::Foo}, decl\n"1820 "12: targets = {foo()::Foo::Foo}, decl\n"1821 "13: targets = {Foo}\n"},1822 // Anonymous entities should not be reported.1823 {1824 R"cpp(1825 void foo() {1826 $0^class {} $1^x;1827 int (*$2^fptr)(int $3^a, int) = nullptr;1828 }1829 )cpp",1830 "0: targets = {(unnamed)}\n"1831 "1: targets = {x}, decl\n"1832 "2: targets = {fptr}, decl\n"1833 "3: targets = {a}, decl\n"},1834 // Namespace aliases should be handled properly.1835 {1836 R"cpp(1837 namespace ns { struct Type {}; }1838 namespace alias = ns;1839 namespace rec_alias = alias;1840 1841 void foo() {1842 $0^ns::$1^Type $2^a;1843 $3^alias::$4^Type $5^b;1844 $6^rec_alias::$7^Type $8^c;1845 }1846 )cpp",1847 "0: targets = {ns}\n"1848 "1: targets = {ns::Type}, qualifier = 'ns::'\n"1849 "2: targets = {a}, decl\n"1850 "3: targets = {alias}\n"1851 "4: targets = {ns::Type}, qualifier = 'alias::'\n"1852 "5: targets = {b}, decl\n"1853 "6: targets = {rec_alias}\n"1854 "7: targets = {ns::Type}, qualifier = 'rec_alias::'\n"1855 "8: targets = {c}, decl\n"},1856 // Handle SizeOfPackExpr.1857 {1858 R"cpp(1859 template <typename... E>1860 void foo() {1861 constexpr int $0^size = sizeof...($1^E);1862 };1863 )cpp",1864 "0: targets = {size}, decl\n"1865 "1: targets = {E}\n"},1866 // Class template argument deduction1867 {1868 R"cpp(1869 template <typename T>1870 struct Test {1871 Test(T);1872 };1873 void foo() {1874 $0^Test $1^a(5);1875 }1876 )cpp",1877 "0: targets = {Test}\n"1878 "1: targets = {a}, decl\n"},1879 // Templates1880 {R"cpp(1881 namespace foo {1882 template <typename $0^T>1883 class $1^Bar {};1884 }1885 )cpp",1886 "0: targets = {foo::Bar::T}, decl\n"1887 "1: targets = {foo::Bar}, decl\n"},1888 // Templates1889 {R"cpp(1890 namespace foo {1891 template <typename $0^T>1892 void $1^func();1893 }1894 )cpp",1895 "0: targets = {T}, decl\n"1896 "1: targets = {foo::func}, decl\n"},1897 // Templates1898 {R"cpp(1899 namespace foo {1900 template <typename $0^T>1901 $1^T $2^x;1902 }1903 )cpp",1904 "0: targets = {foo::T}, decl\n"1905 "1: targets = {foo::T}\n"1906 "2: targets = {foo::x}, decl\n"},1907 // Templates1908 {R"cpp(1909 template<typename T> class vector {};1910 namespace foo {1911 template <typename $0^T>1912 using $1^V = $2^vector<$3^T>;1913 }1914 )cpp",1915 "0: targets = {foo::T}, decl\n"1916 "1: targets = {foo::V}, decl\n"1917 "2: targets = {vector}\n"1918 "3: targets = {foo::T}\n"},1919 // Concept1920 {1921 R"cpp(1922 template <typename T>1923 concept Drawable = requires (T t) { t.draw(); };1924 1925 namespace foo {1926 template <typename $0^T> requires $1^Drawable<$2^T>1927 void $3^bar($4^T $5^t) {1928 $6^t.$7^draw();1929 }1930 }1931 )cpp",1932 "0: targets = {T}, decl\n"1933 "1: targets = {Drawable}\n"1934 "2: targets = {T}\n"1935 "3: targets = {foo::bar}, decl\n"1936 "4: targets = {T}\n"1937 "5: targets = {t}, decl\n"1938 "6: targets = {t}\n"1939 "7: targets = {}\n"},1940 // Objective-C: instance variables1941 {1942 R"cpp(1943 @interface I {1944 @public1945 I *_z;1946 }1947 @end1948 I *f;1949 void foo() {1950 $0^f->$1^_z = 0;1951 }1952 )cpp",1953 "0: targets = {f}\n"1954 "1: targets = {I::_z}\n"},1955 // Objective-C: properties1956 {1957 R"cpp(1958 @interface I {}1959 @property(retain) I* x;1960 @property(retain) I* y;1961 @end1962 I *f;1963 void foo() {1964 $0^f.$1^x.$2^y = 0;1965 }1966 )cpp",1967 "0: targets = {f}\n"1968 "1: targets = {I::x}\n"1969 "2: targets = {I::y}\n"},1970 // Objective-C: implicit properties1971 {1972 R"cpp(1973 @interface I {}1974 -(I*)x;1975 -(void)setY:(I*)y;1976 @end1977 I *f;1978 void foo() {1979 $0^f.$1^x.$2^y = 0;1980 }1981 )cpp",1982 "0: targets = {f}\n"1983 "1: targets = {I::x}\n"1984 "2: targets = {I::setY:}\n"},1985 // Objective-C: class properties1986 {1987 R"cpp(1988 @interface I {}1989 @property(class) I *x;1990 @end1991 id local;1992 void foo() {1993 $0^I.$1^x = 0;1994 $2^local = $3^I.$4^x;1995 }1996 )cpp",1997 "0: targets = {I}\n"1998 "1: targets = {I::setX:}\n"1999 "2: targets = {local}\n"2000 "3: targets = {I}\n"2001 "4: targets = {I::x}\n"},2002 // Objective-C: implicit class properties2003 {2004 R"cpp(2005 @interface I {}2006 +(I*)x;2007 +(void)setX:(I*)x;2008 @end2009 id local;2010 void foo() {2011 $0^I.$1^x = 0;2012 $2^local = $3^I.$4^x;2013 }2014 )cpp",2015 "0: targets = {I}\n"2016 "1: targets = {I::setX:}\n"2017 "2: targets = {local}\n"2018 "3: targets = {I}\n"2019 "4: targets = {I::x}\n"},2020 {// Objective-C: methods2021 R"cpp(2022 @interface I2023 -(void) a:(int)x b:(int)y;2024 @end2025 void foo(I *i) {2026 [$0^i $1^a:1 b:2];2027 }2028 )cpp",2029 "0: targets = {i}\n"2030 "1: targets = {I::a:b:}\n"},2031 {// Objective-C: protocols2032 R"cpp(2033 @interface I2034 @end2035 @protocol P2036 @end2037 void foo() {2038 $0^I<$1^P> *$2^x;2039 }2040 )cpp",2041 "0: targets = {I}\n"2042 "1: targets = {P}\n"2043 "2: targets = {x}, decl\n"},2044 2045 // Designated initializers.2046 {R"cpp(2047 void foo() {2048 struct $0^Foo {2049 int $1^Bar;2050 };2051 $2^Foo $3^f { .$4^Bar = 42 };2052 }2053 )cpp",2054 "0: targets = {Foo}, decl\n"2055 "1: targets = {foo()::Foo::Bar}, decl\n"2056 "2: targets = {Foo}\n"2057 "3: targets = {f}, decl\n"2058 "4: targets = {foo()::Foo::Bar}\n"},2059 {R"cpp(2060 void foo() {2061 struct $0^Baz {2062 int $1^Field;2063 };2064 struct $2^Bar {2065 $3^Baz $4^Foo;2066 };2067 $5^Bar $6^bar { .$7^Foo.$8^Field = 42 };2068 }2069 )cpp",2070 "0: targets = {Baz}, decl\n"2071 "1: targets = {foo()::Baz::Field}, decl\n"2072 "2: targets = {Bar}, decl\n"2073 "3: targets = {Baz}\n"2074 "4: targets = {foo()::Bar::Foo}, decl\n"2075 "5: targets = {Bar}\n"2076 "6: targets = {bar}, decl\n"2077 "7: targets = {foo()::Bar::Foo}\n"2078 "8: targets = {foo()::Baz::Field}\n"},2079 {R"cpp(2080 template<typename T>2081 void crash(T);2082 template<typename T>2083 void foo() {2084 $0^crash({.$1^x = $2^T()});2085 }2086 )cpp",2087 "0: targets = {crash}\n"2088 "1: targets = {}\n"2089 "2: targets = {T}\n"},2090 // unknown template name should not crash.2091 {R"cpp(2092 template <template <typename> typename T>2093 struct Base {};2094 namespace foo {2095 template <typename $0^T>2096 struct $1^Derive : $2^Base<$3^T::template $4^Unknown> {};2097 }2098 )cpp",2099 "0: targets = {foo::Derive::T}, decl\n"2100 "1: targets = {foo::Derive}, decl\n"2101 "2: targets = {Base}\n"2102 "3: targets = {foo::Derive::T}\n"2103 "4: targets = {}, qualifier = 'T::'\n"},2104 // deduction guide2105 {R"cpp(2106 namespace foo {2107 template <typename $0^T>2108 struct $1^Test {2109 template <typename $2^I>2110 $3^Test($4^I);2111 };2112 template <typename $5^I>2113 $6^Test($7^I) -> $8^Test<typename $9^I::$10^type>;2114 }2115 )cpp",2116 "0: targets = {T}, decl\n"2117 "1: targets = {foo::Test}, decl\n"2118 "2: targets = {I}, decl\n"2119 "3: targets = {foo::Test::Test<T>}, decl\n"2120 "4: targets = {I}\n"2121 "5: targets = {I}, decl\n"2122 "6: targets = {foo::Test}\n"2123 "7: targets = {I}\n"2124 "8: targets = {foo::Test}\n"2125 "9: targets = {I}\n"2126 "10: targets = {}, qualifier = 'I::'\n"}};2127 2128 for (const auto &C : Cases) {2129 llvm::StringRef ExpectedCode = C.first;2130 llvm::StringRef ExpectedRefs = C.second;2131 2132 auto Actual =2133 annotateReferencesInFoo(llvm::Annotations(ExpectedCode).code());2134 EXPECT_EQ(ExpectedCode, Actual.AnnotatedCode);2135 EXPECT_EQ(ExpectedRefs, Actual.DumpedReferences) << ExpectedCode;2136 }2137}2138 2139TEST_F(FindExplicitReferencesTest, AllRefs) {2140 std::pair</*Code*/ llvm::StringRef, /*References*/ llvm::StringRef> Cases[] =2141 {{R"cpp(2142 @interface $0^MyClass2143 @end2144 @implementation $1^$2^MyClass2145 @end2146 )cpp",2147 "0: targets = {MyClass}, decl\n"2148 "1: targets = {MyClass}\n"2149 "2: targets = {MyClass}, decl\n"},2150 {R"cpp(2151 @interface $0^MyClass2152 @end2153 @interface $1^MyClass ($2^Category)2154 @end2155 @implementation $3^MyClass ($4^$5^Category)2156 @end2157 )cpp",2158 "0: targets = {MyClass}, decl\n"2159 "1: targets = {MyClass}\n"2160 "2: targets = {Category}, decl\n"2161 "3: targets = {MyClass}\n"2162 "4: targets = {Category}\n"2163 "5: targets = {Category}, decl\n"}};2164 2165 for (const auto &C : Cases) {2166 llvm::StringRef ExpectedCode = C.first;2167 llvm::StringRef ExpectedRefs = C.second;2168 2169 auto Actual = annotateAllReferences(llvm::Annotations(ExpectedCode).code());2170 EXPECT_EQ(ExpectedCode, Actual.AnnotatedCode);2171 EXPECT_EQ(ExpectedRefs, Actual.DumpedReferences) << ExpectedCode;2172 }2173}2174 2175} // namespace2176} // namespace clangd2177} // namespace clang2178