Skip to content

Commit 876ab2a

Browse files
authored
Merge pull request #65498 from hyp/eng/5.9-math-fns-workaround
[5.9][interop] avoid importing math functions from the C++ standard library
2 parents f0aa860 + 40edad9 commit 876ab2a

File tree

3 files changed

+73
-0
lines changed

3 files changed

+73
-0
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3123,6 +3123,36 @@ namespace {
31233123
if (decl->isDeleted())
31243124
return nullptr;
31253125

3126+
if (Impl.SwiftContext.LangOpts.EnableCXXInterop &&
3127+
!isa<clang::CXXMethodDecl>(decl)) {
3128+
// Do not import math functions from the C++ standard library, as
3129+
// they're also imported from the Darwin/Glibc module, and their
3130+
// presence in the C++ standard library will cause overloading
3131+
// ambiguities or other type checking errors in Swift.
3132+
auto isAlternativeCStdlibFunctionFromTextualHeader =
3133+
[](const clang::FunctionDecl *d) -> bool {
3134+
// stdlib.h might be a textual header in libc++'s module map.
3135+
// in this case, check for known ambiguous functions by their name
3136+
// instead of checking if they come from the `std` module.
3137+
if (!d->getDeclName().isIdentifier())
3138+
return false;
3139+
return d->getName() == "abs" || d->getName() == "div";
3140+
};
3141+
if (decl->getOwningModule() &&
3142+
(decl->getOwningModule()
3143+
->getTopLevelModule()
3144+
->getFullModuleName() == "std" ||
3145+
isAlternativeCStdlibFunctionFromTextualHeader(decl))) {
3146+
auto filename =
3147+
Impl.getClangPreprocessor().getSourceManager().getFilename(
3148+
decl->getLocation());
3149+
if (filename.endswith("cmath") || filename.endswith("math.h") ||
3150+
filename.endswith("stdlib.h") || filename.endswith("cstdlib")) {
3151+
return nullptr;
3152+
}
3153+
}
3154+
}
3155+
31263156
auto dc =
31273157
Impl.importDeclContextOf(decl, importedName.getEffectiveContext());
31283158
if (!dc)
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: %target-swift-frontend %s -typecheck -verify -enable-experimental-cxx-interop -Xcc -std=c++17
2+
3+
// REQUIRES: OS=macosx || OS=linux-gnu
4+
5+
import CxxStdlib
6+
7+
func test() {
8+
let x: Float = 1.0
9+
let y: Double = 2.0
10+
11+
// Note: we dispatch `pow(Float,Double)`
12+
// to ensure we don't pick up the
13+
// C++ stdlib `pow` function template.
14+
// The `pow` function is still reexported
15+
// from Darwin via CxxStdlib, so there are
16+
// matching overloads that can be found still.
17+
// Note: the error is different on Glibc instead
18+
// of Darwin, so do not check the exact error.
19+
let _ = CxxStdlib.pow(x, y) // expected-error {{}}
20+
21+
let _ = CxxStdlib.abs(x) // expected-error {{module 'CxxStdlib' has no member named 'abs'}}
22+
let _ = CxxStdlib.div(x) // expected-error {{module 'CxxStdlib' has no member named 'div'}}
23+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// RUN: %target-swift-frontend %s -typecheck -enable-experimental-cxx-interop -Xcc -std=c++17
2+
3+
#if canImport(Foundation)
4+
// Foundation depends on C++ standard library
5+
// on some platforms already, and as such
6+
// may bring math functions from it.
7+
import Foundation
8+
9+
func test() -> Float {
10+
let x: Float = 1.0
11+
// Note: we mix 'Float' and 'Double' (literal)
12+
// intentionally, as this might trigger Swift
13+
// to instantiate a function template from
14+
// the C++ standard library.
15+
let z = pow(x, 2.0)
16+
let _ = abs(x)
17+
let m = z + 1.0
18+
return m
19+
}
20+
#endif

0 commit comments

Comments
 (0)