///get the source code of stmt StringRef FindPatternVisitor::expr2str(Stmt *s){ if(!s) return ""; FullSourceLoc begin = CI->getASTContext().getFullLoc(s->getLocStart()); FullSourceLoc end = CI->getASTContext().getFullLoc(s->getLocEnd()); if(begin.isInvalid() || end.isInvalid()) return ""; SourceRange sr(begin.getExpansionLoc(), end.getExpansionLoc()); return Lexer::getSourceText(CharSourceRange::getTokenRange(sr), CI->getSourceManager(), LangOptions(), 0); }
bool FindPatternVisitor::VisitFunctionDecl (FunctionDecl* Declaration){ if(!Declaration) return true; if(!(Declaration->isThisDeclarationADefinition() && Declaration->hasBody())) return true; FullSourceLoc FullLocation = CI->getASTContext().getFullLoc(Declaration->getLocStart()); if(!FullLocation.isValid()) return true; ///the function is located in head file if(FullLocation.getExpansionLoc().getFileID() != CI->getSourceManager().getMainFileID()) return true; //llvm::errs()<<"Found function "<<Declaration->getQualifiedNameAsString() ; //llvm::errs()<<" @ " << FullLocation.printToString(FullLocation.getManager()) <<"\n"; hasRecorded.clear(); if(Stmt* function = Declaration->getBody()){ travelStmt(function, function); } return true; }
void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID, const PathDiagnosticPiece& P, unsigned num, unsigned max) { // For now, just draw a box above the line in question, and emit the // warning. FullSourceLoc Pos = P.getLocation().asLocation(); if (!Pos.isValid()) return; SourceManager &SM = R.getSourceMgr(); assert(&Pos.getManager() == &SM && "SourceManagers are different!"); std::pair<FileID, unsigned> LPosInfo = SM.getDecomposedExpansionLoc(Pos); if (LPosInfo.first != BugFileID) return; const llvm::MemoryBuffer *Buf = SM.getBuffer(LPosInfo.first); const char* FileStart = Buf->getBufferStart(); // Compute the column number. Rewind from the current position to the start // of the line. unsigned ColNo = SM.getColumnNumber(LPosInfo.first, LPosInfo.second); const char *TokInstantiationPtr =Pos.getExpansionLoc().getCharacterData(); const char *LineStart = TokInstantiationPtr-ColNo; // Compute LineEnd. const char *LineEnd = TokInstantiationPtr; const char* FileEnd = Buf->getBufferEnd(); while (*LineEnd != '\n' && LineEnd != FileEnd) ++LineEnd; // Compute the margin offset by counting tabs and non-tabs. unsigned PosNo = 0; for (const char* c = LineStart; c != TokInstantiationPtr; ++c) PosNo += *c == '\t' ? 8 : 1; // Create the html for the message. const char *Kind = 0; switch (P.getKind()) { case PathDiagnosticPiece::Call: llvm_unreachable("Calls should already be handled"); case PathDiagnosticPiece::Event: Kind = "Event"; break; case PathDiagnosticPiece::ControlFlow: Kind = "Control"; break; // Setting Kind to "Control" is intentional. case PathDiagnosticPiece::Macro: Kind = "Control"; break; } std::string sbuf; llvm::raw_string_ostream os(sbuf); os << "\n<tr><td class=\"num\"></td><td class=\"line\"><div id=\""; if (num == max) os << "EndPath"; else os << "Path" << num; os << "\" class=\"msg"; if (Kind) os << " msg" << Kind; os << "\" style=\"margin-left:" << PosNo << "ex"; // Output a maximum size. if (!isa<PathDiagnosticMacroPiece>(P)) { // Get the string and determining its maximum substring. const std::string& Msg = P.getString(); unsigned max_token = 0; unsigned cnt = 0; unsigned len = Msg.size(); for (std::string::const_iterator I=Msg.begin(), E=Msg.end(); I!=E; ++I) switch (*I) { default: ++cnt; continue; case ' ': case '\t': case '\n': if (cnt > max_token) max_token = cnt; cnt = 0; } if (cnt > max_token) max_token = cnt; // Determine the approximate size of the message bubble in em. unsigned em; const unsigned max_line = 120; if (max_token >= max_line) em = max_token / 2; else { unsigned characters = max_line; unsigned lines = len / max_line; if (lines > 0) { for (; characters > max_token; --characters) if (len / characters > lines) { ++characters; break; } } em = characters / 2; } if (em < max_line/2) os << "; max-width:" << em << "em"; } else os << "; max-width:100em"; os << "\">"; if (max > 1) { os << "<table class=\"msgT\"><tr><td valign=\"top\">"; os << "<div class=\"PathIndex"; if (Kind) os << " PathIndex" << Kind; os << "\">" << num << "</div>"; if (num > 1) { os << "</td><td><div class=\"PathNav\"><a href=\"#Path" << (num - 1) << "\" title=\"Previous event (" << (num - 1) << ")\">←</a></div></td>"; } os << "</td><td>"; } if (const PathDiagnosticMacroPiece *MP = dyn_cast<PathDiagnosticMacroPiece>(&P)) { os << "Within the expansion of the macro '"; // Get the name of the macro by relexing it. { FullSourceLoc L = MP->getLocation().asLocation().getExpansionLoc(); assert(L.isFileID()); StringRef BufferInfo = L.getBufferData(); std::pair<FileID, unsigned> LocInfo = L.getDecomposedLoc(); const char* MacroName = LocInfo.second + BufferInfo.data(); Lexer rawLexer(SM.getLocForStartOfFile(LocInfo.first), PP.getLangOpts(), BufferInfo.begin(), MacroName, BufferInfo.end()); Token TheTok; rawLexer.LexFromRawLexer(TheTok); for (unsigned i = 0, n = TheTok.getLength(); i < n; ++i) os << MacroName[i]; } os << "':\n"; if (max > 1) { os << "</td>"; if (num < max) { os << "<td><div class=\"PathNav\"><a href=\"#"; if (num == max - 1) os << "EndPath"; else os << "Path" << (num + 1); os << "\" title=\"Next event (" << (num + 1) << ")\">→</a></div></td>"; } os << "</tr></table>"; } // Within a macro piece. Write out each event. ProcessMacroPiece(os, *MP, 0); } else { os << html::EscapeText(P.getString()); if (max > 1) { os << "</td>"; if (num < max) { os << "<td><div class=\"PathNav\"><a href=\"#"; if (num == max - 1) os << "EndPath"; else os << "Path" << (num + 1); os << "\" title=\"Next event (" << (num + 1) << ")\">→</a></div></td>"; } os << "</tr></table>"; } } os << "</div></td></tr>"; // Insert the new html. unsigned DisplayPos = LineEnd - FileStart; SourceLocation Loc = SM.getLocForStartOfFile(LPosInfo.first).getLocWithOffset(DisplayPos); R.InsertTextBefore(Loc, os.str()); // Now highlight the ranges. ArrayRef<SourceRange> Ranges = P.getRanges(); for (ArrayRef<SourceRange>::iterator I = Ranges.begin(), E = Ranges.end(); I != E; ++I) { HighlightRange(R, LPosInfo.first, *I); } }
/// Print out the file/line/column information and include trace. /// /// This method handlen the emission of the diagnostic location information. /// This includes extracting as much location information as is present for /// the diagnostic and printing it, as well as any include stack or source /// ranges necessary. void TextDiagnostic::emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level, ArrayRef<CharSourceRange> Ranges) { if (PLoc.isInvalid()) { // At least print the file name if available: FileID FID = Loc.getFileID(); if (FID.isValid()) { const FileEntry *FE = Loc.getFileEntry(); if (FE && FE->isValid()) { emitFilename(FE->getName(), Loc.getManager()); if (FE->isInPCH()) OS << " (in PCH)"; OS << ": "; } } return; } unsigned LineNo = PLoc.getLine(); if (!DiagOpts->ShowLocation) return; if (DiagOpts->ShowColors) OS.changeColor(savedColor, true); emitFilename(PLoc.getFilename(), Loc.getManager()); switch (DiagOpts->getFormat()) { case DiagnosticOptions::Clang: OS << ':' << LineNo; break; case DiagnosticOptions::MSVC: OS << '(' << LineNo; break; case DiagnosticOptions::Vi: OS << " +" << LineNo; break; } if (DiagOpts->ShowColumn) // Compute the column number. if (unsigned ColNo = PLoc.getColumn()) { if (DiagOpts->getFormat() == DiagnosticOptions::MSVC) { OS << ','; // Visual Studio 2010 or earlier expects column number to be off by one if (LangOpts.MSCompatibilityVersion && !LangOpts.isCompatibleWithMSVC(LangOptions::MSVC2012)) ColNo--; } else OS << ':'; OS << ColNo; } switch (DiagOpts->getFormat()) { case DiagnosticOptions::Clang: case DiagnosticOptions::Vi: OS << ':'; break; case DiagnosticOptions::MSVC: // MSVC2013 and before print 'file(4) : error'. MSVC2015 gets rid of the // space and prints 'file(4): error'. OS << ')'; if (LangOpts.MSCompatibilityVersion && !LangOpts.isCompatibleWithMSVC(LangOptions::MSVC2015)) OS << ' '; OS << ": "; break; } if (DiagOpts->ShowSourceRanges && !Ranges.empty()) { FileID CaretFileID = Loc.getExpansionLoc().getFileID(); bool PrintedRange = false; for (ArrayRef<CharSourceRange>::const_iterator RI = Ranges.begin(), RE = Ranges.end(); RI != RE; ++RI) { // Ignore invalid ranges. if (!RI->isValid()) continue; auto &SM = Loc.getManager(); SourceLocation B = SM.getExpansionLoc(RI->getBegin()); CharSourceRange ERange = SM.getExpansionRange(RI->getEnd()); SourceLocation E = ERange.getEnd(); bool IsTokenRange = ERange.isTokenRange(); std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(B); std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(E); // If the start or end of the range is in another file, just discard // it. if (BInfo.first != CaretFileID || EInfo.first != CaretFileID) continue; // Add in the length of the token, so that we cover multi-char // tokens. unsigned TokSize = 0; if (IsTokenRange) TokSize = Lexer::MeasureTokenLength(E, SM, LangOpts); FullSourceLoc BF(B, SM), EF(E, SM); OS << '{' << BF.getLineNumber() << ':' << BF.getColumnNumber() << '-' << EF.getLineNumber() << ':' << (EF.getColumnNumber() + TokSize) << '}'; PrintedRange = true; } if (PrintedRange) OS << ':'; } OS << ' '; }