Skip to content

Commit 3a61394

Browse files
authored
Merge pull request swiftlang#70693 from xedin/rdar-104246144
[ClangImporter] Augment type import to support SwiftAttr in type contexts
2 parents 1185730 + 6a3ef05 commit 3a61394

File tree

8 files changed

+340
-89
lines changed

8 files changed

+340
-89
lines changed

lib/ClangImporter/ClangImporter.cpp

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7196,36 +7196,40 @@ static bool isForeignReferenceType(const clang::QualType type) {
71967196
return hasImportAsRefAttr(pointeeType->getDecl());
71977197
}
71987198

7199+
static bool hasSwiftAttribute(const clang::Decl *decl, StringRef attr) {
7200+
if (decl->hasAttrs() && llvm::any_of(decl->getAttrs(), [&](auto *A) {
7201+
if (auto swiftAttr = dyn_cast<clang::SwiftAttrAttr>(A))
7202+
return swiftAttr->getAttribute() == attr;
7203+
return false;
7204+
}))
7205+
return true;
7206+
7207+
if (auto *P = dyn_cast<clang::ParmVarDecl>(decl)) {
7208+
bool found = false;
7209+
findSwiftAttributes(P->getOriginalType(),
7210+
[&](const clang::SwiftAttrAttr *swiftAttr) {
7211+
found |= swiftAttr->getAttribute() == attr;
7212+
});
7213+
return found;
7214+
}
7215+
7216+
return false;
7217+
}
7218+
71997219
static bool hasOwnedValueAttr(const clang::RecordDecl *decl) {
7200-
return decl->hasAttrs() && llvm::any_of(decl->getAttrs(), [](auto *attr) {
7201-
if (auto swiftAttr = dyn_cast<clang::SwiftAttrAttr>(attr))
7202-
return swiftAttr->getAttribute() == "import_owned";
7203-
return false;
7204-
});
7220+
return hasSwiftAttribute(decl, "import_owned");
72057221
}
72067222

72077223
bool importer::hasUnsafeAPIAttr(const clang::Decl *decl) {
7208-
return decl->hasAttrs() && llvm::any_of(decl->getAttrs(), [](auto *attr) {
7209-
if (auto swiftAttr = dyn_cast<clang::SwiftAttrAttr>(attr))
7210-
return swiftAttr->getAttribute() == "import_unsafe";
7211-
return false;
7212-
});
7224+
return hasSwiftAttribute(decl, "import_unsafe");
72137225
}
72147226

72157227
static bool hasIteratorAPIAttr(const clang::Decl *decl) {
7216-
return decl->hasAttrs() && llvm::any_of(decl->getAttrs(), [](auto *attr) {
7217-
if (auto swiftAttr = dyn_cast<clang::SwiftAttrAttr>(attr))
7218-
return swiftAttr->getAttribute() == "import_iterator";
7219-
return false;
7220-
});
7228+
return hasSwiftAttribute(decl, "import_iterator");
72217229
}
72227230

72237231
static bool hasNonCopyableAttr(const clang::RecordDecl *decl) {
7224-
return decl->hasAttrs() && llvm::any_of(decl->getAttrs(), [](auto *attr) {
7225-
if (auto swiftAttr = dyn_cast<clang::SwiftAttrAttr>(attr))
7226-
return swiftAttr->getAttribute() == "~Copyable";
7227-
return false;
7228-
});
7232+
return hasSwiftAttribute(decl, "~Copyable");
72297233
}
72307234

72317235
/// Recursively checks that there are no pointers in any fields or base classes.

