Given a range whose endpoints may be in different expansions or files, tries to find a range within a common file by following up the expansion and include location in each.
| 119 | // tries to find a range within a common file by following up the expansion and |
| 120 | // include location in each. |
| 121 | static SourceRange rangeInCommonFile(SourceRange R, |
| 122 | const SourceManager& SM, |
| 123 | const LangOptions& LangOpts) { |
| 124 | // Fast path for most common cases. |
| 125 | if(SM.isWrittenInSameFile(R.getBegin(), R.getEnd())) |
| 126 | return R; |
| 127 | // Record the stack of expansion locations for the beginning, keyed by FileID. |
| 128 | llvm::DenseMap<FileID, SourceLocation> BeginExpansions; |
| 129 | for(SourceLocation Begin = R.getBegin(); Begin.isValid(); |
| 130 | Begin = Begin.isFileID() ? includeHashLoc(SM.getFileID(Begin), SM) |
| 131 | : SM.getImmediateExpansionRange(Begin).getBegin()) { |
| 132 | BeginExpansions[SM.getFileID(Begin)] = Begin; |
| 133 | } |
| 134 | // Move up the stack of expansion locations for the end until we find the |
| 135 | // location in BeginExpansions with that has the same file id. |
| 136 | for(SourceLocation End = R.getEnd(); End.isValid(); |
| 137 | End = End.isFileID() |
| 138 | ? includeHashLoc(SM.getFileID(End), SM) |
| 139 | : toTokenRange(SM.getImmediateExpansionRange(End), SM, LangOpts).getEnd()) { |
| 140 | auto It = BeginExpansions.find(SM.getFileID(End)); |
| 141 | if(It != BeginExpansions.end()) { |
| 142 | if(SM.getFileOffset(It->second) > SM.getFileOffset(End)) |
| 143 | return SourceLocation(); |
| 144 | return {It->second, End}; |
| 145 | } |
| 146 | } |
| 147 | return SourceRange(); |
| 148 | } |
| 149 | |
| 150 | // Find an expansion range (not necessarily immediate) the ends of which are in |
| 151 | // the same file id. |
no test coverage detected