return static_cast<bool>(findHeaderInUmbrellaDirs(File, IntermediateDirs));
}
- Module *inferFrameworkModule(StringRef ModuleName,
- const DirectoryEntry *FrameworkDir,
+ Module *inferFrameworkModule(const DirectoryEntry *FrameworkDir,
Attributes Attrs, Module *Parent);
public:
/// \brief Infer the contents of a framework module map from the given
/// framework directory.
- Module *inferFrameworkModule(StringRef ModuleName,
- const DirectoryEntry *FrameworkDir,
+ Module *inferFrameworkModule(const DirectoryEntry *FrameworkDir,
bool IsSystem, Module *Parent);
-
+
/// \brief Retrieve the module map file containing the definition of the given
/// module.
///
// Load this framework module. If that succeeds, find the suggested module
// for this header, if any.
bool IsSystem = getDirCharacteristic() != SrcMgr::C_User;
- if (HS.loadFrameworkModule(ModuleName, TopFrameworkDir, IsSystem)) {
- *SuggestedModule = HS.findModuleForHeader(FE);
- }
+ HS.loadFrameworkModule(ModuleName, TopFrameworkDir, IsSystem);
+
+ // FIXME: This can find a module not part of ModuleName, which is
+ // important so that we're consistent about whether this header
+ // corresponds to a module. Possibly we should lock down framework modules
+ // so that this is not possible.
+ *SuggestedModule = HS.findModuleForHeader(FE);
} else {
*SuggestedModule = HS.findModuleForHeader(FE);
}
// Try to load a module map file.
switch (loadModuleMapFile(Dir, IsSystem, /*IsFramework*/true)) {
case LMM_InvalidModuleMap:
+ // Try to infer a module map from the framework directory.
+ if (HSOpts->ImplicitModuleMaps)
+ ModMap.inferFrameworkModule(Dir, IsSystem, /*Parent=*/nullptr);
break;
case LMM_AlreadyLoaded:
return nullptr;
case LMM_NewlyLoaded:
- return ModMap.findModule(Name);
+ break;
}
-
- // Try to infer a module map from the framework directory.
- if (HSOpts->ImplicitModuleMaps)
- return ModMap.inferFrameworkModule(Name, Dir, IsSystem, /*Parent=*/nullptr);
-
- return nullptr;
+ return ModMap.findModule(Name);
}
}
}
-Module *
-ModuleMap::inferFrameworkModule(StringRef ModuleName,
- const DirectoryEntry *FrameworkDir,
- bool IsSystem,
- Module *Parent) {
+Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
+ bool IsSystem, Module *Parent) {
Attributes Attrs;
Attrs.IsSystem = IsSystem;
- return inferFrameworkModule(ModuleName, FrameworkDir, Attrs, Parent);
+ return inferFrameworkModule(FrameworkDir, Attrs, Parent);
}
-Module *ModuleMap::inferFrameworkModule(StringRef ModuleName,
- const DirectoryEntry *FrameworkDir,
+Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
Attributes Attrs, Module *Parent) {
+ // Note: as an egregious but useful hack we use the real path here, because
+ // we might be looking at an embedded framework that symlinks out to a
+ // top-level framework, and we need to infer as if we were naming the
+ // top-level framework.
+ StringRef FrameworkDirName =
+ SourceMgr.getFileManager().getCanonicalName(FrameworkDir);
+
+ // In case this is a case-insensitive filesystem, use the canonical
+ // directory name as the ModuleName, since modules are case-sensitive.
+ // FIXME: we should be able to give a fix-it hint for the correct spelling.
+ SmallString<32> ModuleNameStorage;
+ StringRef ModuleName = sanitizeFilenameAsIdentifier(
+ llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage);
// Check whether we've already found this module.
if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
const FileEntry *ModuleMapFile = nullptr;
if (!Parent) {
// Determine whether we're allowed to infer a module map.
-
- // Note: as an egregious but useful hack we use the real path here, because
- // we might be looking at an embedded framework that symlinks out to a
- // top-level framework, and we need to infer as if we were naming the
- // top-level framework.
- StringRef FrameworkDirName
- = SourceMgr.getFileManager().getCanonicalName(FrameworkDir);
-
- // In case this is a case-insensitive filesystem, make sure the canonical
- // directory name matches ModuleName exactly. Modules are case-sensitive.
- // FIXME: we should be able to give a fix-it hint for the correct spelling.
- if (llvm::sys::path::stem(FrameworkDirName) != ModuleName)
- return nullptr;
-
bool canInfer = false;
if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
// Figure out the parent path.
continue;
// FIXME: Do we want to warn about subframeworks without umbrella headers?
- SmallString<32> NameBuf;
- inferFrameworkModule(sanitizeFilenameAsIdentifier(
- llvm::sys::path::stem(Dir->path()), NameBuf),
- SubframeworkDir, Attrs, Result);
+ inferFrameworkModule(SubframeworkDir, Attrs, Result);
}
}
--- /dev/null
+#import <NameInDir/NameInDir.h>
+
+// Don't crash.
+#undef NAME_IN_DIR
--- /dev/null
+// NameInDir.h
+#define NAME_IN_DIR 1
--- /dev/null
+framework module NameInModMap {
+ umbrella header "NameInDir.h"
+ export *
+ module * { export * }
+}
--- /dev/null
+// NameInDir2.h
--- /dev/null
+framework module NameInDir2 {
+ umbrella header "NameInDir2.h"
+ export *
+ module * { export * }
+}
--- /dev/null
+// NameInDirInferred.h
header "DebugModule.h"
}
+module ImportNameInDir {
+ header "ImportNameInDir.h"
+ export *
+}
--- /dev/null
+// REQUIRES: shell
+// RUN: rm -rf %t.mcp %t
+// RUN: mkdir -p %t
+// RUN: ln -s %S/Inputs/NameInDir2.framework %t/NameInImport.framework
+// RUN: ln -s %S/Inputs/NameInDirInferred.framework %t/NameInImportInferred.framework
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t.mcp -fimplicit-module-maps -I %S/Inputs -F %S/Inputs -F %t -Wauto-import -verify %s
+
+// Sanity check that we won't somehow find non-canonical module names or
+// modules where we shouldn't search the framework.
+// RUN: echo '@import NameInModMap' | not %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t.mcp -F %S/Inputs -F %t -Wauto-import -x objective-c - 2>&1 | FileCheck %s
+// RUN: echo '@import NameInDir' | not %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t.mcp -F %S/Inputs -F %t -Wauto-import -x objective-c - 2>&1 | FileCheck %s
+// RUN: echo '@import NameInImport' | not %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t.mcp -F %S/Inputs -F %t -Wauto-import -x objective-c - 2>&1 | FileCheck %s
+// RUN: echo '@import NameInImportInferred' | not %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t.mcp -F %S/Inputs -F %t -Wauto-import -x objective-c - 2>&1 | FileCheck %s
+// CHECK: module '{{.*}}' not found
+
+// FIXME: We might want to someday lock down framework modules so that these
+// name mismatches are disallowed. However, as long as we *don't* prevent them
+// it's important that they map correctly to module imports.
+
+// The module map name doesn't match the directory name.
+#import <NameInDir/NameInDir.h> // expected-warning {{import of module 'NameInModMap'}}
+
+// The name in the import doesn't match the module name.
+#import <NameInImport/NameInDir2.h> // expected-warning {{import of module 'NameInDir2'}}
+@import NameInDir2; // OK
+
+// The name in the import doesn't match the module name (inferred framework module).
+#import <NameInImportInferred/NameInDirInferred.h> // expected-warning {{import of module 'NameInDirInferred'}}
+
+@import ImportNameInDir;
+#ifdef NAME_IN_DIR
+#error NAME_IN_DIR should be undef'd
+#endif