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 Decl *
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(); 119 TEST_F(TargetDeclTest, UsingDecl) {
151 int x = Y().[[foo]](); 157 TEST_F(TargetDeclTest, ConstructorInitList) {
175 TEST_F(TargetDeclTest, DesignatedInit) {
179 struct Y { int b; struct X c[2]; }; 180 struct Y y = { .c[0].[[a]] = 1 }; 185 TEST_F(TargetDeclTest, NestedNameSpecifier) {
187 namespace a { namespace b { int c; } } 193 namespace a { struct X { enum { y }; }; } 199 template <typename T> 206 namespace a { int x; } 214 TEST_F(TargetDeclTest, Types) {
231 Flags = {
"-fno-delayed-template-parsing"};
234 void foo() { [[T]] x; } 242 Flags = {
"-fno-delayed-template-parsing"};
244 template<template<typename> class T> 245 void foo() { [[T<int>]] x; } 247 EXPECT_DECLS("TemplateSpecializationTypeLoc",
"template <typename> class T");
265 TEST_F(TargetDeclTest, ClassTemplate) {
267 // Implicit specialization. 268 template<int x> class Foo{}; 276 // Explicit specialization. 277 template<int x> class Foo{}; 278 template<> class Foo<42>{}; 281 EXPECT_DECLS("TemplateSpecializationTypeLoc",
"template<> class Foo<42>");
284 // Partial specialization. 285 template<typename T> class Foo{}; 286 template<typename T> class Foo<T*>{}; 291 {
"template <typename T> class Foo<type-parameter-0-0 *>",
295 TEST_F(TargetDeclTest, FunctionTemplate) {
297 // Implicit specialization. 298 template<typename T> bool foo(T) { return false; }; 299 bool x = [[foo]](42); 306 // Explicit specialization. 307 template<typename T> bool foo(T) { return false; }; 308 template<> bool foo<int>(int) { return false; }; 309 bool x = [[foo]](42); 311 EXPECT_DECLS("DeclRefExpr",
"template<> bool foo<int>(int)");
314 TEST_F(TargetDeclTest, VariableTemplate) {
317 // Implicit specialization. 318 template<typename T> int foo; 319 int x = [[foo]]<char>; 325 // Explicit specialization. 326 template<typename T> int foo; 327 template <> bool foo<char>; 328 int x = [[foo]]<char>; 333 // Partial specialization. 334 template<typename T> int foo; 335 template<typename T> bool foo<T*>; 336 bool x = [[foo]]<char*>; 342 TEST_F(TargetDeclTest, TypeAliasTemplate) {
344 template<typename T, int X> class SmallVector {}; 345 template<typename U> using TinyVector = SmallVector<U, 1>; 346 [[TinyVector<int>]] X; 349 {
"template<> class SmallVector<int, 1>",
352 {
"using TinyVector = SmallVector<U, 1>",
356 TEST_F(TargetDeclTest, MemberOfTemplate) {
358 template <typename T> struct Foo { 361 int y = Foo<int>().[[x]](42); 367 template <typename T> struct Foo { 368 template <typename U> 371 int y = Foo<char>().[[x]]('c', 42); 378 TEST_F(TargetDeclTest, Lambda) {
380 void foo(int x = 42) { 381 auto l = [ [[x]] ]{ return x + 1; }; 389 void foo(int x = 42) { 390 auto l = [x]{ return [[x]] + 1; }; 397 auto l = [x = 1]{ return [[x]] + 1; }; 404 TEST_F(TargetDeclTest, OverloadExpr) {
407 Flags = {
"-fno-delayed-template-parsing"};
418 EXPECT_DECLS("UnresolvedLookupExpr",
"void func(int *)",
"void func(char *)");
431 EXPECT_DECLS("UnresolvedMemberExpr",
"void func(int *)",
"void func(char *)");
434 TEST_F(TargetDeclTest, ObjC) {
435 Flags = {
"-xobjective-c"};
447 @interface Foo { @public int bar; } 464 EXPECT_DECLS("ObjCPropertyRefExpr",
"- (void)setX:(int)x");
475 "@property(atomic, assign, unsafe_unretained, readwrite) int x");
481 return [[@protocol(Foo)]]; 489 void test([[Foo]] *p); 496 void test([[id<Foo>]] p); 504 void test(C<[[Foo]]> *p); 510 class FindExplicitReferencesTest :
public ::testing::Test {
520 AllRefs annotateReferencesInFoo(llvm::StringRef
Code) {
526 TU.ExtraArgs.push_back(
"-fno-delayed-template-parsing");
528 auto AST = TU.build();
531 if (
auto *T = llvm::dyn_cast<FunctionTemplateDecl>(TestDecl))
532 TestDecl = T->getTemplatedDecl();
533 auto &Func = llvm::cast<FunctionDecl>(*TestDecl);
535 std::vector<ReferenceLoc>
Refs;
537 Refs.push_back(std::move(R));
540 auto &SM =
AST.getSourceManager();
541 llvm::sort(Refs, [&](
const ReferenceLoc &L,
const ReferenceLoc &R) {
542 return SM.isBeforeInTranslationUnit(L.NameLoc, R.NameLoc);
546 unsigned NextCodeChar = 0;
547 for (
unsigned I = 0; I < Refs.size(); ++I) {
550 SourceLocation Pos = R.NameLoc;
551 assert(Pos.isValid());
553 Pos = SM.getExpansionLoc(Pos);
554 assert(Pos.isFileID());
558 std::tie(File, Offset) = SM.getDecomposedLoc(Pos);
559 if (File == SM.getMainFileID()) {
561 assert(NextCodeChar <= Offset);
562 AnnotatedCode += Code.substr(NextCodeChar, Offset - NextCodeChar);
563 AnnotatedCode +=
"$" + std::to_string(I) +
"^";
568 AnnotatedCode += Code.substr(NextCodeChar);
571 for (
unsigned I = 0; I < Refs.size(); ++I)
572 DumpedReferences += llvm::formatv(
"{0}: {1}\n", I, Refs[I]);
574 return AllRefs{std::move(AnnotatedCode), std::move(DumpedReferences)};
578 TEST_F(FindExplicitReferencesTest,
All) {
579 std::pair< llvm::StringRef, llvm::StringRef> Cases[] =
585 void foo(int param) { 586 $0^global = $1^param + $2^func(); 589 "0: targets = {global}\n" 590 "1: targets = {param}\n" 591 "2: targets = {func}\n"},
599 "1: targets = {X::a}\n"},
603 namespace alias = ns; 605 using namespace $0^ns; 606 using namespace $1^alias; 609 "0: targets = {ns}\n" 610 "1: targets = {alias}\n"},
613 namespace ns { int global; } 615 using $0^ns::$1^global; 618 "0: targets = {ns}\n" 619 "1: targets = {ns::global}, qualifier = 'ns::'\n"},
622 struct Struct { int a; }; 627 static_cast<$4^Struct*>(0); 630 "0: targets = {Struct}\n" 631 "1: targets = {x}, decl\n" 632 "2: targets = {Typedef}\n" 633 "3: targets = {y}, decl\n" 634 "4: targets = {Struct}\n"},
637 namespace a { namespace b { struct S { typedef int type; }; } } 639 $0^a::$1^b::$2^S $3^x; 640 using namespace $4^a::$5^b; 645 "1: targets = {a::b}, qualifier = 'a::'\n" 646 "2: targets = {a::b::S}, qualifier = 'a::b::'\n" 647 "3: targets = {x}, decl\n" 649 "5: targets = {a::b}, qualifier = 'a::'\n" 650 "6: targets = {a::b::S}\n" 651 "7: targets = {a::b::S::type}, qualifier = 'struct S::'\n" 652 "8: targets = {y}, decl\n"},
655 template <class T> struct vector { using value_type = T; }; 656 template <> struct vector<bool> { using value_type = bool; }; 658 $0^vector<int> $1^vi; 659 $2^vector<bool> $3^vb; 662 "0: targets = {vector<int>}\n" 663 "1: targets = {vi}, decl\n" 664 "2: targets = {vector<bool>}\n" 665 "3: targets = {vb}, decl\n"},
668 template <class T> struct vector { using value_type = T; }; 669 template <> struct vector<bool> { using value_type = bool; }; 670 template <class T> using valias = vector<T>; 672 $0^valias<int> $1^vi; 673 $2^valias<bool> $3^vb; 676 "0: targets = {valias}\n" 677 "1: targets = {vi}, decl\n" 678 "2: targets = {valias}\n" 679 "3: targets = {vb}, decl\n"},
682 struct X { void func(int); } 691 "1: targets = {Y::func}\n"},
694 namespace ns { void bar(int); } 701 "0: targets = {bar}\n"},
707 void foo(int a, int b) { 712 "1: targets = {b}\n"},
721 for (int $0^x : $1^vector()) { 726 "0: targets = {x}, decl\n" 727 "1: targets = {vector}\n" 728 "2: targets = {x}\n"},
731 namespace ns1 { void func(char*); } 732 namespace ns2 { void func(int*); } 741 "0: targets = {ns1::func, ns2::func}\n" 742 "1: targets = {t}\n"},
756 "1: targets = {X::func, X::func}\n" 757 "2: targets = {t}\n"},
762 static_cast<$0^T>(0); 770 "3: targets = {t}, decl\n"},
778 "0: targets = {x}, decl\n" 779 "1: targets = {I}\n"},
782 template <class T> struct vector {}; 784 template <template<class> class TT, template<class> class ...TP> 792 "0: targets = {TT}\n" 793 "1: targets = {x}, decl\n" 794 "2: targets = {foo}\n" 795 "3: targets = {TT}\n" 796 "4: targets = {foo}\n" 797 "5: targets = {vector}\n" 798 "6: targets = {foo}\n" 799 "7: targets = {TP}\n"},
803 template <int(*)()> struct wrapper {}; 805 template <int(*FuncParam)()> 807 $0^wrapper<$1^func> $2^w; 811 "0: targets = {wrapper<&func>}\n" 812 "1: targets = {func}\n" 813 "2: targets = {w}, decl\n" 814 "3: targets = {FuncParam}\n"},
819 class $0^Foo { $1^Foo(); ~$2^Foo(); int $3^field; }; 821 enum $5^E { $6^ABC }; 824 namespace $9^NS = $10^ns; 827 "0: targets = {Foo}, decl\n" 828 "1: targets = {foo()::Foo::Foo}, decl\n" 829 "2: targets = {Foo}\n" 830 "3: targets = {foo()::Foo::field}, decl\n" 831 "4: targets = {Var}, decl\n" 832 "5: targets = {E}, decl\n" 833 "6: targets = {foo()::ABC}, decl\n" 834 "7: targets = {INT}, decl\n" 835 "8: targets = {INT2}, decl\n" 836 "9: targets = {NS}, decl\n" 837 "10: targets = {ns}\n"},
840 for (
const auto &C : Cases) {
841 llvm::StringRef ExpectedCode = C.first;
842 llvm::StringRef ExpectedRefs = C.second;
845 annotateReferencesInFoo(llvm::Annotations(ExpectedCode).code());
846 EXPECT_EQ(ExpectedCode, Actual.AnnotatedCode);
847 EXPECT_EQ(ExpectedRefs, Actual.DumpedReferences) << ExpectedCode;
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)
bool operator==(const Ref &L, const Ref &R)
This is the template instantiation that was referred to.
static TestTU withCode(llvm::StringRef Code)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
llvm::SmallVector< std::pair< const Decl *, DeclRelationSet >, 1 > allTargetDecls(const ast_type_traits::DynTypedNode &N)
Similar to targetDecl(), however instead of applying a filter, all possible decls are returned along ...
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)