summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/tools/clang/lib/Lex/ModuleMap.cpp
diff options
context:
space:
mode:
authorpatrick <patrick@openbsd.org>2019-01-27 16:42:12 +0000
committerpatrick <patrick@openbsd.org>2019-01-27 16:42:12 +0000
commitb773203fb58f3ef282fb69c832d8710cab5bc82d (patch)
treee75913f147570fbd75169647b144df85b88a038c /gnu/llvm/tools/clang/lib/Lex/ModuleMap.cpp
parenttweak errno in previous (diff)
downloadwireguard-openbsd-b773203fb58f3ef282fb69c832d8710cab5bc82d.tar.xz
wireguard-openbsd-b773203fb58f3ef282fb69c832d8710cab5bc82d.zip
Import LLVM 7.0.1 release including clang, lld and lldb.
Diffstat (limited to 'gnu/llvm/tools/clang/lib/Lex/ModuleMap.cpp')
-rw-r--r--gnu/llvm/tools/clang/lib/Lex/ModuleMap.cpp486
1 files changed, 296 insertions, 190 deletions
diff --git a/gnu/llvm/tools/clang/lib/Lex/ModuleMap.cpp b/gnu/llvm/tools/clang/lib/Lex/ModuleMap.cpp
index b3ac10c5c5a..87749f74734 100644
--- a/gnu/llvm/tools/clang/lib/Lex/ModuleMap.cpp
+++ b/gnu/llvm/tools/clang/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");
@@ -85,8 +103,8 @@ ModuleMap::headerKindToRole(Module::HeaderKind Kind) {
llvm_unreachable("unknown header kind");
}
-Module::ExportDecl
-ModuleMap::resolveExport(Module *Mod,
+Module::ExportDecl
+ModuleMap::resolveExport(Module *Mod,
const Module::UnresolvedExportDecl &Unresolved,
bool Complain) const {
// We may have just a wildcard.
@@ -94,7 +112,7 @@ ModuleMap::resolveExport(Module *Mod,
assert(Unresolved.Wildcard && "Invalid unresolved export");
return Module::ExportDecl(nullptr, true);
}
-
+
// Resolve the module-id.
Module *Context = resolveModuleId(Unresolved.Id, Mod, Complain);
if (!Context)
@@ -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) {
@@ -143,19 +161,22 @@ static void appendSubframeworkPaths(Module *Mod,
if (Mod->IsFramework)
Paths.push_back(Mod->Name);
}
-
+
if (Paths.empty())
return;
-
+
// Add Frameworks/Name.framework for each subframework.
for (unsigned I = Paths.size() - 1; I != 0; --I)
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,15 +320,17 @@ 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) {
- assert((!this->Target || this->Target == &Target) &&
+ assert((!this->Target || this->Target == &Target) &&
"Improper target override");
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,10 +525,10 @@ 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.
+ // Do not diagnose when we are not compiling a module.
diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ?
diag::warn_non_modular_include_in_framework_module :
diag::warn_non_modular_include_in_module;
@@ -691,7 +732,7 @@ ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header,
if (IsUnavailable(Found))
return true;
}
-
+
// Infer a submodule with the same name as this header file.
SmallString<32> NameBuf;
StringRef Name = sanitizeFilenameAsIdentifier(
@@ -704,18 +745,18 @@ ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header,
return IsUnavailable(Found);
}
-
+
SkippedDirs.push_back(Dir);
-
+
// Retrieve our parent path.
DirName = llvm::sys::path::parent_path(DirName);
if (DirName.empty())
break;
-
+
// Resolve the parent path to a directory entry.
Dir = SourceMgr.getFileManager().getDirectory(DirName);
} while (Dir);
-
+
return false;
}
@@ -733,14 +774,14 @@ Module *ModuleMap::lookupModuleUnqualified(StringRef Name,
if (Module *Sub = lookupModuleQualified(Name, Context))
return Sub;
}
-
+
return findModule(Name);
}
Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{
if (!Context)
return findModule(Name);
-
+
return Context->findSubmodule(Name);
}
@@ -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) {
@@ -850,7 +892,7 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
// Check whether we've already found this module.
if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
return Mod;
-
+
FileManager &FileMgr = SourceMgr.getFileManager();
// If the framework has a parent path from which we're allowed to infer
@@ -911,7 +953,7 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h");
const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName);
-
+
// FIXME: If there's no umbrella header, we could probably scan the
// framework to load *everything*. But, it's not clear that this is a good
// idea.
@@ -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;
@@ -940,14 +983,14 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
// The "Headers/" component of the name is implied because this is
// a framework module.
setUmbrellaHeader(Result, UmbrellaHeader, ModuleName + ".h");
-
+
// export *
Result->Exports.push_back(Module::ExportDecl(nullptr, true));
// module * { export * }
Result->InferSubmodules = true;
Result->InferExportWildcard = true;
-
+
// Look for subframeworks.
std::error_code EC;
SmallString<128> SubframeworksDirName
@@ -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();
}
@@ -1140,11 +1200,11 @@ void ModuleMap::setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap) {
LLVM_DUMP_METHOD void ModuleMap::dump() {
llvm::errs() << "Modules:";
- for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
- MEnd = Modules.end();
+ for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
+ MEnd = Modules.end();
M != MEnd; ++M)
M->getValue()->print(llvm::errs(), 2);
-
+
llvm::errs() << "Headers:";
for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
H != HEnd; ++H) {
@@ -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,
@@ -1239,7 +1299,7 @@ namespace clang {
LSquare,
RSquare
} Kind;
-
+
unsigned Location;
unsigned StringLength;
union {
@@ -1249,16 +1309,16 @@ namespace clang {
// If Kind == IntegerLiteral.
uint64_t IntegerValue;
};
-
+
void clear() {
Kind = EndOfFile;
Location = 0;
StringLength = 0;
StringData = nullptr;
}
-
+
bool is(TokenKind K) const { return Kind == K; }
-
+
SourceLocation getLocation() const {
return SourceLocation::getFromRawEncoding(Location);
}
@@ -1266,7 +1326,7 @@ namespace clang {
uint64_t getInteger() const {
return Kind == IntegerLiteral ? IntegerValue : 0;
}
-
+
StringRef getString() const {
return Kind == IntegerLiteral ? StringRef()
: StringRef(StringData, StringLength);
@@ -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; }
@@ -1408,7 +1475,7 @@ retry:
case tok::eof:
Tok.Kind = MMToken::EndOfFile;
break;
-
+
case tok::l_brace:
Tok.Kind = MMToken::LBrace;
break;
@@ -1416,27 +1483,27 @@ retry:
case tok::l_square:
Tok.Kind = MMToken::LSquare;
break;
-
+
case tok::period:
Tok.Kind = MMToken::Period;
break;
-
+
case tok::r_brace:
Tok.Kind = MMToken::RBrace;
break;
-
+
case tok::r_square:
Tok.Kind = MMToken::RSquare;
break;
-
+
case tok::star:
Tok.Kind = MMToken::Star;
break;
-
+
case tok::exclaim:
Tok.Kind = MMToken::Exclaim;
break;
-
+
case tok::string_literal: {
if (LToken.hasUDSuffix()) {
Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
@@ -1449,13 +1516,13 @@ retry:
StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target);
if (StringLiteral.hadError)
goto retry;
-
+
// Copy the string literal into our string data allocator.
unsigned Length = StringLiteral.GetStringLength();
char *Saved = StringData.Allocate<char>(Length + 1);
memcpy(Saved, StringLiteral.GetString().data(), Length);
Saved[Length] = 0;
-
+
// Form the token.
Tok.Kind = MMToken::StringLiteral;
Tok.StringData = Saved;
@@ -1481,7 +1548,7 @@ retry:
Tok.IntegerValue = Value;
break;
}
-
+
case tok::comment:
goto retry;
@@ -1509,7 +1576,7 @@ retry:
HadError = true;
goto retry;
}
-
+
return Result;
}
@@ -1524,14 +1591,14 @@ void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
case MMToken::LBrace:
if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
return;
-
+
++braceDepth;
break;
case MMToken::LSquare:
if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
return;
-
+
++squareDepth;
break;
@@ -1554,12 +1621,12 @@ void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
return;
break;
}
-
+
consumeToken();
} while (true);
}
-/// \brief Parse a module-id.
+/// Parse a module-id.
///
/// module-id:
/// identifier
@@ -1576,33 +1643,33 @@ bool ModuleMapParser::parseModuleId(ModuleId &Id) {
Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
return true;
}
-
+
if (!Tok.is(MMToken::Period))
break;
-
+
consumeToken();
} while (true);
-
+
return false;
}
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,16 +1730,17 @@ 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
-/// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
+/// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
/// { module-member* }
///
/// module-member:
@@ -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,10 +1776,10 @@ void ModuleMapParser::parseModuleDecl() {
// Parse 'framework' keyword, if present.
if (Tok.is(MMToken::FrameworkKeyword)) {
- consumeToken();
+ FrameworkLoc = consumeToken();
Framework = true;
- }
-
+ }
+
// Parse 'module' keyword.
if (!Tok.is(MMToken::ModuleKeyword)) {
Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
@@ -1706,13 +1787,13 @@ 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.
+ // Parse it.
if (Tok.is(MMToken::Star))
return parseInferredModuleDecl(Framework, Explicit);
-
+
// Parse the module name.
ModuleId Id;
if (parseModuleId(Id)) {
@@ -1724,7 +1805,7 @@ void ModuleMapParser::parseModuleDecl() {
if (Id.size() > 1) {
Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
<< SourceRange(Id.front().second, Id.back().second);
-
+
HadError = true;
return;
}
@@ -1735,8 +1816,8 @@ void ModuleMapParser::parseModuleDecl() {
ExplicitLoc = SourceLocation();
HadError = true;
}
-
- Module *PreviousActiveModule = ActiveModule;
+
+ Module *PreviousActiveModule = ActiveModule;
if (Id.size() > 1) {
// This module map defines a submodule. Go find the module of which it
// is a submodule.
@@ -1749,7 +1830,7 @@ void ModuleMapParser::parseModuleDecl() {
ActiveModule = Next;
continue;
}
-
+
if (ActiveModule) {
Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
<< Id[I].first
@@ -1768,10 +1849,10 @@ void ModuleMapParser::parseModuleDecl() {
Map.addAdditionalModuleMapFile(TopLevelModule, ModuleMapFile);
}
}
-
+
StringRef ModuleName = Id.back().first;
SourceLocation ModuleNameLoc = Id.back().second;
-
+
// Parse the optional attribute list.
Attributes Attrs;
if (parseOptionalAttributes(Attrs))
@@ -1783,10 +1864,11 @@ void ModuleMapParser::parseModuleDecl() {
<< ModuleName;
HadError = true;
return;
- }
+ }
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:
@@ -1808,27 +1890,39 @@ void ModuleMapParser::parseModuleDecl() {
else {
Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
- HadError = true;
+ HadError = true;
}
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 {
@@ -1889,7 +1986,7 @@ void ModuleMapParser::parseModuleDecl() {
case MMToken::UseKeyword:
parseUseDecl();
break;
-
+
case MMToken::RequiresKeyword:
parseRequiresDecl();
break;
@@ -1926,7 +2023,7 @@ void ModuleMapParser::parseModuleDecl() {
default:
Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
consumeToken();
- break;
+ break;
}
} while (!Done);
@@ -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
@@ -2136,7 +2233,7 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
// Parse the header name.
if (!Tok.is(MMToken::StringLiteral)) {
- Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
+ Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
<< "header";
HadError = true;
return;
@@ -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,14 +2323,14 @@ 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
void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
// Parse the directory name.
if (!Tok.is(MMToken::StringLiteral)) {
- Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
+ Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
<< "umbrella";
HadError = true;
return;
@@ -2235,7 +2338,7 @@ void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
std::string DirName = Tok.getString();
SourceLocation DirNameLoc = consumeToken();
-
+
// Check whether we already have an umbrella.
if (ActiveModule->Umbrella) {
Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
@@ -2254,7 +2357,7 @@ void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
llvm::sys::path::append(PathName, DirName);
Dir = SourceMgr.getFileManager().getDirectory(PathName);
}
-
+
if (!Dir) {
Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found)
<< DirName;
@@ -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
@@ -2310,43 +2413,43 @@ void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
void ModuleMapParser::parseExportDecl() {
assert(Tok.is(MMToken::ExportKeyword));
SourceLocation ExportLoc = consumeToken();
-
+
// Parse the module-id with an optional wildcard at the end.
ModuleId ParsedModuleId;
bool Wildcard = false;
do {
// FIXME: Support string-literal module names here.
if (Tok.is(MMToken::Identifier)) {
- ParsedModuleId.push_back(std::make_pair(Tok.getString(),
+ ParsedModuleId.push_back(std::make_pair(Tok.getString(),
Tok.getLocation()));
consumeToken();
-
+
if (Tok.is(MMToken::Period)) {
consumeToken();
continue;
- }
-
+ }
+
break;
}
-
+
if(Tok.is(MMToken::Star)) {
Wildcard = true;
consumeToken();
break;
}
-
+
Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
HadError = true;
return;
} while (true);
-
- Module::UnresolvedExportDecl Unresolved = {
- ExportLoc, ParsedModuleId, Wildcard
+
+ Module::UnresolvedExportDecl Unresolved = {
+ ExportLoc, ParsedModuleId, Wildcard
};
ActiveModule->UnresolvedExports.push_back(Unresolved);
}
-/// \brief Parse a module export_as declaration.
+/// Parse a module export_as declaration.
///
/// export-as-declaration:
/// 'export_as' identifier
@@ -2365,7 +2468,7 @@ void ModuleMapParser::parseExportAsDecl() {
consumeToken();
return;
}
-
+
if (!ActiveModule->ExportAsModule.empty()) {
if (ActiveModule->ExportAsModule == Tok.getString()) {
Diags.Report(Tok.getLocation(), diag::warn_mmap_redundant_export_as)
@@ -2376,12 +2479,14 @@ void ModuleMapParser::parseExportAsDecl() {
<< Tok.getString();
}
}
-
+
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]
@@ -2561,7 +2666,7 @@ void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
Failed = true;
}
-
+
// Check for redefinition of an inferred module.
if (!Failed && ActiveModule->InferSubmodules) {
Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
@@ -2616,7 +2721,7 @@ void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
HadError = true;
return;
- }
+ }
SourceLocation LBraceLoc = consumeToken();
// Parse the body of the inferred submodule.
@@ -2657,10 +2762,10 @@ void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
}
consumeToken();
- if (Tok.is(MMToken::Star))
+ if (Tok.is(MMToken::Star))
ActiveModule->InferExportWildcard = true;
else
- Diags.Report(Tok.getLocation(),
+ Diags.Report(Tok.getLocation(),
diag::err_mmap_expected_export_wildcard);
consumeToken();
break;
@@ -2674,10 +2779,10 @@ void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
<< (ActiveModule != nullptr);
consumeToken();
- break;
+ break;
}
} while (!Done);
-
+
if (Tok.is(MMToken::RBrace))
consumeToken();
else {
@@ -2687,7 +2792,7 @@ void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
}
}
-/// \brief Parse optional attributes.
+/// Parse optional attributes.
///
/// attributes:
/// attribute attributes
@@ -2701,7 +2806,7 @@ void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
/// \returns true if an error occurred, false otherwise.
bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
bool HadError = false;
-
+
while (Tok.is(MMToken::LSquare)) {
// Consume the '['.
SourceLocation LSquareLoc = consumeToken();
@@ -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*
@@ -2771,7 +2876,7 @@ bool ModuleMapParser::parseModuleMapFile() {
switch (Tok.Kind) {
case MMToken::EndOfFile:
return HadError;
-
+
case MMToken::ExplicitKeyword:
case MMToken::ExternKeyword:
case MMToken::ModuleKeyword:
@@ -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;
}