SHA256
1
0
forked from pool/llvm

Accepting request 127882 from home:llunak:branches:devel:tools:compiler

This adds few fixes, but mostly it updates the rewrite-includes patch. Sadly upstream has decided to rename the option name for whatever reason, so if unchanged 12.2 would be the only clang with the option named this way, causing further problems e.g. with icecream.

So it would be very nice to get this into 12.2. As it is an isolated feature, it should be low-risk.

OBS-URL: https://build.opensuse.org/request/show/127882
OBS-URL: https://build.opensuse.org/package/show/devel:tools:compiler/llvm?expand=0&rev=155
This commit is contained in:
Ismail Dönmez 2012-07-14 15:44:52 +00:00 committed by Git OBS Bridge
parent b08970fa49
commit 7c611aed7c
6 changed files with 407 additions and 577 deletions

View File

@ -1,3 +1,19 @@
-------------------------------------------------------------------
Fri Jul 13 21:03:40 UTC 2012 - llunak@suse.com
- change rewrite-includes patch to use options to match upstream
changed option names
-------------------------------------------------------------------
Fri Jul 13 10:14:15 UTC 2012 - llunak@suse.com
- fix debuginfo generation (PR#13303)
-------------------------------------------------------------------
Mon Jun 18 20:26:51 UTC 2012 - llunak@suse.com
- Do not reject PCH because of -DFOO duplication (PR#13141)
-------------------------------------------------------------------
Tue May 15 09:01:26 UTC 2012 - idonmez@suse.com

View File

@ -39,6 +39,9 @@ Patch3: clang-disable-ada-extension.patch
Patch4: default-to-i586.patch
Patch5: clang-fix-mips-test.patch
Patch6: rewrite-includes.patch
Patch7: pr12463.patch
Patch8: pr13141.patch
Patch9: pr13303.patch
BuildRoot: %{_tmppath}/%{name}-%{version}-build
BuildRequires: autoconf
BuildRequires: automake
@ -138,6 +141,9 @@ This package contains vim plugins for LLVM like syntax highlighting.
%patch6 -p0
# sle11 patch cannot create empty files
touch tools/clang/test/Frontend/Inputs/rewrite-includes9.h
%patch7 -p0
%patch8 -p0
%patch9 -p1
# We hardcode i586
rm tools/clang/test/Driver/x86_features.c

111
pr12463.patch Normal file
View File

@ -0,0 +1,111 @@
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index fea0fe1..1046972 100644
--- tools/clang/lib/Sema/SemaExpr.cpp
+++ tools/clang/lib/Sema/SemaExpr.cpp
@@ -6577,23 +6577,29 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
checkEnumComparison(*this, Loc, LHS, RHS);
if (!LHSType->hasFloatingRepresentation() &&
- !(LHSType->isBlockPointerType() && IsRelational) &&
- !LHS.get()->getLocStart().isMacroID() &&
- !RHS.get()->getLocStart().isMacroID()) {
+ !(LHSType->isBlockPointerType() && IsRelational)) {
// For non-floating point types, check for self-comparisons of the form
// x == x, x != x, x < x, etc. These always evaluate to a constant, and
// often indicate logic errors in the program.
//
- // NOTE: Don't warn about comparison expressions resulting from macro
- // expansion. Also don't warn about comparisons which are only self
+ // NOTE: Don't warn about self-comparison expressions resulting from macro
+ // expansion, unless they don't make sense at all.
+ // Also don't warn about comparisons which are only self
// comparisons within a template specialization. The warnings should catch
// obvious cases in the definition of the template anyways. The idea is to
// warn when the typed comparison operator will always evaluate to the same
// result.
+ bool InMacro = LHS.get()->getLocStart().isMacroID() ||
+ RHS.get()->getLocStart().isMacroID();
if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(LHSStripped)) {
if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(RHSStripped)) {
+ if (isa<CastExpr>(LHSStripped))
+ LHSStripped = LHSStripped->IgnoreParenCasts();
if (DRL->getDecl() == DRR->getDecl() &&
- !IsWithinTemplateSpecialization(DRL->getDecl())) {
+ !IsWithinTemplateSpecialization(DRL->getDecl()) &&
+ !InMacro &&
+ !isa<StringLiteral>(LHSStripped) &&
+ !isa<ObjCEncodeExpr>(LHSStripped)) {
DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always)
<< 0 // self-
<< (Opc == BO_EQ
@@ -6602,23 +6608,26 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
} else if (LHSType->isArrayType() && RHSType->isArrayType() &&
!DRL->getDecl()->getType()->isReferenceType() &&
!DRR->getDecl()->getType()->isReferenceType()) {
- // what is it always going to eval to?
- char always_evals_to;
switch(Opc) {
case BO_EQ: // e.g. array1 == array2
- always_evals_to = 0; // false
+ if (!InMacro)
+ DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always)
+ << 1 // array
+ << 0 /* evaluates to false */ );
break;
case BO_NE: // e.g. array1 != array2
- always_evals_to = 1; // true
+ if (!InMacro)
+ DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always)
+ << 1 // array
+ << 1 /* evaluates to true */ );
break;
- default:
+ default: // e.g. array1 <= array2
// best we can say is 'a constant'
- always_evals_to = 2; // e.g. array1 <= array2
+ DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always)
+ << 1 // array
+ << 2 /* evaluates to constant */ );
break;
}
- DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always)
- << 1 // array
- << always_evals_to);
}
}
}
diff --git a/test/Sema/exprs.c b/test/Sema/exprs.c
index 72cff65..b17b6ec 100644
--- tools/clang/test/Sema/exprs.c
+++ tools/clang/test/Sema/exprs.c
@@ -125,6 +125,12 @@ int test12b(const char *X) {
return sizeof(X == "foo"); // no-warning
}
+// PR12463
+#define FOO_LITERAL "foo"
+int test12c(const char *X) {
+ return X == FOO_LITERAL; // expected-warning {{comparison against a string literal is unspecified (use strncmp instead)}}
+}
+
// rdar://6719156
void test13(
void (^P)()) { // expected-error {{blocks support disabled - compile with -fblocks}}
diff --git a/test/Sema/self-comparison.c b/test/Sema/self-comparison.c
index edb3a6a..8679a3f 100644
--- tools/clang/test/Sema/self-comparison.c
+++ tools/clang/test/Sema/self-comparison.c
@@ -72,6 +72,13 @@ int array_comparisons() {
return array1 <= array2; // expected-warning{{array comparison always evaluates to a constant}}
return array1 > array2; // expected-warning{{array comparison always evaluates to a constant}}
return array1 >= array2; // expected-warning{{array comparison always evaluates to a constant}}
+ // Issue a warning for this even if macro expansion is involved (PR12463)
+#define ARRAY1 array1
+#define ARRAY2 array2
+ return ARRAY1 < ARRAY2; // expected-warning{{array comparison always evaluates to a constant}}
+ return ARRAY1 <= ARRAY2; // expected-warning{{array comparison always evaluates to a constant}}
+ return ARRAY1 > ARRAY2; // expected-warning{{array comparison always evaluates to a constant}}
+ return ARRAY1 >= ARRAY2; // expected-warning{{array comparison always evaluates to a constant}}
}

28
pr13141.patch Normal file
View File

@ -0,0 +1,28 @@
From e9ddb0fd37e4245392af7e8f1e2c86a44d4339ba Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lubo=C5=A1=20Lu=C5=88=C3=A1k?= <l.lunak@suse.cz>
Date: Mon, 18 Jun 2012 22:23:37 +0200
Subject: [PATCH] do not reject PCH because of -DFOO -DFOO duplication
---
lib/Serialization/ASTReader.cpp | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index f224056..d176ee3 100644
--- tools/clang/lib/Serialization/ASTReader.cpp
+++ tools/clang/lib/Serialization/ASTReader.cpp
@@ -259,6 +259,11 @@ bool PCHValidator::ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers,
// definitions and they may appear at any point in the output.
std::sort(CmdLineLines.begin(), CmdLineLines.end());
std::sort(PCHLines.begin(), PCHLines.end());
+ // And remove duplicated definitions.
+ CmdLineLines.resize(
+ std::unique(CmdLineLines.begin(), CmdLineLines.end())-CmdLineLines.begin());
+ PCHLines.resize(
+ std::unique(PCHLines.begin(), PCHLines.end())-PCHLines.begin());
// Determine which predefines that were used to build the PCH file are missing
// from the command line.
--
1.7.7

58
pr13303.patch Normal file
View File

@ -0,0 +1,58 @@
commit 5cf55e1c6a22ae066db5066fdc69f99564ace8ea
Author: Eric Christopher <echristo@apple.com>
Date: Thu Jul 12 23:30:25 2012 +0000
The end of the prologue should be marked with is_stmt.
Fixes PR13303.
Patch by Paul Robinson!
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@160148 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 038792b..649684a 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -1382,7 +1382,7 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) {
MF->getFunction()->getContext());
recordSourceLine(FnStartDL.getLine(), FnStartDL.getCol(),
FnStartDL.getScope(MF->getFunction()->getContext()),
- 0);
+ DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0);
}
}
diff --git a/test/DebugInfo/X86/pr13303.ll b/test/DebugInfo/X86/pr13303.ll
new file mode 100644
index 0000000..e820cb5
--- /dev/null
+++ b/test/DebugInfo/X86/pr13303.ll
@@ -0,0 +1,28 @@
+; RUN: llc %s -o %t -filetype=obj -mtriple=x86_64-unknown-linux-gnu
+; RUN: llvm-dwarfdump %t | FileCheck %s
+; PR13303
+
+; Check that the prologue ends with is_stmt here.
+; CHECK: 0x0000000000000000 {{.*}} is_stmt
+
+define i32 @main() nounwind uwtable {
+entry:
+ %retval = alloca i32, align 4
+ store i32 0, i32* %retval
+ ret i32 0, !dbg !10
+}
+
+!llvm.dbg.cu = !{!0}
+
+!0 = metadata !{i32 786449, i32 0, i32 12, metadata !"PR13303.c", metadata !"/home/probinson", metadata !"clang version 3.2 (trunk 160143)", i1 true, i1 false, metadata !"", i32 0, metadata !1, metadata !1, metadata !3, metadata !1} ; [ DW_TAG_compile_unit ] [/home/probinson/PR13303.c] [DW_LANG_C99]
+!1 = metadata !{metadata !2}
+!2 = metadata !{i32 0}
+!3 = metadata !{metadata !4}
+!4 = metadata !{metadata !5}
+!5 = metadata !{i32 786478, i32 0, metadata !6, metadata !"main", metadata !"main", metadata !"", metadata !6, i32 1, metadata !7, i1 false, i1 true, i32 0, i32 0, null, i32 0, i1 false, i32 ()* @main, null, null, metadata !1, i32 1} ; [ DW_TAG_subprogram ] [line 1] [def] [main]
+!6 = metadata !{i32 786473, metadata !"PR13303.c", metadata !"/home/probinson", null} ; [ DW_TAG_file_type ]
+!7 = metadata !{i32 786453, i32 0, metadata !"", i32 0, i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !8, i32 0, i32 0} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]
+!8 = metadata !{metadata !9}
+!9 = metadata !{i32 786468, null, metadata !"int", null, i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed]
+!10 = metadata !{i32 1, i32 14, metadata !11, null}
+!11 = metadata !{i32 786443, metadata !5, i32 1, i32 12, metadata !6, i32 0} ; [ DW_TAG_lexical_block ] [/home/probinson/PR13303.c]

