summaryrefslogtreecommitdiff
path: root/clang/lib/Lex/ModuleMapFile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Lex/ModuleMapFile.cpp')
-rw-r--r--clang/lib/Lex/ModuleMapFile.cpp34
1 files changed, 30 insertions, 4 deletions
diff --git a/clang/lib/Lex/ModuleMapFile.cpp b/clang/lib/Lex/ModuleMapFile.cpp
index 183e919d14c2..f0cd9d2bee82 100644
--- a/clang/lib/Lex/ModuleMapFile.cpp
+++ b/clang/lib/Lex/ModuleMapFile.cpp
@@ -118,7 +118,8 @@ struct ModuleMapFileParser {
std::optional<ExcludeDecl> parseExcludeDecl(clang::SourceLocation LeadingLoc);
std::optional<UmbrellaDirDecl>
parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
- std::optional<LinkDecl> parseLinkDecl();
+ std::optional<LinkDecl>
+ parseLinkDecl(llvm::StringMap<SourceLocation> &SeenLinkDecl, bool Allowed);
SourceLocation consumeToken();
void skipUntil(MMToken::TokenKind K);
@@ -325,6 +326,7 @@ std::optional<ModuleDecl> ModuleMapFileParser::parseModuleDecl(bool TopLevel) {
SourceLocation LBraceLoc = consumeToken();
bool Done = false;
+ llvm::StringMap<SourceLocation> SeenLinkDecl;
do {
std::optional<Decl> SubDecl;
switch (Tok.Kind) {
@@ -405,7 +407,9 @@ std::optional<ModuleDecl> ModuleMapFileParser::parseModuleDecl(bool TopLevel) {
break;
case MMToken::LinkKeyword:
- SubDecl = parseLinkDecl();
+ // Link decls are only allowed in top level modules or explicit
+ // submodules.
+ SubDecl = parseLinkDecl(SeenLinkDecl, TopLevel || MDecl.Explicit);
break;
default:
@@ -822,7 +826,8 @@ ModuleMapFileParser::parseUmbrellaDirDecl(clang::SourceLocation UmbrellaLoc) {
///
/// module-declaration:
/// 'link' 'framework'[opt] string-literal
-std::optional<LinkDecl> ModuleMapFileParser::parseLinkDecl() {
+std::optional<LinkDecl> ModuleMapFileParser::parseLinkDecl(
+ llvm::StringMap<SourceLocation> &SeenLinkDecl, bool Allowed) {
assert(Tok.is(MMToken::LinkKeyword));
LinkDecl LD;
LD.Location = consumeToken();
@@ -838,12 +843,33 @@ std::optional<LinkDecl> ModuleMapFileParser::parseLinkDecl() {
if (!Tok.is(MMToken::StringLiteral)) {
Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name)
<< LD.Framework << SourceRange(LD.Location);
+ consumeToken();
HadError = true;
return std::nullopt;
}
- LD.Library = Tok.getString();
+ StringRef Library = Tok.getString();
+
+ LD.Library = Library;
consumeToken();
+
+ // Make sure we eat all the tokens when we report the errors so parsing
+ // can continue.
+ if (!Allowed) {
+ Diags.Report(LD.Location, diag::err_mmap_submodule_link_decl);
+ HadError = true;
+ return std::nullopt;
+ }
+
+ auto [It, Inserted] =
+ SeenLinkDecl.insert(std::make_pair(Library, LD.Location));
+ if (!Inserted) {
+ Diags.Report(LD.Location, diag::warn_mmap_link_redeclaration) << Library;
+ Diags.Report(It->second, diag::note_mmap_prev_link_declaration);
+ HadError = true;
+ return std::nullopt;
+ }
+
return std::move(LD);
}