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 @@ -780,6 +780,16 @@ $LocalVariable_decl[[d]]($LocalVariable[[b]]) ]() {}(); } )cpp", + // Enum base specifier + R"cpp( + using $Primitive_decl[[MyTypedef]] = int; + enum $Enum_decl[[MyEnum]] : $Primitive[[MyTypedef]] {}; + )cpp", + // Enum base specifier + R"cpp( + typedef int $Primitive_decl[[MyTypedef]]; + enum $Enum_decl[[MyEnum]] : $Primitive[[MyTypedef]] {}; + )cpp", }; for (const auto &TestCase : TestCases) // Mask off scope modifiers to keep the tests manageable. diff --git a/clang-tools-extra/clangd/unittests/XRefsTests.cpp b/clang-tools-extra/clangd/unittests/XRefsTests.cpp --- a/clang-tools-extra/clangd/unittests/XRefsTests.cpp +++ b/clang-tools-extra/clangd/unittests/XRefsTests.cpp @@ -880,6 +880,15 @@ }; )cpp", + R"cpp(// Enum base + typedef int $decl[[MyTypeDef]]; + enum Foo : My^TypeDef {}; + )cpp", + R"cpp(// Enum base + using $decl[[MyTypeDef]] = int; + enum Foo : My^TypeDef {}; + )cpp", + R"objc( @protocol Dog; @protocol $decl[[Dog]] @@ -1953,6 +1962,16 @@ [[f^oo]](s); } )cpp", + + // Enum base + R"cpp( + typedef int $def[[MyTypeDef]]; + enum MyEnum : [[MyTy^peDef]] { }; + )cpp", + R"cpp( + using $def[[MyTypeDef]] = int; + enum MyEnum : [[MyTy^peDef]] { }; + )cpp", }; for (const char *Test : Tests) checkFindRefs(Test); diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -1863,6 +1863,9 @@ DEF_TRAVERSE_DECL(EnumDecl, { TRY_TO(TraverseDeclTemplateParameterLists(D)); + if (auto *TSI = D->getIntegerTypeSourceInfo()) + TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); + if (D->getTypeForDecl()) TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0))); diff --git a/clang/lib/Index/IndexTypeSourceInfo.cpp b/clang/lib/Index/IndexTypeSourceInfo.cpp --- a/clang/lib/Index/IndexTypeSourceInfo.cpp +++ b/clang/lib/Index/IndexTypeSourceInfo.cpp @@ -7,8 +7,10 @@ //===----------------------------------------------------------------------===// #include "IndexingContext.h" +#include "clang/AST/Decl.h" #include "clang/AST/RecursiveASTVisitor.h" #include "llvm/ADT/ScopeExit.h" +#include "llvm/Support/Casting.h" using namespace clang; using namespace index; @@ -305,6 +307,9 @@ for (const auto &I : CXXRD->bases()) { indexTypeSourceInfo(I.getTypeSourceInfo(), CXXRD, CXXRD, /*isBase=*/true); } + } else if (auto *ED = dyn_cast(D)) { + if (auto *TSI = ED->getIntegerTypeSourceInfo()) + indexTypeSourceInfo(TSI, ED, ED, /*isBase=*/true); } indexDeclContext(D); } diff --git a/clang/unittests/Index/IndexTests.cpp b/clang/unittests/Index/IndexTests.cpp --- a/clang/unittests/Index/IndexTests.cpp +++ b/clang/unittests/Index/IndexTests.cpp @@ -377,6 +377,18 @@ Not(HasRole(SymbolRole::RelationBaseOf))))); } +TEST(IndexTest, EnumBase) { + std::string Code = R"cpp( + typedef int MyTypedef; + enum Foo : MyTypedef {}; + )cpp"; + auto Index = std::make_shared(); + tooling::runToolOnCode(std::make_unique(Index), Code); + // A should not be the base of anything. + EXPECT_THAT(Index->Symbols, + Contains(AllOf(QName("MyTypedef"), HasRole(SymbolRole::Reference), + WrittenAt(Position(3, 16))))); +} } // namespace } // namespace index } // namespace clang