2

Is there any way to get clang::SourceLocation for every #include in file by its clang::FileID or clang::FileEntry or something?

Mike Kinghan
  • 55,740
  • 12
  • 153
  • 182
Yuriy
  • 701
  • 4
  • 18

2 Answers2

2

What about using source manager's GetIncludedLoc function which takes fileid as parameter.

SourceManager.GetIncludedLoc(fileid)

Hemant
  • 767
  • 6
  • 20
  • Once I have the include location, how do I navigate between the includes include? I'm using this to inject an include statement but it goes before the comments of the copyright which is not what I want. – emitrax Mar 09 '21 at 15:05
  • This is a good tip, but the method name is `getIncludeLoc` (and has been since its [introduction](https://github.com/llvm/llvm-project/commit/61ef3db22246)). – Scott McPeak Jul 20 '23 at 04:47
1

Thank's @Hemant for your answer, you're right

I Already found that by myself (in clang 3.8 it is called getIncludeLoc) but forgot to write here. I used this to find the location after all #includes where i can put my own. Here's the function (For sure not the best way) I wrote for this, hope it helps someone

SourceLocation getIncludeLocation(FileID fileID, SourceManager &sm, unsigned carriages) {
       return SourceLocation();
     set<unsigned> lines;
    if (fileID.isInvalid())
    for (auto it = sm.fileinfo_begin(); it != sm.fileinfo_end(); it++) {
        SourceLocation includeLoc = sm.getIncludeLoc(sm.translateFile(it->first));
        if (includeLoc.isValid() && sm.isInFileID(includeLoc, fileID)) {
            lines.insert(sm.getSpellingLineNumber(includeLoc));
        }
    }
    unsigned pos(0);
    if (!lines.empty()) {
        bool first = true;
        for (unsigned line :lines) {
            if (first)
                first = false;
            else if ((line - pos) > carriages)
                break;
            pos = line;
            //cout << "Include line:" << pos << endl;
        }
        //cout << console_hline('-') << endl;
    }
    cout << sm.getFileEntryForID(fileID)->getName() << endl;
    return sm.translateFileLineCol(sm.getFileEntryForID(fileID), ++pos, 1);
}

Also some information about includes can be get by

Preprocessor::GetIncludeFilenameSpelling(SourceLocation Loc, StringRef &Buffer)

and

Lexer::ComputePreamble(StringRef Buffer, const LangOptions &LangOpts, unsigned MaxLines = 0)    
Yuriy
  • 701
  • 4
  • 18