26 #include "llvm/ADT/SmallPtrSet.h" 27 #include "llvm/ADT/SmallVector.h" 28 #include "llvm/ADT/Statistic.h" 29 #include "llvm/Support/Casting.h" 31 using namespace clang;
41 class PlistDiagnostics :
public PathDiagnosticConsumer {
42 const std::string OutputFile;
46 const bool SupportsCrossFileDiagnostics;
48 PlistDiagnostics(
AnalyzerOptions &AnalyzerOpts,
const std::string &prefix,
51 bool supportsMultipleFiles);
53 ~PlistDiagnostics()
override {}
55 void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
56 FilesMade *filesMade)
override;
58 StringRef
getName()
const override {
59 return "PlistDiagnostics";
62 PathGenerationScheme getGenerationScheme()
const override {
65 bool supportsLogicalOpControlFlow()
const override {
return true; }
66 bool supportsCrossFileDiagnostics()
const override {
67 return SupportsCrossFileDiagnostics;
86 : FM(FM), AnOpts(AnOpts), PP(PP), CTU(CTU) {
89 void ReportDiag(raw_ostream &o,
const PathDiagnosticPiece&
P) {
90 ReportPiece(o, P, 4, 0,
true);
102 void ReportMacroExpansions(raw_ostream &o,
unsigned indent);
105 void ReportPiece(raw_ostream &o,
const PathDiagnosticPiece &
P,
106 unsigned indent,
unsigned depth,
bool includeControlFlow,
107 bool isKeyEvent =
false) {
108 switch (P.getKind()) {
110 if (includeControlFlow)
111 ReportControlFlow(o, cast<PathDiagnosticControlFlowPiece>(P), indent);
114 ReportCall(o, cast<PathDiagnosticCallPiece>(P), indent,
118 ReportEvent(o, cast<PathDiagnosticEventPiece>(P), indent, depth,
122 ReportMacroSubPieces(o, cast<PathDiagnosticMacroPiece>(P), indent,
126 ReportNote(o, cast<PathDiagnosticNotePiece>(P), indent);
129 ReportPopUp(o, cast<PathDiagnosticPopUpPiece>(P), indent);
136 void EmitMessage(raw_ostream &o, StringRef Message,
unsigned indent);
139 void ReportControlFlow(raw_ostream &o,
140 const PathDiagnosticControlFlowPiece& P,
142 void ReportEvent(raw_ostream &o,
const PathDiagnosticEventPiece& P,
143 unsigned indent,
unsigned depth,
bool isKeyEvent =
false);
144 void ReportCall(raw_ostream &o,
const PathDiagnosticCallPiece &P,
145 unsigned indent,
unsigned depth);
146 void ReportMacroSubPieces(raw_ostream &o,
const PathDiagnosticMacroPiece& P,
147 unsigned indent,
unsigned depth);
148 void ReportNote(raw_ostream &o,
const PathDiagnosticNotePiece& P,
151 void ReportPopUp(raw_ostream &o,
const PathDiagnosticPopUpPiece &P,
159 struct ExpansionInfo {
160 std::string MacroName;
161 std::string Expansion;
162 ExpansionInfo(std::string N, std::string E)
163 : MacroName(
std::move(N)), Expansion(
std::move(E)) {}
171 const PathPieces &Path);
175 static void printCoverage(
const PathDiagnostic *D,
176 unsigned InputIndentLevel,
179 llvm::raw_fd_ostream &o);
189 void PlistPrinter::EmitRanges(raw_ostream &o,
196 Indent(o, indent) <<
"<key>ranges</key>\n";
197 Indent(o, indent) <<
"<array>\n";
203 for (
auto &R : Ranges)
208 Indent(o, indent) <<
"</array>\n";
211 void PlistPrinter::EmitMessage(raw_ostream &o, StringRef Message,
214 assert(!Message.empty());
215 Indent(o, indent) <<
"<key>extended_message</key>\n";
221 Indent(o, indent) <<
"<key>message</key>\n";
228 if (fixits.size() == 0)
234 Indent(o, indent) <<
"<key>fixits</key>\n";
235 Indent(o, indent) <<
"<array>\n";
236 for (
const auto &fixit : fixits) {
237 assert(!fixit.isNull());
239 assert(!fixit.InsertFromRange.isValid() &&
"Not implemented yet!");
240 assert(!fixit.BeforePreviousInsertions &&
"Not implemented yet!");
241 Indent(o, indent) <<
" <dict>\n";
242 Indent(o, indent) <<
" <key>remove_range</key>\n";
245 Indent(o, indent) <<
" <key>insert_string</key>";
248 Indent(o, indent) <<
" </dict>\n";
250 Indent(o, indent) <<
"</array>\n";
253 void PlistPrinter::ReportControlFlow(raw_ostream &o,
254 const PathDiagnosticControlFlowPiece& P,
260 Indent(o, indent) <<
"<dict>\n";
263 Indent(o, indent) <<
"<key>kind</key><string>control</string>\n";
266 Indent(o, indent) <<
"<key>edges</key>\n";
268 Indent(o, indent) <<
"<array>\n";
272 Indent(o, indent) <<
"<dict>\n";
278 Indent(o, indent) <<
"<key>start</key>\n";
284 Indent(o, indent) <<
"<key>end</key>\n";
290 Indent(o, indent) <<
"</dict>\n";
293 Indent(o, indent) <<
"</array>\n";
297 const auto &s = P.getString();
299 Indent(o, indent) <<
"<key>alternate</key>";
303 assert(P.getFixits().size() == 0 &&
304 "Fixits on constrol flow pieces are not implemented yet!");
307 Indent(o, indent) <<
"</dict>\n";
310 void PlistPrinter::ReportEvent(raw_ostream &o,
const PathDiagnosticEventPiece& P,
311 unsigned indent,
unsigned depth,
316 Indent(o, indent) <<
"<dict>\n";
319 Indent(o, indent) <<
"<key>kind</key><string>event</string>\n";
322 Indent(o, indent) <<
"<key>key_event</key><true/>\n";
328 Indent(o, indent) <<
"<key>location</key>\n";
333 EmitRanges(o, Ranges, indent);
336 Indent(o, indent) <<
"<key>depth</key>";
340 EmitMessage(o, P.getString(), indent);
343 EmitFixits(o, P.getFixits(), indent);
347 Indent(o, indent); o <<
"</dict>\n";
350 void PlistPrinter::ReportCall(raw_ostream &o,
const PathDiagnosticCallPiece &P,
354 if (
auto callEnter = P.getCallEnterEvent())
355 ReportPiece(o, *callEnter, indent, depth,
true,
356 P.isLastInMainSourceFile());
361 if (
auto callEnterWithinCaller = P.getCallEnterWithinCallerEvent())
362 ReportPiece(o, *callEnterWithinCaller, indent, depth,
365 for (PathPieces::const_iterator I = P.path.begin(), E = P.path.end();I!=E;++I)
366 ReportPiece(o, **I, indent, depth,
true);
370 if (
auto callExit = P.getCallExitEvent())
371 ReportPiece(o, *callExit, indent, depth,
true);
373 assert(P.getFixits().size() == 0 &&
374 "Fixits on call pieces are not implemented yet!");
377 void PlistPrinter::ReportMacroSubPieces(raw_ostream &o,
378 const PathDiagnosticMacroPiece& P,
379 unsigned indent,
unsigned depth) {
380 MacroPieces.push_back(&P);
382 for (PathPieces::const_iterator I = P.subPieces.begin(),
383 E = P.subPieces.end();
385 ReportPiece(o, **I, indent, depth,
false);
388 assert(P.getFixits().size() == 0 &&
389 "Fixits on constrol flow pieces are not implemented yet!");
392 void PlistPrinter::ReportMacroExpansions(raw_ostream &o,
unsigned indent) {
394 for (
const PathDiagnosticMacroPiece *P : MacroPieces) {
396 ExpansionInfo EI = getExpandedMacro(P->getLocation().asLocation(), PP, CTU);
398 Indent(o, indent) <<
"<dict>\n";
404 Indent(o, indent) <<
"<key>location</key>\n";
409 EmitRanges(o, Ranges, indent);
412 Indent(o, indent) <<
"<key>name</key>";
416 Indent(o, indent) <<
"<key>expansion</key>";
426 void PlistPrinter::ReportNote(raw_ostream &o,
const PathDiagnosticNotePiece& P,
431 Indent(o, indent) <<
"<dict>\n";
437 Indent(o, indent) <<
"<key>location</key>\n";
442 EmitRanges(o, Ranges, indent);
445 EmitMessage(o, P.getString(), indent);
448 EmitFixits(o, P.getFixits(), indent);
452 Indent(o, indent); o <<
"</dict>\n";
455 void PlistPrinter::ReportPopUp(raw_ostream &o,
456 const PathDiagnosticPopUpPiece &P,
460 Indent(o, indent) <<
"<dict>\n";
463 Indent(o, indent) <<
"<key>kind</key><string>pop-up</string>\n";
468 Indent(o, indent) <<
"<key>location</key>\n";
473 EmitRanges(o, Ranges, indent);
476 EmitMessage(o, P.getString(), indent);
478 assert(P.getFixits().size() == 0 &&
479 "Fixits on pop-up pieces are not implemented yet!");
483 Indent(o, indent) <<
"</dict>\n";
492 static void printCoverage(
const PathDiagnostic *D,
493 unsigned InputIndentLevel,
496 llvm::raw_fd_ostream &o) {
497 unsigned IndentLevel = InputIndentLevel;
499 Indent(o, IndentLevel) <<
"<key>ExecutedLines</key>\n";
500 Indent(o, IndentLevel) <<
"<dict>\n";
505 for (
auto I = ExecutedLines.begin(), E = ExecutedLines.end(); I != E; ++I) {
506 unsigned FileKey =
AddFID(FM, Fids, I->first);
507 Indent(o, IndentLevel) <<
"<key>" << FileKey <<
"</key>\n";
508 Indent(o, IndentLevel) <<
"<array>\n";
510 for (
unsigned LineNo : I->second) {
515 Indent(o, IndentLevel) <<
"</array>\n";
518 Indent(o, IndentLevel) <<
"</dict>\n";
520 assert(IndentLevel == InputIndentLevel);
526 const PathPieces &Path) {
527 PlistPrinter Printer(FM, AnOpts, PP, CTU);
528 assert(std::is_partitioned(Path.begin(), Path.end(),
532 "PathDiagnostic is not partitioned so that notes precede the rest");
534 PathPieces::const_iterator FirstNonNote = std::partition_point(
539 PathPieces::const_iterator I = Path.begin();
541 if (FirstNonNote != Path.begin()) {
542 o <<
" <key>notes</key>\n" 545 for (; I != FirstNonNote; ++I)
546 Printer.ReportDiag(o, **I);
551 o <<
" <key>path</key>\n";
555 for (PathPieces::const_iterator E = Path.end(); I != E; ++I)
556 Printer.ReportDiag(o, **I);
560 if (!AnOpts.ShouldDisplayMacroExpansions)
563 o <<
" <key>macro_expansions</key>\n" 565 Printer.ReportMacroExpansions(o, 4);
573 PlistDiagnostics::PlistDiagnostics(
576 bool supportsMultipleFiles)
577 : OutputFile(output), PP(PP), CTU(CTU), AnOpts(AnalyzerOpts),
578 SupportsCrossFileDiagnostics(supportsMultipleFiles) {
583 void ento::createPlistDiagnosticConsumer(
587 C.push_back(
new PlistDiagnostics(AnalyzerOpts, s, PP, CTU,
591 void ento::createPlistMultiFileDiagnosticConsumer(
595 C.push_back(
new PlistDiagnostics(AnalyzerOpts, s, PP, CTU,
598 void PlistDiagnostics::FlushDiagnosticsImpl(
599 std::vector<const PathDiagnostic *> &Diags,
600 FilesMade *filesMade) {
608 auto AddPieceFID = [&FM, &Fids, &
SM](
const PathDiagnosticPiece &Piece) {
609 AddFID(FM, Fids, SM, Piece.getLocation().asLocation());
612 AddFID(FM, Fids, SM, Range.getBegin());
613 AddFID(FM, Fids, SM, Range.getEnd());
617 for (
const PathDiagnostic *D : Diags) {
620 WorkList.push_back(&D->path);
622 while (!WorkList.empty()) {
623 const PathPieces &Path = *WorkList.pop_back_val();
625 for (
const auto &Iter : Path) {
626 const PathDiagnosticPiece &Piece = *Iter;
629 if (
const PathDiagnosticCallPiece *Call =
630 dyn_cast<PathDiagnosticCallPiece>(&Piece)) {
631 if (
auto CallEnterWithin =
Call->getCallEnterWithinCallerEvent())
632 AddPieceFID(*CallEnterWithin);
634 if (
auto CallEnterEvent =
Call->getCallEnterEvent())
635 AddPieceFID(*CallEnterEvent);
637 WorkList.push_back(&
Call->path);
638 }
else if (
const PathDiagnosticMacroPiece *Macro =
639 dyn_cast<PathDiagnosticMacroPiece>(&Piece)) {
640 WorkList.push_back(&
Macro->subPieces);
648 llvm::raw_fd_ostream o(OutputFile, EC, llvm::sys::fs::OF_Text);
650 llvm::errs() <<
"warning: could not create file: " << EC.message() <<
'\n';
661 " <key>clang_version</key>\n";
663 o <<
" <key>diagnostics</key>\n" 666 for (std::vector<const PathDiagnostic*>::iterator DI=Diags.begin(),
667 DE = Diags.end(); DI!=DE; ++DI) {
671 const PathDiagnostic *D = *DI;
675 o <<
" <key>description</key>";
676 EmitString(o, D->getShortDescription()) <<
'\n';
677 o <<
" <key>category</key>";
679 o <<
" <key>type</key>";
681 o <<
" <key>check_name</key>";
684 o <<
" <!-- This hash is experimental and going to change! -->\n";
685 o <<
" <key>issue_hash_content_of_line_in_context</key>";
686 PathDiagnosticLocation UPDLoc = D->getUniqueingLoc();
688 ? UPDLoc.asLocation()
689 : D->getLocation().asLocation()),
691 const Decl *DeclWithIssue = D->getDeclWithIssue();
693 DeclWithIssue, LangOpts))
698 if (
const Decl *DeclWithIssue = D->getDeclWithIssue()) {
700 if (
const NamedDecl *ND = dyn_cast<NamedDecl>(DeclWithIssue)) {
702 switch (ND->getKind()) {
703 case Decl::CXXRecord:
704 declKind =
"C++ class";
706 case Decl::CXXMethod:
707 declKind =
"C++ method";
709 case Decl::ObjCMethod:
710 declKind =
"Objective-C method";
713 declKind =
"function";
718 if (!declKind.empty()) {
719 const std::string &declName = ND->getDeclName().getAsString();
720 o <<
" <key>issue_context_kind</key>";
722 o <<
" <key>issue_context</key>";
735 if (UPDLoc.isValid()) {
738 D->getUniqueingDecl()->getBody()->getBeginLoc()),
740 o <<
" <key>issue_hash_function_offset</key><string>" 747 o <<
" <key>issue_hash_function_offset</key><string>" 757 o <<
" <key>location</key>\n";
758 EmitLocation(o, SM, D->getLocation().asLocation(), FM, 2);
761 if (!filesMade->empty()) {
763 PDFileEntry::ConsumerFiles *files = filesMade->getFiles(*D);
765 for (PDFileEntry::ConsumerFiles::const_iterator CI = files->begin(),
766 CE = files->end(); CI != CE; ++CI) {
767 StringRef newName = CI->first;
768 if (newName != lastName) {
769 if (!lastName.empty()) {
773 o <<
" <key>" << lastName <<
"_files</key>\n";
776 o <<
" <string>" << CI->second <<
"</string>\n";
782 printCoverage(D, 2, Fids, FM, o);
790 o <<
" <key>files</key>\n" 796 if (llvm::AreStatisticsEnabled() && AnOpts.ShouldSerializeStats) {
797 o <<
" <key>statistics</key>\n";
799 llvm::raw_string_ostream os(stats);
800 llvm::PrintStatisticsJSON(os);
806 o <<
"</dict>\n</plist>\n";
819 class MacroArgMap :
public std::map<const IdentifierInfo *, ExpArgTokens> {
821 void expandFromPrevMacro(
const MacroArgMap &Super);
824 struct MacroNameAndArgs {
829 MacroNameAndArgs(std::string N,
const MacroInfo *MI, MacroArgMap M)
830 : Name(
std::move(N)), MI(MI), Args(
std::move(M)) {}
834 llvm::raw_ostream &
OS;
837 Token PrevTok, PrevPrevTok;
841 TokenPrinter(llvm::raw_ostream &OS,
const Preprocessor &PP)
842 : OS(OS), PP(PP), ConcatInfo(PP) {
844 PrevPrevTok.
setKind(tok::unknown);
877 static std::string getMacroNameAndPrintExpansion(
878 TokenPrinter &Printer,
881 const MacroArgMap &PrevArgs,
882 llvm::SmallPtrSet<IdentifierInfo *, 8> &AlreadyProcessedTokens);
906 static MacroNameAndArgs getMacroNameAndArgs(
SourceLocation ExpanLoc,
931 MacroLoc = LocAndUnit->first;
932 PPToUse = &LocAndUnit->second->getPreprocessor();
936 llvm::raw_svector_ostream
OS(ExpansionBuf);
937 TokenPrinter Printer(OS, *PPToUse);
938 llvm::SmallPtrSet<IdentifierInfo*, 8> AlreadyProcessedTokens;
940 std::string MacroName = getMacroNameAndPrintExpansion(
941 Printer, MacroLoc, *PPToUse, MacroArgMap{}, AlreadyProcessedTokens);
942 return { MacroName, OS.str() };
945 static std::string getMacroNameAndPrintExpansion(
946 TokenPrinter &Printer,
949 const MacroArgMap &PrevArgs,
950 llvm::SmallPtrSet<IdentifierInfo *, 8> &AlreadyProcessedTokens) {
954 MacroNameAndArgs Info = getMacroNameAndArgs(SM.
getExpansionLoc(MacroLoc), PP);
963 if (AlreadyProcessedTokens.find(IDInfo) != AlreadyProcessedTokens.end())
965 AlreadyProcessedTokens.insert(IDInfo);
971 Info.Args.expandFromPrevMacro(PrevArgs);
974 for (
auto It = Info.MI->tokens_begin(), E = Info.MI->tokens_end(); It != E;
979 if (T.
isNot(tok::identifier)) {
980 Printer.printToken(T);
986 "This token is an identifier but has no IdentifierInfo!");
990 if (getMacroInfoForLocation(PP, SM, II, T.
getLocation())) {
991 getMacroNameAndPrintExpansion(Printer, T.
getLocation(), PP, Info.Args,
992 AlreadyProcessedTokens);
997 auto N = std::next(It);
998 if (N != E && N->is(tok::l_paren))
999 It = getMatchingRParen(++It, E);
1004 auto ArgMapIt = Info.Args.find(II);
1005 if (ArgMapIt != Info.Args.end()) {
1007 ArgEnd = ArgMapIt->second.end();
1008 ArgIt != ArgEnd; ++ArgIt) {
1012 const auto *ArgII = ArgIt->getIdentifierInfo();
1014 Printer.printToken(*ArgIt);
1020 Printer.printToken(*ArgIt);
1024 getMacroNameAndPrintExpansion(Printer, ArgIt->getLocation(), PP,
1025 Info.Args, AlreadyProcessedTokens);
1034 auto N = std::next(ArgIt);
1035 if (N != ArgEnd && N->is(tok::l_paren))
1036 ArgIt = getMatchingRParen(++ArgIt, ArgEnd);
1043 Printer.printToken(T);
1046 AlreadyProcessedTokens.erase(IDInfo);
1051 static MacroNameAndArgs getMacroNameAndArgs(
SourceLocation ExpanLoc,
1060 const llvm::MemoryBuffer *MB = SM.
getBuffer(LocInfo.first);
1061 const char *MacroNameTokenPos = MB->getBufferStart() + LocInfo.second;
1064 MB->getBufferStart(), MacroNameTokenPos, MB->getBufferEnd());
1068 RawLexer.LexFromRawLexer(TheTok);
1073 assert(II &&
"Failed to acquire the IndetifierInfo for the macro!");
1075 const MacroInfo *MI = getMacroInfoForLocation(PP, SM, II, ExpanLoc);
1083 return { MacroName, MI, {} };
1093 if (MacroArgs.empty())
1094 return { MacroName, MI, {} };
1096 RawLexer.LexFromRawLexer(TheTok);
1105 if (TheTok.isNot(tok::l_paren))
1106 return { MacroName, MI, {} };
1119 int ParenthesesDepth = 1;
1126 MacroArgMap::mapped_type ExpandedArgTokens;
1137 if (ParenthesesDepth != 0) {
1140 RawLexer.LexFromRawLexer(TheTok);
1142 while (!(ParenthesesDepth == 1 &&
1143 (UnexpArgII == __VA_ARGS__II ?
false : TheTok.is(tok::comma)))) {
1145 "EOF encountered while looking for expanded macro args!");
1147 if (TheTok.is(tok::l_paren))
1150 if (TheTok.is(tok::r_paren))
1153 if (ParenthesesDepth == 0)
1156 if (TheTok.is(tok::raw_identifier))
1159 ExpandedArgTokens.push_back(TheTok);
1160 RawLexer.LexFromRawLexer(TheTok);
1163 assert(UnexpArgII == __VA_ARGS__II);
1166 Args.emplace(UnexpArgII, std::move(ExpandedArgTokens));
1169 assert(TheTok.is(tok::r_paren) &&
1170 "Expanded macro argument acquisition failed! After the end of the loop" 1171 " this token should be ')'!");
1173 return { MacroName, MI, Args };
1180 assert(It->is(tok::l_paren) &&
"This token should be '('!");
1183 int ParenthesesDepth = 1;
1184 while (ParenthesesDepth != 0) {
1188 "Encountered EOF while attempting to skip macro arguments!");
1190 "End of the macro definition reached before finding ')'!");
1192 if (It->is(tok::l_paren))
1195 if (It->is(tok::r_paren))
1213 void MacroArgMap::expandFromPrevMacro(
const MacroArgMap &Super) {
1215 for (value_type &Pair : *
this) {
1216 ExpArgTokens &CurrExpArgTokens = Pair.second;
1219 auto It = CurrExpArgTokens.begin();
1220 while (It != CurrExpArgTokens.end()) {
1221 if (It->isNot(tok::identifier)) {
1226 const auto *II = It->getIdentifierInfo();
1230 if (!Super.count(II)) {
1235 const ExpArgTokens &SuperExpArgTokens = Super.at(II);
1237 It = CurrExpArgTokens.insert(
1238 It, SuperExpArgTokens.begin(), SuperExpArgTokens.end());
1239 std::advance(It, SuperExpArgTokens.size());
1240 It = CurrExpArgTokens.erase(It);
1245 void TokenPrinter::printToken(
const Token &
Tok) {
1247 if (PrevTok.
isNot(tok::unknown)) {
1253 if (PrevTok.
isNot(tok::hashhash) && Tok.
isNot(tok::hashhash)) {
1259 if (!Tok.
isOneOf(tok::hash, tok::hashhash)) {
1260 if (PrevTok.
is(tok::hash))
1266 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
std::shared_ptr< PathDiagnosticPiece > PathDiagnosticPieceRef
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
std::map< FileID, std::set< unsigned > > FilesToLineNumsMap
File IDs mapped to sets of line numbers.
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 void printBugPath(llvm::raw_ostream &o, const FIDMap &FM, AnalyzerOptions &AnOpts, const Preprocessor &PP, const cross_tu::CrossTranslationUnitContext &CTU, const PathPieces &Path)
static std::string getName(const CallEvent &Call)
bool isOneOf(tok::TokenKind K1, tok::TokenKind K2) const
MacroInfo * getMacroInfo()
void EmitRange(raw_ostream &o, const SourceManager &SM, CharSourceRange R, const FIDMap &FM, unsigned indent)
This class is used for tools that requires cross translation unit capability.
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.
llvm::Optional< std::pair< SourceLocation, ASTUnit * > > getImportedFromSourceLocation(const clang::SourceLocation &ToLoc) const
Determine the original source location in the original TU for an imported source location.
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.
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