diff --git a/llvm.changes b/llvm.changes index 835f9b9..bfd0783 100644 --- a/llvm.changes +++ b/llvm.changes @@ -1,3 +1,8 @@ +------------------------------------------------------------------- +Tue May 8 08:21:42 UTC 2012 - llunak@suse.com + +- make -rewrite-includes support -C and -CC + ------------------------------------------------------------------- Thu May 3 07:32:06 UTC 2012 - llunak@suse.com diff --git a/llvm.spec b/llvm.spec index 1c06e0c..dd23d2b 100644 --- a/llvm.spec +++ b/llvm.spec @@ -134,6 +134,8 @@ This package contains vim plugins for LLVM like syntax highlighting. %patch5 -p1 %endif %patch6 -p0 +# sle11 patch cannot create empty files +touch tools/clang/test/Frontend/Inputs/rewrite-includes9.h # We hardcode i586 rm tools/clang/test/Driver/x86_features.c diff --git a/rewrite-includes.patch b/rewrite-includes.patch index 0df143c..215629e 100644 --- a/rewrite-includes.patch +++ b/rewrite-includes.patch @@ -1,4 +1,4 @@ -diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td +diff --git tools/clang/include/clang/Driver/CC1Options.td tools/clang/include/clang/Driver/CC1Options.td index 83c988a..b278082 100644 --- tools/clang/include/clang/Driver/CC1Options.td +++ tools/clang/include/clang/Driver/CC1Options.td @@ -11,7 +11,7 @@ index 83c988a..b278082 100644 def migrate : Flag<"-migrate">, HelpText<"Migrate source code">; } -diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h +diff --git tools/clang/include/clang/Frontend/FrontendOptions.h tools/clang/include/clang/Frontend/FrontendOptions.h index 888388c..78d3adf 100644 --- tools/clang/include/clang/Frontend/FrontendOptions.h +++ tools/clang/include/clang/Frontend/FrontendOptions.h @@ -23,7 +23,7 @@ index 888388c..78d3adf 100644 RewriteObjC, ///< ObjC->C Rewriter. RewriteTest, ///< Rewriter playground RunAnalysis, ///< Run one or more source code analyses. -diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h +diff --git tools/clang/include/clang/Lex/Preprocessor.h tools/clang/include/clang/Lex/Preprocessor.h index 055008f..638b4aa 100644 --- tools/clang/include/clang/Lex/Preprocessor.h +++ tools/clang/include/clang/Lex/Preprocessor.h @@ -54,7 +54,7 @@ index 055008f..638b4aa 100644 /// LookAhead - This peeks ahead N tokens and returns that token without /// consuming any tokens. LookAhead(0) returns the next token that would be /// returned by Lex(), LookAhead(1) returns the token after it, etc. This -diff --git a/include/clang/Rewrite/FrontendActions.h b/include/clang/Rewrite/FrontendActions.h +diff --git tools/clang/include/clang/Rewrite/FrontendActions.h tools/clang/include/clang/Rewrite/FrontendActions.h index 6e9ecac..ea876d9 100644 --- tools/clang/include/clang/Rewrite/FrontendActions.h +++ tools/clang/include/clang/Rewrite/FrontendActions.h @@ -70,7 +70,7 @@ index 6e9ecac..ea876d9 100644 } // end namespace clang #endif -diff --git a/include/clang/Rewrite/Rewriters.h b/include/clang/Rewrite/Rewriters.h +diff --git tools/clang/include/clang/Rewrite/Rewriters.h tools/clang/include/clang/Rewrite/Rewriters.h index 203b9bc..9704fe3 100644 --- tools/clang/include/clang/Rewrite/Rewriters.h +++ tools/clang/include/clang/Rewrite/Rewriters.h @@ -92,7 +92,7 @@ index 203b9bc..9704fe3 100644 } // end namespace clang #endif -diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp +diff --git tools/clang/lib/Frontend/CompilerInvocation.cpp tools/clang/lib/Frontend/CompilerInvocation.cpp index 4c5b063..4e46973 100644 --- tools/clang/lib/Frontend/CompilerInvocation.cpp +++ tools/clang/lib/Frontend/CompilerInvocation.cpp @@ -113,7 +113,7 @@ index 4c5b063..4e46973 100644 case OPT_rewrite_objc: Opts.ProgramAction = frontend::RewriteObjC; break; case OPT_rewrite_test: -diff --git a/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/lib/FrontendTool/ExecuteCompilerInvocation.cpp +diff --git tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp index 07d2b8d..49d0bb8 100644 --- tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -125,7 +125,7 @@ index 07d2b8d..49d0bb8 100644 case RewriteObjC: return new RewriteObjCAction(); case RewriteTest: return new RewriteTestAction(); case RunAnalysis: return new ento::AnalysisAction(); -diff --git a/lib/Lex/Lexer.cpp b/lib/Lex/Lexer.cpp +diff --git tools/clang/lib/Lex/Lexer.cpp tools/clang/lib/Lex/Lexer.cpp index 535a852..aa424b4 100644 --- tools/clang/lib/Lex/Lexer.cpp +++ tools/clang/lib/Lex/Lexer.cpp @@ -148,7 +148,7 @@ index 535a852..aa424b4 100644 // Since we consumed a newline, we are back at the start of a line. IsAtStartOfLine = true; -diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp +diff --git tools/clang/lib/Lex/PPDirectives.cpp tools/clang/lib/Lex/PPDirectives.cpp index 625a204..29a8614 100644 --- tools/clang/lib/Lex/PPDirectives.cpp +++ tools/clang/lib/Lex/PPDirectives.cpp @@ -186,7 +186,7 @@ index 625a204..29a8614 100644 TryAgain: switch (Result.getKind()) { case tok::eod: -diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp +diff --git tools/clang/lib/Lex/Preprocessor.cpp tools/clang/lib/Lex/Preprocessor.cpp index 06e5685..f5d7a51 100644 --- tools/clang/lib/Lex/Preprocessor.cpp +++ tools/clang/lib/Lex/Preprocessor.cpp @@ -198,7 +198,7 @@ index 06e5685..f5d7a51 100644 InMacroArgs = false; InMacroArgPreExpansion = false; NumCachedTokenLexers = 0; -diff --git a/lib/Rewrite/CMakeLists.txt b/lib/Rewrite/CMakeLists.txt +diff --git tools/clang/lib/Rewrite/CMakeLists.txt tools/clang/lib/Rewrite/CMakeLists.txt index 2a05040..8070ba2 100644 --- tools/clang/lib/Rewrite/CMakeLists.txt +++ tools/clang/lib/Rewrite/CMakeLists.txt @@ -210,7 +210,7 @@ index 2a05040..8070ba2 100644 RewriteMacros.cpp RewriteModernObjC.cpp RewriteObjC.cpp -diff --git a/lib/Rewrite/FrontendActions.cpp b/lib/Rewrite/FrontendActions.cpp +diff --git tools/clang/lib/Rewrite/FrontendActions.cpp tools/clang/lib/Rewrite/FrontendActions.cpp index 1753325..e462671 100644 --- tools/clang/lib/Rewrite/FrontendActions.cpp +++ tools/clang/lib/Rewrite/FrontendActions.cpp @@ -226,12 +226,12 @@ index 1753325..e462671 100644 + + RewriteIncludesInInput(CI.getPreprocessor(), OS, CI.getPreprocessorOutputOpts()); +} -diff --git a/lib/Rewrite/RewriteIncludes.cpp b/lib/Rewrite/RewriteIncludes.cpp +diff --git tools/clang/lib/Rewrite/RewriteIncludes.cpp tools/clang/lib/Rewrite/RewriteIncludes.cpp new file mode 100644 -index 0000000..679e556 +index 0000000..54e09c5 --- /dev/null +++ tools/clang/lib/Rewrite/RewriteIncludes.cpp -@@ -0,0 +1,333 @@ +@@ -0,0 +1,542 @@ +//===--- RewriteIncludes.cpp - Rewrite includes into their expansions -----===// +// +// The LLVM Compiler Infrastructure @@ -257,7 +257,8 @@ index 0000000..679e556 + +namespace { + -+class IncludeRewriter : public PPCallbacks { ++/// Class representing the whole rewriting process and global data for it. ++class IncludeRewriter : public PPCallbacks, public CommentHandler { + /// Information about which #includes were actually performed, + /// created by preprocessor callbacks. + struct FileChange { @@ -273,10 +274,19 @@ index 0000000..679e556 + typedef std::map FileChangeMap; + FileChangeMap FileChanges; + unsigned LastInsertedFileChange; ++ /// From HandleComment() callback, two raw-encoded SourceLocation's, ++ /// will be sorted by the location. ++ typedef std::vector< std::pair > CommentRangeVector; ++ CommentRangeVector CommentRanges; ++ bool KeepAllComments; ++ /// Keep comments in lines which are not only comments (such comments may be ++ /// visible in error/warning messages). ++ bool KeepCommentsInCodeLines; ++ class File; +public: -+ IncludeRewriter(Preprocessor &PP, raw_ostream &OS, bool LineMarkers); -+ bool Process(FileID FileId, SrcMgr::CharacteristicKind Type); -+private: ++ IncludeRewriter(Preprocessor &PP, raw_ostream &OS, ++ const PreprocessorOutputOptions &Opts); ++ void Process(); + virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason, + SrcMgr::CharacteristicKind FileType, + FileID PrevFID); @@ -288,46 +298,68 @@ index 0000000..679e556 + SourceLocation EndLoc, + StringRef SearchPath, + StringRef RelativePath); -+ void WriteLineInfo(const char* Filename, int Line, -+ SrcMgr::CharacteristicKind Type, -+ const char* EOL, StringRef Extra = StringRef()); -+ void OutputContentUpTo(unsigned WriteEnd, unsigned& NextToWrite, -+ int& Lines, const char* EOL, -+ const MemoryBuffer* FromFile, -+ bool EnsureNewline = false); -+ void CommentOutDirective(Lexer& DirectivesLex, const Token& StartToken, -+ unsigned& NextToWrite, int& Lines, -+ const char* EOL, const MemoryBuffer* FromFile); ++ virtual bool HandleComment(Preprocessor &PP, SourceRange Comment); ++private: + const FileChange* FindFileChangeLocation(SourceLocation Loc) const; -+ StringRef NextIdentifierName(Lexer& RawLex, Token& RawToken); ++}; ++ ++/// Class representing the process of rewriting one source file. ++class IncludeRewriter::File { ++ IncludeRewriter* Rewriter; ++ Preprocessor &PP; ++ SourceManager &SM; ++ raw_ostream &OS; ++ FileID FileId; ++ SrcMgr::CharacteristicKind Type; ++ const MemoryBuffer *FromFile; ++ const char* FileName; ++ SourceLocation StartLocation; ++ bool Invalid; ++ const char* EOL; ++ OwningPtr RawLex; ++ // file position from which the content has not yet been copied to the output ++ unsigned NextToWrite; ++ // In case of KeepCommentsInCodeLines, this is actually the position from ++ // which the content has not yet been written, as in that mode the last line ++ // is output only if it's known there is some non-whitespace content in it. ++ unsigned NextToWriteLine; ++ // the next CommentRange item that processed file contents contain (i.e. ++ // the current source location is >= NextToWrite's source location) ++ unsigned NextCommentRange; ++ int Line; // current input file line number ++public: ++ File(IncludeRewriter* Rewriter, FileID FileId, ++ SrcMgr::CharacteristicKind Type); ++ bool Process(); ++private: ++ void WriteLineInfo(StringRef Extra = StringRef()); ++ void OutputContentUpTo(unsigned WriteEnd, bool EnsureNewline = false); ++ void CommentOutDirective(const Token& StartToken); ++ void OutputContentStripComments(unsigned WriteEnd, bool RemoveAll); ++ StringRef NextIdentifierName(Token& RawToken); ++ void DetectEOL(); ++ unsigned CountNewLines(const char* Pos, int Len); +}; + +} // end anonymous namespace + +IncludeRewriter::IncludeRewriter(Preprocessor &pp, raw_ostream &os, -+ bool lineMarkers) -+ : PP(pp), SM(PP.getSourceManager()), OS(os), -+ DisableLineMarkers(lineMarkers), LastInsertedFileChange(0) { ++ const PreprocessorOutputOptions &Opts) ++ : PP(pp) ++ , SM(PP.getSourceManager()) ++ , OS(os) ++ , DisableLineMarkers(!Opts.ShowLineMarkers) ++ , LastInsertedFileChange(0) ++ , KeepAllComments(false) ++ , KeepCommentsInCodeLines(false) { + // If we're in microsoft mode, use normal #line instead of line markers. + UseLineDirective = PP.getLangOpts().MicrosoftExt; -+} -+ -+void IncludeRewriter::WriteLineInfo(const char* Filename, int Line, -+ SrcMgr::CharacteristicKind Type, -+ const char* EOL, StringRef Extra) { -+ // Emit #line directives or GNU line markers depending on what mode we're in. -+ if (UseLineDirective) { -+ OS << "#line" << ' ' << Line << ' ' << '"' << Filename << '"'; -+ } else { -+ OS << '#' << ' ' << Line << ' ' << '"' << Filename << '"'; -+ if (!Extra.empty()) -+ OS << Extra; -+ if (Type == SrcMgr::C_System) -+ OS << " 3"; -+ else if (Type == SrcMgr::C_ExternCSystem) -+ OS << " 3 4"; -+ } -+ OS << EOL; ++ // TODO: This is interpreting the -C and -CC options a bit differently than ++ // plain -E does, either document it or create new options. ++ if (Opts.ShowMacroComments) ++ KeepAllComments = true; ++ else if (Opts.ShowComments) ++ KeepCommentsInCodeLines = true; +} + +/// FileChanged - Whenever the preprocessor enters or exits a #include file @@ -374,112 +406,70 @@ index 0000000..679e556 + return NULL; +} + -+inline unsigned CountNewLines(const char* Pos, int Len) { -+ const char* End = Pos + Len; -+ unsigned Lines = 0; -+ --Pos; -+ while ((Pos = static_cast(memchr(Pos + 1, '\n', End - Pos - 1)))) -+ ++Lines; -+ return Lines; ++bool IncludeRewriter::HandleComment(Preprocessor &, SourceRange Comment) { ++ CommentRanges.push_back( std::make_pair(Comment.getBegin().getRawEncoding(), ++ Comment.getEnd().getRawEncoding())); ++ return false; +} + -+static const char* DetectEOL(const MemoryBuffer* FromFile) { -+ // detect what line endings the file uses, so that added content does not mix -+ // the style -+ const char* Pos = strchr(FromFile->getBufferStart(), '\n'); -+ if (Pos == NULL) -+ return "\n"; -+ if (Pos+1 < FromFile->getBufferEnd() && *(Pos+1) == '\r') -+ return "\n\r"; -+ if (Pos-1 >= FromFile->getBufferStart() && *(Pos+1) == '\r') -+ return "\r\n"; -+ return "\n"; ++static bool CompareCommentRanges( const std::pair& left, ++ const std::pair& right ) { ++ return left.first < right.first; +} + -+/// Copies next not yet written file content up (and not including) to writeEnd. -+void IncludeRewriter::OutputContentUpTo(unsigned WriteEnd, -+ unsigned& NextToWrite, -+ int& Lines, const char* EOL, -+ const MemoryBuffer* FromFile, -+ bool EnsureNewline) { -+ if (WriteEnd > NextToWrite) { -+ OS.write(FromFile->getBufferStart() + NextToWrite, WriteEnd - NextToWrite); -+ // count lines manually, it's faster than getPresumedLoc() -+ Lines += CountNewLines(FromFile->getBufferStart() + NextToWrite, -+ WriteEnd - NextToWrite); -+ if (EnsureNewline) { -+ char LastChar = FromFile->getBufferStart()[WriteEnd - 1]; -+ if (LastChar != '\n' && LastChar != '\r') -+ OS << EOL; -+ } -+ NextToWrite = WriteEnd; -+ } ++void IncludeRewriter::Process() { ++// Sort comment ranges for easy finding of the next one from a given location. ++ std::sort(CommentRanges.begin(), CommentRanges.end(), CompareCommentRanges); ++ File MainFile(this, SM.getMainFileID(), SrcMgr::C_User); ++ MainFile.Process(); +} + -+void IncludeRewriter::CommentOutDirective(Lexer& DirectiveLex, -+ const Token& StartToken, -+ unsigned& NextToWrite, int& Lines, -+ const char* EOL, -+ const MemoryBuffer* FromFile) { -+ OutputContentUpTo(SM.getFileOffset(StartToken.getLocation()), NextToWrite, -+ Lines, EOL, FromFile); -+ Token DirectiveToken; -+ do { -+ DirectiveLex.LexFromRawLexer(DirectiveToken); -+ } while (!DirectiveToken.is(tok::eod) && DirectiveToken.isNot(tok::eof)); -+ OS << "#if 0 /* expanded by -rewrite-includes */" << EOL; -+ OutputContentUpTo(SM.getFileOffset(DirectiveToken.getLocation()) -+ + DirectiveToken.getLength(), NextToWrite, Lines, EOL, FromFile); -+ OS << "#endif /* expanded by -rewrite-includes */" << EOL; -+} + -+StringRef IncludeRewriter::NextIdentifierName(Lexer& RawLex, Token& RawToken) { -+ RawLex.LexFromRawLexer(RawToken); -+ if (RawToken.is(tok::raw_identifier)) -+ PP.LookUpIdentifierInfo(RawToken); -+ if (RawToken.is(tok::identifier)) -+ return RawToken.getIdentifierInfo()->getName(); -+ return StringRef(); -+} ++IncludeRewriter::File::File(IncludeRewriter* Rewriter, ++ FileID FileId, ++ SrcMgr::CharacteristicKind Type) ++ : Rewriter(Rewriter) ++ , PP(Rewriter->PP) ++ , SM(Rewriter->SM) ++ , OS(Rewriter->OS) ++ , FileId(FileId) ++ , Type(Type) ++ , Invalid(true) ++ , NextToWrite(0) ++ , NextToWriteLine(0) ++ , NextCommentRange(0) ++ , Line(1) { + -+bool IncludeRewriter::Process(FileID FileId, SrcMgr::CharacteristicKind Type) -+{ -+ bool Invalid; -+ const char* FileName = SM.getBufferName(SM.getLocForStartOfFile(FileId), -+ &Invalid); ++ StartLocation = SM.getLocForStartOfFile(FileId); ++ FileName = SM.getBufferName(StartLocation, &Invalid); + if (Invalid) -+ return false; ++ return; + + // Use a raw lexer to analyze the input file, incrementally copying parts of + // it and including content of included files recursively. -+ const MemoryBuffer *FromFile = SM.getBuffer(FileId); -+ Lexer RawLex(FileId, FromFile, PP.getSourceManager(), PP.getLangOpts()); -+ RawLex.SetCommentRetentionState(false); ++ FromFile = SM.getBuffer(FileId); ++ RawLex.reset( new Lexer(FileId, FromFile, PP.getSourceManager(), PP.getLangOpts())); ++ RawLex->SetCommentRetentionState(false); ++ DetectEOL(); + -+ const char* EOL = DetectEOL(FromFile); -+ -+ WriteLineInfo(FileName, 1, Type, EOL, " 1"); ++ WriteLineInfo(" 1"); ++} + ++bool IncludeRewriter::File::Process() ++{ ++ if (Invalid) ++ return false; + if (SM.getFileIDSize(FileId) == 0) + return true; + -+ // file position from which the content has not yet been copied to the output -+ unsigned NextToWrite = 0; -+ int Lines = 1; // current input file line number -+ + Token RawToken; -+ RawLex.LexFromRawLexer(RawToken); ++ RawLex->LexFromRawLexer(RawToken); + -+ // TODO: It might be beneficial to have a switch that removes content of lines -+ // that are irrevelant for compile, i.e. comments. Comments are usually -+ // a significant part of the resulting file and cleaning up such lines would -+ // significantly reduce the size of the resulting file without having any -+ // effect on any following usage (with the exception of human inspection). + while (RawToken.isNot(tok::eof)) { + if (RawToken.is(tok::hash) && RawToken.isAtStartOfLine()) { -+ RawLex.setParsingPreprocessorDirective(true); ++ RawLex->setParsingPreprocessorDirective(true); + Token HashToken = RawToken; -+ RawLex.LexFromRawLexer(RawToken); ++ RawLex->LexFromRawLexer(RawToken); + if (RawToken.is(tok::raw_identifier)) + PP.LookUpIdentifierInfo(RawToken); + if (RawToken.is(tok::identifier)) { @@ -491,40 +481,38 @@ index 0000000..679e556 + // (clang sometimes optimizes and does not repeatedly include some + // files even though it should, so all includes need to be + // commented, otherwise valid directives would be left in) -+ CommentOutDirective(RawLex, HashToken, NextToWrite, Lines, EOL, -+ FromFile); ++ CommentOutDirective(HashToken); + // fix up lineinfo, commenting out has added lines + bool NeedFixup = true; -+ if (const FileChange* Change = FindFileChangeLocation( ++ if (const FileChange* Change = Rewriter->FindFileChangeLocation( + HashToken.getLocation())) { + // now include and recursively process the file -+ if(Process(Change->Id, Change->Type)) { ++ File IncludedFile(Rewriter, Change->Id, Change->Type); ++ if (IncludedFile.Process()) { + // and set lineinfo back to this file, if the nested one was + // actually included -+ WriteLineInfo(FileName, Lines, Type, EOL, " 2"); ++ WriteLineInfo(" 2"); + NeedFixup = false; + } + } + if(NeedFixup) -+ WriteLineInfo(FileName, Lines, Type, EOL); ++ WriteLineInfo(); + break; + } + case tok::pp_pragma: { -+ StringRef Identifier = NextIdentifierName(RawLex, RawToken); ++ StringRef Identifier = NextIdentifierName(RawToken); + if (Identifier == "clang" || Identifier == "GCC") { -+ if (NextIdentifierName(RawLex, RawToken) == "system_header") { ++ if (NextIdentifierName(RawToken) == "system_header") { + // keep the directive in, commented out -+ CommentOutDirective(RawLex, HashToken, NextToWrite, Lines, -+ EOL, FromFile); ++ CommentOutDirective(HashToken); + // update our own type + Type = SM.getFileCharacteristic(RawToken.getLocation()); -+ WriteLineInfo(FileName, Lines, Type, EOL); ++ WriteLineInfo(); + } + } else if (Identifier == "once") { + // keep the directive in, commented out -+ CommentOutDirective(RawLex, HashToken, NextToWrite, Lines, -+ EOL, FromFile); -+ WriteLineInfo(FileName, Lines, Type, EOL); ++ CommentOutDirective(HashToken); ++ WriteLineInfo(); + } + break; + } @@ -532,22 +520,243 @@ index 0000000..679e556 + break; + } + } -+ RawLex.setParsingPreprocessorDirective(false); -+ RawLex.SetCommentRetentionState(false); ++ RawLex->setParsingPreprocessorDirective(false); ++ RawLex->SetCommentRetentionState(false); + } -+ RawLex.LexFromRawLexer(RawToken); ++ RawLex->LexFromRawLexer(RawToken); + } -+ OutputContentUpTo(SM.getFileOffset(SM.getLocForEndOfFile(FileId)) + 1, -+ NextToWrite, Lines, EOL, FromFile, true); ++ OutputContentUpTo(SM.getFileIDSize(FileId), true); + return true; +} + ++void IncludeRewriter::File::DetectEOL() { ++ // detect what line endings the file uses, so that added content does not mix ++ // the style ++ const char* Pos = strchr(FromFile->getBufferStart(), '\n'); ++ if (Pos == NULL) ++ EOL = "\n"; ++ else if (Pos+1 < FromFile->getBufferEnd() && *(Pos+1) == '\r') ++ EOL = "\n\r"; ++ else if (Pos-1 >= FromFile->getBufferStart() && *(Pos+1) == '\r') ++ EOL = "\r\n"; ++ else ++ EOL = "\n"; ++} ++ ++void IncludeRewriter::File::WriteLineInfo(StringRef Extra) { ++ if (Rewriter->DisableLineMarkers) { ++ OS << EOL; // Still need to at least separate lines. ++ return; ++ } ++ // Emit #line directives or GNU line markers depending on what mode we're in. ++ if (Rewriter->UseLineDirective) { ++ OS << "#line" << ' ' << Line << ' ' << '"' << FileName << '"'; ++ } else { ++ OS << '#' << ' ' << Line << ' ' << '"' << FileName << '"'; ++ if (!Extra.empty()) ++ OS << Extra; ++ if (Type == SrcMgr::C_System) ++ OS << " 3"; ++ else if (Type == SrcMgr::C_ExternCSystem) ++ OS << " 3 4"; ++ } ++ OS << EOL; ++} ++ ++inline unsigned IncludeRewriter::File::CountNewLines(const char* Pos, int Len) { ++ const char* End = Pos + Len; ++ unsigned Lines = 0; ++ --Pos; ++ while ((Pos = static_cast(memchr(Pos + 1, '\n', End - Pos - 1)))) ++ ++Lines; ++ return Lines; ++} ++ ++// Used by OutputContentUpTo() to output content depending on comment ++// removing options (either all comments are removed if RemoveAll), ++// or only comments on lines that have other non-whitespace). ++void IncludeRewriter::File::OutputContentStripComments(unsigned WriteEnd, ++ bool RemoveAll) { ++ unsigned LocalNextToWrite = NextToWrite; ++ // Only in !RemoveAll mode, true means there's something on the line ++ // besides whitespace and comments, so the comments should be kept. ++ bool LineKeepComment = false; ++ // Only in !RemoveAll mode, number of \n's in all comments ++ // from NextToWriteLine (in case they can be removed and just replaced ++ // with this number of \n's). ++ unsigned NewLinesInComments = 0; ++ for (;;) { ++ while (NextCommentRange < Rewriter->CommentRanges.size() ++ && Rewriter->CommentRanges[NextCommentRange].first ++ < LocalNextToWrite + StartLocation.getRawEncoding()) ++ ++NextCommentRange; ++ // WriteEnd cannot be in the middle of a comment. ++ assert( !(NextCommentRange < Rewriter->CommentRanges.size() ++ && Rewriter->CommentRanges[NextCommentRange].first ++ <= StartLocation.getRawEncoding() + WriteEnd - 1 ++ && Rewriter->CommentRanges[NextCommentRange].second ++ > StartLocation.getRawEncoding() + WriteEnd)); ++ if (NextCommentRange >= Rewriter->CommentRanges.size() ++ || StartLocation.getRawEncoding() + WriteEnd - 1 ++ < Rewriter->CommentRanges[NextCommentRange].first) { ++ // no further comment up to WriteEnd, write out all what we have ++ if (RemoveAll) { ++ OS.write(FromFile->getBufferStart() + LocalNextToWrite, ++ WriteEnd - LocalNextToWrite); ++ } else { ++ unsigned Pos = LocalNextToWrite; ++ unsigned ToWrite = WriteEnd - LocalNextToWrite; ++ for (unsigned int I = 0; I < ToWrite; ++I, ++Pos) { ++ char C = FromFile->getBufferStart()[Pos]; ++ // TODO This is possibly wrong for EOL different from plain \n. ++ if (C == '\n') { ++ if (LineKeepComment) ++ OS.write(FromFile->getBufferStart() + NextToWriteLine, ++ Pos - NextToWriteLine + 1); ++ else { ++ for (unsigned I = 0; I < NewLinesInComments; ++I) ++ OS << EOL; ++ OS << EOL; ++ } ++ NextToWriteLine = Pos + 1; ++ LineKeepComment = false; ++ NewLinesInComments = 0; ++ } ++ if (!isspace(C)) ++ LineKeepComment = true; ++ } ++ if (WriteEnd == SM.getFileIDSize(FileId)) { ++ // End of file, write out the rest if needed (there's no comment ++ // in it, so just write it out). ++ OS.write(FromFile->getBufferStart() + NextToWriteLine, ++ WriteEnd - NextToWriteLine); ++ NextToWriteLine = WriteEnd; ++ } ++ } ++ return; ++ } ++ const unsigned CommentStart = Rewriter->CommentRanges ++ [NextCommentRange].first - StartLocation.getRawEncoding(); ++ const unsigned CommentEnd = Rewriter->CommentRanges ++ [NextCommentRange].second - StartLocation.getRawEncoding();//first after ++ // data up to the next comment ++ unsigned ToWrite = CommentStart - LocalNextToWrite; ++ if (RemoveAll) { ++ if (ToWrite > 0) ++ OS.write(FromFile->getBufferStart() + LocalNextToWrite, ToWrite); ++ // keep \n's and trailing \'s from the comment ++ unsigned Pos = CommentStart; ++ for (unsigned int I = 0; I < CommentEnd - CommentStart; ++I, ++Pos) { ++ char C = FromFile->getBufferStart()[Pos]; ++ // TODO This is possibly wrong for EOL different from plain \n. ++ if (C == '\n') ++ OS << EOL; ++ else if (C == '\\' && I + 1 < CommentEnd - CommentStart ++ && FromFile->getBufferStart()[Pos + 1] == '\n') { ++ OS << '\\'; ++ } ++ } ++ } else { ++ // Check if there's any \n, if yes, check if the line before it ++ // should be output (including comments) or whether it has only ++ // whitespace and comments, in which case output only \n for it. ++ unsigned Pos = LocalNextToWrite; ++ for (unsigned int I = 0; I < ToWrite; ++I, ++Pos) { ++ char C = FromFile->getBufferStart()[Pos]; ++ // TODO This is possibly wrong for EOL different from plain \n. ++ if (C == '\n') { ++ if (LineKeepComment) ++ OS.write(FromFile->getBufferStart() + NextToWriteLine, ++ Pos - NextToWriteLine + 1); ++ else { ++ for (unsigned I = 0; I < NewLinesInComments; ++I) ++ OS << EOL; ++ OS << EOL; ++ } ++ NextToWriteLine = Pos + 1; ++ LineKeepComment = false; ++ NewLinesInComments = 0; ++ } ++ if (!isspace(C)) ++ LineKeepComment = true; ++ } ++ // Process the comment - count the number of \n's in it, in case ++ // it can be removed. ++ // TODO Ideally, if there is a multiline comment, all lines inside ++ // the comment should be replaced with empty lines, to further reduce ++ // the size of the resulting output, even if the first and/or last ++ // line of the comment contain also other non-whitespace and should ++ // therefore be kept. Currently such a comment is kept as a whole. ++ // However in practice multiline comments, especially large ones ++ // (doxygen comments, file headers) usually can be removed as a whole, ++ // so this probably would not make a big difference. ++ for (unsigned int I = 0; I < CommentEnd - CommentStart; ++I, ++Pos) { ++ char C = FromFile->getBufferStart()[Pos]; ++ if (C == '\n') { ++ ++NewLinesInComments; ++ } else if (C == '\\' && I + 1 < CommentEnd - CommentStart ++ && FromFile->getBufferStart()[Pos + 1] == '\n') { ++ // Do not remove lines in multiline comments that end with \, ++ // as that could be a body of a macro. ++ // TODO This is possibly wrong with EOL different from plain \n. ++ LineKeepComment = true; ++ } ++ } ++ } ++ // and move after the comment ++ LocalNextToWrite = CommentEnd; ++ } ++} ++ ++/// Copies next not yet written file content up (and not including) to writeEnd. ++void IncludeRewriter::File::OutputContentUpTo(unsigned WriteEnd, ++ bool EnsureNewline) { ++ if (WriteEnd > NextToWrite) { ++ if (Rewriter->KeepAllComments) ++ OS.write(FromFile->getBufferStart() + NextToWrite, WriteEnd - NextToWrite); ++ else if (Rewriter->KeepCommentsInCodeLines) ++ OutputContentStripComments(WriteEnd, false); ++ else // Remove all comments. ++ OutputContentStripComments(WriteEnd, true); ++ // count lines manually, it's faster than getPresumedLoc() ++ Line += CountNewLines(FromFile->getBufferStart() + NextToWrite, ++ WriteEnd - NextToWrite); ++ if (EnsureNewline) { ++ char LastChar = FromFile->getBufferStart()[WriteEnd - 1]; ++ if (LastChar != '\n' && LastChar != '\r') ++ OS << EOL; ++ } ++ NextToWrite = WriteEnd; ++ } ++} ++ ++void IncludeRewriter::File::CommentOutDirective(const Token& StartToken) { ++ OutputContentUpTo(SM.getFileOffset(StartToken.getLocation())); ++ Token DirectiveToken; ++ do { ++ RawLex->LexFromRawLexer(DirectiveToken); ++ } while (!DirectiveToken.is(tok::eod) && DirectiveToken.isNot(tok::eof)); ++ OS << "#if 0 /* expanded by -rewrite-includes */" << EOL; ++ OutputContentUpTo(SM.getFileOffset(DirectiveToken.getLocation()) ++ + DirectiveToken.getLength()); ++ OS << "#endif /* expanded by -rewrite-includes */" << EOL; ++} ++ ++StringRef IncludeRewriter::File::NextIdentifierName(Token& RawToken) { ++ RawLex->LexFromRawLexer(RawToken); ++ if (RawToken.is(tok::raw_identifier)) ++ PP.LookUpIdentifierInfo(RawToken); ++ if (RawToken.is(tok::identifier)) ++ return RawToken.getIdentifierInfo()->getName(); ++ return StringRef(); ++} ++ +/// RewriteIncludesInInput - Implement -rewrite-includes mode. +void clang::RewriteIncludesInInput(Preprocessor &PP, raw_ostream *OS, + const PreprocessorOutputOptions &Opts) { -+ SourceManager &SM = PP.getSourceManager(); -+ IncludeRewriter* Rewrite = new IncludeRewriter(PP, *OS,!Opts.ShowLineMarkers); ++ IncludeRewriter* Rewrite = new IncludeRewriter(PP, *OS, Opts); + PP.addPPCallbacks(Rewrite); ++ PP.AddCommentHandler(Rewrite); + + // First let the preprocessor process the entire file and call callbacks. + // Callbacks will record which #include's were actually performed. @@ -562,10 +771,12 @@ index 0000000..679e556 + do { + PP.Lex(Tok); + } while (Tok.isNot(tok::eof)); -+ Rewrite->Process(SM.getMainFileID(), SrcMgr::C_User); ++ Rewrite->Process(); + OS->flush(); +} -diff --git a/test/Frontend/Inputs/rewrite-includes1.h b/test/Frontend/Inputs/rewrite-includes1.h +diff --git tools/clang/make_patch tools/clang/make_patch +index d42af26..61a263d 100755 +diff --git tools/clang/test/Frontend/Inputs/rewrite-includes1.h tools/clang/test/Frontend/Inputs/rewrite-includes1.h new file mode 100644 index 0000000..1b6c80d --- /dev/null @@ -574,35 +785,35 @@ index 0000000..1b6c80d +#pragma clang system_header +included_line1 +#include "rewrite-includes2.h" -diff --git a/test/Frontend/Inputs/rewrite-includes2.h b/test/Frontend/Inputs/rewrite-includes2.h +diff --git tools/clang/test/Frontend/Inputs/rewrite-includes2.h tools/clang/test/Frontend/Inputs/rewrite-includes2.h new file mode 100644 index 0000000..1114e51 --- /dev/null +++ tools/clang/test/Frontend/Inputs/rewrite-includes2.h @@ -0,0 +1 @@ +included_line2 -diff --git a/test/Frontend/Inputs/rewrite-includes3.h b/test/Frontend/Inputs/rewrite-includes3.h +diff --git tools/clang/test/Frontend/Inputs/rewrite-includes3.h tools/clang/test/Frontend/Inputs/rewrite-includes3.h new file mode 100644 index 0000000..3757bc8 --- /dev/null +++ tools/clang/test/Frontend/Inputs/rewrite-includes3.h @@ -0,0 +1 @@ +included_line3 -diff --git a/test/Frontend/Inputs/rewrite-includes4.h b/test/Frontend/Inputs/rewrite-includes4.h +diff --git tools/clang/test/Frontend/Inputs/rewrite-includes4.h tools/clang/test/Frontend/Inputs/rewrite-includes4.h new file mode 100644 index 0000000..b4e25d2 --- /dev/null +++ tools/clang/test/Frontend/Inputs/rewrite-includes4.h @@ -0,0 +1 @@ +included_line4 -diff --git a/test/Frontend/Inputs/rewrite-includes5.h b/test/Frontend/Inputs/rewrite-includes5.h +diff --git tools/clang/test/Frontend/Inputs/rewrite-includes5.h tools/clang/test/Frontend/Inputs/rewrite-includes5.h new file mode 100644 index 0000000..934bf41 --- /dev/null +++ tools/clang/test/Frontend/Inputs/rewrite-includes5.h @@ -0,0 +1 @@ +included_line5 -diff --git a/test/Frontend/Inputs/rewrite-includes6.h b/test/Frontend/Inputs/rewrite-includes6.h +diff --git tools/clang/test/Frontend/Inputs/rewrite-includes6.h tools/clang/test/Frontend/Inputs/rewrite-includes6.h new file mode 100644 index 0000000..c18e501 --- /dev/null @@ -610,15 +821,38 @@ index 0000000..c18e501 @@ -0,0 +1,2 @@ +#pragma once +included_line6 -diff --git a/test/Frontend/rewrite-includes.c b/test/Frontend/rewrite-includes.c +diff --git tools/clang/test/Frontend/Inputs/rewrite-includes7.h tools/clang/test/Frontend/Inputs/rewrite-includes7.h new file mode 100644 -index 0000000..fbe901f +index 0000000..85428fd +--- /dev/null ++++ tools/clang/test/Frontend/Inputs/rewrite-includes7.h +@@ -0,0 +1,4 @@ ++#ifndef REWRITE_INCLUDES7_H ++#define REWRITE_INCLUDES7_H ++included_line7 ++#endif +diff --git tools/clang/test/Frontend/Inputs/rewrite-includes8.h tools/clang/test/Frontend/Inputs/rewrite-includes8.h +new file mode 100644 +index 0000000..7ab5fd9 +--- /dev/null ++++ tools/clang/test/Frontend/Inputs/rewrite-includes8.h +@@ -0,0 +1 @@ ++included_line8 +\ No newline at end of file +diff --git tools/clang/test/Frontend/Inputs/rewrite-includes9.h tools/clang/test/Frontend/Inputs/rewrite-includes9.h +new file mode 100644 +index 0000000..e69de29 +diff --git tools/clang/test/Frontend/rewrite-includes.c tools/clang/test/Frontend/rewrite-includes.c +new file mode 100644 +index 0000000..52be495 --- /dev/null +++ tools/clang/test/Frontend/rewrite-includes.c -@@ -0,0 +1,77 @@ -+// RUN: %clang_cc1 -verify -rewrite-includes -DFIRST -I %S/Inputs %s -o %t -+// RUN: cat %t | FileCheck -strict-whitespace %s -+// STARTCOMPARE +@@ -0,0 +1,46 @@ ++// RUN: %clang_cc1 -verify -rewrite-includes -DFIRST -I %S/Inputs %s -CC -o - | FileCheck -check-prefix=CHECK-C2 -strict-whitespace %s.check ++// RUN: %clang_cc1 -verify -rewrite-includes -DFIRST -I %S/Inputs %s -C -o - | FileCheck -check-prefix=CHECK-C1 -strict-whitespace %s.check ++// RUN: %clang_cc1 -verify -rewrite-includes -DFIRST -I %S/Inputs %s -o - | FileCheck -check-prefix=CHECK-C0 -strict-whitespace %s.check ++ ++STARTCOMPARE +#define A(a,b) a ## b +A(1,2) +#include "rewrite-includes1.h" @@ -632,64 +866,345 @@ index 0000000..fbe901f + +#include "rewrite-includes6.h" // comment + ++ // comment ++ /* ++ multiline ++ comment ++ */ ++#define MACRO \ ++ /*comment*/ \ ++ /*multi \ ++ line*/ \ ++ ++MACRO ++/* ++\ ++comment ++*/ ++foo /* multiline ++with code ++prepended */ ++/* multiline ++with code ++appended */ bar +#include "rewrite-includes6.h" /* comment + continues */ -+// ENDCOMPARE ++#include "rewrite-includes7.h" ++#include "rewrite-includes7.h" ++#include "rewrite-includes8.h" // no trailing \n in file ++#include "rewrite-includes9.h" // empty file ++ENDCOMPARE +diff --git tools/clang/test/Frontend/rewrite-includes.c.check tools/clang/test/Frontend/rewrite-includes.c.check +new file mode 100644 +index 0000000..7e920a5 +--- /dev/null ++++ tools/clang/test/Frontend/rewrite-includes.c.check +@@ -0,0 +1,308 @@ ++Modes that remove comments would also remove these check lines, so keep them in a separate file. + -+// CHECK: {{^}}// STARTCOMPARE{{$}} -+// CHECK-NEXT: {{^}}#define A(a,b) a ## b{{$}} -+// CHECK-NEXT: {{^}}A(1,2){{$}} -+// CHECK-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} -+// CHECK-NEXT: {{^}}#include "rewrite-includes1.h"{{$}} -+// CHECK-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} -+// CHECK-NEXT: {{^}}# 1 "{{.*}}/Inputs/rewrite-includes1.h" 1{{$}} -+// CHECK-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} -+// CHECK-NEXT: {{^}}#pragma clang system_header{{$}} -+// CHECK-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} -+// CHECK-NEXT: {{^}}# 2 "{{.*}}/Inputs/rewrite-includes1.h" 3{{$}} -+// CHECK-NEXT: {{^}}included_line1{{$}} -+// CHECK-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} -+// CHECK-NEXT: {{^}}#include "rewrite-includes2.h"{{$}} -+// CHECK-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} -+// CHECK-NEXT: {{^}}# 1 "{{.*}}/Inputs/rewrite-includes2.h" 1 3{{$}} -+// CHECK-NEXT: {{^}}included_line2{{$}} -+// CHECK-NEXT: {{^}}# 4 "{{.*}}/Inputs/rewrite-includes1.h" 2 3{{$}} -+// CHECK-NEXT: {{^}}# 7 "{{.*}}rewrite-includes.c" 2{{$}} -+// CHECK-NEXT: {{^}}#ifdef FIRST{{$}} -+// CHECK-NEXT: {{^}}#define HEADER "rewrite-includes3.h"{{$}} -+// CHECK-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} -+// CHECK-NEXT: {{^}}#include HEADER{{$}} -+// CHECK-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} -+// CHECK-NEXT: {{^}}# 1 "{{.*}}/Inputs/rewrite-includes3.h" 1{{$}} -+// CHECK-NEXT: {{^}}included_line3{{$}} -+// CHECK-NEXT: {{^}}# 10 "{{.*}}rewrite-includes.c" 2{{$}} -+// CHECK-NEXT: {{^}}#else{{$}} -+// CHECK-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} -+// CHECK-NEXT: {{^}}#include "rewrite-includes4.h"{{$}} -+// CHECK-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} -+// CHECK-NEXT: {{^}}# 12 "{{.*}}rewrite-includes.c"{{$}} -+// CHECK-NEXT: {{^}}#endif{{$}} -+// CHECK-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} -+// CHECK-NEXT: {{^}}#/**/include /**/ "rewrite-includes5.h" /**/ {{\\}}{{$}} -+// CHECK-NEXT: {{^}} {{$}} -+// CHECK-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} -+// CHECK-NEXT: {{^}}# 1 "{{.*}}/Inputs/rewrite-includes5.h" 1{{$}} -+// CHECK-NEXT: {{^}}included_line5{{$}} -+// CHECK-NEXT: {{^}}# 15 "{{.*}}rewrite-includes.c" 2{{$}} -+// CHECK-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} -+// CHECK-NEXT: {{^}}#include "rewrite-includes6.h" // comment{{$}} -+// CHECK-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} -+// CHECK-NEXT: {{^}}# 1 "{{.*}}/Inputs/rewrite-includes6.h" 1{{$}} -+// CHECK-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} -+// CHECK-NEXT: {{^}}#pragma once{{$}} -+// CHECK-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} -+// CHECK-NEXT: {{^}}# 2 "{{.*}}/Inputs/rewrite-includes6.h"{{$}} -+// CHECK-NEXT: {{^}}included_line6{{$}} -+// CHECK-NEXT: {{^}}# 16 "{{.*}}rewrite-includes.c" 2{{$}} -+// CHECK-NEXT: {{^}} {{$}} -+// CHECK-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} -+// CHECK-NEXT: {{^}}#include "rewrite-includes6.h" /* comment{{$}} -+// CHECK-NEXT: {{^}} continues */{{$}} -+// CHECK-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} -+// CHECK-NEXT: {{^}}# 19 "{{.*}}rewrite-includes.c"{{$}} -+// CHECK-NEXT: {{^}}// ENDCOMPARE{{$}} ++Note that FileCheck does not seem to have a way to check for an empty line, ++so there is just a comment, the next non-empty line is not -NEXT but a plain check line ++and the line correctness is checked by same later # directive check. ++ ++This one checks -CC, i.e. all comments are kept. It's the primary mode for the test. ++ ++// CHECK-C2: {{^}}STARTCOMPARE{{$}} ++// CHECK-C2-NEXT: {{^}}#define A(a,b) a ## b{{$}} ++// CHECK-C2-NEXT: {{^}}A(1,2){{$}} ++// CHECK-C2-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} ++// CHECK-C2-NEXT: {{^}}#include "rewrite-includes1.h"{{$}} ++// CHECK-C2-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} ++// CHECK-C2-NEXT: {{^}}# 1 "{{.*}}/Inputs/rewrite-includes1.h" 1{{$}} ++// CHECK-C2-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} ++// CHECK-C2-NEXT: {{^}}#pragma clang system_header{{$}} ++// CHECK-C2-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} ++// CHECK-C2-NEXT: {{^}}# 2 "{{.*}}/Inputs/rewrite-includes1.h" 3{{$}} ++// CHECK-C2-NEXT: {{^}}included_line1{{$}} ++// CHECK-C2-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} ++// CHECK-C2-NEXT: {{^}}#include "rewrite-includes2.h"{{$}} ++// CHECK-C2-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} ++// CHECK-C2-NEXT: {{^}}# 1 "{{.*}}/Inputs/rewrite-includes2.h" 1 3{{$}} ++// CHECK-C2-NEXT: {{^}}included_line2{{$}} ++// CHECK-C2-NEXT: {{^}}# 4 "{{.*}}/Inputs/rewrite-includes1.h" 2 3{{$}} ++// CHECK-C2-NEXT: {{^}}# 9 "{{.*}}rewrite-includes.c" 2{{$}} ++// CHECK-C2-NEXT: {{^}}#ifdef FIRST{{$}} ++// CHECK-C2-NEXT: {{^}}#define HEADER "rewrite-includes3.h"{{$}} ++// CHECK-C2-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} ++// CHECK-C2-NEXT: {{^}}#include HEADER{{$}} ++// CHECK-C2-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} ++// CHECK-C2-NEXT: {{^}}# 1 "{{.*}}/Inputs/rewrite-includes3.h" 1{{$}} ++// CHECK-C2-NEXT: {{^}}included_line3{{$}} ++// CHECK-C2-NEXT: {{^}}# 12 "{{.*}}rewrite-includes.c" 2{{$}} ++// CHECK-C2-NEXT: {{^}}#else{{$}} ++// CHECK-C2-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} ++// CHECK-C2-NEXT: {{^}}#include "rewrite-includes4.h"{{$}} ++// CHECK-C2-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} ++// CHECK-C2-NEXT: {{^}}# 14 "{{.*}}rewrite-includes.c"{{$}} ++// CHECK-C2-NEXT: {{^}}#endif{{$}} ++// CHECK-C2-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} ++// CHECK-C2-NEXT: {{^}}#/**/include /**/ "rewrite-includes5.h" /**/ {{\\}}{{$}} ++// CHECK-C2-NEXT: {{^}} {{$}} ++// CHECK-C2-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} ++// CHECK-C2-NEXT: {{^}}# 1 "{{.*}}/Inputs/rewrite-includes5.h" 1{{$}} ++// CHECK-C2-NEXT: {{^}}included_line5{{$}} ++// CHECK-C2-NEXT: {{^}}# 17 "{{.*}}rewrite-includes.c" 2{{$}} ++// CHECK-C2-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} ++// CHECK-C2-NEXT: {{^}}#include "rewrite-includes6.h" // comment{{$}} ++// CHECK-C2-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} ++// CHECK-C2-NEXT: {{^}}# 1 "{{.*}}/Inputs/rewrite-includes6.h" 1{{$}} ++// CHECK-C2-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} ++// CHECK-C2-NEXT: {{^}}#pragma once{{$}} ++// CHECK-C2-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} ++// CHECK-C2-NEXT: {{^}}# 2 "{{.*}}/Inputs/rewrite-includes6.h"{{$}} ++// CHECK-C2-NEXT: {{^}}included_line6{{$}} ++// CHECK-C2-NEXT: {{^}}# 18 "{{.*}}rewrite-includes.c" 2{{$}} ++// CHECK-C2-NEXT: {{^}} {{$}} ++// CHECK-C2-NEXT: {{^}} // comment{{$}} ++// CHECK-C2-NEXT: {{^}} /*{{$}} ++// CHECK-C2-NEXT: {{^}} multiline{{$}} ++// CHECK-C2-NEXT: {{^}} comment{{$}} ++// CHECK-C2-NEXT: {{^}} */{{$}} ++// CHECK-C2-NEXT: {{^}}#define MACRO \{{$}} ++// CHECK-C2-NEXT: {{^}} /*comment*/ \{{$}} ++// CHECK-C2-NEXT: {{^}} /*multi \{{$}} ++// CHECK-C2-NEXT: {{^}} line*/ \{{$}} ++// CHECK-C2-NEXT: {{^}} {{$}} ++// CHECK-C2-NEXT: {{^}}MACRO{{$}} ++// CHECK-C2-NEXT: {{^}}/*{{$}} ++// CHECK-C2-NEXT: {{^}}\{{$}} ++// CHECK-C2-NEXT: {{^}}comment{{$}} ++// CHECK-C2-NEXT: {{^}}*/{{$}} ++// CHECK-C2-NEXT: {{^}}foo /* multiline{{$}} ++// CHECK-C2-NEXT: {{^}}with code{{$}} ++// CHECK-C2-NEXT: {{^}}prepended */{{$}} ++// CHECK-C2-NEXT: {{^}}/* multiline{{$}} ++// CHECK-C2-NEXT: {{^}}with code{{$}} ++// CHECK-C2-NEXT: {{^}}appended */ bar{{$}} ++// CHECK-C2-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} ++// CHECK-C2-NEXT: {{^}}#include "rewrite-includes6.h" /* comment{{$}} ++// CHECK-C2-NEXT: {{^}} continues */{{$}} ++// CHECK-C2-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} ++// CHECK-C2-NEXT: {{^}}# 42 "{{.*}}rewrite-includes.c"{{$}} ++// CHECK-C2-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} ++// CHECK-C2-NEXT: {{^}}#include "rewrite-includes7.h"{{$}} ++// CHECK-C2-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} ++// CHECK-C2-NEXT: {{^}}# 1 "{{.*}}/Inputs/rewrite-includes7.h" 1{{$}} ++// CHECK-C2-NEXT: {{^}}#ifndef REWRITE_INCLUDES7_H{{$}} ++// CHECK-C2-NEXT: {{^}}#define REWRITE_INCLUDES7_H{{$}} ++// CHECK-C2-NEXT: {{^}}included_line7{{$}} ++// CHECK-C2-NEXT: {{^}}#endif{{$}} ++// CHECK-C2-NEXT: {{^}}# 43 "{{.*}}rewrite-includes.c" 2{{$}} ++// CHECK-C2-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} ++// CHECK-C2-NEXT: {{^}}#include "rewrite-includes7.h"{{$}} ++// CHECK-C2-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} ++// CHECK-C2-NEXT: {{^}}# 44 "{{.*}}rewrite-includes.c"{{$}} ++// CHECK-C2-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} ++// CHECK-C2-NEXT: {{^}}#include "rewrite-includes8.h" // no trailing \n in file{{$}} ++// CHECK-C2-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} ++// CHECK-C2-NEXT: {{^}}# 1 "{{.*}}/Inputs/rewrite-includes8.h" 1{{$}} ++// CHECK-C2-NEXT: {{^}}included_line8{{$}} ++// CHECK-C2-NEXT: {{^}}# 45 "{{.*}}rewrite-includes.c" 2{{$}} ++// CHECK-C2-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} ++// CHECK-C2-NEXT: {{^}}#include "rewrite-includes9.h" // empty file{{$}} ++// CHECK-C2-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} ++// CHECK-C2-NEXT: {{^}}# 1 "{{.*}}/Inputs/rewrite-includes9.h" 1{{$}} ++// CHECK-C2-NEXT: {{^}}# 46 "{{.*}}rewrite-includes.c" 2{{$}} ++// CHECK-C2-NEXT: {{^}}ENDCOMPARE{{$}} ++ ++This one checks -C, i.e. only comments on lines with other non-whitespace are kept. ++Note that lines containing only whitespace are not preserved exactly and are converted to empty lines. ++ ++// CHECK-C1: {{^}}STARTCOMPARE{{$}} ++// CHECK-C1-NEXT: {{^}}#define A(a,b) a ## b{{$}} ++// CHECK-C1-NEXT: {{^}}A(1,2){{$}} ++// CHECK-C1-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} ++// CHECK-C1-NEXT: {{^}}#include "rewrite-includes1.h"{{$}} ++// CHECK-C1-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} ++// CHECK-C1-NEXT: {{^}}# 1 "{{.*}}/Inputs/rewrite-includes1.h" 1{{$}} ++// CHECK-C1-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} ++// CHECK-C1-NEXT: {{^}}#pragma clang system_header{{$}} ++// CHECK-C1-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} ++// CHECK-C1-NEXT: {{^}}# 2 "{{.*}}/Inputs/rewrite-includes1.h" 3{{$}} ++// CHECK-C1-NEXT: {{^}}included_line1{{$}} ++// CHECK-C1-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} ++// CHECK-C1-NEXT: {{^}}#include "rewrite-includes2.h"{{$}} ++// CHECK-C1-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} ++// CHECK-C1-NEXT: {{^}}# 1 "{{.*}}/Inputs/rewrite-includes2.h" 1 3{{$}} ++// CHECK-C1-NEXT: {{^}}included_line2{{$}} ++// CHECK-C1-NEXT: {{^}}# 4 "{{.*}}/Inputs/rewrite-includes1.h" 2 3{{$}} ++// CHECK-C1-NEXT: {{^}}# 9 "{{.*}}rewrite-includes.c" 2{{$}} ++// CHECK-C1-NEXT: {{^}}#ifdef FIRST{{$}} ++// CHECK-C1-NEXT: {{^}}#define HEADER "rewrite-includes3.h"{{$}} ++// CHECK-C1-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} ++// CHECK-C1-NEXT: {{^}}#include HEADER{{$}} ++// CHECK-C1-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} ++// CHECK-C1-NEXT: {{^}}# 1 "{{.*}}/Inputs/rewrite-includes3.h" 1{{$}} ++// CHECK-C1-NEXT: {{^}}included_line3{{$}} ++// CHECK-C1-NEXT: {{^}}# 12 "{{.*}}rewrite-includes.c" 2{{$}} ++// CHECK-C1-NEXT: {{^}}#else{{$}} ++// CHECK-C1-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} ++// CHECK-C1-NEXT: {{^}}#include "rewrite-includes4.h"{{$}} ++// CHECK-C1-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} ++// CHECK-C1-NEXT: {{^}}# 14 "{{.*}}rewrite-includes.c"{{$}} ++// CHECK-C1-NEXT: {{^}}#endif{{$}} ++// CHECK-C1-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} ++// CHECK-C1-NEXT: {{^}}#/**/include /**/ "rewrite-includes5.h" /**/ {{\\}}{{$}} ++// here's an empty line ++// CHECK-C1: {{^}}#endif /* expanded by -rewrite-includes */{{$}} ++// CHECK-C1-NEXT: {{^}}# 1 "{{.*}}/Inputs/rewrite-includes5.h" 1{{$}} ++// CHECK-C1-NEXT: {{^}}included_line5{{$}} ++// CHECK-C1-NEXT: {{^}}# 17 "{{.*}}rewrite-includes.c" 2{{$}} ++// CHECK-C1-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} ++// CHECK-C1-NEXT: {{^}}#include "rewrite-includes6.h" // comment{{$}} ++// CHECK-C1-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} ++// CHECK-C1-NEXT: {{^}}# 1 "{{.*}}/Inputs/rewrite-includes6.h" 1{{$}} ++// CHECK-C1-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} ++// CHECK-C1-NEXT: {{^}}#pragma once{{$}} ++// CHECK-C1-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} ++// CHECK-C1-NEXT: {{^}}# 2 "{{.*}}/Inputs/rewrite-includes6.h"{{$}} ++// CHECK-C1-NEXT: {{^}}included_line6{{$}} ++// CHECK-C1-NEXT: {{^}}# 18 "{{.*}}rewrite-includes.c" 2{{$}} ++// here are 6 empty lines ++// CHECK-C1: {{^}}#define MACRO \{{$}} ++// CHECK-C1-NEXT: {{^}} /*comment*/ \{{$}} ++// CHECK-C1-NEXT: {{^}} /*multi \{{$}} ++// CHECK-C1-NEXT: {{^}} line*/ \{{$}} ++// here's an empty line ++// CHECK-C1: {{^}}MACRO{{$}} ++// CHECK-C1-NEXT: {{^}}/*{{$}} ++// CHECK-C1-NEXT: {{^}}\{{$}} ++// CHECK-C1-NEXT: {{^}}comment{{$}} ++// CHECK-C1-NEXT: {{^}}*/{{$}} ++// CHECK-C1-NEXT: {{^}}foo /* multiline{{$}} ++// CHECK-C1-NEXT: {{^}}with code{{$}} ++// CHECK-C1-NEXT: {{^}}prepended */{{$}} ++// CHECK-C1-NEXT: {{^}}/* multiline{{$}} ++// CHECK-C1-NEXT: {{^}}with code{{$}} ++// CHECK-C1-NEXT: {{^}}appended */ bar{{$}} ++// CHECK-C1-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} ++// CHECK-C1-NEXT: {{^}}#include "rewrite-includes6.h" /* comment{{$}} ++// CHECK-C1-NEXT: {{^}} continues */{{$}} ++// CHECK-C1-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} ++// CHECK-C1-NEXT: {{^}}# 42 "{{.*}}rewrite-includes.c"{{$}} ++// CHECK-C1-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} ++// CHECK-C1-NEXT: {{^}}#include "rewrite-includes7.h"{{$}} ++// CHECK-C1-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} ++// CHECK-C1-NEXT: {{^}}# 1 "{{.*}}/Inputs/rewrite-includes7.h" 1{{$}} ++// CHECK-C1-NEXT: {{^}}#ifndef REWRITE_INCLUDES7_H{{$}} ++// CHECK-C1-NEXT: {{^}}#define REWRITE_INCLUDES7_H{{$}} ++// CHECK-C1-NEXT: {{^}}included_line7{{$}} ++// CHECK-C1-NEXT: {{^}}#endif{{$}} ++// CHECK-C1-NEXT: {{^}}# 43 "{{.*}}rewrite-includes.c" 2{{$}} ++// CHECK-C1-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} ++// CHECK-C1-NEXT: {{^}}#include "rewrite-includes7.h"{{$}} ++// CHECK-C1-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} ++// CHECK-C1-NEXT: {{^}}# 44 "{{.*}}rewrite-includes.c"{{$}} ++// CHECK-C1-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} ++// CHECK-C1-NEXT: {{^}}#include "rewrite-includes8.h" // no trailing \n in file{{$}} ++// CHECK-C1-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} ++// CHECK-C1-NEXT: {{^}}# 1 "{{.*}}/Inputs/rewrite-includes8.h" 1{{$}} ++// CHECK-C1-NEXT: {{^}}included_line8{{$}} ++// CHECK-C1-NEXT: {{^}}# 45 "{{.*}}rewrite-includes.c" 2{{$}} ++// CHECK-C1-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} ++// CHECK-C1-NEXT: {{^}}#include "rewrite-includes9.h" // empty file{{$}} ++// CHECK-C1-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} ++// CHECK-C1-NEXT: {{^}}# 1 "{{.*}}/Inputs/rewrite-includes9.h" 1{{$}} ++// CHECK-C1-NEXT: {{^}}# 46 "{{.*}}rewrite-includes.c" 2{{$}} ++// CHECK-C1-NEXT: {{^}}ENDCOMPARE{{$}} ++ ++This one checks without -C or -CC, i.e. comments removed. ++ ++// CHECK-C0: {{^}}STARTCOMPARE{{$}} ++// CHECK-C0-NEXT: {{^}}#define A(a,b) a ## b{{$}} ++// CHECK-C0-NEXT: {{^}}A(1,2){{$}} ++// CHECK-C0-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} ++// CHECK-C0-NEXT: {{^}}#include "rewrite-includes1.h"{{$}} ++// CHECK-C0-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} ++// CHECK-C0-NEXT: {{^}}# 1 "{{.*}}/Inputs/rewrite-includes1.h" 1{{$}} ++// CHECK-C0-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} ++// CHECK-C0-NEXT: {{^}}#pragma clang system_header{{$}} ++// CHECK-C0-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} ++// CHECK-C0-NEXT: {{^}}# 2 "{{.*}}/Inputs/rewrite-includes1.h" 3{{$}} ++// CHECK-C0-NEXT: {{^}}included_line1{{$}} ++// CHECK-C0-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} ++// CHECK-C0-NEXT: {{^}}#include "rewrite-includes2.h"{{$}} ++// CHECK-C0-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} ++// CHECK-C0-NEXT: {{^}}# 1 "{{.*}}/Inputs/rewrite-includes2.h" 1 3{{$}} ++// CHECK-C0-NEXT: {{^}}included_line2{{$}} ++// CHECK-C0-NEXT: {{^}}# 4 "{{.*}}/Inputs/rewrite-includes1.h" 2 3{{$}} ++// CHECK-C0-NEXT: {{^}}# 9 "{{.*}}rewrite-includes.c" 2{{$}} ++// CHECK-C0-NEXT: {{^}}#ifdef FIRST{{$}} ++// CHECK-C0-NEXT: {{^}}#define HEADER "rewrite-includes3.h"{{$}} ++// CHECK-C0-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} ++// CHECK-C0-NEXT: {{^}}#include HEADER{{$}} ++// CHECK-C0-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} ++// CHECK-C0-NEXT: {{^}}# 1 "{{.*}}/Inputs/rewrite-includes3.h" 1{{$}} ++// CHECK-C0-NEXT: {{^}}included_line3{{$}} ++// CHECK-C0-NEXT: {{^}}# 12 "{{.*}}rewrite-includes.c" 2{{$}} ++// CHECK-C0-NEXT: {{^}}#else{{$}} ++// CHECK-C0-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} ++// CHECK-C0-NEXT: {{^}}#include "rewrite-includes4.h"{{$}} ++// CHECK-C0-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} ++// CHECK-C0-NEXT: {{^}}# 14 "{{.*}}rewrite-includes.c"{{$}} ++// CHECK-C0-NEXT: {{^}}#endif{{$}} ++// CHECK-C0-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} ++// CHECK-C0-NEXT: {{^}}#include "rewrite-includes5.h" {{\\}}{{$}} ++// CHECK-C0-NEXT: {{^}} {{$}} ++// CHECK-C0-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} ++// CHECK-C0-NEXT: {{^}}# 1 "{{.*}}/Inputs/rewrite-includes5.h" 1{{$}} ++// CHECK-C0-NEXT: {{^}}included_line5{{$}} ++// CHECK-C0-NEXT: {{^}}# 17 "{{.*}}rewrite-includes.c" 2{{$}} ++// CHECK-C0-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} ++// CHECK-C0-NEXT: {{^}}#include "rewrite-includes6.h" {{$}} ++// CHECK-C0-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} ++// CHECK-C0-NEXT: {{^}}# 1 "{{.*}}/Inputs/rewrite-includes6.h" 1{{$}} ++// CHECK-C0-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} ++// CHECK-C0-NEXT: {{^}}#pragma once{{$}} ++// CHECK-C0-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} ++// CHECK-C0-NEXT: {{^}}# 2 "{{.*}}/Inputs/rewrite-includes6.h"{{$}} ++// CHECK-C0-NEXT: {{^}}included_line6{{$}} ++// CHECK-C0-NEXT: {{^}}# 18 "{{.*}}rewrite-includes.c" 2{{$}} ++// CHECK-C0-NEXT: {{^}} {{$}} ++// here are 5 empty lines ++// CHECK-C0: {{^}}#define MACRO \{{$}} ++// CHECK-C0-NEXT: {{^}} \{{$}} ++// CHECK-C0-NEXT: {{^}} \{{$}} ++// CHECK-C0-NEXT: {{^}} \{{$}} ++// here's an empty line ++// CHECK-C0: {{^}}MACRO{{$}} ++// here's an empty line ++// CHECK-C0: {{^}}\{{$}} ++// here are 2 empty lines ++// CHECK-C0: {{^}}foo {{$}} ++// here are 4 empty lines ++// CHECK-C0: {{^}} bar{{$}} ++// CHECK-C0-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} ++// CHECK-C0-NEXT: {{^}}#include "rewrite-includes6.h" {{$}} ++// here's an empty line ++// CHECK-C0: {{^}}#endif /* expanded by -rewrite-includes */{{$}} ++// CHECK-C0-NEXT: {{^}}# 42 "{{.*}}rewrite-includes.c"{{$}} ++// CHECK-C0-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} ++// CHECK-C0-NEXT: {{^}}#include "rewrite-includes7.h"{{$}} ++// CHECK-C0-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} ++// CHECK-C0-NEXT: {{^}}# 1 "{{.*}}/Inputs/rewrite-includes7.h" 1{{$}} ++// CHECK-C0-NEXT: {{^}}#ifndef REWRITE_INCLUDES7_H{{$}} ++// CHECK-C0-NEXT: {{^}}#define REWRITE_INCLUDES7_H{{$}} ++// CHECK-C0-NEXT: {{^}}included_line7{{$}} ++// CHECK-C0-NEXT: {{^}}#endif{{$}} ++// CHECK-C0-NEXT: {{^}}# 43 "{{.*}}rewrite-includes.c" 2{{$}} ++// CHECK-C0-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} ++// CHECK-C0-NEXT: {{^}}#include "rewrite-includes7.h"{{$}} ++// CHECK-C0-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} ++// CHECK-C0-NEXT: {{^}}# 44 "{{.*}}rewrite-includes.c"{{$}} ++// CHECK-C0-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} ++// CHECK-C0-NEXT: {{^}}#include "rewrite-includes8.h" {{$}} ++// CHECK-C0-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} ++// CHECK-C0-NEXT: {{^}}# 1 "{{.*}}/Inputs/rewrite-includes8.h" 1{{$}} ++// CHECK-C0-NEXT: {{^}}included_line8{{$}} ++// CHECK-C0-NEXT: {{^}}# 45 "{{.*}}rewrite-includes.c" 2{{$}} ++// CHECK-C0-NEXT: {{^}}#if 0 /* expanded by -rewrite-includes */{{$}} ++// CHECK-C0-NEXT: {{^}}#include "rewrite-includes9.h" {{$}} ++// CHECK-C0-NEXT: {{^}}#endif /* expanded by -rewrite-includes */{{$}} ++// CHECK-C0-NEXT: {{^}}# 1 "{{.*}}/Inputs/rewrite-includes9.h" 1{{$}} ++// CHECK-C0-NEXT: {{^}}# 46 "{{.*}}rewrite-includes.c" 2{{$}} ++// CHECK-C0-NEXT: {{^}}ENDCOMPARE{{$}}