Skip to content

Commit b07c06e

Browse files
committed
[Serialization] Fix crashes when allowing compiler errors in modules
1 parent a9f5107 commit b07c06e

11 files changed

+135
-78
lines changed

lib/AST/ASTPrinter.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,9 @@ PrintOptions PrintOptions::printSwiftInterfaceFile(bool preferTypeRepr,
150150

151151
class ShouldPrintForModuleInterface : public ShouldPrintChecker {
152152
bool shouldPrint(const Decl *D, const PrintOptions &options) override {
153+
if (!D)
154+
return false;
155+
153156
// Skip anything that is marked `@_implementationOnly` itself.
154157
if (D->getAttrs().hasAttribute<ImplementationOnlyAttr>())
155158
return false;

lib/AST/DeclContext.cpp

+9-4
Original file line numberDiff line numberDiff line change
@@ -532,12 +532,17 @@ void AccessScope::dump() const {
532532

533533
if (auto *decl = getDeclContext()->getAsDecl()) {
534534
llvm::errs() << Decl::getKindName(decl->getKind()) << " ";
535-
if (auto *ext = dyn_cast<ExtensionDecl>(decl))
536-
llvm::errs() << ext->getExtendedNominal()->getName();
537-
else if (auto *named = dyn_cast<ValueDecl>(decl))
535+
if (auto *ext = dyn_cast<ExtensionDecl>(decl)) {
536+
auto *extended = ext->getExtendedNominal();
537+
if (extended)
538+
llvm::errs() << extended->getName();
539+
else
540+
llvm::errs() << "(null)";
541+
} else if (auto *named = dyn_cast<ValueDecl>(decl)) {
538542
llvm::errs() << named->getName();
539-
else
543+
} else {
540544
llvm::errs() << (const void *)decl;
545+
}
541546

542547
SourceLoc loc = decl->getLoc();
543548
if (loc.isValid()) {

lib/IDE/ModuleInterfacePrinting.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,8 @@ static bool printModuleInterfaceDecl(Decl *D,
247247
// a cross-module extension.
248248
if (!extensionHasClangNode(Ext)) {
249249
auto ExtendedNominal = Ext->getExtendedNominal();
250-
if (Ext->getModuleContext() == ExtendedNominal->getModuleContext())
250+
if (!ExtendedNominal ||
251+
Ext->getModuleContext() == ExtendedNominal->getModuleContext())
251252
return false;
252253
}
253254
}

lib/SILOptimizer/Analysis/ProtocolConformanceAnalysis.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class NominalTypeWalker : public ASTWalker {
4747
/// (2) Walk over all ExtensionDecls to determine conformances.
4848
if (auto *e = dyn_cast<ExtensionDecl>(D)) {
4949
auto *ntd = e->getExtendedNominal();
50-
if (!isa<ProtocolDecl>(ntd)) {
50+
if (ntd && !isa<ProtocolDecl>(ntd)) {
5151
for (auto *conformance : e->getLocalConformances()) {
5252
if (isa<NormalProtocolConformance>(conformance)) {
5353
auto *proto = conformance->getProtocol();

lib/Serialization/Deserialization.cpp

+6-3
Original file line numberDiff line numberDiff line change
@@ -3952,7 +3952,7 @@ class DeclDeserializer {
39523952
auto extendedType = MF.getType(extendedTypeID);
39533953
ctx.evaluator.cacheOutput(ExtendedTypeRequest{extension},
39543954
std::move(extendedType));
3955-
auto nominal = dyn_cast<NominalTypeDecl>(MF.getDecl(extendedNominalID));
3955+
auto nominal = dyn_cast_or_null<NominalTypeDecl>(MF.getDecl(extendedNominalID));
39563956
ctx.evaluator.cacheOutput(ExtendedNominalRequest{extension},
39573957
std::move(nominal));
39583958

@@ -3969,7 +3969,9 @@ class DeclDeserializer {
39693969
encodeLazyConformanceContextData(numConformances,
39703970
MF.DeclTypeCursor.GetCurrentBitNo()));
39713971

3972-
nominal->addExtension(extension);
3972+
if (nominal) {
3973+
nominal->addExtension(extension);
3974+
}
39733975

39743976
#ifndef NDEBUG
39753977
if (outerParams) {
@@ -6176,7 +6178,8 @@ void ModuleFile::finishNormalConformance(NormalProtocolConformance *conformance,
61766178
auto isConformanceReq = [](const Requirement &req) {
61776179
return req.getKind() == RequirementKind::Conformance;
61786180
};
6179-
if (conformanceCount != llvm::count_if(proto->getRequirementSignature(),
6181+
if (!isAllowModuleWithCompilerErrorsEnabled() &&
6182+
conformanceCount != llvm::count_if(proto->getRequirementSignature(),
61806183
isConformanceReq)) {
61816184
fatal(llvm::make_error<llvm::StringError>(
61826185
"serialized conformances do not match requirement signature",

lib/Serialization/Serialization.cpp

+11-4
Original file line numberDiff line numberDiff line change
@@ -1355,7 +1355,8 @@ void Serializer::writeASTBlockEntity(
13551355
using namespace decls_block;
13561356

13571357
// The conformance must be complete, or we can't serialize it.
1358-
assert(conformance->isComplete());
1358+
assert(conformance->isComplete() ||
1359+
getASTContext().LangOpts.AllowModuleWithCompilerErrors);
13591360
assert(NormalConformancesToSerialize.hasRef(conformance));
13601361

13611362
auto protocol = conformance->getProtocol();
@@ -1541,6 +1542,8 @@ static bool shouldSerializeMember(Decl *D) {
15411542
case DeclKind::Extension:
15421543
case DeclKind::Module:
15431544
case DeclKind::PrecedenceGroup:
1545+
if (D->getASTContext().LangOpts.AllowModuleWithCompilerErrors)
1546+
return false;
15441547
llvm_unreachable("decl should never be a member");
15451548

15461549
case DeclKind::MissingMember:
@@ -5050,7 +5053,9 @@ static void collectInterestingNestedDeclarations(
50505053
if (!nominalParent) {
50515054
const DeclContext *DC = member->getDeclContext();
50525055
nominalParent = DC->getSelfNominalTypeDecl();
5053-
assert(nominalParent && "parent context is not a type or extension");
5056+
assert(nominalParent ||
5057+
nestedType->getASTContext().LangOpts.AllowModuleWithCompilerErrors &&
5058+
"parent context is not a type or extension");
50545059
}
50555060
nestedTypeDecls[nestedType->getName()].push_back({
50565061
S.addDeclRef(nominalParent),
@@ -5115,8 +5120,10 @@ void Serializer::writeAST(ModuleOrSourceFile DC) {
51155120
.push_back({ getKindForTable(D), addDeclRef(D) });
51165121
} else if (auto ED = dyn_cast<ExtensionDecl>(D)) {
51175122
const NominalTypeDecl *extendedNominal = ED->getExtendedNominal();
5118-
extensionDecls[extendedNominal->getName()]
5119-
.push_back({ extendedNominal, addDeclRef(D) });
5123+
if (extendedNominal) {
5124+
extensionDecls[extendedNominal->getName()]
5125+
.push_back({ extendedNominal, addDeclRef(D) });
5126+
}
51205127
} else if (auto OD = dyn_cast<OperatorDecl>(D)) {
51215128
operatorDecls[OD->getName()]
51225129
.push_back({ getStableFixity(OD->getFixity()), addDeclRef(D) });

lib/Serialization/SerializeDoc.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,10 @@ static bool shouldIncludeDecl(Decl *D, bool ExcludeDoubleUnderscore) {
346346
return false;
347347

348348
if (auto *ED = dyn_cast<ExtensionDecl>(D)) {
349-
return shouldIncludeDecl(ED->getExtendedNominal(), ExcludeDoubleUnderscore);
349+
auto *extended = ED->getExtendedNominal();
350+
if (!extended)
351+
return false;
352+
return shouldIncludeDecl(extended, ExcludeDoubleUnderscore);
350353
}
351354
if (ExcludeDoubleUnderscore && hasDoubleUnderscore(D)) {
352355
return false;

test/SourceKit/Misc/Inputs/errors-a.swift

+11-3
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public protocol InvalidProtocol : undefined {
5555
public struct InvalidStruct : undefined, InvalidProtocol {
5656
typealias Item = undefined
5757

58-
public let memberA: Int = undefined {
58+
public let memberA: Int {
5959
willSet(newVal invalid) {
6060
print("Setting value \(newVal)")
6161
}
@@ -71,10 +71,10 @@ public struct InvalidStruct : undefined, InvalidProtocol {
7171
print("Set value \(oldValue)")
7272
}
7373
}
74-
public var memberC: undefined {
74+
public var memberC: undefined = {
7575
return undefined
7676
}()
77-
public lazy var memberD: undefined {
77+
public lazy var memberD: undefined = {
7878
return undefined
7979
}()
8080
public var memberE: undefined {
@@ -86,3 +86,11 @@ public struct InvalidStruct : undefined, InvalidProtocol {
8686
undefined
8787
}
8888
}
89+
90+
public extension undefined {
91+
public enum ValidEnum: String {
92+
case a
93+
case b
94+
case c
95+
}
96+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
extension
2+
3+
extension InvalidStruct {
4+
5+
extension InvalidProtocol
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,79 @@
11
import errors
22

3-
func foo() {
3+
func testInvalidGlobalCursor() {
44
invalidGlobalMissingInit = ""
5+
}
56

6-
let bar: InvalidStruct
7-
bar.memberB
7+
func testInvalidFuncCursor() {
88
invalidPartialFunc()
9-
bar.
9+
}
10+
11+
func testInvalidStructCursor() {
12+
let foo: InvalidStruct
13+
foo.memberB
14+
}
1015

11-
let baz: ;
16+
func testInvalidStructMemberCompletion() {
17+
let foo: InvalidStruct
18+
foo.#^INVALID-MEMBER^#
19+
// INVALID-MEMBER: Begin completions
20+
// INVALID-MEMBER-DAG: Decl[InstanceVar]/CurrNominal: memberA[#Int#];
21+
// INVALID-MEMBER-DAG: Decl[InstanceVar]/CurrNominal: memberB[#<<error type>>#];
22+
// INVALID-MEMBER-DAG: Decl[InstanceVar]/CurrNominal: memberC[#<<error type>>#];
23+
// INVALID-MEMBER-DAG: Decl[InstanceVar]/CurrNominal: memberD[#<<error type>>#];
24+
// INVALID-MEMBER-DAG: Decl[InstanceVar]/CurrNominal: memberE[#<<error type>>#];
25+
// INVALID-MEMBER-DAG: Decl[InstanceMethod]/Super: add({#<<error type>>#})[#Void#];
26+
// INVALID-MEMBER-DAG: Decl[InstanceMethod]/Super: get()[#InvalidStruct.Item#];
27+
// INVALID-MEMBER-DAG: Decl[InstanceMethod]/Super: set({#item: InvalidStruct.Item#})[#Void#];
28+
// INVALID-MEMBER: End completions
29+
}
1230

31+
func testInvalidTypeCompletion() {
32+
let foo: #^INVALID-TYPE^#;
33+
// INVALID-TYPE: Begin completions
34+
// INVALID-TYPE-DAG: Decl[Enum]/OtherModule[errors]: InvalidEnum[#InvalidEnum#];
35+
// INVALID-TYPE-DAG: Decl[Class]/OtherModule[errors]: InvalidClass[#InvalidClass#];
36+
// INVALID-TYPE-DAG: Decl[Struct]/OtherModule[errors]: InvalidGenericStruct[#InvalidGenericStruct#];
37+
// INVALID-TYPE-DAG: Decl[Struct]/OtherModule[errors]: InvalidStruct[#InvalidStruct#];
38+
// INVALID-TYPE-DAG: Decl[TypeAlias]/OtherModule[errors]: InvalidAlias[#InvalidAlias#];
39+
// INVALID-TYPE-DAG: Decl[Class]/OtherModule[errors]: InvalidClassSub1[#InvalidClassSub1#];
40+
// INVALID-TYPE-DAG: Decl[Class]/OtherModule[errors]: InvalidClassSub2[#InvalidClassSub2#];
41+
// INVALID-TYPE-DAG: Decl[Protocol]/OtherModule[errors]: InvalidProtocol[#InvalidProtocol#];
42+
// INVALID-TYPE: End completions
43+
}
44+
45+
func testInvalidTopLevelCompletion() {
46+
#^INVALID-TOP^#
47+
// INVALID-TOP: Begin completions
48+
// INVALID-TOP-DAG: Decl[Enum]/OtherModule[errors]: InvalidEnum[#InvalidEnum#];
49+
// INVALID-TOP-DAG: Decl[Class]/OtherModule[errors]: InvalidClass[#InvalidClass#];
50+
// INVALID-TOP-DAG: Decl[FreeFunction]/OtherModule[errors]: invalidGenericFuncBody({#param: T#})[#T#];
51+
// INVALID-TOP-DAG: Decl[FreeFunction]/OtherModule[errors]: invalidPartialFunc()[#Void#];
52+
// INVALID-TOP-DAG: Decl[FreeFunction]/OtherModule[errors]: invalidFuncBody()[#Void#];
53+
// INVALID-TOP-DAG: Decl[GlobalVar]/OtherModule[errors]: invalidGlobalClosureBody[#<<error type>>#];
54+
// INVALID-TOP-DAG: Decl[FreeFunction]/OtherModule[errors]: invalidFuncSignature()[#Void#];
55+
// INVALID-TOP-DAG: Decl[GlobalVar]/OtherModule[errors]: invalidGlobalMissingInit[#String#];
56+
// INVALID-TOP-DAG: Decl[Struct]/OtherModule[errors]: InvalidGenericStruct[#InvalidGenericStruct#];
57+
// INVALID-TOP-DAG: Decl[Struct]/OtherModule[errors]: InvalidStruct[#InvalidStruct#];
58+
// INVALID-TOP-DAG: Decl[FreeFunction]/OtherModule[errors]: typeUsesFunc({#pe: InvalidEnum#}, {#pa: <<error type>>#}, {#pp: InvalidProtocol#}, {#ps: InvalidStruct#}, {#pg: <<error type>>#}, {#pc: InvalidClass#})[#Int#];
59+
// INVALID-TOP-DAG: Decl[GlobalVar]/OtherModule[errors]: invalidGlobalKeypath[#InvalidStruct.Type#];
60+
// INVALID-TOP-DAG: Decl[TypeAlias]/OtherModule[errors]: InvalidAlias[#InvalidAlias#];
61+
// INVALID-TOP-DAG: Decl[FreeFunction]/OtherModule[errors]: invalidGenericFuncType({#param: T#})[#<<error type>>#];
62+
// INVALID-TOP-DAG: Decl[FreeFunction]/OtherModule[errors]: invalidFuncType()[#<<error type>>#];
63+
// INVALID-TOP-DAG: Decl[GlobalVar]/OtherModule[errors]: invalidGlobalClosureType[#() -> ()#];
64+
// INVALID-TOP-DAG: Decl[Class]/OtherModule[errors]: InvalidClassSub1[#InvalidClassSub1#];
65+
// INVALID-TOP-DAG: Decl[Class]/OtherModule[errors]: InvalidClassSub2[#InvalidClassSub2#];
66+
// INVALID-TOP-DAG: Decl[Protocol]/OtherModule[errors]: InvalidProtocol[#InvalidProtocol#];
67+
// INVALID-TOP-DAG: Decl[FreeFunction]/OtherModule[errors]: invalidFuncThrows()[' throws'][#<<error type>>#];
68+
// INVALID-TOP: End completions
1369
}
1470

1571
// RUN: %empty-directory(%t)
16-
// RUN: %target-swift-frontend -emit-module -experimental-allow-module-with-compiler-errors -primary-file %S/Inputs/errors-a.swift %S/Inputs/errors-b.swift -module-name errors -o %t/errors.a.swiftmodule
17-
// RUN: %target-swift-frontend -emit-module -experimental-allow-module-with-compiler-errors %S/Inputs/errors-a.swift -primary-file %S/Inputs/errors-b.swift -module-name errors -o %t/errors.b.swiftmodule
18-
// RUN: %target-swift-frontend -merge-modules -emit-module -experimental-allow-module-with-compiler-errors %t/errors.a.swiftmodule %t/errors.b.swiftmodule -module-name errors -o %t/errors.swiftmodule
72+
73+
// RUN: %target-swift-frontend -emit-module -experimental-allow-module-with-compiler-errors -primary-file %S/Inputs/errors-a.swift %S/Inputs/errors-b.swift %S/Inputs/errors-c.swift -module-name errors -o %t/errors.a.swiftmodule
74+
// RUN: %target-swift-frontend -emit-module -experimental-allow-module-with-compiler-errors %S/Inputs/errors-a.swift -primary-file %S/Inputs/errors-b.swift %S/Inputs/errors-c.swift -module-name errors -o %t/errors.b.swiftmodule
75+
// RUN: %target-swift-frontend -emit-module -experimental-allow-module-with-compiler-errors %S/Inputs/errors-a.swift %S/Inputs/errors-b.swift -primary-file %S/Inputs/errors-c.swift -module-name errors -o %t/errors.c.swiftmodule
76+
// RUN: %target-swift-frontend -merge-modules -emit-module -experimental-allow-module-with-compiler-errors %t/errors.a.swiftmodule %t/errors.b.swiftmodule %t/errors.c.swiftmodule -module-name errors -o %t/errors.swiftmodule
1977

2078
// Read the module back in to make sure it can be deserialized
2179
// RUN: %target-swift-ide-test -print-module -source-filename dummy -module-to-print errors -I %t | %FileCheck %s
@@ -47,8 +105,8 @@ func foo() {
47105
// CHECK: typealias Item = <<error type>>
48106
// CHECK: let memberA: Int
49107
// CHECK: let memberB: <<error type>>
50-
// CHECK: var memberC: <<error type>> { get }
51-
// CHECK: lazy var memberD: <<error type>> { mutating get }
108+
// CHECK: var memberC: <<error type>>
109+
// CHECK: lazy var memberD: <<error type>>
52110
// CHECK: var memberE: <<error type>>
53111
// CHECK: mutating func set(item: <<error type>>)
54112
// CHECK: func invalidFuncBody()
@@ -64,62 +122,23 @@ func foo() {
64122
// CHECK: func invalidPartialFunc()
65123
// CHECK: func typeUsesFunc
66124

125+
// Check completions
126+
// RUN: %target-swift-ide-test -batch-code-completion -source-filename %s -filecheck %raw-FileCheck -completion-output-dir %t-completions -I %t
127+
67128
// Check cursor info for the various symbols
68129
// RUN: %sourcekitd-test -req=cursor -pos=4:3 %s -- -I %t -target %target-triple %s | %FileCheck %s -check-prefix=CHECK-GLOBAL
69130
// CHECK-GLOBAL: source.lang.swift.ref.var.global
70131
// CHECK-GLOBAL: invalidGlobalMissingInit
71132

72-
// RUN: %sourcekitd-test -req=cursor -pos=6:12 %s -- -I %t -target %target-triple %s | %FileCheck %s -check-prefix=CHECK-STRUCT
73-
// CHECK-STRUCT: source.lang.swift.ref.struct
74-
// CHECK-STRUCT: InvalidStruct
75-
76-
// : %sourcekitd-test -req=cursor -pos=7:7 %s -- -I %t -target %target-triple %s | %FileCheck %s -check-prefix=CHECK-MEMBER
77-
// CHECK-MEMBER: source.lang.swift.ref.var.instance
78-
// CHECK-MEMBER: memberB
79-
80133
// RUN: %sourcekitd-test -req=cursor -pos=8:3 %s -- -I %t -target %target-triple %s | %FileCheck %s -check-prefix=CHECK-FUNC
81134
// CHECK-FUNC: source.lang.swift.ref.function.free
82135
// CHECK-FUNC: invalidPartialFunc
83136

84-
// Check completions
85-
// RUN: %sourcekitd-test -req=complete -pos=9:7 %s -- -I %t -target %target-triple %s | %FileCheck %s -check-prefix=CHECK-MEMBER-COMPLETE
86-
// CHECK-MEMBER-COMPLETE: key.name: "add(
87-
// CHECK-MEMBER-COMPLETE: key.name: "get(
88-
// CHECK-MEMBER-COMPLETE: key.name: "memberA"
89-
// CHECK-MEMBER-COMPLETE: key.name: "memberB"
90-
// CHECK-MEMBER-COMPLETE: key.name: "memberC"
91-
// CHECK-MEMBER-COMPLETE: key.name: "memberD"
92-
// CHECK-MEMBER-COMPLETE: key.name: "memberE"
93-
// CHECK-MEMBER-COMPLETE: key.name: "set(
94-
95-
// RUN: %sourcekitd-test -req=complete -pos=11:11 %s -- -I %t -target %target-triple %s | %FileCheck %s -check-prefix=CHECK-TYPE-COMPLETE
96-
// CHECK-TYPE-COMPLETE: key.name: "InvalidAlias"
97-
// CHECK-TYPE-COMPLETE: key.name: "InvalidClass"
98-
// CHECK-TYPE-COMPLETE: key.name: "InvalidClassSub1"
99-
// CHECK-TYPE-COMPLETE: key.name: "InvalidClassSub2"
100-
// CHECK-TYPE-COMPLETE: key.name: "InvalidEnum"
101-
// CHECK-TYPE-COMPLETE: key.name: "InvalidGenericStruct"
102-
// CHECK-TYPE-COMPLETE: key.name: "InvalidProtocol"
103-
// CHECK-TYPE-COMPLETE: key.name: "InvalidStruct"
137+
// RUN: %sourcekitd-test -req=cursor -pos=12:12 %s -- -I %t -target %target-triple %s | %FileCheck %s -check-prefix=CHECK-STRUCT
138+
// CHECK-STRUCT: source.lang.swift.ref.struct
139+
// CHECK-STRUCT: InvalidStruct
104140

105-
// RUN: %sourcekitd-test -req=complete -pos=12:1 %s -- -I %t -target %target-triple %s | %FileCheck %s -check-prefix=CHECK-GLOBAL-COMPLETE
106-
// CHECK-GLOBAL-COMPLETE: key.name: "InvalidAlias"
107-
// CHECK-GLOBAL-COMPLETE: key.name: "InvalidClass"
108-
// CHECK-GLOBAL-COMPLETE: key.name: "InvalidClassSub1"
109-
// CHECK-GLOBAL-COMPLETE: key.name: "InvalidClassSub2"
110-
// CHECK-GLOBAL-COMPLETE: key.name: "InvalidEnum"
111-
// CHECK-GLOBAL-COMPLETE: key.name: "invalidFuncBody(
112-
// CHECK-GLOBAL-COMPLETE: key.name: "invalidFuncSignature(
113-
// CHECK-GLOBAL-COMPLETE: key.name: "invalidFuncThrows(
114-
// CHECK-GLOBAL-COMPLETE: key.name: "invalidFuncType(
115-
// CHECK-GLOBAL-COMPLETE: key.name: "invalidGenericFuncBody(
116-
// CHECK-GLOBAL-COMPLETE: key.name: "invalidGenericFuncType(
117-
// CHECK-GLOBAL-COMPLETE: key.name: "InvalidGenericStruct"
118-
// CHECK-GLOBAL-COMPLETE: key.name: "invalidGlobalClosureBody"
119-
// CHECK-GLOBAL-COMPLETE: key.name: "invalidGlobalClosureType
120-
// CHECK-GLOBAL-COMPLETE: key.name: "invalidGlobalKeypath
121-
// CHECK-GLOBAL-COMPLETE: key.name: "invalidGlobalMissingInit
122-
// CHECK-GLOBAL-COMPLETE: key.name: "invalidPartialFunc(
123-
// CHECK-GLOBAL-COMPLETE: key.name: "InvalidProtocol"
124-
// CHECK-GLOBAL-COMPLETE: key.name: "InvalidStruct"
125-
// CHECK-GLOBAL-COMPLETE: key.name: "typeUsesFunc(
141+
// Currently doesn't work for any members with invalid types, even within the same module: rdar://71514163
142+
// RUN: %sourcekitd-test -req=cursor -pos=13:7 %s -- -I %t -target %target-triple %s | not %FileCheck %s -check-prefix=CHECK-MEMBER
143+
// CHECK-MEMBER: source.lang.swift.ref.var.instance
144+
// CHECK-MEMBER: memberB

tools/swift-ast-script/ASTScriptEvaluator.cpp

+5-2
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,11 @@ class ASTScriptWalker : public ASTWalker {
9292
if (auto module = dyn_cast<ModuleDecl>(dc)) {
9393
out << module->getName() << ".";
9494
} else if (auto extension = dyn_cast<ExtensionDecl>(dc)) {
95-
printDecl(out, extension->getExtendedNominal());
96-
out << ".";
95+
auto *extended = extension->getExtendedNominal();
96+
if (extended) {
97+
printDecl(out, extended);
98+
out << ".";
99+
}
97100
} else if (auto decl = dyn_cast_or_null<ValueDecl>(dc->getAsDecl())) {
98101
printDecl(out, decl);
99102
out << ".";

0 commit comments

Comments
 (0)