diff options
Diffstat (limited to 'clang')
21 files changed, 173 insertions, 74 deletions
diff --git a/clang/docs/Modules.rst b/clang/docs/Modules.rst index 7545bf0cc05..611a5edc23f 100644 --- a/clang/docs/Modules.rst +++ b/clang/docs/Modules.rst @@ -144,7 +144,7 @@ Module maps ----------- The crucial link between modules and headers is described by a *module map*, which describes how a collection of existing headers maps on to the (logical) structure of a module. For example, one could imagine a module ``std`` covering the C standard library. Each of the C standard library headers (``<stdio.h>``, ``<stdlib.h>``, ``<math.h>``, etc.) would contribute to the ``std`` module, by placing their respective APIs into the corresponding submodule (``std.io``, ``std.lib``, ``std.math``, etc.). Having a list of the headers that are part of the ``std`` module allows the compiler to build the ``std`` module as a standalone entity, and having the mapping from header names to (sub)modules allows the automatic translation of ``#include`` directives to module imports. -Module maps are specified as separate files (each named ``module.map``) alongside the headers they describe, which allows them to be added to existing software libraries without having to change the library headers themselves (in most cases [#]_). The actual `Module map language`_ is described in a later section. +Module maps are specified as separate files (each named ``module.modulemap``) alongside the headers they describe, which allows them to be added to existing software libraries without having to change the library headers themselves (in most cases [#]_). The actual `Module map language`_ is described in a later section. .. note:: @@ -237,10 +237,13 @@ Module Map Language The module map language describes the mapping from header files to the logical structure of modules. To enable support for using a library as -a module, one must write a ``module.map`` file for that library. The -``module.map`` file is placed alongside the header files themselves, +a module, one must write a ``module.modulemap`` file for that library. The +``module.modulemap`` file is placed alongside the header files themselves, and is written in the module map language described below. +.. note:: + For compatibility with previous releases, if a module map file named ``module.modulemap`` is not found, Clang will also search for a file named ``module.map``. This behavior is deprecated and we plan to eventually remove it. + As an example, the module map file for the C standard library might look a bit like this: .. parsed-literal:: @@ -319,7 +322,7 @@ The ``framework`` qualifier specifies that this module corresponds to a Darwin-s .. parsed-literal:: Name.framework/ - module.map Module map for the framework + Modules/module.modulemap Module map for the framework Headers/ Subdirectory containing framework headers Frameworks/ Subdirectory containing embedded frameworks Resources/ Subdirectory containing additional resources diff --git a/clang/include/clang/Lex/HeaderSearch.h b/clang/include/clang/Lex/HeaderSearch.h index e326db763c4..23be9277156 100644 --- a/clang/include/clang/Lex/HeaderSearch.h +++ b/clang/include/clang/Lex/HeaderSearch.h @@ -502,6 +502,12 @@ public: /// /// \returns The module with the given name. Module *lookupModule(StringRef ModuleName, bool AllowSearch = true); + + + /// \brief Try to find a module map file in the given directory, returning + /// \c nullptr if none is found. + const FileEntry *lookupModuleMapFile(const DirectoryEntry *Dir, + bool IsFramework); void IncrementFrameworkLookupCount() { ++NumFrameworkLookups; } @@ -623,26 +629,32 @@ private: /// invalid. LMM_InvalidModuleMap }; - + + LoadModuleMapResult loadModuleMapFileImpl(const FileEntry *File, + bool IsSystem); + /// \brief Try to load the module map file in the given directory. /// /// \param DirName The name of the directory where we will look for a module /// map file. /// \param IsSystem Whether this is a system header directory. + /// \param IsFramework Whether this is a framework directory. /// /// \returns The result of attempting to load the module map file from the /// named directory. - LoadModuleMapResult loadModuleMapFile(StringRef DirName, bool IsSystem); + LoadModuleMapResult loadModuleMapFile(StringRef DirName, bool IsSystem, + bool IsFramework); /// \brief Try to load the module map file in the given directory. /// /// \param Dir The directory where we will look for a module map file. /// \param IsSystem Whether this is a system header directory. + /// \param IsFramework Whether this is a framework directory. /// /// \returns The result of attempting to load the module map file from the /// named directory. LoadModuleMapResult loadModuleMapFile(const DirectoryEntry *Dir, - bool IsSystem); + bool IsSystem, bool IsFramework); /// \brief Return the HeaderFileInfo structure for the specified FileEntry. HeaderFileInfo &getFileInfo(const FileEntry *FE); diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp index 46d4d41b9af..cb76923f2d6 100644 --- a/clang/lib/Lex/HeaderSearch.cpp +++ b/clang/lib/Lex/HeaderSearch.cpp @@ -165,8 +165,8 @@ Module *HeaderSearch::lookupModule(StringRef ModuleName, bool AllowSearch) { bool IsSystem = SearchDirs[Idx].isSystemHeaderDirectory(); // Search for a module map file in this directory. - if (loadModuleMapFile(SearchDirs[Idx].getDir(), IsSystem) - == LMM_NewlyLoaded) { + if (loadModuleMapFile(SearchDirs[Idx].getDir(), IsSystem, + /*IsFramework*/false) == LMM_NewlyLoaded) { // We just loaded a module map file; check whether the module is // available now. Module = ModMap.findModule(ModuleName); @@ -179,7 +179,8 @@ Module *HeaderSearch::lookupModule(StringRef ModuleName, bool AllowSearch) { SmallString<128> NestedModuleMapDirName; NestedModuleMapDirName = SearchDirs[Idx].getDir()->getName(); llvm::sys::path::append(NestedModuleMapDirName, ModuleName); - if (loadModuleMapFile(NestedModuleMapDirName, IsSystem) == LMM_NewlyLoaded){ + if (loadModuleMapFile(NestedModuleMapDirName, IsSystem, + /*IsFramework*/false) == LMM_NewlyLoaded){ // If we just loaded a module map file, look for the module again. Module = ModMap.findModule(ModuleName); if (Module) @@ -1097,8 +1098,8 @@ bool HeaderSearch::hasModuleMap(StringRef FileName, if (!Dir) return false; - // Try to load the "module.map" file in this directory. - switch (loadModuleMapFile(Dir, IsSystem)) { + // Try to load the module map file in this directory. + switch (loadModuleMapFile(Dir, IsSystem, /*IsFramework*/false)) { case LMM_NewlyLoaded: case LMM_AlreadyLoaded: // Success. All of the directories we stepped through inherit this module @@ -1132,36 +1133,84 @@ HeaderSearch::findModuleForHeader(const FileEntry *File) const { return ModMap.findModuleForHeader(File); } +static const FileEntry *getPrivateModuleMap(StringRef ModuleMapPath, + const DirectoryEntry *Directory, + FileManager &FileMgr) { + StringRef Filename = llvm::sys::path::filename(ModuleMapPath); + SmallString<128> PrivateFilename(Directory->getName()); + if (Filename == "module.map") + llvm::sys::path::append(PrivateFilename, "module_private.map"); + else if (Filename == "module.modulemap") + llvm::sys::path::append(PrivateFilename, "module.private.modulemap"); + else + return nullptr; + return FileMgr.getFile(PrivateFilename); +} + bool HeaderSearch::loadModuleMapFile(const FileEntry *File, bool IsSystem) { + switch (loadModuleMapFileImpl(File, IsSystem)) { + case LMM_AlreadyLoaded: + case LMM_NewlyLoaded: + return false; + case LMM_NoDirectory: + case LMM_InvalidModuleMap: + return true; + } +} + +HeaderSearch::LoadModuleMapResult +HeaderSearch::loadModuleMapFileImpl(const FileEntry *File, bool IsSystem) { + assert(File && "expected FileEntry"); + const DirectoryEntry *Dir = File->getDir(); - - llvm::DenseMap<const DirectoryEntry *, bool>::iterator KnownDir - = DirectoryHasModuleMap.find(Dir); + auto KnownDir = DirectoryHasModuleMap.find(Dir); if (KnownDir != DirectoryHasModuleMap.end()) - return !KnownDir->second; - - bool Result = ModMap.parseModuleMapFile(File, IsSystem); - if (!Result && llvm::sys::path::filename(File->getName()) == "module.map") { - // If the file we loaded was a module.map, look for the corresponding - // module_private.map. - SmallString<128> PrivateFilename(Dir->getName()); - llvm::sys::path::append(PrivateFilename, "module_private.map"); - if (const FileEntry *PrivateFile = FileMgr.getFile(PrivateFilename)) - Result = ModMap.parseModuleMapFile(PrivateFile, IsSystem); + return KnownDir->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap; + + if (ModMap.parseModuleMapFile(File, IsSystem)) { + DirectoryHasModuleMap[Dir] = false; + return LMM_InvalidModuleMap; } - - DirectoryHasModuleMap[Dir] = !Result; - return Result; + + // Try to load a corresponding private module map. + if (const FileEntry *PMMFile = + getPrivateModuleMap(File->getName(), Dir, FileMgr)) { + if (ModMap.parseModuleMapFile(PMMFile, IsSystem)) { + DirectoryHasModuleMap[Dir] = false; + return LMM_InvalidModuleMap; + } + } + + // This directory has a module map. + DirectoryHasModuleMap[Dir] = true; + return LMM_NewlyLoaded; +} + +const FileEntry * +HeaderSearch::lookupModuleMapFile(const DirectoryEntry *Dir, bool IsFramework) { + // For frameworks, the preferred spelling is Modules/module.modulemap, but + // module.map at the framework root is also accepted. + SmallString<128> ModuleMapFileName(Dir->getName()); + if (IsFramework) + llvm::sys::path::append(ModuleMapFileName, "Modules"); + llvm::sys::path::append(ModuleMapFileName, "module.modulemap"); + if (const FileEntry *F = FileMgr.getFile(ModuleMapFileName)) + return F; + + // Continue to allow module.map + ModuleMapFileName = Dir->getName(); + llvm::sys::path::append(ModuleMapFileName, "module.map"); + return FileMgr.getFile(ModuleMapFileName); } -Module *HeaderSearch::loadFrameworkModule(StringRef Name, +Module *HeaderSearch::loadFrameworkModule(StringRef Name, const DirectoryEntry *Dir, bool IsSystem) { if (Module *Module = ModMap.findModule(Name)) return Module; // Try to load a module map file. - switch (loadModuleMapFile(Dir, IsSystem)) { + switch (loadModuleMapFile(Dir, IsSystem, /*IsFramework*/true)) { case LMM_InvalidModuleMap: break; @@ -1201,53 +1250,30 @@ Module *HeaderSearch::loadFrameworkModule(StringRef Name, HeaderSearch::LoadModuleMapResult -HeaderSearch::loadModuleMapFile(StringRef DirName, bool IsSystem) { +HeaderSearch::loadModuleMapFile(StringRef DirName, bool IsSystem, + bool IsFramework) { if (const DirectoryEntry *Dir = FileMgr.getDirectory(DirName)) - return loadModuleMapFile(Dir, IsSystem); + return loadModuleMapFile(Dir, IsSystem, IsFramework); return LMM_NoDirectory; } HeaderSearch::LoadModuleMapResult -HeaderSearch::loadModuleMapFile(const DirectoryEntry *Dir, bool IsSystem) { - llvm::DenseMap<const DirectoryEntry *, bool>::iterator KnownDir - = DirectoryHasModuleMap.find(Dir); +HeaderSearch::loadModuleMapFile(const DirectoryEntry *Dir, bool IsSystem, + bool IsFramework) { + auto KnownDir = DirectoryHasModuleMap.find(Dir); if (KnownDir != DirectoryHasModuleMap.end()) return KnownDir->second? LMM_AlreadyLoaded : LMM_InvalidModuleMap; - - SmallString<128> ModuleMapFileName; - ModuleMapFileName += Dir->getName(); - unsigned ModuleMapDirNameLen = ModuleMapFileName.size(); - llvm::sys::path::append(ModuleMapFileName, "module.map"); - if (const FileEntry *ModuleMapFile = FileMgr.getFile(ModuleMapFileName)) { - // We have found a module map file. Try to parse it. - if (ModMap.parseModuleMapFile(ModuleMapFile, IsSystem)) { - // No suitable module map. - DirectoryHasModuleMap[Dir] = false; - return LMM_InvalidModuleMap; - } - // This directory has a module map. - DirectoryHasModuleMap[Dir] = true; - - // Check whether there is a private module map that we need to load as well. - ModuleMapFileName.erase(ModuleMapFileName.begin() + ModuleMapDirNameLen, - ModuleMapFileName.end()); - llvm::sys::path::append(ModuleMapFileName, "module_private.map"); - if (const FileEntry *PrivateModuleMapFile - = FileMgr.getFile(ModuleMapFileName)) { - if (ModMap.parseModuleMapFile(PrivateModuleMapFile, IsSystem)) { - // No suitable module map. - DirectoryHasModuleMap[Dir] = false; - return LMM_InvalidModuleMap; - } - } - - return LMM_NewlyLoaded; + if (const FileEntry *ModuleMapFile = lookupModuleMapFile(Dir, IsFramework)) { + LoadModuleMapResult Result = loadModuleMapFileImpl(ModuleMapFile, IsSystem); + // Add Dir explicitly in case ModuleMapFile is in a subdirectory. + // E.g. Foo.framework/Modules/module.modulemap + // ^Dir ^ModuleMapFile + if (Result == LMM_NewlyLoaded) + DirectoryHasModuleMap[Dir] = true; + return Result; } - - // No suitable module map. - DirectoryHasModuleMap[Dir] = false; return LMM_InvalidModuleMap; } @@ -1285,7 +1311,7 @@ void HeaderSearch::collectAllModules(SmallVectorImpl<Module *> &Modules) { continue; // Try to load a module map file for the search directory. - loadModuleMapFile(SearchDirs[Idx].getDir(), IsSystem); + loadModuleMapFile(SearchDirs[Idx].getDir(), IsSystem, /*IsFramework*/false); // Try to load module map files for immediate subdirectories of this search // directory. @@ -1310,7 +1336,8 @@ void HeaderSearch::loadTopLevelSystemModules() { // Try to load a module map file for the search directory. loadModuleMapFile(SearchDirs[Idx].getDir(), - SearchDirs[Idx].isSystemHeaderDirectory()); + SearchDirs[Idx].isSystemHeaderDirectory(), + SearchDirs[Idx].isFramework()); } } @@ -1323,7 +1350,8 @@ void HeaderSearch::loadSubdirectoryModuleMaps(DirectoryLookup &SearchDir) { llvm::sys::path::native(SearchDir.getDir()->getName(), DirNative); for (llvm::sys::fs::directory_iterator Dir(DirNative.str(), EC), DirEnd; Dir != DirEnd && !EC; Dir.increment(EC)) { - loadModuleMapFile(Dir->path(), SearchDir.isSystemHeaderDirectory()); + loadModuleMapFile(Dir->path(), SearchDir.isSystemHeaderDirectory(), + SearchDir.isFramework()); } SearchDir.setSearchedAllModuleMaps(true); diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp index d5e8af95fe6..e78806dc50b 100644 --- a/clang/lib/Lex/ModuleMap.cpp +++ b/clang/lib/Lex/ModuleMap.cpp @@ -594,9 +594,9 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName, if (inferred == InferredDirectories.end()) { // We haven't looked here before. Load a module map, if there is // one. - SmallString<128> ModMapPath = Parent; - llvm::sys::path::append(ModMapPath, "module.map"); - if (const FileEntry *ModMapFile = FileMgr.getFile(ModMapPath)) { + bool IsFrameworkDir = Parent.endswith(".framework"); + if (const FileEntry *ModMapFile = + HeaderInfo.lookupModuleMapFile(ParentDir, IsFrameworkDir)) { parseModuleMapFile(ModMapFile, IsSystem); inferred = InferredDirectories.find(ParentDir); } @@ -2219,10 +2219,21 @@ bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem) { const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(ID); if (!Buffer) return ParsedModuleMap[File] = true; + + // Find the directory for the module. For frameworks, that may require going + // up from the 'Modules' directory. + const DirectoryEntry *Dir = File->getDir(); + StringRef DirName(Dir->getName()); + if (llvm::sys::path::filename(DirName) == "Modules") { + DirName = llvm::sys::path::parent_path(DirName); + if (DirName.endswith(".framework")) + Dir = SourceMgr.getFileManager().getDirectory(DirName); + assert(Dir && "parent must exist"); + } // Parse this module map file. Lexer L(ID, SourceMgr.getBuffer(ID), SourceMgr, MMapLangOpts); - ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File->getDir(), + ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, Dir, BuiltinIncludeDir, IsSystem); bool Result = Parser.parseModuleMapFile(); ParsedModuleMap[File] = Result; diff --git a/clang/test/Modules/Inputs/ModuleMapLocations/Both/a.h b/clang/test/Modules/Inputs/ModuleMapLocations/Both/a.h new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/clang/test/Modules/Inputs/ModuleMapLocations/Both/a.h diff --git a/clang/test/Modules/Inputs/ModuleMapLocations/Both/b.h b/clang/test/Modules/Inputs/ModuleMapLocations/Both/b.h new file mode 100644 index 00000000000..3abbd398c7e --- /dev/null +++ b/clang/test/Modules/Inputs/ModuleMapLocations/Both/b.h @@ -0,0 +1 @@ +void wont_be_found1(void); diff --git a/clang/test/Modules/Inputs/ModuleMapLocations/Both/module.map b/clang/test/Modules/Inputs/ModuleMapLocations/Both/module.map new file mode 100644 index 00000000000..bf5aaed37ab --- /dev/null +++ b/clang/test/Modules/Inputs/ModuleMapLocations/Both/module.map @@ -0,0 +1,3 @@ +module both { + header "b.h" +} diff --git a/clang/test/Modules/Inputs/ModuleMapLocations/Both/module.modulemap b/clang/test/Modules/Inputs/ModuleMapLocations/Both/module.modulemap new file mode 100644 index 00000000000..0bfa0968c45 --- /dev/null +++ b/clang/test/Modules/Inputs/ModuleMapLocations/Both/module.modulemap @@ -0,0 +1,3 @@ +module both { + header "a.h" +} diff --git a/clang/test/Modules/Inputs/ModuleMapLocations/Both_F.framework/Headers/a.h b/clang/test/Modules/Inputs/ModuleMapLocations/Both_F.framework/Headers/a.h new file mode 100644 index 00000000000..9dabfc089a1 --- /dev/null +++ b/clang/test/Modules/Inputs/ModuleMapLocations/Both_F.framework/Headers/a.h @@ -0,0 +1 @@ +void will_be_found2(void); diff --git a/clang/test/Modules/Inputs/ModuleMapLocations/Both_F.framework/Headers/b.h b/clang/test/Modules/Inputs/ModuleMapLocations/Both_F.framework/Headers/b.h new file mode 100644 index 00000000000..26169fa2f69 --- /dev/null +++ b/clang/test/Modules/Inputs/ModuleMapLocations/Both_F.framework/Headers/b.h @@ -0,0 +1 @@ +void wont_be_found2(void); diff --git a/clang/test/Modules/Inputs/ModuleMapLocations/Both_F.framework/Modules/module.modulemap b/clang/test/Modules/Inputs/ModuleMapLocations/Both_F.framework/Modules/module.modulemap new file mode 100644 index 00000000000..da49ba5392f --- /dev/null +++ b/clang/test/Modules/Inputs/ModuleMapLocations/Both_F.framework/Modules/module.modulemap @@ -0,0 +1,3 @@ +framework module Both_F { + header "a.h" +} diff --git a/clang/test/Modules/Inputs/ModuleMapLocations/Both_F.framework/module.map b/clang/test/Modules/Inputs/ModuleMapLocations/Both_F.framework/module.map new file mode 100644 index 00000000000..8fc108d3eaa --- /dev/null +++ b/clang/test/Modules/Inputs/ModuleMapLocations/Both_F.framework/module.map @@ -0,0 +1,3 @@ +framework module Both_F { + header "b.h" +} diff --git a/clang/test/Modules/Inputs/ModuleMapLocations/Inferred.framework/Headers/Inferred.h b/clang/test/Modules/Inputs/ModuleMapLocations/Inferred.framework/Headers/Inferred.h new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/clang/test/Modules/Inputs/ModuleMapLocations/Inferred.framework/Headers/Inferred.h diff --git a/clang/test/Modules/Inputs/ModuleMapLocations/Module_ModuleMap/a.h b/clang/test/Modules/Inputs/ModuleMapLocations/Module_ModuleMap/a.h new file mode 100644 index 00000000000..d571c6e4f79 --- /dev/null +++ b/clang/test/Modules/Inputs/ModuleMapLocations/Module_ModuleMap/a.h @@ -0,0 +1 @@ +void will_be_found1(void); diff --git a/clang/test/Modules/Inputs/ModuleMapLocations/Module_ModuleMap/module.modulemap b/clang/test/Modules/Inputs/ModuleMapLocations/Module_ModuleMap/module.modulemap new file mode 100644 index 00000000000..2ac7cc52b4f --- /dev/null +++ b/clang/test/Modules/Inputs/ModuleMapLocations/Module_ModuleMap/module.modulemap @@ -0,0 +1,3 @@ +module module_modulemap { + header "a.h" +} diff --git a/clang/test/Modules/Inputs/ModuleMapLocations/Module_ModuleMap_F.framework/Headers/a.h b/clang/test/Modules/Inputs/ModuleMapLocations/Module_ModuleMap_F.framework/Headers/a.h new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/clang/test/Modules/Inputs/ModuleMapLocations/Module_ModuleMap_F.framework/Headers/a.h diff --git a/clang/test/Modules/Inputs/ModuleMapLocations/Module_ModuleMap_F.framework/Modules/module.modulemap b/clang/test/Modules/Inputs/ModuleMapLocations/Module_ModuleMap_F.framework/Modules/module.modulemap new file mode 100644 index 00000000000..400f3043e7a --- /dev/null +++ b/clang/test/Modules/Inputs/ModuleMapLocations/Module_ModuleMap_F.framework/Modules/module.modulemap @@ -0,0 +1,3 @@ +framework module Module_ModuleMap_F { + header "a.h" +} diff --git a/clang/test/Modules/Inputs/ModuleMapLocations/Module_ModuleMap_F.framework/Modules/module.private.modulemap b/clang/test/Modules/Inputs/ModuleMapLocations/Module_ModuleMap_F.framework/Modules/module.private.modulemap new file mode 100644 index 00000000000..25a469dafbe --- /dev/null +++ b/clang/test/Modules/Inputs/ModuleMapLocations/Module_ModuleMap_F.framework/Modules/module.private.modulemap @@ -0,0 +1,3 @@ +explicit framework module Module_ModuleMap_F.Private { + header "private.h" +} diff --git a/clang/test/Modules/Inputs/ModuleMapLocations/Module_ModuleMap_F.framework/PrivateHeaders/private.h b/clang/test/Modules/Inputs/ModuleMapLocations/Module_ModuleMap_F.framework/PrivateHeaders/private.h new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/clang/test/Modules/Inputs/ModuleMapLocations/Module_ModuleMap_F.framework/PrivateHeaders/private.h diff --git a/clang/test/Modules/Inputs/ModuleMapLocations/module.modulemap b/clang/test/Modules/Inputs/ModuleMapLocations/module.modulemap new file mode 100644 index 00000000000..a8f5d1fbf25 --- /dev/null +++ b/clang/test/Modules/Inputs/ModuleMapLocations/module.modulemap @@ -0,0 +1,2 @@ +framework module * { +} diff --git a/clang/test/Modules/modulemap-locations.m b/clang/test/Modules/modulemap-locations.m new file mode 100644 index 00000000000..9acdcd63436 --- /dev/null +++ b/clang/test/Modules/modulemap-locations.m @@ -0,0 +1,18 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -I %S/Inputs/ModuleMapLocations/Module_ModuleMap -I %S/Inputs/ModuleMapLocations/Both -F %S/Inputs/ModuleMapLocations -x objective-c -fsyntax-only %s -verify + +// regular +@import module_modulemap; +@import both; +// framework +@import Module_ModuleMap_F; +@import Module_ModuleMap_F.Private; +@import Both_F; +@import Inferred; + +void test() { + will_be_found1(); + wont_be_found1(); // expected-warning{{implicit declaration of function 'wont_be_found1' is invalid in C99}} + will_be_found2(); + wont_be_found2(); // expected-warning{{implicit declaration of function 'wont_be_found2' is invalid in C99}} +} |