From d775eff4c77cac03406fc6146a162f1f1b076db4 Mon Sep 17 00:00:00 2001 From: Ben Langmuir Date: Tue, 13 Jan 2015 17:47:44 +0000 Subject: [PATCH] Inherit attributes when infering a framework module If a module map contains framework module * [extern_c] {} We will now infer [extern_c] on the inferred framework modules (we already inferred [system] as a special case). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@225803 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Lex/ModuleMap.h | 24 ++++++++-- lib/Lex/ModuleMap.cpp | 47 +++++++++---------- .../Headers/InferredExternC.h | 1 + .../Inputs/inferred-attr/module.modulemap | 1 + test/Modules/inferred-attributes.mm | 6 +++ 5 files changed, 52 insertions(+), 27 deletions(-) create mode 100644 test/Modules/Inputs/inferred-attr/InferredExternC.framework/Headers/InferredExternC.h create mode 100644 test/Modules/Inputs/inferred-attr/module.modulemap create mode 100644 test/Modules/inferred-attributes.mm diff --git a/include/clang/Lex/ModuleMap.h b/include/clang/Lex/ModuleMap.h index a628e0f869..ed885a7410 100644 --- a/include/clang/Lex/ModuleMap.h +++ b/include/clang/Lex/ModuleMap.h @@ -127,15 +127,29 @@ private: /// header. llvm::DenseMap UmbrellaDirs; + /// \brief The set of attributes that can be attached to a module. + struct Attributes { + Attributes() : IsSystem(), IsExternC(), IsExhaustive() {} + + /// \brief Whether this is a system module. + unsigned IsSystem : 1; + + /// \brief Whether this is an extern "C" module. + unsigned IsExternC : 1; + + /// \brief Whether this is an exhaustive set of configuration macros. + unsigned IsExhaustive : 1; + }; + /// \brief A directory for which framework modules can be inferred. struct InferredDirectory { - InferredDirectory() : InferModules(), InferSystemModules() { } + InferredDirectory() : InferModules() {} /// \brief Whether to infer modules from this directory. unsigned InferModules : 1; - /// \brief Whether the modules we infer are [system] modules. - unsigned InferSystemModules : 1; + /// \brief The attributes to use for inferred modules. + Attributes Attrs; /// \brief If \c InferModules is non-zero, the module map file that allowed /// inferred modules. Otherwise, nullptr. @@ -214,6 +228,10 @@ private: return static_cast(findHeaderInUmbrellaDirs(File, IntermediateDirs)); } + Module *inferFrameworkModule(StringRef ModuleName, + const DirectoryEntry *FrameworkDir, + Attributes Attrs, Module *Parent); + public: /// \brief Construct a new module map. /// diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp index 132bd62b5f..ef322d8cdc 100644 --- a/lib/Lex/ModuleMap.cpp +++ b/lib/Lex/ModuleMap.cpp @@ -585,6 +585,15 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName, const DirectoryEntry *FrameworkDir, bool IsSystem, Module *Parent) { + Attributes Attrs; + Attrs.IsSystem = IsSystem; + return inferFrameworkModule(ModuleName, FrameworkDir, Attrs, Parent); +} + +Module *ModuleMap::inferFrameworkModule(StringRef ModuleName, + const DirectoryEntry *FrameworkDir, + Attributes Attrs, Module *Parent) { + // Check whether we've already found this module. if (Module *Mod = lookupModuleQualified(ModuleName, Parent)) return Mod; @@ -625,7 +634,7 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName, bool IsFrameworkDir = Parent.endswith(".framework"); if (const FileEntry *ModMapFile = HeaderInfo.lookupModuleMapFile(ParentDir, IsFrameworkDir)) { - parseModuleMapFile(ModMapFile, IsSystem, ParentDir); + parseModuleMapFile(ModMapFile, Attrs.IsSystem, ParentDir); inferred = InferredDirectories.find(ParentDir); } @@ -642,8 +651,9 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName, inferred->second.ExcludedModules.end(), Name) == inferred->second.ExcludedModules.end(); - if (inferred->second.InferSystemModules) - IsSystem = true; + Attrs.IsSystem |= inferred->second.Attrs.IsSystem; + Attrs.IsExternC |= inferred->second.Attrs.IsExternC; + Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive; ModuleMapFile = inferred->second.ModuleMapFile; } } @@ -675,9 +685,11 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName, SourceModule = Result; SourceModuleName = ModuleName; } - if (IsSystem) - Result->IsSystem = IsSystem; - + + Result->IsSystem |= Attrs.IsSystem; + Result->IsExternC |= Attrs.IsExternC; + Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive; + if (!Parent) Modules[ModuleName] = Result; @@ -732,8 +744,8 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName, // FIXME: Do we want to warn about subframeworks without umbrella headers? SmallString<32> NameBuf; inferFrameworkModule(sanitizeFilenameAsIdentifier( - llvm::sys::path::stem(Dir->path()), NameBuf), - SubframeworkDir, IsSystem, Result); + llvm::sys::path::stem(Dir->path()), NameBuf), + SubframeworkDir, Attrs, Result); } } @@ -972,21 +984,6 @@ namespace clang { } }; - /// \brief The set of attributes that can be attached to a module. - struct Attributes { - Attributes() : IsSystem(), IsExternC(), IsExhaustive() { } - - /// \brief Whether this is a system module. - unsigned IsSystem : 1; - - /// \brief Whether this is an extern "C" module. - unsigned IsExternC : 1; - - /// \brief Whether this is an exhaustive set of configuration macros. - unsigned IsExhaustive : 1; - }; - - class ModuleMapParser { Lexer &L; SourceManager &SourceMgr; @@ -1045,6 +1042,8 @@ namespace clang { void parseConfigMacros(); void parseConflict(); void parseInferredModuleDecl(bool Framework, bool Explicit); + + typedef ModuleMap::Attributes Attributes; bool parseOptionalAttributes(Attributes &Attrs); public: @@ -2117,7 +2116,7 @@ void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) { } else { // We'll be inferring framework modules for this directory. Map.InferredDirectories[Directory].InferModules = true; - Map.InferredDirectories[Directory].InferSystemModules = Attrs.IsSystem; + Map.InferredDirectories[Directory].Attrs = Attrs; Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile; // FIXME: Handle the 'framework' keyword. } diff --git a/test/Modules/Inputs/inferred-attr/InferredExternC.framework/Headers/InferredExternC.h b/test/Modules/Inputs/inferred-attr/InferredExternC.framework/Headers/InferredExternC.h new file mode 100644 index 0000000000..63242fae9a --- /dev/null +++ b/test/Modules/Inputs/inferred-attr/InferredExternC.framework/Headers/InferredExternC.h @@ -0,0 +1 @@ +// InferredExternC.h diff --git a/test/Modules/Inputs/inferred-attr/module.modulemap b/test/Modules/Inputs/inferred-attr/module.modulemap new file mode 100644 index 0000000000..beb6ea159d --- /dev/null +++ b/test/Modules/Inputs/inferred-attr/module.modulemap @@ -0,0 +1 @@ +framework module * [extern_c] { } diff --git a/test/Modules/inferred-attributes.mm b/test/Modules/inferred-attributes.mm new file mode 100644 index 0000000000..5fc1d623f3 --- /dev/null +++ b/test/Modules/inferred-attributes.mm @@ -0,0 +1,6 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -F %S/Inputs/inferred-attr -fsyntax-only -verify %s +// expected-no-diagnostics +extern "C" { +@import InferredExternC; +} -- 2.40.0