diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2015-02-19 20:12:20 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2015-02-19 20:12:20 +0000 |
commit | bd0b651bd249ab766f9c17cf4a9f5ef268f53632 (patch) | |
tree | 3aa21db58320d852de48f1eb76db2cfb32406da6 /clang | |
parent | dfedfeb298ae491ff6f2f39ab33c01739177d365 (diff) | |
download | bcm5719-llvm-bd0b651bd249ab766f9c17cf4a9f5ef268f53632.tar.gz bcm5719-llvm-bd0b651bd249ab766f9c17cf4a9f5ef268f53632.zip |
[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
Diffstat (limited to 'clang')
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSerializationKinds.td | 2 | ||||
-rw-r--r-- | clang/include/clang/Frontend/CompilerInstance.h | 2 | ||||
-rw-r--r-- | clang/include/clang/Serialization/ASTReader.h | 8 | ||||
-rw-r--r-- | clang/lib/Frontend/CompilerInstance.cpp | 20 | ||||
-rw-r--r-- | clang/lib/Frontend/FrontendAction.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Frontend/FrontendActions.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 63 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriter.cpp | 2 | ||||
-rw-r--r-- | clang/test/Modules/ignored_macros.m | 2 | ||||
-rw-r--r-- | clang/test/Modules/implementation-of-module.m | 2 | ||||
-rw-r--r-- | clang/test/PCH/Inputs/modules/Foo.h | 1 | ||||
-rw-r--r-- | clang/test/PCH/Inputs/modules/module.modulemap | 3 | ||||
-rw-r--r-- | clang/test/PCH/cxx-templates.cpp | 2 | ||||
-rw-r--r-- | clang/test/PCH/module-hash-difference.m | 8 |
14 files changed, 100 insertions, 21 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSerializationKinds.td b/clang/include/clang/Basic/DiagnosticSerializationKinds.td index fe5fd00d737..f28f9983d0e 100644 --- a/clang/include/clang/Basic/DiagnosticSerializationKinds.td +++ b/clang/include/clang/Basic/DiagnosticSerializationKinds.td @@ -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">; diff --git a/clang/include/clang/Frontend/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h index f40e115c23d..cee87b0475f 100644 --- a/clang/include/clang/Frontend/CompilerInstance.h +++ b/clang/include/clang/Frontend/CompilerInstance.h @@ -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(); diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index d7ecf266069..27af9995aa9 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -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 diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index 187e2b78b8f..5d554b717b3 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -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() { diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp index 0bb5d87407b..75670d9a202 100644 --- a/clang/lib/Frontend/FrontendAction.cpp +++ b/clang/lib/Frontend/FrontendAction.cpp @@ -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; diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp index e7ecb2952ac..c8673e50a05 100644 --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -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, diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 3125b8e43e9..7774b7b1c6e 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -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, diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index ee1b631f1ec..c0ce5f8e5ca 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -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. diff --git a/clang/test/Modules/ignored_macros.m b/clang/test/Modules/ignored_macros.m index e8ee50ace31..669db4ddc2d 100644 --- a/clang/test/Modules/ignored_macros.m +++ b/clang/test/Modules/ignored_macros.m @@ -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 diff --git a/clang/test/Modules/implementation-of-module.m b/clang/test/Modules/implementation-of-module.m index b3984042015..818cce8c36d 100644 --- a/clang/test/Modules/implementation-of-module.m +++ b/clang/test/Modules/implementation-of-module.m @@ -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 diff --git a/clang/test/PCH/Inputs/modules/Foo.h b/clang/test/PCH/Inputs/modules/Foo.h new file mode 100644 index 00000000000..d661dbccbc3 --- /dev/null +++ b/clang/test/PCH/Inputs/modules/Foo.h @@ -0,0 +1 @@ +void make_foo(void); diff --git a/clang/test/PCH/Inputs/modules/module.modulemap b/clang/test/PCH/Inputs/modules/module.modulemap new file mode 100644 index 00000000000..5590b43a2d3 --- /dev/null +++ b/clang/test/PCH/Inputs/modules/module.modulemap @@ -0,0 +1,3 @@ +module Foo { + header "Foo.h" +} diff --git a/clang/test/PCH/cxx-templates.cpp b/clang/test/PCH/cxx-templates.cpp index 52ea8752b36..d50eee0623c 100644 --- a/clang/test/PCH/cxx-templates.cpp +++ b/clang/test/PCH/cxx-templates.cpp @@ -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 diff --git a/clang/test/PCH/module-hash-difference.m b/clang/test/PCH/module-hash-difference.m new file mode 100644 index 00000000000..073540eb540 --- /dev/null +++ b/clang/test/PCH/module-hash-difference.m @@ -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; |