mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[interop] avoid importing math functions from the C++ standard library
They cause ambiguities with math functions from platform's libc
This commit is contained in:
@@ -3121,6 +3121,36 @@ namespace {
|
||||
if (decl->isDeleted())
|
||||
return nullptr;
|
||||
|
||||
if (Impl.SwiftContext.LangOpts.EnableCXXInterop &&
|
||||
!isa<clang::CXXMethodDecl>(decl)) {
|
||||
// Do not import math functions from the C++ standard library, as
|
||||
// they're also imported from the Darwin/Glibc module, and their
|
||||
// presence in the C++ standard library will cause overloading
|
||||
// ambiguities or other type checking errors in Swift.
|
||||
auto isAlternativeCStdlibFunctionFromTextualHeader =
|
||||
[](const clang::FunctionDecl *d) -> bool {
|
||||
// stdlib.h might be a textual header in libc++'s module map.
|
||||
// in this case, check for known ambiguous functions by their name
|
||||
// instead of checking if they come from the `std` module.
|
||||
if (!d->getDeclName().isIdentifier())
|
||||
return false;
|
||||
return d->getName() == "abs" || d->getName() == "div";
|
||||
};
|
||||
if (decl->getOwningModule() &&
|
||||
(decl->getOwningModule()
|
||||
->getTopLevelModule()
|
||||
->getFullModuleName() == "std" ||
|
||||
isAlternativeCStdlibFunctionFromTextualHeader(decl))) {
|
||||
auto filename =
|
||||
Impl.getClangPreprocessor().getSourceManager().getFilename(
|
||||
decl->getLocation());
|
||||
if (filename.endswith("cmath") || filename.endswith("math.h") ||
|
||||
filename.endswith("stdlib.h") || filename.endswith("cstdlib")) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto dc =
|
||||
Impl.importDeclContextOf(decl, importedName.getEffectiveContext());
|
||||
if (!dc)
|
||||
|
||||
23
test/Interop/Cxx/stdlib/avoid-import-cxx-math.swift
Normal file
23
test/Interop/Cxx/stdlib/avoid-import-cxx-math.swift
Normal file
@@ -0,0 +1,23 @@
|
||||
// RUN: %target-swift-frontend %s -typecheck -verify -enable-experimental-cxx-interop -Xcc -std=c++17
|
||||
|
||||
// REQUIRES: OS=macosx || OS=linux-gnu
|
||||
|
||||
import CxxStdlib
|
||||
|
||||
func test() {
|
||||
let x: Float = 1.0
|
||||
let y: Double = 2.0
|
||||
|
||||
// Note: we dispatch `pow(Float,Double)`
|
||||
// to ensure we don't pick up the
|
||||
// C++ stdlib `pow` function template.
|
||||
// The `pow` function is still reexported
|
||||
// from Darwin via CxxStdlib, so there are
|
||||
// matching overloads that can be found still.
|
||||
// Note: the error is different on Glibc instead
|
||||
// of Darwin, so do not check the exact error.
|
||||
let _ = CxxStdlib.pow(x, y) // expected-error {{}}
|
||||
|
||||
let _ = CxxStdlib.abs(x) // expected-error {{module 'CxxStdlib' has no member named 'abs'}}
|
||||
let _ = CxxStdlib.div(x) // expected-error {{module 'CxxStdlib' has no member named 'div'}}
|
||||
}
|
||||
20
test/Interop/Cxx/stdlib/import-cxx-math-ambiguities.swift
Normal file
20
test/Interop/Cxx/stdlib/import-cxx-math-ambiguities.swift
Normal file
@@ -0,0 +1,20 @@
|
||||
// RUN: %target-swift-frontend %s -typecheck -enable-experimental-cxx-interop -Xcc -std=c++17
|
||||
|
||||
#if canImport(Foundation)
|
||||
// Foundation depends on C++ standard library
|
||||
// on some platforms already, and as such
|
||||
// may bring math functions from it.
|
||||
import Foundation
|
||||
|
||||
func test() -> Float {
|
||||
let x: Float = 1.0
|
||||
// Note: we mix 'Float' and 'Double' (literal)
|
||||
// intentionally, as this might trigger Swift
|
||||
// to instantiate a function template from
|
||||
// the C++ standard library.
|
||||
let z = pow(x, 2.0)
|
||||
let _ = abs(x)
|
||||
let m = z + 1.0
|
||||
return m
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user