Skip to content

Commit f7aa3aa

Browse files
committed
Parse syntactically invalid module selectors early
When a module selector does not start with an identifier, we often end up trying to parse whatever token it *does* have there as something else, which doesn't handle the module selector well. Correct this by speculatively parsing invalid selectors in various places.
1 parent ec18e47 commit f7aa3aa

File tree

6 files changed

+164
-5
lines changed

6 files changed

+164
-5
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ ERROR(forbidden_extended_escaping_string,none,
9696
ERROR(expected_identifier_in_module_selector,none,
9797
"expected identifier in module selector", ())
9898
ERROR(module_selector_not_allowed,none,
99-
"%select{%error|name in %1 declaration|captured variable name|"
99+
"%select{%error|%error|name in %1 declaration|captured variable name|"
100100
"parameter name|generic parameter name|argument label|SPI group|"
101101
"Objective-C name|name of sibling declaration|precedence group name|"
102102
"attribute parameter value|%error}0 cannot be qualified with a module "

include/swift/Parse/Parser.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1807,11 +1807,16 @@ class Parser {
18071807
bool isAttr = false);
18081808

18091809
/// The reason we are trying to parse a module selector. Other than
1810-
/// \c Allowed, all reasons indicate an error should be emitted.
1810+
/// \c Allowed and \c InvalidOnly, all reasons indicate an error should be
1811+
/// emitted.
18111812
enum class ModuleSelectorReason : uint8_t {
18121813
/// Use of a module selector is allowed.
18131814
Allowed,
18141815

1816+
/// Only parse (and diagnose) invalid module selectors here; if the module
1817+
/// selector is valid, return \c None and leave it for later.
1818+
InvalidOnly,
1819+
18151820
/// Not allowed; this is the name of a declaration. The string parameter
18161821
/// describes the declaration in question (e.g. a class, struct, etc.).
18171822
///

lib/Parse/Lexer.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -819,9 +819,12 @@ static bool isLeftBound(const char *tokBegin, const char *bufferBegin) {
819819
static bool isRightBound(const char *tokEnd, bool isLeftBound,
820820
const char *codeCompletionPtr) {
821821
switch (*tokEnd) {
822+
case ':': // ':' is an expression separator; '::' is not
823+
return tokEnd[1] == ':';
824+
822825
case ' ': case '\r': case '\n': case '\t': // whitespace
823826
case ')': case ']': case '}': // closing delimiters
824-
case ',': case ';': case ':': // expression separators
827+
case ',': case ';': // expression separators
825828
return false;
826829

827830
case '\0':

lib/Parse/ParseExpr.cpp

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,9 @@ ParserResult<Expr> Parser::parseExprSequenceElement(Diag<> message,
613613
/// '&' expr-unary(Mode)
614614
///
615615
ParserResult<Expr> Parser::parseExprUnary(Diag<> Message, bool isExprBasic) {
616+
// If we have an invalid module selector, consume that first.
617+
parseModuleSelector(ModuleSelectorReason::InvalidOnly);
618+
616619
UnresolvedDeclRefExpr *Operator;
617620

618621
// First check to see if we have the start of a regex literal `/.../`.
@@ -1270,6 +1273,8 @@ Parser::parseExprPostfixSuffix(ParserResult<Expr> Result, bool isExprBasic,
12701273
Tok.setKind(tok::period);
12711274
consumeToken();
12721275

1276+
parseModuleSelector(ModuleSelectorReason::InvalidOnly);
1277+
12731278
// Handle "x.42" - a tuple index.
12741279
if (Tok.is(tok::integer_literal)) {
12751280
DeclNameRef name(Context.getIdentifier(Tok.getText()));
@@ -1641,6 +1646,9 @@ ParserResult<Expr> Parser::parseExprPostfix(Diag<> ID, bool isExprBasic) {
16411646
/// expr-selector
16421647
///
16431648
ParserResult<Expr> Parser::parseExprPrimary(Diag<> ID, bool isExprBasic) {
1649+
// If we have an invalid module selector, consume that first.
1650+
parseModuleSelector(ModuleSelectorReason::InvalidOnly);
1651+
16441652
switch (Tok.getKind()) {
16451653
case tok::integer_literal: {
16461654
StringRef Text = copyAndStripUnderscores(Tok.getText());
@@ -2277,6 +2285,13 @@ parseModuleSelector(ModuleSelectorReason reason, StringRef declKindName) {
22772285
if (peekToken().isNot(tok::colon_colon) && Tok.isNot(tok::colon_colon))
22782286
return std::nullopt;
22792287

2288+
// Leave these paired tokens to be diagnosed by a future call to
2289+
// `parseModuleSelector()` at the next token, rather than consuming them as
2290+
// malformed module names and causing more errors later in the parser.
2291+
if (Tok.isAny(tok::l_paren, tok::l_brace, tok::l_angle, tok::l_square,
2292+
tok::r_paren, tok::r_brace, tok::r_angle, tok::r_square))
2293+
return std::nullopt;
2294+
22802295
// We will parse the selector whether or not it's allowed, then early return
22812296
// if it's disallowed, then diagnose any other errors in what we parsed. This
22822297
// will make sure we always consume the module selector's tokens, but don't
@@ -2285,8 +2300,15 @@ parseModuleSelector(ModuleSelectorReason reason, StringRef declKindName) {
22852300

22862301
SourceLoc nameLoc;
22872302
Identifier moduleName;
2288-
if (Tok.is(tok::identifier))
2303+
if (Tok.is(tok::identifier)) {
2304+
// If we are only supposed to consume invalid selectors, leave this for
2305+
// later.
2306+
if (reason == ModuleSelectorReason::InvalidOnly) {
2307+
return std::nullopt;
2308+
}
2309+
22892310
nameLoc = consumeIdentifier(moduleName, /*diagnoseDollarPrefix=*/true);
2311+
}
22902312
else if (Tok.is(tok::colon_colon))
22912313
// Let nameLoc and colonColonLoc both point to the tok::colon_colon.
22922314
nameLoc = Tok.getLoc();
@@ -2295,7 +2317,8 @@ parseModuleSelector(ModuleSelectorReason reason, StringRef declKindName) {
22952317

22962318
auto colonColonLoc = consumeToken(tok::colon_colon);
22972319

2298-
if (reason != ModuleSelectorReason::Allowed) {
2320+
if (reason != ModuleSelectorReason::Allowed &&
2321+
reason != ModuleSelectorReason::InvalidOnly) {
22992322
diagnose(colonColonLoc, diag::module_selector_not_allowed,
23002323
(uint8_t)reason, declKindName);
23012324

lib/Parse/ParseType.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,9 @@ ParserResult<TypeRepr> Parser::parseSILBoxType(GenericParamList *generics,
402402
///
403403
ParserResult<TypeRepr> Parser::parseTypeScalar(
404404
Diag<> MessageID, ParseTypeReason reason) {
405+
// If we have an invalid module selector, consume that first.
406+
parseModuleSelector(ModuleSelectorReason::InvalidOnly);
407+
405408
// Start a context for creating type syntax.
406409
ParserStatus status;
407410

test/NameLookup/module_selector.swift

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,131 @@ func badModuleNames() {
405405
// expected-error@-1 {{'MyChildType' is not a member type of struct 'ModuleSelectorTestingKit.A'}}
406406
}
407407

408+
struct BadModuleSelectorSyntax { // expected-note {{in declaration of 'BadModuleSelectorSyntax'}}
409+
var a: ::Int
410+
// expected-error@-1 {{expected identifier in module selector}}
411+
412+
var b: (::Int)
413+
// expected-error@-1 {{expected identifier in module selector}}
414+
415+
var c: *::Int
416+
// expected-error@-1 {{expected identifier in module selector}}
417+
418+
var d: _::Int
419+
// expected-error@-1 {{expected identifier in module selector}}
420+
421+
var e: Self::Int
422+
// expected-error@-1 {{expected identifier in module selector}}
423+
424+
var f: self::Int
425+
// expected-error@-1 {{expected identifier in module selector}}
426+
427+
var g: inout::Int
428+
// expected-error@-1 {{expected identifier in module selector}}
429+
430+
var h: Any::Int
431+
// expected-error@-1 {{expected identifier in module selector}}
432+
433+
var aArray: [::Int]
434+
// expected-error@-1 {{expected identifier in module selector}}
435+
436+
var bArray: [(::Int)]
437+
// expected-error@-1 {{expected identifier in module selector}}
438+
439+
var cArray: [*::Int]
440+
// expected-error@-1 {{expected identifier in module selector}}
441+
442+
var dArray: [_::Int]
443+
// expected-error@-1 {{expected identifier in module selector}}
444+
445+
var eArray: [Self::Int]
446+
// expected-error@-1 {{expected identifier in module selector}}
447+
448+
var fArray: [self::Int]
449+
// expected-error@-1 {{expected identifier in module selector}}
450+
451+
var gArray: [inout::Int]
452+
// expected-error@-1 {{expected identifier in module selector}}
453+
454+
var hArray: [Any::Int]
455+
// expected-error@-1 {{expected identifier in module selector}}
456+
457+
var aIndex: String.::Index
458+
// expected-error@-1 {{expected identifier in module selector}}
459+
460+
// FIXME: This gets interpreted as a single `.*` operator; may not be ideal.
461+
var cIndex: String.*::Index
462+
// expected-error@-1 {{consecutive declarations on a line must be separated by ';'}}
463+
// expected-error@-2 {{expected declaration}}
464+
465+
var dIndex: String._::Index
466+
// expected-error@-1 {{expected identifier in module selector}}
467+
468+
var eIndex: String.Self::Index
469+
// expected-error@-1 {{expected identifier in module selector}}
470+
471+
var fIndex: String.self::Index
472+
// expected-error@-1 {{expected identifier in module selector}}
473+
474+
var gIndex: String.inout::Index
475+
// expected-error@-1 {{expected identifier in module selector}}
476+
477+
var hIndex: String.Any::Index
478+
// expected-error@-1 {{expected identifier in module selector}}
479+
480+
func inExpr() {
481+
::print()
482+
// expected-error@-1 {{expected identifier in module selector}}
483+
484+
(::print())
485+
// expected-error@-1 {{expected identifier in module selector}}
486+
487+
*::print()
488+
// expected-error@-1 {{expected identifier in module selector}}
489+
490+
_::print()
491+
// expected-error@-1 {{expected identifier in module selector}}
492+
493+
Self::print()
494+
// expected-error@-1 {{expected identifier in module selector}}
495+
496+
self::print()
497+
// expected-error@-1 {{expected identifier in module selector}}
498+
499+
inout::print()
500+
// expected-error@-1 {{expected identifier in module selector}}
501+
502+
Any::print()
503+
// expected-error@-1 {{expected identifier in module selector}}
504+
505+
_ = 1.::magnitude
506+
// expected-error@-1 {{expected identifier in module selector}}
507+
508+
_ = (1.::magnitude)
509+
// expected-error@-1 {{expected identifier in module selector}}
510+
511+
// FIXME: This gets interpreted as a single `.*` operator; may not be ideal.
512+
_ = 1.*::magnitude
513+
// expected-error@-1 {{expected identifier in module selector}}
514+
// expected-error@-2 {{cannot find operator '.*' in scope}}
515+
516+
_ = 1._::magnitude
517+
// expected-error@-1 {{expected identifier in module selector}}
518+
519+
_ = 1.Self::magnitude
520+
// expected-error@-1 {{expected identifier in module selector}}
521+
522+
_ = 1.self::magnitude
523+
// expected-error@-1 {{expected identifier in module selector}}
524+
525+
_ = 1.inout::magnitude
526+
// expected-error@-1 {{expected identifier in module selector}}
527+
528+
_ = 1.Any::magnitude
529+
// expected-error@-1 {{expected identifier in module selector}}
530+
}
531+
}
532+
408533
@_spi(main::Private)
409534
// expected-error@-1 {{SPI group cannot be qualified with a module selector}} expected-note@-1 {{remove module selector from this name}} {{7-13=}}
410535
public struct BadImplementsAttr: CustomStringConvertible {

0 commit comments

Comments
 (0)