View File

@ -1,28 +1,63 @@
diff --git tools/clang/include/clang/Driver/CC1Options.td tools/clang/include/clang/Driver/CC1Options.td
index 83c988a..b278082 100644
index 83c988a..b7deed0 100644
--- tools/clang/include/clang/Driver/CC1Options.td
+++ tools/clang/include/clang/Driver/CC1Options.td
@@ -452,6 +452,8 @@ def rewrite_objc : Flag<"-rewrite-objc">,
HelpText<"Rewrite ObjC into C (code rewriter example)">;
def rewrite_macros : Flag<"-rewrite-macros">,
HelpText<"Expand macros without full preprocessing">;
+def rewrite_includes : Flag<"-rewrite-includes">,
@@ -814,6 +814,8 @@ def dM : Flag<"-dM">,
HelpText<"Print macro definitions in -E mode instead of normal output">;
def dD : Flag<"-dD">,
HelpText<"Print macro definitions in -E mode in addition to normal output">;
+def frewrite_includes : Flag<"-frewrite-includes">,
+ HelpText<"Expand includes without full preprocessing">;
def migrate : Flag<"-migrate">,
HelpText<"Migrate source code">;
}
//===----------------------------------------------------------------------===//
// OpenCL Options
diff --git tools/clang/include/clang/Driver/Options.td tools/clang/include/clang/Driver/Options.td
index b796771..f58d824 100644
--- tools/clang/include/clang/Driver/Options.td
+++ tools/clang/include/clang/Driver/Options.td
@@ -362,6 +362,9 @@ def fno_trapping_math : Flag<"-fno-trapping-math">, Group<f_Group>;
def ffor_scope : Flag<"-ffor-scope">, Group<f_Group>;
def fno_for_scope : Flag<"-fno-for-scope">, Group<f_Group>;
+def frewrite_includes : Flag<"-frewrite-includes">, Group<f_Group>;
+def fno_rewrite_includes : Flag<"-fno-rewrite-includes">, Group<f_Group>;
+
def ffreestanding : Flag<"-ffreestanding">, Group<f_Group>;
def fgnu_keywords : Flag<"-fgnu-keywords">, Group<f_Group>;
def fgnu89_inline : Flag<"-fgnu89-inline">, Group<f_Group>;
diff --git tools/clang/include/clang/Frontend/FrontendOptions.h tools/clang/include/clang/Frontend/FrontendOptions.h
index 888388c..78d3adf 100644
index 888388c..48cd317 100644
--- tools/clang/include/clang/Frontend/FrontendOptions.h
+++ tools/clang/include/clang/Frontend/FrontendOptions.h
@@ -43,6 +43,7 @@ namespace frontend {
@@ -42,7 +42,7 @@ namespace frontend {
PrintDeclContext, ///< Print DeclContext and their Decls.
PrintPreamble, ///< Print the "preamble" of the input file
PrintPreprocessedInput, ///< -E mode.
RewriteMacros, ///< Expand macros but not #includes.
+ RewriteIncludes, ///< Expand #includes but not macros.
- RewriteMacros, ///< Expand macros but not #includes.
+ RewriteMacros, ///< Expand macros but not \#includes.
RewriteObjC, ///< ObjC->C Rewriter.
RewriteTest, ///< Rewriter playground
RunAnalysis, ///< Run one or more source code analyses.
diff --git tools/clang/include/clang/Frontend/PreprocessorOutputOptions.h tools/clang/include/clang/Frontend/PreprocessorOutputOptions.h
index 1eda0d4..31724cd 100644
--- tools/clang/include/clang/Frontend/PreprocessorOutputOptions.h
+++ tools/clang/include/clang/Frontend/PreprocessorOutputOptions.h
@@ -21,6 +21,7 @@ public:
unsigned ShowLineMarkers : 1; ///< Show #line markers.
unsigned ShowMacroComments : 1; ///< Show comments, even in macros.
unsigned ShowMacros : 1; ///< Print macro definitions.
+ unsigned RewriteIncludes : 1; ///< Preprocess include directives only.
public:
PreprocessorOutputOptions() {
@@ -29,6 +30,7 @@ public:
ShowLineMarkers = 1;
ShowMacroComments = 0;
ShowMacros = 0;
+ RewriteIncludes = 0;
}
};
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
@ -71,7 +106,7 @@ index 6e9ecac..ea876d9 100644
#endif
diff --git tools/clang/include/clang/Rewrite/Rewriters.h tools/clang/include/clang/Rewrite/Rewriters.h
index 203b9bc..9704fe3 100644
index 203b9bc..f5ade5a 100644
--- tools/clang/include/clang/Rewrite/Rewriters.h
+++ tools/clang/include/clang/Rewrite/Rewriters.h
@@ -18,6 +18,7 @@
@ -82,49 +117,62 @@ index 203b9bc..9704fe3 100644
/// RewriteMacrosInInput - Implement -rewrite-macros mode.
void RewriteMacrosInInput(Preprocessor &PP, raw_ostream *OS);
@@ -25,6 +26,9 @@ void RewriteMacrosInInput(Preprocessor &PP, raw_ostream *OS);
@@ -25,6 +26,10 @@ void RewriteMacrosInInput(Preprocessor &PP, raw_ostream *OS);
/// DoRewriteTest - A simple test for the TokenRewriter class.
void DoRewriteTest(Preprocessor &PP, raw_ostream *OS);
+/// RewriteIncludesInInput - Implement -rewrite-includes mode.
+void RewriteIncludesInInput(Preprocessor &PP, raw_ostream *OS, const PreprocessorOutputOptions &Opts);
+/// RewriteIncludesInInput - Implement -frewrite-includes mode.
+void RewriteIncludesInInput(Preprocessor &PP, raw_ostream *OS,
+ const PreprocessorOutputOptions &Opts);
+
} // end namespace clang
#endif
diff --git tools/clang/lib/Driver/Tools.cpp tools/clang/lib/Driver/Tools.cpp
index 47b5294..c0504e7 100644
--- tools/clang/lib/Driver/Tools.cpp
+++ tools/clang/lib/Driver/Tools.cpp
@@ -2106,6 +2106,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.getLastArg(options::OPT_fapple_kext))
CmdArgs.push_back("-fapple-kext");
+ if (Args.hasFlag(options::OPT_frewrite_includes,
+ options::OPT_fno_rewrite_includes, false))
+ CmdArgs.push_back("-frewrite-includes");
+
Args.AddLastArg(CmdArgs, options::OPT_fobjc_sender_dependent_dispatch);
Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_print_source_range_info);
Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_parseable_fixits);
diff --git tools/clang/lib/Frontend/CompilerInvocation.cpp tools/clang/lib/Frontend/CompilerInvocation.cpp
index 4c5b063..4e46973 100644
index 4c5b063..28935ce 100644
--- tools/clang/lib/Frontend/CompilerInvocation.cpp
+++ tools/clang/lib/Frontend/CompilerInvocation.cpp
@@ -430,6 +430,7 @@ static const char *getActionName(frontend::ActionKind Kind) {
case frontend::PrintPreamble: return "-print-preamble";
case frontend::PrintPreprocessedInput: return "-E";
case frontend::RewriteMacros: return "-rewrite-macros";
+ case frontend::RewriteIncludes: return "-rewrite-includes";
case frontend::RewriteObjC: return "-rewrite-objc";
case frontend::RewriteTest: return "-rewrite-test";
case frontend::RunAnalysis: return "-analyze";
@@ -1370,6 +1371,8 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
Opts.ProgramAction = frontend::PrintPreprocessedInput; break;
case OPT_rewrite_macros:
Opts.ProgramAction = frontend::RewriteMacros; break;
+ case OPT_rewrite_includes:
+ Opts.ProgramAction = frontend::RewriteIncludes; break;
case OPT_rewrite_objc:
Opts.ProgramAction = frontend::RewriteObjC; break;
case OPT_rewrite_test:
@@ -2058,6 +2058,7 @@ static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts,
Opts.ShowLineMarkers = !Args.hasArg(OPT_P);
Opts.ShowMacroComments = Args.hasArg(OPT_CC);
Opts.ShowMacros = Args.hasArg(OPT_dM) || Args.hasArg(OPT_dD);
+ Opts.RewriteIncludes = Args.hasArg(OPT_frewrite_includes);
}
static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args) {
diff --git tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index 07d2b8d..49d0bb8 100644
index 07d2b8d..0824978 100644
--- tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -73,6 +73,7 @@ static FrontendAction *CreateFrontendBaseAction(CompilerInstance &CI) {
@@ -71,7 +71,12 @@ static FrontendAction *CreateFrontendBaseAction(CompilerInstance &CI) {
case PrintDeclContext: return new DeclContextPrintAction();
case PrintPreamble: return new PrintPreambleAction();
case PrintPreprocessedInput: return new PrintPreprocessedAction();
- case PrintPreprocessedInput: return new PrintPreprocessedAction();
+ case PrintPreprocessedInput: {
+ if (CI.getPreprocessorOutputOpts().RewriteIncludes)
+ return new RewriteIncludesAction();
+ return new PrintPreprocessedAction();
+ }
+
case RewriteMacros: return new RewriteMacrosAction();
+ case RewriteIncludes: return new RewriteIncludesAction();
case RewriteObjC: return new RewriteObjCAction();
case RewriteTest: return new RewriteTestAction();
case RunAnalysis: return new ento::AnalysisAction();
diff --git tools/clang/lib/Lex/Lexer.cpp tools/clang/lib/Lex/Lexer.cpp
index 535a852..aa424b4 100644
--- tools/clang/lib/Lex/Lexer.cpp
@ -228,10 +276,10 @@ index 1753325..e462671 100644
+}
diff --git tools/clang/lib/Rewrite/RewriteIncludes.cpp tools/clang/lib/Rewrite/RewriteIncludes.cpp
new file mode 100644
index 0000000..54e09c5
index 0000000..b7de20c
--- /dev/null
+++ tools/clang/lib/Rewrite/RewriteIncludes.cpp
@@ -0,0 +1,542 @@
@@ -0,0 +1,362 @@
+//===--- RewriteIncludes.cpp - Rewrite includes into their expansions -----===//
+//
+// The LLVM Compiler Infrastructure
@ -258,7 +306,7 @@ index 0000000..54e09c5
+namespace {
+
+/// Class representing the whole rewriting process and global data for it.
+class IncludeRewriter : public PPCallbacks, public CommentHandler {
+class IncludeRewriter : public PPCallbacks {
+ /// Information about which #includes were actually performed,
+ /// created by preprocessor callbacks.
+ struct FileChange {
@ -274,14 +322,6 @@ index 0000000..54e09c5
+ typedef std::map<unsigned, FileChange> FileChangeMap;
+ FileChangeMap FileChanges;
+ unsigned LastInsertedFileChange;
+ /// From HandleComment() callback, two raw-encoded SourceLocation's,
+ /// will be sorted by the location.
+ typedef std::vector< std::pair<unsigned, unsigned> > 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,
@ -298,7 +338,6 @@ index 0000000..54e09c5
+ SourceLocation EndLoc,
+ StringRef SearchPath,
+ StringRef RelativePath);
+ virtual bool HandleComment(Preprocessor &PP, SourceRange Comment);
+private:
+ const FileChange* FindFileChangeLocation(SourceLocation Loc) const;
+};
@ -319,13 +358,6 @@ index 0000000..54e09c5
+ OwningPtr<Lexer> 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,
@ -335,7 +367,6 @@ index 0000000..54e09c5
+ 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);
@ -345,21 +376,10 @@ index 0000000..54e09c5
+
+IncludeRewriter::IncludeRewriter(Preprocessor &pp, raw_ostream &os,
+ const PreprocessorOutputOptions &Opts)
+ : PP(pp)
+ , SM(PP.getSourceManager())
+ , OS(os)
+ , DisableLineMarkers(!Opts.ShowLineMarkers)
+ , LastInsertedFileChange(0)
+ , KeepAllComments(false)
+ , KeepCommentsInCodeLines(false) {
+ : PP(pp), SM(PP.getSourceManager()), OS(os),
+ DisableLineMarkers(!Opts.ShowLineMarkers), LastInsertedFileChange(0) {
+ // If we're in microsoft mode, use normal #line instead of line markers.
+ UseLineDirective = PP.getLangOpts().MicrosoftExt;
+ // 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
@ -406,20 +426,7 @@ index 0000000..54e09c5
+ return NULL;
+}
+
+bool IncludeRewriter::HandleComment(Preprocessor &, SourceRange Comment) {
+ CommentRanges.push_back( std::make_pair(Comment.getBegin().getRawEncoding(),
+ Comment.getEnd().getRawEncoding()));
+ return false;
+}
+
+static bool CompareCommentRanges( const std::pair<unsigned, unsigned>& left,
+ const std::pair<unsigned, unsigned>& right ) {
+ return left.first < right.first;
+}
+
+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();
+}
@ -436,8 +443,6 @@ index 0000000..54e09c5
+ , Type(Type)
+ , Invalid(true)
+ , NextToWrite(0)
+ , NextToWriteLine(0)
+ , NextCommentRange(0)
+ , Line(1) {
+
+ StartLocation = SM.getLocForStartOfFile(FileId);
@ -465,6 +470,11 @@ index 0000000..54e09c5
+ Token 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);
@ -572,152 +582,11 @@ index 0000000..54e09c5
+ 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);
+ OS.write(FromFile->getBufferStart() + NextToWrite, WriteEnd - NextToWrite);
+ // count lines manually, it's faster than getPresumedLoc()
+ Line += CountNewLines(FromFile->getBufferStart() + NextToWrite,
+ WriteEnd - NextToWrite);
@ -736,10 +605,10 @@ index 0000000..54e09c5
+ do {
+ RawLex->LexFromRawLexer(DirectiveToken);
+ } while (!DirectiveToken.is(tok::eod) && DirectiveToken.isNot(tok::eof));
+ OS << "#if 0 /* expanded by -rewrite-includes */" << EOL;
+ OS << "#if 0 /* expanded by -frewrite-includes */" << EOL;
+ OutputContentUpTo(SM.getFileOffset(DirectiveToken.getLocation())
+ + DirectiveToken.getLength());
+ OS << "#endif /* expanded by -rewrite-includes */" << EOL;
+ OS << "#endif /* expanded by -frewrite-includes */" << EOL;
+}
+
+StringRef IncludeRewriter::File::NextIdentifierName(Token& RawToken) {
@ -751,12 +620,11 @@ index 0000000..54e09c5
+ return StringRef();
+}
+
+/// RewriteIncludesInInput - Implement -rewrite-includes mode.
+/// RewriteIncludesInInput - Implement -frewrite-includes mode.
+void clang::RewriteIncludesInInput(Preprocessor &PP, raw_ostream *OS,
+ const PreprocessorOutputOptions &Opts) {
+ 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.
@ -774,8 +642,6 @@ index 0000000..54e09c5
+ Rewrite->Process();
+ OS->flush();
+}
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
@ -844,15 +710,13 @@ 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
index 0000000..67a8802
--- /dev/null
+++ tools/clang/test/Frontend/rewrite-includes.c
@@ -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
@@ -0,0 +1,105 @@
+// RUN: %clang_cc1 -verify -E -frewrite-includes -DFIRST -I %S/Inputs %s -o - | FileCheck -strict-whitespace %s
+
+STARTCOMPARE
+// STARTCOMPARE
+#define A(a,b) a ## b
+A(1,2)
+#include "rewrite-includes1.h"
@ -866,345 +730,92 @@ index 0000000..52be495
+
+#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 */
+#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.
+// 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{{$}}
+// CHECK: {{^}}// STARTCOMPARE{{$}}
+// CHECK-NEXT: {{^}}#define A(a,b) a ## b{{$}}
+// CHECK-NEXT: {{^}}A(1,2){{$}}
+// CHECK-NEXT: {{^}}#if 0 /* expanded by -frewrite-includes */{{$}}
+// CHECK-NEXT: {{^}}#include "rewrite-includes1.h"{{$}}
+// CHECK-NEXT: {{^}}#endif /* expanded by -frewrite-includes */{{$}}
+// CHECK-NEXT: {{^}}# 1 "{{.*}}/Inputs/rewrite-includes1.h" 1{{$}}
+// CHECK-NEXT: {{^}}#if 0 /* expanded by -frewrite-includes */{{$}}
+// CHECK-NEXT: {{^}}#pragma clang system_header{{$}}
+// CHECK-NEXT: {{^}}#endif /* expanded by -frewrite-includes */{{$}}
+// CHECK-NEXT: {{^}}# 2 "{{.*}}/Inputs/rewrite-includes1.h" 3{{$}}
+// CHECK-NEXT: {{^}}included_line1{{$}}
+// CHECK-NEXT: {{^}}#if 0 /* expanded by -frewrite-includes */{{$}}
+// CHECK-NEXT: {{^}}#include "rewrite-includes2.h"{{$}}
+// CHECK-NEXT: {{^}}#endif /* expanded by -frewrite-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 -frewrite-includes */{{$}}
+// CHECK-NEXT: {{^}}#include HEADER{{$}}
+// CHECK-NEXT: {{^}}#endif /* expanded by -frewrite-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 -frewrite-includes */{{$}}
+// CHECK-NEXT: {{^}}#include "rewrite-includes4.h"{{$}}
+// CHECK-NEXT: {{^}}#endif /* expanded by -frewrite-includes */{{$}}
+// CHECK-NEXT: {{^}}# 12 "{{.*}}rewrite-includes.c"{{$}}
+// CHECK-NEXT: {{^}}#endif{{$}}
+// CHECK-NEXT: {{^}}#if 0 /* expanded by -frewrite-includes */{{$}}
+// CHECK-NEXT: {{^}}#/**/include /**/ "rewrite-includes5.h" /**/ {{\\}}{{$}}
+// CHECK-NEXT: {{^}} {{$}}
+// CHECK-NEXT: {{^}}#endif /* expanded by -frewrite-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 -frewrite-includes */{{$}}
+// CHECK-NEXT: {{^}}#include "rewrite-includes6.h" // comment{{$}}
+// CHECK-NEXT: {{^}}#endif /* expanded by -frewrite-includes */{{$}}
+// CHECK-NEXT: {{^}}# 1 "{{.*}}/Inputs/rewrite-includes6.h" 1{{$}}
+// CHECK-NEXT: {{^}}#if 0 /* expanded by -frewrite-includes */{{$}}
+// CHECK-NEXT: {{^}}#pragma once{{$}}
+// CHECK-NEXT: {{^}}#endif /* expanded by -frewrite-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 -frewrite-includes */{{$}}
+// CHECK-NEXT: {{^}}#include "rewrite-includes6.h" /* comment{{$}}
+// CHECK-NEXT: {{^}} continues */{{$}}
+// CHECK-NEXT: {{^}}#endif /* expanded by -frewrite-includes */{{$}}
+// CHECK-NEXT: {{^}}# 19 "{{.*}}rewrite-includes.c"{{$}}
+// CHECK-NEXT: {{^}}#if 0 /* expanded by -frewrite-includes */{{$}}
+// CHECK-NEXT: {{^}}#include "rewrite-includes7.h"{{$}}
+// CHECK-NEXT: {{^}}#endif /* expanded by -frewrite-includes */{{$}}
+// CHECK-NEXT: {{^}}# 1 "{{.*}}/Inputs/rewrite-includes7.h" 1{{$}}
+// CHECK-NEXT: {{^}}#ifndef REWRITE_INCLUDES7_H{{$}}
+// CHECK-NEXT: {{^}}#define REWRITE_INCLUDES7_H{{$}}
+// CHECK-NEXT: {{^}}included_line7{{$}}
+// CHECK-NEXT: {{^}}#endif{{$}}
+// CHECK-NEXT: {{^}}# 20 "{{.*}}rewrite-includes.c" 2{{$}}
+// CHECK-NEXT: {{^}}#if 0 /* expanded by -frewrite-includes */{{$}}
+// CHECK-NEXT: {{^}}#include "rewrite-includes7.h"{{$}}
+// CHECK-NEXT: {{^}}#endif /* expanded by -frewrite-includes */{{$}}
+// CHECK-NEXT: {{^}}# 21 "{{.*}}rewrite-includes.c"{{$}}
+// CHECK-NEXT: {{^}}#if 0 /* expanded by -frewrite-includes */{{$}}
+// CHECK-NEXT: {{^}}#include "rewrite-includes8.h" // no trailing \n in file{{$}}
+// CHECK-NEXT: {{^}}#endif /* expanded by -frewrite-includes */{{$}}
+// CHECK-NEXT: {{^}}# 1 "{{.*}}/Inputs/rewrite-includes8.h" 1{{$}}
+// CHECK-NEXT: {{^}}included_line8{{$}}
+// CHECK-NEXT: {{^}}# 22 "{{.*}}rewrite-includes.c" 2{{$}}
+// CHECK-NEXT: {{^}}#if 0 /* expanded by -frewrite-includes */{{$}}
+// CHECK-NEXT: {{^}}#include "rewrite-includes9.h" // empty file{{$}}
+// CHECK-NEXT: {{^}}#endif /* expanded by -frewrite-includes */{{$}}
+// CHECK-NEXT: {{^}}# 1 "{{.*}}/Inputs/rewrite-includes9.h" 1{{$}}
+// CHECK-NEXT: {{^}}# 23 "{{.*}}rewrite-includes.c" 2{{$}}
+// CHECK-NEXT: {{^}}// ENDCOMPARE{{$}}