@@ -97,6 +97,9 @@ class PrintPPOutputPPCallbacks : public PPCallbacks {
97
97
bool IsFirstFileEntered;
98
98
bool MinimizeWhitespace;
99
99
bool DirectivesOnly;
100
+ bool KeepSystemIncludes;
101
+ raw_ostream *OrigOS;
102
+ std::unique_ptr<llvm::raw_null_ostream> NullOS;
100
103
101
104
Token PrevTok;
102
105
Token PrevPrevTok;
@@ -105,19 +108,22 @@ class PrintPPOutputPPCallbacks : public PPCallbacks {
105
108
PrintPPOutputPPCallbacks (Preprocessor &pp, raw_ostream *os, bool lineMarkers,
106
109
bool defines, bool DumpIncludeDirectives,
107
110
bool UseLineDirectives, bool MinimizeWhitespace,
108
- bool DirectivesOnly)
111
+ bool DirectivesOnly, bool KeepSystemIncludes )
109
112
: PP(pp), SM(PP.getSourceManager()), ConcatInfo(PP), OS(os),
110
113
DisableLineMarkers (lineMarkers), DumpDefines(defines),
111
114
DumpIncludeDirectives(DumpIncludeDirectives),
112
115
UseLineDirectives(UseLineDirectives),
113
- MinimizeWhitespace(MinimizeWhitespace), DirectivesOnly(DirectivesOnly) {
116
+ MinimizeWhitespace(MinimizeWhitespace), DirectivesOnly(DirectivesOnly),
117
+ KeepSystemIncludes(KeepSystemIncludes), OrigOS(os) {
114
118
CurLine = 0 ;
115
119
CurFilename += " <uninit>" ;
116
120
EmittedTokensOnThisLine = false ;
117
121
EmittedDirectiveOnThisLine = false ;
118
122
FileType = SrcMgr::C_User;
119
123
Initialized = false ;
120
124
IsFirstFileEntered = false ;
125
+ if (KeepSystemIncludes)
126
+ NullOS = std::make_unique<llvm::raw_null_ostream>();
121
127
122
128
PrevTok.startToken ();
123
129
PrevPrevTok.startToken ();
@@ -350,6 +356,10 @@ void PrintPPOutputPPCallbacks::FileChanged(SourceLocation Loc,
350
356
351
357
CurLine = NewLine;
352
358
359
+ // In KeepSystemIncludes mode, redirect OS as needed.
360
+ if (KeepSystemIncludes && (isSystem (FileType) != isSystem (NewFileType)))
361
+ OS = isSystem (FileType) ? OrigOS : NullOS.get ();
362
+
353
363
CurFilename.clear ();
354
364
CurFilename += UserLoc.getFilename ();
355
365
FileType = NewFileType;
@@ -394,14 +404,16 @@ void PrintPPOutputPPCallbacks::InclusionDirective(
394
404
StringRef SearchPath, StringRef RelativePath, const Module *Imported,
395
405
SrcMgr::CharacteristicKind FileType) {
396
406
// 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)) ) {
399
409
MoveToLine (HashLoc, /* RequireStartOfLine=*/ true );
400
410
const std::string TokenText = PP.getSpelling (IncludeTok);
401
411
assert (!TokenText.empty ());
402
412
*OS << " #" << TokenText << " "
403
413
<< (IsAngled ? ' <' : ' "' ) << FileName << (IsAngled ? ' >' : ' "' )
404
- << " /* clang -E -dI */" ;
414
+ << " /* clang -E "
415
+ << (DumpIncludeDirectives ? " -dI" : " -fkeep-system-includes" )
416
+ << " */" ;
405
417
setEmittedDirectiveOnThisLine ();
406
418
}
407
419
@@ -412,7 +424,8 @@ void PrintPPOutputPPCallbacks::InclusionDirective(
412
424
case tok::pp_import:
413
425
case tok::pp_include_next:
414
426
MoveToLine (HashLoc, /* RequireStartOfLine=*/ true );
415
- *OS << " #pragma clang module import " << Imported->getFullModuleName (true )
427
+ *OS << " #pragma clang module import "
428
+ << Imported->getFullModuleName (true )
416
429
<< " /* clang -E: implicit import for "
417
430
<< " #" << PP.getSpelling (IncludeTok) << " "
418
431
<< (IsAngled ? ' <' : ' "' ) << FileName << (IsAngled ? ' >' : ' "' )
@@ -794,8 +807,7 @@ struct UnknownPragmaHandler : public PragmaHandler {
794
807
795
808
796
809
static void PrintPreprocessedTokens (Preprocessor &PP, Token &Tok,
797
- PrintPPOutputPPCallbacks *Callbacks,
798
- raw_ostream *OS) {
810
+ PrintPPOutputPPCallbacks *Callbacks) {
799
811
bool DropComments = PP.getLangOpts ().TraditionalCPP &&
800
812
!PP.getCommentRetentionState ();
801
813
@@ -863,22 +875,22 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok,
863
875
// components. We don't have a good way to round-trip those.
864
876
Module *M = reinterpret_cast <Module *>(Tok.getAnnotationValue ());
865
877
std::string Name = M->getFullModuleName ();
866
- OS->write (Name.data (), Name.size ());
878
+ Callbacks-> OS ->write (Name.data (), Name.size ());
867
879
Callbacks->HandleNewlinesInToken (Name.data (), Name.size ());
868
880
} else if (Tok.isAnnotation ()) {
869
881
// Ignore annotation tokens created by pragmas - the pragmas themselves
870
882
// will be reproduced in the preprocessed output.
871
883
PP.Lex (Tok);
872
884
continue ;
873
885
} else if (IdentifierInfo *II = Tok.getIdentifierInfo ()) {
874
- *OS << II->getName ();
886
+ *Callbacks-> OS << II->getName ();
875
887
} else if (Tok.isLiteral () && !Tok.needsCleaning () &&
876
888
Tok.getLiteralData ()) {
877
- OS->write (Tok.getLiteralData (), Tok.getLength ());
889
+ Callbacks-> OS ->write (Tok.getLiteralData (), Tok.getLength ());
878
890
} else if (Tok.getLength () < std::size (Buffer)) {
879
891
const char *TokPtr = Buffer;
880
892
unsigned Len = PP.getSpelling (Tok, TokPtr);
881
- OS->write (TokPtr, Len);
893
+ Callbacks-> OS ->write (TokPtr, Len);
882
894
883
895
// Tokens that can contain embedded newlines need to adjust our current
884
896
// line number.
@@ -895,7 +907,7 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok,
895
907
}
896
908
} else {
897
909
std::string S = PP.getSpelling (Tok);
898
- OS->write (S.data (), S.size ());
910
+ Callbacks-> OS ->write (S.data (), S.size ());
899
911
900
912
// Tokens that can contain embedded newlines need to adjust our current
901
913
// line number.
@@ -970,7 +982,7 @@ void clang::DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream *OS,
970
982
PrintPPOutputPPCallbacks *Callbacks = new PrintPPOutputPPCallbacks (
971
983
PP, OS, !Opts.ShowLineMarkers , Opts.ShowMacros ,
972
984
Opts.ShowIncludeDirectives , Opts.UseLineDirectives ,
973
- Opts.MinimizeWhitespace , Opts.DirectivesOnly );
985
+ Opts.MinimizeWhitespace , Opts.DirectivesOnly , Opts. KeepSystemIncludes );
974
986
975
987
// Expand macros in pragmas with -fms-extensions. The assumption is that
976
988
// the majority of pragmas in such a file will be Microsoft pragmas.
@@ -1028,7 +1040,7 @@ void clang::DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream *OS,
1028
1040
} while (true );
1029
1041
1030
1042
// Read all the preprocessed tokens, printing them out to the stream.
1031
- PrintPreprocessedTokens (PP, Tok, Callbacks, OS );
1043
+ PrintPreprocessedTokens (PP, Tok, Callbacks);
1032
1044
*OS << ' \n ' ;
1033
1045
1034
1046
// Remove the handlers we just added to leave the preprocessor in a sane state
0 commit comments