24 #include "llvm/ADT/Statistic.h" 25 #include "llvm/ADT/SmallPtrSet.h" 26 #include "llvm/ADT/SmallVector.h" 27 #include "llvm/Support/Casting.h" 29 using namespace clang;
39 class PlistDiagnostics :
public PathDiagnosticConsumer {
40 const std::string OutputFile;
43 const bool SupportsCrossFileDiagnostics;
46 const std::string& prefix,
48 bool supportsMultipleFiles);
50 ~PlistDiagnostics()
override {}
52 void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
53 FilesMade *filesMade)
override;
55 StringRef
getName()
const override {
56 return "PlistDiagnostics";
59 PathGenerationScheme getGenerationScheme()
const override {
62 bool supportsLogicalOpControlFlow()
const override {
return true; }
63 bool supportsCrossFileDiagnostics()
const override {
64 return SupportsCrossFileDiagnostics;
81 : FM(FM), AnOpts(AnOpts), PP(PP) {
84 void ReportDiag(raw_ostream &o,
const PathDiagnosticPiece&
P) {
85 ReportPiece(o, P, 4, 0,
true);
97 void ReportMacroExpansions(raw_ostream &o,
unsigned indent);
100 void ReportPiece(raw_ostream &o,
const PathDiagnosticPiece &
P,
101 unsigned indent,
unsigned depth,
bool includeControlFlow,
102 bool isKeyEvent =
false) {
103 switch (P.getKind()) {
105 if (includeControlFlow)
106 ReportControlFlow(o, cast<PathDiagnosticControlFlowPiece>(P), indent);
109 ReportCall(o, cast<PathDiagnosticCallPiece>(P), indent,
113 ReportEvent(o, cast<PathDiagnosticEventPiece>(P), indent, depth,
117 ReportMacroSubPieces(o, cast<PathDiagnosticMacroPiece>(P), indent,
121 ReportNote(o, cast<PathDiagnosticNotePiece>(P), indent);
124 ReportPopUp(o, cast<PathDiagnosticPopUpPiece>(P), indent);
131 void EmitMessage(raw_ostream &o, StringRef Message,
unsigned indent);
133 void ReportControlFlow(raw_ostream &o,
134 const PathDiagnosticControlFlowPiece& P,
136 void ReportEvent(raw_ostream &o,
const PathDiagnosticEventPiece& P,
137 unsigned indent,
unsigned depth,
bool isKeyEvent =
false);
138 void ReportCall(raw_ostream &o,
const PathDiagnosticCallPiece &P,
139 unsigned indent,
unsigned depth);
140 void ReportMacroSubPieces(raw_ostream &o,
const PathDiagnosticMacroPiece& P,
141 unsigned indent,
unsigned depth);
142 void ReportNote(raw_ostream &o,
const PathDiagnosticNotePiece& P,
145 void ReportPopUp(raw_ostream &o,
const PathDiagnosticPopUpPiece &P,
153 struct ExpansionInfo {
154 std::string MacroName;
155 std::string Expansion;
156 ExpansionInfo(std::string N, std::string E)
157 : MacroName(
std::move(N)), Expansion(
std::move(E)) {}
165 const PathPieces &Path);
169 static void printCoverage(
const PathDiagnostic *D,
170 unsigned InputIndentLevel,
173 llvm::raw_fd_ostream &o);
182 void PlistPrinter::EmitRanges(raw_ostream &o,
189 Indent(o, indent) <<
"<key>ranges</key>\n";
190 Indent(o, indent) <<
"<array>\n";
196 for (
auto &R : Ranges)
201 Indent(o, indent) <<
"</array>\n";
204 void PlistPrinter::EmitMessage(raw_ostream &o, StringRef Message,
207 assert(!Message.empty());
208 Indent(o, indent) <<
"<key>extended_message</key>\n";
214 Indent(o, indent) <<
"<key>message</key>\n";
219 void PlistPrinter::ReportControlFlow(raw_ostream &o,
220 const PathDiagnosticControlFlowPiece& P,
226 Indent(o, indent) <<
"<dict>\n";
229 Indent(o, indent) <<
"<key>kind</key><string>control</string>\n";
232 Indent(o, indent) <<
"<key>edges</key>\n";
234 Indent(o, indent) <<
"<array>\n";
238 Indent(o, indent) <<
"<dict>\n";
244 Indent(o, indent) <<
"<key>start</key>\n";
250 Indent(o, indent) <<
"<key>end</key>\n";
256 Indent(o, indent) <<
"</dict>\n";
259 Indent(o, indent) <<
"</array>\n";
263 const auto &s = P.getString();
265 Indent(o, indent) <<
"<key>alternate</key>";
270 Indent(o, indent) <<
"</dict>\n";
273 void PlistPrinter::ReportEvent(raw_ostream &o,
const PathDiagnosticEventPiece& P,
274 unsigned indent,
unsigned depth,
279 Indent(o, indent) <<
"<dict>\n";
282 Indent(o, indent) <<
"<key>kind</key><string>event</string>\n";
285 Indent(o, indent) <<
"<key>key_event</key><true/>\n";
291 Indent(o, indent) <<
"<key>location</key>\n";
296 EmitRanges(o, Ranges, indent);
299 Indent(o, indent) <<
"<key>depth</key>";
303 EmitMessage(o, P.getString(), indent);
307 Indent(o, indent); o <<
"</dict>\n";
310 void PlistPrinter::ReportCall(raw_ostream &o,
const PathDiagnosticCallPiece &P,
314 if (
auto callEnter = P.getCallEnterEvent())
315 ReportPiece(o, *callEnter, indent, depth,
true,
316 P.isLastInMainSourceFile());
321 if (
auto callEnterWithinCaller = P.getCallEnterWithinCallerEvent())
322 ReportPiece(o, *callEnterWithinCaller, indent, depth,
325 for (PathPieces::const_iterator I = P.path.begin(), E = P.path.end();I!=E;++I)
326 ReportPiece(o, **I, indent, depth,
true);
330 if (
auto callExit = P.getCallExitEvent())
331 ReportPiece(o, *callExit, indent, depth,
true);
334 void PlistPrinter::ReportMacroSubPieces(raw_ostream &o,
335 const PathDiagnosticMacroPiece& P,
336 unsigned indent,
unsigned depth) {
337 MacroPieces.push_back(&P);
339 for (PathPieces::const_iterator I = P.subPieces.begin(),
340 E = P.subPieces.end();
342 ReportPiece(o, **I, indent, depth,
false);
346 void PlistPrinter::ReportMacroExpansions(raw_ostream &o,
unsigned indent) {
348 for (
const PathDiagnosticMacroPiece *P : MacroPieces) {
350 ExpansionInfo EI = getExpandedMacro(P->getLocation().asLocation(), PP);
352 Indent(o, indent) <<
"<dict>\n";
358 Indent(o, indent) <<
"<key>location</key>\n";
363 EmitRanges(o, Ranges, indent);
366 Indent(o, indent) <<
"<key>name</key>";
370 Indent(o, indent) <<
"<key>expansion</key>";
380 void PlistPrinter::ReportNote(raw_ostream &o,
const PathDiagnosticNotePiece& P,
385 Indent(o, indent) <<
"<dict>\n";
391 Indent(o, indent) <<
"<key>location</key>\n";
396 EmitRanges(o, Ranges, indent);
399 EmitMessage(o, P.getString(), indent);
403 Indent(o, indent); o <<
"</dict>\n";
406 void PlistPrinter::ReportPopUp(raw_ostream &o,
407 const PathDiagnosticPopUpPiece &P,
411 Indent(o, indent) <<
"<dict>\n";
414 Indent(o, indent) <<
"<key>kind</key><string>pop-up</string>\n";
419 Indent(o, indent) <<
"<key>location</key>\n";
424 EmitRanges(o, Ranges, indent);
427 EmitMessage(o, P.getString(), indent);
431 Indent(o, indent) <<
"</dict>\n";
440 static void printCoverage(
const PathDiagnostic *D,
441 unsigned InputIndentLevel,
444 llvm::raw_fd_ostream &o) {
445 unsigned IndentLevel = InputIndentLevel;
447 Indent(o, IndentLevel) <<
"<key>ExecutedLines</key>\n";
448 Indent(o, IndentLevel) <<
"<dict>\n";
453 for (
auto I = ExecutedLines.begin(), E = ExecutedLines.end(); I != E; ++I) {
454 unsigned FileKey =
AddFID(FM, Fids, I->first);
455 Indent(o, IndentLevel) <<
"<key>" << FileKey <<
"</key>\n";
456 Indent(o, IndentLevel) <<
"<array>\n";
458 for (
unsigned LineNo : I->second) {
463 Indent(o, IndentLevel) <<
"</array>\n";
466 Indent(o, IndentLevel) <<
"</dict>\n";
468 assert(IndentLevel == InputIndentLevel);
474 const PathPieces &Path) {
475 PlistPrinter Printer(FM, AnOpts, PP);
476 assert(std::is_partitioned(
477 Path.begin(), Path.end(),
478 [](
const std::shared_ptr<PathDiagnosticPiece> &E)
480 "PathDiagnostic is not partitioned so that notes precede the rest");
482 PathPieces::const_iterator FirstNonNote = std::partition_point(
483 Path.begin(), Path.end(),
484 [](
const std::shared_ptr<PathDiagnosticPiece> &E)
487 PathPieces::const_iterator I = Path.begin();
489 if (FirstNonNote != Path.begin()) {
490 o <<
" <key>notes</key>\n" 493 for (; I != FirstNonNote; ++I)
494 Printer.ReportDiag(o, **I);
499 o <<
" <key>path</key>\n";
503 for (PathPieces::const_iterator E = Path.end(); I != E; ++I)
504 Printer.ReportDiag(o, **I);
508 if (!AnOpts.ShouldDisplayMacroExpansions)
511 o <<
" <key>macro_expansions</key>\n" 513 Printer.ReportMacroExpansions(o, 4);
522 const std::string& output,
524 bool supportsMultipleFiles)
525 : OutputFile(output), PP(PP), AnOpts(AnalyzerOpts),
526 SupportsCrossFileDiagnostics(supportsMultipleFiles) {}
528 void ento::createPlistDiagnosticConsumer(
AnalyzerOptions &AnalyzerOpts,
530 const std::string& s,
532 C.push_back(
new PlistDiagnostics(AnalyzerOpts, s, PP,
536 void ento::createPlistMultiFileDiagnosticConsumer(
AnalyzerOptions &AnalyzerOpts,
538 const std::string &s,
540 C.push_back(
new PlistDiagnostics(AnalyzerOpts, s, PP,
543 void PlistDiagnostics::FlushDiagnosticsImpl(
544 std::vector<const PathDiagnostic *> &Diags,
545 FilesMade *filesMade) {
553 auto AddPieceFID = [&FM, &Fids, &SM](
const PathDiagnosticPiece &Piece) {
554 AddFID(FM, Fids, SM, Piece.getLocation().asLocation());
562 for (
const PathDiagnostic *D : Diags) {
565 WorkList.push_back(&D->path);
567 while (!WorkList.empty()) {
568 const PathPieces &Path = *WorkList.pop_back_val();
570 for (
const auto &Iter : Path) {
571 const PathDiagnosticPiece &Piece = *Iter;
574 if (
const PathDiagnosticCallPiece *Call =
575 dyn_cast<PathDiagnosticCallPiece>(&Piece)) {
576 if (
auto CallEnterWithin =
Call->getCallEnterWithinCallerEvent())
577 AddPieceFID(*CallEnterWithin);
579 if (
auto CallEnterEvent =
Call->getCallEnterEvent())
580 AddPieceFID(*CallEnterEvent);
582 WorkList.push_back(&
Call->path);
583 }
else if (
const PathDiagnosticMacroPiece *Macro =
584 dyn_cast<PathDiagnosticMacroPiece>(&Piece)) {
585 WorkList.push_back(&
Macro->subPieces);
593 llvm::raw_fd_ostream o(OutputFile, EC, llvm::sys::fs::F_Text);
595 llvm::errs() <<
"warning: could not create file: " << EC.message() <<
'\n';
606 " <key>clang_version</key>\n";
608 o <<
" <key>diagnostics</key>\n" 611 for (std::vector<const PathDiagnostic*>::iterator DI=Diags.begin(),
612 DE = Diags.end(); DI!=DE; ++DI) {
616 const PathDiagnostic *D = *DI;
620 o <<
" <key>description</key>";
621 EmitString(o, D->getShortDescription()) <<
'\n';
622 o <<
" <key>category</key>";
624 o <<
" <key>type</key>";
626 o <<
" <key>check_name</key>";
629 o <<
" <!-- This hash is experimental and going to change! -->\n";
630 o <<
" <key>issue_hash_content_of_line_in_context</key>";
633 ? UPDLoc.asLocation()
634 : D->getLocation().asLocation()),
636 const Decl *DeclWithIssue = D->getDeclWithIssue();
638 DeclWithIssue, LangOpts))
643 if (
const Decl *DeclWithIssue = D->getDeclWithIssue()) {
645 if (
const NamedDecl *ND = dyn_cast<NamedDecl>(DeclWithIssue)) {
647 switch (ND->getKind()) {
648 case Decl::CXXRecord:
649 declKind =
"C++ class";
651 case Decl::CXXMethod:
652 declKind =
"C++ method";
654 case Decl::ObjCMethod:
655 declKind =
"Objective-C method";
658 declKind =
"function";
663 if (!declKind.empty()) {
664 const std::string &declName = ND->getDeclName().getAsString();
665 o <<
" <key>issue_context_kind</key>";
667 o <<
" <key>issue_context</key>";
680 if (UPDLoc.isValid()) {
683 D->getUniqueingDecl()->getBody()->getBeginLoc()),
685 o <<
" <key>issue_hash_function_offset</key><string>" 692 o <<
" <key>issue_hash_function_offset</key><string>" 702 o <<
" <key>location</key>\n";
703 EmitLocation(o, SM, D->getLocation().asLocation(), FM, 2);
706 if (!filesMade->empty()) {
708 PDFileEntry::ConsumerFiles *files = filesMade->getFiles(*D);
710 for (PDFileEntry::ConsumerFiles::const_iterator CI = files->begin(),
711 CE = files->end(); CI != CE; ++CI) {
712 StringRef newName = CI->first;
713 if (newName != lastName) {
714 if (!lastName.empty()) {
718 o <<
" <key>" << lastName <<
"_files</key>\n";
721 o <<
" <string>" << CI->second <<
"</string>\n";
727 printCoverage(D, 2, Fids, FM, o);
735 o <<
" <key>files</key>\n" 741 if (llvm::AreStatisticsEnabled() && AnOpts.ShouldSerializeStats) {
742 o <<
" <key>statistics</key>\n";
744 llvm::raw_string_ostream os(stats);
745 llvm::PrintStatisticsJSON(os);
751 o <<
"</dict>\n</plist>\n";
764 class MacroArgMap :
public std::map<const IdentifierInfo *, ExpArgTokens> {
766 void expandFromPrevMacro(
const MacroArgMap &Super);
769 struct MacroNameAndArgs {
774 MacroNameAndArgs(std::string N,
const MacroInfo *MI, MacroArgMap M)
775 : Name(
std::move(N)), MI(MI), Args(
std::move(M)) {}
779 llvm::raw_ostream &
OS;
782 Token PrevTok, PrevPrevTok;
786 TokenPrinter(llvm::raw_ostream &OS,
const Preprocessor &PP)
787 : OS(OS), PP(PP), ConcatInfo(PP) {
789 PrevPrevTok.
setKind(tok::unknown);
822 static std::string getMacroNameAndPrintExpansion(
823 TokenPrinter &Printer,
826 const MacroArgMap &PrevArgs,
827 llvm::SmallPtrSet<IdentifierInfo *, 8> &AlreadyProcessedTokens);
851 static MacroNameAndArgs getMacroNameAndArgs(
SourceLocation ExpanLoc,
874 llvm::raw_svector_ostream
OS(ExpansionBuf);
875 TokenPrinter Printer(OS, PP);
876 llvm::SmallPtrSet<IdentifierInfo*, 8> AlreadyProcessedTokens;
878 std::string MacroName =
879 getMacroNameAndPrintExpansion(Printer, MacroLoc, PP, MacroArgMap{},
880 AlreadyProcessedTokens);
881 return { MacroName, OS.str() };
884 static std::string getMacroNameAndPrintExpansion(
885 TokenPrinter &Printer,
888 const MacroArgMap &PrevArgs,
889 llvm::SmallPtrSet<IdentifierInfo *, 8> &AlreadyProcessedTokens) {
893 MacroNameAndArgs Info = getMacroNameAndArgs(SM.
getExpansionLoc(MacroLoc), PP);
902 if (AlreadyProcessedTokens.find(IDInfo) != AlreadyProcessedTokens.end())
904 AlreadyProcessedTokens.insert(IDInfo);
910 Info.Args.expandFromPrevMacro(PrevArgs);
913 for (
auto It = Info.MI->tokens_begin(), E = Info.MI->tokens_end(); It != E;
918 if (T.
isNot(tok::identifier)) {
919 Printer.printToken(T);
925 "This token is an identifier but has no IdentifierInfo!");
929 if (getMacroInfoForLocation(PP, SM, II, T.
getLocation())) {
930 getMacroNameAndPrintExpansion(Printer, T.
getLocation(), PP, Info.Args,
931 AlreadyProcessedTokens);
936 auto N = std::next(It);
937 if (N != E && N->is(tok::l_paren))
938 It = getMatchingRParen(++It, E);
943 auto ArgMapIt = Info.Args.find(II);
944 if (ArgMapIt != Info.Args.end()) {
946 ArgEnd = ArgMapIt->second.end();
947 ArgIt != ArgEnd; ++ArgIt) {
951 const auto *ArgII = ArgIt->getIdentifierInfo();
953 Printer.printToken(*ArgIt);
959 Printer.printToken(*ArgIt);
963 getMacroNameAndPrintExpansion(Printer, ArgIt->getLocation(), PP,
964 Info.Args, AlreadyProcessedTokens);
973 auto N = std::next(ArgIt);
974 if (N != ArgEnd && N->is(tok::l_paren))
975 ArgIt = getMatchingRParen(++ArgIt, ArgEnd);
982 Printer.printToken(T);
985 AlreadyProcessedTokens.erase(IDInfo);
990 static MacroNameAndArgs getMacroNameAndArgs(
SourceLocation ExpanLoc,
999 const llvm::MemoryBuffer *MB = SM.
getBuffer(LocInfo.first);
1000 const char *MacroNameTokenPos = MB->getBufferStart() + LocInfo.second;
1003 MB->getBufferStart(), MacroNameTokenPos, MB->getBufferEnd());
1007 RawLexer.LexFromRawLexer(TheTok);
1012 assert(II &&
"Failed to acquire the IndetifierInfo for the macro!");
1014 const MacroInfo *MI = getMacroInfoForLocation(PP, SM, II, ExpanLoc);
1022 return { MacroName, MI, {} };
1032 if (MacroArgs.empty())
1033 return { MacroName, MI, {} };
1035 RawLexer.LexFromRawLexer(TheTok);
1044 if (TheTok.isNot(tok::l_paren))
1045 return { MacroName, MI, {} };
1058 int ParenthesesDepth = 1;
1065 MacroArgMap::mapped_type ExpandedArgTokens;
1076 if (ParenthesesDepth != 0) {
1079 RawLexer.LexFromRawLexer(TheTok);
1081 while (!(ParenthesesDepth == 1 &&
1082 (UnexpArgII == __VA_ARGS__II ?
false : TheTok.is(tok::comma)))) {
1084 "EOF encountered while looking for expanded macro args!");
1086 if (TheTok.is(tok::l_paren))
1089 if (TheTok.is(tok::r_paren))
1092 if (ParenthesesDepth == 0)
1095 if (TheTok.is(tok::raw_identifier))
1098 ExpandedArgTokens.push_back(TheTok);
1099 RawLexer.LexFromRawLexer(TheTok);
1102 assert(UnexpArgII == __VA_ARGS__II);
1105 Args.emplace(UnexpArgII, std::move(ExpandedArgTokens));
1108 assert(TheTok.is(tok::r_paren) &&
1109 "Expanded macro argument acquisition failed! After the end of the loop" 1110 " this token should be ')'!");
1112 return { MacroName, MI, Args };
1119 assert(It->is(tok::l_paren) &&
"This token should be '('!");
1122 int ParenthesesDepth = 1;
1123 while (ParenthesesDepth != 0) {
1127 "Encountered EOF while attempting to skip macro arguments!");
1129 "End of the macro definition reached before finding ')'!");
1131 if (It->is(tok::l_paren))
1134 if (It->is(tok::r_paren))
1152 void MacroArgMap::expandFromPrevMacro(
const MacroArgMap &Super) {
1154 for (value_type &Pair : *
this) {
1155 ExpArgTokens &CurrExpArgTokens = Pair.second;
1158 auto It = CurrExpArgTokens.begin();
1159 while (It != CurrExpArgTokens.end()) {
1160 if (It->isNot(tok::identifier)) {
1165 const auto *II = It->getIdentifierInfo();
1169 if (!Super.count(II)) {
1174 const ExpArgTokens &SuperExpArgTokens = Super.at(II);
1176 It = CurrExpArgTokens.insert(
1177 It, SuperExpArgTokens.begin(), SuperExpArgTokens.end());
1178 std::advance(It, SuperExpArgTokens.size());
1179 It = CurrExpArgTokens.erase(It);
1184 void TokenPrinter::printToken(
const Token &
Tok) {
1186 if (PrevTok.
isNot(tok::unknown)) {
1192 if (PrevTok.
isNot(tok::hashhash) && Tok.
isNot(tok::hashhash)) {
1198 if (!Tok.
isOneOf(tok::hash, tok::hashhash)) {
1199 if (PrevTok.
is(tok::hash))
1205 PrevPrevTok = PrevTok;
SourceLocation getLocForStartOfFile(FileID FID) const
Return the source location corresponding to the first byte of the specified file. ...
Lexer - This provides a simple interface that turns a text buffer into a stream of tokens...
void EmitLocation(raw_ostream &o, const SourceManager &SM, SourceLocation L, const FIDMap &FM, unsigned indent)
IdentifierInfo * getIdentifierInfo(StringRef Name) const
Return information about the specified preprocessor identifier token.
Defines the clang::FileManager interface and associated types.
std::string getClangFullVersion()
Retrieves a string representing the complete clang version, which includes the clang version number...
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
Stmt - This represents one statement.
bool is(tok::TokenKind K) const
is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {...
Defines the SourceManager interface.
TokenConcatenation class, which answers the question of "Is it safe to emit two tokens without a whit...
Decl - This represents one declaration (or definition), e.g.
llvm::SmallString< 32 > GetIssueHash(const SourceManager &SM, FullSourceLoc &IssueLoc, llvm::StringRef CheckerName, llvm::StringRef BugType, const Decl *D, const LangOptions &LangOpts)
Get an MD5 hash to help identify bugs.
constexpr XRayInstrMask Function
raw_ostream & EmitInteger(raw_ostream &o, int64_t value)
One of these records is kept for each identifier that is lexed.
unsigned AddFID(FIDMap &FIDs, SmallVectorImpl< FileID > &V, FileID FID)
Token - This structure provides full information about a lexed token.
void setKind(tok::TokenKind K)
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
const LangOptions & getLangOpts() const
StringRef getSpelling(SourceLocation loc, SmallVectorImpl< char > &buffer, bool *invalid=nullptr) const
Return the 'spelling' of the token at the given location; does not go up to the spelling location or ...
SourceLocation getExpansionLoc(SourceLocation Loc) const
Given a SourceLocation object Loc, return the expansion location referenced by the ID...
SmallVectorImpl< Token >::const_iterator tokens_iterator
std::vector< PathDiagnosticLocationPair >::const_iterator const_iterator
IdentifierInfo * LookUpIdentifierInfo(Token &Identifier) const
Given a tok::raw_identifier token, look up the identifier information for the token and install it in...
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
MacroArgs - An instance of this class captures information about the formal arguments specified to a ...
Defines version macros and version-related utility functions for Clang.
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file. ...
Defines the clang::Preprocessor interface.
const MacroInfo * getMacroInfo(const IdentifierInfo *II) const
SourceLocation getEnd() const
std::map< FileID, std::set< unsigned > > FilesToLineNumsMap
File IDs mapped to sets of line numbers.
static void printBugPath(llvm::raw_ostream &o, const FIDMap &FM, AnalyzerOptions &AnOpts, const Preprocessor &PP, const PathPieces &Path)
llvm::DenseMap< FileID, unsigned > FIDMap
SourceManager & getSourceManager() const
const DefInfo findDirectiveAtLoc(SourceLocation L, const SourceManager &SM) const
Find macro definition active in the specified source location.
Encapsulates changes to the "macros namespace" (the location where the macro name became active...
Encodes a location in the source.
StringRef getName() const
std::vector< PathDiagnosticConsumer * > PathDiagnosticConsumers
MacroDirective * getLocalMacroDirectiveHistory(const IdentifierInfo *II) const
Given an identifier, return the latest non-imported macro directive for that identifier.
void EscapeText(Rewriter &R, FileID FID, bool EscapeSpaces=false, bool ReplaceTabs=false)
EscapeText - HTMLize a specified file so that special characters are are translated so that they are ...
IdentifierInfo * getIdentifierInfo() const
raw_ostream & EmitPlistHeader(raw_ostream &o)
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
bool isNot(tok::TokenKind K) const
const llvm::MemoryBuffer * getBuffer(FileID FID, SourceLocation Loc, bool *Invalid=nullptr) const
Return the buffer for the specified FileID.
Dataflow Directional Tag Classes.
static std::string getName(const CallEvent &Call)
bool isOneOf(tok::TokenKind K1, tok::TokenKind K2) const
PathDiagnosticLocation()=default
Create an invalid location.
MacroInfo * getMacroInfo()
void EmitRange(raw_ostream &o, const SourceManager &SM, CharSourceRange R, const FIDMap &FM, unsigned indent)
unsigned getExpansionLineNumber(bool *Invalid=nullptr) const
Encapsulates the data about a macro definition (e.g.
static CharSourceRange getAsCharRange(SourceRange Range, const SourceManager &SM, const LangOptions &LangOpts)
Given a token range, produce a corresponding CharSourceRange that is not a token range.
Indicates that the tracking object is a descendant of a referenced-counted OSObject, used in the Darwin kernel.
bool AvoidConcat(const Token &PrevPrevTok, const Token &PrevTok, const Token &Tok) const
AvoidConcat - If printing PrevTok immediately followed by Tok would cause the two individual tokens t...
CharSourceRange getExpansionRange(SourceLocation Loc) const
Given a SourceLocation object, return the range of tokens covered by the expansion in the ultimate fi...
raw_ostream & EmitString(raw_ostream &o, StringRef s)
Stores options for the analyzer from the command line.
A SourceLocation and its associated SourceManager.
raw_ostream & Indent(raw_ostream &Out, const unsigned int Space, bool IsDot)
A trivial tuple used to represent a source range.
This represents a decl that may have a name.
SourceLocation getBegin() const
bool hasLeadingSpace() const
Return true if this token has whitespace before it.
This class handles loading and caching of source files into memory.
std::pair< FileID, unsigned > getDecomposedLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
ArrayRef< const IdentifierInfo * > params() const