本文整理汇总了C++中SourceLocation::isFileID方法的典型用法代码示例。如果您正苦于以下问题:C++ SourceLocation::isFileID方法的具体用法?C++ SourceLocation::isFileID怎么用?C++ SourceLocation::isFileID使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类SourceLocation
的用法示例。
在下文中一共展示了SourceLocation::isFileID方法的13个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: assert
/// If \arg loc is a file ID and points inside the current macro
/// definition, returns the appropriate source location pointing at the
/// macro expansion source location entry, otherwise it returns an invalid
/// SourceLocation.
SourceLocation
TokenLexer::getExpansionLocForMacroDefLoc(SourceLocation loc) const {
assert(ExpandLocStart.isValid() && MacroExpansionStart.isValid() &&
"Not appropriate for token streams");
assert(loc.isValid() && loc.isFileID());
SourceManager &SM = PP.getSourceManager();
assert(SM.isInSLocAddrSpace(loc, MacroDefStart, MacroDefLength) &&
"Expected loc to come from the macro definition");
unsigned relativeOffset = 0;
SM.isInSLocAddrSpace(loc, MacroDefStart, MacroDefLength, &relativeOffset);
return MacroExpansionStart.getLocWithOffset(relativeOffset);
}
示例2: CheckRemoval
// Checks if 'typedef' keyword can be removed - we do it only if
// it is the only declaration in a declaration chain.
static bool CheckRemoval(SourceManager &SM, SourceLocation StartLoc,
ASTContext &Context) {
assert(StartLoc.isFileID() && "StartLoc must not be in a macro");
std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(StartLoc);
StringRef File = SM.getBufferData(LocInfo.first);
const char *TokenBegin = File.data() + LocInfo.second;
Lexer DeclLexer(SM.getLocForStartOfFile(LocInfo.first), Context.getLangOpts(),
File.begin(), TokenBegin, File.end());
Token Tok;
int ParenLevel = 0;
bool FoundTypedef = false;
while (!DeclLexer.LexFromRawLexer(Tok) && !Tok.is(tok::semi)) {
switch (Tok.getKind()) {
case tok::l_brace:
case tok::r_brace:
// This might be the `typedef struct {...} T;` case.
return false;
case tok::l_paren:
ParenLevel++;
break;
case tok::r_paren:
ParenLevel--;
break;
case tok::comma:
if (ParenLevel == 0) {
// If there is comma and we are not between open parenthesis then it is
// two or more declarations in this chain.
return false;
}
break;
case tok::raw_identifier:
if (Tok.getRawIdentifier() == "typedef") {
FoundTypedef = true;
}
break;
default:
break;
}
}
// Sanity check against weird macro cases.
return FoundTypedef;
}
示例3: isEmptyARCMTMacroStatement
static bool isEmptyARCMTMacroStatement(NullStmt *S,
std::vector<SourceLocation> &MacroLocs,
ASTContext &Ctx) {
if (!S->hasLeadingEmptyMacro())
return false;
SourceLocation SemiLoc = S->getSemiLoc();
if (SemiLoc.isInvalid() || SemiLoc.isMacroID())
return false;
if (MacroLocs.empty())
return false;
SourceManager &SM = Ctx.getSourceManager();
std::vector<SourceLocation>::iterator
I = std::upper_bound(MacroLocs.begin(), MacroLocs.end(), SemiLoc,
BeforeThanCompare<SourceLocation>(SM));
--I;
SourceLocation
AfterMacroLoc = I->getLocWithOffset(getARCMTMacroName().size());
assert(AfterMacroLoc.isFileID());
if (AfterMacroLoc == SemiLoc)
return true;
int RelOffs = 0;
if (!SM.isInSameSLocAddrSpace(AfterMacroLoc, SemiLoc, &RelOffs))
return false;
if (RelOffs < 0)
return false;
// We make the reasonable assumption that a semicolon after 100 characters
// means that it is not the next token after our macro. If this assumption
// fails it is not critical, we will just fail to clear out, e.g., an empty
// 'if'.
if (RelOffs - getARCMTMacroName().size() > 100)
return false;
SourceLocation AfterMacroSemiLoc = findSemiAfterLocation(AfterMacroLoc, Ctx);
return AfterMacroSemiLoc == SemiLoc;
}
示例4: locationsInSameFile
static bool locationsInSameFile(const SourceManager &Sources,
SourceLocation Loc1, SourceLocation Loc2) {
return Loc1.isFileID() && Loc2.isFileID() &&
Sources.getFileID(Loc1) == Sources.getFileID(Loc2);
}
示例5: emitMacroExpansions
/// \brief Recursively emit notes for each macro expansion and caret
/// diagnostics where appropriate.
///
/// Walks up the macro expansion stack printing expansion notes, the code
/// snippet, caret, underlines and FixItHint display as appropriate at each
/// level.
///
/// \param Loc The location for this caret.
/// \param Level The diagnostic level currently being emitted.
/// \param Ranges The underlined ranges for this code snippet.
/// \param Hints The FixIt hints active for this diagnostic.
void DiagnosticRenderer::emitMacroExpansions(SourceLocation Loc,
DiagnosticsEngine::Level Level,
ArrayRef<CharSourceRange> Ranges,
ArrayRef<FixItHint> Hints,
const SourceManager &SM) {
assert(!Loc.isInvalid() && "must have a valid source location here");
// Produce a stack of macro backtraces.
SmallVector<SourceLocation, 8> LocationStack;
unsigned IgnoredEnd = 0;
while (Loc.isMacroID()) {
// If this is the expansion of a macro argument, point the caret at the
// use of the argument in the definition of the macro, not the expansion.
if (SM.isMacroArgExpansion(Loc))
LocationStack.push_back(SM.getImmediateExpansionRange(Loc).first);
else
LocationStack.push_back(Loc);
if (checkRangesForMacroArgExpansion(Loc, Ranges, SM))
IgnoredEnd = LocationStack.size();
Loc = SM.getImmediateMacroCallerLoc(Loc);
// Once the location no longer points into a macro, try stepping through
// the last found location. This sometimes produces additional useful
// backtraces.
if (Loc.isFileID())
Loc = SM.getImmediateMacroCallerLoc(LocationStack.back());
assert(!Loc.isInvalid() && "must have a valid source location here");
}
LocationStack.erase(LocationStack.begin(),
LocationStack.begin() + IgnoredEnd);
unsigned MacroDepth = LocationStack.size();
unsigned MacroLimit = DiagOpts->MacroBacktraceLimit;
if (MacroDepth <= MacroLimit || MacroLimit == 0) {
for (auto I = LocationStack.rbegin(), E = LocationStack.rend();
I != E; ++I)
emitSingleMacroExpansion(*I, Level, Ranges, SM);
return;
}
unsigned MacroStartMessages = MacroLimit / 2;
unsigned MacroEndMessages = MacroLimit / 2 + MacroLimit % 2;
for (auto I = LocationStack.rbegin(),
E = LocationStack.rbegin() + MacroStartMessages;
I != E; ++I)
emitSingleMacroExpansion(*I, Level, Ranges, SM);
SmallString<200> MessageStorage;
llvm::raw_svector_ostream Message(MessageStorage);
Message << "(skipping " << (MacroDepth - MacroLimit)
<< " expansions in backtrace; use -fmacro-backtrace-limit=0 to "
"see all)";
emitBasicNote(Message.str());
for (auto I = LocationStack.rend() - MacroEndMessages,
E = LocationStack.rend();
I != E; ++I)
emitSingleMacroExpansion(*I, Level, Ranges, SM);
}
示例6: emitSnippetAndCaret
/// \brief Emit a code snippet and caret line.
///
/// This routine emits a single line's code snippet and caret line..
///
/// \param Loc The location for the caret.
/// \param Ranges The underlined ranges for this code snippet.
/// \param Hints The FixIt hints active for this diagnostic.
void TextDiagnostic::emitSnippetAndCaret(
SourceLocation Loc, DiagnosticsEngine::Level Level,
SmallVectorImpl<CharSourceRange>& Ranges,
ArrayRef<FixItHint> Hints,
const SourceManager &SM) {
assert(!Loc.isInvalid() && "must have a valid source location here");
assert(Loc.isFileID() && "must have a file location here");
// If caret diagnostics are enabled and we have location, we want to
// emit the caret. However, we only do this if the location moved
// from the last diagnostic, if the last diagnostic was a note that
// was part of a different warning or error diagnostic, or if the
// diagnostic has ranges. We don't want to emit the same caret
// multiple times if one loc has multiple diagnostics.
if (!DiagOpts->ShowCarets)
return;
if (Loc == LastLoc && Ranges.empty() && Hints.empty() &&
(LastLevel != DiagnosticsEngine::Note || Level == LastLevel))
return;
// Decompose the location into a FID/Offset pair.
std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
FileID FID = LocInfo.first;
unsigned FileOffset = LocInfo.second;
// Get information about the buffer it points into.
bool Invalid = false;
const char *BufStart = SM.getBufferData(FID, &Invalid).data();
if (Invalid)
return;
unsigned LineNo = SM.getLineNumber(FID, FileOffset);
unsigned ColNo = SM.getColumnNumber(FID, FileOffset);
// Rewind from the current position to the start of the line.
const char *TokPtr = BufStart+FileOffset;
const char *LineStart = TokPtr-ColNo+1; // Column # is 1-based.
// Compute the line end. Scan forward from the error position to the end of
// the line.
const char *LineEnd = TokPtr;
while (*LineEnd != '\n' && *LineEnd != '\r' && *LineEnd != '\0')
++LineEnd;
// Copy the line of code into an std::string for ease of manipulation.
std::string SourceLine(LineStart, LineEnd);
// Create a line for the caret that is filled with spaces that is the same
// length as the line of source code.
std::string CaretLine(LineEnd-LineStart, ' ');
const SourceColumnMap sourceColMap(SourceLine, DiagOpts->TabStop);
// Highlight all of the characters covered by Ranges with ~ characters.
for (SmallVectorImpl<CharSourceRange>::iterator I = Ranges.begin(),
E = Ranges.end();
I != E; ++I)
highlightRange(*I, LineNo, FID, sourceColMap, CaretLine, SM, LangOpts);
// Next, insert the caret itself.
ColNo = sourceColMap.byteToContainingColumn(ColNo-1);
if (CaretLine.size()<ColNo+1)
CaretLine.resize(ColNo+1, ' ');
CaretLine[ColNo] = '^';
std::string FixItInsertionLine = buildFixItInsertionLine(LineNo,
sourceColMap,
Hints, SM,
DiagOpts.getPtr());
// If the source line is too long for our terminal, select only the
// "interesting" source region within that line.
unsigned Columns = DiagOpts->MessageLength;
if (Columns)
selectInterestingSourceRegion(SourceLine, CaretLine, FixItInsertionLine,
Columns, sourceColMap);
// If we are in -fdiagnostics-print-source-range-info mode, we are trying
// to produce easily machine parsable output. Add a space before the
// source line and the caret to make it trivial to tell the main diagnostic
// line from what the user is intended to see.
if (DiagOpts->ShowSourceRanges) {
SourceLine = ' ' + SourceLine;
CaretLine = ' ' + CaretLine;
}
// Finally, remove any blank spaces from the end of CaretLine.
while (CaretLine[CaretLine.size()-1] == ' ')
CaretLine.erase(CaretLine.end()-1);
// Emit what we have computed.
emitSnippet(SourceLine);
//.........这里部分代码省略.........
示例7: EmitCaretDiagnostic
void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc,
SourceRange *Ranges,
unsigned NumRanges,
SourceManager &SM,
const CodeModificationHint *Hints,
unsigned NumHints,
unsigned Columns) {
assert(LangOpts && "Unexpected diagnostic outside source file processing");
assert(!Loc.isInvalid() && "must have a valid source location here");
// If this is a macro ID, first emit information about where this was
// instantiated (recursively) then emit information about where the token was
// spelled from.
if (!Loc.isFileID()) {
SourceLocation OneLevelUp = SM.getImmediateInstantiationRange(Loc).first;
// FIXME: Map ranges?
EmitCaretDiagnostic(OneLevelUp, Ranges, NumRanges, SM, 0, 0, Columns);
// Map the location.
Loc = SM.getImmediateSpellingLoc(Loc);
// Map the ranges.
for (unsigned i = 0; i != NumRanges; ++i) {
SourceLocation S = Ranges[i].getBegin(), E = Ranges[i].getEnd();
if (S.isMacroID()) S = SM.getImmediateSpellingLoc(S);
if (E.isMacroID()) E = SM.getImmediateSpellingLoc(E);
Ranges[i] = SourceRange(S, E);
}
// Get the pretty name, according to #line directives etc.
PresumedLoc PLoc = SM.getPresumedLoc(Loc);
// If this diagnostic is not in the main file, print out the "included from"
// lines.
if (LastWarningLoc != PLoc.getIncludeLoc()) {
LastWarningLoc = PLoc.getIncludeLoc();
PrintIncludeStack(LastWarningLoc, SM);
}
if (DiagOpts->ShowLocation) {
// Emit the file/line/column that this expansion came from.
OS << PLoc.getFilename() << ':' << PLoc.getLine() << ':';
if (DiagOpts->ShowColumn)
OS << PLoc.getColumn() << ':';
OS << ' ';
}
OS << "note: instantiated from:\n";
EmitCaretDiagnostic(Loc, Ranges, NumRanges, SM, Hints, NumHints, Columns);
return;
}
// Decompose the location into a FID/Offset pair.
std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
FileID FID = LocInfo.first;
unsigned FileOffset = LocInfo.second;
// Get information about the buffer it points into.
std::pair<const char*, const char*> BufferInfo = SM.getBufferData(FID);
const char *BufStart = BufferInfo.first;
unsigned ColNo = SM.getColumnNumber(FID, FileOffset);
unsigned CaretEndColNo
= ColNo + Lexer::MeasureTokenLength(Loc, SM, *LangOpts);
// Rewind from the current position to the start of the line.
const char *TokPtr = BufStart+FileOffset;
const char *LineStart = TokPtr-ColNo+1; // Column # is 1-based.
// Compute the line end. Scan forward from the error position to the end of
// the line.
const char *LineEnd = TokPtr;
while (*LineEnd != '\n' && *LineEnd != '\r' && *LineEnd != '\0')
++LineEnd;
// FIXME: This shouldn't be necessary, but the CaretEndColNo can extend past
// the source line length as currently being computed. See
// test/Misc/message-length.c.
CaretEndColNo = std::min(CaretEndColNo, unsigned(LineEnd - LineStart));
// Copy the line of code into an std::string for ease of manipulation.
std::string SourceLine(LineStart, LineEnd);
// Create a line for the caret that is filled with spaces that is the same
// length as the line of source code.
std::string CaretLine(LineEnd-LineStart, ' ');
// Highlight all of the characters covered by Ranges with ~ characters.
if (NumRanges) {
unsigned LineNo = SM.getLineNumber(FID, FileOffset);
for (unsigned i = 0, e = NumRanges; i != e; ++i)
HighlightRange(Ranges[i], SM, LineNo, FID, CaretLine, SourceLine);
}
// Next, insert the caret itself.
if (ColNo-1 < CaretLine.size())
CaretLine[ColNo-1] = '^';
else
//.........这里部分代码省略.........
示例8: EmitCaretDiagnostic
void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc,
SourceRange *Ranges,
unsigned NumRanges,
SourceManager &SM,
const CodeModificationHint *Hints,
unsigned NumHints,
unsigned Columns) {
assert(!Loc.isInvalid() && "must have a valid source location here");
// If this is a macro ID, first emit information about where this was
// instantiated (recursively) then emit information about where. the token was
// spelled from.
if (!Loc.isFileID()) {
SourceLocation OneLevelUp = SM.getImmediateInstantiationRange(Loc).first;
// FIXME: Map ranges?
EmitCaretDiagnostic(OneLevelUp, Ranges, NumRanges, SM, 0, 0, Columns);
Loc = SM.getImmediateSpellingLoc(Loc);
// Map the ranges.
for (unsigned i = 0; i != NumRanges; ++i) {
SourceLocation S = Ranges[i].getBegin(), E = Ranges[i].getEnd();
if (S.isMacroID()) S = SM.getImmediateSpellingLoc(S);
if (E.isMacroID()) E = SM.getImmediateSpellingLoc(E);
Ranges[i] = SourceRange(S, E);
}
if (ShowLocation) {
std::pair<FileID, unsigned> IInfo = SM.getDecomposedInstantiationLoc(Loc);
// Emit the file/line/column that this expansion came from.
OS << SM.getBuffer(IInfo.first)->getBufferIdentifier() << ':'
<< SM.getLineNumber(IInfo.first, IInfo.second) << ':';
if (ShowColumn)
OS << SM.getColumnNumber(IInfo.first, IInfo.second) << ':';
OS << ' ';
}
OS << "note: instantiated from:\n";
EmitCaretDiagnostic(Loc, Ranges, NumRanges, SM, Hints, NumHints, Columns);
return;
}
// Decompose the location into a FID/Offset pair.
std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
FileID FID = LocInfo.first;
unsigned FileOffset = LocInfo.second;
// Get information about the buffer it points into.
std::pair<const char*, const char*> BufferInfo = SM.getBufferData(FID);
const char *BufStart = BufferInfo.first;
unsigned ColNo = SM.getColumnNumber(FID, FileOffset);
unsigned CaretEndColNo
= ColNo + Lexer::MeasureTokenLength(Loc, SM, *LangOpts);
// Rewind from the current position to the start of the line.
const char *TokPtr = BufStart+FileOffset;
const char *LineStart = TokPtr-ColNo+1; // Column # is 1-based.
// Compute the line end. Scan forward from the error position to the end of
// the line.
const char *LineEnd = TokPtr;
while (*LineEnd != '\n' && *LineEnd != '\r' && *LineEnd != '\0')
++LineEnd;
// Copy the line of code into an std::string for ease of manipulation.
std::string SourceLine(LineStart, LineEnd);
// Create a line for the caret that is filled with spaces that is the same
// length as the line of source code.
std::string CaretLine(LineEnd-LineStart, ' ');
// Highlight all of the characters covered by Ranges with ~ characters.
if (NumRanges) {
unsigned LineNo = SM.getLineNumber(FID, FileOffset);
for (unsigned i = 0, e = NumRanges; i != e; ++i)
HighlightRange(Ranges[i], SM, LineNo, FID, CaretLine, SourceLine);
}
// Next, insert the caret itself.
if (ColNo-1 < CaretLine.size())
CaretLine[ColNo-1] = '^';
else
CaretLine.push_back('^');
// Scan the source line, looking for tabs. If we find any, manually expand
// them to 8 characters and update the CaretLine to match.
for (unsigned i = 0; i != SourceLine.size(); ++i) {
if (SourceLine[i] != '\t') continue;
// Replace this tab with at least one space.
SourceLine[i] = ' ';
// Compute the number of spaces we need to insert.
unsigned NumSpaces = ((i+8)&~7) - (i+1);
assert(NumSpaces < 8 && "Invalid computation of space amt");
//.........这里部分代码省略.........
示例9: emitMacroExpansionsAndCarets
/// \brief Recursively emit notes for each macro expansion and caret
/// diagnostics where appropriate.
///
/// Walks up the macro expansion stack printing expansion notes, the code
/// snippet, caret, underlines and FixItHint display as appropriate at each
/// level.
///
/// \param Loc The location for this caret.
/// \param Level The diagnostic level currently being emitted.
/// \param Ranges The underlined ranges for this code snippet.
/// \param Hints The FixIt hints active for this diagnostic.
/// \param MacroSkipEnd The depth to stop skipping macro expansions.
/// \param OnMacroInst The current depth of the macro expansion stack.
void TextDiagnostic::emitMacroExpansionsAndCarets(
SourceLocation Loc,
DiagnosticsEngine::Level Level,
SmallVectorImpl<CharSourceRange>& Ranges,
ArrayRef<FixItHint> Hints,
unsigned &MacroDepth,
unsigned OnMacroInst) {
assert(!Loc.isInvalid() && "must have a valid source location here");
// If this is a file source location, directly emit the source snippet and
// caret line. Also record the macro depth reached.
if (Loc.isFileID()) {
assert(MacroDepth == 0 && "We shouldn't hit a leaf node twice!");
MacroDepth = OnMacroInst;
emitSnippetAndCaret(Loc, Level, Ranges, Hints);
return;
}
// Otherwise recurse through each macro expansion layer.
// When processing macros, skip over the expansions leading up to
// a macro argument, and trace the argument's expansion stack instead.
Loc = skipToMacroArgExpansion(SM, Loc);
SourceLocation OneLevelUp = getImmediateMacroCallerLoc(SM, Loc);
// FIXME: Map ranges?
emitMacroExpansionsAndCarets(OneLevelUp, Level, Ranges, Hints, MacroDepth,
OnMacroInst + 1);
// Save the original location so we can find the spelling of the macro call.
SourceLocation MacroLoc = Loc;
// Map the location.
Loc = getImmediateMacroCalleeLoc(SM, Loc);
unsigned MacroSkipStart = 0, MacroSkipEnd = 0;
if (MacroDepth > DiagOpts.MacroBacktraceLimit) {
MacroSkipStart = DiagOpts.MacroBacktraceLimit / 2 +
DiagOpts.MacroBacktraceLimit % 2;
MacroSkipEnd = MacroDepth - DiagOpts.MacroBacktraceLimit / 2;
}
// Whether to suppress printing this macro expansion.
bool Suppressed = (OnMacroInst >= MacroSkipStart &&
OnMacroInst < MacroSkipEnd);
// Map the ranges.
for (SmallVectorImpl<CharSourceRange>::iterator I = Ranges.begin(),
E = Ranges.end();
I != E; ++I) {
SourceLocation Start = I->getBegin(), End = I->getEnd();
if (Start.isMacroID())
I->setBegin(getImmediateMacroCalleeLoc(SM, Start));
if (End.isMacroID())
I->setEnd(getImmediateMacroCalleeLoc(SM, End));
}
if (Suppressed) {
// Tell the user that we've skipped contexts.
if (OnMacroInst == MacroSkipStart) {
// FIXME: Emit this as a real note diagnostic.
// FIXME: Format an actual diagnostic rather than a hard coded string.
OS << "note: (skipping " << (MacroSkipEnd - MacroSkipStart)
<< " expansions in backtrace; use -fmacro-backtrace-limit=0 to see "
"all)\n";
}
return;
}
llvm::SmallString<100> MessageStorage;
llvm::raw_svector_ostream Message(MessageStorage);
Message << "expanded from macro '"
<< getImmediateMacroName(MacroLoc, SM, LangOpts) << "'";
emitDiagnostic(SM.getSpellingLoc(Loc), DiagnosticsEngine::Note,
Message.str(),
Ranges, ArrayRef<FixItHint>());
}
示例10: HandlePathDiagnostic
void PathDiagnosticConsumer::HandlePathDiagnostic(
std::unique_ptr<PathDiagnostic> D) {
if (!D || D->path.empty())
return;
// We need to flatten the locations (convert Stmt* to locations) because
// the referenced statements may be freed by the time the diagnostics
// are emitted.
D->flattenLocations();
// If the PathDiagnosticConsumer does not support diagnostics that
// cross file boundaries, prune out such diagnostics now.
if (!supportsCrossFileDiagnostics()) {
// Verify that the entire path is from the same FileID.
FileID FID;
const SourceManager &SMgr = D->path.front()->getLocation().getManager();
SmallVector<const PathPieces *, 5> WorkList;
WorkList.push_back(&D->path);
SmallString<128> buf;
llvm::raw_svector_ostream warning(buf);
warning << "warning: Path diagnostic report is not generated. Current "
<< "output format does not support diagnostics that cross file "
<< "boundaries. Refer to --analyzer-output for valid output "
<< "formats\n";
while (!WorkList.empty()) {
const PathPieces &path = *WorkList.pop_back_val();
for (const auto &I : path) {
const PathDiagnosticPiece *piece = I.get();
FullSourceLoc L = piece->getLocation().asLocation().getExpansionLoc();
if (FID.isInvalid()) {
FID = SMgr.getFileID(L);
} else if (SMgr.getFileID(L) != FID) {
llvm::errs() << warning.str();
return;
}
// Check the source ranges.
ArrayRef<SourceRange> Ranges = piece->getRanges();
for (const auto &I : Ranges) {
SourceLocation L = SMgr.getExpansionLoc(I.getBegin());
if (!L.isFileID() || SMgr.getFileID(L) != FID) {
llvm::errs() << warning.str();
return;
}
L = SMgr.getExpansionLoc(I.getEnd());
if (!L.isFileID() || SMgr.getFileID(L) != FID) {
llvm::errs() << warning.str();
return;
}
}
if (const auto *call = dyn_cast<PathDiagnosticCallPiece>(piece))
WorkList.push_back(&call->path);
else if (const auto *macro = dyn_cast<PathDiagnosticMacroPiece>(piece))
WorkList.push_back(¯o->subPieces);
}
}
if (FID.isInvalid())
return; // FIXME: Emit a warning?
}
// Profile the node to see if we already have something matching it
llvm::FoldingSetNodeID profile;
D->Profile(profile);
void *InsertPos = nullptr;
if (PathDiagnostic *orig = Diags.FindNodeOrInsertPos(profile, InsertPos)) {
// Keep the PathDiagnostic with the shorter path.
// Note, the enclosing routine is called in deterministic order, so the
// results will be consistent between runs (no reason to break ties if the
// size is the same).
const unsigned orig_size = orig->full_size();
const unsigned new_size = D->full_size();
if (orig_size <= new_size)
return;
assert(orig != D.get());
Diags.RemoveNode(orig);
delete orig;
}
Diags.InsertNode(D.release());
}
示例11: PasteTokens
/// PasteTokens - Tok is the LHS of a ## operator, and CurToken is the ##
/// operator. Read the ## and RHS, and paste the LHS/RHS together. If there
/// are more ## after it, chomp them iteratively. Return the result as Tok.
/// If this returns true, the caller should immediately return the token.
bool TokenLexer::PasteTokens(Token &Tok) {
SmallString<128> Buffer;
const char *ResultTokStrPtr = 0;
SourceLocation StartLoc = Tok.getLocation();
SourceLocation PasteOpLoc;
do {
// Consume the ## operator.
PasteOpLoc = Tokens[CurToken].getLocation();
++CurToken;
assert(!isAtEnd() && "No token on the RHS of a paste operator!");
// Get the RHS token.
const Token &RHS = Tokens[CurToken];
// Allocate space for the result token. This is guaranteed to be enough for
// the two tokens.
Buffer.resize(Tok.getLength() + RHS.getLength());
// Get the spelling of the LHS token in Buffer.
const char *BufPtr = &Buffer[0];
bool Invalid = false;
unsigned LHSLen = PP.getSpelling(Tok, BufPtr, &Invalid);
if (BufPtr != &Buffer[0]) // Really, we want the chars in Buffer!
memcpy(&Buffer[0], BufPtr, LHSLen);
if (Invalid)
return true;
BufPtr = &Buffer[LHSLen];
unsigned RHSLen = PP.getSpelling(RHS, BufPtr, &Invalid);
if (Invalid)
return true;
if (BufPtr != &Buffer[LHSLen]) // Really, we want the chars in Buffer!
memcpy(&Buffer[LHSLen], BufPtr, RHSLen);
// Trim excess space.
Buffer.resize(LHSLen+RHSLen);
// Plop the pasted result (including the trailing newline and null) into a
// scratch buffer where we can lex it.
Token ResultTokTmp;
ResultTokTmp.startToken();
// Claim that the tmp token is a string_literal so that we can get the
// character pointer back from CreateString in getLiteralData().
ResultTokTmp.setKind(tok::string_literal);
PP.CreateString(&Buffer[0], Buffer.size(), ResultTokTmp);
SourceLocation ResultTokLoc = ResultTokTmp.getLocation();
ResultTokStrPtr = ResultTokTmp.getLiteralData();
// Lex the resultant pasted token into Result.
Token Result;
if (Tok.isAnyIdentifier() && RHS.isAnyIdentifier()) {
// Common paste case: identifier+identifier = identifier. Avoid creating
// a lexer and other overhead.
PP.IncrementPasteCounter(true);
Result.startToken();
Result.setKind(tok::raw_identifier);
Result.setRawIdentifierData(ResultTokStrPtr);
Result.setLocation(ResultTokLoc);
Result.setLength(LHSLen+RHSLen);
} else {
PP.IncrementPasteCounter(false);
assert(ResultTokLoc.isFileID() &&
"Should be a raw location into scratch buffer");
SourceManager &SourceMgr = PP.getSourceManager();
FileID LocFileID = SourceMgr.getFileID(ResultTokLoc);
bool Invalid = false;
const char *ScratchBufStart
= SourceMgr.getBufferData(LocFileID, &Invalid).data();
if (Invalid)
return false;
// Make a lexer to lex this string from. Lex just this one token.
// Make a lexer object so that we lex and expand the paste result.
Lexer TL(SourceMgr.getLocForStartOfFile(LocFileID),
PP.getLangOpts(), ScratchBufStart,
ResultTokStrPtr, ResultTokStrPtr+LHSLen+RHSLen);
// Lex a token in raw mode. This way it won't look up identifiers
// automatically, lexing off the end will return an eof token, and
// warnings are disabled. This returns true if the result token is the
// entire buffer.
bool isInvalid = !TL.LexFromRawLexer(Result);
// If we got an EOF token, we didn't form even ONE token. For example, we
// did "/ ## /" to get "//".
isInvalid |= Result.is(tok::eof);
// If pasting the two tokens didn't form a full new token, this is an
// error. This occurs with "x ## +" and other stuff. Return with Tok
// unmodified and with RHS as the next token to lex.
if (isInvalid) {
// Test for the Microsoft extension of /##/ turning into // here on the
//.........这里部分代码省略.........
示例12: HandlePathDiagnostic
void PathDiagnosticConsumer::HandlePathDiagnostic(PathDiagnostic *D) {
llvm::OwningPtr<PathDiagnostic> OwningD(D);
if (!D || D->path.empty())
return;
// We need to flatten the locations (convert Stmt* to locations) because
// the referenced statements may be freed by the time the diagnostics
// are emitted.
D->flattenLocations();
// If the PathDiagnosticConsumer does not support diagnostics that
// cross file boundaries, prune out such diagnostics now.
if (!supportsCrossFileDiagnostics()) {
// Verify that the entire path is from the same FileID.
FileID FID;
const SourceManager &SMgr = (*D->path.begin())->getLocation().getManager();
llvm::SmallVector<const PathPieces *, 5> WorkList;
WorkList.push_back(&D->path);
while (!WorkList.empty()) {
const PathPieces &path = *WorkList.back();
WorkList.pop_back();
for (PathPieces::const_iterator I = path.begin(), E = path.end();
I != E; ++I) {
const PathDiagnosticPiece *piece = I->getPtr();
FullSourceLoc L = piece->getLocation().asLocation().getExpansionLoc();
if (FID.isInvalid()) {
FID = SMgr.getFileID(L);
} else if (SMgr.getFileID(L) != FID)
return; // FIXME: Emit a warning?
// Check the source ranges.
ArrayRef<SourceRange> Ranges = piece->getRanges();
for (ArrayRef<SourceRange>::iterator I = Ranges.begin(),
E = Ranges.end(); I != E; ++I) {
SourceLocation L = SMgr.getExpansionLoc(I->getBegin());
if (!L.isFileID() || SMgr.getFileID(L) != FID)
return; // FIXME: Emit a warning?
L = SMgr.getExpansionLoc(I->getEnd());
if (!L.isFileID() || SMgr.getFileID(L) != FID)
return; // FIXME: Emit a warning?
}
if (const PathDiagnosticCallPiece *call =
dyn_cast<PathDiagnosticCallPiece>(piece)) {
WorkList.push_back(&call->path);
}
else if (const PathDiagnosticMacroPiece *macro =
dyn_cast<PathDiagnosticMacroPiece>(piece)) {
WorkList.push_back(¯o->subPieces);
}
}
}
if (FID.isInvalid())
return; // FIXME: Emit a warning?
}
// Profile the node to see if we already have something matching it
llvm::FoldingSetNodeID profile;
D->Profile(profile);
void *InsertPos = 0;
if (PathDiagnostic *orig = Diags.FindNodeOrInsertPos(profile, InsertPos)) {
// Keep the PathDiagnostic with the shorter path.
// Note, the enclosing routine is called in deterministic order, so the
// results will be consistent between runs (no reason to break ties if the
// size is the same).
const unsigned orig_size = orig->full_size();
const unsigned new_size = D->full_size();
if (orig_size <= new_size)
return;
assert(orig != D);
Diags.RemoveNode(orig);
delete orig;
}
Diags.InsertNode(OwningD.take());
}
示例13: isCodeCompletionFile
bool Preprocessor::isCodeCompletionFile(SourceLocation FileLoc) const {
return CodeCompletionFile && FileLoc.isFileID() &&
SourceMgr.getFileEntryForID(SourceMgr.getFileID(FileLoc))
== CodeCompletionFile;
}