[clang] [clang][Modules] Reporting Errors for Duplicating Link Declarations in `modulemap`s (PR #148959)
Qiongsi Wu via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 17 10:10:58 PDT 2025
https://github.com/qiongsiwu updated https://github.com/llvm/llvm-project/pull/148959
>From 0e8a0db8ace8fd1f450cf2364b4c975d418eddc1 Mon Sep 17 00:00:00 2001
From: Qiongsi Wu <qiongsi_wu at apple.com>
Date: Mon, 14 Jul 2025 18:22:27 -0700
Subject: [PATCH 1/5] Initial implementation of modulemap link decl duplication
check.
---
.../include/clang/Basic/DiagnosticLexKinds.td | 2 ++
clang/lib/Lex/ModuleMap.cpp | 12 ++++++++
.../ClangScanDeps/link-libraries-diag-dup.c | 30 +++++++++++++++++++
3 files changed, 44 insertions(+)
create mode 100644 clang/test/ClangScanDeps/link-libraries-diag-dup.c
diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td b/clang/include/clang/Basic/DiagnosticLexKinds.td
index 723f5d48b4f5f..f3c9e63a7ca61 100644
--- a/clang/include/clang/Basic/DiagnosticLexKinds.td
+++ b/clang/include/clang/Basic/DiagnosticLexKinds.td
@@ -909,6 +909,8 @@ def err_mmap_nested_submodule_id : Error<
"qualified module name can only be used to define modules at the top level">;
def err_mmap_expected_feature : Error<"expected a feature name">;
def err_mmap_expected_attribute : Error<"expected an attribute name">;
+def err_mmap_link_redecalration : Error<"redeclaration of link library '%0'">;
+def note_mmap_prev_link_declaration : Note<"previously declared here">;
def warn_mmap_unknown_attribute : Warning<"unknown attribute '%0'">,
InGroup<IgnoredAttributes>;
def warn_mmap_mismatched_private_submodule : Warning<
diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp
index 637a08fe4dcdb..5f815f38a4f54 100644
--- a/clang/lib/Lex/ModuleMap.cpp
+++ b/clang/lib/Lex/ModuleMap.cpp
@@ -1570,6 +1570,10 @@ class ModuleMapLoader {
/// 'textual' to match the original intent.
llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack;
+ /// Tracks the link library decls in the module map.
+ llvm::DenseMap<Module *, llvm::StringMap<SourceLocation>>
+ LinkLibraryLibStrMap;
+
void handleModuleDecl(const modulemap::ModuleDecl &MD);
void handleExternModuleDecl(const modulemap::ExternModuleDecl &EMD);
void handleRequiresDecl(const modulemap::RequiresDecl &RD);
@@ -2067,6 +2071,14 @@ void ModuleMapLoader::handleUseDecl(const modulemap::UseDecl &UD) {
}
void ModuleMapLoader::handleLinkDecl(const modulemap::LinkDecl &LD) {
+ auto &LibStrMap = LinkLibraryLibStrMap[ActiveModule];
+ auto [It, Inserted] =
+ LibStrMap.insert(std::make_pair(LD.Library, LD.Location));
+ if (!Inserted) {
+ Diags.Report(LD.Location, diag::err_mmap_link_redecalration) << LD.Library;
+ Diags.Report(It->second, diag::note_mmap_prev_link_declaration);
+ return;
+ }
ActiveModule->LinkLibraries.push_back(
Module::LinkLibrary(std::string{LD.Library}, LD.Framework));
}
diff --git a/clang/test/ClangScanDeps/link-libraries-diag-dup.c b/clang/test/ClangScanDeps/link-libraries-diag-dup.c
new file mode 100644
index 0000000000000..c04769465fe0b
--- /dev/null
+++ b/clang/test/ClangScanDeps/link-libraries-diag-dup.c
@@ -0,0 +1,30 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: split-file %s %t
+
+//--- module.modulemap
+module A {
+ umbrella header "A.h"
+
+ link "libraryA"
+ link "libraryA"
+}
+
+//--- A.h
+// empty
+//--- TU.c
+#include "A.h"
+
+//--- cdb.json.template
+[{
+ "file": "DIR/TU.c",
+ "directory": "DIR",
+ "command": "clang -fmodules -fmodules-cache-path=DIR/cache -I DIR -c DIR/TU.c"
+}]
+
+// RUN: sed "s|DIR|%/t|g" %t/cdb.json.template > %t/cdb.json
+// RUN: not clang-scan-deps -compilation-database %t/cdb.json -format \
+// RUN: experimental-full 2>&1 | FileCheck %s
+
+// CHECK: module.modulemap:5:3: error: redeclaration of link library 'libraryA'
+// CHECK-NEXT: module.modulemap:4:3: note: previously declared here
>From b21831f82dbc23d7ad19d8c89bbcd7eb3f777326 Mon Sep 17 00:00:00 2001
From: Qiongsi Wu <qiongsi_wu at apple.com>
Date: Tue, 15 Jul 2025 17:00:07 -0700
Subject: [PATCH 2/5] Moving the checks to parsing time (instead of load time),
and adding an error whe link declarations are used in submodules.
---
.../include/clang/Basic/DiagnosticLexKinds.td | 2 ++
clang/lib/Lex/ModuleMap.cpp | 12 -------
clang/lib/Lex/ModuleMapFile.cpp | 32 ++++++++++++++++---
.../ClangScanDeps/link-libraries-diag-dup.c | 21 ++++++++++--
4 files changed, 49 insertions(+), 18 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td b/clang/include/clang/Basic/DiagnosticLexKinds.td
index f3c9e63a7ca61..b4dcb35454585 100644
--- a/clang/include/clang/Basic/DiagnosticLexKinds.td
+++ b/clang/include/clang/Basic/DiagnosticLexKinds.td
@@ -911,6 +911,8 @@ def err_mmap_expected_feature : Error<"expected a feature name">;
def err_mmap_expected_attribute : Error<"expected an attribute name">;
def err_mmap_link_redecalration : Error<"redeclaration of link library '%0'">;
def note_mmap_prev_link_declaration : Note<"previously declared here">;
+def err_mmap_submodule_link_decl
+ : Error<"link declaration is not allowed in submodules">;
def warn_mmap_unknown_attribute : Warning<"unknown attribute '%0'">,
InGroup<IgnoredAttributes>;
def warn_mmap_mismatched_private_submodule : Warning<
diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp
index 5f815f38a4f54..637a08fe4dcdb 100644
--- a/clang/lib/Lex/ModuleMap.cpp
+++ b/clang/lib/Lex/ModuleMap.cpp
@@ -1570,10 +1570,6 @@ class ModuleMapLoader {
/// 'textual' to match the original intent.
llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack;
- /// Tracks the link library decls in the module map.
- llvm::DenseMap<Module *, llvm::StringMap<SourceLocation>>
- LinkLibraryLibStrMap;
-
void handleModuleDecl(const modulemap::ModuleDecl &MD);
void handleExternModuleDecl(const modulemap::ExternModuleDecl &EMD);
void handleRequiresDecl(const modulemap::RequiresDecl &RD);
@@ -2071,14 +2067,6 @@ void ModuleMapLoader::handleUseDecl(const modulemap::UseDecl &UD) {
}
void ModuleMapLoader::handleLinkDecl(const modulemap::LinkDecl &LD) {
- auto &LibStrMap = LinkLibraryLibStrMap[ActiveModule];
- auto [It, Inserted] =
- LibStrMap.insert(std::make_pair(LD.Library, LD.Location));
- if (!Inserted) {
- Diags.Report(LD.Location, diag::err_mmap_link_redecalration) << LD.Library;
- Diags.Report(It->second, diag::note_mmap_prev_link_declaration);
- return;
- }
ActiveModule->LinkLibraries.push_back(
Module::LinkLibrary(std::string{LD.Library}, LD.Framework));
}
diff --git a/clang/lib/Lex/ModuleMapFile.cpp b/clang/lib/Lex/ModuleMapFile.cpp
index 183e919d14c22..abbac9cae09fb 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 TopLevel);
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,7 @@ std::optional<ModuleDecl> ModuleMapFileParser::parseModuleDecl(bool TopLevel) {
break;
case MMToken::LinkKeyword:
- SubDecl = parseLinkDecl();
+ SubDecl = parseLinkDecl(SeenLinkDecl, TopLevel);
break;
default:
@@ -822,7 +824,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 TopLevel) {
assert(Tok.is(MMToken::LinkKeyword));
LinkDecl LD;
LD.Location = consumeToken();
@@ -838,12 +841,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 (!TopLevel) {
+ 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::err_mmap_link_redecalration) << Library;
+ Diags.Report(It->second, diag::note_mmap_prev_link_declaration);
+ HadError = true;
+ return std::nullopt;
+ }
+
return std::move(LD);
}
diff --git a/clang/test/ClangScanDeps/link-libraries-diag-dup.c b/clang/test/ClangScanDeps/link-libraries-diag-dup.c
index c04769465fe0b..26bfdbac24a81 100644
--- a/clang/test/ClangScanDeps/link-libraries-diag-dup.c
+++ b/clang/test/ClangScanDeps/link-libraries-diag-dup.c
@@ -6,14 +6,29 @@
module A {
umbrella header "A.h"
+ module B {
+ header "B.h"
+ link "libraryB"
+ }
+
link "libraryA"
link "libraryA"
}
+module C {
+ header "C.h"
+ link "libraryA"
+}
+
//--- A.h
+#include "B.h"
+//--- B.h
+// empty
+//--- C.h
// empty
//--- TU.c
#include "A.h"
+#include "C.h"
//--- cdb.json.template
[{
@@ -26,5 +41,7 @@ module A {
// RUN: not clang-scan-deps -compilation-database %t/cdb.json -format \
// RUN: experimental-full 2>&1 | FileCheck %s
-// CHECK: module.modulemap:5:3: error: redeclaration of link library 'libraryA'
-// CHECK-NEXT: module.modulemap:4:3: note: previously declared here
+// CHECK: module.modulemap:6:5: error: link decl is not allowed in submodules
+// CHECK-NEXT: module.modulemap:10:3: error: redeclaration of link library 'libraryA'
+// CHECK-NEXT: module.modulemap:9:3: note: previously declared here
+// CHECK-NOT: module.modulemap:15:3: error: redeclaration of link library 'libraryA'
>From 3286622919aae32dc2f6da9ae75109f70cfd064a Mon Sep 17 00:00:00 2001
From: Qiongsi Wu <qiongsi_wu at apple.com>
Date: Wed, 16 Jul 2025 09:57:03 -0700
Subject: [PATCH 3/5] Revert the error check for link decls in submodules as
that is a feature as indicated by the test case clang/test/Modules/autolink.m
---
clang/include/clang/Basic/DiagnosticLexKinds.td | 2 --
clang/lib/Lex/ModuleMapFile.cpp | 6 ------
clang/test/ClangScanDeps/link-libraries-diag-dup.c | 10 ++++++----
3 files changed, 6 insertions(+), 12 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td b/clang/include/clang/Basic/DiagnosticLexKinds.td
index b4dcb35454585..f3c9e63a7ca61 100644
--- a/clang/include/clang/Basic/DiagnosticLexKinds.td
+++ b/clang/include/clang/Basic/DiagnosticLexKinds.td
@@ -911,8 +911,6 @@ def err_mmap_expected_feature : Error<"expected a feature name">;
def err_mmap_expected_attribute : Error<"expected an attribute name">;
def err_mmap_link_redecalration : Error<"redeclaration of link library '%0'">;
def note_mmap_prev_link_declaration : Note<"previously declared here">;
-def err_mmap_submodule_link_decl
- : Error<"link declaration is not allowed in submodules">;
def warn_mmap_unknown_attribute : Warning<"unknown attribute '%0'">,
InGroup<IgnoredAttributes>;
def warn_mmap_mismatched_private_submodule : Warning<
diff --git a/clang/lib/Lex/ModuleMapFile.cpp b/clang/lib/Lex/ModuleMapFile.cpp
index abbac9cae09fb..5719155c6305c 100644
--- a/clang/lib/Lex/ModuleMapFile.cpp
+++ b/clang/lib/Lex/ModuleMapFile.cpp
@@ -853,12 +853,6 @@ std::optional<LinkDecl> ModuleMapFileParser::parseLinkDecl(
// Make sure we eat all the tokens when we report the errors so parsing
// can continue.
- if (!TopLevel) {
- 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) {
diff --git a/clang/test/ClangScanDeps/link-libraries-diag-dup.c b/clang/test/ClangScanDeps/link-libraries-diag-dup.c
index 26bfdbac24a81..b948eba7c3dec 100644
--- a/clang/test/ClangScanDeps/link-libraries-diag-dup.c
+++ b/clang/test/ClangScanDeps/link-libraries-diag-dup.c
@@ -8,7 +8,7 @@ module A {
module B {
header "B.h"
- link "libraryB"
+ link "libraryA"
}
link "libraryA"
@@ -41,7 +41,9 @@ module C {
// RUN: not clang-scan-deps -compilation-database %t/cdb.json -format \
// RUN: experimental-full 2>&1 | FileCheck %s
-// CHECK: module.modulemap:6:5: error: link decl is not allowed in submodules
-// CHECK-NEXT: module.modulemap:10:3: error: redeclaration of link library 'libraryA'
+// Note that the link declaration in submodule B does not conflict with the
+// first link declaration in module A, since we only check link declaration
+// duplications within the current module.
+// CHECK: module.modulemap:10:3: error: redeclaration of link library 'libraryA'
// CHECK-NEXT: module.modulemap:9:3: note: previously declared here
-// CHECK-NOT: module.modulemap:15:3: error: redeclaration of link library 'libraryA'
+// CHECK-NOT: module.modulemap:15:3: error: redeclaration of link library 'libraryA'
>From 42e168576f54cb536cddaa01d0a3d7d4c40dc69b Mon Sep 17 00:00:00 2001
From: Qiongsi Wu <qiongsi_wu at apple.com>
Date: Thu, 17 Jul 2025 09:03:55 -0700
Subject: [PATCH 4/5] Revert "Revert the error check for link decls in
submodules as that is a feature as indicated by the test case
clang/test/Modules/autolink.m"
This reverts commit 3286622919aae32dc2f6da9ae75109f70cfd064a.
---
clang/include/clang/Basic/DiagnosticLexKinds.td | 2 ++
clang/lib/Lex/ModuleMapFile.cpp | 6 ++++++
clang/test/ClangScanDeps/link-libraries-diag-dup.c | 10 ++++------
3 files changed, 12 insertions(+), 6 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td b/clang/include/clang/Basic/DiagnosticLexKinds.td
index f3c9e63a7ca61..b4dcb35454585 100644
--- a/clang/include/clang/Basic/DiagnosticLexKinds.td
+++ b/clang/include/clang/Basic/DiagnosticLexKinds.td
@@ -911,6 +911,8 @@ def err_mmap_expected_feature : Error<"expected a feature name">;
def err_mmap_expected_attribute : Error<"expected an attribute name">;
def err_mmap_link_redecalration : Error<"redeclaration of link library '%0'">;
def note_mmap_prev_link_declaration : Note<"previously declared here">;
+def err_mmap_submodule_link_decl
+ : Error<"link declaration is not allowed in submodules">;
def warn_mmap_unknown_attribute : Warning<"unknown attribute '%0'">,
InGroup<IgnoredAttributes>;
def warn_mmap_mismatched_private_submodule : Warning<
diff --git a/clang/lib/Lex/ModuleMapFile.cpp b/clang/lib/Lex/ModuleMapFile.cpp
index 5719155c6305c..abbac9cae09fb 100644
--- a/clang/lib/Lex/ModuleMapFile.cpp
+++ b/clang/lib/Lex/ModuleMapFile.cpp
@@ -853,6 +853,12 @@ std::optional<LinkDecl> ModuleMapFileParser::parseLinkDecl(
// Make sure we eat all the tokens when we report the errors so parsing
// can continue.
+ if (!TopLevel) {
+ 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) {
diff --git a/clang/test/ClangScanDeps/link-libraries-diag-dup.c b/clang/test/ClangScanDeps/link-libraries-diag-dup.c
index b948eba7c3dec..26bfdbac24a81 100644
--- a/clang/test/ClangScanDeps/link-libraries-diag-dup.c
+++ b/clang/test/ClangScanDeps/link-libraries-diag-dup.c
@@ -8,7 +8,7 @@ module A {
module B {
header "B.h"
- link "libraryA"
+ link "libraryB"
}
link "libraryA"
@@ -41,9 +41,7 @@ module C {
// RUN: not clang-scan-deps -compilation-database %t/cdb.json -format \
// RUN: experimental-full 2>&1 | FileCheck %s
-// Note that the link declaration in submodule B does not conflict with the
-// first link declaration in module A, since we only check link declaration
-// duplications within the current module.
-// CHECK: module.modulemap:10:3: error: redeclaration of link library 'libraryA'
+// CHECK: module.modulemap:6:5: error: link decl is not allowed in submodules
+// CHECK-NEXT: module.modulemap:10:3: error: redeclaration of link library 'libraryA'
// CHECK-NEXT: module.modulemap:9:3: note: previously declared here
-// CHECK-NOT: module.modulemap:15:3: error: redeclaration of link library 'libraryA'
+// CHECK-NOT: module.modulemap:15:3: error: redeclaration of link library 'libraryA'
>From bf8a718e546ae4dcaf7d796cd2e492eaba0a46eb Mon Sep 17 00:00:00 2001
From: Qiongsi Wu <qiongsi_wu at apple.com>
Date: Thu, 17 Jul 2025 10:10:38 -0700
Subject: [PATCH 5/5] Allowing link decls in explicit submodules.
---
clang/lib/Lex/ModuleMapFile.cpp | 10 ++++++----
.../ClangScanDeps/link-libraries-diag-dup.c | 18 ++++++++++++++----
2 files changed, 20 insertions(+), 8 deletions(-)
diff --git a/clang/lib/Lex/ModuleMapFile.cpp b/clang/lib/Lex/ModuleMapFile.cpp
index abbac9cae09fb..08bba8c16e2d6 100644
--- a/clang/lib/Lex/ModuleMapFile.cpp
+++ b/clang/lib/Lex/ModuleMapFile.cpp
@@ -119,7 +119,7 @@ struct ModuleMapFileParser {
std::optional<UmbrellaDirDecl>
parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
std::optional<LinkDecl>
- parseLinkDecl(llvm::StringMap<SourceLocation> &SeenLinkDecl, bool TopLevel);
+ parseLinkDecl(llvm::StringMap<SourceLocation> &SeenLinkDecl, bool Allowed);
SourceLocation consumeToken();
void skipUntil(MMToken::TokenKind K);
@@ -407,7 +407,9 @@ std::optional<ModuleDecl> ModuleMapFileParser::parseModuleDecl(bool TopLevel) {
break;
case MMToken::LinkKeyword:
- SubDecl = parseLinkDecl(SeenLinkDecl, TopLevel);
+ // Link decls are only allowed in top level modules or explicit
+ // submodules.
+ SubDecl = parseLinkDecl(SeenLinkDecl, TopLevel || MDecl.Explicit);
break;
default:
@@ -825,7 +827,7 @@ ModuleMapFileParser::parseUmbrellaDirDecl(clang::SourceLocation UmbrellaLoc) {
/// module-declaration:
/// 'link' 'framework'[opt] string-literal
std::optional<LinkDecl> ModuleMapFileParser::parseLinkDecl(
- llvm::StringMap<SourceLocation> &SeenLinkDecl, bool TopLevel) {
+ llvm::StringMap<SourceLocation> &SeenLinkDecl, bool Allowed) {
assert(Tok.is(MMToken::LinkKeyword));
LinkDecl LD;
LD.Location = consumeToken();
@@ -853,7 +855,7 @@ std::optional<LinkDecl> ModuleMapFileParser::parseLinkDecl(
// Make sure we eat all the tokens when we report the errors so parsing
// can continue.
- if (!TopLevel) {
+ if (!Allowed) {
Diags.Report(LD.Location, diag::err_mmap_submodule_link_decl);
HadError = true;
return std::nullopt;
diff --git a/clang/test/ClangScanDeps/link-libraries-diag-dup.c b/clang/test/ClangScanDeps/link-libraries-diag-dup.c
index 26bfdbac24a81..6f9d4be4447a6 100644
--- a/clang/test/ClangScanDeps/link-libraries-diag-dup.c
+++ b/clang/test/ClangScanDeps/link-libraries-diag-dup.c
@@ -11,6 +11,11 @@ module A {
link "libraryB"
}
+ explicit module D {
+ header "D.h"
+ link "libraryD"
+ }
+
link "libraryA"
link "libraryA"
}
@@ -26,9 +31,12 @@ module C {
// empty
//--- C.h
// empty
+//--- D.h
+// empty
//--- TU.c
#include "A.h"
#include "C.h"
+#include "D.h"
//--- cdb.json.template
[{
@@ -41,7 +49,9 @@ module C {
// RUN: not clang-scan-deps -compilation-database %t/cdb.json -format \
// RUN: experimental-full 2>&1 | FileCheck %s
-// CHECK: module.modulemap:6:5: error: link decl is not allowed in submodules
-// CHECK-NEXT: module.modulemap:10:3: error: redeclaration of link library 'libraryA'
-// CHECK-NEXT: module.modulemap:9:3: note: previously declared here
-// CHECK-NOT: module.modulemap:15:3: error: redeclaration of link library 'libraryA'
+// Note that module D does not report an error because it is explicit.
+// Therefore we can use CHECK-NEXT for the redeclaration error on line 15.
+// CHECK: module.modulemap:6:5: error: link declaration is not allowed in submodules
+// CHECK-NEXT: module.modulemap:15:3: error: redeclaration of link library 'libraryA'
+// CHECK-NEXT: module.modulemap:14:3: note: previously declared here
+// CHECK-NOT: module.modulemap:20:3: error: redeclaration of link library 'libraryA'
More information about the cfe-commits
mailing list