diff --git a/clang-tools-extra/clangd/SemanticHighlighting.cpp b/clang-tools-extra/clangd/SemanticHighlighting.cpp --- a/clang-tools-extra/clangd/SemanticHighlighting.cpp +++ b/clang-tools-extra/clangd/SemanticHighlighting.cpp @@ -250,16 +250,44 @@ bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) { H.addToken(E->getNameInfo().getLoc(), HighlightingKind::DependentName); + visitDependentTypesInQualifier(E->getQualifierLoc()); return true; } bool VisitDependentNameTypeLoc(DependentNameTypeLoc L) { H.addToken(L.getNameLoc(), HighlightingKind::DependentType); + visitDependentTypesInQualifier(L.getQualifierLoc()); + return true; + } + + // This is similar to DependentNameTypeLoc, but used for + // template-ids where the template-name itself is dependent. + bool VisitDependentTemplateSpecializationTypeLoc( + DependentTemplateSpecializationTypeLoc L) { + H.addToken(L.getTemplateNameLoc(), HighlightingKind::DependentType); + visitDependentTypesInQualifier(L.getQualifierLoc()); return true; } private: HighlightingsBuilder &H; + + // findExplicitReferences will walk nested-name-specifiers and + // find anything that can be resolved to a Decl. However, non-leaf + // components of nested-name-specifiers which are dependent names + // (kind "Identifier") cannot be resolved to a decl and also do + // not have a Visit() method called on them directly, so we + // walk the nested-name-specifiers of relevant node types + // (e.g. DependentScopeDeclRefExpr) here to catch them. + void visitDependentTypesInQualifier(NestedNameSpecifierLoc Q) { + NestedNameSpecifier *NNS = Q.getNestedNameSpecifier(); + if (!NNS) + return; + if (NNS->getKind() == NestedNameSpecifier::Identifier) { + H.addToken(Q.getLocalBeginLoc(), HighlightingKind::DependentType); + } + visitDependentTypesInQualifier(Q.getPrefix()); + } }; // Encode binary data into base64. 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 @@ -630,7 +630,24 @@ R"cpp( template struct $Class[[TupleSize]] { - static const int $StaticField[[size]] = sizeof...($TemplateParameter[[Elements]]); + static const int $StaticField[[size]] = +sizeof...($TemplateParameter[[Elements]]); + }; + )cpp", + // More dependent types + R"cpp( + template + struct $Class[[Waldo]] { + using $Typedef[[Location1]] = typename $TemplateParameter[[T]] + ::$DependentType[[Resolver]]::$DependentType[[Location]]; + using $Typedef[[Location2]] = typename $TemplateParameter[[T]] + ::template $DependentType[[Resolver]]<$TemplateParameter[[T]]> + ::$DependentType[[Location]]; + using $Typedef[[Location3]] = typename $TemplateParameter[[T]] + ::$DependentType[[Resolver]] + ::template $DependentType[[Location]]<$TemplateParameter[[T]]>; + static const int $StaticField[[Value]] = $TemplateParameter[[T]] + ::$DependentType[[Resolver]]::$DependentName[[Value]]; }; )cpp"}; for (const auto &TestCase : TestCases) {