Skip to content

Commit 9010d89

Browse files
authored
Merge pull request #39999 from egorzhdan/cxx-mutating-attr
C++ Interop: support mutating attribute for C++ methods
2 parents e37eb35 + 0661293 commit 9010d89

File tree

5 files changed

+44
-1
lines changed

5 files changed

+44
-1
lines changed

lib/ClangImporter/ClangImporter.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4493,7 +4493,14 @@ ClangImporter::instantiateCXXClassTemplate(
44934493

44944494
bool ClangImporter::isCXXMethodMutating(const clang::CXXMethodDecl *method) {
44954495
return isa<clang::CXXConstructorDecl>(method) || !method->isConst() ||
4496-
method->getParent()->hasMutableFields();
4496+
method->getParent()->hasMutableFields() ||
4497+
(method->hasAttrs() &&
4498+
llvm::any_of(method->getAttrs(), [](clang::Attr *a) {
4499+
if (auto swiftAttr = dyn_cast<clang::SwiftAttrAttr>(a)) {
4500+
return swiftAttr->getAttribute() == "mutating";
4501+
}
4502+
return false;
4503+
}));
44974504
}
44984505

44994506
SwiftLookupTable *

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ module MutableMembers {
5353
requires cplusplus
5454
}
5555

56+
module MutabilityAnnotations {
57+
header "mutability-annotations.h"
58+
requires cplusplus
59+
}
60+
5661
module ProtocolConformance {
5762
header "protocol-conformance.h"
5863
requires cplusplus
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#ifndef TEST_INTEROP_CXX_CLASS_INPUTS_MUTABILITY_ANNOTATIONS_H
2+
#define TEST_INTEROP_CXX_CLASS_INPUTS_MUTABILITY_ANNOTATIONS_H
3+
4+
struct HasConstMethodAnnotatedAsMutating {
5+
int a;
6+
7+
int annotatedMutating() const __attribute__((__swift_attr__("mutating"))) {
8+
const_cast<HasConstMethodAnnotatedAsMutating *>(this)->a++;
9+
return a;
10+
}
11+
12+
int annotatedMutatingWithOtherAttrs() const __attribute__((__swift_attr__("public"))) __attribute__((__swift_attr__("mutating"))) {
13+
const_cast<HasConstMethodAnnotatedAsMutating *>(this)->a++;
14+
return a;
15+
}
16+
};
17+
18+
#endif // TEST_INTEROP_CXX_CLASS_INPUTS_MUTABILITY_ANNOTATIONS_H
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// RUN: %target-swift-ide-test -print-module -module-to-print=MutabilityAnnotations -I %S/Inputs -source-filename=x -enable-cxx-interop | %FileCheck %s
2+
3+
// CHECK: struct HasConstMethodAnnotatedAsMutating {
4+
// CHECK: mutating func annotatedMutating() -> Int32
5+
// CHECK: mutating func annotatedMutatingWithOtherAttrs() -> Int32
6+
// CHECK: var a: Int32
7+
// CHECK: }
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// RUN: %target-typecheck-verify-swift -I %S/Inputs -enable-cxx-interop
2+
3+
import MutabilityAnnotations
4+
5+
let obj = HasConstMethodAnnotatedAsMutating(a: 42) // expected-note {{change 'let' to 'var' to make it mutable}}
6+
let i = obj.annotatedMutating() // expected-error {{cannot use mutating member on immutable value: 'obj' is a 'let' constant}}

0 commit comments

Comments
 (0)