diff --git a/llvm/include/llvm/TableGen/Record.h b/llvm/include/llvm/TableGen/Record.h --- a/llvm/include/llvm/TableGen/Record.h +++ b/llvm/include/llvm/TableGen/Record.h @@ -1558,6 +1558,7 @@ // Location where record was instantiated, followed by the location of // multiclass prototypes used. SmallVector Locs; + SmallVector ForwardDeclarationLocs; SmallVector TemplateArgs; SmallVector Values; SmallVector Assertions; @@ -1623,6 +1624,13 @@ ArrayRef getLoc() const { return Locs; } void appendLoc(SMLoc Loc) { Locs.push_back(Loc); } + ArrayRef 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(); diff --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp --- a/llvm/lib/TableGen/Record.cpp +++ b/llvm/lib/TableGen/Record.cpp @@ -2424,6 +2424,14 @@ 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(Name); diff --git a/llvm/lib/TableGen/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp --- a/llvm/lib/TableGen/TGParser.cpp +++ b/llvm/lib/TableGen/TGParser.cpp @@ -3391,6 +3391,8 @@ !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 = diff --git a/llvm/test/TableGen/GenTags.td b/llvm/test/TableGen/GenTags.td new file mode 100644 --- /dev/null +++ b/llvm/test/TableGen/GenTags.td @@ -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"; +} diff --git a/llvm/utils/TableGen/CTagsEmitter.cpp b/llvm/utils/TableGen/CTagsEmitter.cpp --- a/llvm/utils/TableGen/CTagsEmitter.cpp +++ b/llvm/utils/TableGen/CTagsEmitter.cpp @@ -27,18 +27,22 @@ 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 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 @@ std::vector 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.