Skip to content

Commit 59a7eb4

Browse files
committed
Merge remote-tracking branch 'origin/main' into rebranch
2 parents 9f2e416 + 89708dd commit 59a7eb4

File tree

5 files changed

+135
-9
lines changed

5 files changed

+135
-9
lines changed

include/swift/ClangImporter/ClangImporterRequests.h

+41-2
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@
1616
#ifndef SWIFT_CLANG_IMPORTER_REQUESTS_H
1717
#define SWIFT_CLANG_IMPORTER_REQUESTS_H
1818

19-
#include "swift/AST/SimpleRequest.h"
2019
#include "swift/AST/ASTTypeIDs.h"
2120
#include "swift/AST/EvaluatorDependencies.h"
22-
#include "swift/AST/FileUnit.h"
2321
#include "swift/AST/Identifier.h"
2422
#include "swift/AST/NameLookup.h"
23+
#include "swift/AST/SimpleRequest.h"
2524
#include "swift/Basic/Statistic.h"
25+
#include "clang/AST/Type.h"
2626
#include "llvm/ADT/Hashing.h"
2727
#include "llvm/ADT/TinyPtrVector.h"
2828

@@ -500,6 +500,45 @@ class CustomRefCountingOperation
500500
CustomRefCountingOperationDescriptor desc) const;
501501
};
502502

503+
enum class CxxEscapability { Escapable, NonEscapable, Unknown };
504+
505+
struct EscapabilityLookupDescriptor final {
506+
const clang::Type *type;
507+
508+
friend llvm::hash_code hash_value(const EscapabilityLookupDescriptor &desc) {
509+
return llvm::hash_combine(desc.type);
510+
}
511+
512+
friend bool operator==(const EscapabilityLookupDescriptor &lhs,
513+
const EscapabilityLookupDescriptor &rhs) {
514+
return lhs.type == rhs.type;
515+
}
516+
517+
friend bool operator!=(const EscapabilityLookupDescriptor &lhs,
518+
const EscapabilityLookupDescriptor &rhs) {
519+
return !(lhs == rhs);
520+
}
521+
};
522+
523+
class ClangTypeEscapability
524+
: public SimpleRequest<ClangTypeEscapability,
525+
CxxEscapability(EscapabilityLookupDescriptor),
526+
RequestFlags::Cached> {
527+
public:
528+
using SimpleRequest::SimpleRequest;
529+
530+
bool isCached() const { return true; }
531+
532+
private:
533+
friend SimpleRequest;
534+
535+
CxxEscapability evaluate(Evaluator &evaluator,
536+
EscapabilityLookupDescriptor desc) const;
537+
};
538+
539+
void simple_display(llvm::raw_ostream &out, EscapabilityLookupDescriptor desc);
540+
SourceLoc extractNearestSourceLoc(EscapabilityLookupDescriptor desc);
541+
503542
#define SWIFT_TYPEID_ZONE ClangImporter
504543
#define SWIFT_TYPEID_HEADER "swift/ClangImporter/ClangImporterTypeIDZone.def"
505544
#include "swift/Basic/DefineTypeIDZone.h"

include/swift/ClangImporter/ClangImporterTypeIDZone.def

