diff --git a/clang-tools-extra/clangd/IncludeCleaner.cpp b/clang-tools-extra/clangd/IncludeCleaner.cpp --- a/clang-tools-extra/clangd/IncludeCleaner.cpp +++ b/clang-tools-extra/clangd/IncludeCleaner.cpp @@ -15,6 +15,7 @@ #include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/SourceLocation.h" #include "clang/Tooling/Syntax/Tokens.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/Path.h" @@ -42,6 +43,14 @@ } bool VisitTagType(TagType *TT) { + // For RecordDecls take either definition or the most recent forward + // declaration. + if (const auto *RD = llvm::dyn_cast(TT->getDecl())) { + const auto *Definition = RD->getDefinition(); + Result.insert(Definition ? Definition->getLocation() + : RD->getMostRecentDecl()->getLocation()); + return true; + } add(TT->getDecl()); return true; } diff --git a/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp b/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp --- a/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp +++ b/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp @@ -72,9 +72,13 @@ }, // Redecls { - "class ^X; class ^X{}; class ^X;", + "class X; class ^X{}; class X;", "X *y;", }, + { + "class X;", + "class X; X *y;", + }, // Constructor { "struct ^X { ^X(int) {} int ^foo(); };",