Skip to content

[clang] Fix sorting header paths #73323

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open

Conversation

tuliom
Copy link
Contributor

@tuliom tuliom commented Nov 24, 2023

This code was initially written in commit
7ff2914 with the intention of sorting headers according to their path. At the time, the path was saved in field NameAsWritten of Module::Header.

Later, commit e6830b6 added field PathRelativeToRootModuleDirectory to Module::Header and modified ModuleMapParser::parseUmbrellaDirDecl() so that it started to save the header path in the new field and started setting NameAsWritten = "". It didn't modify compareModuleHeaders() in order to adapt it to the new field.

After this commit, the sorting stopped working because it continued comparing only NameAsWritten.

This commit fixes it by treating NameAsWritten and PathRelativeToRootModuleDirectory as a tuple when comparing Module::Header.

This code was initially written in commit
7ff2914 with the intention of sorting
headers according to their path. At the time, the path was saved in
field NameAsWritten of Module::Header.

Later, commit e6830b6 added field
PathRelativeToRootModuleDirectory to Module::Header and modified
ModuleMapParser::parseUmbrellaDirDecl() so that it started to save the
header path in the new field and started setting NameAsWritten = "".
It didn't modify compareModuleHeaders() in order to adapt it to the new
field.

After this commit, the sorting stopped working because it continued
comparing only NameAsWritten.

This commit fixes it by treating NameAsWritten and
PathRelativeToRootModuleDirectory as a tuple when comparing Module::Header.
@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 Nov 24, 2023
@llvmbot
Copy link
Member

llvmbot commented Nov 24, 2023

@llvm/pr-subscribers-clang-modules

@llvm/pr-subscribers-clang

Author: Tulio Magno Quites Machado Filho (tuliom)

Changes

This code was initially written in commit
7ff2914 with the intention of sorting headers according to their path. At the time, the path was saved in field NameAsWritten of Module::Header.

Later, commit e6830b6 added field PathRelativeToRootModuleDirectory to Module::Header and modified ModuleMapParser::parseUmbrellaDirDecl() so that it started to save the header path in the new field and started setting NameAsWritten = "". It didn't modify compareModuleHeaders() in order to adapt it to the new field.

After this commit, the sorting stopped working because it continued comparing only NameAsWritten.

This commit fixes it by treating NameAsWritten and PathRelativeToRootModuleDirectory as a tuple when comparing Module::Header.


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

1 Files Affected:

  • (modified) clang/lib/Lex/ModuleMap.cpp (+3-1)
diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp
index 1d67e275cb4775a..7bc89b2fed36bf2 100644
--- a/clang/lib/Lex/ModuleMap.cpp
+++ b/clang/lib/Lex/ModuleMap.cpp
@@ -49,6 +49,7 @@
 #include <optional>
 #include <string>
 #include <system_error>
+#include <tuple>
 #include <utility>
 
 using namespace clang;
@@ -2511,7 +2512,8 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
 
 static bool compareModuleHeaders(const Module::Header &A,
                                  const Module::Header &B) {
-  return A.NameAsWritten < B.NameAsWritten;
+  return std::tie(A.NameAsWritten, A.PathRelativeToRootModuleDirectory) <
+         std::tie(B.NameAsWritten, B.PathRelativeToRootModuleDirectory);
 }
 
 /// Parse an umbrella directory declaration.

@dwblaikie
Copy link
Collaborator

So what breakage is caused by the sorting failure? Can that behavior be tested in some way to validate this change and ensure it doesn't regress in the future?

@tuliom
Copy link
Contributor Author

tuliom commented Nov 27, 2023

So what breakage is caused by the sorting failure?

@dwblaikie This is not causing a breakage. It is just not working as designed because the sort function has been comparing "" against "" since commit e6830b6 .

I found this while investigating issue #73145.

The way the code is behaving now, the sort function is acting as a NOP and could be removed. However, I don't think that was the intention of the author of 7ff2914.

Can that behavior be tested in some way to validate this change and ensure it doesn't regress in the future?

Possibly. Let me think on this.

@dwblaikie
Copy link
Collaborator

So what breakage is caused by the sorting failure?

@dwblaikie This is not causing a breakage. It is just not working as designed because the sort function has been comparing "" against "" since commit e6830b6 .

I found this while investigating issue #73145.

The way the code is behaving now, the sort function is acting as a NOP and could be removed. However, I don't think that was the intention of the author of 7ff2914.

Can that behavior be tested in some way to validate this change and ensure it doesn't regress in the future?

Possibly. Let me think on this.

Yeah, looks like this was undertested when originally committed. Perhaps @benlangmuir can help sort out a test for this?

Possibly creating a directory with a few headers & they'll appear in some arbitrary order from the OS in the recursive_directory_iterator - and then is there a way to print out the header map? We could print that out and demonstrate it is in the sorted order, not whatever order the iterator provided maybe.

@benlangmuir
Copy link
Collaborator

You could try using clang -cc1 -E -x c-module-map which calls Module::print. To trigger this code path you can follow the pattern in darwin_specific_modulemap_hacks.m, ie create a module like

$ touch Tcl/x1.h
$ touch Tcl/x2.h
$ cat Tcl/module.modulemap
module Tcl {
  module Private {
    requires excluded
    umbrella ""
  }
}

$ clang -cc1 -E -x c-module-map Tcl/module.modulemap -fmodule-name=Tcl
# 1 "Tcl/module.modulemap"
module Tcl {
  module Private {
    textual header "" { size 0 mtime 1701196669 }
    textual header "" { size 0 mtime 1701196741 }
    textual header "" { size 75 mtime 1701196655 }
  }
}

However I think the printing would need to be fixed to print the right header name instead of "" first.

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.

4 participants