forked from OSchip/llvm-project
[PCH/Modules] Check that the specific module cache path the PCH was built with, is the same as
the one in the current compiler invocation. If they differ reject the PCH. This protects against the badness occurring from getting modules loaded from different module caches (see crashes). rdar://19889860 llvm-svn: 229909
This commit is contained in:
parent
dfedfeb298
commit
bd0b651bd2
|
@ -41,6 +41,8 @@ def err_pch_langopt_value_mismatch : Error<
|
||||||
"%0 differs in PCH file vs. current file">;
|
"%0 differs in PCH file vs. current file">;
|
||||||
def err_pch_diagopt_mismatch : Error<"%0 is currently enabled, but was not in "
|
def err_pch_diagopt_mismatch : Error<"%0 is currently enabled, but was not in "
|
||||||
"the PCH file">;
|
"the PCH file">;
|
||||||
|
def err_pch_modulecache_mismatch : Error<"PCH was compiled with module cache "
|
||||||
|
"path '%0', but the path is currently '%1'">;
|
||||||
|
|
||||||
def err_pch_version_too_old : Error<
|
def err_pch_version_too_old : Error<
|
||||||
"PCH file uses an older PCH format that is no longer supported">;
|
"PCH file uses an older PCH format that is no longer supported">;
|
||||||
|
|
|
@ -575,6 +575,8 @@ public:
|
||||||
/// and replace any existing one with it.
|
/// and replace any existing one with it.
|
||||||
void createPreprocessor(TranslationUnitKind TUKind);
|
void createPreprocessor(TranslationUnitKind TUKind);
|
||||||
|
|
||||||
|
std::string getSpecificModuleCachePath();
|
||||||
|
|
||||||
/// Create the AST context.
|
/// Create the AST context.
|
||||||
void createASTContext();
|
void createASTContext();
|
||||||
|
|
||||||
|
|
|
@ -153,6 +153,7 @@ public:
|
||||||
/// \returns true to indicate the header search options are invalid, or false
|
/// \returns true to indicate the header search options are invalid, or false
|
||||||
/// otherwise.
|
/// otherwise.
|
||||||
virtual bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
|
virtual bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
|
||||||
|
StringRef SpecificModuleCachePath,
|
||||||
bool Complain) {
|
bool Complain) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -230,6 +231,7 @@ public:
|
||||||
bool Complain) override;
|
bool Complain) override;
|
||||||
|
|
||||||
bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
|
bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
|
||||||
|
StringRef SpecificModuleCachePath,
|
||||||
bool Complain) override;
|
bool Complain) override;
|
||||||
bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
|
bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
|
||||||
bool Complain,
|
bool Complain,
|
||||||
|
@ -261,6 +263,9 @@ public:
|
||||||
bool Complain) override;
|
bool Complain) override;
|
||||||
bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, bool Complain,
|
bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, bool Complain,
|
||||||
std::string &SuggestedPredefines) override;
|
std::string &SuggestedPredefines) override;
|
||||||
|
bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
|
||||||
|
StringRef SpecificModuleCachePath,
|
||||||
|
bool Complain) override;
|
||||||
void ReadCounter(const serialization::ModuleFile &M, unsigned Value) override;
|
void ReadCounter(const serialization::ModuleFile &M, unsigned Value) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -1496,7 +1501,8 @@ public:
|
||||||
FileManager &FileMgr,
|
FileManager &FileMgr,
|
||||||
const LangOptions &LangOpts,
|
const LangOptions &LangOpts,
|
||||||
const TargetOptions &TargetOpts,
|
const TargetOptions &TargetOpts,
|
||||||
const PreprocessorOptions &PPOpts);
|
const PreprocessorOptions &PPOpts,
|
||||||
|
std::string ExistingModuleCachePath);
|
||||||
|
|
||||||
/// \brief Returns the suggested contents of the predefines buffer,
|
/// \brief Returns the suggested contents of the predefines buffer,
|
||||||
/// which contains a (typically-empty) subset of the predefines
|
/// which contains a (typically-empty) subset of the predefines
|
||||||
|
|
|
@ -329,14 +329,7 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) {
|
||||||
|
|
||||||
PP->setPreprocessedOutput(getPreprocessorOutputOpts().ShowCPP);
|
PP->setPreprocessedOutput(getPreprocessorOutputOpts().ShowCPP);
|
||||||
|
|
||||||
// Set up the module path, including the hash for the
|
PP->getHeaderSearchInfo().setModuleCachePath(getSpecificModuleCachePath());
|
||||||
// module-creation options.
|
|
||||||
SmallString<256> SpecificModuleCache(
|
|
||||||
getHeaderSearchOpts().ModuleCachePath);
|
|
||||||
if (!getHeaderSearchOpts().DisableModuleHash)
|
|
||||||
llvm::sys::path::append(SpecificModuleCache,
|
|
||||||
getInvocation().getModuleHash());
|
|
||||||
PP->getHeaderSearchInfo().setModuleCachePath(SpecificModuleCache);
|
|
||||||
|
|
||||||
// Handle generating dependencies, if requested.
|
// Handle generating dependencies, if requested.
|
||||||
const DependencyOutputOptions &DepOpts = getDependencyOutputOpts();
|
const DependencyOutputOptions &DepOpts = getDependencyOutputOpts();
|
||||||
|
@ -373,6 +366,17 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string CompilerInstance::getSpecificModuleCachePath() {
|
||||||
|
// Set up the module path, including the hash for the
|
||||||
|
// module-creation options.
|
||||||
|
SmallString<256> SpecificModuleCache(
|
||||||
|
getHeaderSearchOpts().ModuleCachePath);
|
||||||
|
if (!getHeaderSearchOpts().DisableModuleHash)
|
||||||
|
llvm::sys::path::append(SpecificModuleCache,
|
||||||
|
getInvocation().getModuleHash());
|
||||||
|
return SpecificModuleCache.str();
|
||||||
|
}
|
||||||
|
|
||||||
// ASTContext
|
// ASTContext
|
||||||
|
|
||||||
void CompilerInstance::createASTContext() {
|
void CompilerInstance::createASTContext() {
|
||||||
|
|
|
@ -262,6 +262,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
|
||||||
FileManager &FileMgr = CI.getFileManager();
|
FileManager &FileMgr = CI.getFileManager();
|
||||||
PreprocessorOptions &PPOpts = CI.getPreprocessorOpts();
|
PreprocessorOptions &PPOpts = CI.getPreprocessorOpts();
|
||||||
StringRef PCHInclude = PPOpts.ImplicitPCHInclude;
|
StringRef PCHInclude = PPOpts.ImplicitPCHInclude;
|
||||||
|
std::string SpecificModuleCachePath = CI.getSpecificModuleCachePath();
|
||||||
if (const DirectoryEntry *PCHDir = FileMgr.getDirectory(PCHInclude)) {
|
if (const DirectoryEntry *PCHDir = FileMgr.getDirectory(PCHInclude)) {
|
||||||
std::error_code EC;
|
std::error_code EC;
|
||||||
SmallString<128> DirNative;
|
SmallString<128> DirNative;
|
||||||
|
@ -273,7 +274,8 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
|
||||||
if (ASTReader::isAcceptableASTFile(Dir->path(), FileMgr,
|
if (ASTReader::isAcceptableASTFile(Dir->path(), FileMgr,
|
||||||
CI.getLangOpts(),
|
CI.getLangOpts(),
|
||||||
CI.getTargetOpts(),
|
CI.getTargetOpts(),
|
||||||
CI.getPreprocessorOpts())) {
|
CI.getPreprocessorOpts(),
|
||||||
|
SpecificModuleCachePath)) {
|
||||||
PPOpts.ImplicitPCHInclude = Dir->path();
|
PPOpts.ImplicitPCHInclude = Dir->path();
|
||||||
Found = true;
|
Found = true;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -501,9 +501,11 @@ namespace {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
|
bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
|
||||||
|
StringRef SpecificModuleCachePath,
|
||||||
bool Complain) override {
|
bool Complain) override {
|
||||||
Out.indent(2) << "Header search options:\n";
|
Out.indent(2) << "Header search options:\n";
|
||||||
Out.indent(4) << "System root [-isysroot=]: '" << HSOpts.Sysroot << "'\n";
|
Out.indent(4) << "System root [-isysroot=]: '" << HSOpts.Sysroot << "'\n";
|
||||||
|
Out.indent(4) << "Module Cache: '" << SpecificModuleCachePath << "'\n";
|
||||||
DUMP_BOOLEAN(HSOpts.UseBuiltinIncludes,
|
DUMP_BOOLEAN(HSOpts.UseBuiltinIncludes,
|
||||||
"Use builtin include directories [-nobuiltininc]");
|
"Use builtin include directories [-nobuiltininc]");
|
||||||
DUMP_BOOLEAN(HSOpts.UseStandardSystemIncludes,
|
DUMP_BOOLEAN(HSOpts.UseStandardSystemIncludes,
|
||||||
|
|
|
@ -108,9 +108,12 @@ ChainedASTReaderListener::ReadFileSystemOptions(const FileSystemOptions &FSOpts,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChainedASTReaderListener::ReadHeaderSearchOptions(
|
bool ChainedASTReaderListener::ReadHeaderSearchOptions(
|
||||||
const HeaderSearchOptions &HSOpts, bool Complain) {
|
const HeaderSearchOptions &HSOpts, StringRef SpecificModuleCachePath,
|
||||||
return First->ReadHeaderSearchOptions(HSOpts, Complain) ||
|
bool Complain) {
|
||||||
Second->ReadHeaderSearchOptions(HSOpts, Complain);
|
return First->ReadHeaderSearchOptions(HSOpts, SpecificModuleCachePath,
|
||||||
|
Complain) ||
|
||||||
|
Second->ReadHeaderSearchOptions(HSOpts, SpecificModuleCachePath,
|
||||||
|
Complain);
|
||||||
}
|
}
|
||||||
bool ChainedASTReaderListener::ReadPreprocessorOptions(
|
bool ChainedASTReaderListener::ReadPreprocessorOptions(
|
||||||
const PreprocessorOptions &PPOpts, bool Complain,
|
const PreprocessorOptions &PPOpts, bool Complain,
|
||||||
|
@ -591,6 +594,36 @@ bool PCHValidator::ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
|
||||||
PP.getLangOpts());
|
PP.getLangOpts());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check the header search options deserialized from the control block
|
||||||
|
/// against the header search options in an existing preprocessor.
|
||||||
|
///
|
||||||
|
/// \param Diags If non-null, produce diagnostics for any mismatches incurred.
|
||||||
|
static bool checkHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
|
||||||
|
StringRef SpecificModuleCachePath,
|
||||||
|
StringRef ExistingModuleCachePath,
|
||||||
|
DiagnosticsEngine *Diags,
|
||||||
|
const LangOptions &LangOpts) {
|
||||||
|
if (LangOpts.Modules) {
|
||||||
|
if (SpecificModuleCachePath != ExistingModuleCachePath) {
|
||||||
|
if (Diags)
|
||||||
|
Diags->Report(diag::err_pch_modulecache_mismatch)
|
||||||
|
<< SpecificModuleCachePath << ExistingModuleCachePath;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PCHValidator::ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
|
||||||
|
StringRef SpecificModuleCachePath,
|
||||||
|
bool Complain) {
|
||||||
|
return checkHeaderSearchOptions(HSOpts, SpecificModuleCachePath,
|
||||||
|
PP.getHeaderSearchInfo().getModuleCachePath(),
|
||||||
|
Complain ? &Reader.Diags : nullptr,
|
||||||
|
PP.getLangOpts());
|
||||||
|
}
|
||||||
|
|
||||||
void PCHValidator::ReadCounter(const ModuleFile &M, unsigned Value) {
|
void PCHValidator::ReadCounter(const ModuleFile &M, unsigned Value) {
|
||||||
PP.setCounterValue(Value);
|
PP.setCounterValue(Value);
|
||||||
}
|
}
|
||||||
|
@ -4191,16 +4224,19 @@ namespace {
|
||||||
const LangOptions &ExistingLangOpts;
|
const LangOptions &ExistingLangOpts;
|
||||||
const TargetOptions &ExistingTargetOpts;
|
const TargetOptions &ExistingTargetOpts;
|
||||||
const PreprocessorOptions &ExistingPPOpts;
|
const PreprocessorOptions &ExistingPPOpts;
|
||||||
|
std::string ExistingModuleCachePath;
|
||||||
FileManager &FileMgr;
|
FileManager &FileMgr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SimplePCHValidator(const LangOptions &ExistingLangOpts,
|
SimplePCHValidator(const LangOptions &ExistingLangOpts,
|
||||||
const TargetOptions &ExistingTargetOpts,
|
const TargetOptions &ExistingTargetOpts,
|
||||||
const PreprocessorOptions &ExistingPPOpts,
|
const PreprocessorOptions &ExistingPPOpts,
|
||||||
|
StringRef ExistingModuleCachePath,
|
||||||
FileManager &FileMgr)
|
FileManager &FileMgr)
|
||||||
: ExistingLangOpts(ExistingLangOpts),
|
: ExistingLangOpts(ExistingLangOpts),
|
||||||
ExistingTargetOpts(ExistingTargetOpts),
|
ExistingTargetOpts(ExistingTargetOpts),
|
||||||
ExistingPPOpts(ExistingPPOpts),
|
ExistingPPOpts(ExistingPPOpts),
|
||||||
|
ExistingModuleCachePath(ExistingModuleCachePath),
|
||||||
FileMgr(FileMgr)
|
FileMgr(FileMgr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -4214,6 +4250,13 @@ namespace {
|
||||||
bool Complain) override {
|
bool Complain) override {
|
||||||
return checkTargetOptions(ExistingTargetOpts, TargetOpts, nullptr);
|
return checkTargetOptions(ExistingTargetOpts, TargetOpts, nullptr);
|
||||||
}
|
}
|
||||||
|
bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
|
||||||
|
StringRef SpecificModuleCachePath,
|
||||||
|
bool Complain) override {
|
||||||
|
return checkHeaderSearchOptions(HSOpts, SpecificModuleCachePath,
|
||||||
|
ExistingModuleCachePath,
|
||||||
|
nullptr, ExistingLangOpts);
|
||||||
|
}
|
||||||
bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
|
bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
|
||||||
bool Complain,
|
bool Complain,
|
||||||
std::string &SuggestedPredefines) override {
|
std::string &SuggestedPredefines) override {
|
||||||
|
@ -4408,8 +4451,10 @@ bool ASTReader::isAcceptableASTFile(StringRef Filename,
|
||||||
FileManager &FileMgr,
|
FileManager &FileMgr,
|
||||||
const LangOptions &LangOpts,
|
const LangOptions &LangOpts,
|
||||||
const TargetOptions &TargetOpts,
|
const TargetOptions &TargetOpts,
|
||||||
const PreprocessorOptions &PPOpts) {
|
const PreprocessorOptions &PPOpts,
|
||||||
SimplePCHValidator validator(LangOpts, TargetOpts, PPOpts, FileMgr);
|
std::string ExistingModuleCachePath) {
|
||||||
|
SimplePCHValidator validator(LangOpts, TargetOpts, PPOpts,
|
||||||
|
ExistingModuleCachePath, FileMgr);
|
||||||
return !readASTFileControlBlock(Filename, FileMgr, validator);
|
return !readASTFileControlBlock(Filename, FileMgr, validator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4780,8 +4825,10 @@ bool ASTReader::ParseHeaderSearchOptions(const RecordData &Record,
|
||||||
HSOpts.UseStandardSystemIncludes = Record[Idx++];
|
HSOpts.UseStandardSystemIncludes = Record[Idx++];
|
||||||
HSOpts.UseStandardCXXIncludes = Record[Idx++];
|
HSOpts.UseStandardCXXIncludes = Record[Idx++];
|
||||||
HSOpts.UseLibcxx = Record[Idx++];
|
HSOpts.UseLibcxx = Record[Idx++];
|
||||||
|
std::string SpecificModuleCachePath = ReadString(Record, Idx);
|
||||||
|
|
||||||
return Listener.ReadHeaderSearchOptions(HSOpts, Complain);
|
return Listener.ReadHeaderSearchOptions(HSOpts, SpecificModuleCachePath,
|
||||||
|
Complain);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ASTReader::ParsePreprocessorOptions(const RecordData &Record,
|
bool ASTReader::ParsePreprocessorOptions(const RecordData &Record,
|
||||||
|
|
|
@ -1344,6 +1344,8 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
|
||||||
Record.push_back(HSOpts.UseStandardSystemIncludes);
|
Record.push_back(HSOpts.UseStandardSystemIncludes);
|
||||||
Record.push_back(HSOpts.UseStandardCXXIncludes);
|
Record.push_back(HSOpts.UseStandardCXXIncludes);
|
||||||
Record.push_back(HSOpts.UseLibcxx);
|
Record.push_back(HSOpts.UseLibcxx);
|
||||||
|
// Write out the specific module cache path that contains the module files.
|
||||||
|
AddString(PP.getHeaderSearchInfo().getModuleCachePath(), Record);
|
||||||
Stream.EmitRecord(HEADER_SEARCH_OPTIONS, Record);
|
Stream.EmitRecord(HEADER_SEARCH_OPTIONS, Record);
|
||||||
|
|
||||||
// Preprocessor options.
|
// Preprocessor options.
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
// RUN: %clang_cc1 -fmodules-cache-path=%t.modules -fmodules -I %S/Inputs -emit-pch -o %t.pch -x objective-c-header %s -verify
|
// RUN: %clang_cc1 -fmodules-cache-path=%t.modules -fmodules -I %S/Inputs -emit-pch -o %t.pch -x objective-c-header %s -verify
|
||||||
// RUN: not %clang_cc1 -fmodules-cache-path=%t.modules -DIGNORED=1 -fmodules -I %S/Inputs -include-pch %t.pch %s > %t.err 2>&1
|
// RUN: not %clang_cc1 -fmodules-cache-path=%t.modules -DIGNORED=1 -fmodules -I %S/Inputs -include-pch %t.pch %s > %t.err 2>&1
|
||||||
// RUN: FileCheck -check-prefix=CHECK-CONFLICT %s < %t.err
|
// RUN: FileCheck -check-prefix=CHECK-CONFLICT %s < %t.err
|
||||||
// CHECK-CONFLICT: module 'ignored_macros' found in both
|
// CHECK-CONFLICT: PCH was compiled with module cache path
|
||||||
|
|
||||||
// Third trial: pass -DIGNORED=1 only to the second invocation, but
|
// Third trial: pass -DIGNORED=1 only to the second invocation, but
|
||||||
// make it ignored. There should be no failure, IGNORED is defined in
|
// make it ignored. There should be no failure, IGNORED is defined in
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
// RUN: %clang_cc1 -x objective-c-header -fmodules -fmodules-cache-path=%t -w -Werror=auto-import %s -I %S/Inputs \
|
// RUN: %clang_cc1 -x objective-c-header -fmodules -fmodules-cache-path=%t -w -Werror=auto-import %s -I %S/Inputs \
|
||||||
// RUN: -fmodule-implementation-of category_right -emit-pch -o %t.pch
|
// RUN: -fmodule-implementation-of category_right -emit-pch -o %t.pch
|
||||||
// RUN: %clang_cc1 -x objective-c-header -fmodules -fmodules-cache-path=%t -w -Werror=auto-import %s -I %S/Inputs \
|
// RUN: %clang_cc1 -x objective-c-header -fmodules -fmodules-cache-path=%t -w -Werror=auto-import %s -I %S/Inputs \
|
||||||
// RUN: -DWITH_PREFIX -include-pch %t.pch -fmodule-implementation-of category_right
|
// RUN: -DWITH_PREFIX -fmodules-ignore-macro=WITH_PREFIX -include-pch %t.pch -fmodule-implementation-of category_right
|
||||||
|
|
||||||
#ifndef WITH_PREFIX
|
#ifndef WITH_PREFIX
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
void make_foo(void);
|
|
@ -0,0 +1,3 @@
|
||||||
|
module Foo {
|
||||||
|
header "Foo.h"
|
||||||
|
}
|
|
@ -10,7 +10,7 @@
|
||||||
// Test with modules.
|
// Test with modules.
|
||||||
// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fcxx-exceptions -fexceptions -fmodules -x c++-header -emit-pch -o %t %S/cxx-templates.h
|
// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fcxx-exceptions -fexceptions -fmodules -x c++-header -emit-pch -o %t %S/cxx-templates.h
|
||||||
// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fcxx-exceptions -fexceptions -fmodules -include-pch %t -verify %s -ast-dump -o -
|
// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fcxx-exceptions -fexceptions -fmodules -include-pch %t -verify %s -ast-dump -o -
|
||||||
// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fcxx-exceptions -fexceptions -fmodules -include-pch %t %s -emit-llvm -o - -error-on-deserialized-decl doNotDeserialize -DNO_ERRORS | FileCheck %s
|
// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fcxx-exceptions -fexceptions -fmodules -include-pch %t %s -emit-llvm -o - -error-on-deserialized-decl doNotDeserialize -DNO_ERRORS -fmodules-ignore-macro=NO_ERRORS | FileCheck %s
|
||||||
|
|
||||||
// Test with pch and delayed template parsing.
|
// Test with pch and delayed template parsing.
|
||||||
// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fcxx-exceptions -fdelayed-template-parsing -fexceptions -x c++-header -emit-pch -o %t %S/cxx-templates.h
|
// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fcxx-exceptions -fdelayed-template-parsing -fexceptions -x c++-header -emit-pch -o %t %S/cxx-templates.h
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
// RUN: rm -rf %t.mcp
|
||||||
|
// RUN: rm -rf %t.err
|
||||||
|
// RUN: %clang_cc1 -emit-pch -o %t.pch %s -I %S/Inputs/modules -fmodules -fmodules-cache-path=%t.mcp
|
||||||
|
// RUN: not %clang_cc1 -fsyntax-only -include-pch %t.pch %s -I %S/Inputs/modules -fmodules -fmodules-cache-path=%t.mcp -fdisable-module-hash 2> %t.err
|
||||||
|
// RUN: FileCheck -input-file=%t.err %s
|
||||||
|
|
||||||
|
// CHECK: error: PCH was compiled with module cache path {{.*}}, but the path is currently {{.*}}
|
||||||
|
@import Foo;
|
Loading…
Reference in New Issue