lib/ClangImporter/ImportDecl.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7308,8 +7308,14 @@ llvm::Optional<GenericParamList *> SwiftDeclConverter::importObjCGenericParams(
73087308
SmallVector<InheritedEntry, 1> inherited;
73097309
if (objcGenericParam->hasExplicitBound()) {
73107310
assert(!objcGenericParam->getUnderlyingType().isNull());
7311-
auto clangBound = objcGenericParam->getUnderlyingType()
7311+
auto underlyingTy = objcGenericParam->getUnderlyingType();
7312+
auto clangBound = underlyingTy
73127313
->castAs<clang::ObjCObjectPointerType>();
7314+
7315+
ImportTypeAttrs attrs;
7316+
getConcurrencyAttrs(Impl.SwiftContext, ImportTypeKind::Abstract, attrs,
7317+
underlyingTy);
7318+
73137319
if (clangBound->getInterfaceDecl()) {
73147320
auto unqualifiedClangBound =
73157321
clangBound->stripObjCKindOfTypeAndQuals(Impl.getClangASTContext());
@@ -7324,6 +7330,15 @@ llvm::Optional<GenericParamList *> SwiftDeclConverter::importObjCGenericParams(
73247330
}
73257331
inherited.push_back(TypeLoc::withoutLoc(superclassType));
73267332
}
7333+
7334+
if (attrs.contains(ImportTypeAttr::Sendable)) {
7335+
if (auto *sendable =
7336+
Impl.SwiftContext.getProtocol(KnownProtocolKind::Sendable)) {
7337+
inherited.push_back(
7338+
TypeLoc::withoutLoc(sendable->getDeclaredInterfaceType()));
7339+
}
7340+
}
7341+
73277342
for (clang::ObjCProtocolDecl *clangProto : clangBound->quals()) {
73287343
ProtocolDecl *proto = castIgnoringCompatibilityAlias<ProtocolDecl>(
73297344
Impl.importDecl(clangProto, getActiveSwiftVersion()));

lib/ClangImporter/ImportType.cpp

Lines changed: 97 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1282,9 +1282,8 @@ static bool canBridgeTypes(ImportTypeKind importKind) {
12821282
case ImportTypeKind::Result:
12831283
case ImportTypeKind::AuditedResult:
12841284
case ImportTypeKind::Parameter:
1285+
case ImportTypeKind::CompletionHandlerParameter:
12851286
case ImportTypeKind::CompletionHandlerResultParameter:
1286-
case ImportTypeKind::CFRetainedOutParameter:
1287-
case ImportTypeKind::CFUnretainedOutParameter:
12881287
case ImportTypeKind::Property:
12891288
case ImportTypeKind::PropertyWithReferenceSemantics:
12901289
case ImportTypeKind::ObjCCollectionElement:
@@ -1310,9 +1309,8 @@ static bool isCFAudited(ImportTypeKind importKind) {
13101309
case ImportTypeKind::AuditedVariable:
13111310
case ImportTypeKind::AuditedResult:
13121311
case ImportTypeKind::Parameter:
1312+
case ImportTypeKind::CompletionHandlerParameter:
13131313
case ImportTypeKind::CompletionHandlerResultParameter:
1314-
case ImportTypeKind::CFRetainedOutParameter:
1315-
case ImportTypeKind::CFUnretainedOutParameter:
13161314
case ImportTypeKind::Property:
13171315
case ImportTypeKind::PropertyWithReferenceSemantics:
13181316
return true;
@@ -1388,7 +1386,7 @@ static Type maybeImportNSErrorOutParameter(ClangImporter::Implementation &impl,
13881386

13891387
static Type maybeImportCFOutParameter(ClangImporter::Implementation &impl,
13901388
Type importedType,
1391-
ImportTypeKind importKind) {
1389+
ImportTypeAttrs attrs) {
13921390
PointerTypeKind PTK;
13931391
auto elementType = importedType->getAnyPointerElementType(PTK);
13941392
if (!elementType || PTK != PTK_UnsafeMutablePointer)
@@ -1414,7 +1412,7 @@ static Type maybeImportCFOutParameter(ClangImporter::Implementation &impl,
14141412
resultTy = OptionalType::get(resultTy);
14151413

14161414
PointerTypeKind pointerKind;
1417-
if (importKind == ImportTypeKind::CFRetainedOutParameter)
1415+
if (attrs.contains(ImportTypeAttr::CFRetainedOutParameter))
14181416
pointerKind = PTK_UnsafeMutablePointer;
14191417
else
14201418
pointerKind = PTK_AutoreleasingUnsafeMutablePointer;
@@ -1569,8 +1567,16 @@ static ImportedType adjustTypeForConcreteImport(
15691567
break;
15701568

15711569
case ImportHint::OtherPointer:
1572-
// Special-case AutoreleasingUnsafeMutablePointer<NSError?> parameters.
1573-
if (importKind == ImportTypeKind::Parameter) {
1570+
// Remove 'Unmanaged' from audited CF out-parameters.
1571+
if (attrs.contains(ImportTypeAttr::CFRetainedOutParameter) ||
1572+
attrs.contains(ImportTypeAttr::CFUnretainedOutParameter)) {
1573+
if (Type outParamTy =
1574+
maybeImportCFOutParameter(impl, importedType, attrs)) {
1575+
importedType = outParamTy;
1576+
break;
1577+
}
1578+
} else if (importKind == ImportTypeKind::Parameter) {
1579+
// Special-case AutoreleasingUnsafeMutablePointer<NSError?> parameters.
15741580
if (Type result = maybeImportNSErrorOutParameter(impl, importedType,
15751581
resugarNSErrorPointer)) {
15761582
importedType = result;
@@ -1579,16 +1585,6 @@ static ImportedType adjustTypeForConcreteImport(
15791585
}
15801586
}
15811587

1582-
// Remove 'Unmanaged' from audited CF out-parameters.
1583-
if (importKind == ImportTypeKind::CFRetainedOutParameter ||
1584-
importKind == ImportTypeKind::CFUnretainedOutParameter) {
1585-
if (Type outParamTy = maybeImportCFOutParameter(impl, importedType,
1586-
importKind)) {
1587-
importedType = outParamTy;
1588-
break;
1589-
}
1590-
}
1591-
15921588
break;
15931589
}
15941590

@@ -1637,6 +1633,63 @@ static ImportedType adjustTypeForConcreteImport(
16371633
return {importedType, isIUO};
16381634
}
16391635

1636+
void swift::findSwiftAttributes(
1637+
clang::QualType type,
1638+
llvm::function_ref<void(const clang::SwiftAttrAttr *)> callback) {
1639+
std::function<clang::QualType(clang::QualType)> skipUnrelatedSugar =
1640+
[&](clang::QualType type) -> clang::QualType {
1641+
if (auto *MQT = dyn_cast<clang::MacroQualifiedType>(type))
1642+
return MQT->isSugared() ? skipUnrelatedSugar(MQT->desugar()) : type;
1643+
1644+
if (auto *ET = dyn_cast<clang::ElaboratedType>(type))
1645+
return ET->isSugared() ? skipUnrelatedSugar(ET->desugar()) : type;
1646+
1647+
return type;
1648+
};
1649+
1650+
type = skipUnrelatedSugar(type);
1651+
1652+
// Consider only immediate attributes, don't look through the typerefs
1653+
// because they are imported separately.
1654+
while (const auto *AT = dyn_cast<clang::AttributedType>(type)) {
1655+
if (auto swiftAttr =
1656+
dyn_cast_or_null<clang::SwiftAttrAttr>(AT->getAttr())) {
1657+
callback(swiftAttr);
1658+
}
1659+
type = skipUnrelatedSugar(AT->getEquivalentType());
1660+
}
1661+
}
1662+
1663+
void swift::getConcurrencyAttrs(ASTContext &SwiftContext,
1664+
ImportTypeKind importKind,
1665+
ImportTypeAttrs &attrs, clang::QualType type) {
1666+
bool isMainActor = false;
1667+
bool isSendable =
1668+
SwiftContext.LangOpts.hasFeature(Feature::SendableCompletionHandlers) &&
1669+
importKind == ImportTypeKind::CompletionHandlerParameter;
1670+
bool isNonSendable = false;
1671+
1672+
// Consider only immediate attributes, don't look through the typerefs
1673+
// because they are imported separately.
1674+
findSwiftAttributes(type, [&](const clang::SwiftAttrAttr *attr) {
1675+
if (isMainActorAttr(attr)) {
1676+
isMainActor = true;
1677+
isNonSendable = importKind == ImportTypeKind::Parameter ||
1678+
importKind == ImportTypeKind::CompletionHandlerParameter;
1679+
} else if (attr->getAttribute() == "@Sendable")
1680+
isSendable = true;
1681+
else if (attr->getAttribute() == "@_nonSendable")
1682+
isNonSendable = true;
1683+
});
1684+
1685+
if (isMainActor)
1686+
attrs |= ImportTypeAttr::MainActor;
1687+
if (isSendable)
1688+
attrs |= ImportTypeAttr::Sendable;
1689+
if (isNonSendable)
1690+
attrs -= ImportTypeAttr::Sendable;
1691+
}
1692+
16401693
ImportedType ClangImporter::Implementation::importType(
16411694
clang::QualType type, ImportTypeKind importKind,
16421695
llvm::function_ref<void(Diagnostic &&)> addImportDiagnosticFn,
@@ -1683,6 +1736,8 @@ ImportedType ClangImporter::Implementation::importType(
16831736
optionality = translateNullability(*nullability, stripNonResultOptionality);
16841737
}
16851738

1739+
getConcurrencyAttrs(SwiftContext, importKind, attrs, type);
1740+
16861741
// If this is a completion handler parameter, record the function type whose
16871742
// parameters will act as the results of the completion handler.
16881743
const clang::FunctionType *completionHandlerType = nullptr;
@@ -1944,7 +1999,9 @@ class GetSendableType :
19441999
VISIT(ModuleType, pass)
19452000
VISIT(DynamicSelfType, pass)
19462001

1947-
NEVER_VISIT(SubstitutableType)
2002+
// Ignore attributes placed on generic parameter references and
2003+
// other substitutable types.
2004+
VISIT(SubstitutableType, pass)
19482005
NEVER_VISIT(DependentMemberType)
19492006

19502007
Result visitAnyFunctionType(AnyFunctionType *ty) {
@@ -2004,14 +2061,10 @@ class GetSendableType :
20042061

20052062
} // anonymous namespace
20062063

2007-
ImportTypeAttrs swift::getImportTypeAttrs(const clang::Decl *D, bool isParam,
2008-
bool sendableByDefault) {
2064+
ImportTypeAttrs swift::getImportTypeAttrs(const clang::Decl *D, bool isParam) {
20092065
ImportTypeAttrs attrs;
20102066

2011-
if (sendableByDefault)
2012-
attrs |= ImportTypeAttr::DefaultsToSendable;
2013-
2014-
bool sendableRequested = sendableByDefault;
2067+
bool sendableRequested = false;
20152068
bool sendableDisqualified = false;
20162069

20172070
if (D->hasAttrs()) {
@@ -2022,6 +2075,16 @@ ImportTypeAttrs swift::getImportTypeAttrs(const clang::Decl *D, bool isParam,
20222075
continue;
20232076
}
20242077

2078+
if (isa<clang::CFReturnsRetainedAttr>(attr)) {
2079+
attrs |= ImportTypeAttr::CFRetainedOutParameter;
2080+
continue;
2081+
}
2082+
2083+
if (isa<clang::CFReturnsNotRetainedAttr>(attr)) {
2084+
attrs |= ImportTypeAttr::CFUnretainedOutParameter;
2085+
continue;
2086+
}
2087+
20252088
auto swiftAttr = dyn_cast<clang::SwiftAttrAttr>(attr);
20262089
if (!swiftAttr)
20272090
continue;
@@ -2295,17 +2358,6 @@ ImportedType ClangImporter::Implementation::importFunctionParamsAndReturnType(
22952358
return {swiftResultTy, importedType.isImplicitlyUnwrapped()};
22962359
}
22972360

2298-
static ImportTypeKind
2299-
getImportTypeKindForParam(const clang::ParmVarDecl *param) {
2300-
ImportTypeKind importKind = ImportTypeKind::Parameter;
2301-
if (param->hasAttr<clang::CFReturnsRetainedAttr>())
2302-
importKind = ImportTypeKind::CFRetainedOutParameter;
2303-
else if (param->hasAttr<clang::CFReturnsNotRetainedAttr>())
2304-
importKind = ImportTypeKind::CFUnretainedOutParameter;
2305-
2306-
return importKind;
2307-
}
2308-
23092361
llvm::Optional<ClangImporter::Implementation::ImportParameterTypeResult>
23102362
ClangImporter::Implementation::importParameterType(
23112363
const clang::ParmVarDecl *param, OptionalTypeKind optionalityOfParam,
@@ -2318,7 +2370,9 @@ ClangImporter::Implementation::importParameterType(
23182370
if (auto elaborated = dyn_cast<clang::ElaboratedType>(paramTy))
23192371
paramTy = elaborated->desugar();
23202372

2321-
ImportTypeKind importKind = getImportTypeKindForParam(param);
2373+
ImportTypeKind importKind = paramIsCompletionHandler
2374+
? ImportTypeKind::CompletionHandlerParameter
2375+
: ImportTypeKind::Parameter;
23222376

23232377
// Import the parameter type into Swift.
23242378
auto attrs = getImportTypeAttrs(param, /*isParam=*/true);
@@ -2432,12 +2486,6 @@ ClangImporter::Implementation::importParameterType(
24322486
}
24332487

24342488
if (!swiftParamTy) {
2435-
bool sendableByDefault =
2436-
paramIsCompletionHandler &&
2437-
SwiftContext.LangOpts.hasFeature(Feature::SendableCompletionHandlers);
2438-
2439-
auto attrs = getImportTypeAttrs(param, /*isParam=*/true, sendableByDefault);
2440-
24412489
// If this is the throws error parameter, we don't need to convert any
24422490
// NSError** arguments to the sugared NSErrorPointer typealias form,
24432491
// because all that is done with it is retrieving the canonical
@@ -3206,17 +3254,16 @@ ImportedType ClangImporter::Implementation::importMethodParamsAndReturnType(
32063254
decomposeCompletionHandlerType(swiftParamTy, *asyncInfo)) {
32073255
swiftResultTy = replacedSwiftResultTy;
32083256

3209-
ImportTypeKind importKind = getImportTypeKindForParam(param);
3210-
32113257
// Import the original completion handler type without adjustments.
32123258
Type origSwiftParamTy =
3213-
importType(paramTy, importKind, paramAddDiag,
3214-
allowNSUIntegerAsIntInParam, Bridgeability::Full,
3215-
ImportTypeAttrs(), optionalityOfParam,
3259+
importType(paramTy, ImportTypeKind::CompletionHandlerParameter,
3260+
paramAddDiag, allowNSUIntegerAsIntInParam,
3261+
Bridgeability::Full, ImportTypeAttrs(),
3262+
optionalityOfParam,
32163263
/*resugarNSErrorPointer=*/!paramIsError, llvm::None)
32173264
.getType();
3218-
completionHandlerType = mapGenericArgs(origDC, dc, origSwiftParamTy)
3219-
->getCanonicalType();
3265+
completionHandlerType =
3266+
mapGenericArgs(origDC, dc, origSwiftParamTy)->getCanonicalType();
32203267
continue;
32213268
}
32223269

0 commit comments

Comments
 (0)