Skip to content

Commit 2ea015a

Browse files
authored
Merge pull request #63653 from apple/egorzhdan/cxx-ambiguous-pointee
[cxx-interop] Do not synthesize ambiguous pointee properties
2 parents 55c1b65 + cc23f46 commit 2ea015a

File tree

7 files changed

+105
-3
lines changed

7 files changed

+105
-3
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2127,6 +2127,17 @@ namespace {
21272127
// The name of every member.
21282128
llvm::DenseSet<StringRef> allMemberNames;
21292129

2130+
bool hasConstOperatorStar = false;
2131+
for (auto member : decl->decls()) {
2132+
if (auto method = dyn_cast<clang::CXXMethodDecl>(member)) {
2133+
if (method->getOverloadedOperator() ==
2134+
clang::OverloadedOperatorKind::OO_Star &&
2135+
method->param_empty() && method->isConst())
2136+
hasConstOperatorStar = true;
2137+
}
2138+
}
2139+
bool hasSynthesizedPointeeProperty = false;
2140+
21302141
// FIXME: Import anonymous union fields and support field access when
21312142
// it is nested in a struct.
21322143
for (auto m : decl->decls()) {
@@ -2210,9 +2221,16 @@ namespace {
22102221
if (cxxOperatorKind == clang::OO_Star && cxxMethod->param_empty()) {
22112222
// This is a dereference operator. We synthesize a computed
22122223
// property called `pointee` for it.
2213-
VarDecl *pointeeProperty =
2214-
synthesizer.makeDereferencedPointeeProperty(MD);
2215-
result->addMember(pointeeProperty);
2224+
2225+
// If this record has multiple overloads of `operator*`, prefer
2226+
// the const overload if it exists.
2227+
if ((cxxMethod->isConst() || !hasConstOperatorStar) &&
2228+
!hasSynthesizedPointeeProperty) {
2229+
VarDecl *pointeeProperty =
2230+
synthesizer.makeDereferencedPointeeProperty(MD);
2231+
result->addMember(pointeeProperty);
2232+
hasSynthesizedPointeeProperty = true;
2233+
}
22162234

22172235
Impl.markUnavailable(MD, "use .pointee property");
22182236
MD->overwriteAccess(AccessLevel::Private);

test/Interop/Cxx/operators/Inputs/member-inline.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,4 +394,21 @@ struct ConstIteratorByVal {
394394
int operator*() const { return value; }
395395
};
396396

397+
struct AmbiguousOperatorStar {
398+
private:
399+
int value = 567;
400+
public:
401+
int &operator*() { return value; }
402+
const int &operator*() const { return value; }
403+
};
404+
405+
struct AmbiguousOperatorStar2 {
406+
private:
407+
int value = 678;
408+
public:
409+
int &operator*() & { return value; }
410+
const int &operator*() const & { return value; }
411+
const int &&operator*() const && { return static_cast<const int &&>(value); }
412+
};
413+
397414
#endif

test/Interop/Cxx/operators/member-inline-module-interface.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,3 +221,23 @@
221221
// CHECK: @available(*, unavailable, message: "use .pointee property")
222222
// CHECK: func __operatorStar() -> Int32
223223
// CHECK: }
224+
225+
// CHECK: struct AmbiguousOperatorStar {
226+
// CHECK-NEXT: var pointee: Int32 { get }
227+
// CHECK-NEXT: init()
228+
// CHECK-NEXT: @available(*, unavailable, message: "use .pointee property")
229+
// CHECK-NEXT: mutating func __operatorStar() -> UnsafeMutablePointer<Int32>
230+
// CHECK-NEXT: @available(*, unavailable, message: "use .pointee property")
231+
// CHECK-NEXT: func __operatorStar() -> UnsafePointer<Int32>
232+
// CHECK-NEXT: }
233+
234+
// CHECK: struct AmbiguousOperatorStar2 {
235+
// CHECK-NEXT: var pointee: Int32 { get }
236+
// CHECK-NEXT: init()
237+
// CHECK-NEXT: @available(*, unavailable, message: "use .pointee property")
238+
// CHECK-NEXT: mutating func __operatorStar() -> UnsafeMutablePointer<Int32>
239+
// CHECK-NEXT: @available(*, unavailable, message: "use .pointee property")
240+
// CHECK-NEXT: func __operatorStar() -> UnsafePointer<Int32>
241+
// CHECK-NEXT: @available(*, unavailable, message: "use .pointee property")
242+
// CHECK-NEXT: func __operatorStar() -> UnsafePointer<Int32>
243+
// CHECK-NEXT: }

test/Interop/Cxx/operators/member-inline.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,4 +363,16 @@ OperatorsTestSuite.test("ConstIteratorByVal.pointee") {
363363
expectEqual(456, res)
364364
}
365365

366+
OperatorsTestSuite.test("AmbiguousOperatorStar.pointee") {
367+
let stars = AmbiguousOperatorStar()
368+
let res = stars.pointee
369+
expectEqual(567, res)
370+
}
371+
372+
OperatorsTestSuite.test("AmbiguousOperatorStar2.pointee") {
373+
let stars = AmbiguousOperatorStar2()
374+
let res = stars.pointee
375+
expectEqual(678, res)
376+
}
377+
366378
runAllTests()

test/Interop/Cxx/stdlib/Inputs/module.modulemap

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ module StdMap {
1313
requires cplusplus
1414
}
1515

16+
module StdOptional {
17+
header "std-optional.h"
18+
requires cplusplus
19+
}
20+
1621
module StdSet {
1722
header "std-set.h"
1823
requires cplusplus
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#ifndef TEST_INTEROP_CXX_STDLIB_INPUTS_STD_OPTIONAL_H
2+
#define TEST_INTEROP_CXX_STDLIB_INPUTS_STD_OPTIONAL_H
3+
4+
#include <optional>
5+
6+
using CxxOptional = std::optional<int>;
7+
8+
inline CxxOptional getNonNilOptional() { return {123}; }
9+
10+
inline CxxOptional getNilOptional() { return {std::nullopt}; }
11+
12+
#endif // TEST_INTEROP_CXX_STDLIB_INPUTS_STD_OPTIONAL_H
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -enable-experimental-cxx-interop -Xcc -std=c++17)
2+
//
3+
// REQUIRES: executable_test
4+
// REQUIRES: OS=macosx
5+
6+
import StdlibUnittest
7+
import StdOptional
8+
import CxxStdlib
9+
10+
var StdOptionalTestSuite = TestSuite("StdOptional")
11+
12+
StdOptionalTestSuite.test("pointee") {
13+
let nonNilOpt = getNonNilOptional()
14+
let pointee = nonNilOpt.pointee
15+
expectEqual(123, pointee)
16+
}
17+
18+
runAllTests()

0 commit comments

Comments
 (0)