Skip to content

Commit 2b9632f

Browse files
committed
Merge remote-tracking branch 'origin/main' into rebranch
2 parents 88da350 + e54752a commit 2b9632f

File tree

5 files changed

+76
-53
lines changed

5 files changed

+76
-53
lines changed

lib/ClangImporter/ClangImporter.cpp

Lines changed: 46 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -8255,17 +8255,15 @@ static bool hasCopyTypeOperations(const clang::CXXRecordDecl *decl) {
82558255
}
82568256

82578257
static bool hasMoveTypeOperations(const clang::CXXRecordDecl *decl) {
8258-
if (llvm::any_of(decl->ctors(), [](clang::CXXConstructorDecl *ctor) {
8259-
return ctor->isMoveConstructor() &&
8260-
(ctor->isDeleted() || ctor->isIneligibleOrNotSelected() ||
8261-
ctor->getAccess() != clang::AS_public);
8262-
}))
8263-
return false;
8258+
if (decl->hasSimpleMoveConstructor())
8259+
return true;
82648260

82658261
return llvm::any_of(decl->ctors(), [](clang::CXXConstructorDecl *ctor) {
8266-
return ctor->isMoveConstructor() &&
8262+
return ctor->isMoveConstructor() && !ctor->isDeleted() &&
8263+
!ctor->isIneligibleOrNotSelected() &&
82678264
// FIXME: Support default arguments (rdar://142414553)
8268-
ctor->getNumParams() == 1;
8265+
ctor->getNumParams() == 1 &&
8266+
ctor->getAccess() == clang::AS_public;
82698267
});
82708268
}
82718269

@@ -8397,46 +8395,48 @@ CxxValueSemantics::evaluate(Evaluator &evaluator,
83978395
return CxxValueSemanticsKind::Copyable;
83988396
}
83998397

