[TableGen] Add a location for a class definition that was forward-declared

This change improves ctags generation for tablegen files.

For the following example
```
class A;

class A {
  int a;
}
```
Previously, tags were generated only for a forward declaration of class 'A'.

This patch allows generating tags for the forward declarations
and further definition of class 'A'.

Reviewed By: barannikov88

Original patch by: rusyaev-roman (Roman Rusyaev)
Some adjustments by: nhaehnle (Nicolai Hähnle)

Differential Revision: https://reviews.llvm.org/D129935
This commit is contained in:
Roman Rusyaev 2022-07-20 15:25:02 +02:00 committed by Nicolai Hähnle
parent 643dfd97d5
commit 394a388d14
5 changed files with 45 additions and 11 deletions

View File

@ -1558,6 +1558,7 @@ private:
// Location where record was instantiated, followed by the location of
// multiclass prototypes used.
SmallVector<SMLoc, 4> Locs;
SmallVector<SMLoc, 0> ForwardDeclarationLocs;
SmallVector<Init *, 0> TemplateArgs;
SmallVector<RecordVal, 0> Values;
SmallVector<AssertionInfo, 0> Assertions;
@ -1623,6 +1624,13 @@ public:
ArrayRef<SMLoc> getLoc() const { return Locs; }
void appendLoc(SMLoc Loc) { Locs.push_back(Loc); }
ArrayRef<SMLoc> getForwardDeclarationLocs() const {
return ForwardDeclarationLocs;
}
// Update a class location when encountering a (re-)definition.
void updateClassLoc(SMLoc Loc);
// Make the type that this record should have based on its superclasses.
RecordRecTy *getType();

View File

@ -2424,6 +2424,14 @@ void RecordVal::print(raw_ostream &OS, bool PrintSem) const {
if (PrintSem) OS << ";\n";
}
void Record::updateClassLoc(SMLoc Loc) {
assert(Locs.size() == 1);
ForwardDeclarationLocs.push_back(Locs.front());
Locs.clear();
Locs.push_back(Loc);
}
void Record::checkName() {
// Ensure the record name has string type.
const TypedInit *TypedName = cast<const TypedInit>(Name);

View File

@ -3391,6 +3391,8 @@ bool TGParser::ParseClass() {
!CurRec->getTemplateArgs().empty())
return TokError("Class '" + CurRec->getNameInitAsString() +
"' already defined");
CurRec->updateClassLoc(Lex.getLoc());
} else {
// If this is the first reference to this class, create and add it.
auto NewRec =

View File

@ -0,0 +1,9 @@
// RUN: llvm-tblgen --gen-ctags %s | FileCheck %s -DFILE=%s
// CHECK: A [[FILE]] [[@LINE+1]]
class A;
// CHECK: A [[FILE]] [[@LINE+1]]
class A {
string name = "A";
}

View File

@ -27,18 +27,22 @@ namespace {
class Tag {
private:
const std::string *Id;
SMLoc Loc;
StringRef Id;
StringRef BufferIdentifier;
unsigned Line;
public:
Tag(const std::string &Name, const SMLoc Location)
: Id(&Name), Loc(Location) {}
int operator<(const Tag &B) const { return *Id < *B.Id; }
void emit(raw_ostream &OS) const {
Tag(StringRef Name, const SMLoc Location) : Id(Name) {
const MemoryBuffer *CurMB =
SrcMgr.getMemoryBuffer(SrcMgr.FindBufferContainingLoc(Loc));
auto BufferName = CurMB->getBufferIdentifier();
std::pair<unsigned, unsigned> LineAndColumn = SrcMgr.getLineAndColumn(Loc);
OS << *Id << "\t" << BufferName << "\t" << LineAndColumn.first << "\n";
SrcMgr.getMemoryBuffer(SrcMgr.FindBufferContainingLoc(Location));
BufferIdentifier = CurMB->getBufferIdentifier();
auto LineAndColumn = SrcMgr.getLineAndColumn(Location);
Line = LineAndColumn.first;
}
int operator<(const Tag &B) const {
return std::make_tuple(Id, BufferIdentifier, Line) < std::make_tuple(B.Id, B.BufferIdentifier, B.Line);
}
void emit(raw_ostream &OS) const {
OS << Id << "\t" << BufferIdentifier << "\t" << Line << "\n";
}
};
@ -67,8 +71,11 @@ void CTagsEmitter::run(raw_ostream &OS) {
std::vector<Tag> Tags;
// Collect tags.
Tags.reserve(Classes.size() + Defs.size());
for (const auto &C : Classes)
for (const auto &C : Classes) {
Tags.push_back(Tag(C.first, locate(C.second.get())));
for (SMLoc FwdLoc : C.second->getForwardDeclarationLocs())
Tags.push_back(Tag(C.first, FwdLoc));
}
for (const auto &D : Defs)
Tags.push_back(Tag(D.first, locate(D.second.get())));
// Emit tags.