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/Support/Annotations.h" 19 #include "gmock/gmock.h" 20 #include "gtest/gtest.h" 21 #include <initializer_list> 37 PrintedDecl(
const NamedDecl *D, DeclRelationSet
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 = FirstLine.rtrim(
" {");
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;
64 class TargetDeclTest :
public ::testing::Test {
68 std::vector<const char *>
Flags;
73 std::vector<PrintedDecl> assertNodeAndPrintDecls(
const char *NodeType) {
74 llvm::Annotations A(Code);
77 auto AST = TU.build();
78 EXPECT_THAT(
AST.getDiagnostics(), ::testing::IsEmpty()) << Code;
80 SelectionTree Selection(
AST.getASTContext(),
AST.getTokens(), R.Begin,
82 const SelectionTree::Node *N = Selection.commonAncestor();
84 ADD_FAILURE() <<
"No node selected!\n" <<
Code;
87 EXPECT_EQ(N->kind(), NodeType) << Selection;
89 std::vector<PrintedDecl> ActualDecls;
91 ActualDecls.emplace_back(
Entry.first,
Entry.second);
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) {
113 struct S { S operator+(S) const; }; 114 auto X = S() [[+]] S(); 126 void operator()(int n); 133 EXPECT_DECLS("CXXOperatorCallExpr",
"void operator()(int n)");
136 TEST_F(TargetDeclTest, UsingDecl) {
168 int x = Y().[[foo]](); 174 TEST_F(TargetDeclTest, ConstructorInitList) {
192 TEST_F(TargetDeclTest, DesignatedInit) {
196 struct Y { int b; struct X c[2]; }; 197 struct Y y = { .c[0].[[a]] = 1 }; 202 TEST_F(TargetDeclTest, NestedNameSpecifier) {
204 namespace a { namespace b { int c; } } 210 namespace a { struct X { enum { y }; }; } 216 template <typename T> 223 namespace a { int x; } 231 TEST_F(TargetDeclTest, Types) {
248 Flags = {
"-fno-delayed-template-parsing"};
251 void foo() { [[T]] x; } 259 Flags = {
"-fno-delayed-template-parsing"};
261 template<template<typename> class T> 262 void foo() { [[T<int>]] x; } 264 EXPECT_DECLS("TemplateSpecializationTypeLoc",
"template <typename> class T");
282 template <typename... E> 284 static const int size = sizeof...([[E]]); 291 TEST_F(TargetDeclTest, ClassTemplate) {
293 // Implicit specialization. 294 template<int x> class Foo{}; 302 // Explicit specialization. 303 template<int x> class Foo{}; 304 template<> class Foo<42>{}; 307 EXPECT_DECLS("TemplateSpecializationTypeLoc",
"template<> class Foo<42>");
310 // Partial specialization. 311 template<typename T> class Foo{}; 312 template<typename T> class Foo<T*>{}; 320 // Class template argument deduction 321 template <typename T> 329 Flags.push_back("-std=c++17");
334 TEST_F(TargetDeclTest, FunctionTemplate) {
336 // Implicit specialization. 337 template<typename T> bool foo(T) { return false; }; 338 bool x = [[foo]](42); 345 // Explicit specialization. 346 template<typename T> bool foo(T) { return false; }; 347 template<> bool foo<int>(int) { return false; }; 348 bool x = [[foo]](42); 350 EXPECT_DECLS("DeclRefExpr",
"template<> bool foo<int>(int)");
353 TEST_F(TargetDeclTest, VariableTemplate) {
356 // Implicit specialization. 357 template<typename T> int foo; 358 int x = [[foo]]<char>; 364 // Explicit specialization. 365 template<typename T> int foo; 366 template <> bool foo<char>; 367 int x = [[foo]]<char>; 372 // Partial specialization. 373 template<typename T> int foo; 374 template<typename T> bool foo<T*>; 375 bool x = [[foo]]<char*>; 381 TEST_F(TargetDeclTest, TypeAliasTemplate) {
383 template<typename T, int X> class SmallVector {}; 384 template<typename U> using TinyVector = SmallVector<U, 1>; 385 [[TinyVector<int>]] X; 388 {
"template<> class SmallVector<int, 1>",
391 {
"using TinyVector = SmallVector<U, 1>",
395 TEST_F(TargetDeclTest, MemberOfTemplate) {
397 template <typename T> struct Foo { 400 int y = Foo<int>().[[x]](42); 406 template <typename T> struct Foo { 407 template <typename U> 410 int y = Foo<char>().[[x]]('c', 42); 417 TEST_F(TargetDeclTest, Lambda) {
419 void foo(int x = 42) { 420 auto l = [ [[x]] ]{ return x + 1; }; 428 void foo(int x = 42) { 429 auto l = [x]{ return [[x]] + 1; }; 436 auto l = [x = 1]{ return [[x]] + 1; }; 443 TEST_F(TargetDeclTest, OverloadExpr) {
446 Flags = {
"-fno-delayed-template-parsing"};
457 EXPECT_DECLS("UnresolvedLookupExpr",
"void func(int *)",
"void func(char *)");
470 EXPECT_DECLS("UnresolvedMemberExpr",
"void func(int *)",
"void func(char *)");
473 TEST_F(TargetDeclTest, ObjC) {
474 Flags = {
"-xobjective-c"};
486 @interface Foo { @public int bar; } 503 EXPECT_DECLS("ObjCPropertyRefExpr",
"- (void)setX:(int)x");
507 @property(retain) I* x; 508 @property(retain) I* y; 514 EXPECT_DECLS("OpaqueValueExpr",
"@property(atomic, retain, readwrite) I *x");
520 return [[@protocol(Foo)]]; 528 void test([[Foo]] *p); 535 void test([[id<Foo>]] p); 543 void test(C<[[Foo]]> *p); 549 class FindExplicitReferencesTest :
public ::testing::Test {
559 AllRefs annotateReferencesInFoo(llvm::StringRef
Code) {
565 TU.ExtraArgs.push_back(
"-fno-delayed-template-parsing");
566 TU.ExtraArgs.push_back(
"-std=c++17");
568 auto AST = TU.build();
569 for (
auto &D :
AST.getDiagnostics()) {
571 ADD_FAILURE() << D <<
Code;
575 if (
auto *T = llvm::dyn_cast<FunctionTemplateDecl>(TestDecl))
576 TestDecl = T->getTemplatedDecl();
577 auto &Func = llvm::cast<FunctionDecl>(*TestDecl);
579 std::vector<ReferenceLoc>
Refs;
581 Refs.push_back(std::move(R));
584 auto &SM =
AST.getSourceManager();
585 llvm::sort(Refs, [&](
const ReferenceLoc &L,
const ReferenceLoc &R) {
586 return SM.isBeforeInTranslationUnit(L.NameLoc, R.NameLoc);
590 unsigned NextCodeChar = 0;
591 for (
unsigned I = 0; I < Refs.size(); ++I) {
594 SourceLocation
Pos = R.NameLoc;
595 assert(Pos.isValid());
597 Pos = SM.getExpansionLoc(Pos);
598 assert(Pos.isFileID());
602 std::tie(File, Offset) = SM.getDecomposedLoc(Pos);
603 if (File == SM.getMainFileID()) {
605 assert(NextCodeChar <= Offset);
606 AnnotatedCode += Code.substr(NextCodeChar, Offset - NextCodeChar);
607 AnnotatedCode +=
"$" + std::to_string(I) +
"^";
612 AnnotatedCode += Code.substr(NextCodeChar);
615 for (
unsigned I = 0; I < Refs.size(); ++I)
616 DumpedReferences += llvm::formatv(
"{0}: {1}\n", I, Refs[I]);
618 return AllRefs{std::move(AnnotatedCode), std::move(DumpedReferences)};
622 TEST_F(FindExplicitReferencesTest,
All) {
623 std::pair< llvm::StringRef, llvm::StringRef> Cases[] =
628 void foo(int param) { 629 $0^global = $1^param + $2^func(); 632 "0: targets = {global}\n" 633 "1: targets = {param}\n" 634 "2: targets = {func}\n"},
642 "1: targets = {X::a}\n"},
646 namespace alias = ns; 648 using namespace $0^ns; 649 using namespace $1^alias; 652 "0: targets = {ns}\n" 653 "1: targets = {alias}\n"},
656 namespace ns { int global; } 658 using $0^ns::$1^global; 661 "0: targets = {ns}\n" 662 "1: targets = {ns::global}, qualifier = 'ns::'\n"},
665 struct Struct { int a; }; 670 static_cast<$4^Struct*>(0); 673 "0: targets = {Struct}\n" 674 "1: targets = {x}, decl\n" 675 "2: targets = {Typedef}\n" 676 "3: targets = {y}, decl\n" 677 "4: targets = {Struct}\n"},
680 namespace a { namespace b { struct S { typedef int type; }; } } 682 $0^a::$1^b::$2^S $3^x; 683 using namespace $4^a::$5^b; 688 "1: targets = {a::b}, qualifier = 'a::'\n" 689 "2: targets = {a::b::S}, qualifier = 'a::b::'\n" 690 "3: targets = {x}, decl\n" 692 "5: targets = {a::b}, qualifier = 'a::'\n" 693 "6: targets = {a::b::S}\n" 694 "7: targets = {a::b::S::type}, qualifier = 'struct S::'\n" 695 "8: targets = {y}, decl\n"},
698 template <class T> struct vector { using value_type = T; }; 699 template <> struct vector<bool> { using value_type = bool; }; 701 $0^vector<int> $1^vi; 702 $2^vector<bool> $3^vb; 705 "0: targets = {vector<int>}\n" 706 "1: targets = {vi}, decl\n" 707 "2: targets = {vector<bool>}\n" 708 "3: targets = {vb}, decl\n"},
711 template <class T> struct vector { using value_type = T; }; 712 template <> struct vector<bool> { using value_type = bool; }; 713 template <class T> using valias = vector<T>; 715 $0^valias<int> $1^vi; 716 $2^valias<bool> $3^vb; 719 "0: targets = {valias}\n" 720 "1: targets = {vi}, decl\n" 721 "2: targets = {valias}\n" 722 "3: targets = {vb}, decl\n"},
725 struct X { void func(int); }; 734 "1: targets = {Y::func}\n"},
737 namespace ns { void bar(int); } 744 "0: targets = {bar}\n"},
750 void foo(int a, int b) { 755 "1: targets = {b}\n"},
764 for (int $0^x : $1^vector()) { 769 "0: targets = {x}, decl\n" 770 "1: targets = {vector}\n" 771 "2: targets = {x}\n"},
774 namespace ns1 { void func(char*); } 775 namespace ns2 { void func(int*); } 784 "0: targets = {ns1::func, ns2::func}\n" 785 "1: targets = {t}\n"},
799 "1: targets = {X::func, X::func}\n" 800 "2: targets = {t}\n"},
805 static_cast<$0^T>(0); 813 "3: targets = {t}, decl\n"},
821 "0: targets = {x}, decl\n" 822 "1: targets = {I}\n"},
825 template <class T> struct vector {}; 827 template <template<class> class TT, template<class> class ...TP> 835 "0: targets = {TT}\n" 836 "1: targets = {x}, decl\n" 837 "2: targets = {foo}\n" 838 "3: targets = {TT}\n" 839 "4: targets = {foo}\n" 840 "5: targets = {vector}\n" 841 "6: targets = {foo}\n" 842 "7: targets = {TP}\n"},
846 template <int(*)()> struct wrapper {}; 848 template <int(*FuncParam)()> 850 $0^wrapper<$1^func> $2^w; 854 "0: targets = {wrapper<&func>}\n" 855 "1: targets = {func}\n" 856 "2: targets = {w}, decl\n" 857 "3: targets = {FuncParam}\n"},
863 class $0^Foo { $1^Foo(); ~$2^Foo(); int $3^field; }; 865 enum $5^E { $6^ABC }; 868 namespace $9^NS = $10^ns; 871 "0: targets = {Foo}, decl\n" 872 "1: targets = {foo()::Foo::Foo}, decl\n" 873 "2: targets = {Foo}\n" 874 "3: targets = {foo()::Foo::field}, decl\n" 875 "4: targets = {Var}, decl\n" 876 "5: targets = {E}, decl\n" 877 "6: targets = {foo()::ABC}, decl\n" 878 "7: targets = {INT}, decl\n" 879 "8: targets = {INT2}, decl\n" 880 "9: targets = {NS}, decl\n" 881 "10: targets = {ns}\n"},
886 // member initializer 892 class $4^Derived : public $5^Base { 894 $8^Derived() : $9^Base() {} 896 // delegating initializer 899 $12^Foo(): $13^Foo(111) {} 903 "0: targets = {X}, decl\n" 904 "1: targets = {foo()::X::abc}, decl\n" 905 "2: targets = {foo()::X::X}, decl\n" 906 "3: targets = {foo()::X::abc}\n" 907 "4: targets = {Derived}, decl\n" 908 "5: targets = {Base}\n" 909 "6: targets = {Base}\n" 910 "7: targets = {foo()::Derived::B}, decl\n" 911 "8: targets = {foo()::Derived::Derived}, decl\n" 912 "9: targets = {Base}\n" 913 "10: targets = {Foo}, decl\n" 914 "11: targets = {foo()::Foo::Foo}, decl\n" 915 "12: targets = {foo()::Foo::Foo}, decl\n" 916 "13: targets = {Foo}\n"},
922 int (*$1^fptr)(int $2^a, int) = nullptr; 925 "0: targets = {x}, decl\n" 926 "1: targets = {fptr}, decl\n" 927 "2: targets = {a}, decl\n"},
931 namespace ns { struct Type {}; } 932 namespace alias = ns; 933 namespace rec_alias = alias; 937 $3^alias::$4^Type $5^b; 938 $6^rec_alias::$7^Type $8^c; 941 "0: targets = {ns}\n" 942 "1: targets = {ns::Type}, qualifier = 'ns::'\n" 943 "2: targets = {a}, decl\n" 944 "3: targets = {alias}\n" 945 "4: targets = {ns::Type}, qualifier = 'alias::'\n" 946 "5: targets = {b}, decl\n" 947 "6: targets = {rec_alias}\n" 948 "7: targets = {ns::Type}, qualifier = 'rec_alias::'\n" 949 "8: targets = {c}, decl\n"},
953 template <typename... E> 955 constexpr int $0^size = sizeof...($1^E); 958 "0: targets = {size}, decl\n" 959 "1: targets = {E}\n"},
963 template <typename T> 971 "0: targets = {Test}\n" 972 "1: targets = {a}, decl\n"}};
974 for (
const auto &C : Cases) {
975 llvm::StringRef ExpectedCode = C.first;
976 llvm::StringRef ExpectedRefs = C.second;
979 annotateReferencesInFoo(llvm::Annotations(ExpectedCode).code());
980 EXPECT_EQ(ExpectedCode, Actual.AnnotatedCode);
981 EXPECT_EQ(ExpectedRefs, Actual.DumpedReferences) << ExpectedCode;
bool operator==(const HoverInfo::Param &LHS, const HoverInfo::Param &RHS)
llvm::SmallVector< std::pair< const NamedDecl *, DeclRelationSet >, 1 > allTargetDecls(const ast_type_traits::DynTypedNode &N)
Similar to targetDecl(), however instead of applying a filter, all possible decls are returned along ...
std::string DumpedReferences
This is the pattern the template specialization was instantiated from.
std::vector< const char * > Flags
#define EXPECT_DECLS(NodeType,...)
This declaration is an alias that was referred to.
std::vector< const char * > ExtraArgs
TEST_F(BackgroundIndexTest, NoCrashOnErrorFile)
This is the template instantiation that was referred to.
static TestTU withCode(llvm::StringRef Code)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
void findExplicitReferences(const Stmt *S, llvm::function_ref< void(ReferenceLoc)> Out)
Recursively traverse S and report all references explicitly written in the code.
This is the underlying declaration for an alias, decltype etc.
DeclRelationSet Relations
CharSourceRange Range
SourceRange for the file name.
llvm::raw_ostream & operator<<(llvm::raw_ostream &OS, const CodeCompletion &C)
std::string AnnotatedCode
const NamedDecl & findDecl(ParsedAST &AST, llvm::StringRef QName)