Skip to content

Conversation

@hjyamauchi
Copy link
Contributor

@hjyamauchi hjyamauchi commented Nov 20, 2025

This tweaks the existing logic that disables the import of the C++
math functions to avoid ambiguity with the C math functions by
handling the case where the module directory can be null in explicit
module builds.

For #85606

@hjyamauchi
Copy link
Contributor Author

@swift-ci please test

@hjyamauchi hjyamauchi marked this pull request as ready for review November 20, 2025 19:27
@hjyamauchi hjyamauchi requested review from a team and artemcm as code owners November 20, 2025 19:27
@hjyamauchi
Copy link
Contributor Author

@swift-ci please test

@@ -295,7 +295,11 @@ public func lgamma(_ x: ${T}) -> (${T}, Int) {
@_transparent
public func remquo(_ x: ${T}, _ y: ${T}) -> (${T}, Int) {
var quo = Int32(0)
#if !os(Windows)
Copy link
Member

Choose a reason for hiding this comment

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

This problem should occur for any platform that doesn't differentiate long double from double right?

I think that rather than differentiating this on os(Windows), we want to use something to differentiate this based on sizeof(long double) == sizeof(double).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not exactly. This also requires another condition: the way the Windows headers declare it. This doesn't occur and the following reproducer test doesn't err on macos because the macos C++ header imports the C remquo into the std namespace for C++ rather than declaring another remquo for long double that would cause an overload with C remquo for long in Swift. I added text on it in the bug description here. So I think this is specific to Windows.

Copy link
Member

Choose a reason for hiding this comment

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

Looking at that description, I think that this is the wrong solution. The problem is that corecrt_math.h does define a module, and the header being transitively imported in the headers by CxxStdlib results in the incorrect definition.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My previous comment was not right. I think the headers are similar in macos. I updated the PR to explicitly call the C remquo. I think the conditions to detect long double == double case is captured by the % if T == 'Float80': 6 lines above. I think this should work.

@hjyamauchi
Copy link
Contributor Author

@swift-ci please test

@hjyamauchi
Copy link
Contributor Author

@swift-ci please test

@hjyamauchi hjyamauchi changed the title Disambiguate the reference to remquo on Windows Avoid C/C++ math function ambiguity for explicit module builds on Windows Dec 2, 2025
@hjyamauchi
Copy link
Contributor Author

@swift-ci please test

Comment on lines 3788 to 3789
// owningModule->Directory can be null in an explicit module build
if ((!owningModule->Directory || file->getDir() == owningModule->Directory) &&
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// owningModule->Directory can be null in an explicit module build
if ((!owningModule->Directory || file->getDir() == owningModule->Directory) &&
// If we are a non-umbrella module without a canonical location the directory member may
// not be populated.
if (!owningModule->Directory)
return nullptr;
if (file->getDir() == owningModule->Directory &&

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Would the suggested change cause non-math functions to not be imported?

@compnerd
Copy link
Member

compnerd commented Dec 3, 2025

I think that the check should be separated as it is unrelated to the check being modified. The Directory member may not be populated in some cases (but unrelated to explicit modules). This field represents the directory that the module is notionally built in. Since we inject the module maps via the VFS, the path may be unresolved, leaving the member not populated.

@ian-twilightcoder and @cachemeifyoucan might be able to shed more light on this.

@ian-twilightcoder
Copy link
Contributor

I think that the check should be separated as it is unrelated to the check being modified. The Directory member may not be populated in some cases (but unrelated to explicit modules). This field represents the directory that the module is notionally built in. Since we inject the module maps via the VFS, the path may be unresolved, leaving the member not populated.

@ian-twilightcoder and @cachemeifyoucan might be able to shed more light on this.

I'm not all that familiar with the Directory member or how that gets put together. I'm not totally sure what the workaround is trying to work around either, neither cmath nor math.h are textual so I'm not sure what the issues are with those.

@compnerd
Copy link
Member

compnerd commented Dec 4, 2025

I'm not all that familiar with the Directory member or how that gets put together. I'm not totally sure what the workaround is trying to work around either, neither cmath nor math.h are textual so I'm not sure what the issues are with those.

It seems that the field is optional and not always populated. Does it make sense to ignore the check for the directory? It seems that would open us up to cases where the header may be attributed to the wrong module.

Alternatively, should we bail early if the Directory member is not populated?

Copy link
Contributor

@egorzhdan egorzhdan left a comment

Choose a reason for hiding this comment

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

LGTM, although I'm not too familiar with the testing approach here!

@egorzhdan egorzhdan added the c++ interop Feature: Interoperability with C++ label Dec 4, 2025
@ian-twilightcoder
Copy link
Contributor

ian-twilightcoder commented Dec 4, 2025

I'm not all that familiar with the Directory member or how that gets put together. I'm not totally sure what the workaround is trying to work around either, neither cmath nor math.h are textual so I'm not sure what the issues are with those.

It seems that the field is optional and not always populated. Does it make sense to ignore the check for the directory? It seems that would open us up to cases where the header may be attributed to the wrong module.

Alternatively, should we bail early if the Directory member is not populated?

I don't really know, @Bigcheese @vsapsai @jansvoboda11 @benlangmuir do any of you know?

@benlangmuir
Copy link
Contributor

@ian-twilightcoder am I missing something or did you not add this Directory check in #71075? I don't see why we are checking it at all here. I don't really understand why we're trying to hide decls from these headers in this manner, but given that goal I think just checking the filename without looking at Directory should be enough.

The Directory will be nullptr when building cached modules.

@hjyamauchi
Copy link
Contributor Author

In the non-explicit module build case, the Module is instantiated and its Directory is set in clang::ModuleMapLoader::handleModuleDecl. In the explicit module case, the Module is instantiated from clang::ASTReader::ReadSubmoduleBlock -> clang::ModuleMap::createModule (and Directory isn't set) when the module is loaded from a pcm file that was previously built. Perhaps it's not necessarily known/conveyed where it was built.

Encouraged by @benlangmuir 's comment, I removed the Directory part of the check. PTAL.

@swift-ci please test

@hjyamauchi
Copy link
Contributor Author

@swift-ci please test macos platform

@hjyamauchi
Copy link
Contributor Author

@swift-ci please test linux platform

5 similar comments
@hjyamauchi
Copy link
Contributor Author

@swift-ci please test linux platform

@hjyamauchi
Copy link
Contributor Author

@swift-ci please test linux platform

@hjyamauchi
Copy link
Contributor Author

@swift-ci please test linux platform

@hjyamauchi
Copy link
Contributor Author

@swift-ci please test linux platform

@hjyamauchi
Copy link
Contributor Author

@swift-ci please test linux platform

@hjyamauchi
Copy link
Contributor Author

@swift-ci please test

@hjyamauchi
Copy link
Contributor Author

If I remove the Directory check, I get following errors in the Linux CI, meaning it unintentionally ends up over-hiding decls like realpath and free from stdlib.h.

Maybe this was masked by this Directory check? I am curious why #71075 added this.

I think the original intention as in #65437 was to hide the integer versions abs and div from stdlib.h in addition to the decls in math.h and the filename checks were nested inside the function name checks (isAlternativeCStdlibFunctionFromTextualHeader) but later they were somehow separated by #66896.

I think removing the Directory check and but restricting the stdlib.h case to the variants of abs and div would be the way to go.

What do you think? @ian-twilightcoder @egorzhdan @zoecarver @benlangmuir @compnerd

[2025-12-10T05:35:44.338Z] /home/build-user/swift/stdlib/public/RuntimeModule/Elf.swift:236:22: error: cannot find 'realpath' in scope
[2025-12-10T05:35:44.338Z]  234 | 
[2025-12-10T05:35:44.338Z]  235 | private func realPath(_ path: String) -> String? {
[2025-12-10T05:35:44.338Z]  236 |   guard let result = realpath(path, nil) else {
[2025-12-10T05:35:44.338Z]      |                      `- error: cannot find 'realpath' in scope
[2025-12-10T05:35:44.338Z]  237 |     return nil
[2025-12-10T05:35:44.338Z]  238 |   }
[2025-12-10T05:35:44.338Z] /home/build-user/swift/stdlib/public/RuntimeModule/Elf.swift:242:3: error: cannot find 'free' in scope
[2025-12-10T05:35:44.338Z]  240 |   let s = String(cString: result)
[2025-12-10T05:35:44.338Z]  241 | 
[2025-12-10T05:35:44.338Z]  242 |   free(result)
[2025-12-10T05:35:44.338Z]      |   `- error: cannot find 'free' in scope
[2025-12-10T05:35:44.338Z]  243 | 
[2025-12-10T05:35:44.338Z]  244 |   return s
[2025-12-10T05:35:44.338Z] 
[2025-12-10T05:35:44.338Z] /home/build-user/swift/stdlib/public/RuntimeModule/SymbolicatedBacktrace.swift:208:17: error: cannot find 'free' in scope
[2025-12-10T05:35:44.338Z] 206 |       if let demangled = _swift_backtrace_demangle(rawName, rawName.utf8.count,
[2025-12-10T05:35:44.338Z] 207 |                                                    nil, &length) {
[2025-12-10T05:35:44.338Z] 208 |         defer { free(demangled) }
[2025-12-10T05:35:44.338Z]     |                 `- error: cannot find 'free' in scope
[2025-12-10T05:35:44.338Z] 209 | 
[2025-12-10T05:35:44.338Z] 210 |         // length is the size of the buffer that was allocated, *not* the

…dows

This tweaks the existing logic that disables the import of the C++
math functions to avoid ambiguity with the C math functions by
handling the case where the module directory can be null in explicit
module builds.

For swiftlang#85606
@hjyamauchi
Copy link
Contributor Author

@swift-ci please test

@hjyamauchi
Copy link
Contributor Author

I changed it so it removes the Directory check and but restricted the stdlib case to abs and div and it passed the CI in a test PR.

Please take another look.

Copy link
Member

@compnerd compnerd left a comment

Choose a reason for hiding this comment

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

This makes a lot more sense to me. Thank you!

@benlangmuir
Copy link
Contributor

This looks fine to me, but I don't understand the specific history of these changes with respect to abs/div. @egorzhdan you removed the abs/div name checks in 9b7dbf2; does this make sense to you?

@hjyamauchi
Copy link
Contributor Author

@swift-ci please test macos platform

@hjyamauchi
Copy link
Contributor Author

@swift-ci please test windows platform

1 similar comment
@hjyamauchi
Copy link
Contributor Author

@swift-ci please test windows platform

@hjyamauchi hjyamauchi requested a review from egorzhdan December 15, 2025 19:10
@hjyamauchi
Copy link
Contributor Author

Since no response, I think I'll merge this. Please let me know if you or anyone disagree. I'd rework it if needed

@hjyamauchi hjyamauchi merged commit fc25044 into swiftlang:main Dec 16, 2025
5 checks passed
@egorzhdan
Copy link
Contributor

Looks like this is causing test failures on FreeBSD: #86103

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c++ interop Feature: Interoperability with C++

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants