Skip to content

Commit 6a6380b

Browse files
authored
Merge pull request #80763 from swiftlang/egorzhdan/rvalue-arg-operator
[cxx-interop] Do not import arithmetic operators with rvalue reference parameters
2 parents 352907f + eb7adc7 commit 6a6380b

File tree

5 files changed

+50
-0
lines changed

5 files changed

+50
-0
lines changed

Diff for: lib/ClangImporter/ImportName.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -1967,6 +1967,14 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
19671967
case clang::OverloadedOperatorKind::OO_GreaterEqual:
19681968
case clang::OverloadedOperatorKind::OO_AmpAmp:
19691969
case clang::OverloadedOperatorKind::OO_PipePipe: {
1970+
// If the operator has a parameter that is an rvalue reference, it would
1971+
// cause name lookup collision with an overload that has lvalue reference
1972+
// parameter, if it exists.
1973+
for (auto paramDecl : functionDecl->parameters()) {
1974+
if (paramDecl->getType()->isRValueReferenceType())
1975+
return ImportedName();
1976+
}
1977+
19701978
auto operatorName =
19711979
isa<clang::CXXMethodDecl>(functionDecl)
19721980
? getOperatorName(swiftCtx, op)

Diff for: test/Interop/Cxx/operators/Inputs/non-member-inline.h

+23
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,29 @@ inline bool operator==(const ClassWithOperatorEqualsParamUnnamed &,
9494
return false;
9595
}
9696

97+
struct RValueArithmetic {
98+
int value;
99+
};
100+
101+
RValueArithmetic operator+(const RValueArithmetic &lhs,
102+
RValueArithmetic &&rhs) {
103+
return {lhs.value + rhs.value};
104+
}
105+
106+
struct LValueAndRValueArithmetic {
107+
int value;
108+
};
109+
110+
LValueAndRValueArithmetic operator+(const LValueAndRValueArithmetic &lhs,
111+
const LValueAndRValueArithmetic &rhs) {
112+
return {lhs.value + rhs.value};
113+
}
114+
115+
LValueAndRValueArithmetic operator+(const LValueAndRValueArithmetic &lhs,
116+
LValueAndRValueArithmetic &&rhs) {
117+
return {lhs.value + rhs.value};
118+
}
119+
97120
// Make sure that we don't crash on templated operators
98121
template<typename T> struct S {};
99122
template<typename T> S<T> operator+(S<T> lhs, S<T> rhs);

Diff for: test/Interop/Cxx/operators/non-member-inline-module-interface.swift

+4
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,7 @@
1919

2020
// CHECK: func && (lhs: LoadableBoolWrapper, rhs: LoadableBoolWrapper) -> LoadableBoolWrapper
2121
// CHECK-NEXT: func || (lhs: LoadableBoolWrapper, rhs: LoadableBoolWrapper) -> LoadableBoolWrapper
22+
23+
// CHECK-NOT: func + (lhs: RValueArithmetic
24+
25+
// CHECK: func + (lhs: LValueAndRValueArithmetic, rhs: LValueAndRValueArithmetic) -> LValueAndRValueArithmetic

Diff for: test/Interop/Cxx/operators/non-member-inline-typechecker.swift

+8
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,11 @@ var rhsBool = LoadableBoolWrapper(value: false)
3737

3838
let resultAmpAmp = lhsBool && rhsBool
3939
let resultPipePipe = lhsBool && rhsBool
40+
41+
let lhsRValue = RValueArithmetic(value: 123)
42+
let rhsRValue = RValueArithmetic(value: 146)
43+
let resultRValue = lhsRValue + rhsRValue // expected-error {{binary operator '+' cannot be applied to two 'RValueArithmetic' operands}}
44+
45+
let lhsLRValue = LValueAndRValueArithmetic(value: 123)
46+
let rhsLRValue = LValueAndRValueArithmetic(value: 146)
47+
let resultLRValue = lhsLRValue + rhsLRValue

Diff for: test/Interop/Cxx/operators/non-member-inline.swift

+7
Original file line numberDiff line numberDiff line change
@@ -193,4 +193,11 @@ OperatorsTestSuite.test("UnnamedParameterInOperator.equal") {
193193
expectFalse(lhs == rhs)
194194
}
195195

196+
OperatorsTestSuite.test("LValueAndRValueArithmetic.+") {
197+
let lhs = LValueAndRValueArithmetic(value: 123)
198+
let rhs = LValueAndRValueArithmetic(value: 146)
199+
200+
expectEqual(269, (lhs + rhs).value)
201+
}
202+
196203
runAllTests()

0 commit comments

Comments
 (0)