Skip to content

Commit 3282fb7

Browse files
authored
Merge pull request #65437 from hyp/eng/nomathinthiscompiler
[interop] avoid importing math functions from the C++ standard library
2 parents 82eb493 + 8e7766b commit 3282fb7

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
@@ -3126,6 +3126,36 @@ namespace {
31263126
if (decl->isDeleted())
31273127
return nullptr;
31283128

3129+
if (Impl.SwiftContext.LangOpts.EnableCXXInterop &&
3130+
!isa<clang::CXXMethodDecl>(decl)) {
3131+
// Do not import math functions from the C++ standard library, as
3132+
// they're also imported from the Darwin/Glibc module, and their
3133+
// presence in the C++ standard library will cause overloading
3134+
// ambiguities or other type checking errors in Swift.
3135+
auto isAlternativeCStdlibFunctionFromTextualHeader =
3136+
[](const clang::FunctionDecl *d) -> bool {
3137+
// stdlib.h might be a textual header in libc++'s module map.
3138+
// in this case, check for known ambiguous functions by their name
3139+
// instead of checking if they come from the `std` module.
3140+
if (!d->getDeclName().isIdentifier())
3141+
return false;
3142+
return d->getName() == "abs" || d->getName() == "div";
3143+
};
3144+
if (decl->getOwningModule() &&
3145+
(decl->getOwningModule()
3146+
->getTopLevelModule()
3147+
->getFullModuleName() == "std" ||
3148+
isAlternativeCStdlibFunctionFromTextualHeader(decl))) {
3149+
auto filename =
3150+
Impl.getClangPreprocessor().getSourceManager().getFilename(
3151+
decl->getLocation());
3152+
if (filename.endswith("cmath") || filename.endswith("math.h") ||
3153+
filename.endswith("stdlib.h") || filename.endswith("cstdlib")) {
3154+
return nullptr;
3155+
}
3156+
}
3157+
}
3158+
31293159
auto dc =
31303160
Impl.importDeclContextOf(decl, importedName.getEffectiveContext());
31313161
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)