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">;
|
||||
def err_pch_diagopt_mismatch : Error<"%0 is currently enabled, but was not in "
|
||||
"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<
|
||||
"PCH file uses an older PCH format that is no longer supported">;
|
||||
|
|
|
@ -575,6 +575,8 @@ public:
|
|||
/// and replace any existing one with it.
|
||||
void createPreprocessor(TranslationUnitKind TUKind);
|
||||
|
||||
std::string getSpecificModuleCachePath();
|
||||
|
||||
/// Create the AST context.
|
||||
void createASTContext();
|
||||
|
||||
|
|
|
@ -153,6 +153,7 @@ public:
|
|||
/// \returns true to indicate the header search options are invalid, or false
|
||||
/// otherwise.
|
||||
virtual bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
|
||||
StringRef SpecificModuleCachePath,
|
||||
bool Complain) {
|
||||
return false;
|
||||
}
|
||||
|
@ -230,6 +231,7 @@ public:
|
|||
bool Complain) override;
|
||||
|
||||
bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
|
||||
StringRef SpecificModuleCachePath,
|
||||
bool Complain) override;
|
||||
bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
|
||||
bool Complain,
|
||||
|
@ -261,6 +263,9 @@ public:
|
|||
bool Complain) override;
|
||||
bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, bool Complain,
|
||||
std::string &SuggestedPredefines) override;
|
||||
bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
|
||||
StringRef SpecificModuleCachePath,
|
||||
bool Complain) override;
|
||||
void ReadCounter(const serialization::ModuleFile &M, unsigned Value) override;
|
||||
|
||||
private:
|
||||
|
@ -1496,7 +1501,8 @@ public:
|
|||
FileManager &FileMgr,
|
||||
const LangOptions &LangOpts,
|
||||
const TargetOptions &TargetOpts,
|
||||
const PreprocessorOptions &PPOpts);
|
||||
const PreprocessorOptions &PPOpts,
|
||||
std::string ExistingModuleCachePath);
|
||||
|
||||
/// \brief Returns the suggested contents of the predefines buffer,
|
||||
/// which contains a (typically-empty) subset of the predefines
|
||||
|
|
|
@ -329,14 +329,7 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) {
|
|||
|
||||
PP->setPreprocessedOutput(getPreprocessorOutputOpts().ShowCPP);
|
||||
|
||||
// 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());
|
||||
PP->getHeaderSearchInfo().setModuleCachePath(SpecificModuleCache);
|
||||
PP->getHeaderSearchInfo().setModuleCachePath(getSpecificModuleCachePath());
|
||||
|
||||
// Handle generating dependencies, if requested.
|
||||
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
|
||||
|
||||
void CompilerInstance::createASTContext() {
|
||||
|
|
|
@ -262,6 +262,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
|
|||
FileManager &FileMgr = CI.getFileManager();
|
||||
PreprocessorOptions &PPOpts = CI.getPreprocessorOpts();
|
||||
StringRef PCHInclude = PPOpts.ImplicitPCHInclude;
|
||||
std::string SpecificModuleCachePath = CI.getSpecificModuleCachePath();
|
||||
if (const DirectoryEntry *PCHDir = FileMgr.getDirectory(PCHInclude)) {
|
||||
std::error_code EC;
|
||||
SmallString<128> DirNative;
|
||||
|
@ -273,7 +274,8 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
|
|||
if (ASTReader::isAcceptableASTFile(Dir->path(), FileMgr,
|
||||
CI.getLangOpts(),
|
||||
CI.getTargetOpts(),
|
||||
CI.getPreprocessorOpts())) {
|
||||
CI.getPreprocessorOpts(),
|
||||
SpecificModuleCachePath)) {
|
||||
PPOpts.ImplicitPCHInclude = Dir->path();
|
||||
Found = true;
|
||||
break;
|
||||
|
|
|
@ -501,9 +501,11 @@ namespace {
|
|||
}
|
||||
|
||||
bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
|
||||
StringRef SpecificModuleCachePath,
|
||||
bool Complain) override {
|
||||
Out.indent(2) << "Header search options:\n";
|
||||
Out.indent(4) << "System root [-isysroot=]: '" << HSOpts.Sysroot << "'\n";
|
||||
Out.indent(4) << "Module Cache: '" << SpecificModuleCachePath << "'\n";
|
||||
DUMP_BOOLEAN(HSOpts.UseBuiltinIncludes,
|
||||
"Use builtin include directories [-nobuiltininc]");
|
||||
DUMP_BOOLEAN(HSOpts.UseStandardSystemIncludes,
|
||||
|
|
|
@ -108,9 +108,12 @@ ChainedASTReaderListener::ReadFileSystemOptions(const FileSystemOptions &FSOpts,
|
|||
}
|
||||
|
||||
bool ChainedASTReaderListener::ReadHeaderSearchOptions(
|
||||
const HeaderSearchOptions &HSOpts, bool Complain) {
|
||||
return First->ReadHeaderSearchOptions(HSOpts, Complain) ||
|
||||
Second->ReadHeaderSearchOptions(HSOpts, Complain);
|
||||
const HeaderSearchOptions &HSOpts, StringRef SpecificModuleCachePath,
|
||||
bool Complain) {
|
||||
return First->ReadHeaderSearchOptions(HSOpts, SpecificModuleCachePath,
|
||||
Complain) ||
|
||||
Second->ReadHeaderSearchOptions(HSOpts, SpecificModuleCachePath,
|
||||
Complain);
|
||||
}
|
||||
bool ChainedASTReaderListener::ReadPreprocessorOptions(
|
||||
const PreprocessorOptions &PPOpts, bool Complain,
|
||||
|
@ -464,7 +467,7 @@ collectMacroDefinitions(const PreprocessorOptions &PPOpts,
|
|||
Macros[MacroName] = std::make_pair(MacroBody, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// \brief Check the preprocessor options deserialized from the control block
|
||||
/// against the preprocessor options in an existing preprocessor.
|
||||
///
|
||||
|
@ -591,6 +594,36 @@ bool PCHValidator::ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
|
|||
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) {
|
||||
PP.setCounterValue(Value);
|
||||
}
|
||||
|
@ -4191,16 +4224,19 @@ namespace {
|
|||
const LangOptions &ExistingLangOpts;
|
||||
const TargetOptions &ExistingTargetOpts;
|
||||
const PreprocessorOptions &ExistingPPOpts;
|
||||
std::string ExistingModuleCachePath;
|
||||
FileManager &FileMgr;
|
||||
|
||||
|
||||
public:
|
||||
SimplePCHValidator(const LangOptions &ExistingLangOpts,
|
||||
const TargetOptions &ExistingTargetOpts,
|
||||
const PreprocessorOptions &ExistingPPOpts,
|
||||
StringRef ExistingModuleCachePath,
|
||||
FileManager &FileMgr)
|
||||
: ExistingLangOpts(ExistingLangOpts),
|
||||
ExistingTargetOpts(ExistingTargetOpts),
|
||||
ExistingPPOpts(ExistingPPOpts),
|
||||
ExistingModuleCachePath(ExistingModuleCachePath),
|
||||
FileMgr(FileMgr)
|
||||
{
|
||||
}
|
||||
|
@ -4214,6 +4250,13 @@ namespace {
|
|||
bool Complain) override {
|
||||
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 Complain,
|
||||
std::string &SuggestedPredefines) override {
|
||||
|
@ -4408,8 +4451,10 @@ bool ASTReader::isAcceptableASTFile(StringRef Filename,
|
|||
FileManager &FileMgr,
|
||||
const LangOptions &LangOpts,
|
||||
const TargetOptions &TargetOpts,
|
||||
const PreprocessorOptions &PPOpts) {
|
||||
SimplePCHValidator validator(LangOpts, TargetOpts, PPOpts, FileMgr);
|
||||
const PreprocessorOptions &PPOpts,
|
||||
std::string ExistingModuleCachePath) {
|
||||
SimplePCHValidator validator(LangOpts, TargetOpts, PPOpts,
|
||||
ExistingModuleCachePath, FileMgr);
|
||||
return !readASTFileControlBlock(Filename, FileMgr, validator);
|
||||
}
|
||||
|
||||
|
@ -4780,8 +4825,10 @@ bool ASTReader::ParseHeaderSearchOptions(const RecordData &Record,
|
|||
HSOpts.UseStandardSystemIncludes = Record[Idx++];
|
||||
HSOpts.UseStandardCXXIncludes = 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,
|
||||
|
|
|
@ -1344,6 +1344,8 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
|
|||
Record.push_back(HSOpts.UseStandardSystemIncludes);
|
||||
Record.push_back(HSOpts.UseStandardCXXIncludes);
|
||||
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);
|
||||
|
||||
// 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: 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
|
||||
// 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
|
||||
// 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: -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: -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
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
void make_foo(void);
|
|
@ -0,0 +1,3 @@
|
|||
module Foo {
|
||||
header "Foo.h"
|
||||
}
|
|
@ -10,7 +10,7 @@
|
|||
// 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 -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.
|
||||
// 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