Skip to content

Commit dcffbc0

Browse files
authored
Merge pull request #37436 from allevato/lost-in-a-c-of-decls
[PrintAsObjC] Import/fwd-declare types used in `@_cdecl` functions.
2 parents 5d34f5b + f9ea748 commit dcffbc0

File tree

3 files changed

+71
-22
lines changed

3 files changed

+71
-22
lines changed

lib/PrintAsObjC/DeclAndTypePrinter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -773,7 +773,7 @@ class DeclAndTypePrinter::Implementation
773773

774774
printAvailability(FD);
775775

776-
os << ';';
776+
os << ";\n";
777777
}
778778

779779
enum class PrintLeadingSpace : bool {

lib/PrintAsObjC/ModuleContentsWriter.cpp

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,30 @@ class ModuleWriter {
235235
});
236236
}
237237

238+
void forwardDeclareType(const TypeDecl *TD) {
239+
if (auto CD = dyn_cast<ClassDecl>(TD)) {
240+
if (!forwardDeclare(CD)) {
241+
(void)addImport(CD);
242+
}
243+
} else if (auto PD = dyn_cast<ProtocolDecl>(TD)) {
244+
forwardDeclare(PD);
245+
} else if (auto TAD = dyn_cast<TypeAliasDecl>(TD)) {
246+
bool imported = false;
247+
if (TAD->hasClangNode())
248+
imported = addImport(TD);
249+
assert((imported || !TAD->isGeneric()) &&
250+
"referencing non-imported generic typealias?");
251+
} else if (addImport(TD)) {
252+
return;
253+
} else if (auto ED = dyn_cast<EnumDecl>(TD)) {
254+
forwardDeclare(ED);
255+
} else if (isa<AbstractTypeParamDecl>(TD)) {
256+
llvm_unreachable("should not see type params here");
257+
} else {
258+
assert(false && "unknown local type decl");
259+
}
260+
}
261+
238262
bool forwardDeclareMemberTypes(DeclRange members, const Decl *container) {
239263
PrettyStackTraceDecl
240264
entry("printing forward declarations needed by members of", container);
@@ -312,26 +336,7 @@ class ModuleWriter {
312336
// FIXME: It would be nice to diagnose this.
313337
}
314338

315-
if (auto CD = dyn_cast<ClassDecl>(TD)) {
316-
if (!forwardDeclare(CD)) {
317-
(void)addImport(CD);
318-
}
319-
} else if (auto PD = dyn_cast<ProtocolDecl>(TD)) {
320-
forwardDeclare(PD);
321-
} else if (auto TAD = dyn_cast<TypeAliasDecl>(TD)) {
322-
bool imported = false;
323-
if (TAD->hasClangNode())
324-
imported = addImport(TD);
325-
assert((imported || !TAD->isGeneric()) && "referencing non-imported generic typealias?");
326-
} else if (addImport(TD)) {
327-
return;
328-
} else if (auto ED = dyn_cast<EnumDecl>(TD)) {
329-
forwardDeclare(ED);
330-
} else if (isa<AbstractTypeParamDecl>(TD)) {
331-
llvm_unreachable("should not see type params here");
332-
} else {
333-
assert(false && "unknown local type decl");
334-
}
339+
forwardDeclareType(TD);
335340
});
336341

337342
if (needsToBeIndividuallyDelayed) {
@@ -374,11 +379,22 @@ class ModuleWriter {
374379
printer.print(CD);
375380
return true;
376381
}
377-
382+
378383
bool writeFunc(const FuncDecl *FD) {
379384
if (addImport(FD))
380385
return true;
381386

387+
PrettyStackTraceDecl entry(
388+
"printing forward declarations needed by function", FD);
389+
ReferencedTypeFinder::walk(
390+
FD->getInterfaceType(),
391+
[&](ReferencedTypeFinder &finder, const TypeDecl *TD) {
392+
PrettyStackTraceDecl entry("walking its interface type, currently at",
393+
TD);
394+
forwardDeclareType(TD);
395+
});
396+
397+
os << '\n';
382398
printer.print(FD);
383399
return true;
384400
}

test/PrintAsObjC/cdecl-imports.swift

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck %s -parse-as-library -emit-objc-header-path %t/swift.h
3+
// RUN: %FileCheck %s < %t/swift.h
4+
// RUN: %check-in-clang %t/swift.h
5+
6+
// REQUIRES: objc_interop
7+
8+
import CoreGraphics
9+
import Foundation
10+
11+
// CHECK: @import CoreGraphics;
12+
// CHECK-NOT: @import Foundation;
13+
14+
// CHECK: @class Bee;
15+
// CHECK-LABEL: Bee * _Nonnull fwd_declares_bee(void) SWIFT_WARN_UNUSED_RESULT;
16+
17+
@_cdecl("fwd_declares_bee")
18+
public func fwdDeclaresBee() -> Bee { fatalError() }
19+
20+
// CHECK: @class Hive;
21+
// CHECK-LABEL: void fwd_declares_hive(SWIFT_NOESCAPE Hive * _Nonnull (* _Nonnull bzzz)(Bee * _Nonnull));
22+
23+
@_cdecl("fwd_declares_hive")
24+
public func fwdDeclaresHive(bzzz: @convention(c) (Bee) -> Hive) { fatalError() }
25+
26+
// CHECK: @protocol NSWobbling;
27+
// CHECK-LABEL: void fwd_declares_wobble(id <NSWobbling> _Nonnull wobbler);
28+
29+
@_cdecl("fwd_declares_wobble")
30+
public func fwdDeclaresWobble(wobbler: NSWobbling) { fatalError() }
31+
32+
@_cdecl("imports_cgpoint")
33+
public func importsCGPoint(pt: CGPoint) { fatalError() }

0 commit comments

Comments
 (0)