25 #include "llvm/ADT/Statistic.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);
128 void EmitMessage(raw_ostream &o, StringRef Message,
unsigned indent);
130 void ReportControlFlow(raw_ostream &o,
131 const PathDiagnosticControlFlowPiece& P,
133 void ReportEvent(raw_ostream &o,
const PathDiagnosticEventPiece& P,
134 unsigned indent,
unsigned depth,
bool isKeyEvent =
false);
135 void ReportCall(raw_ostream &o,
const PathDiagnosticCallPiece &P,
136 unsigned indent,
unsigned depth);
137 void ReportMacroSubPieces(raw_ostream &o,
const PathDiagnosticMacroPiece& P,
138 unsigned indent,
unsigned depth);
139 void ReportNote(raw_ostream &o,
const PathDiagnosticNotePiece& P,
147 struct ExpansionInfo {
148 std::string MacroName;
149 std::string Expansion;
150 ExpansionInfo(std::string N, std::string E)
151 : MacroName(
std::move(N)), Expansion(
std::move(E)) {}
159 const PathPieces &Path);
163 static void printCoverage(
const PathDiagnostic *D,
164 unsigned InputIndentLevel,
167 llvm::raw_fd_ostream &o);
176 void PlistPrinter::EmitRanges(raw_ostream &o,
183 Indent(o, indent) <<
"<key>ranges</key>\n";
184 Indent(o, indent) <<
"<array>\n";
190 for (
auto &R : Ranges)
195 Indent(o, indent) <<
"</array>\n";
198 void PlistPrinter::EmitMessage(raw_ostream &o, StringRef Message,
201 assert(!Message.empty());
202 Indent(o, indent) <<
"<key>extended_message</key>\n";
208 Indent(o, indent) <<
"<key>message</key>\n";
213 void PlistPrinter::ReportControlFlow(raw_ostream &o,
214 const PathDiagnosticControlFlowPiece& P,
220 Indent(o, indent) <<
"<dict>\n";
223 Indent(o, indent) <<
"<key>kind</key><string>control</string>\n";
226 Indent(o, indent) <<
"<key>edges</key>\n";
228 Indent(o, indent) <<
"<array>\n";
232 Indent(o, indent) <<
"<dict>\n";
238 Indent(o, indent) <<
"<key>start</key>\n";
244 Indent(o, indent) <<
"<key>end</key>\n";
250 Indent(o, indent) <<
"</dict>\n";
253 Indent(o, indent) <<
"</array>\n";
257 const auto &s = P.getString();
259 Indent(o, indent) <<
"<key>alternate</key>";
264 Indent(o, indent) <<
"</dict>\n";
267 void PlistPrinter::ReportEvent(raw_ostream &o,
const PathDiagnosticEventPiece& P,
268 unsigned indent,
unsigned depth,
273 Indent(o, indent) <<
"<dict>\n";
276 Indent(o, indent) <<
"<key>kind</key><string>event</string>\n";
279 Indent(o, indent) <<
"<key>key_event</key><true/>\n";
285 Indent(o, indent) <<
"<key>location</key>\n";
290 EmitRanges(o, Ranges, indent);
293 Indent(o, indent) <<
"<key>depth</key>";
297 EmitMessage(o, P.getString(), indent);
301 Indent(o, indent); o <<
"</dict>\n";
304 void PlistPrinter::ReportCall(raw_ostream &o,
const PathDiagnosticCallPiece &P,
308 if (
auto callEnter = P.getCallEnterEvent())
309 ReportPiece(o, *callEnter, indent, depth,
true,
310 P.isLastInMainSourceFile());
315 if (
auto callEnterWithinCaller = P.getCallEnterWithinCallerEvent())
316 ReportPiece(o, *callEnterWithinCaller, indent, depth,
319 for (PathPieces::const_iterator I = P.path.begin(), E = P.path.end();I!=E;++I)
320 ReportPiece(o, **I, indent, depth,
true);
324 if (
auto callExit = P.getCallExitEvent())
325 ReportPiece(o, *callExit, indent, depth,
true);
328 void PlistPrinter::ReportMacroSubPieces(raw_ostream &o,
329 const PathDiagnosticMacroPiece& P,
330 unsigned indent,
unsigned depth) {
331 MacroPieces.push_back(&P);
333 for (PathPieces::const_iterator I = P.subPieces.begin(),
334 E = P.subPieces.end();
336 ReportPiece(o, **I, indent, depth,
false);
340 void PlistPrinter::ReportMacroExpansions(raw_ostream &o,
unsigned indent) {
342 for (
const PathDiagnosticMacroPiece *P : MacroPieces) {
344 ExpansionInfo EI = getExpandedMacro(P->getLocation().asLocation(), PP);
346 Indent(o, indent) <<
"<dict>\n";
352 Indent(o, indent) <<
"<key>location</key>\n";
357 EmitRanges(o, Ranges, indent);
360 Indent(o, indent) <<
"<key>name</key>";
364 Indent(o, indent) <<
"<key>expansion</key>";
374 void PlistPrinter::ReportNote(raw_ostream &o,
const PathDiagnosticNotePiece& P,
379 Indent(o, indent) <<
"<dict>\n";
385 Indent(o, indent) <<
"<key>location</key>\n";
390 EmitRanges(o, Ranges, indent);
393 EmitMessage(o, P.getString(), indent);
397 Indent(o, indent); o <<
"</dict>\n";
406 static void printCoverage(
const PathDiagnostic *D,
407 unsigned InputIndentLevel,
410 llvm::raw_fd_ostream &o) {
411 unsigned IndentLevel = InputIndentLevel;
413 Indent(o, IndentLevel) <<
"<key>ExecutedLines</key>\n";
414 Indent(o, IndentLevel) <<
"<dict>\n";
419 for (
auto I = ExecutedLines.begin(), E = ExecutedLines.end(); I != E; ++I) {
420 unsigned FileKey =
AddFID(FM, Fids, I->first);
421 Indent(o, IndentLevel) <<
"<key>" << FileKey <<
"</key>\n";
422 Indent(o, IndentLevel) <<
"<array>\n";
424 for (
unsigned LineNo : I->second) {
425 Indent(o, IndentLevel);
429 Indent(o, IndentLevel) <<
"</array>\n";
432 Indent(o, IndentLevel) <<
"</dict>\n";
434 assert(IndentLevel == InputIndentLevel);
440 const PathPieces &Path) {
441 PlistPrinter Printer(FM, AnOpts, PP);
442 assert(std::is_partitioned(
443 Path.begin(), Path.end(),
444 [](
const std::shared_ptr<PathDiagnosticPiece> &E)
446 "PathDiagnostic is not partitioned so that notes precede the rest");
448 PathPieces::const_iterator FirstNonNote = std::partition_point(
449 Path.begin(), Path.end(),
450 [](
const std::shared_ptr<PathDiagnosticPiece> &E)
453 PathPieces::const_iterator I = Path.begin();
455 if (FirstNonNote != Path.begin()) {
456 o <<
" <key>notes</key>\n" 459 for (; I != FirstNonNote; ++I)
460 Printer.ReportDiag(o, **I);
465 o <<
" <key>path</key>\n";
469 for (PathPieces::const_iterator E = Path.end(); I != E; ++I)
470 Printer.ReportDiag(o, **I);
474 if (!AnOpts.ShouldDisplayMacroExpansions)
477 o <<
" <key>macro_expansions</key>\n" 479 Printer.ReportMacroExpansions(o, 4);
488 const std::string& output,
490 bool supportsMultipleFiles)
491 : OutputFile(output), PP(PP), AnOpts(AnalyzerOpts),
492 SupportsCrossFileDiagnostics(supportsMultipleFiles) {}
494 void ento::createPlistDiagnosticConsumer(
AnalyzerOptions &AnalyzerOpts,
496 const std::string& s,
498 C.push_back(
new PlistDiagnostics(AnalyzerOpts, s, PP,
502 void ento::createPlistMultiFileDiagnosticConsumer(
AnalyzerOptions &AnalyzerOpts,
504 const std::string &s,
506 C.push_back(
new PlistDiagnostics(AnalyzerOpts, s, PP,
509 void PlistDiagnostics::FlushDiagnosticsImpl(
510 std::vector<const PathDiagnostic *> &Diags,
511 FilesMade *filesMade) {
519 auto AddPieceFID = [&FM, &Fids, &SM](
const PathDiagnosticPiece &Piece) {
520 AddFID(FM, Fids, SM, Piece.getLocation().asLocation());
528 for (
const PathDiagnostic *D : Diags) {
531 WorkList.push_back(&D->path);
533 while (!WorkList.empty()) {
534 const PathPieces &Path = *WorkList.pop_back_val();
536 for (
const auto &Iter : Path) {
537 const PathDiagnosticPiece &Piece = *Iter;
540 if (
const PathDiagnosticCallPiece *Call =
541 dyn_cast<PathDiagnosticCallPiece>(&Piece)) {
542 if (
auto CallEnterWithin =
Call->getCallEnterWithinCallerEvent())
543 AddPieceFID(*CallEnterWithin);
545 if (
auto CallEnterEvent =
Call->getCallEnterEvent())
546 AddPieceFID(*CallEnterEvent);
548 WorkList.push_back(&
Call->path);
549 }
else if (
const PathDiagnosticMacroPiece *Macro =
550 dyn_cast<PathDiagnosticMacroPiece>(&Piece)) {
551 WorkList.push_back(&
Macro->subPieces);
559 llvm::raw_fd_ostream o(OutputFile, EC, llvm::sys::fs::F_Text);
561 llvm::errs() <<
"warning: could not create file: " << EC.message() <<
'\n';
572 " <key>clang_version</key>\n";
574 o <<
" <key>diagnostics</key>\n" 577 for (std::vector<const PathDiagnostic*>::iterator DI=Diags.begin(),
578 DE = Diags.end(); DI!=DE; ++DI) {
582 const PathDiagnostic *D = *DI;
586 o <<
" <key>description</key>";
587 EmitString(o, D->getShortDescription()) <<
'\n';
588 o <<
" <key>category</key>";
590 o <<
" <key>type</key>";
592 o <<
" <key>check_name</key>";
595 o <<
" <!-- This hash is experimental and going to change! -->\n";
596 o <<
" <key>issue_hash_content_of_line_in_context</key>";
599 ? UPDLoc.asLocation()
600 : D->getLocation().asLocation()),
602 const Decl *DeclWithIssue = D->getDeclWithIssue();
604 DeclWithIssue, LangOpts))
609 if (
const Decl *DeclWithIssue = D->getDeclWithIssue()) {
611 if (
const NamedDecl *ND = dyn_cast<NamedDecl>(DeclWithIssue)) {
613 switch (ND->getKind()) {
614 case Decl::CXXRecord:
615 declKind =
"C++ class";
617 case Decl::CXXMethod:
618 declKind =
"C++ method";
620 case Decl::ObjCMethod:
621 declKind =
"Objective-C method";
624 declKind =
"function";
629 if (!declKind.empty()) {
630 const std::string &declName = ND->getDeclName().getAsString();
631 o <<
" <key>issue_context_kind</key>";
633 o <<
" <key>issue_context</key>";
646 if (UPDLoc.isValid()) {
649 D->getUniqueingDecl()->getBody()->getBeginLoc()),
651 o <<
" <key>issue_hash_function_offset</key><string>" 658 o <<
" <key>issue_hash_function_offset</key><string>" 668 o <<
" <key>location</key>\n";
669 EmitLocation(o, SM, D->getLocation().asLocation(), FM, 2);
672 if (!filesMade->empty()) {
674 PDFileEntry::ConsumerFiles *files = filesMade->getFiles(*D);
676 for (PDFileEntry::ConsumerFiles::const_iterator CI = files->begin(),
677 CE = files->end(); CI != CE; ++CI) {
678 StringRef newName = CI->first;
679 if (newName != lastName) {
680 if (!lastName.empty()) {
684 o <<
" <key>" << lastName <<
"_files</key>\n";
687 o <<
" <string>" << CI->second <<
"</string>\n";
693 printCoverage(D, 2, Fids, FM, o);
701 o <<
" <key>files</key>\n" 707 if (llvm::AreStatisticsEnabled() && AnOpts.ShouldSerializeStats) {
708 o <<
" <key>statistics</key>\n";
710 llvm::raw_string_ostream os(stats);
711 llvm::PrintStatisticsJSON(os);
717 o <<
"</dict>\n</plist>";
730 class MacroArgMap :
public std::map<const IdentifierInfo *, ExpArgTokens> {
732 void expandFromPrevMacro(
const MacroArgMap &Super);
735 struct MacroNameAndArgs {
740 MacroNameAndArgs(std::string N,
const MacroInfo *MI, MacroArgMap M)
741 : Name(
std::move(N)), MI(MI), Args(
std::move(M)) {}
745 llvm::raw_ostream &
OS;
748 Token PrevTok, PrevPrevTok;
752 TokenPrinter(llvm::raw_ostream &OS,
const Preprocessor &PP)
753 : OS(OS), PP(PP), ConcatInfo(PP) {
755 PrevPrevTok.
setKind(tok::unknown);
780 static std::string getMacroNameAndPrintExpansion(TokenPrinter &Printer,
783 const MacroArgMap &PrevArgs);
807 static MacroNameAndArgs getMacroNameAndArgs(
SourceLocation ExpanLoc,
830 llvm::raw_svector_ostream
OS(ExpansionBuf);
831 TokenPrinter Printer(OS, PP);
832 std::string MacroName =
833 getMacroNameAndPrintExpansion(Printer, MacroLoc, PP, MacroArgMap{});
834 return { MacroName, OS.str() };
837 static std::string getMacroNameAndPrintExpansion(TokenPrinter &Printer,
840 const MacroArgMap &PrevArgs) {
844 MacroNameAndArgs Info = getMacroNameAndArgs(SM.
getExpansionLoc(MacroLoc), PP);
847 Info.Args.expandFromPrevMacro(PrevArgs);
850 for (
auto It = Info.MI->tokens_begin(), E = Info.MI->tokens_end(); It != E;
855 if (T.
isNot(tok::identifier)) {
856 Printer.printToken(T);
862 "This token is an identifier but has no IdentifierInfo!");
867 getMacroInfoForLocation(PP, SM, II, T.
getLocation())) {
868 getMacroNameAndPrintExpansion(Printer, T.
getLocation(), PP, Info.Args);
873 if (MI->getNumParams() != 0)
874 It = getMatchingRParen(++It, E);
879 auto ArgMapIt = Info.Args.find(II);
880 if (ArgMapIt != Info.Args.end()) {
882 ArgEnd = ArgMapIt->second.end();
883 ArgIt != ArgEnd; ++ArgIt) {
887 const auto *ArgII = ArgIt->getIdentifierInfo();
889 Printer.printToken(*ArgIt);
895 Printer.printToken(*ArgIt);
899 getMacroNameAndPrintExpansion(Printer, ArgIt->getLocation(), PP,
901 if (MI->getNumParams() != 0)
902 ArgIt = getMatchingRParen(++ArgIt, ArgEnd);
909 Printer.printToken(T);
915 static MacroNameAndArgs getMacroNameAndArgs(
SourceLocation ExpanLoc,
924 const llvm::MemoryBuffer *MB = SM.
getBuffer(LocInfo.first);
925 const char *MacroNameTokenPos = MB->getBufferStart() + LocInfo.second;
928 MB->getBufferStart(), MacroNameTokenPos, MB->getBufferEnd());
932 RawLexer.LexFromRawLexer(TheTok);
937 assert(II &&
"Failed to acquire the IndetifierInfo for the macro!");
939 const MacroInfo *MI = getMacroInfoForLocation(PP, SM, II, ExpanLoc);
940 assert(MI &&
"The macro must've been defined at it's expansion location!");
950 if (MacroArgs.empty())
951 return { MacroName, MI, {} };
953 RawLexer.LexFromRawLexer(TheTok);
954 assert(TheTok.is(tok::l_paren) &&
955 "The token after the macro's identifier token should be '('!");
968 int ParenthesesDepth = 1;
975 MacroArgMap::mapped_type ExpandedArgTokens;
986 if (ParenthesesDepth != 0) {
989 RawLexer.LexFromRawLexer(TheTok);
991 while (!(ParenthesesDepth == 1 &&
992 (UnexpArgII == __VA_ARGS__II ?
false : TheTok.is(tok::comma)))) {
994 "EOF encountered while looking for expanded macro args!");
996 if (TheTok.is(tok::l_paren))
999 if (TheTok.is(tok::r_paren))
1002 if (ParenthesesDepth == 0)
1005 if (TheTok.is(tok::raw_identifier))
1008 ExpandedArgTokens.push_back(TheTok);
1009 RawLexer.LexFromRawLexer(TheTok);
1012 assert(UnexpArgII == __VA_ARGS__II);
1015 Args.emplace(UnexpArgII, std::move(ExpandedArgTokens));
1018 assert(TheTok.is(tok::r_paren) &&
1019 "Expanded macro argument acquisition failed! After the end of the loop" 1020 " this token should be ')'!");
1022 return { MacroName, MI, Args };
1029 assert(It->is(tok::l_paren) &&
"This token should be '('!");
1032 int ParenthesesDepth = 1;
1033 while (ParenthesesDepth != 0) {
1037 "Encountered EOF while attempting to skip macro arguments!");
1039 "End of the macro definition reached before finding ')'!");
1041 if (It->is(tok::l_paren))
1044 if (It->is(tok::r_paren))
1062 void MacroArgMap::expandFromPrevMacro(
const MacroArgMap &Super) {
1064 for (value_type &Pair : *
this) {
1065 ExpArgTokens &CurrExpArgTokens = Pair.second;
1068 auto It = CurrExpArgTokens.begin();
1069 while (It != CurrExpArgTokens.end()) {
1070 if (It->isNot(tok::identifier)) {
1075 const auto *II = It->getIdentifierInfo();
1079 if (!Super.count(II)) {
1084 const ExpArgTokens &SuperExpArgTokens = Super.at(II);
1086 It = CurrExpArgTokens.insert(
1087 It, SuperExpArgTokens.begin(), SuperExpArgTokens.end());
1088 std::advance(It, SuperExpArgTokens.size());
1089 It = CurrExpArgTokens.erase(It);
1094 void TokenPrinter::printToken(
const Token &
Tok) {
1096 if (PrevTok.
isNot(tok::unknown)) {
1102 if (PrevTok.
isNot(tok::hashhash) && Tok.
isNot(tok::hashhash)) {
1108 if (!Tok.
isOneOf(tok::hash, tok::hashhash)) {
1109 if (PrevTok.
is(tok::hash))
1115 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)
std::string getName(ArrayRef< StringRef > Parts) const
Get the platform-specific name separator.
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...
llvm::MemoryBuffer * getBuffer(FileID FID, SourceLocation Loc, bool *Invalid=nullptr) const
Return the buffer for the specified FileID.
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
Dataflow Directional Tag Classes.
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.
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