Skip to content

Commit c942dac

Browse files
committed
[cxx-interop] Do not synthesize ambiguous pointee properties
If a C++ struct defines multiple overloads of `operator*`, avoid synthesizing multiple `var pointee: Pointee` properties, since that would introduce name resolution ambiguity. Instead, pick one of the const overloads and synthesize a single `pointee` property. This is required for `std::optional` support.
1 parent e80f571 commit c942dac

File tree

4 files changed

+70
-3
lines changed

4 files changed

+70
-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()

0 commit comments

Comments
 (0)