Skip to content

Commit b2ae2be

Browse files
authored
Merge pull request #4251 from jckarter/pseudogeneric-crashers-3.0
[3.0] rdar://problem/26867815 Prevent crashes when accessing ObjC generic members
2 parents 5648521 + ef187af commit b2ae2be

File tree

6 files changed

+49
-8
lines changed

6 files changed

+49
-8
lines changed

lib/IRGen/GenMeta.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -267,8 +267,8 @@ static bool isTypeErasedGenericClassType(CanType type) {
267267
}
268268

269269
// Get the type that exists at runtime to represent a compile-time type.
270-
static CanType
271-
getRuntimeReifiedType(IRGenModule &IGM, CanType type) {
270+
CanType
271+
irgen::getRuntimeReifiedType(IRGenModule &IGM, CanType type) {
272272
return CanType(type.transform([&](Type t) -> Type {
273273
if (isTypeErasedGenericClassType(CanType(t))) {
274274
return t->getAnyNominal()->getDeclaredType()->getCanonicalType();

lib/IRGen/GenMeta.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ namespace irgen {
8585
CanType type,
8686
SymbolReferenceKind refKind);
8787

88+
/// Get the type as it exists in Swift's runtime type system, removing any
89+
/// erased generic parameters.
90+
CanType getRuntimeReifiedType(IRGenModule &IGM, CanType type);
91+
8892
/// Emit a reference to a compile-time constant piece of heap metadata, or
8993
/// return a null pointer if the type's heap metadata cannot be represented
9094
/// by a constant.

lib/IRGen/IRGenSIL.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -747,8 +747,10 @@ class IRGenSILFunction :
747747
// Force all archetypes referenced by the type to be bound by this point.
748748
// TODO: just make sure that we have a path to them that the debug info
749749
// can follow.
750-
if (!IGM.IRGen.Opts.Optimize && Ty.getType()->hasArchetype())
751-
Ty.getType()->getCanonicalType().visit([&](Type t) {
750+
auto runtimeTy = getRuntimeReifiedType(IGM,
751+
Ty.getType()->getCanonicalType());
752+
if (!IGM.IRGen.Opts.Optimize && runtimeTy->hasArchetype())
753+
runtimeTy.visit([&](Type t) {
752754
if (auto archetype = dyn_cast<ArchetypeType>(CanType(t)))
753755
emitTypeMetadataRef(archetype);
754756
});

lib/Sema/TypeCheckCaptures.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,13 @@ class FindCapturedVars : public ASTWalker {
199199
std::pair<bool, Expr *> walkToDeclRefExpr(DeclRefExpr *DRE) {
200200
auto *D = DRE->getDecl();
201201

202+
// Capture the generic parameters of the decl.
203+
if (!AFR.isObjC() || !D->isObjC() || isa<ConstructorDecl>(D)) {
204+
for (auto sub : DRE->getDeclRef().getSubstitutions()) {
205+
checkType(sub.getReplacement(), DRE->getLoc());
206+
}
207+
}
208+
202209
// DC is the DeclContext where D was defined
203210
// CurDC is the DeclContext where D was referenced
204211
auto DC = D->getDeclContext();
@@ -430,17 +437,22 @@ class FindCapturedVars : public ASTWalker {
430437
&& !E->getType()->is<AnyMetatypeType>());
431438

432439
// Accessing @objc members doesn't require type metadata.
440+
// rdar://problem/27796375 -- allocating init entry points for ObjC
441+
// initializers are generated as true Swift generics, so reify type
442+
// parameters.
433443
if (auto memberRef = dyn_cast<MemberRefExpr>(E))
434444
return !memberRef->getMember().getDecl()->hasClangNode();
435445

436446
if (auto applyExpr = dyn_cast<ApplyExpr>(E)) {
437447
if (auto methodApply = dyn_cast<ApplyExpr>(applyExpr->getFn())) {
438448
if (auto callee = dyn_cast<DeclRefExpr>(methodApply->getFn())) {
439-
return !callee->getDecl()->isObjC();
449+
return !callee->getDecl()->isObjC()
450+
|| isa<ConstructorDecl>(callee->getDecl());
440451
}
441452
}
442453
if (auto callee = dyn_cast<DeclRefExpr>(applyExpr->getFn())) {
443-
return !callee->getDecl()->isObjC();
454+
return !callee->getDecl()->isObjC()
455+
|| isa<ConstructorDecl>(callee->getDecl());
444456
}
445457
}
446458

test/ClangModules/objc_bridging_generics.swift

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,14 @@ extension AnimalContainer {
265265
T.apexPredator = x // expected-note{{used here}}
266266
}
267267

268+
// rdar://problem/27796375 -- allocating init entry points for ObjC
269+
// initializers are generated as true Swift generics, so reify type
270+
// parameters.
271+
// expected-error@+1{{extension of a generic Objective-C class cannot access the class's generic parameters}}
272+
func usesGenericParamE(_ x: T) {
273+
_ = GenericClass(thing: x) // expected-note{{used here}}
274+
}
275+
268276
func checkThatMethodsAreObjC() {
269277
_ = #selector(AnimalContainer.doesntUseGenericParam1)
270278
_ = #selector(AnimalContainer.doesntUseGenericParam2)
@@ -283,9 +291,11 @@ extension AnimalContainer {
283291

284292
extension PettableContainer {
285293
func doesntUseGenericParam(_ x: T, _ y: T.Type) {
286-
_ = type(of: x).init(fur: x).other()
294+
// TODO: rdar://problem/27796375--allocating entry points are emitted as
295+
// true generics.
296+
// _ = type(of: x).init(fur: x).other()
287297
_ = type(of: x).adopt().other()
288-
_ = y.init(fur: x).other()
298+
// _ = y.init(fur: x).other()
289299
_ = y.adopt().other()
290300
x.pet()
291301
x.pet(with: x)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
2+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) %s -emit-ir -g -verify
3+
4+
// REQUIRES: objc_interop
5+
6+
import Swift
7+
import Foundation
8+
import objc_generics
9+
10+
extension GenericClass {
11+
func method() {}
12+
class func classMethod() {}
13+
}

0 commit comments

Comments
 (0)