70 changes: 69 additions & 1 deletion clang/lib/Driver/Tools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -386,9 +386,71 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
// wonky, but we include looking for .gch so we can support seamless
// replacement into a build system already set up to be generating
// .gch files.
int YcIndex = -1, YuIndex = -1;
{
int AI = -1;
const Arg *YcArg = Args.getLastArg(options::OPT__SLASH_Yc);
const Arg *YuArg = Args.getLastArg(options::OPT__SLASH_Yu);
for (const Arg *A : Args.filtered(options::OPT_clang_i_Group)) {
// Walk the whole i_Group and skip non "-include" flags so that the index
// here matches the index in the next loop below.
++AI;
if (!A->getOption().matches(options::OPT_include))
continue;
if (YcArg && strcmp(A->getValue(), YcArg->getValue()) == 0)
YcIndex = AI;
if (YuArg && strcmp(A->getValue(), YuArg->getValue()) == 0)
YuIndex = AI;
}
}
if (isa<PrecompileJobAction>(JA) && YcIndex != -1) {
Driver::InputList Inputs;
D.BuildInputs(getToolChain(), C.getArgs(), Inputs);
assert(Inputs.size() == 1 && "Need one input when building pch");
CmdArgs.push_back(Args.MakeArgString(Twine("-find-pch-source=") +
Inputs[0].second->getValue()));
}

