@@ -97,6 +97,9 @@ class PrintPPOutputPPCallbacks : public PPCallbacks {
9797 bool IsFirstFileEntered;
9898 bool MinimizeWhitespace;
9999 bool DirectivesOnly;
100+ bool KeepSystemIncludes;
101+ raw_ostream *OrigOS;
102+ std::unique_ptr<llvm::raw_null_ostream> NullOS;
100103
101104 Token PrevTok;
102105 Token PrevPrevTok;
@@ -105,19 +108,22 @@ class PrintPPOutputPPCallbacks : public PPCallbacks {
105108 PrintPPOutputPPCallbacks (Preprocessor &pp, raw_ostream *os, bool lineMarkers,
106109 bool defines, bool DumpIncludeDirectives,
107110 bool UseLineDirectives, bool MinimizeWhitespace,
108- bool DirectivesOnly)
111+ bool DirectivesOnly, bool KeepSystemIncludes )
109112 : PP(pp), SM(PP.getSourceManager()), ConcatInfo(PP), OS(os),
110113 DisableLineMarkers (lineMarkers), DumpDefines(defines),
111114 DumpIncludeDirectives(DumpIncludeDirectives),
112115 UseLineDirectives(UseLineDirectives),
113- MinimizeWhitespace(MinimizeWhitespace), DirectivesOnly(DirectivesOnly) {
116+ MinimizeWhitespace(MinimizeWhitespace), DirectivesOnly(DirectivesOnly),
117+ KeepSystemIncludes(KeepSystemIncludes), OrigOS(os) {
114118 CurLine = 0 ;
115119 CurFilename += " <uninit>" ;
116120 EmittedTokensOnThisLine = false ;
117121 EmittedDirectiveOnThisLine = false ;
118122 FileType = SrcMgr::C_User;
119123 Initialized = false ;
120124 IsFirstFileEntered = false ;
125+ if (KeepSystemIncludes)
126+ NullOS = std::make_unique<llvm::raw_null_ostream>();
121127
122128 PrevTok.startToken ();
123129 PrevPrevTok.startToken ();
@@ -350,6 +356,10 @@ void PrintPPOutputPPCallbacks::FileChanged(SourceLocation Loc,
350356
351357 CurLine = NewLine;
352358
359+ // In KeepSystemIncludes mode, redirect OS as needed.
360+ if (KeepSystemIncludes && (isSystem (FileType) != isSystem (NewFileType)))
361+ OS = isSystem (FileType) ? OrigOS : NullOS.get ();
362+
353363 CurFilename.clear ();
354364 CurFilename += UserLoc.getFilename ();
355365 FileType = NewFileType;
@@ -394,14 +404,16 @@ void PrintPPOutputPPCallbacks::InclusionDirective(
394404 StringRef SearchPath, StringRef RelativePath, const Module *Imported,
395405 SrcMgr::CharacteristicKind FileType) {
396406 // In -dI mode, dump #include directives prior to dumping their content or
397- // interpretation.
398- if (DumpIncludeDirectives) {
407+ // interpretation. Similar for -fkeep-system-includes.
408+ if (DumpIncludeDirectives || (KeepSystemIncludes && isSystem (FileType)) ) {
399409 MoveToLine (HashLoc, /* RequireStartOfLine=*/ true );
400410 const std::string TokenText = PP.getSpelling (IncludeTok);
401411 assert (!TokenText.empty ());
402412 *OS << " #" << TokenText << " "
403413 << (IsAngled ? ' <' : ' "' ) << FileName << (IsAngled ? ' >' : ' "' )
404- << " /* clang -E -dI */" ;
414+ << " /* clang -E "
415+ << (DumpIncludeDirectives ? " -dI" : " -fkeep-system-includes" )
416+ << " */" ;
405417 setEmittedDirectiveOnThisLine ();
406418 }
407419
@@ -412,7 +424,8 @@ void PrintPPOutputPPCallbacks::InclusionDirective(
412424 case tok::pp_import:
413425 case tok::pp_include_next:
414426 MoveToLine (HashLoc, /* RequireStartOfLine=*/ true );
415- *OS << " #pragma clang module import " << Imported->getFullModuleName (true )
427+ *OS << " #pragma clang module import "
428+ << Imported->getFullModuleName (true )
416429 << " /* clang -E: implicit import for "
417430 << " #" << PP.getSpelling (IncludeTok) << " "
418431 << (IsAngled ? ' <' : ' "' ) << FileName << (IsAngled ? ' >' : ' "' )
@@ -794,8 +807,7 @@ struct UnknownPragmaHandler : public PragmaHandler {
794807
795808
796809static void PrintPreprocessedTokens (Preprocessor &PP, Token &Tok,
797- PrintPPOutputPPCallbacks *Callbacks,
798- raw_ostream *OS) {
810+ PrintPPOutputPPCallbacks *Callbacks) {
799811 bool DropComments = PP.getLangOpts ().TraditionalCPP &&
800812 !PP.getCommentRetentionState ();
801813
@@ -863,22 +875,22 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok,
863875 // components. We don't have a good way to round-trip those.
864876 Module *M = reinterpret_cast <Module *>(Tok.getAnnotationValue ());
865877 std::string Name = M->getFullModuleName ();
866- OS->write (Name.data (), Name.size ());
878+ Callbacks-> OS ->write (Name.data (), Name.size ());
867879 Callbacks->HandleNewlinesInToken (Name.data (), Name.size ());
868880 } else if (Tok.isAnnotation ()) {
869881 // Ignore annotation tokens created by pragmas - the pragmas themselves
870882 // will be reproduced in the preprocessed output.
871883 PP.Lex (Tok);
872884 continue ;
873885 } else if (IdentifierInfo *II = Tok.getIdentifierInfo ()) {
874- *OS << II->getName ();
886+ *Callbacks-> OS << II->getName ();
875887 } else if (Tok.isLiteral () && !Tok.needsCleaning () &&
876888 Tok.getLiteralData ()) {
877- OS->write (Tok.getLiteralData (), Tok.getLength ());
889+ Callbacks-> OS ->write (Tok.getLiteralData (), Tok.getLength ());
878890 } else if (Tok.getLength () < std::size (Buffer)) {
879891 const char *TokPtr = Buffer;
880892 unsigned Len = PP.getSpelling (Tok, TokPtr);
881- OS->write (TokPtr, Len);
893+ Callbacks-> OS ->write (TokPtr, Len);
882894
883895 // Tokens that can contain embedded newlines need to adjust our current
884896 // line number.
@@ -895,7 +907,7 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok,
895907 }
896908 } else {
897909 std::string S = PP.getSpelling (Tok);
898- OS->write (S.data (), S.size ());
910+ Callbacks-> OS ->write (S.data (), S.size ());
899911
900912 // Tokens that can contain embedded newlines need to adjust our current
901913 // line number.
@@ -970,7 +982,7 @@ void clang::DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream *OS,
970982 PrintPPOutputPPCallbacks *Callbacks = new PrintPPOutputPPCallbacks (
971983 PP, OS, !Opts.ShowLineMarkers , Opts.ShowMacros ,
972984 Opts.ShowIncludeDirectives , Opts.UseLineDirectives ,
973- Opts.MinimizeWhitespace , Opts.DirectivesOnly );
985+ Opts.MinimizeWhitespace , Opts.DirectivesOnly , Opts. KeepSystemIncludes );
974986
975987 // Expand macros in pragmas with -fms-extensions. The assumption is that
976988 // the majority of pragmas in such a file will be Microsoft pragmas.
@@ -1028,7 +1040,7 @@ void clang::DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream *OS,
10281040 } while (true );
10291041
10301042 // Read all the preprocessed tokens, printing them out to the stream.
1031- PrintPreprocessedTokens (PP, Tok, Callbacks, OS );
1043+ PrintPreprocessedTokens (PP, Tok, Callbacks);
10321044 *OS << ' \n ' ;
10331045
10341046 // Remove the handlers we just added to leave the preprocessor in a sane state
0 commit comments