summaryrefslogtreecommitdiff
path: root/lib/Lex/ModuleMap.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2018-07-28 11:06:01 +0000
committerDimitry Andric <dim@FreeBSD.org>2018-07-28 11:06:01 +0000
commit486754660bb926339aefcf012a3f848592babb8b (patch)
treeecdbc446c9876f4f120f701c243373cd3cb43db3 /lib/Lex/ModuleMap.cpp
parent55e6d896ad333f07bb3b1ba487df214fc268a4ab (diff)
Notes
Diffstat (limited to 'lib/Lex/ModuleMap.cpp')
-rw-r--r--lib/Lex/ModuleMap.cpp310
1 files changed, 208 insertions, 102 deletions
diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp
index b3ac10c5c5ae8..f048a73a8ccc2 100644
--- a/lib/Lex/ModuleMap.cpp
+++ b/lib/Lex/ModuleMap.cpp
@@ -54,6 +54,24 @@
using namespace clang;
+void ModuleMap::resolveLinkAsDependencies(Module *Mod) {
+ auto PendingLinkAs = PendingLinkAsModule.find(Mod->Name);
+ if (PendingLinkAs != PendingLinkAsModule.end()) {
+ for (auto &Name : PendingLinkAs->second) {
+ auto *M = findModule(Name.getKey());
+ if (M)
+ M->UseExportAsModuleLinkName = true;
+ }
+ }
+}
+
+void ModuleMap::addLinkAsDependency(Module *Mod) {
+ if (findModule(Mod->ExportAsModule))
+ Mod->UseExportAsModuleLinkName = true;
+ else
+ PendingLinkAsModule[Mod->ExportAsModule].insert(Mod->Name);
+}
+
Module::HeaderKind ModuleMap::headerRoleToKind(ModuleHeaderRole Role) {
switch ((int)Role) {
default: llvm_unreachable("unknown header role");
@@ -133,7 +151,7 @@ Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod,
return Context;
}
-/// \brief Append to \p Paths the set of paths needed to get to the
+/// Append to \p Paths the set of paths needed to get to the
/// subframework in which the given module lives.
static void appendSubframeworkPaths(Module *Mod,
SmallVectorImpl<char> &Path) {
@@ -152,10 +170,13 @@ static void appendSubframeworkPaths(Module *Mod,
llvm::sys::path::append(Path, "Frameworks", Paths[I-1] + ".framework");
}
-const FileEntry *
-ModuleMap::findHeader(Module *M,
- const Module::UnresolvedHeaderDirective &Header,
- SmallVectorImpl<char> &RelativePathName) {
+const FileEntry *ModuleMap::findHeader(
+ Module *M, const Module::UnresolvedHeaderDirective &Header,
+ SmallVectorImpl<char> &RelativePathName, bool &NeedsFramework) {
+ // Search for the header file within the module's home directory.
+ auto *Directory = M->Directory;
+ SmallString<128> FullPathName(Directory->getName());
+
auto GetFile = [&](StringRef Filename) -> const FileEntry * {
auto *File = SourceMgr.getFileManager().getFile(Filename);
if (!File ||
@@ -165,18 +186,8 @@ ModuleMap::findHeader(Module *M,
return File;
};
- if (llvm::sys::path::is_absolute(Header.FileName)) {
- RelativePathName.clear();
- RelativePathName.append(Header.FileName.begin(), Header.FileName.end());
- return GetFile(Header.FileName);
- }
-
- // Search for the header file within the module's home directory.
- auto *Directory = M->Directory;
- SmallString<128> FullPathName(Directory->getName());
- unsigned FullPathLength = FullPathName.size();
-
- if (M->isPartOfFramework()) {
+ auto GetFrameworkFile = [&]() -> const FileEntry * {
+ unsigned FullPathLength = FullPathName.size();
appendSubframeworkPaths(M, RelativePathName);
unsigned RelativePathLength = RelativePathName.size();
@@ -201,18 +212,46 @@ ModuleMap::findHeader(Module *M,
Header.FileName);
llvm::sys::path::append(FullPathName, RelativePathName);
return GetFile(FullPathName);
+ };
+
+ if (llvm::sys::path::is_absolute(Header.FileName)) {
+ RelativePathName.clear();
+ RelativePathName.append(Header.FileName.begin(), Header.FileName.end());
+ return GetFile(Header.FileName);
}
+ if (M->isPartOfFramework())
+ return GetFrameworkFile();
+
// Lookup for normal headers.
llvm::sys::path::append(RelativePathName, Header.FileName);
llvm::sys::path::append(FullPathName, RelativePathName);
- return GetFile(FullPathName);
+ auto *NormalHdrFile = GetFile(FullPathName);
+
+ if (M && !NormalHdrFile && Directory->getName().endswith(".framework")) {
+ // The lack of 'framework' keyword in a module declaration it's a simple
+ // mistake we can diagnose when the header exists within the proper
+ // framework style path.
+ FullPathName.assign(Directory->getName());
+ RelativePathName.clear();
+ if (GetFrameworkFile()) {
+ Diags.Report(Header.FileNameLoc,
+ diag::warn_mmap_incomplete_framework_module_declaration)
+ << Header.FileName << M->getFullModuleName();
+ NeedsFramework = true;
+ }
+ return nullptr;
+ }
+
+ return NormalHdrFile;
}
void ModuleMap::resolveHeader(Module *Mod,
- const Module::UnresolvedHeaderDirective &Header) {
+ const Module::UnresolvedHeaderDirective &Header,
+ bool &NeedsFramework) {
SmallString<128> RelativePathName;
- if (const FileEntry *File = findHeader(Mod, Header, RelativePathName)) {
+ if (const FileEntry *File =
+ findHeader(Mod, Header, RelativePathName, NeedsFramework)) {
if (Header.IsUmbrella) {
const DirectoryEntry *UmbrellaDir = File->getDir();
if (Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir])
@@ -281,6 +320,8 @@ ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
ModuleMap::~ModuleMap() {
for (auto &M : Modules)
delete M.getValue();
+ for (auto *M : ShadowModules)
+ delete M;
}
void ModuleMap::setTarget(const TargetInfo &Target) {
@@ -289,7 +330,7 @@ void ModuleMap::setTarget(const TargetInfo &Target) {
this->Target = &Target;
}
-/// \brief "Sanitize" a filename so that it can be used as an identifier.
+/// "Sanitize" a filename so that it can be used as an identifier.
static StringRef sanitizeFilenameAsIdentifier(StringRef Name,
SmallVectorImpl<char> &Buffer) {
if (Name.empty())
@@ -326,7 +367,7 @@ static StringRef sanitizeFilenameAsIdentifier(StringRef Name,
return Name;
}
-/// \brief Determine whether the given file name is the name of a builtin
+/// Determine whether the given file name is the name of a builtin
/// header, supplied by Clang to replace, override, or augment existing system
/// headers.
bool ModuleMap::isBuiltinHeader(StringRef FileName) {
@@ -473,7 +514,7 @@ void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
// We have found a module, but we don't use it.
if (NotUsed) {
Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
- << RequestingModule->getFullModuleName() << Filename;
+ << RequestingModule->getTopLevelModule()->Name << Filename;
return;
}
@@ -484,7 +525,7 @@ void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
if (LangOpts.ModulesStrictDeclUse) {
Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
- << RequestingModule->getFullModuleName() << Filename;
+ << RequestingModule->getTopLevelModule()->Name << Filename;
} else if (RequestingModule && RequestingModuleIsModuleInterface &&
LangOpts.isCompilingModule()) {
// Do not diagnose when we are not compiling a module.
@@ -751,7 +792,7 @@ std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
// Try to find an existing module with this name.
if (Module *Sub = lookupModuleQualified(Name, Parent))
return std::make_pair(Sub, false);
-
+
// Create a new module with this name.
Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
IsExplicit, NumCreatedModules++);
@@ -759,6 +800,7 @@ std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
if (LangOpts.CurrentModule == Name)
SourceModule = Result;
Modules[Name] = Result;
+ ModuleScopeIDs[Result] = CurrentModuleScopeID;
}
return std::make_pair(Result, true);
}
@@ -799,7 +841,7 @@ Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
return Result;
}
-/// \brief For a framework module, infer the framework against which we
+/// For a framework module, infer the framework against which we
/// should link.
static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir,
FileManager &FileMgr) {
@@ -927,6 +969,7 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
if (LangOpts.CurrentModule == ModuleName)
SourceModule = Result;
Modules[ModuleName] = Result;
+ ModuleScopeIDs[Result] = CurrentModuleScopeID;
}
Result->IsSystem |= Attrs.IsSystem;
@@ -999,6 +1042,21 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
return Result;
}
+Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework,
+ Module *ShadowingModule) {
+
+ // Create a new module with this name.
+ Module *Result =
+ new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework,
+ /*IsExplicit=*/false, NumCreatedModules++);
+ Result->ShadowingModule = ShadowingModule;
+ Result->IsAvailable = false;
+ ModuleScopeIDs[Result] = CurrentModuleScopeID;
+ ShadowModules.push_back(Result);
+
+ return Result;
+}
+
void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader,
Twine NameAsWritten) {
Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader));
@@ -1019,7 +1077,8 @@ void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir,
}
void ModuleMap::addUnresolvedHeader(Module *Mod,
- Module::UnresolvedHeaderDirective Header) {
+ Module::UnresolvedHeaderDirective Header,
+ bool &NeedsFramework) {
// If there is a builtin counterpart to this file, add it now so it can
// wrap the system header.
if (resolveAsBuiltinHeader(Mod, Header)) {
@@ -1050,7 +1109,7 @@ void ModuleMap::addUnresolvedHeader(Module *Mod,
// We don't have stat information or can't defer looking this file up.
// Perform the lookup now.
- resolveHeader(Mod, Header);
+ resolveHeader(Mod, Header, NeedsFramework);
}
void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const {
@@ -1070,10 +1129,11 @@ void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const {
}
void ModuleMap::resolveHeaderDirectives(Module *Mod) const {
+ bool NeedsFramework = false;
for (auto &Header : Mod->UnresolvedHeaders)
// This operation is logically const; we're just changing how we represent
// the header information for this file.
- const_cast<ModuleMap*>(this)->resolveHeader(Mod, Header);
+ const_cast<ModuleMap*>(this)->resolveHeader(Mod, Header, NeedsFramework);
Mod->UnresolvedHeaders.clear();
}
@@ -1207,7 +1267,7 @@ bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {
namespace clang {
- /// \brief A token in a module map file.
+ /// A token in a module map file.
struct MMToken {
enum TokenKind {
Comma,
@@ -1277,37 +1337,40 @@ namespace clang {
Lexer &L;
SourceManager &SourceMgr;
- /// \brief Default target information, used only for string literal
+ /// Default target information, used only for string literal
/// parsing.
const TargetInfo *Target;
DiagnosticsEngine &Diags;
ModuleMap &Map;
- /// \brief The current module map file.
+ /// The current module map file.
const FileEntry *ModuleMapFile;
-
- /// \brief The directory that file names in this module map file should
+
+ /// Source location of most recent parsed module declaration
+ SourceLocation CurrModuleDeclLoc;
+
+ /// The directory that file names in this module map file should
/// be resolved relative to.
const DirectoryEntry *Directory;
- /// \brief Whether this module map is in a system header directory.
+ /// Whether this module map is in a system header directory.
bool IsSystem;
- /// \brief Whether an error occurred.
+ /// Whether an error occurred.
bool HadError = false;
- /// \brief Stores string data for the various string literals referenced
+ /// Stores string data for the various string literals referenced
/// during parsing.
llvm::BumpPtrAllocator StringData;
- /// \brief The current token.
+ /// The current token.
MMToken Tok;
- /// \brief The active module.
+ /// The active module.
Module *ActiveModule = nullptr;
- /// \brief Whether a module uses the 'requires excluded' hack to mark its
+ /// Whether a module uses the 'requires excluded' hack to mark its
/// contents as 'textual'.
///
/// On older Darwin SDK versions, 'requires excluded' is used to mark the
@@ -1317,10 +1380,10 @@ namespace clang {
/// 'textual' to match the original intent.
llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack;
- /// \brief Consume the current token and return its location.
+ /// Consume the current token and return its location.
SourceLocation consumeToken();
-
- /// \brief Skip tokens until we reach the a token with the given kind
+
+ /// Skip tokens until we reach the a token with the given kind
/// (or the end of the file).
void skipUntil(MMToken::TokenKind K);
@@ -1340,25 +1403,29 @@ namespace clang {
void parseConflict();
void parseInferredModuleDecl(bool Framework, bool Explicit);
+ /// Private modules are canonicalized as Foo_Private. Clang provides extra
+ /// module map search logic to find the appropriate private module when PCH
+ /// is used with implicit module maps. Warn when private modules are written
+ /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
+ void diagnosePrivateModules(SourceLocation ExplicitLoc,
+ SourceLocation FrameworkLoc);
+
using Attributes = ModuleMap::Attributes;
bool parseOptionalAttributes(Attributes &Attrs);
public:
- explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
- const TargetInfo *Target,
- DiagnosticsEngine &Diags,
- ModuleMap &Map,
- const FileEntry *ModuleMapFile,
- const DirectoryEntry *Directory,
- bool IsSystem)
+ explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
+ const TargetInfo *Target, DiagnosticsEngine &Diags,
+ ModuleMap &Map, const FileEntry *ModuleMapFile,
+ const DirectoryEntry *Directory, bool IsSystem)
: L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
ModuleMapFile(ModuleMapFile), Directory(Directory),
IsSystem(IsSystem) {
Tok.clear();
consumeToken();
}
-
+
bool parseModuleMapFile();
bool terminatedByDirective() { return false; }
@@ -1559,7 +1626,7 @@ void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
} while (true);
}
-/// \brief Parse a module-id.
+/// Parse a module-id.
///
/// module-id:
/// identifier
@@ -1588,21 +1655,21 @@ bool ModuleMapParser::parseModuleId(ModuleId &Id) {
namespace {
- /// \brief Enumerates the known attributes.
+ /// Enumerates the known attributes.
enum AttributeKind {
- /// \brief An unknown attribute.
+ /// An unknown attribute.
AT_unknown,
- /// \brief The 'system' attribute.
+ /// The 'system' attribute.
AT_system,
- /// \brief The 'extern_c' attribute.
+ /// The 'extern_c' attribute.
AT_extern_c,
- /// \brief The 'exhaustive' attribute.
+ /// The 'exhaustive' attribute.
AT_exhaustive,
- /// \brief The 'no_undeclared_includes' attribute.
+ /// The 'no_undeclared_includes' attribute.
AT_no_undeclared_includes
};
@@ -1612,16 +1679,14 @@ namespace {
/// module map search logic to find the appropriate private module when PCH
/// is used with implicit module maps. Warn when private modules are written
/// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
-static void diagnosePrivateModules(const ModuleMap &Map,
- DiagnosticsEngine &Diags,
- const Module *ActiveModule) {
-
+void ModuleMapParser::diagnosePrivateModules(SourceLocation ExplicitLoc,
+ SourceLocation FrameworkLoc) {
auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical,
- const Module *M) {
+ const Module *M, SourceRange ReplLoc) {
auto D = Diags.Report(ActiveModule->DefinitionLoc,
diag::note_mmap_rename_top_level_private_module);
D << BadName << M->Name;
- D << FixItHint::CreateReplacement(ActiveModule->DefinitionLoc, Canonical);
+ D << FixItHint::CreateReplacement(ReplLoc, Canonical);
};
for (auto E = Map.module_begin(); E != Map.module_end(); ++E) {
@@ -1632,6 +1697,7 @@ static void diagnosePrivateModules(const ModuleMap &Map,
SmallString<128> FullName(ActiveModule->getFullModuleName());
if (!FullName.startswith(M->Name) && !FullName.endswith("Private"))
continue;
+ SmallString<128> FixedPrivModDecl;
SmallString<128> Canonical(M->Name);
Canonical.append("_Private");
@@ -1641,7 +1707,20 @@ static void diagnosePrivateModules(const ModuleMap &Map,
Diags.Report(ActiveModule->DefinitionLoc,
diag::warn_mmap_mismatched_private_submodule)
<< FullName;
- GenNoteAndFixIt(FullName, Canonical, M);
+
+ SourceLocation FixItInitBegin = CurrModuleDeclLoc;
+ if (FrameworkLoc.isValid())
+ FixItInitBegin = FrameworkLoc;
+ if (ExplicitLoc.isValid())
+ FixItInitBegin = ExplicitLoc;
+
+ if (FrameworkLoc.isValid() || ActiveModule->Parent->IsFramework)
+ FixedPrivModDecl.append("framework ");
+ FixedPrivModDecl.append("module ");
+ FixedPrivModDecl.append(Canonical);
+
+ GenNoteAndFixIt(FullName, FixedPrivModDecl, M,
+ SourceRange(FixItInitBegin, ActiveModule->DefinitionLoc));
continue;
}
@@ -1651,12 +1730,13 @@ static void diagnosePrivateModules(const ModuleMap &Map,
Diags.Report(ActiveModule->DefinitionLoc,
diag::warn_mmap_mismatched_private_module_name)
<< ActiveModule->Name;
- GenNoteAndFixIt(ActiveModule->Name, Canonical, M);
+ GenNoteAndFixIt(ActiveModule->Name, Canonical, M,
+ SourceRange(ActiveModule->DefinitionLoc));
}
}
}
-/// \brief Parse a module declaration.
+/// Parse a module declaration.
///
/// module-declaration:
/// 'extern' 'module' module-id string-literal
@@ -1684,6 +1764,7 @@ void ModuleMapParser::parseModuleDecl() {
// Parse 'explicit' or 'framework' keyword, if present.
SourceLocation ExplicitLoc;
+ SourceLocation FrameworkLoc;
bool Explicit = false;
bool Framework = false;
@@ -1695,7 +1776,7 @@ void ModuleMapParser::parseModuleDecl() {
// Parse 'framework' keyword, if present.
if (Tok.is(MMToken::FrameworkKeyword)) {
- consumeToken();
+ FrameworkLoc = consumeToken();
Framework = true;
}
@@ -1706,7 +1787,7 @@ void ModuleMapParser::parseModuleDecl() {
HadError = true;
return;
}
- consumeToken(); // 'module' keyword
+ CurrModuleDeclLoc = consumeToken(); // 'module' keyword
// If we have a wildcard for the module name, this is an inferred submodule.
// Parse it.
@@ -1787,6 +1868,7 @@ void ModuleMapParser::parseModuleDecl() {
SourceLocation LBraceLoc = consumeToken();
// Determine whether this (sub)module has already been defined.
+ Module *ShadowingModule = nullptr;
if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
// We might see a (re)definition of a module that we already have a
// definition for in two cases:
@@ -1812,23 +1894,35 @@ void ModuleMapParser::parseModuleDecl() {
}
return;
}
-
- Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
- << ModuleName;
- Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
-
- // Skip the module definition.
- skipUntil(MMToken::RBrace);
- if (Tok.is(MMToken::RBrace))
- consumeToken();
-
- HadError = true;
- return;
+
+ if (!Existing->Parent && Map.mayShadowNewModule(Existing)) {
+ ShadowingModule = Existing;
+ } else {
+ // This is not a shawdowed module decl, it is an illegal redefinition.
+ Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
+ << ModuleName;
+ Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
+
+ // Skip the module definition.
+ skipUntil(MMToken::RBrace);
+ if (Tok.is(MMToken::RBrace))
+ consumeToken();
+
+ HadError = true;
+ return;
+ }
}
// Start defining this module.
- ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework,
- Explicit).first;
+ if (ShadowingModule) {
+ ActiveModule =
+ Map.createShadowedModule(ModuleName, Framework, ShadowingModule);
+ } else {
+ ActiveModule =
+ Map.findOrCreateModule(ModuleName, ActiveModule, Framework, Explicit)
+ .first;
+ }
+
ActiveModule->DefinitionLoc = ModuleNameLoc;
if (Attrs.IsSystem || IsSystem)
ActiveModule->IsSystem = true;
@@ -1839,21 +1933,24 @@ void ModuleMapParser::parseModuleDecl() {
ActiveModule->NoUndeclaredIncludes = true;
ActiveModule->Directory = Directory;
+ StringRef MapFileName(ModuleMapFile->getName());
+ if (MapFileName.endswith("module.private.modulemap") ||
+ MapFileName.endswith("module_private.map")) {
+ ActiveModule->ModuleMapIsPrivate = true;
+ }
// Private modules named as FooPrivate, Foo.Private or similar are likely a
// user error; provide warnings, notes and fixits to direct users to use
// Foo_Private instead.
SourceLocation StartLoc =
SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
- StringRef MapFileName(ModuleMapFile->getName());
if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
!Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule,
StartLoc) &&
!Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name,
StartLoc) &&
- (MapFileName.endswith("module.private.modulemap") ||
- MapFileName.endswith("module_private.map")))
- diagnosePrivateModules(Map, Diags, ActiveModule);
+ ActiveModule->ModuleMapIsPrivate)
+ diagnosePrivateModules(ExplicitLoc, FrameworkLoc);
bool Done = false;
do {
@@ -1958,7 +2055,7 @@ void ModuleMapParser::parseModuleDecl() {
ActiveModule = PreviousActiveModule;
}
-/// \brief Parse an extern module declaration.
+/// Parse an extern module declaration.
///
/// extern module-declaration:
/// 'extern' 'module' module-id string-literal
@@ -2036,7 +2133,7 @@ static bool shouldAddRequirement(Module *M, StringRef Feature,
return true;
}
-/// \brief Parse a requires declaration.
+/// Parse a requires declaration.
///
/// requires-declaration:
/// 'requires' feature-list
@@ -2092,7 +2189,7 @@ void ModuleMapParser::parseRequiresDecl() {
} while (true);
}
-/// \brief Parse a header declaration.
+/// Parse a header declaration.
///
/// header-declaration:
/// 'textual'[opt] 'header' string-literal
@@ -2212,7 +2309,13 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
}
}
- Map.addUnresolvedHeader(ActiveModule, std::move(Header));
+ bool NeedsFramework = false;
+ Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework);
+
+ if (NeedsFramework && ActiveModule)
+ Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword)
+ << ActiveModule->getFullModuleName()
+ << FixItHint::CreateReplacement(CurrModuleDeclLoc, "framework module");
}
static int compareModuleHeaders(const Module::Header *A,
@@ -2220,7 +2323,7 @@ static int compareModuleHeaders(const Module::Header *A,
return A->NameAsWritten.compare(B->NameAsWritten);
}
-/// \brief Parse an umbrella directory declaration.
+/// Parse an umbrella directory declaration.
///
/// umbrella-dir-declaration:
/// umbrella string-literal
@@ -2298,7 +2401,7 @@ void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
Map.setUmbrellaDir(ActiveModule, Dir, DirName);
}
-/// \brief Parse a module export declaration.
+/// Parse a module export declaration.
///
/// export-declaration:
/// 'export' wildcard-module-id
@@ -2346,7 +2449,7 @@ void ModuleMapParser::parseExportDecl() {
ActiveModule->UnresolvedExports.push_back(Unresolved);
}
-/// \brief Parse a module export_as declaration.
+/// Parse a module export_as declaration.
///
/// export-as-declaration:
/// 'export_as' identifier
@@ -2378,10 +2481,12 @@ void ModuleMapParser::parseExportAsDecl() {
}
ActiveModule->ExportAsModule = Tok.getString();
+ Map.addLinkAsDependency(ActiveModule);
+
consumeToken();
}
-/// \brief Parse a module use declaration.
+/// Parse a module use declaration.
///
/// use-declaration:
/// 'use' wildcard-module-id
@@ -2398,7 +2503,7 @@ void ModuleMapParser::parseUseDecl() {
ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId);
}
-/// \brief Parse a link declaration.
+/// Parse a link declaration.
///
/// module-declaration:
/// 'link' 'framework'[opt] string-literal
@@ -2427,7 +2532,7 @@ void ModuleMapParser::parseLinkDecl() {
IsFramework));
}
-/// \brief Parse a configuration macro declaration.
+/// Parse a configuration macro declaration.
///
/// module-declaration:
/// 'config_macros' attributes[opt] config-macro-list?
@@ -2484,7 +2589,7 @@ void ModuleMapParser::parseConfigMacros() {
} while (true);
}
-/// \brief Format a module-id into a string.
+/// Format a module-id into a string.
static std::string formatModuleId(const ModuleId &Id) {
std::string result;
{
@@ -2500,7 +2605,7 @@ static std::string formatModuleId(const ModuleId &Id) {
return result;
}
-/// \brief Parse a conflict declaration.
+/// Parse a conflict declaration.
///
/// module-declaration:
/// 'conflict' module-id ',' string-literal
@@ -2534,7 +2639,7 @@ void ModuleMapParser::parseConflict() {
ActiveModule->UnresolvedConflicts.push_back(Conflict);
}
-/// \brief Parse an inferred module declaration (wildcard modules).
+/// Parse an inferred module declaration (wildcard modules).
///
/// module-declaration:
/// 'explicit'[opt] 'framework'[opt] 'module' * attributes[opt]
@@ -2687,7 +2792,7 @@ void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
}
}
-/// \brief Parse optional attributes.
+/// Parse optional attributes.
///
/// attributes:
/// attribute attributes
@@ -2762,7 +2867,7 @@ bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
return HadError;
}
-/// \brief Parse a module map file.
+/// Parse a module map file.
///
/// module-map-file:
/// module-declaration*
@@ -2854,5 +2959,6 @@ bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem,
// Notify callbacks that we parsed it.
for (const auto &Cb : Callbacks)
Cb->moduleMapFileRead(Start, *File, IsSystem);
+
return Result;
}