Skip to content

Commit 5693003

Browse files
committed
[Parse] Fix parsing protocol<Any>
Fix crash while constructing diagnostic fix-it for deprecated syntax. (because of accessing elements in empty SmallVector) ``` 0 swift 0x000000010a1682ed PrintStackTraceSignalHandler(void*) + 45 1 swift 0x000000010a167d36 SignalHandler(int) + 470 2 libsystem_platform.dylib 0x00007fff9452852a _sigtramp + 26 3 libsystem_platform.dylib 000000000000000000 _sigtramp + 1806531312 4 swift 0x0000000107c6904a swift::Lexer::getTokenAtLocation(swift::SourceManager const&, swift::SourceLoc) + 490 5 swift 0x0000000107cde0f2 swift::Parser::parseTypeIdentifierOrTypeComposition() + 1698 6 swift 0x0000000107cdf2ec swift::Parser::parseType(swift::Diag<>, bool) + 380 7 swift 0x0000000107c8d9e0 swift::Parser::parseExprSequence(swift::Diag<>, bool, bool) + 1456 8 swift 0x0000000107c8d3c4 swift::Parser::parseExprImpl(swift::Diag<>, bool) + 148 9 swift 0x0000000107ccdfed swift::Parser::parseExprOrStmt(swift::ASTNode&) + 429 10 swift 0x0000000107cd5212 swift::Parser::parseBraceItems(llvm::SmallVectorImpl<swift::ASTNode>&, swift::BraceItemListKind, swift::BraceItemListKind) + 2994 11 swift 0x0000000107c69598 swift::Parser::parseTopLevel() + 184 12 swift 0x0000000107ca3a4f swift::parseIntoSourceFile(swift::SourceFile&, unsigned int, bool*, swift::SILParserState*, swift::PersistentParserState*, swift::DelayedParsingCallbacks*) + 239 13 swift 0x0000000107ac77a4 swift::CompilerInstance::performSema() + 5156 14 swift 0x000000010756ef1d performCompile(swift::CompilerInstance&, swift::CompilerInvocation&, llvm::ArrayRef<char const*>, int&, swift::FrontendObserver*) + 2765 15 swift 0x000000010756c175 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 17029 16 swift 0x00000001075293bd main + 8685 17 libdyld.dylib 0x00007fff998ea5ad start + 1 Stack dump: 0. Program arguments: /Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift -frontend -interpret test.swift -target x86_64-apple-macosx10.9 -enable-objc-interop -sdk /Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk -color-diagnostics -module-name test 1. With parser at source location: test.swift:2:1 Segmentation fault: 11 ```
1 parent 44f13d8 commit 5693003

File tree

2 files changed

+29
-32
lines changed

2 files changed

+29
-32
lines changed

lib/Parse/ParseType.cpp

