Skip to content

Commit c98c862

Browse files
authored
Start implementing C++ operator interop (swiftlang#32015)
This imports the four basic arithmetic operators `+`, `-`, `*`, `/` declared as inline non-member functions. More to come.
1 parent 2140981 commit c98c862

File tree

6 files changed

+119
-1
lines changed

6 files changed

+119
-1
lines changed

lib/ClangImporter/ImportName.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "clang/AST/ASTContext.h"
3535
#include "clang/Basic/IdentifierTable.h"
3636
#include "clang/Basic/Module.h"
37+
#include "clang/Basic/OperatorKinds.h"
3738
#include "clang/Lex/Preprocessor.h"
3839
#include "clang/Parse/Parser.h"
3940
#include "clang/Sema/Lookup.h"
@@ -1410,12 +1411,35 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
14101411
case clang::DeclarationName::CXXConversionFunctionName:
14111412
case clang::DeclarationName::CXXDestructorName:
14121413
case clang::DeclarationName::CXXLiteralOperatorName:
1413-
case clang::DeclarationName::CXXOperatorName:
14141414
case clang::DeclarationName::CXXUsingDirective:
14151415
case clang::DeclarationName::CXXDeductionGuideName:
14161416
// TODO: Handling these is part of C++ interoperability.
14171417
return ImportedName();
14181418

1419+
case clang::DeclarationName::CXXOperatorName: {
1420+
auto op = D->getDeclName().getCXXOverloadedOperator();
1421+
switch (op) {
1422+
case clang::OverloadedOperatorKind::OO_Plus:
1423+
case clang::OverloadedOperatorKind::OO_Minus:
1424+
case clang::OverloadedOperatorKind::OO_Star:
1425+
case clang::OverloadedOperatorKind::OO_Slash:
1426+
if (auto FD = dyn_cast<clang::FunctionDecl>(D)) {
1427+
baseName = clang::getOperatorSpelling(op);
1428+
isFunction = true;
1429+
argumentNames.resize(FD->param_size());
1430+
} else {
1431+
// This can happen for example for templated operators functions.
1432+
// We don't support those, yet.
1433+
return ImportedName();
1434+
}
1435+
break;
1436+
default:
1437+
// We don't import these yet.
1438+
return ImportedName();
1439+
}
1440+
break;
1441+
}
1442+
14191443
case clang::DeclarationName::Identifier:
14201444
// Map the identifier.
14211445
baseName = D->getDeclName().getAsIdentifierInfo()->getName();
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module NonMemberInline {
2+
header "non-member-inline.h"
3+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#ifndef TEST_INTEROP_CXX_OPERATORS_INPUTS_NON_MEMBER_INLINE_H
2+
#define TEST_INTEROP_CXX_OPERATORS_INPUTS_NON_MEMBER_INLINE_H
3+
4+
struct IntBox {
5+
int value;
6+
};
7+
8+
inline IntBox operator+(IntBox lhs, IntBox rhs) {
9+
return IntBox{.value = lhs.value + rhs.value};
10+
}
11+
12+
inline IntBox operator-(IntBox lhs, IntBox rhs) {
13+
return IntBox{.value = lhs.value - rhs.value};
14+
}
15+
16+
inline IntBox operator*(IntBox lhs, IntBox rhs) {
17+
return IntBox{.value = lhs.value * rhs.value};
18+
}
19+
20+
inline IntBox operator/(IntBox lhs, IntBox rhs) {
21+
return IntBox{.value = lhs.value / rhs.value};
22+
}
23+
24+
// Make sure that we don't crash on templated operators
25+
template<typename T> struct S {};
26+
template<typename T> S<T> operator+(S<T> lhs, S<T> rhs);
27+
28+
#endif
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// RUN: %target-swift-ide-test -print-module -module-to-print=NonMemberInline -I %S/Inputs -source-filename=x -enable-cxx-interop | %FileCheck %s
2+
3+
// CHECK: func + (lhs: IntBox, rhs: IntBox) -> IntBox
4+
// CHECK-NEXT: func - (lhs: IntBox, rhs: IntBox) -> IntBox
5+
// CHECK-NEXT: func * (lhs: IntBox, rhs: IntBox) -> IntBox
6+
// CHECK-NEXT: func / (lhs: IntBox, rhs: IntBox) -> IntBox
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: %target-typecheck-verify-swift -I %S/Inputs -enable-cxx-interop
2+
3+
import NonMemberInline
4+
5+
var lhs = IntBox(value: 42)
6+
var rhs = IntBox(value: 23)
7+
8+
let resultPlus = lhs + rhs
9+
let resultMinus = lhs - rhs
10+
let resultStar = lhs * rhs
11+
let resultSlash = lhs / rhs
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -enable-cxx-interop)
2+
//
3+
// REQUIRES: executable_test
4+
5+
import NonMemberInline
6+
import StdlibUnittest
7+
8+
var OperatorsTestSuite = TestSuite("Operators")
9+
10+
OperatorsTestSuite.test("plus") {
11+
let lhs = IntBox(value: 42)
12+
let rhs = IntBox(value: 23)
13+
14+
let result = lhs + rhs
15+
16+
expectEqual(65, result.value)
17+
}
18+
19+
OperatorsTestSuite.test("minus") {
20+
let lhs = IntBox(value: 42)
21+
let rhs = IntBox(value: 23)
22+
23+
let result = lhs - rhs
24+
25+
expectEqual(19, result.value)
26+
}
27+
28+
OperatorsTestSuite.test("star") {
29+
let lhs = IntBox(value: 42)
30+
let rhs = IntBox(value: 23)
31+
32+
let result = lhs * rhs
33+
34+
expectEqual(966, result.value)
35+
}
36+
37+
OperatorsTestSuite.test("slash") {
38+
let lhs = IntBox(value: 42)
39+
let rhs = IntBox(value: 23)
40+
41+
let result = lhs / rhs
42+
43+
expectEqual(1, result.value)
44+
}
45+
46+
runAllTests()

0 commit comments

Comments
 (0)