clang: lib/Frontend/PrintPreprocessedOutput.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
24#include "llvm/ADT/STLExtras.h"
25#include "llvm/ADT/SmallString.h"
26#include "llvm/ADT/StringRef.h"
27#include "llvm/Support/ErrorHandling.h"
28#include "llvm/Support/raw_ostream.h"
29#include
30using namespace clang;
31
32
33
36 *OS << "#define " << II.getName();
37
39 *OS << '(';
42 for (; AI+1 != E; ++AI) {
43 *OS << (*AI)->getName();
44 *OS << ',';
45 }
46
47
48 if ((*AI)->getName() == "__VA_ARGS__")
49 *OS << "...";
50 else
51 *OS << (*AI)->getName();
52 }
53
55 *OS << "...";
56
57 *OS << ')';
58 }
59
60
61
63 *OS << ' ';
64
66 for (const auto &T : MI.tokens()) {
67 if (T.hasLeadingSpace())
68 *OS << ' ';
69
71 }
72}
73
74
75
76
77
78namespace {
79class PrintPPOutputPPCallbacks : public PPCallbacks {
83public:
84 raw_ostream *OS;
85private:
86 unsigned CurLine;
87
88 bool EmittedTokensOnThisLine;
89 bool EmittedDirectiveOnThisLine;
93 bool DisableLineMarkers;
94 bool DumpDefines;
95 bool DumpIncludeDirectives;
96 bool DumpEmbedDirectives;
97 bool UseLineDirectives;
98 bool IsFirstFileEntered;
99 bool MinimizeWhitespace;
100 bool DirectivesOnly;
101 bool KeepSystemIncludes;
102 raw_ostream *OrigOS;
103 std::unique_ptrllvm::raw\_null\_ostream NullOS;
104 unsigned NumToksToSkip;
105
107 Token PrevPrevTok;
108
109public:
110 PrintPPOutputPPCallbacks(Preprocessor &pp, raw_ostream *os, bool lineMarkers,
111 bool defines, bool DumpIncludeDirectives,
112 bool DumpEmbedDirectives, bool UseLineDirectives,
113 bool MinimizeWhitespace, bool DirectivesOnly,
114 bool KeepSystemIncludes)
115 : PP(pp), SM(PP.getSourceManager()), ConcatInfo(PP), OS(os),
116 DisableLineMarkers(lineMarkers), DumpDefines(defines),
117 DumpIncludeDirectives(DumpIncludeDirectives),
118 DumpEmbedDirectives(DumpEmbedDirectives),
119 UseLineDirectives(UseLineDirectives),
120 MinimizeWhitespace(MinimizeWhitespace), DirectivesOnly(DirectivesOnly),
121 KeepSystemIncludes(KeepSystemIncludes), OrigOS(os), NumToksToSkip(0) {
122 CurLine = 0;
123 CurFilename += "";
124 EmittedTokensOnThisLine = false;
125 EmittedDirectiveOnThisLine = false;
128 IsFirstFileEntered = false;
129 if (KeepSystemIncludes)
130 NullOS = std::make_uniquellvm::raw\_null\_ostream();
131
134 }
135
136
137
138 bool expandEmbedContents() const { return !DumpEmbedDirectives; }
139
140 bool isMinimizeWhitespace() const { return MinimizeWhitespace; }
141
142 void setEmittedTokensOnThisLine() { EmittedTokensOnThisLine = true; }
143 bool hasEmittedTokensOnThisLine() const { return EmittedTokensOnThisLine; }
144
145 void setEmittedDirectiveOnThisLine() { EmittedDirectiveOnThisLine = true; }
146 bool hasEmittedDirectiveOnThisLine() const {
147 return EmittedDirectiveOnThisLine;
148 }
149
150
151
152
153
154
155 void startNewLineIfNeeded();
156
159 FileID PrevFID) override;
164 StringRef FileName, bool IsAngled,
167 StringRef RelativePath, const Module *SuggestedModule,
168 bool ModuleImported,
172 PragmaMessageKind Kind, StringRef Str) override;
186
187
188
189
190
191
192
193
194 void HandleWhitespaceBeforeTok(const Token &Tok, bool RequireSpace,
195 bool RequireSameLine);
196
197
198
199
200
201
202
203
204
205
206
207
208
209 bool MoveToLine(const Token &Tok, bool RequireStartOfLine) {
211 unsigned TargetLine = PLoc.isValid() ? PLoc.getLine() : CurLine;
212 bool IsFirstInFile =
214 return MoveToLine(TargetLine, RequireStartOfLine) || IsFirstInFile;
215 }
216
217
218
221 unsigned TargetLine = PLoc.isValid() ? PLoc.getLine() : CurLine;
222 return MoveToLine(TargetLine, RequireStartOfLine);
223 }
224 bool MoveToLine(unsigned LineNo, bool RequireStartOfLine);
225
226 bool AvoidConcat(const Token &PrevPrevTok, const Token &PrevTok,
227 const Token &Tok) {
228 return ConcatInfo.AvoidConcat(PrevPrevTok, PrevTok, Tok);
229 }
230 void WriteLineInfo(unsigned LineNo, const char *Extra=nullptr,
231 unsigned ExtraLen=0);
232 bool LineMarkersAreDisabled() const { return DisableLineMarkers; }
233 void HandleNewlinesInToken(const char *TokStr, unsigned Len);
234
235
238
239
243
244 void BeginModule(const Module *M);
245 void EndModule(const Module *M);
246
247 unsigned GetNumToksToSkip() const { return NumToksToSkip; }
248 void ResetSkipToks() { NumToksToSkip = 0; }
249};
250}
251
252void PrintPPOutputPPCallbacks::WriteLineInfo(unsigned LineNo,
253 const char *Extra,
254 unsigned ExtraLen) {
255 startNewLineIfNeeded();
256
257
258 if (UseLineDirectives) {
259 *OS << "#line" << ' ' << LineNo << ' ' << '"';
260 OS->write_escaped(CurFilename);
261 *OS << '"';
262 } else {
263 *OS << '#' << ' ' << LineNo << ' ' << '"';
264 OS->write_escaped(CurFilename);
265 *OS << '"';
266
267 if (ExtraLen)
268 OS->write(Extra, ExtraLen);
269
271 OS->write(" 3", 2);
273 OS->write(" 3 4", 4);
274 }
275 *OS << '\n';
276}
277
278
279
280
281
282bool PrintPPOutputPPCallbacks::MoveToLine(unsigned LineNo,
283 bool RequireStartOfLine) {
284
285
286
287 bool StartedNewLine = false;
288 if ((RequireStartOfLine && EmittedTokensOnThisLine) ||
289 EmittedDirectiveOnThisLine) {
290 *OS << '\n';
291 StartedNewLine = true;
292 CurLine += 1;
293 EmittedTokensOnThisLine = false;
294 EmittedDirectiveOnThisLine = false;
295 }
296
297
298
299 if (CurLine == LineNo) {
300
301 } else if (MinimizeWhitespace && DisableLineMarkers) {
302
303 } else if (!StartedNewLine && LineNo - CurLine == 1) {
304
305
306
307 *OS << '\n';
308 StartedNewLine = true;
309 } else if (!DisableLineMarkers) {
310 if (LineNo - CurLine <= 8) {
311 const char *NewLines = "\n\n\n\n\n\n\n\n";
312 OS->write(NewLines, LineNo - CurLine);
313 } else {
314
315 WriteLineInfo(LineNo, nullptr, 0);
316 }
317 StartedNewLine = true;
318 } else if (EmittedTokensOnThisLine) {
319
320
321 *OS << '\n';
322 StartedNewLine = true;
323 }
324
325 if (StartedNewLine) {
326 EmittedTokensOnThisLine = false;
327 EmittedDirectiveOnThisLine = false;
328 }
329
330 CurLine = LineNo;
331 return StartedNewLine;
332}
333
334void PrintPPOutputPPCallbacks::startNewLineIfNeeded() {
335 if (EmittedTokensOnThisLine || EmittedDirectiveOnThisLine) {
336 *OS << '\n';
337 EmittedTokensOnThisLine = false;
338 EmittedDirectiveOnThisLine = false;
339 }
340}
341
342
343
344
346 FileChangeReason Reason,
349
350
352
355 return;
356
358
361 if (IncludeLoc.isValid())
362 MoveToLine(IncludeLoc, false);
364
365
366
367
368
370 }
371
373
374
377
378 CurFilename.clear();
381
382 if (DisableLineMarkers) {
383 if (!MinimizeWhitespace)
384 startNewLineIfNeeded();
385 return;
386 }
387
389 WriteLineInfo(CurLine);
391 }
392
393
394
395
396
398 IsFirstFileEntered = true;
399 return;
400 }
401
402 switch (Reason) {
404 WriteLineInfo(CurLine, " 1", 2);
405 break;
407 WriteLineInfo(CurLine, " 2", 2);
408 break;
411 WriteLineInfo(CurLine);
412 break;
413 }
414}
415
416void PrintPPOutputPPCallbacks::EmbedDirective(
419 if (!DumpEmbedDirectives)
420 return;
421
422
423
424
425
426
427
428
429
430
431
432 MoveToLine(HashLoc, true);
433 *OS << "#embed " << (IsAngled ? '<' : '"') << FileName
434 << (IsAngled ? '>' : '"');
435
438 for (const Token &T : Toks) {
439 if (T.hasLeadingSpace())
440 *OS << " ";
442 }
443 };
444 bool SkipAnnotToks = true;
446 *OS << " if_empty(";
448 *OS << ")";
449
450
451 if (File && ->getSize()) {
453 SkipAnnotToks = false;
454 }
455 }
456
458 *OS << " limit(" << Params.MaybeLimitParam->Limit << ")";
459 }
461 *OS << " clang::offset(" << Params.MaybeOffsetParam->Offset << ")";
462 }
464 *OS << " prefix(";
466 *OS << ")";
468 }
470 *OS << " suffix(";
472 *OS << ")";
474 }
475
476
477 if (SkipAnnotToks)
478 NumToksToSkip++;
479
480 *OS << " /* clang -E -dE */";
481 setEmittedDirectiveOnThisLine();
482}
483
484void PrintPPOutputPPCallbacks::InclusionDirective(
487 StringRef SearchPath, StringRef RelativePath, const Module *SuggestedModule,
489
490
491 if (DumpIncludeDirectives || (KeepSystemIncludes && isSystem(FileType))) {
492 MoveToLine(HashLoc, true);
493 const std::string TokenText = PP.getSpelling(IncludeTok);
494 assert(!TokenText.empty());
495 *OS << "#" << TokenText << " "
496 << (IsAngled ? '<' : '"') << FileName << (IsAngled ? '>' : '"')
497 << " /* clang -E "
498 << (DumpIncludeDirectives ? "-dI" : "-fkeep-system-includes")
499 << " */";
500 setEmittedDirectiveOnThisLine();
501 }
502
503
504 if (ModuleImported) {
506 case tok::pp_include:
507 case tok::pp_import:
508 case tok::pp_include_next:
509 MoveToLine(HashLoc, true);
510 *OS << "#pragma clang module import "
512 << " /* clang -E: implicit import for "
513 << "#" << PP.getSpelling(IncludeTok) << " "
514 << (IsAngled ? '<' : '"') << FileName << (IsAngled ? '>' : '"')
515 << " */";
516 setEmittedDirectiveOnThisLine();
517 break;
518
519 case tok::pp___include_macros:
520
521
522
523
524
525 break;
526
527 default:
528 llvm_unreachable("unknown include directive kind");
529 break;
530 }
531 }
532}
533
534
535void PrintPPOutputPPCallbacks::BeginModule(const Module *M) {
536 startNewLineIfNeeded();
537 *OS << "#pragma clang module begin " << M->getFullModuleName(true);
538 setEmittedDirectiveOnThisLine();
539}
540
541
542void PrintPPOutputPPCallbacks::EndModule(const Module *M) {
543 startNewLineIfNeeded();
544 *OS << "#pragma clang module end /*" << M->getFullModuleName(true) << "*/";
545 setEmittedDirectiveOnThisLine();
546}
547
548
549
550void PrintPPOutputPPCallbacks::Ident(SourceLocation Loc, StringRef S) {
551 MoveToLine(Loc, true);
552
553 OS->write("#ident ", strlen("#ident "));
554 OS->write(S.begin(), S.size());
555 setEmittedTokensOnThisLine();
556}
557
558
559void PrintPPOutputPPCallbacks::MacroDefined(const Token &MacroNameTok,
562
563
564 if ((!DumpDefines && !DirectivesOnly) ||
565
567 return;
568
570 if (DirectivesOnly && !MI->isUsed()) {
572 if (SM.isWrittenInBuiltinFile(DefLoc) ||
573 SM.isWrittenInCommandLineFile(DefLoc))
574 return;
575 }
576 MoveToLine(DefLoc, true);
578 setEmittedDirectiveOnThisLine();
579}
580
581void PrintPPOutputPPCallbacks::MacroUndefined(const Token &MacroNameTok,
584
585
586 if (!DumpDefines && !DirectivesOnly)
587 return;
588
589 MoveToLine(MacroNameTok.getLocation(), true);
591 setEmittedDirectiveOnThisLine();
592}
593
595 for (unsigned char Char : Str) {
596 if (isPrintable(Char) && Char != '\\' && Char != '"')
597 *OS << (char)Char;
598 else
599 *OS << '\\'
600 << (char)('0' + ((Char >> 6) & 7))
601 << (char)('0' + ((Char >> 3) & 7))
602 << (char)('0' + ((Char >> 0) & 7));
603 }
604}
605
607 StringRef Namespace,
608 PragmaMessageKind Kind,
609 StringRef Str) {
610 MoveToLine(Loc, true);
611 *OS << "#pragma ";
614 switch (Kind) {
615 case PMK_Message:
616 *OS << "message(\"";
617 break;
618 case PMK_Warning:
619 *OS << "warning \"";
620 break;
621 case PMK_Error:
622 *OS << "error \"";
623 break;
624 }
625
627 *OS << '"';
628 if (Kind == PMK_Message)
629 *OS << ')';
630 setEmittedDirectiveOnThisLine();
631}
632
634 StringRef DebugType) {
635 MoveToLine(Loc, true);
636
637 *OS << "#pragma clang __debug ";
638 *OS << DebugType;
639
640 setEmittedDirectiveOnThisLine();
641}
642
643void PrintPPOutputPPCallbacks::
645 MoveToLine(Loc, true);
646 *OS << "#pragma " << Namespace << " diagnostic push";
647 setEmittedDirectiveOnThisLine();
648}
649
650void PrintPPOutputPPCallbacks::
652 MoveToLine(Loc, true);
653 *OS << "#pragma " << Namespace << " diagnostic pop";
654 setEmittedDirectiveOnThisLine();
655}
656
657void PrintPPOutputPPCallbacks::PragmaDiagnostic(SourceLocation Loc,
658 StringRef Namespace,
660 StringRef Str) {
661 MoveToLine(Loc, true);
662 *OS << "#pragma " << Namespace << " diagnostic ";
663 switch (Map) {
664 case diag::Severity::Remark:
665 *OS << "remark";
666 break;
667 case diag::Severity::Warning:
668 *OS << "warning";
669 break;
670 case diag::Severity::Error:
671 *OS << "error";
672 break;
673 case diag::Severity::Ignored:
674 *OS << "ignored";
675 break;
676 case diag::Severity::Fatal:
677 *OS << "fatal";
678 break;
679 }
680 *OS << " \"" << Str << '"';
681 setEmittedDirectiveOnThisLine();
682}
683
685 PragmaWarningSpecifier WarningSpec,
687 MoveToLine(Loc, true);
688
689 *OS << "#pragma warning(";
690 switch(WarningSpec) {
691 case PWS_Default: *OS << "default"; break;
692 case PWS_Disable: *OS << "disable"; break;
693 case PWS_Error: *OS << "error"; break;
694 case PWS_Once: *OS << "once"; break;
695 case PWS_Suppress: *OS << "suppress"; break;
696 case PWS_Level1: *OS << '1'; break;
697 case PWS_Level2: *OS << '2'; break;
698 case PWS_Level3: *OS << '3'; break;
699 case PWS_Level4: *OS << '4'; break;
700 }
701 *OS << ':';
702
704 *OS << ' ' << *I;
705 *OS << ')';
706 setEmittedDirectiveOnThisLine();
707}
708
709void PrintPPOutputPPCallbacks::PragmaWarningPush(SourceLocation Loc,
710 int Level) {
711 MoveToLine(Loc, true);
712 *OS << "#pragma warning(push";
713 if (Level >= 0)
714 *OS << ", " << Level;
715 *OS << ')';
716 setEmittedDirectiveOnThisLine();
717}
718
719void PrintPPOutputPPCallbacks::PragmaWarningPop(SourceLocation Loc) {
720 MoveToLine(Loc, true);
721 *OS << "#pragma warning(pop)";
722 setEmittedDirectiveOnThisLine();
723}
724
725void PrintPPOutputPPCallbacks::PragmaExecCharsetPush(SourceLocation Loc,
726 StringRef Str) {
727 MoveToLine(Loc, true);
728 *OS << "#pragma character_execution_set(push";
729 if (!Str.empty())
730 *OS << ", " << Str;
731 *OS << ')';
732 setEmittedDirectiveOnThisLine();
733}
734
735void PrintPPOutputPPCallbacks::PragmaExecCharsetPop(SourceLocation Loc) {
736 MoveToLine(Loc, true);
737 *OS << "#pragma character_execution_set(pop)";
738 setEmittedDirectiveOnThisLine();
739}
740
741void PrintPPOutputPPCallbacks::
743 MoveToLine(Loc, true);
744 *OS << "#pragma clang assume_nonnull begin";
745 setEmittedDirectiveOnThisLine();
746}
747
748void PrintPPOutputPPCallbacks::
750 MoveToLine(Loc, true);
751 *OS << "#pragma clang assume_nonnull end";
752 setEmittedDirectiveOnThisLine();
753}
754
755void PrintPPOutputPPCallbacks::HandleWhitespaceBeforeTok(const Token &Tok,
756 bool RequireSpace,
757 bool RequireSameLine) {
758
759
760 if (Tok.is(tok::eof) ||
761 (Tok.isAnnotation() && !Tok.is(tok::annot_header_unit) &&
762 !Tok.is(tok::annot_module_begin) && !Tok.is(tok::annot_module_end) &&
763 !Tok.is(tok::annot_repl_input_end) && !Tok.is(tok::annot_embed)))
764 return;
765
766
767 if ((!RequireSameLine || EmittedDirectiveOnThisLine) &&
768 MoveToLine(Tok, EmittedDirectiveOnThisLine)) {
769 if (MinimizeWhitespace) {
770
771 if (Tok.is(tok::hash))
772 *OS << ' ';
773 } else {
774
775
776 unsigned ColNo = SM.getExpansionColumnNumber(Tok.getLocation());
777
778
779
780
781
783 ColNo = 2;
784
785
786
787
788
789
790
791 if (ColNo <= 1 && Tok.is(tok::hash))
792 *OS << ' ';
793
794
795 for (; ColNo > 1; --ColNo)
796 *OS << ' ';
797 }
798 } else {
799
800
801
802
803
804
805 if (RequireSpace || (!MinimizeWhitespace && Tok.hasLeadingSpace()) ||
806 ((EmittedTokensOnThisLine || EmittedDirectiveOnThisLine) &&
807 AvoidConcat(PrevPrevTok, PrevTok, Tok)))
808 *OS << ' ';
809 }
810
811 PrevPrevTok = PrevTok;
812 PrevTok = Tok;
813}
814
815void PrintPPOutputPPCallbacks::HandleNewlinesInToken(const char *TokStr,
816 unsigned Len) {
817 unsigned NumNewlines = 0;
818 for (; Len; --Len, ++TokStr) {
819 if (*TokStr != '\n' &&
820 *TokStr != '\r')
821 continue;
822
823 ++NumNewlines;
824
825
826 if (Len != 1 &&
827 (TokStr[1] == '\n' || TokStr[1] == '\r') &&
828 TokStr[0] != TokStr[1]) {
829 ++TokStr;
830 --Len;
831 }
832 }
833
834 if (NumNewlines == 0) return;
835
836 CurLine += NumNewlines;
837}
838
839
840namespace {
841struct UnknownPragmaHandler : public PragmaHandler {
842 const char *Prefix;
843 PrintPPOutputPPCallbacks *Callbacks;
844
845
846 bool ShouldExpandTokens;
847
848 UnknownPragmaHandler(const char *prefix, PrintPPOutputPPCallbacks *callbacks,
849 bool RequireTokenExpansion)
850 : Prefix(prefix), Callbacks(callbacks),
851 ShouldExpandTokens(RequireTokenExpansion) {}
853 Token &PragmaTok) override {
854
855
856 Callbacks->MoveToLine(PragmaTok.getLocation(), true);
857 Callbacks->OS->write(Prefix, strlen(Prefix));
858 Callbacks->setEmittedTokensOnThisLine();
859
860 if (ShouldExpandTokens) {
861
862
863 auto Toks = std::make_unique<Token[]>(1);
864 Toks[0] = PragmaTok;
865 PP.EnterTokenStream(std::move(Toks), 1,
866 false,
867 false);
868 PP.Lex(PragmaTok);
869 }
870
871
872 bool IsFirst = true;
873 while (PragmaTok.isNot(tok::eod)) {
874 Callbacks->HandleWhitespaceBeforeTok(PragmaTok, IsFirst,
875 true);
876 IsFirst = false;
877 std::string TokSpell = PP.getSpelling(PragmaTok);
878 Callbacks->OS->write(&TokSpell[0], TokSpell.size());
879 Callbacks->setEmittedTokensOnThisLine();
880
881 if (ShouldExpandTokens)
882 PP.Lex(PragmaTok);
883 else
885 }
886 Callbacks->setEmittedDirectiveOnThisLine();
887 }
888};
889}
890
891
893 PrintPPOutputPPCallbacks *Callbacks) {
894 bool DropComments = PP.getLangOpts().TraditionalCPP &&
896
897 bool IsStartOfLine = false;
898 char Buffer[256];
899 while (true) {
900
901
902
903
904
905
906
908
909 Callbacks->HandleWhitespaceBeforeTok(Tok, false,
910 !IsStartOfLine);
911
912 if (DropComments && Tok.is(tok::comment)) {
913
914
915
916 PP.Lex(Tok);
917 continue;
918 } else if (Tok.is(tok::annot_repl_input_end)) {
919
920 } else if (Tok.is(tok::eod)) {
921
922
923
924 PP.Lex(Tok);
925
926
927 IsStartOfLine = true;
928 continue;
929 } else if (Tok.is(tok::annot_module_include)) {
930
931
932 PP.Lex(Tok);
933 IsStartOfLine = true;
934 continue;
935 } else if (Tok.is(tok::annot_module_begin)) {
936
937
938
939
940
941
942 Callbacks->BeginModule(
944 PP.Lex(Tok);
945 IsStartOfLine = true;
946 continue;
947 } else if (Tok.is(tok::annot_module_end)) {
948 Callbacks->EndModule(
950 PP.Lex(Tok);
951 IsStartOfLine = true;
952 continue;
953 } else if (Tok.is(tok::annot_header_unit)) {
954
955
956
957
958
961 *Callbacks->OS << '"';
962 Callbacks->OS->write_escaped(Name);
963 *Callbacks->OS << '"';
964 } else if (Tok.is(tok::annot_embed)) {
965
966
967
968
969 assert(Callbacks->expandEmbedContents() &&
970 "did not expect an embed annotation");
973
974
975
976 bool PrintComma = false;
977 for (auto Iter = Data->BinaryData.begin(), End = Data->BinaryData.end();
979 if (PrintComma)
980 *Callbacks->OS << ", ";
981 *Callbacks->OS << static_cast<unsigned>(*Iter);
982 PrintComma = true;
983 }
985
986
987 PP.Lex(Tok);
988 continue;
990 *Callbacks->OS << II->getName();
994 } else if (Tok.getLength() < std::size(Buffer)) {
995 const char *TokPtr = Buffer;
996 unsigned Len = PP.getSpelling(Tok, TokPtr);
997 Callbacks->OS->write(TokPtr, Len);
998
999
1000
1001
1002
1003
1004 if (Tok.getKind() == tok::comment || Tok.getKind() == tok::unknown)
1005 Callbacks->HandleNewlinesInToken(TokPtr, Len);
1006 if (Tok.is(tok::comment) && Len >= 2 && TokPtr[0] == '/' &&
1007 TokPtr[1] == '/') {
1008
1009
1010 Callbacks->setEmittedDirectiveOnThisLine();
1011 }
1012 } else {
1014 Callbacks->OS->write(S.data(), S.size());
1015
1016
1017
1018 if (Tok.getKind() == tok::comment || Tok.getKind() == tok::unknown)
1019 Callbacks->HandleNewlinesInToken(S.data(), S.size());
1020 if (Tok.is(tok::comment) && S.size() >= 2 && S[0] == '/' && S[1] == '/') {
1021
1022
1023 Callbacks->setEmittedDirectiveOnThisLine();
1024 }
1025 }
1026 Callbacks->setEmittedTokensOnThisLine();
1027 IsStartOfLine = false;
1028
1029 if (Tok.is(tok::eof) || Tok.is(tok::annot_repl_input_end))
1030 break;
1031
1032 PP.Lex(Tok);
1033
1034 for (unsigned I = 0, Skip = Callbacks->GetNumToksToSkip(); I < Skip; ++I)
1035 PP.Lex(Tok);
1036 Callbacks->ResetSkipToks();
1037 }
1038}
1039
1040typedef std::pair<const IdentifierInfo *, MacroInfo *> id_macro_pair;
1042 return LHS->first->getName().compare(RHS->first->getName());
1043}
1044
1046
1048
1049
1050
1052
1054
1057 I != E; ++I) {
1058 auto *MD = I->second.getLatest();
1059 if (MD && MD->isDefined())
1061 }
1062 llvm::array_pod_sort(MacrosByID.begin(), MacrosByID.end(), MacroIDCompare);
1063
1064 for (unsigned i = 0, e = MacrosByID.size(); i != e; ++i) {
1065 MacroInfo &MI = *MacrosByID[i].second;
1066
1068
1070 *OS << '\n';
1071 }
1072}
1073
1074
1075
1078
1080 assert(Opts.ShowMacros && "Not yet implemented!");
1082 return;
1083 }
1084
1085
1086
1088
1089 PrintPPOutputPPCallbacks *Callbacks = new PrintPPOutputPPCallbacks(
1094
1095
1096
1097
1098 std::unique_ptr MicrosoftExtHandler(
1099 new UnknownPragmaHandler(
1100 "#pragma", Callbacks,
1101 PP.getLangOpts().MicrosoftExt));
1102
1103 std::unique_ptr GCCHandler(new UnknownPragmaHandler(
1104 "#pragma GCC", Callbacks,
1105 PP.getLangOpts().MicrosoftExt));
1106
1107 std::unique_ptr ClangHandler(new UnknownPragmaHandler(
1108 "#pragma clang", Callbacks,
1109 PP.getLangOpts().MicrosoftExt));
1110
1114
1115
1116
1117
1118
1119
1120 std::unique_ptr OpenMPHandler(
1121 new UnknownPragmaHandler("#pragma omp", Callbacks,
1122 true));
1124
1125 PP.addPPCallbacks(std::unique_ptr(Callbacks));
1126
1127
1131
1132
1133
1134
1137 do {
1138 PP.Lex(Tok);
1140 break;
1141
1144 break;
1145
1146 if (strcmp(PLoc.getFilename(), ""))
1147 break;
1148 } while (true);
1149
1150
1152 *OS << '\n';
1153
1154
1155
1160}
Defines the Diagnostic-related interfaces.
llvm::MachO::FileType FileType
Defines the clang::MacroInfo and clang::MacroDirective classes.
Defines the PPCallbacks interface.
Defines the clang::Preprocessor interface.
std::pair< const IdentifierInfo *, MacroInfo * > id_macro_pair
static void DoPrintMacros(Preprocessor &PP, raw_ostream *OS)
static void PrintMacroDefinition(const IdentifierInfo &II, const MacroInfo &MI, Preprocessor &PP, raw_ostream *OS)
PrintMacroDefinition - Print a macro definition in a form that will be properly accepted back as a de...
static int MacroIDCompare(const id_macro_pair *LHS, const id_macro_pair *RHS)
static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok, PrintPPOutputPPCallbacks *Callbacks)
static void outputPrintable(raw_ostream *OS, StringRef Str)
Defines the SourceManager interface.
Represents a character-granular source range.
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
One of these records is kept for each identifier that is lexed.
tok::PPKeywordKind getPPKeywordID() const
Return the preprocessor keyword ID for this identifier.
StringRef getName() const
Return the actual identifier string.
Record the location of an inclusion directive, such as an #include or #import statement.
A description of the current definition of a macro.
MacroInfo * getMacroInfo() const
Get the MacroInfo that should be used for this definition.
Encapsulates changes to the "macros namespace" (the location where the macro name became active,...
const MacroInfo * getMacroInfo() const
Encapsulates the data about a macro definition (e.g.
bool isUsed() const
Return false if this macro is defined in the main file and has not yet been used.
bool isFunctionLike() const
const_tokens_iterator tokens_begin() const
param_iterator param_begin() const
bool isBuiltinMacro() const
Return true if this macro requires processing before expansion.
IdentifierInfo *const * param_iterator
Parameters - The list of parameters for a function-like macro.
SourceLocation getDefinitionLoc() const
Return the location that the macro was defined at.
bool tokens_empty() const
param_iterator param_end() const
ArrayRef< Token > tokens() const
bool isGNUVarargs() const
Describes a module or submodule.
std::string getFullModuleName(bool AllowStringLiterals=false) const
Retrieve the full name of this module, including the path from its top-level module.
This interface provides a way to observe the actions of the preprocessor as it does its thing.
virtual void PragmaExecCharsetPop(SourceLocation Loc)
Callback invoked when a #pragma execution_character_set(pop) directive is read.
virtual void PragmaDiagnosticPush(SourceLocation Loc, StringRef Namespace)
Callback invoked when a #pragma gcc diagnostic push directive is read.
virtual void PragmaWarning(SourceLocation Loc, PragmaWarningSpecifier WarningSpec, ArrayRef< int > Ids)
virtual void PragmaDebug(SourceLocation Loc, StringRef DebugType)
Callback invoked when a #pragma clang __debug directive is read.
virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason, SrcMgr::CharacteristicKind FileType, FileID PrevFID=FileID())
Callback invoked whenever a source file is entered or exited.
virtual void MacroUndefined(const Token &MacroNameTok, const MacroDefinition &MD, const MacroDirective *Undef)
Hook called whenever a macro #undef is seen.
virtual void MacroDefined(const Token &MacroNameTok, const MacroDirective *MD)
Hook called whenever a macro definition is seen.
virtual void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace, diag::Severity mapping, StringRef Str)
Callback invoked when a #pragma gcc diagnostic directive is read.
virtual void PragmaAssumeNonNullEnd(SourceLocation Loc)
Callback invoked when a #pragma clang assume_nonnull end directive is read.
virtual void PragmaAssumeNonNullBegin(SourceLocation Loc)
Callback invoked when a #pragma clang assume_nonnull begin directive is read.
virtual void EmbedDirective(SourceLocation HashLoc, StringRef FileName, bool IsAngled, OptionalFileEntryRef File, const LexEmbedParametersResult &Params)
Callback invoked whenever an embed directive has been processed, regardless of whether the embed will...
virtual void Ident(SourceLocation Loc, StringRef str)
Callback invoked when a #ident or #sccs directive is read.
virtual void PragmaMessage(SourceLocation Loc, StringRef Namespace, PragmaMessageKind Kind, StringRef Str)
Callback invoked when a #pragma message directive is read.
virtual void PragmaExecCharsetPush(SourceLocation Loc, StringRef Str)
Callback invoked when a #pragma execution_character_set(push) directive is read.
virtual void PragmaDiagnosticPop(SourceLocation Loc, StringRef Namespace)
Callback invoked when a #pragma gcc diagnostic pop directive is read.
virtual void PragmaWarningPop(SourceLocation Loc)
Callback invoked when a #pragma warning(pop) directive is read.
virtual void PragmaWarningPush(SourceLocation Loc, int Level)
Callback invoked when a #pragma warning(push) directive is read.
PragmaHandler - Instances of this interface defined to handle the various pragmas that the language f...
virtual void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, Token &FirstToken)=0
PreprocessorOutputOptions - Options for controlling the C preprocessor output (e.g....
unsigned UseLineDirectives
Use #line instead of GCC-style # N.
unsigned ShowMacros
Print macro definitions.
unsigned ShowIncludeDirectives
Print includes, imports etc. within preprocessed output.
unsigned ShowMacroComments
Show comments, even in macros.
unsigned ShowCPP
Print normal preprocessed output.
unsigned MinimizeWhitespace
Ignore whitespace from input.
unsigned KeepSystemIncludes
Do not expand system headers.
unsigned ShowComments
Show comments.
unsigned ShowEmbedDirectives
Print embeds, etc. within preprocessed.
unsigned ShowLineMarkers
Show #line markers.
unsigned DirectivesOnly
Process directives but do not expand macros.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
void IgnorePragmas()
Install empty handlers for all pragmas (making them ignored).
macro_iterator macro_begin(bool IncludeExternalMacros=true) const
void Lex(Token &Result)
Lex the next token for this preprocessor.
void addPPCallbacks(std::unique_ptr< PPCallbacks > C)
void EnterMainSourceFile()
Enter the specified FileID as the main source file, which implicitly adds the builtin defines etc.
macro_iterator macro_end(bool IncludeExternalMacros=true) const
SourceManager & getSourceManager() const
bool getCommentRetentionState() const
void SetMacroExpansionOnlyInDirectives()
Disables macro expansion everywhere except for preprocessor directives.
MacroMap::const_iterator macro_iterator
void LexUnexpandedToken(Token &Result)
Just like Lex, but disables macro expansion of identifier tokens.
void AddPragmaHandler(StringRef Namespace, PragmaHandler *Handler)
Add the specified pragma handler to this preprocessor.
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 ...
const LangOptions & getLangOpts() const
void LexTokensUntilEOF(std::vector< Token > *Tokens=nullptr)
Lex all tokens for this preprocessor until (and excluding) end of file.
void SetCommentRetentionState(bool KeepComments, bool KeepMacroComments)
Control whether the preprocessor retains comments in output.
void RemovePragmaHandler(StringRef Namespace, PragmaHandler *Handler)
Remove the specific pragma handler from this preprocessor.
Represents an unpacked "presumed" location which can be presented to the user.
const char * getFilename() const
Return the presumed filename of this location.
unsigned getLine() const
Return the presumed line number of this location.
bool isInvalid() const
Return true if this object is invalid or uninitialized.
SourceLocation getIncludeLoc() const
Return the presumed include location of this location.
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
This class handles loading and caching of source files into memory.
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.
TokenConcatenation class, which answers the question of "Is it safe to emit two tokens without a whit...
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...
Token - This structure provides full information about a lexed token.
IdentifierInfo * getIdentifierInfo() const
bool isLiteral() const
Return true if this is a "literal", like a numeric constant, string, etc.
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file.
unsigned getLength() const
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)) {....
void * getAnnotationValue() const
tok::TokenKind getKind() const
bool isAtStartOfLine() const
isAtStartOfLine - Return true if this token is at the start of a line.
bool hasLeadingSpace() const
Return true if this token has whitespace before it.
bool isNot(tok::TokenKind K) const
bool isAnnotation() const
Return true if this is any of tok::annot_* kind tokens.
void startToken()
Reset all flags to cleared.
bool needsCleaning() const
Return true if this token has trigraphs or escaped newlines in it.
const char * getLiteralData() const
getLiteralData - For a literal token (numeric constant, string, etc), this returns a pointer to the s...
CharacteristicKind
Indicates whether a file or directory holds normal user code, system code, or system code which is im...
bool isSystem(CharacteristicKind CK)
Determine whether a file / directory characteristic is for system code.
Severity
Enum values that allow the client to map NOTEs, WARNINGs, and EXTENSIONs to either Ignore (nothing),...
The JSON file list parser is used to communicate input to InstallAPI.
LLVM_READONLY bool isPrintable(unsigned char c)
Return true if this character is an ASCII printable character; that is, a character that should take ...
void DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream *OS, const PreprocessorOutputOptions &Opts)
DoPrintPreprocessedInput - Implement -E mode.
const FunctionProtoType * T
Helper class to shuttle information about #embed directives from the preprocessor to the parser throu...
std::optional< PPEmbedParameterIfEmpty > MaybeIfEmptyParam
std::optional< PPEmbedParameterOffset > MaybeOffsetParam
std::optional< PPEmbedParameterLimit > MaybeLimitParam
std::optional< PPEmbedParameterSuffix > MaybeSuffixParam
std::optional< PPEmbedParameterPrefix > MaybePrefixParam
Describes how and where the pragma was introduced.