Detect when we end up trying to load conflicting module files.

This can happen when one abuses precompiled headers by passing more -D
options when using a precompiled hedaer than when it was built. This
is intentionally permitted by precompiled headers (and is exploited by
some build environments), but causes problems for modules.

First part of <rdar://problem/13165109>, detecting when something when
horribly wrong.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@174554 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Douglas Gregor 2013-02-06 22:40:31 +00:00
Родитель 474e46211a
Коммит 8bf778eb9c
6 изменённых файлов: 68 добавлений и 4 удалений

Просмотреть файл

@ -118,4 +118,8 @@ def err_unable_to_rename_temp : Error<
"unable to rename temporary '%0' to output file '%1': '%2'">;
def err_unable_to_make_temp : Error<
"unable to make temporary file: %0">;
// Modules
def err_module_file_conflict : Error<"module '%0' found in both '%1' and '%2'">;
}

Просмотреть файл

@ -915,9 +915,9 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
// Search for a module with the given name.
Module = PP->getHeaderSearchInfo().lookupModule(ModuleName);
std::string ModuleFileName;
if (Module)
if (Module) {
ModuleFileName = PP->getHeaderSearchInfo().getModuleFileName(Module);
else
} else
ModuleFileName = PP->getHeaderSearchInfo().getModuleFileName(ModuleName);
if (ModuleFileName.empty()) {
@ -987,6 +987,20 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
return ModuleLoadResult();
}
// If there is already a module file associated with this module, make sure
// it is the same as the module file we're looking for. Otherwise, we
// have two module files for the same module.
if (const FileEntry *CurModuleFile = Module? Module->getASTFile() : 0) {
if (CurModuleFile != ModuleFile) {
getDiagnostics().Report(ModuleNameLoc, diag::err_module_file_conflict)
<< ModuleName
<< CurModuleFile->getName()
<< ModuleFile->getName();
ModuleBuildFailed = true;
return ModuleLoadResult();
}
}
// If we don't already have an ASTReader, create one now.
if (!ModuleManager) {
if (!hasASTContext())
@ -1085,8 +1099,9 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
.findModule((Path[0].first->getName()));
}
if (Module)
if (Module) {
Module->setASTFile(ModuleFile);
}
// Cache the result of this top-level module lookup for later.
Known = KnownModules.insert(std::make_pair(Path[0].first, Module)).first;

Просмотреть файл

@ -3408,7 +3408,18 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) {
Error("too many submodules");
return true;
}
if (const FileEntry *CurFile = CurrentModule->getASTFile()) {
if (CurFile != F.File) {
if (!Diags.isDiagnosticInFlight()) {
Diag(diag::err_module_file_conflict)
<< CurrentModule->getTopLevelModuleName()
<< CurFile->getName()
<< F.File->getName();
}
return true;
}
}
CurrentModule->setASTFile(F.File);
CurrentModule->IsFromModuleFile = true;
CurrentModule->IsSystem = IsSystem || CurrentModule->IsSystem;

Просмотреть файл

@ -0,0 +1,8 @@
struct Point {
double x, y;
};
#ifdef IGNORED
int *has_ignored(void);
#endif

Просмотреть файл

@ -159,3 +159,7 @@ module autolink {
module weird_objc {
header "weird_objc.h"
}
module ignored_macros {
header "ignored_macros.h"
}

Просмотреть файл

@ -0,0 +1,22 @@
// First trial: pass -DIGNORED=1 to both. It should be ignored in both
// RUN: rm -rf %t.modules
// RUN: %clang_cc1 -fmodule-cache-path %t.modules -DIGNORED=1 -fmodules -I %S/Inputs -emit-pch -o %t.pch -x objective-c-header %s -verify
// RUN: %clang_cc1 -fmodule-cache-path %t.modules -DIGNORED=1 -fmodules -I %S/Inputs -include-pch %t.pch %s -verify
// Second trial: pass -DIGNORED=1 only to the second invocation.
// RUN: rm -rf %t.modules
// RUN: %clang_cc1 -fmodule-cache-path %t.modules -fmodules -I %S/Inputs -emit-pch -o %t.pch -x objective-c-header %s -verify
// RUN: not %clang_cc1 -fmodule-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
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@import ignored_macros;
#endif
@import ignored_macros;
struct Point p;