Skip to content

[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

Merged
merged 3 commits into from
Oct 20, 2023

Conversation

jansvoboda11
Copy link
Contributor

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().

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()`.
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:modules C++20 modules and Clang Header Modules labels Oct 13, 2023
@llvmbot
Copy link
Member

llvmbot commented Oct 13, 2023

@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clang-modules

Author: Jan Svoboda (jansvoboda11)

Changes

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().


Full diff: https://github.com/llvm/llvm-project/pull/68957.diff

4 Files Affected:

  • (modified) clang/lib/Lex/HeaderSearch.cpp (+1-1)
  • (modified) clang/lib/Serialization/ASTWriter.cpp (+2-2)
  • (added) clang/test/Modules/Inputs/all-product-headers.yaml (+33)
  • (added) clang/test/Modules/modulemap-collision.m (+15)
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);
Copy link
Collaborator

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?

Copy link
Contributor Author

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>.

Copy link
Contributor Author

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.

Copy link
Collaborator

@benlangmuir benlangmuir left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:modules C++20 modules and Clang Header Modules clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants