I have a SourceLocation
that I wish to extract its filename from. Apparently, I should be able to do that by using SourceManager
's getFilename
. However, the result seems to always be an empty string when I process some header files.
I follow the source code and found that the issue is that in the getFilename
function, which reads:
/// Return the filename of the file containing a SourceLocation.
StringRef getFilename(SourceLocation SpellingLoc) const {
if (const FileEntry *F = getFileEntryForID(getFileID(SpellingLoc)))
return F->getName();
return StringRef();
}
The result of getFileID
is somehow invalid in a sense that SLocEntry
constructed from it will have isFile
returning false
. This causes getFileEntryForID
(which does construct SLocEntry
under the hood) to return a null pointer.
I have a workaround, which is:
StringRef myGetFilename(SourceLocation SpellingLoc) const {
std::pair<FileID, unsigned> locInfo = getDecomposedExpansionLoc(SpellingLoc);
if (const FileEntry *F = srcManager.getFileEntryForID(locInfo.first))
return F->getName();
return StringRef();
}
That is, call getDecomposedExpansionLoc
first to get a raw FileID
and use it in getFileEntryForID
instead.
Experimentally, this seems to work well, but this is my first day with clang, so I'm very unsure if it's actually correct. So I have two questions:
Thanks!
Ah, so the problem seems to be that getFilename
expects a specific kind of SourceLocation
, namely "SpellingLoc". So, change:
srcManager.getFilename(loc)
to
srcManager.getFilename(srcManager.getSpellingLoc(loc))
will fix the problem.