Skip to content

Commit bf2ca1a

Browse files
committed
Sema/AST: Don't crash when stdlib declarations are missing
I don't have reduced test cases. The original test cases were a series of frontend invocations in -parse-stdlib mode. While the original bugs seem to have been fixed, while verifying I found a few places where we weren't checking for null decls property in the ASTContext. Probably not too useful to check this in, but I don't see it causing any harm, either.
1 parent edfaf7f commit bf2ca1a

11 files changed

+54
-19
lines changed

lib/AST/ASTContext.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -701,7 +701,10 @@ CanType ASTContext::getAnyObjectType() const {
701701
}
702702

703703
CanType ASTContext::getNeverType() const {
704-
return getNeverDecl()->getDeclaredType()->getCanonicalType();
704+
auto neverDecl = getNeverDecl();
705+
if (!neverDecl)
706+
return CanType();
707+
return neverDecl->getDeclaredType()->getCanonicalType();
705708
}
706709

707710
TypeAliasDecl *ASTContext::getVoidDecl() const {
@@ -885,6 +888,9 @@ FuncDecl *ASTContext::getEqualIntDecl() const {
885888
if (Impl.EqualIntDecl)
886889
return Impl.EqualIntDecl;
887890

891+
if (!getIntDecl() || !getBoolDecl())
892+
return nullptr;
893+
888894
auto intType = getIntDecl()->getDeclaredType();
889895
auto boolType = getBoolDecl()->getDeclaredType();
890896
SmallVector<ValueDecl *, 30> equalFuncs;

lib/AST/Builtins.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,8 +1062,12 @@ static ValueDecl *getIntToFPWithOverflowOperation(ASTContext &Context,
10621062

10631063
static ValueDecl *getUnreachableOperation(ASTContext &Context,
10641064
Identifier Id) {
1065+
auto NeverTy = Context.getNeverType();
1066+
if (!NeverTy)
1067+
return nullptr;
1068+
10651069
// () -> Never
1066-
return getBuiltinFunction(Id, {}, Context.getNeverType());
1070+
return getBuiltinFunction(Id, {}, NeverTy);
10671071
}
10681072

10691073
static ValueDecl *getOnceOperation(ASTContext &Context,
@@ -1295,8 +1299,11 @@ getSwiftFunctionTypeForIntrinsic(unsigned iid, ArrayRef<Type> TypeArgs,
12951299
llvm::Intrinsic::getAttributes(getGlobalLLVMContext(), ID);
12961300
Info = FunctionType::ExtInfo();
12971301
if (attrs.hasAttribute(llvm::AttributeList::FunctionIndex,
1298-
llvm::Attribute::NoReturn))
1302+
llvm::Attribute::NoReturn)) {
12991303
ResultTy = Context.getNeverType();
1304+
if (!ResultTy)
1305+
return false;
1306+
}
13001307

13011308
return true;
13021309
}

lib/ClangImporter/ImportDecl.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2439,6 +2439,8 @@ namespace {
24392439
ProtocolDecl *protocols[]
24402440
= {cxt.getProtocol(KnownProtocolKind::RawRepresentable),
24412441
cxt.getProtocol(KnownProtocolKind::Equatable)};
2442+
if (!protocols[0] || !protocols[1])
2443+
return nullptr;
24422444

24432445
auto options = getDefaultMakeStructRawValuedOptions();
24442446
options |= MakeStructRawValuedFlags::MakeUnlabeledValueInit;

lib/ClangImporter/ImportType.cpp

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,10 @@ namespace {
202202
// of the exit(3) libc function as "func exit(Int32)", not as
203203
// "func exit(CInt)".
204204
static Type unwrapCType(Type T) {
205-
if (auto *NAT = dyn_cast_or_null<NameAliasType>(T.getPointer()))
205+
// Handle missing or invalid stdlib declarations
206+
if (!T || T->hasError())
207+
return Type();
208+
if (auto *NAT = dyn_cast<NameAliasType>(T.getPointer()))
206209
return NAT->getSinglyDesugaredType();
207210
return T;
208211
}
@@ -334,11 +337,14 @@ namespace {
334337
// that 'Unsafe[Mutable]Pointer<T>' implicitly converts to
335338
// 'Unsafe[Mutable]RawPointer' for interoperability.
336339
if (pointeeQualType->isVoidType()) {
337-
return {
338-
(quals.hasConst() ? Impl.SwiftContext.getUnsafeRawPointerDecl()
339-
: Impl.SwiftContext.getUnsafeMutableRawPointerDecl())
340-
->getDeclaredType(),
341-
ImportHint::OtherPointer};
340+
auto pointerTypeDecl =
341+
(quals.hasConst()
342+
? Impl.SwiftContext.getUnsafeRawPointerDecl()
343+
: Impl.SwiftContext.getUnsafeMutableRawPointerDecl());
344+
if (!pointerTypeDecl)
345+
return Type();
346+
return {pointerTypeDecl->getDeclaredType(),
347+
ImportHint::OtherPointer};
342348
}
343349

344350
// All other C pointers to concrete types map to
@@ -359,9 +365,13 @@ namespace {
359365

360366
// If the pointed-to type is unrepresentable in Swift, import as
361367
// OpaquePointer.
362-
if (!pointeeType)
363-
return {Impl.SwiftContext.getOpaquePointerDecl()->getDeclaredType(),
368+
if (!pointeeType) {
369+
auto opaquePointer = Impl.SwiftContext.getOpaquePointerDecl();
370+
if (!opaquePointer)
371+
return Type();
372+
return {opaquePointer->getDeclaredType(),
364373
ImportHint::OtherPointer};
374+
}
365375

366376
if (pointeeQualType->isFunctionType()) {
367377
auto funcTy = pointeeType->castTo<FunctionType>();

lib/Sema/CSDiag.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3792,12 +3792,15 @@ static bool trySequenceSubsequenceConversionFixIts(InFlightDiagnostic &diag,
37923792
ConstraintSystem &CS,
37933793
Type fromType, Type toType,
37943794
Expr *expr) {
3795-
if (CS.TC.Context.getStdlibModule() == nullptr) {
3795+
if (CS.TC.Context.getStdlibModule() == nullptr)
37963796
return false;
3797-
}
3797+
37983798
auto String = CS.TC.getStringType(CS.DC);
37993799
auto Substring = CS.TC.getSubstringType(CS.DC);
38003800

3801+
if (!String || !Substring)
3802+
return false;
3803+
38013804
/// FIXME: Remove this flag when void subscripts are implemented.
38023805
/// Make this unconditional and remove the if statement.
38033806
if (CS.TC.getLangOpts().FixStringToSubstringConversions) {

lib/Sema/TypeCheckAttr.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,9 @@ class AttributeEarlyChecker : public AttributeVisitor<AttributeEarlyChecker> {
164164
diag.fixItInsert(resultLoc, fix);
165165
}
166166

167-
FD->getBodyResultTypeLoc() = TypeLoc::withoutLoc(
168-
TC.Context.getNeverType());
167+
auto neverType = TC.Context.getNeverType();
168+
if (neverType)
169+
FD->getBodyResultTypeLoc() = TypeLoc::withoutLoc(neverType);
169170
}
170171
}
171172

lib/Sema/TypeCheckPattern.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1503,7 +1503,9 @@ bool TypeChecker::coercePatternToType(Pattern *&P, DeclContext *dc, Type type,
15031503
}
15041504

15051505
EnumElementDecl *elementDecl = Context.getOptionalSomeDecl(optionalKind);
1506-
assert(elementDecl && "missing optional some decl?!");
1506+
if (!elementDecl)
1507+
return true;
1508+
15071509
OP->setElementDecl(elementDecl);
15081510

15091511
Pattern *sub = OP->getSubPattern();

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5608,6 +5608,8 @@ bool TypeChecker::useObjectiveCBridgeableConformances(DeclContext *dc,
56085608
auto keyType = args[0];
56095609
auto *hashableProto =
56105610
TC.Context.getProtocol(KnownProtocolKind::Hashable);
5611+
if (!hashableProto)
5612+
return Action::Stop;
56115613

56125614
auto result = TC.conformsToProtocol(
56135615
keyType, hashableProto, DC, options,

lib/Sema/TypeCheckStmt.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,9 @@ static void tryDiagnoseUnnecessaryCastOverOptionSet(ASTContext &Ctx,
237237
auto *NTD = ResultType->getAnyNominal();
238238
if (!NTD)
239239
return;
240-
auto optionSetType = dyn_cast<ProtocolDecl>(Ctx.getOptionSetDecl());
240+
auto optionSetType = dyn_cast_or_null<ProtocolDecl>(Ctx.getOptionSetDecl());
241+
if (!optionSetType)
242+
return;
241243
SmallVector<ProtocolConformance *, 4> conformances;
242244
if (!(optionSetType &&
243245
NTD->lookupConformance(module, optionSetType, conformances)))

validation-test/SIL/crashers/016-swift-typechecker-typecheckfunctionbodyuntil.sil

Lines changed: 0 additions & 2 deletions
This file was deleted.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// RUN: not %target-sil-opt %s
2+
func n->a{return:}class a

0 commit comments

Comments
 (0)