8400-
auto injectedStlAnnotation =
8401-
recordDecl->isInStdNamespace()
8402-
? STLConditionalParams.find(recordDecl->getName())
8403-
: STLConditionalParams.end();
8404-
auto STLParams = injectedStlAnnotation != STLConditionalParams.end()
8405-
? injectedStlAnnotation->second
8406-
: std::vector<int>();
8407-
auto conditionalParams = getConditionalCopyableAttrParams(recordDecl);
8408-
8409-
if (!STLParams.empty() || !conditionalParams.empty()) {
8410-
HeaderLoc loc{recordDecl->getLocation()};
8411-
std::function checkArgValueSemantics =
8412-
[&](clang::TemplateArgument &arg,
8413-
StringRef argToCheck) -> std::optional<CxxValueSemanticsKind> {
8414-
if (arg.getKind() != clang::TemplateArgument::Type && importerImpl) {
8415-
importerImpl->diagnose(loc, diag::type_template_parameter_expected,
8416-
argToCheck);
8417-
return CxxValueSemanticsKind::Unknown;
8418-
}
8398+
if (!hasNonCopyableAttr(recordDecl)) {
8399+
auto injectedStlAnnotation =
8400+
recordDecl->isInStdNamespace()
8401+
? STLConditionalParams.find(recordDecl->getName())
8402+
: STLConditionalParams.end();
8403+
auto STLParams = injectedStlAnnotation != STLConditionalParams.end()
8404+
? injectedStlAnnotation->second
8405+
: std::vector<int>();
8406+
auto conditionalParams = getConditionalCopyableAttrParams(recordDecl);
84198407

8420-
auto argValueSemantics = evaluateOrDefault(
8421-
evaluator,
8422-
CxxValueSemantics(
8423-
{arg.getAsType()->getUnqualifiedDesugaredType(), importerImpl}),
8424-
{});
8425-
if (argValueSemantics != CxxValueSemanticsKind::Copyable)
8426-
return argValueSemantics;
8427-
return std::nullopt;
8428-
};
8408+
if (!STLParams.empty() || !conditionalParams.empty()) {
8409+
HeaderLoc loc{recordDecl->getLocation()};
8410+
std::function checkArgValueSemantics =
8411+
[&](clang::TemplateArgument &arg,
8412+
StringRef argToCheck) -> std::optional<CxxValueSemanticsKind> {
8413+
if (arg.getKind() != clang::TemplateArgument::Type && importerImpl) {
8414+
importerImpl->diagnose(loc, diag::type_template_parameter_expected,
8415+
argToCheck);
8416+
return CxxValueSemanticsKind::Unknown;
8417+
}
84298418

8430-
auto result = checkConditionalParams<CxxValueSemanticsKind>(
8431-
recordDecl, STLParams, conditionalParams, checkArgValueSemantics);
8432-
if (result.has_value())
8433-
return result.value();
8419+
auto argValueSemantics = evaluateOrDefault(
8420+
evaluator,
8421+
CxxValueSemantics(
8422+
{arg.getAsType()->getUnqualifiedDesugaredType(), importerImpl}),
8423+
{});
8424+
if (argValueSemantics != CxxValueSemanticsKind::Copyable)
8425+
return argValueSemantics;
8426+
return std::nullopt;
8427+
};
84348428

8435-
if (importerImpl)
8436-
for (auto name : conditionalParams)
8437-
importerImpl->diagnose(loc, diag::unknown_template_parameter, name);
8429+
auto result = checkConditionalParams<CxxValueSemanticsKind>(
8430+
recordDecl, STLParams, conditionalParams, checkArgValueSemantics);
8431+
if (result.has_value())
8432+
return result.value();
84388433

8439-
return CxxValueSemanticsKind::Copyable;
8434+
if (importerImpl)
8435+
for (auto name : conditionalParams)
8436+
importerImpl->diagnose(loc, diag::unknown_template_parameter, name);
8437+
8438+
return CxxValueSemanticsKind::Copyable;
8439+
}
84408440
}
84418441

84428442
const auto cxxRecordDecl = dyn_cast<clang::CXXRecordDecl>(recordDecl);
@@ -8446,7 +8446,8 @@ CxxValueSemantics::evaluate(Evaluator &evaluator,
84468446
return CxxValueSemanticsKind::Copyable;
84478447
}
84488448

8449-
bool isCopyable = hasCopyTypeOperations(cxxRecordDecl);
8449+
bool isCopyable = !hasNonCopyableAttr(cxxRecordDecl) &&
8450+
hasCopyTypeOperations(cxxRecordDecl);
84508451
bool isMovable = hasMoveTypeOperations(cxxRecordDecl);
84518452

84528453
if (!hasDestroyTypeOperations(cxxRecordDecl) || (!isCopyable && !isMovable)) {

lib/ClangImporter/SwiftDeclSynthesizer.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3012,10 +3012,8 @@ FuncDecl *SwiftDeclSynthesizer::findExplicitDestroy(
30123012
ctx.evaluator,
30133013
CxxValueSemantics({clangType->getTypeForDecl(), &ImporterImpl}), {});
30143014

3015-
if (valueSemanticsKind == CxxValueSemanticsKind::MoveOnly)
3016-
return destroyFunc;
3017-
3018-
if (valueSemanticsKind != CxxValueSemanticsKind::Copyable)
3015+
if (valueSemanticsKind != CxxValueSemanticsKind::Copyable &&
3016+
valueSemanticsKind != CxxValueSemanticsKind::MoveOnly)
30193017
return nullptr;
30203018

30213019
auto cxxRecordSemanticsKind = evaluateOrDefault(
@@ -3034,6 +3032,9 @@ FuncDecl *SwiftDeclSynthesizer::findExplicitDestroy(
30343032
}
30353033
}
30363034

3035+
if (valueSemanticsKind == CxxValueSemanticsKind::MoveOnly)
3036+
return destroyFunc;
3037+
30373038
markDeprecated(
30383039
nominal,
30393040
"destroy operation '" +

test/Interop/C/struct/Inputs/noncopyable-struct.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ void badDestroy2(BadDestroyNonCopyableType2 *ptr);
4747

4848
struct __attribute__((swift_attr("~Copyable"))) __attribute__((swift_attr("destroy:extraDestroy"))) ExtraDestroy {
4949
void *storage;
50-
50+
ExtraDestroy(ExtraDestroy&&) = default;
5151
~ExtraDestroy() { }
5252
};
5353

test/Interop/C/struct/noncopyable_structs_nontrivial.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
// RUN: %target-swift-frontend -emit-sil -I %S/Inputs/ -I %swift_src_root/lib/ClangImporter/SwiftBridging %s -verify -DERRORS -verify-additional-prefix conly-
44
// RUN: %target-swift-frontend -emit-sil -I %S/Inputs/ -I %swift_src_root/lib/ClangImporter/SwiftBridging %s -verify -DERRORS -DCPLUSPLUS -verify-additional-prefix cplusplus- -cxx-interoperability-mode=default
55

6-
// XFAIL: OS=windows-msvc
76
import NoncopyableStructs
87

98
#if CPLUSPLUS

test/Interop/Cxx/class/noncopyable-typechecker.swift

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// RUN: %empty-directory(%t)
22
// RUN: split-file %s %t
3-
// RUN: %target-swift-frontend -cxx-interoperability-mode=default -typecheck -verify -I %swift_src_root/lib/ClangImporter/SwiftBridging -I %t/Inputs %t/test.swift
4-
// RUN: %target-swift-frontend -cxx-interoperability-mode=default -Xcc -std=c++20 -verify-additional-prefix cpp20- -D CPP20 -typecheck -verify -I %swift_src_root/lib/ClangImporter/SwiftBridging -I %t/Inputs %t/test.swift
3+
// RUN: %target-swift-frontend -cxx-interoperability-mode=default -typecheck -verify -I %swift_src_root/lib/ClangImporter/SwiftBridging -I %t%{fs-sep}Inputs %t%{fs-sep}test.swift -verify-additional-file %t%{fs-sep}Inputs%{fs-sep}noncopyable.h
4+
// RUN: %target-swift-frontend -cxx-interoperability-mode=default -Xcc -std=c++20 -verify-additional-prefix cpp20- -D CPP20 -typecheck -verify -I %swift_src_root/lib/ClangImporter/SwiftBridging -I %t%{fs-sep}Inputs %t%{fs-sep}test.swift -verify-additional-file %t%{fs-sep}Inputs%{fs-sep}noncopyable.h
55

66
//--- Inputs/module.modulemap
77
module Test {
@@ -68,6 +68,18 @@ MyPair<int, NonCopyableRequires> p7();
6868

6969
#endif
7070

71+
template<typename T>
72+
struct SWIFT_COPYABLE_IF(T) SWIFT_NONCOPYABLE DoubleAnnotation {};
73+
74+
using DoubleAnnotationInt = DoubleAnnotation<int>;
75+
76+
struct SWIFT_NONCOPYABLE NonCopyableNonMovable { // expected-note {{record 'NonCopyableNonMovable' is not automatically available: it must have a copy/move constructor and a destructor; does this type have reference semantics?}}
77+
NonCopyableNonMovable() {}
78+
NonCopyableNonMovable(const NonCopyableNonMovable& other) {}
79+
NonCopyableNonMovable(NonCopyableNonMovable&& other) = delete;
80+
};
81+
82+
7183
//--- test.swift
7284
import Test
7385
import CxxStdlib
@@ -107,3 +119,13 @@ func useOfRequires() {
107119
takeCopyable(p7()) // expected-cpp20-error {{global function 'takeCopyable' requires that 'MyPair<CInt, RequiresCopyableT<NonCopyable>>' conform to 'Copyable'}}
108120
}
109121
#endif
122+
123+
func doubleAnnotation() {
124+
let s = DoubleAnnotationInt()
125+
takeCopyable(s) // expected-error {{global function 'takeCopyable' requires that 'DoubleAnnotationInt' (aka 'DoubleAnnotation<CInt>') conform to 'Copyable'}}
126+
}
127+
128+
func missingLifetimeOperation() {
129+
let s = NonCopyableNonMovable() // expected-error {{cannot find 'NonCopyableNonMovable' in scope}}
130+
takeCopyable(s)
131+
}

0 commit comments

Comments
 (0)