-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[clang][modules] Use file name as requested #68957
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This prevents redefinition errors due to having multiple paths for the same module map. (rdar://24116019) Originally implemented and tested downstream by @bcardosolopes, I just made use of `FileEntryRef::getNameAsRequested()`.
@llvm/pr-subscribers-clang @llvm/pr-subscribers-clang-modules Author: Jan Svoboda (jansvoboda11) ChangesThis prevents redefinition errors due to having multiple paths for the same module map. (rdar://24116019) Originally implemented and tested downstream by @bcardosolopes, I just made use of Full diff: https://github.com/llvm/llvm-project/pull/68957.diff 4 Files Affected:
diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp
index 4c8b64a374b47d5..cf1c0cc5284f316 100644
--- a/clang/lib/Lex/HeaderSearch.cpp
+++ b/clang/lib/Lex/HeaderSearch.cpp
@@ -1623,7 +1623,7 @@ bool HeaderSearch::findUsableModuleForHeader(
ModuleMap::KnownHeader *SuggestedModule, bool IsSystemHeaderDir) {
if (needModuleLookup(RequestingModule, SuggestedModule)) {
// If there is a module that corresponds to this header, suggest it.
- hasModuleMap(File.getName(), Root, IsSystemHeaderDir);
+ hasModuleMap(File.getNameAsRequested(), Root, IsSystemHeaderDir);
return suggestModule(*this, File, RequestingModule, SuggestedModule);
}
return true;
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 27700c711d52fdd..0d216927d76260d 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -1384,10 +1384,10 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
SmallVector<FileEntryRef, 1> ModMaps(AdditionalModMaps->begin(),
AdditionalModMaps->end());
llvm::sort(ModMaps, [](FileEntryRef A, FileEntryRef B) {
- return A.getName() < B.getName();
+ return A.getNameAsRequested() < B.getNameAsRequested();
});
for (FileEntryRef F : ModMaps)
- AddPath(F.getName(), Record);
+ AddPath(F.getNameAsRequested(), Record);
} else {
Record.push_back(0);
}
diff --git a/clang/test/Modules/Inputs/all-product-headers.yaml b/clang/test/Modules/Inputs/all-product-headers.yaml
new file mode 100644
index 000000000000000..53d683f2ad2ecc0
--- /dev/null
+++ b/clang/test/Modules/Inputs/all-product-headers.yaml
@@ -0,0 +1,33 @@
+{
+ 'version': 0,
+ 'case-sensitive': 'false',
+ 'roots': [
+ {
+ 'type': 'directory',
+ 'name': "DUMMY_DIR/build/A.framework/PrivateHeaders"
+ 'contents': [
+ {
+ 'type': 'file',
+ 'name': "A.h",
+ 'external-contents': "DUMMY_DIR/sources/A.h"
+ }
+ ]
+ },
+ {
+ 'type': 'directory',
+ 'name': "DUMMY_DIR/build/A.framework/Modules"
+ 'contents': [
+ {
+ 'type': 'file',
+ 'name': "module.modulemap",
+ 'external-contents': "DUMMY_DIR/build/module.modulemap"
+ },
+ {
+ 'type': 'file',
+ 'name': "module.private.modulemap",
+ 'external-contents': "DUMMY_DIR/build/module.private.modulemap"
+ }
+ ]
+ }
+ ]
+}
diff --git a/clang/test/Modules/modulemap-collision.m b/clang/test/Modules/modulemap-collision.m
new file mode 100644
index 000000000000000..5ada45da3dae191
--- /dev/null
+++ b/clang/test/Modules/modulemap-collision.m
@@ -0,0 +1,15 @@
+// REQUIRES: shell
+
+// RUN: rm -rf %t
+// RUN: mkdir -p %t/sources %t/build
+// RUN: echo "// A.h" > %t/sources/A.h
+// RUN: echo "framework module A {}" > %t/sources/module.modulemap
+// RUN: echo "framework module A.Private { umbrella header \"A.h\" }" > %t/sources/module.private.modulemap
+// RUN: cp %t/sources/module.modulemap %t/build/module.modulemap
+// RUN: cp %t/sources/module.private.modulemap %t/build/module.private.modulemap
+
+// RUN: sed -e "s:DUMMY_DIR:%t:g" %S/Inputs/all-product-headers.yaml > %t/build/all-product-headers.yaml
+// RUN: %clang_cc1 -fsyntax-only -ivfsoverlay %t/build/all-product-headers.yaml -F%t/build -fmodules -fimplicit-module-maps -Wno-private-module -fmodules-cache-path=%t/cache -x objective-c %s -verify
+
+// expected-no-diagnostics
+#import <A/A.h>
|
}); | ||
for (FileEntryRef F : ModMaps) | ||
AddPath(F.getName(), Record); | ||
AddPath(F.getNameAsRequested(), Record); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does this relate to the header search part of the change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, this is a bit suspicious. This test started failing downstream after de85739 and this change appeared to be required to fix things.
Turns out llvm::SmallPtrSet<FileEntryRef, 1>
determines equality of elements based on the equality of their void *
representation, not based on FileEntryRef::operator==()
. This means that when we find the module map through a VFS, but serialize the on-disk path, we aren't able to correctly match them together in ASTReader
.
I don't want to go messing with the SmallPtrSet
implementation, so I'll probably just revert D154905 (making the types unusable in SmallPtrSet
) and switch from llvm::SmallPtrSet<FileEntryRef, 1>
to llvm::DenseMap<FileEntryRef>
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in the two new commits.
`FileEntryRef::getNameAsRequested()`
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks
This prevents redefinition errors due to having multiple paths for the same module map. (rdar://24116019)
Originally implemented and tested downstream by @bcardosolopes, I just made use of
FileEntryRef::getNameAsRequested()
.