diff --git a/clang-tools-extra/clangd/FindTarget.cpp b/clang-tools-extra/clangd/FindTarget.cpp --- a/clang-tools-extra/clangd/FindTarget.cpp +++ b/clang-tools-extra/clangd/FindTarget.cpp @@ -432,10 +432,13 @@ Outer.add(OIT->getDecl(), Flags); } void VisitObjCObjectType(const ObjCObjectType *OOT) { - // FIXME: ObjCObjectTypeLoc has no children for the protocol list, so - // there is no node in id that refers to ObjCProtocolDecl Foo. - if (OOT->isObjCQualifiedId() && OOT->getNumProtocols() == 1) - Outer.add(OOT->getProtocol(0), Flags); + // Make all of the protocols targets since there's no child nodes for + // protocols. This isn't needed for the base type, which *does* have a + // child `ObjCInterfaceTypeLoc`. This structure is a hack, but it works + // well for go-to-definition. + unsigned NumProtocols = OOT->getNumProtocols(); + for (unsigned I = 0; I < NumProtocols; I++) + Outer.add(OOT->getProtocol(I), Flags); } }; Visitor(*this, Flags).Visit(T.getTypePtr()); @@ -813,30 +816,34 @@ Visitor(const HeuristicResolver *Resolver) : Resolver(Resolver) {} const HeuristicResolver *Resolver; - llvm::Optional Ref; + llvm::SmallVector Refs; void VisitElaboratedTypeLoc(ElaboratedTypeLoc L) { // We only know about qualifier, rest if filled by inner locations. + size_t InitialSize = Refs.size(); Visit(L.getNamedTypeLoc().getUnqualifiedLoc()); - // Fill in the qualifier. - if (!Ref) - return; - assert(!Ref->Qualifier.hasQualifier() && "qualifier already set"); - Ref->Qualifier = L.getQualifierLoc(); + size_t NewSize = Refs.size(); + // Add qualifier for the newly-added refs. + for (unsigned I = InitialSize; I < NewSize; ++I) { + ReferenceLoc *Ref = &Refs[I]; + // Fill in the qualifier. + assert(!Ref->Qualifier.hasQualifier() && "qualifier already set"); + Ref->Qualifier = L.getQualifierLoc(); + } } void VisitTagTypeLoc(TagTypeLoc L) { - Ref = ReferenceLoc{NestedNameSpecifierLoc(), - L.getNameLoc(), - /*IsDecl=*/false, - {L.getDecl()}}; + Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(), + L.getNameLoc(), + /*IsDecl=*/false, + {L.getDecl()}}); } void VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc L) { - Ref = ReferenceLoc{NestedNameSpecifierLoc(), - L.getNameLoc(), - /*IsDecl=*/false, - {L.getDecl()}}; + Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(), + L.getNameLoc(), + /*IsDecl=*/false, + {L.getDecl()}}); } void VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc L) { @@ -848,63 +855,71 @@ // 1. valias with mask 'Alias'. // 2. 'vector' with mask 'Underlying'. // we want to return only #1 in this case. - Ref = ReferenceLoc{ + Refs.push_back(ReferenceLoc{ NestedNameSpecifierLoc(), L.getTemplateNameLoc(), /*IsDecl=*/false, explicitReferenceTargets(DynTypedNode::create(L.getType()), - DeclRelation::Alias, Resolver)}; + DeclRelation::Alias, Resolver)}); } void VisitDeducedTemplateSpecializationTypeLoc( DeducedTemplateSpecializationTypeLoc L) { - Ref = ReferenceLoc{ + Refs.push_back(ReferenceLoc{ NestedNameSpecifierLoc(), L.getNameLoc(), /*IsDecl=*/false, explicitReferenceTargets(DynTypedNode::create(L.getType()), - DeclRelation::Alias, Resolver)}; + DeclRelation::Alias, Resolver)}); } void VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) { - Ref = ReferenceLoc{NestedNameSpecifierLoc(), - TL.getNameLoc(), - /*IsDecl=*/false, - {TL.getDecl()}}; + Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(), + TL.getNameLoc(), + /*IsDecl=*/false, + {TL.getDecl()}}); } void VisitDependentTemplateSpecializationTypeLoc( DependentTemplateSpecializationTypeLoc L) { - Ref = ReferenceLoc{L.getQualifierLoc(), L.getTemplateNameLoc(), - /*IsDecl=*/false, - explicitReferenceTargets( - DynTypedNode::create(L.getType()), {}, Resolver)}; + Refs.push_back( + ReferenceLoc{L.getQualifierLoc(), L.getTemplateNameLoc(), + /*IsDecl=*/false, + explicitReferenceTargets( + DynTypedNode::create(L.getType()), {}, Resolver)}); } void VisitDependentNameTypeLoc(DependentNameTypeLoc L) { - Ref = ReferenceLoc{L.getQualifierLoc(), L.getNameLoc(), /*IsDecl=*/false, - explicitReferenceTargets( - DynTypedNode::create(L.getType()), {}, Resolver)}; + Refs.push_back( + ReferenceLoc{L.getQualifierLoc(), L.getNameLoc(), + /*IsDecl=*/false, + explicitReferenceTargets( + DynTypedNode::create(L.getType()), {}, Resolver)}); } void VisitTypedefTypeLoc(TypedefTypeLoc L) { - Ref = ReferenceLoc{NestedNameSpecifierLoc(), - L.getNameLoc(), - /*IsDecl=*/false, - {L.getTypedefNameDecl()}}; + Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(), + L.getNameLoc(), + /*IsDecl=*/false, + {L.getTypedefNameDecl()}}); } void VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc L) { - Ref = ReferenceLoc{NestedNameSpecifierLoc(), - L.getNameLoc(), - /*IsDecl=*/false, - {L.getIFaceDecl()}}; + Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(), + L.getNameLoc(), + /*IsDecl=*/false, + {L.getIFaceDecl()}}); } - // FIXME: add references to protocols in ObjCObjectTypeLoc and maybe - // ObjCObjectPointerTypeLoc. + void VisitObjCObjectTypeLoc(ObjCObjectTypeLoc L) { + unsigned NumProtocols = L.getNumProtocols(); + for (unsigned I = 0; I < NumProtocols; I++) { + Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(), + L.getProtocolLoc(I), + /*IsDecl=*/false, + {L.getProtocol(I)}}); + } + } }; Visitor V{Resolver}; V.Visit(L.getUnqualifiedLoc()); - if (!V.Ref) - return {}; - return {*V.Ref}; + return V.Refs; } class ExplicitReferenceCollector diff --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp --- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp +++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp @@ -943,14 +943,32 @@ )cpp"; EXPECT_DECLS("ObjCObjectTypeLoc", "@protocol Foo"); + Code = R"cpp( + @class C; + @protocol Foo + @end + void test([[C]] *p); + )cpp"; + EXPECT_DECLS("ObjCInterfaceTypeLoc", "@class C;"); + Code = R"cpp( @class C; @protocol Foo @end void test(C<[[Foo]]> *p); )cpp"; - // FIXME: there's no AST node corresponding to 'Foo', so we're stuck. - EXPECT_DECLS("ObjCObjectTypeLoc"); + EXPECT_DECLS("ObjCObjectTypeLoc", "@protocol Foo"); + + Code = R"cpp( + @class C; + @protocol Foo + @end + @protocol Bar + @end + void test(C<[[Foo]], Bar> *p); + )cpp"; + // FIXME: We currently can't disambiguate between multiple protocols. + EXPECT_DECLS("ObjCObjectTypeLoc", "@protocol Foo", "@protocol Bar"); } class FindExplicitReferencesTest : public ::testing::Test { @@ -1036,37 +1054,36 @@ TEST_F(FindExplicitReferencesTest, All) { std::pair Cases[] = - { - // Simple expressions. - {R"cpp( + {// Simple expressions. + {R"cpp( int global; int func(); void foo(int param) { $0^global = $1^param + $2^func(); } )cpp", - "0: targets = {global}\n" - "1: targets = {param}\n" - "2: targets = {func}\n"}, - {R"cpp( + "0: targets = {global}\n" + "1: targets = {param}\n" + "2: targets = {func}\n"}, + {R"cpp( struct X { int a; }; void foo(X x) { $0^x.$1^a = 10; } )cpp", - "0: targets = {x}\n" - "1: targets = {X::a}\n"}, - {R"cpp( + "0: targets = {x}\n" + "1: targets = {X::a}\n"}, + {R"cpp( // error-ok: testing with broken code int bar(); int foo() { return $0^bar() + $1^bar(42); } )cpp", - "0: targets = {bar}\n" - "1: targets = {bar}\n"}, - // Namespaces and aliases. - {R"cpp( + "0: targets = {bar}\n" + "1: targets = {bar}\n"}, + // Namespaces and aliases. + {R"cpp( namespace ns {} namespace alias = ns; void foo() { @@ -1074,19 +1091,19 @@ using namespace $1^alias; } )cpp", - "0: targets = {ns}\n" - "1: targets = {alias}\n"}, - // Using declarations. - {R"cpp( + "0: targets = {ns}\n" + "1: targets = {alias}\n"}, + // Using declarations. + {R"cpp( namespace ns { int global; } void foo() { using $0^ns::$1^global; } )cpp", - "0: targets = {ns}\n" - "1: targets = {ns::global}, qualifier = 'ns::'\n"}, - // Simple types. - {R"cpp( + "0: targets = {ns}\n" + "1: targets = {ns::global}, qualifier = 'ns::'\n"}, + // Simple types. + {R"cpp( struct Struct { int a; }; using Typedef = int; void foo() { @@ -1095,13 +1112,13 @@ static_cast<$4^Struct*>(0); } )cpp", - "0: targets = {Struct}\n" - "1: targets = {x}, decl\n" - "2: targets = {Typedef}\n" - "3: targets = {y}, decl\n" - "4: targets = {Struct}\n"}, - // Name qualifiers. - {R"cpp( + "0: targets = {Struct}\n" + "1: targets = {x}, decl\n" + "2: targets = {Typedef}\n" + "3: targets = {y}, decl\n" + "4: targets = {Struct}\n"}, + // Name qualifiers. + {R"cpp( namespace a { namespace b { struct S { typedef int type; }; } } void foo() { $0^a::$1^b::$2^S $3^x; @@ -1109,16 +1126,16 @@ $6^S::$7^type $8^y; } )cpp", - "0: targets = {a}\n" - "1: targets = {a::b}, qualifier = 'a::'\n" - "2: targets = {a::b::S}, qualifier = 'a::b::'\n" - "3: targets = {x}, decl\n" - "4: targets = {a}\n" - "5: targets = {a::b}, qualifier = 'a::'\n" - "6: targets = {a::b::S}\n" - "7: targets = {a::b::S::type}, qualifier = 'struct S::'\n" - "8: targets = {y}, decl\n"}, - {R"cpp( + "0: targets = {a}\n" + "1: targets = {a::b}, qualifier = 'a::'\n" + "2: targets = {a::b::S}, qualifier = 'a::b::'\n" + "3: targets = {x}, decl\n" + "4: targets = {a}\n" + "5: targets = {a::b}, qualifier = 'a::'\n" + "6: targets = {a::b::S}\n" + "7: targets = {a::b::S::type}, qualifier = 'struct S::'\n" + "8: targets = {y}, decl\n"}, + {R"cpp( void foo() { $0^ten: // PRINT "HELLO WORLD!" goto $1^ten; @@ -1135,12 +1152,12 @@ $2^vector $3^vb; } )cpp", - "0: targets = {vector}\n" - "1: targets = {vi}, decl\n" - "2: targets = {vector}\n" - "3: targets = {vb}, decl\n"}, - // Template type aliases. - {R"cpp( + "0: targets = {vector}\n" + "1: targets = {vi}, decl\n" + "2: targets = {vector}\n" + "3: targets = {vb}, decl\n"}, + // Template type aliases. + {R"cpp( template struct vector { using value_type = T; }; template <> struct vector { using value_type = bool; }; template using valias = vector; @@ -1149,12 +1166,12 @@ $2^valias $3^vb; } )cpp", - "0: targets = {valias}\n" - "1: targets = {vi}, decl\n" - "2: targets = {valias}\n" - "3: targets = {vb}, decl\n"}, - // Injected class name. - {R"cpp( + "0: targets = {valias}\n" + "1: targets = {vi}, decl\n" + "2: targets = {valias}\n" + "3: targets = {vb}, decl\n"}, + // Injected class name. + {R"cpp( namespace foo { template class $1^Bar { @@ -1163,13 +1180,13 @@ }; } )cpp", - "0: targets = {foo::Bar::T}, decl\n" - "1: targets = {foo::Bar}, decl\n" - "2: targets = {foo::Bar}\n" - "3: targets = {foo::Bar::f}, decl\n" - "4: targets = {foo::Bar}\n"}, - // MemberExpr should know their using declaration. - {R"cpp( + "0: targets = {foo::Bar::T}, decl\n" + "1: targets = {foo::Bar}, decl\n" + "2: targets = {foo::Bar}\n" + "3: targets = {foo::Bar::f}, decl\n" + "4: targets = {foo::Bar}\n"}, + // MemberExpr should know their using declaration. + {R"cpp( struct X { void func(int); }; struct Y : X { using X::func; @@ -1178,10 +1195,10 @@ $0^y.$1^func(1); } )cpp", - "0: targets = {y}\n" - "1: targets = {Y::func}\n"}, - // DeclRefExpr should know their using declaration. - {R"cpp( + "0: targets = {y}\n" + "1: targets = {Y::func}\n"}, + // DeclRefExpr should know their using declaration. + {R"cpp( namespace ns { void bar(int); } using ns::bar; @@ -1189,9 +1206,9 @@ $0^bar(10); } )cpp", - "0: targets = {bar}\n"}, - // References from a macro. - {R"cpp( + "0: targets = {bar}\n"}, + // References from a macro. + {R"cpp( #define FOO a #define BAR b @@ -1199,10 +1216,10 @@ $0^FOO+$1^BAR; } )cpp", - "0: targets = {a}\n" - "1: targets = {b}\n"}, - // No references from implicit nodes. - {R"cpp( + "0: targets = {a}\n" + "1: targets = {b}\n"}, + // No references from implicit nodes. + {R"cpp( struct vector { int *begin(); int *end(); @@ -1214,15 +1231,15 @@ } } )cpp", - "0: targets = {x}, decl\n" - "1: targets = {vector}\n" - "2: targets = {x}\n"}, + "0: targets = {x}, decl\n" + "1: targets = {vector}\n" + "2: targets = {x}\n"}, // Handle UnresolvedLookupExpr. // FIXME // This case fails when expensive checks are enabled. // Seems like the order of ns1::func and ns2::func isn't defined. #ifndef EXPENSIVE_CHECKS - {R"cpp( + {R"cpp( namespace ns1 { void func(char*); } namespace ns2 { void func(int*); } using namespace ns1; @@ -1233,11 +1250,11 @@ $0^func($1^t); } )cpp", - "0: targets = {ns1::func, ns2::func}\n" - "1: targets = {t}\n"}, + "0: targets = {ns1::func, ns2::func}\n" + "1: targets = {t}\n"}, #endif - // Handle UnresolvedMemberExpr. - {R"cpp( + // Handle UnresolvedMemberExpr. + {R"cpp( struct X { void func(char*); void func(int*); @@ -1248,11 +1265,11 @@ $0^x.$1^func($2^t); } )cpp", - "0: targets = {x}\n" - "1: targets = {X::func, X::func}\n" - "2: targets = {t}\n"}, - // Handle DependentScopeDeclRefExpr. - {R"cpp( + "0: targets = {x}\n" + "1: targets = {X::func, X::func}\n" + "2: targets = {t}\n"}, + // Handle DependentScopeDeclRefExpr. + {R"cpp( template struct S { static int value; @@ -1263,11 +1280,11 @@ $0^S<$1^T>::$2^value; } )cpp", - "0: targets = {S}\n" - "1: targets = {T}\n" - "2: targets = {S::value}, qualifier = 'S::'\n"}, - // Handle CXXDependentScopeMemberExpr. - {R"cpp( + "0: targets = {S}\n" + "1: targets = {T}\n" + "2: targets = {S::value}, qualifier = 'S::'\n"}, + // Handle CXXDependentScopeMemberExpr. + {R"cpp( template struct S { int value; @@ -1278,10 +1295,10 @@ $0^t.$1^value; } )cpp", - "0: targets = {t}\n" - "1: targets = {S::value}\n"}, - // Type template parameters. - {R"cpp( + "0: targets = {t}\n" + "1: targets = {S::value}\n"}, + // Type template parameters. + {R"cpp( template void foo() { static_cast<$0^T>(0); @@ -1289,21 +1306,21 @@ $2^T $3^t; } )cpp", - "0: targets = {T}\n" - "1: targets = {T}\n" - "2: targets = {T}\n" - "3: targets = {t}, decl\n"}, - // Non-type template parameters. - {R"cpp( + "0: targets = {T}\n" + "1: targets = {T}\n" + "2: targets = {T}\n" + "3: targets = {t}, decl\n"}, + // Non-type template parameters. + {R"cpp( template void foo() { int $0^x = $1^I; } )cpp", - "0: targets = {x}, decl\n" - "1: targets = {I}\n"}, - // Template template parameters. - {R"cpp( + "0: targets = {x}, decl\n" + "1: targets = {I}\n"}, + // Template template parameters. + {R"cpp( template struct vector {}; template class TT, template class ...TP> @@ -1314,16 +1331,16 @@ $6^foo<$7^TP...>(); } )cpp", - "0: targets = {TT}\n" - "1: targets = {x}, decl\n" - "2: targets = {foo}\n" - "3: targets = {TT}\n" - "4: targets = {foo}\n" - "5: targets = {vector}\n" - "6: targets = {foo}\n" - "7: targets = {TP}\n"}, - // Non-type template parameters with declarations. - {R"cpp( + "0: targets = {TT}\n" + "1: targets = {x}, decl\n" + "2: targets = {foo}\n" + "3: targets = {TT}\n" + "4: targets = {foo}\n" + "5: targets = {vector}\n" + "6: targets = {foo}\n" + "7: targets = {TP}\n"}, + // Non-type template parameters with declarations. + {R"cpp( int func(); template struct wrapper {}; @@ -1333,12 +1350,12 @@ $3^FuncParam(); } )cpp", - "0: targets = {wrapper<&func>}\n" - "1: targets = {func}\n" - "2: targets = {w}, decl\n" - "3: targets = {FuncParam}\n"}, - // declaration references. - {R"cpp( + "0: targets = {wrapper<&func>}\n" + "1: targets = {func}\n" + "2: targets = {w}, decl\n" + "3: targets = {FuncParam}\n"}, + // declaration references. + {R"cpp( namespace ns {} class S {}; void foo() { @@ -1350,19 +1367,19 @@ namespace $9^NS = $10^ns; } )cpp", - "0: targets = {Foo}, decl\n" - "1: targets = {foo()::Foo::Foo}, decl\n" - "2: targets = {Foo}\n" - "3: targets = {foo()::Foo::field}, decl\n" - "4: targets = {Var}, decl\n" - "5: targets = {E}, decl\n" - "6: targets = {foo()::ABC}, decl\n" - "7: targets = {INT}, decl\n" - "8: targets = {INT2}, decl\n" - "9: targets = {NS}, decl\n" - "10: targets = {ns}\n"}, - // User-defined conversion operator. - {R"cpp( + "0: targets = {Foo}, decl\n" + "1: targets = {foo()::Foo::Foo}, decl\n" + "2: targets = {Foo}\n" + "3: targets = {foo()::Foo::field}, decl\n" + "4: targets = {Var}, decl\n" + "5: targets = {E}, decl\n" + "6: targets = {foo()::ABC}, decl\n" + "7: targets = {INT}, decl\n" + "8: targets = {INT2}, decl\n" + "9: targets = {NS}, decl\n" + "10: targets = {ns}\n"}, + // User-defined conversion operator. + {R"cpp( void foo() { class $0^Bar {}; class $1^Foo { @@ -1375,18 +1392,18 @@ $7^f.$8^operator $9^Bar(); } )cpp", - "0: targets = {Bar}, decl\n" - "1: targets = {Foo}, decl\n" - "2: targets = {foo()::Foo::operator Bar}, decl\n" - "3: targets = {Bar}\n" - "4: targets = {Bar}\n" - "5: targets = {Foo}\n" - "6: targets = {f}, decl\n" - "7: targets = {f}\n" - "8: targets = {foo()::Foo::operator Bar}\n" - "9: targets = {Bar}\n"}, - // Destructor. - {R"cpp( + "0: targets = {Bar}, decl\n" + "1: targets = {Foo}, decl\n" + "2: targets = {foo()::Foo::operator Bar}, decl\n" + "3: targets = {Bar}\n" + "4: targets = {Bar}\n" + "5: targets = {Foo}\n" + "6: targets = {f}, decl\n" + "7: targets = {f}\n" + "8: targets = {foo()::Foo::operator Bar}\n" + "9: targets = {Bar}\n"}, + // Destructor. + {R"cpp( void foo() { class $0^Foo { public: @@ -1401,18 +1418,18 @@ $6^f.~ /*...*/ $7^Foo(); } )cpp", - "0: targets = {Foo}, decl\n" - // FIXME: It's better to target destructor's FunctionDecl instead of - // the type itself (similar to constructor). - "1: targets = {Foo}\n" - "2: targets = {foo()::Foo::destructMe}, decl\n" - "3: targets = {Foo}\n" - "4: targets = {Foo}\n" - "5: targets = {f}, decl\n" - "6: targets = {f}\n" - "7: targets = {Foo}\n"}, - // cxx constructor initializer. - {R"cpp( + "0: targets = {Foo}, decl\n" + // FIXME: It's better to target destructor's FunctionDecl instead of + // the type itself (similar to constructor). + "1: targets = {Foo}\n" + "2: targets = {foo()::Foo::destructMe}, decl\n" + "3: targets = {Foo}\n" + "4: targets = {Foo}\n" + "5: targets = {f}, decl\n" + "6: targets = {f}\n" + "7: targets = {Foo}\n"}, + // cxx constructor initializer. + {R"cpp( class Base {}; void foo() { // member initializer @@ -1432,34 +1449,34 @@ }; } )cpp", - "0: targets = {X}, decl\n" - "1: targets = {foo()::X::abc}, decl\n" - "2: targets = {foo()::X::X}, decl\n" - "3: targets = {foo()::X::abc}\n" - "4: targets = {Derived}, decl\n" - "5: targets = {Base}\n" - "6: targets = {Base}\n" - "7: targets = {foo()::Derived::B}, decl\n" - "8: targets = {foo()::Derived::Derived}, decl\n" - "9: targets = {Base}\n" - "10: targets = {Foo}, decl\n" - "11: targets = {foo()::Foo::Foo}, decl\n" - "12: targets = {foo()::Foo::Foo}, decl\n" - "13: targets = {Foo}\n"}, - // Anonymous entities should not be reported. - { - R"cpp( + "0: targets = {X}, decl\n" + "1: targets = {foo()::X::abc}, decl\n" + "2: targets = {foo()::X::X}, decl\n" + "3: targets = {foo()::X::abc}\n" + "4: targets = {Derived}, decl\n" + "5: targets = {Base}\n" + "6: targets = {Base}\n" + "7: targets = {foo()::Derived::B}, decl\n" + "8: targets = {foo()::Derived::Derived}, decl\n" + "9: targets = {Base}\n" + "10: targets = {Foo}, decl\n" + "11: targets = {foo()::Foo::Foo}, decl\n" + "12: targets = {foo()::Foo::Foo}, decl\n" + "13: targets = {Foo}\n"}, + // Anonymous entities should not be reported. + { + R"cpp( void foo() { class {} $0^x; int (*$1^fptr)(int $2^a, int) = nullptr; } )cpp", - "0: targets = {x}, decl\n" - "1: targets = {fptr}, decl\n" - "2: targets = {a}, decl\n"}, - // Namespace aliases should be handled properly. - { - R"cpp( + "0: targets = {x}, decl\n" + "1: targets = {fptr}, decl\n" + "2: targets = {a}, decl\n"}, + // Namespace aliases should be handled properly. + { + R"cpp( namespace ns { struct Type {}; } namespace alias = ns; namespace rec_alias = alias; @@ -1470,28 +1487,28 @@ $6^rec_alias::$7^Type $8^c; } )cpp", - "0: targets = {ns}\n" - "1: targets = {ns::Type}, qualifier = 'ns::'\n" - "2: targets = {a}, decl\n" - "3: targets = {alias}\n" - "4: targets = {ns::Type}, qualifier = 'alias::'\n" - "5: targets = {b}, decl\n" - "6: targets = {rec_alias}\n" - "7: targets = {ns::Type}, qualifier = 'rec_alias::'\n" - "8: targets = {c}, decl\n"}, - // Handle SizeOfPackExpr. - { - R"cpp( + "0: targets = {ns}\n" + "1: targets = {ns::Type}, qualifier = 'ns::'\n" + "2: targets = {a}, decl\n" + "3: targets = {alias}\n" + "4: targets = {ns::Type}, qualifier = 'alias::'\n" + "5: targets = {b}, decl\n" + "6: targets = {rec_alias}\n" + "7: targets = {ns::Type}, qualifier = 'rec_alias::'\n" + "8: targets = {c}, decl\n"}, + // Handle SizeOfPackExpr. + { + R"cpp( template void foo() { constexpr int $0^size = sizeof...($1^E); }; )cpp", - "0: targets = {size}, decl\n" - "1: targets = {E}\n"}, - // Class template argument deduction - { - R"cpp( + "0: targets = {size}, decl\n" + "1: targets = {E}\n"}, + // Class template argument deduction + { + R"cpp( template struct Test { Test(T); @@ -1500,51 +1517,51 @@ $0^Test $1^a(5); } )cpp", - "0: targets = {Test}\n" - "1: targets = {a}, decl\n"}, - // Templates - {R"cpp( + "0: targets = {Test}\n" + "1: targets = {a}, decl\n"}, + // Templates + {R"cpp( namespace foo { template class $1^Bar {}; } )cpp", - "0: targets = {foo::Bar::T}, decl\n" - "1: targets = {foo::Bar}, decl\n"}, - // Templates - {R"cpp( + "0: targets = {foo::Bar::T}, decl\n" + "1: targets = {foo::Bar}, decl\n"}, + // Templates + {R"cpp( namespace foo { template void $1^func(); } )cpp", - "0: targets = {T}, decl\n" - "1: targets = {foo::func}, decl\n"}, - // Templates - {R"cpp( + "0: targets = {T}, decl\n" + "1: targets = {foo::func}, decl\n"}, + // Templates + {R"cpp( namespace foo { template $1^T $2^x; } )cpp", - "0: targets = {foo::T}, decl\n" - "1: targets = {foo::T}\n" - "2: targets = {foo::x}, decl\n"}, - // Templates - {R"cpp( + "0: targets = {foo::T}, decl\n" + "1: targets = {foo::T}\n" + "2: targets = {foo::x}, decl\n"}, + // Templates + {R"cpp( template class vector {}; namespace foo { template using $1^V = $2^vector<$3^T>; } )cpp", - "0: targets = {foo::T}, decl\n" - "1: targets = {foo::V}, decl\n" - "2: targets = {vector}\n" - "3: targets = {foo::T}\n"}, - // Concept - { - R"cpp( + "0: targets = {foo::T}, decl\n" + "1: targets = {foo::V}, decl\n" + "2: targets = {vector}\n" + "3: targets = {foo::T}\n"}, + // Concept + { + R"cpp( template concept Drawable = requires (T t) { t.draw(); }; @@ -1555,17 +1572,17 @@ } } )cpp", - "0: targets = {T}, decl\n" - "1: targets = {Drawable}\n" - "2: targets = {T}\n" - "3: targets = {foo::bar}, decl\n" - "4: targets = {T}\n" - "5: targets = {t}, decl\n" - "6: targets = {t}\n" - "7: targets = {}\n"}, - // Objective-C: properties - { - R"cpp( + "0: targets = {T}, decl\n" + "1: targets = {Drawable}\n" + "2: targets = {T}\n" + "3: targets = {foo::bar}, decl\n" + "4: targets = {T}\n" + "5: targets = {t}, decl\n" + "6: targets = {t}\n" + "7: targets = {}\n"}, + // Objective-C: properties + { + R"cpp( @interface I {} @property(retain) I* x; @property(retain) I* y; @@ -1575,12 +1592,12 @@ $0^f.$1^x.$2^y = 0; } )cpp", - "0: targets = {f}\n" - "1: targets = {I::x}\n" - "2: targets = {I::y}\n"}, - // Objective-C: implicit properties - { - R"cpp( + "0: targets = {f}\n" + "1: targets = {I::x}\n" + "2: targets = {I::y}\n"}, + // Objective-C: implicit properties + { + R"cpp( @interface I {} -(I*)x; -(void)setY:(I*)y; @@ -1590,12 +1607,11 @@ $0^f.$1^x.$2^y = 0; } )cpp", - "0: targets = {f}\n" - "1: targets = {I::x}\n" - "2: targets = {I::setY:}\n"}, - { - // Objective-C: methods - R"cpp( + "0: targets = {f}\n" + "1: targets = {I::x}\n" + "2: targets = {I::setY:}\n"}, + {// Objective-C: methods + R"cpp( @interface I -(void) a:(int)x b:(int)y; @end @@ -1603,27 +1619,24 @@ [$0^i $1^a:1 b:2]; } )cpp", - "0: targets = {i}\n" - "1: targets = {I::a:b:}\n" - }, - { - // Objective-C: protocols - R"cpp( + "0: targets = {i}\n" + "1: targets = {I::a:b:}\n"}, + {// Objective-C: protocols + R"cpp( @interface I @end @protocol P @end void foo() { - // FIXME: should reference P - $0^I

*$1^x; + $0^I<$1^P> *$2^x; } )cpp", - "0: targets = {I}\n" - "1: targets = {x}, decl\n" - }, + "0: targets = {I}\n" + "1: targets = {P}\n" + "2: targets = {x}, decl\n"}, - // Designated initializers. - {R"cpp( + // Designated initializers. + {R"cpp( void foo() { struct $0^Foo { int $1^Bar; @@ -1631,12 +1644,12 @@ $2^Foo $3^f { .$4^Bar = 42 }; } )cpp", - "0: targets = {Foo}, decl\n" - "1: targets = {foo()::Foo::Bar}, decl\n" - "2: targets = {Foo}\n" - "3: targets = {f}, decl\n" - "4: targets = {foo()::Foo::Bar}\n"}, - {R"cpp( + "0: targets = {Foo}, decl\n" + "1: targets = {foo()::Foo::Bar}, decl\n" + "2: targets = {Foo}\n" + "3: targets = {f}, decl\n" + "4: targets = {foo()::Foo::Bar}\n"}, + {R"cpp( void foo() { struct $0^Baz { int $1^Field; diff --git a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp --- a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp +++ b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp @@ -676,8 +676,7 @@ @end @interface $Class_decl[[Klass]] <$Interface[[Protocol]]> @end - // FIXME: protocol list in ObjCObjectType should be highlighted. - id $Variable_decl[[x]]; + id<$Interface[[Protocol]]> $Variable_decl[[x]]; )cpp", R"cpp( // ObjC: Categories