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 @@ -15,12 +15,33 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/Type.h" +#include "clang/AST/TypeLoc.h" #include namespace clang { namespace clangd { namespace { +/// Return a type that should be used for highlighting a typedef to type \p T. +/// Can be null, e.g. for dependent expression in decltype(). +const Type *getTypeForHighlighting(const Type *T) { + assert(T != nullptr); + while (true) { + // Remove all syntax sugar, this handles 'auto', 'decltype', typedefs, etc. + T = T->getUnqualifiedDesugaredType(); + QualType Pointee = T->getPointeeType(); + if (!Pointee.isNull()) + T = Pointee.getTypePtr(); + else if (T->isArrayType()) + T = T->getArrayElementTypeNoTypeQual(); + else if (auto *F = T->getAs()) + T = F->getReturnType().getTypePtrOrNull(); + else // We reached the leaf type, return it to the user. + return T; + } +} + // Collects all semantic tokens in an ASTContext. class HighlightingTokenCollector : public RecursiveASTVisitor { @@ -124,17 +145,17 @@ bool VisitTypedefNameDecl(TypedefNameDecl *TD) { if (const auto *TSI = TD->getTypeSourceInfo()) - addType(TD->getLocation(), TSI->getTypeLoc().getTypePtr()); + addType(TD->getLocation(), + getTypeForHighlighting(TSI->getTypeLoc().getType().getTypePtr())); return true; } - bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc &TL) { - // TemplateTypeParmTypeLoc does not have a TagDecl in its type ptr. - addToken(TL.getBeginLoc(), TL.getDecl()); + bool VisitTypedefTypeLoc(TypedefTypeLoc TL) { + addType(TL.getBeginLoc(), getTypeForHighlighting(TL.getTypePtr())); return true; } - bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc &TL) { + bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) { if (const TemplateDecl *TD = TL.getTypePtr()->getTemplateName().getAsTemplateDecl()) addToken(TL.getBeginLoc(), TD); @@ -187,6 +208,9 @@ if (TP->isBuiltinType()) // Builtins must be special cased as they do not have a TagDecl. addToken(Loc, HighlightingKind::Primitive); + if (const TemplateTypeParmType *TD = dyn_cast(TP)) + // TemplateTypeParmType also do not have a TagDecl. + addToken(Loc, TD->getDecl()); if (const TagDecl *TD = TP->getAsTagDecl()) addToken(Loc, TD); } 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 @@ -231,7 +231,9 @@ )cpp", R"cpp( namespace $Namespace[[a]] { - struct $Class[[A]] {}; + struct $Class[[A]] { + $Primitive[[void]] $Method[[foo]]($Class[[A]]*); + }; typedef $Primitive[[char]] $Primitive[[C]]; } typedef $Namespace[[a]]::$Class[[A]] $Class[[B]]; @@ -244,6 +246,12 @@ $Enum[[CD]] $Function[[f]]($Class[[BB]]); typedef $Namespace[[a]]::$Primitive[[C]] $Primitive[[PC]]; typedef $Primitive[[float]] $Primitive[[F]]; + using $Primitive[[Member]] = + $Primitive[[void]] (B::*)($Namespace[[a]]::$Class[[A]]*); + $Primitive[[void]] $Function[[foo]]($Primitive[[int]], $Class[[B]]); + typedef decltype($Function[[foo]]) $Primitive[[fooo]]; + typedef $Class[[B]] (*$Class[[func]])(); + typedef $Primitive[[int]] (*$Primitive[[func]])(); )cpp", R"cpp( template @@ -439,7 +447,7 @@ $Macro[[assert]]($Variable[[x]] != $Function[[f]]()); } )cpp", - R"cpp( + R"cpp( struct $Class[[S]] { $Primitive[[float]] $Field[[Value]]; $Class[[S]] *$Field[[Next]]; @@ -453,6 +461,20 @@ // Highlights references to BindingDecls. $Variable[[B1]]++; } + )cpp", + R"cpp( + template + class $Class[[A]] { + using $TemplateParameter[[D]] = $TemplateParameter[[T]]; + using $TemplateParameter[[DD]] = $TemplateParameter[[T]] *; + using $TemplateParameter[[DDD]] = $TemplateParameter[[T]] &; + using $TemplateParameter[[B]] = $TemplateParameter[[T]]*[3]; + using $TemplateParameter[[BB]] = $TemplateParameter[[T]]&&; + using $TemplateParameter[[Member]] = + $TemplateParameter[[BB]] (T::*)($Primitive[[int]]); + using $TemplateParameter[[MemberT]] = + $TemplateParameter[[T]]*& (T::*)($Class[[A]]); + }; )cpp"}; for (const auto &TestCase : TestCases) { checkHighlightings(TestCase);