+3
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,6 @@ SWIFT_REQUEST(ClangImporter, IsSafeUseOfCxxDecl,
4242
SWIFT_REQUEST(ClangImporter, CustomRefCountingOperation,
4343
CustomRefCountingOperationResult(CustomRefCountingOperationDescriptor), Cached,
4444
NoLocationInfo)
45+
SWIFT_REQUEST(ClangImporter, ClangTypeEscapability,
46+
CxxEscapability(EscapabilityLookupDescriptor), Cached,
47+
NoLocationInfo)

lib/ClangImporter/ClangImporter.cpp

+70
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@
5252
#include "swift/Strings.h"
5353
#include "swift/Subsystems.h"
5454
#include "clang/AST/ASTContext.h"
55+
#include "clang/AST/DeclCXX.h"
5556
#include "clang/AST/Mangle.h"
57+
#include "clang/AST/Type.h"
5658
#include "clang/Basic/DiagnosticOptions.h"
5759
#include "clang/Basic/FileEntry.h"
5860
#include "clang/Basic/IdentifierTable.h"
@@ -5020,6 +5022,74 @@ TinyPtrVector<ValueDecl *> CXXNamespaceMemberLookup::evaluate(
50205022
return result;
50215023
}
50225024

5025+
CxxEscapability
5026+
ClangTypeEscapability::evaluate(Evaluator &evaluator,
5027+
EscapabilityLookupDescriptor desc) const {
5028+
auto desugared = desc.type->getUnqualifiedDesugaredType();
5029+
if (const auto *recordType = desugared->getAs<clang::RecordType>()) {
5030+
if (importer::hasNonEscapableAttr(recordType->getDecl()))
5031+
return CxxEscapability::NonEscapable;
5032+
if (importer::hasEscapableAttr(recordType->getDecl()))
5033+
return CxxEscapability::Escapable;
5034+
auto recordDecl = recordType->getDecl();
5035+
auto cxxRecordDecl = dyn_cast<clang::CXXRecordDecl>(recordDecl);
5036+
if (!cxxRecordDecl || cxxRecordDecl->isAggregate()) {
5037+
bool hadUnknown = false;
5038+
auto evaluateEscapability = [&](const clang::Type *type) {
5039+
auto escapability = evaluateOrDefault(
5040+
evaluator, ClangTypeEscapability({type}), CxxEscapability::Unknown);
5041+
if (escapability == CxxEscapability::Unknown)
5042+
hadUnknown = true;
5043+
return escapability;
5044+
};
5045+
5046+
if (cxxRecordDecl) {
5047+
for (auto base : cxxRecordDecl->bases()) {
5048+
auto baseEscapability = evaluateEscapability(
5049+
base.getType()->getUnqualifiedDesugaredType());
5050+
if (baseEscapability == CxxEscapability::NonEscapable)
5051+
return CxxEscapability::NonEscapable;
5052+
}
5053+
}
5054+
5055+
for (auto field : recordDecl->fields()) {
5056+
auto fieldEscapability = evaluateEscapability(
5057+
field->getType()->getUnqualifiedDesugaredType());
5058+
if (fieldEscapability == CxxEscapability::NonEscapable)
5059+
return CxxEscapability::NonEscapable;
5060+
}
5061+
5062+
return hadUnknown ? CxxEscapability::Unknown : CxxEscapability::Escapable;
5063+
}
5064+
}
5065+
if (desugared->isArrayType()) {
5066+
auto elemTy = cast<clang::ArrayType>(desugared)
5067+
->getElementType()
5068+
->getUnqualifiedDesugaredType();
5069+
return evaluateOrDefault(evaluator, ClangTypeEscapability({elemTy}),
5070+
CxxEscapability::Unknown);
5071+
}
5072+
5073+
// Base cases
5074+
if (desugared->isAnyPointerType() || desugared->isBlockPointerType() ||
5075+
desugared->isMemberPointerType() || desugared->isReferenceType())
5076+
return CxxEscapability::NonEscapable;
5077+
if (desugared->isScalarType())
5078+
return CxxEscapability::Escapable;
5079+
return CxxEscapability::Unknown;
5080+
}
5081+
5082+
void swift::simple_display(llvm::raw_ostream &out,
5083+
EscapabilityLookupDescriptor desc) {
5084+
out << "Computing escapability for type '";
5085+
out << clang::QualType(desc.type, 0).getAsString();
5086+
out << "'";
5087+
}
5088+
5089+
SourceLoc swift::extractNearestSourceLoc(EscapabilityLookupDescriptor) {
5090+
return SourceLoc();
5091+
}
5092+
50235093
// Just create a specialized function decl for "__swift_interopStaticCast"
50245094
// using the types base and derived.
50255095
static

lib/ClangImporter/ImportDecl.cpp

+4-5
Original file line numberDiff line numberDiff line change
@@ -8132,8 +8132,7 @@ bool swift::importer::isMutabilityAttr(const clang::SwiftAttrAttr *swiftAttr) {
81328132
swiftAttr->getAttribute() == "nonmutating";
81338133
}
81348134

8135-
static bool importAsUnsafe(const ASTContext &context,
8136-
const clang::RecordDecl *decl,
8135+
static bool importAsUnsafe(ASTContext &context, const clang::RecordDecl *decl,
81378136
const Decl *MappedDecl) {
81388137
if (!context.LangOpts.hasFeature(Feature::SafeInterop) ||
81398138
!context.LangOpts.hasFeature(Feature::AllowUnsafeAttribute) || !decl)
@@ -8142,9 +8141,9 @@ static bool importAsUnsafe(const ASTContext &context,
81428141
if (isa<ClassDecl>(MappedDecl))
81438142
return false;
81448143

8145-
// TODO: Add logic to cover structural rules.
8146-
return !importer::hasNonEscapableAttr(decl) &&
8147-
!importer::hasEscapableAttr(decl);
8144+
return evaluateOrDefault(
8145+
context.evaluator, ClangTypeEscapability({decl->getTypeForDecl()}),
8146+
CxxEscapability::Unknown) == CxxEscapability::Unknown;
81488147
}
81498148

81508149
void

test/Interop/Cxx/class/safe-interop-mode.swift

+17-2
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,22 @@ private:
2626

2727
struct SWIFT_ESCAPABLE Owner {};
2828

29-
struct Unannotated {};
29+
struct Unannotated {
30+
Unannotated();
31+
};
3032

3133
struct SWIFT_UNSAFE_REFERENCE UnsafeReference {};
3234

35+
struct SafeEscapableAggregate {
36+
int a;
37+
float b[5];
38+
};
39+
40+
struct UnknownEscapabilityAggregate {
41+
SafeEscapableAggregate agg;
42+
Unannotated unann;
43+
};
44+
3345
//--- test.swift
3446

3547
import Test
@@ -42,7 +54,10 @@ func useUnsafeParam(x: Unannotated) { // expected-warning{{reference to unsafe s
4254
func useUnsafeParam2(x: UnsafeReference) { // expected-warning{{reference to unsafe class 'UnsafeReference'}}
4355
}
4456

45-
func useSafeParams(x: Owner, y: View) {
57+
func useUnsafeParam3(x: UnknownEscapabilityAggregate) { // expected-warning{{reference to unsafe struct 'UnknownEscapabilityAggregate'}}
58+
}
59+
60+
func useSafeParams(x: Owner, y: View, z: SafeEscapableAggregate) {
4661
}
4762

4863
func useCfType(x: CFArray) {

0 commit comments

Comments
 (0)