mirror of
https://github.com/llvm/llvm-project.git
synced 2025-05-09 09:36:07 +00:00

When using FileIndexRecord with macros, symbol references can be seen out of source order, which was causing a regression to insert the symbols into a vector. Instead, we now lazily sort the vector. The impact is small on most code, but in very large files with many macro references (M) near the beginning of the file followed by many decl references (D) it was O(M*D). A particularly bad protobuf-generated header was observed with a 100% regression in practice. rdar://78628133
83 lines
2.8 KiB
C++
83 lines
2.8 KiB
C++
//===--- FileIndexRecord.cpp - Index data per file --------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "FileIndexRecord.h"
|
|
#include "clang/AST/ASTContext.h"
|
|
#include "clang/AST/DeclTemplate.h"
|
|
#include "clang/Basic/SourceManager.h"
|
|
#include "llvm/ADT/SmallString.h"
|
|
#include "llvm/Support/Path.h"
|
|
|
|
using namespace clang;
|
|
using namespace clang::index;
|
|
|
|
ArrayRef<DeclOccurrence>
|
|
FileIndexRecord::getDeclOccurrencesSortedByOffset() const {
|
|
if (!IsSorted) {
|
|
llvm::stable_sort(Decls,
|
|
[](const DeclOccurrence &A, const DeclOccurrence &B) {
|
|
return A.Offset < B.Offset;
|
|
});
|
|
IsSorted = true;
|
|
}
|
|
return Decls;
|
|
}
|
|
|
|
void FileIndexRecord::addDeclOccurence(SymbolRoleSet Roles, unsigned Offset,
|
|
const Decl *D,
|
|
ArrayRef<SymbolRelation> Relations) {
|
|
assert(D->isCanonicalDecl() &&
|
|
"Occurrences should be associated with their canonical decl");
|
|
IsSorted = false;
|
|
Decls.emplace_back(Roles, Offset, D, Relations);
|
|
}
|
|
|
|
void FileIndexRecord::addMacroOccurence(SymbolRoleSet Roles, unsigned Offset,
|
|
const IdentifierInfo *Name,
|
|
const MacroInfo *MI) {
|
|
IsSorted = false;
|
|
Decls.emplace_back(Roles, Offset, Name, MI);
|
|
}
|
|
|
|
void FileIndexRecord::removeHeaderGuardMacros() {
|
|
auto It =
|
|
std::remove_if(Decls.begin(), Decls.end(), [](const DeclOccurrence &D) {
|
|
if (const auto *MI = D.DeclOrMacro.dyn_cast<const MacroInfo *>())
|
|
return MI->isUsedForHeaderGuard();
|
|
return false;
|
|
});
|
|
Decls.erase(It, Decls.end());
|
|
}
|
|
|
|
void FileIndexRecord::print(llvm::raw_ostream &OS, SourceManager &SM) const {
|
|
OS << "DECLS BEGIN ---\n";
|
|
for (auto &DclInfo : Decls) {
|
|
if (const auto *D = DclInfo.DeclOrMacro.dyn_cast<const Decl *>()) {
|
|
SourceLocation Loc = SM.getFileLoc(D->getLocation());
|
|
PresumedLoc PLoc = SM.getPresumedLoc(Loc);
|
|
OS << llvm::sys::path::filename(PLoc.getFilename()) << ':'
|
|
<< PLoc.getLine() << ':' << PLoc.getColumn();
|
|
|
|
if (const auto *ND = dyn_cast<NamedDecl>(D)) {
|
|
OS << ' ' << ND->getDeclName();
|
|
}
|
|
} else {
|
|
const auto *MI = DclInfo.DeclOrMacro.get<const MacroInfo *>();
|
|
SourceLocation Loc = SM.getFileLoc(MI->getDefinitionLoc());
|
|
PresumedLoc PLoc = SM.getPresumedLoc(Loc);
|
|
OS << llvm::sys::path::filename(PLoc.getFilename()) << ':'
|
|
<< PLoc.getLine() << ':' << PLoc.getColumn();
|
|
OS << ' ' << DclInfo.MacroName->getName();
|
|
}
|
|
|
|
OS << '\n';
|
|
}
|
|
OS << "DECLS END ---\n";
|
|
}
|