bool RenderedImplicitInclude = false;
int AI = -1;
for (const Arg *A : Args.filtered(options::OPT_clang_i_Group)) {
if (A->getOption().matches(options::OPT_include)) {
++AI;

if (getToolChain().getDriver().IsCLMode()) {
// In clang-cl mode, /Ycfoo.h means that all code up to a foo.h
// include is compiled into foo.h, and everything after goes into
// the .obj file. /Yufoo.h means that all includes prior to and including
// foo.h are completely skipped and replaced with a use of the pch file
// for foo.h. (Each flag can have at most one value, multiple /Yc flags
// just mean that the last one wins.) If /Yc and /Yu are both present
// and refer to the same file, /Yc wins.
// Note that OPT__SLASH_FI gets mapped to OPT_include.
// FIXME: The code here assumes that /Yc and /Yu refer to the same file.
// cl.exe seems to support both flags with different values, but that
// seems strange (which flag does /Fp now refer to?), so don't implement
// that until someone needs that.
int PchIndex = YcIndex != -1 ? YcIndex : YuIndex;
if (PchIndex != -1) {
if (isa<PrecompileJobAction>(JA)) {
// When building the pch, skip all includes after the pch.
assert(YcIndex != -1 && PchIndex == YcIndex);
if (AI >= YcIndex)
continue;
} else {
// When using the pch, skip all includes prior to the pch.
if (AI < PchIndex)
continue;
if (AI == PchIndex) {
A->claim();
CmdArgs.push_back("-include-pch");
CmdArgs.push_back(
Args.MakeArgString(D.GetClPchPath(C, A->getValue())));
continue;
}
}
}
} else if (A->getOption().matches(options::OPT_include)) {
// Handling of gcc-style gch precompiled headers.
bool IsFirstImplicitInclude = !RenderedImplicitInclude;
RenderedImplicitInclude = true;

Expand Down Expand Up @@ -5654,6 +5716,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
getCLFallback()->GetCommand(C, JA, Output, Inputs, Args, LinkingOutput);
C.addCommand(llvm::make_unique<FallbackCommand>(
JA, *this, Exec, CmdArgs, Inputs, std::move(CLCommand)));
} else if (Args.hasArg(options::OPT__SLASH_fallback) &&
isa<PrecompileJobAction>(JA)) {
// In /fallback builds, run the main compilation even if the pch generation
// fails, so that the main compilation's fallback to cl.exe runs.
C.addCommand(llvm::make_unique<ForceSuccessCommand>(JA, *this, Exec,
CmdArgs, Inputs));
} else {
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
Expand Down
36 changes: 32 additions & 4 deletions clang/lib/Frontend/CompilerInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -712,15 +712,18 @@ std::unique_ptr<llvm::raw_pwrite_stream> CompilerInstance::createOutputFile(
// Initialization Utilities

bool CompilerInstance::InitializeSourceManager(const FrontendInputFile &Input){
return InitializeSourceManager(Input, getDiagnostics(),
getFileManager(), getSourceManager(),
getFrontendOpts());
return InitializeSourceManager(
Input, getDiagnostics(), getFileManager(), getSourceManager(),
hasPreprocessor() ? &getPreprocessor().getHeaderSearchInfo() : nullptr,
getFrontendOpts());
}

// static
bool CompilerInstance::InitializeSourceManager(const FrontendInputFile &Input,
DiagnosticsEngine &Diags,
FileManager &FileMgr,
SourceManager &SourceMgr,
HeaderSearch *HS,
const FrontendOptions &Opts) {
SrcMgr::CharacteristicKind
Kind = Input.isSystem() ? SrcMgr::C_System : SrcMgr::C_User;
Expand All @@ -737,7 +740,32 @@ bool CompilerInstance::InitializeSourceManager(const FrontendInputFile &Input,

// Figure out where to get and map in the main file.
if (InputFile != "-") {
const FileEntry *File = FileMgr.getFile(InputFile, /*OpenFile=*/true);
const FileEntry *File;
if (Opts.FindPchSource.empty()) {
File = FileMgr.getFile(InputFile, /*OpenFile=*/true);
} else {
// When building a pch file in clang-cl mode, the .h file is built as if
// it was included by a cc file. Since the driver doesn't know about
// all include search directories, the frontend must search the input
// file through HeaderSearch here, as if it had been included by the
// cc file at Opts.FindPchSource.
const FileEntry *FindFile = FileMgr.getFile(Opts.FindPchSource);
if (!FindFile) {
Diags.Report(diag::err_fe_error_reading) << Opts.FindPchSource;
return false;
}
const DirectoryLookup *UnusedCurDir;
SmallVector<std::pair<const FileEntry *, const DirectoryEntry *>, 16>
Includers;
Includers.push_back(std::make_pair(FindFile, FindFile->getDir()));
File = HS->LookupFile(InputFile, SourceLocation(), /*isAngled=*/false,
/*FromDir=*/nullptr,
/*CurDir=*/UnusedCurDir, Includers,
/*SearchPath=*/nullptr,
/*RelativePath=*/nullptr,
/*RequestingModule=*/nullptr,
/*SuggestedModule=*/nullptr, /*SkipCache=*/true);
}
if (!File) {
Diags.Report(diag::err_fe_error_reading) << InputFile;
return false;
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1107,6 +1107,7 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
= Args.getLastArgValue(OPT_foverride_record_layout_EQ);
Opts.AuxTriple =
llvm::Triple::normalize(Args.getLastArgValue(OPT_aux_triple));
Opts.FindPchSource = Args.getLastArgValue(OPT_find_pch_source_EQ);

if (const Arg *A = Args.getLastArg(OPT_arcmt_check,
OPT_arcmt_modify,
Expand Down
Empty file.
3 changes: 3 additions & 0 deletions clang/test/Driver/Inputs/pchfile.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#if defined(ERR_HEADER)
#error nope1
#endif
15 changes: 15 additions & 0 deletions clang/test/Driver/cl-pch-errorhandling.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Note: %s and %S must be preceded by --, otherwise it may be interpreted as a
// command-line option, e.g. on Mac where %s is commonly under /Users.

// /Yc but pch generation fails => main file not compiled
// This is a separate file since executing this failure path requires
// code generation, which makes this test require an x86 backend.
// REQUIRES: x86-registered-target

// RUN: not %clang_cl -internal-enable-pch -Werror /Yc%S/Inputs/pchfile.h /FI%S/Inputs/pchfile.h /c -DERR_HEADER -- %s 2>&1 \
// RUN: | FileCheck %s

// CHECK: nope1
// CHECK-NOT: nope2

#error nope2
6 changes: 6 additions & 0 deletions clang/test/Driver/cl-pch-search.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Note: %s and %S must be preceded by --, otherwise it may be interpreted as a
// command-line option, e.g. on Mac where %s is commonly under /Users.

// REQUIRES: x86-registered-target
// Check that pchfile.h next to to pchfile.cc is found correctly.
// RUN: %clang_cl -internal-enable-pch -Werror /Ycpchfile.h /FIpchfile.h /c /Fo%t.obj /Fp%t.pch -- %S/Inputs/pchfile.cpp
45 changes: 45 additions & 0 deletions clang/test/Driver/cl-pch.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Note: %s and %S must be preceded by --, otherwise it may be interpreted as a
// command-line option, e.g. on Mac where %s is commonly under /Users.

// The main test for clang-cl pch handling is cl-pch.cpp. This file only checks
// a few things for .c inputs.

// /Yc with a .c file should build a c pch file.
// RUN: %clang_cl -internal-enable-pch -Werror /Ycpchfile.h /FIpchfile.h /c -### -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YC %s
// CHECK-YC: cc1
// CHECK-YC: -emit-pch
// CHECK-YC: -o
// CHECK-YC: pchfile.pch
// CHECK-YC: -x
// CHECK-YC: "c"

// But not if /TP changes the input language to C++.
// RUN: %clang_cl /TP -internal-enable-pch -Werror /Ycpchfile.h /FIpchfile.h /c -### -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YCTP %s
// CHECK-YCTP: cc1
// CHECK-YCTP: -emit-pch
// CHECK-YCTP: -o
// CHECK-YCTP: pchfile.pch
// CHECK-YCTP: -x
// CHECK-YCTP: "c++"

// Except if a later /TC changes it back.
// RUN: %clang_cl -internal-enable-pch -Werror /Ycpchfile.h /FIpchfile.h /c -### -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YCTPTC %s
// CHECK-YCTPTC: cc1
// CHECK-YCTPTC: -emit-pch
// CHECK-YCTPTC: -o
// CHECK-YCTPTC: pchfile.pch
// CHECK-YCTPTC: -x
// CHECK-YCTPTC: "c"

// Also check lower-case /Tp flag.
// RUN: %clang_cl -internal-enable-pch -Werror /Tp%s /Ycpchfile.h /FIpchfile.h /c -### 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YCTp %s
// CHECK-YCTp: cc1
// CHECK-YCTp: -emit-pch
// CHECK-YCTp: -o
// CHECK-YCTp: pchfile.pch
// CHECK-YCTp: -x
// CHECK-YCTp: "c++"
309 changes: 309 additions & 0 deletions clang/test/Driver/cl-pch.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,309 @@
// Note: %s and %S must be preceded by --, otherwise it may be interpreted as a
// command-line option, e.g. on Mac where %s is commonly under /Users.

// /Yc
// RUN: %clang_cl -internal-enable-pch -Werror /Ycpchfile.h /FIpchfile.h /c -### -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YC %s
// 1. Build .pch file.
// CHECK-YC: cc1
// CHECK-YC: -emit-pch
// CHECK-YC: -o
// CHECK-YC: pchfile.pch
// CHECK-YC: -x
// CHECK-YC: "c++"
// 2. Use .pch file.
// CHECK-YC: cc1
// CHECK-YC: -emit-obj
// CHECK-YC: -include-pch
// CHECK-YC: pchfile.pch

// /Yc /Fo
// /Fo overrides the .obj output filename, but not the .pch filename
// RUN: %clang_cl -internal-enable-pch -Werror /Fomyobj.obj /Ycpchfile.h /FIpchfile.h /c -### -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YCO %s
// 1. Build .pch file.
// CHECK-YCO: cc1
// CHECK-YCO: -emit-pch
// CHECK-YCO: -o
// CHECK-YCO: pchfile.pch
// 2. Use .pch file.
// CHECK-YCO: cc1
// CHECK-YCO: -emit-obj
// CHECK-YCO: -include-pch
// CHECK-YCO: pchfile.pch
// CHECK-YCO: -o
// CHECK-YCO: myobj.obj

// /Yc /Y-
// /Y- disables pch generation
// RUN: %clang_cl -internal-enable-pch -Werror /Y- /Ycpchfile.h /FIpchfile.h /c -### -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YC-Y_ %s
// CHECK-YC-Y_-NOT: -emit-pch
// CHECK-YC-Y_-NOT: -include-pch

// /Yu
// RUN: %clang_cl -internal-enable-pch -Werror /Yupchfile.h /FIpchfile.h /c -### -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YU %s
// Use .pch file, but don't build it.
// CHECK-YU-NOT: -emit-pch
// CHECK-YU: cc1
// CHECK-YU: -emit-obj
// CHECK-YU: -include-pch
// CHECK-YU: pchfile.pch

// /Yu /Y-
// RUN: %clang_cl -internal-enable-pch -Werror /Y- /Yupchfile.h /FIpchfile.h /c -### -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YU-Y_ %s
// CHECK-YU-Y_-NOT: -emit-pch
// CHECK-YU-Y_-NOT: -include-pch

// /Yc /Yu -- /Yc overrides /Yc if they both refer to the same file
// RUN: %clang_cl -internal-enable-pch -Werror /Ycpchfile.h /Yupchfile.h /FIpchfile.h /c -### -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YC-YU %s
// 1. Build .pch file.
// CHECK-YC-YU: cc1
// CHECK-YC-YU: -emit-pch
// CHECK-YC-YU: -o
// CHECK-YC-YU: pchfile.pch
// 2. Use .pch file.
// CHECK-YC-YU: cc1
// CHECK-YC-YU: -emit-obj
// CHECK-YC-YU: -include-pch
// CHECK-YC-YU: pchfile.pch

// If /Yc /Yu refer to different files, semantics are pretty wonky. Since this
// doesn't seem like something that's important in practice, just punt for now.
// RUN: %clang_cl -internal-enable-pch -Werror /Ycfoo1.h /Yufoo2.h /FIfoo1.h /FIfoo2.h /c -### -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YC-YU-MISMATCH %s
// CHECK-YC-YU-MISMATCH: error: support for '/Yc' and '/Yu' with different filenames not implemented yet; flags ignored

// Similarly, punt on /Yc with more than one input file.
// RUN: %clang_cl -internal-enable-pch -Werror /Ycfoo1.h /FIfoo1.h /c -### -- %s %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YC-MULTIINPUT %s
// CHECK-YC-MULTIINPUT: error: support for '/Yc' with more than one source file not implemented yet; flag ignored

// /Yc /Yu /Y-
// RUN: %clang_cl -internal-enable-pch -Werror /Ycpchfile.h /Yupchfile.h /FIpchfile.h /Y- /c -### -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YC-YU-Y_ %s
// CHECK-YC-YU-Y_-NOT: -emit-pch
// CHECK-YC-YU-Y_-NOT: -include-pch

// Test computation of pch filename in various cases.

// /Yu /Fpout.pch => out.pch is filename
// RUN: %clang_cl -internal-enable-pch -Werror /Yupchfile.h /FIpchfile.h /Fpout.pch /c -### -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YUFP1 %s
// Use .pch file, but don't build it.
// CHECK-YUFP1: -include-pch
// CHECK-YUFP1: out.pch

// /Yu /Fpout => out.pch is filename (.pch gets added if no extension present)
// RUN: %clang_cl -internal-enable-pch -Werror /Yupchfile.h /FIpchfile.h /Fpout.pch /c -### -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YUFP2 %s
// Use .pch file, but don't build it.
// CHECK-YUFP2: -include-pch
// CHECK-YUFP2: out.pch

// /Yu /Fpout.bmp => out.bmp is filename (.pch not added when extension present)
// RUN: %clang_cl -internal-enable-pch -Werror /Yupchfile.h /FIpchfile.h /Fpout.bmp /c -### -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YUFP3 %s
// Use .pch file, but don't build it.
// CHECK-YUFP3: -include-pch
// CHECK-YUFP3: out.bmp

// /Yusub/dir.h => sub/dir.pch
// RUN: %clang_cl -internal-enable-pch -Werror /Yusub/pchfile.h /FIsub/pchfile.h /c -### -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YUFP4 %s
// Use .pch file, but don't build it.
// CHECK-YUFP4: -include-pch
// CHECK-YUFP4: sub/pchfile.pch

// /Yudir.h /Isub => dir.pch
// RUN: %clang_cl -internal-enable-pch -Werror /Yupchfile.h /FIpchfile.h /Isub /c -### -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YUFP5 %s
// Use .pch file, but don't build it.
// CHECK-YUFP5: -include-pch
// CHECK-YUFP5: pchfile.pch

// FIXME: /Fpdir: use dir/VCx0.pch when dir is directory, where x is major MSVS
// version in use.

// Spot-check one use of /Fp with /Yc too, else trust the /Yu test cases above
// also all assume to /Yc.
// RUN: %clang_cl -internal-enable-pch -Werror /Ycpchfile.h /FIpchfile.h /Fpsub/file.pch /c -### -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YCFP %s
// 1. Build .pch file.
// CHECK-YCFP: cc1
// CHECK-YCFP: -emit-pch
// CHECK-YCFP: -o
// CHECK-YCFP: sub/file.pch
// 2. Use .pch file.
// CHECK-YCFP: cc1
// CHECK-YCFP: -emit-obj
// CHECK-YCFP: -include-pch
// CHECK-YCFP: sub/file.pch

// /Ycfoo2.h /FIfoo1.h /FIfoo2.h /FIfoo3.h
// => foo1 and foo2 go into pch, foo3 into main compilation
// /Yc
// RUN: %clang_cl -internal-enable-pch -Werror /Ycfoo2.h /FIfoo1.h /FIfoo2.h /FIfoo3.h /c -### -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YCFIFIFI %s
// 1. Build .pch file: Includes foo1.h (but NOT foo3.h) and compiles foo2.h
// CHECK-YCFIFIFI: cc1
// CHECK-YCFIFIFI: -emit-pch
// CHECK-YCFIFIFI: -include
// CHECK-YCFIFIFI: foo1.h
// CHECK-YCFIFIFI-NOT: foo2.h
// CHECK-YCFIFIFI-NOT: foo3.h
// CHECK-YCFIFIFI: -o
// CHECK-YCFIFIFI: foo2.pch
// CHECK-YCFIFIFI: -x
// CHECK-YCFIFIFI: "c++"
// CHECK-YCFIFIFI: foo2.h
// 2. Use .pch file: Inlucdes foo2.pch and foo3.h
// CHECK-YCFIFIFI: cc1
// CHECK-YCFIFIFI: -emit-obj
// CHECK-YCFIFIFI-NOT: foo1.h
// CHECK-YCFIFIFI-NOT: foo2.h
// CHECK-YCFIFIFI: -include-pch
// CHECK-YCFIFIFI: foo2.pch
// CHECK-YCFIFIFI: -include
// CHECK-YCFIFIFI: foo3.h

// /Yucfoo2.h /FIfoo1.h /FIfoo2.h /FIfoo3.h
// => foo1 foo2 filtered out, foo3 into main compilation
// RUN: %clang_cl -internal-enable-pch -Werror /Yufoo2.h /FIfoo1.h /FIfoo2.h /FIfoo3.h /c -### -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YUFIFIFI %s
// Use .pch file, but don't build it.
// CHECK-YUFIFIFI-NOT: -emit-pch
// CHECK-YUFIFIFI: cc1
// CHECK-YUFIFIFI: -emit-obj
// CHECK-YUFIFIFI-NOT: foo1.h
// CHECK-YUFIFIFI-NOT: foo2.h
// CHECK-YUFIFIFI: -include-pch
// CHECK-YUFIFIFI: foo2.pch
// CHECK-YUFIFIFI: -include
// CHECK-YUFIFIFI: foo3.h

// FIXME: Implement support for /Ycfoo.h / /Yufoo.h without /FIfoo.h
// RUN: %clang_cl -internal-enable-pch -Werror /Ycfoo.h /c -### -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YC-NOFI %s
// CHECK-YC-NOFI: error: support for '/Yc' without a corresponding /FI flag not implemented yet; flag ignored
// RUN: %clang_cl -internal-enable-pch -Werror /Yufoo.h /c -### -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YU-NOFI %s
// CHECK-YU-NOFI: error: support for '/Yu' without a corresponding /FI flag not implemented yet; flag ignored

// /Yc and /FI relative to /I paths...
// The rules are:
// Yu/Yc and FI parameter must match exactly, else it's not found
// Must match literally exactly: /FI./foo.h /Ycfoo.h does _not_ work.
// However, the path can be relative to /I paths.
// FIXME: Update the error messages below once /FI is no longer required, but
// these test cases all should stay failures as they fail with cl.exe.

// Check that ./ isn't canonicalized away.
// RUN: %clang_cl -internal-enable-pch -Werror /Ycpchfile.h /FI./pchfile.h /c -### -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YC-I1 %s
// CHECK-YC-I1: support for '/Yc' without a corresponding /FI flag not implemented yet; flag ignored

// Check that ./ isn't canonicalized away.
// RUN: %clang_cl -internal-enable-pch -Werror /Yc./pchfile.h /FIpchfile.h /c -### -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YC-I2 %s
// CHECK-YC-I2: support for '/Yc' without a corresponding /FI flag not implemented yet; flag ignored

// With an actual /I argument.
// RUN: %clang_cl -internal-enable-pch -Werror /Ifoo /Ycpchfile.h /FIpchfile.h /c -### -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YC-I3 %s
// 1. This writes pchfile.pch into the root dir, even if this will pick up
// foo/pchfile.h
// CHECK-YC-I3: cc1
// CHECK-YC-I3: -emit-pch
// CHECK-YC-I3: -o
// CHECK-YC-I3: pchfile.pch
// 2. Use .pch file.
// CHECK-YC-I3: cc1
// CHECK-YC-I3: -emit-obj
// CHECK-YC-I3: -include-pch
// CHECK-YC-I3: pchfile.pch

// Check that ./ isn't canonicalized away for /Yu either.
// RUN: %clang_cl -internal-enable-pch -Werror /Yupchfile.h /FI./pchfile.h /c -### -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YU-I1 %s
// CHECK-YU-I1: support for '/Yu' without a corresponding /FI flag not implemented yet; flag ignored

// But /FIfoo/bar.h /Ycfoo\bar.h does work, as does /FIfOo.h /Ycfoo.H
// FIXME: This part isn't implemented yet. The following two tests should not
// show an error but do regular /Yu handling.
// RUN: %clang_cl -internal-enable-pch -Werror /YupchFILE.h /FI./pchfile.h /c -### -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YU-CASE %s
// CHECK-YU-CASE: support for '/Yu' without a corresponding /FI flag not implemented yet; flag ignored
// RUN: %clang_cl -internal-enable-pch -Werror /Yu./pchfile.h /FI.\pchfile.h /c -### -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YU-SLASH %s
// CHECK-YU-SLASH: support for '/Yu' without a corresponding /FI flag not implemented yet; flag ignored

// cl.exe warns on multiple /Yc, /Yu, /Fp arguments, but clang-cl silently just
// uses the last one. This is true for e.g. /Fo too, so not warning on this
// is self-consistent with clang-cl's flag handling.

// Interaction with /fallback

// /Yc /fallback => /Yc not passed on (but /FI is)
// RUN: %clang_cl -internal-enable-pch -Werror /Ycpchfile.h /FIpchfile.h /Fpfoo.pch /fallback /c -### -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YC-FALLBACK %s
// Note that in /fallback builds, if creation of the pch fails the main compile
// does still run so that /fallback can have an effect (this part is not tested)
// CHECK-YC-FALLBACK: cc1
// CHECK-YC-FALLBACK: -emit-obj
// CHECK-YC-FALLBACK: -include-pch
// CHECK-YC-FALLBACK: foo.pch
// CHECK-YC-FALLBACK: ||
// CHECK-YC-FALLBACK: cl.exe
// CHECK-YC-FALLBACK-NOT: -include-pch
// CHECK-YC-FALLBACK-NOT: /Ycpchfile.h
// CHECK-YC-FALLBACK: /FIpchfile.h
// CHECK-YC-FALLBACK-NOT: /Fpfoo.pch

// /Yu /fallback => /Yu not passed on (but /FI is)
// RUN: %clang_cl -internal-enable-pch -Werror /Yupchfile.h /FIpchfile.h /Fpfoo.pch /fallback /c -### -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YU-FALLBACK %s
// CHECK-YU-FALLBACK-NOT: -emit-pch
// CHECK-YU-FALLBACK: cc1
// CHECK-YU-FALLBACK: -emit-obj
// CHECK-YU-FALLBACK: -include-pch
// CHECK-YU-FALLBACK: foo.pch
// CHECK-YU-FALLBACK: ||
// CHECK-YU-FALLBACK: cl.exe
// CHECK-YU-FALLBACK-NOT: -include-pch
// CHECK-YU-FALLBACK-NOT: /Yupchfile.h
// CHECK-YU-FALLBACK: /FIpchfile.h
// CHECK-YU-FALLBACK-NOT: /Fpfoo.pch

// /FI without /Yu => pch file not used, even if it exists (different from
// -include, which picks up .gch files if they exist).
// RUN: touch %t.pch
// RUN: %clang_cl -internal-enable-pch -Werror /FI%t.pch /Fp%t.pch /c -### -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-FI %s
// CHECK-FI-NOT: -include-pch
// CHECK-FI: -include

// Test interaction of /Yc with language mode flags.

// If /TC changes the input language to C, a c pch file should be produced.
// RUN: %clang_cl /TC -internal-enable-pch -Werror /Ycpchfile.h /FIpchfile.h /c -### -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YCTC %s
// CHECK-YCTC: cc1
// CHECK-YCTC: -emit-pch
// CHECK-YCTC: -o
// CHECK-YCTC: pchfile.pch
// CHECK-YCTC: -x
// CHECK-YCTP: "c"

// Also check lower-case /Tc variant.
// RUN: %clang_cl -internal-enable-pch -Werror /Ycpchfile.h /FIpchfile.h /c -### /Tc%s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YCTc %s
// CHECK-YCTc: cc1
// CHECK-YCTc: -emit-pch
// CHECK-YCTc: -o
// CHECK-YCTc: pchfile.pch
// CHECK-YCTc: -x
// CHECK-YCTc: "c"