Lines changed: 27 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -410,30 +410,20 @@ ParserResult<TypeRepr> Parser::parseTypeIdentifierOrTypeComposition() {
410410
SourceLoc ProtocolLoc = consumeToken(tok::kw_protocol);
411411
SourceLoc LAngleLoc = consumeStartingLess();
412412

413-
// Check for empty protocol composition.
414-
if (startsWithGreater(Tok)) {
415-
SourceLoc RAngleLoc = consumeStartingGreater();
416-
auto AnyRange = SourceRange(ProtocolLoc, RAngleLoc);
417-
418-
// Warn that 'protocol<>' is deprecated and offer to
419-
// replace with the 'Any' keyword
420-
diagnose(LAngleLoc, diag::deprecated_any_composition)
421-
.fixItReplace(AnyRange, "Any");
422-
423-
return makeParserResult(
424-
ProtocolCompositionTypeRepr::createEmptyComposition(Context, ProtocolLoc));
425-
}
426-
427413
// Parse the type-composition-list.
428414
ParserStatus Status;
429415
SmallVector<IdentTypeRepr *, 4> Protocols;
430-
do {
431-
// Parse the type-identifier.
432-
ParserResult<TypeRepr> Protocol = parseTypeIdentifier();
433-
Status |= Protocol;
434-
if (auto *ident = dyn_cast_or_null<IdentTypeRepr>(Protocol.getPtrOrNull()))
435-
Protocols.push_back(ident);
436-
} while (consumeIf(tok::comma));
416+
bool IsEmpty = startsWithGreater(Tok);
417+
if (!IsEmpty) {
418+
do {
419+
// Parse the type-identifier.
420+
ParserResult<TypeRepr> Protocol = parseTypeIdentifier();
421+
Status |= Protocol;
422+
if (auto *ident = dyn_cast_or_null<IdentTypeRepr>(
423+
Protocol.getPtrOrNull()))
424+
Protocols.push_back(ident);
425+
} while (consumeIf(tok::comma));
426+
}
437427

438428
// Check for the terminating '>'.
439429
SourceLoc RAngleLoc = PreviousLoc;
@@ -456,17 +446,21 @@ ParserResult<TypeRepr> Parser::parseTypeIdentifierOrTypeComposition() {
456446
if (Status.isSuccess()) {
457447
// Only if we have complete protocol<...> construct, diagnose deprecated.
458448

459-
auto extractText = [&](IdentTypeRepr *Ty) -> StringRef {
460-
auto SourceRange = Ty->getSourceRange();
461-
return SourceMgr.extractText(
462-
Lexer::getCharSourceRangeFromSourceRange(SourceMgr, SourceRange));
463-
};
464449
SmallString<32> replacement;
465-
auto Begin = Protocols.begin();
466-
replacement += extractText(*Begin);
467-
while (++Begin != Protocols.end()) {
468-
replacement += " & ";
450+
if (Protocols.empty()) {
451+
replacement = "Any";
452+
} else {
453+
auto extractText = [&](IdentTypeRepr *Ty) -> StringRef {
454+
auto SourceRange = Ty->getSourceRange();
455+
return SourceMgr.extractText(
456+
Lexer::getCharSourceRangeFromSourceRange(SourceMgr, SourceRange));
457+
};
458+
auto Begin = Protocols.begin();
469459
replacement += extractText(*Begin);
460+
while (++Begin != Protocols.end()) {
461+
replacement += " & ";
462+
replacement += extractText(*Begin);
463+
}
470464
}
471465

472466
// Copy trailing content after '>' to the replacement string.
@@ -481,8 +475,9 @@ ParserResult<TypeRepr> Parser::parseTypeIdentifierOrTypeComposition() {
481475

482476
// Replace 'protocol<T1, T2>' with 'T1 & T2'
483477
diagnose(ProtocolLoc,
484-
Protocols.size() > 1 ? diag::deprecated_protocol_composition
485-
: diag::deprecated_protocol_composition_single)
478+
IsEmpty ? diag::deprecated_any_composition :
479+
Protocols.size() > 1 ? diag::deprecated_protocol_composition :
480+
diag::deprecated_protocol_composition_single)
486481
.highlight(composition->getSourceRange())
487482
.fixItReplace(composition->getSourceRange(), replacement);
488483
}

test/type/protocol_composition.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,5 @@ typealias B4 = protocol<P1 , P2> // expected-warning {{'protocol<...>' compositi
133133
typealias C1 = protocol<Any, P1> // expected-warning {{'protocol<...>' composition syntax is deprecated and not needed here}} {{16-33=P1}}
134134
typealias C2 = protocol<P1, Any> // expected-warning {{'protocol<...>' composition syntax is deprecated and not needed here}} {{16-33=P1}}
135135
typealias D = protocol<P1> // expected-warning {{'protocol<...>' composition syntax is deprecated and not needed here}} {{15-27=P1}}
136+
typealias E = protocol<Any> // expected-warning {{'protocol<...>' composition syntax is deprecated and not needed here}} {{15-28=Any}}
137+
typealias F = protocol<Any, Any> // expected-warning {{'protocol<...>' composition syntax is deprecated and not needed here}} {{15-33=Any}}

0 commit comments

Comments
 (0)