From ecfde0e71c61184989fde0f93f8d6b7f5375b99a Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Mon, 11 Jan 2016 23:09:27 -0800 Subject: [PATCH] Start parsing names with argument labels. Basic implementatation of SE-0021, naming functions with argument labels. Handle parsing of compound function names in various unqualified-identifier productions, updating the AST representation of various expressions from Identifiers to DeclNames. The result doesn't capture all of the source locations we want; more on that later. As part of this, remove the parsing code for the "selector-style" method names, since we now have a replacement. The feature was never publicized and doesn't make sense in Swift, so zap it outright. --- include/swift/AST/DiagnosticsParse.def | 3 + include/swift/AST/DiagnosticsSema.def | 17 +- include/swift/AST/Expr.h | 22 +-- include/swift/AST/Identifier.h | 6 +- include/swift/Parse/Parser.h | 25 ++- lib/IDE/SyntaxModel.cpp | 2 +- lib/Parse/ParseExpr.cpp | 216 ++++++++++++++--------- lib/Parse/ParseStmt.cpp | 11 +- lib/Sema/CSApply.cpp | 2 +- lib/Sema/CSDiag.cpp | 10 +- lib/Sema/TypeCheckConstraints.cpp | 8 +- lib/Sema/TypeCheckPattern.cpp | 18 +- lib/Sema/TypeChecker.cpp | 2 +- test/ClangModules/objc_parse.swift | 11 +- test/Constraints/fixes.swift | 2 +- test/TypeCoercion/overload_noncall.swift | 2 +- test/decl/ext/protocol.swift | 4 +- test/expr/postfix/dot/selector.swift | 46 ----- test/expr/primary/unqualified_name.swift | 56 ++++++ 19 files changed, 279 insertions(+), 184 deletions(-) delete mode 100644 test/expr/postfix/dot/selector.swift create mode 100644 test/expr/primary/unqualified_name.swift diff --git a/include/swift/AST/DiagnosticsParse.def b/include/swift/AST/DiagnosticsParse.def index f487a369a8d73..96db8277cdeea 100644 --- a/include/swift/AST/DiagnosticsParse.def +++ b/include/swift/AST/DiagnosticsParse.def @@ -953,6 +953,9 @@ ERROR(availability_query_outside_if_stmt_guard, none, "#available may only be used as condition of an 'if', 'guard'" " or 'while' statement", ()) +ERROR(empty_arg_label_underscore, none, + "an empty argument label is spelled with '_'", ()) + ERROR(expected_identifier_after_dot_expr,none, "expected identifier after '.' expression", ()) diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 190bf3418987b..c442d31ca5377 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -55,7 +55,7 @@ NOTE(while_converting_subscript_index,none, //------------------------------------------------------------------------------ ERROR(ambiguous_member_overload_set,none, - "ambiguous reference to member '%0'", (StringRef)) + "ambiguous reference to member %0", (DeclName)) ERROR(ambiguous_subscript,none, "ambiguous subscript with base type %0 and index type %1", @@ -76,9 +76,9 @@ NOTE(did_you_mean_raw_type,none, "did you mean to specify a raw type on the enum declaration?", ()) ERROR(expected_argument_in_contextual_member,none, - "contextual member %0 expects argument of type %1", (Identifier, Type)) + "contextual member %0 expects argument of type %1", (DeclName, Type)) ERROR(unexpected_argument_in_contextual_member,none, - "contextual member %0 has no associated value", (Identifier)) + "contextual member %0 has no associated value", (DeclName)) ERROR(could_not_use_value_member,none, "member %1 cannot be used on value of type %0", (Type, DeclName)) @@ -443,7 +443,7 @@ ERROR(unspaced_unary_operator,none, ERROR(use_unresolved_identifier,none, - "use of unresolved %select{identifier|operator}1 %0", (Identifier, bool)) + "use of unresolved %select{identifier|operator}1 %0", (DeclName, bool)) ERROR(use_undeclared_type,none, "use of undeclared type %0", (Identifier)) ERROR(use_undeclared_type_did_you_mean,none, @@ -470,7 +470,7 @@ ERROR(use_non_type_value,none, NOTE(use_non_type_value_prev,none, "%0 declared here", (Identifier)) ERROR(use_local_before_declaration,none, - "use of local variable %0 before its declaration", (Identifier)) + "use of local variable %0 before its declaration", (DeclName)) ERROR(unsupported_existential_type,none, "protocol %0 can only be used as a generic constraint because it has " "Self or associated type requirements", (Identifier)) @@ -647,11 +647,10 @@ ERROR(argument_out_of_order_named_unnamed,none, ERROR(instance_member_use_on_type,none, "use of instance member %1 on type %0; " - "did you mean to use a value of type %0 instead?", (Type, Identifier)) + "did you mean to use a value of type %0 instead?", (Type, DeclName)) ERROR(instance_member_in_initializer,none, "cannot use instance member %0 within property initializer; " - "property initializers run before 'self' is available", (Identifier)) - + "property initializers run before 'self' is available", (DeclName)) ERROR(missing_argument_named,none, "missing argument for parameter %0 in call", (Identifier)) @@ -1779,7 +1778,7 @@ ERROR(inout_expr_outside_of_call,none, ERROR(unresolved_member_no_inference,none, "reference to member %0 cannot be resolved without a contextual type", - (Identifier)) + (DeclName)) ERROR(type_of_expression_is_ambiguous,none, "type of expression is ambiguous without more context", ()) diff --git a/include/swift/AST/Expr.h b/include/swift/AST/Expr.h index 4612185d2f476..3ef4649c87cbe 100644 --- a/include/swift/AST/Expr.h +++ b/include/swift/AST/Expr.h @@ -1175,26 +1175,26 @@ class OverloadedMemberRefExpr : public OverloadSetRefExpr { return E->getKind() == ExprKind::OverloadedMemberRef; } }; - + /// UnresolvedDeclRefExpr - This represents use of an undeclared identifier, /// which may ultimately be a use of something that hasn't been defined yet, it /// may be a use of something that got imported (which will be resolved during /// sema), or may just be a use of an unknown identifier. /// class UnresolvedDeclRefExpr : public Expr { - Identifier Name; + DeclName Name; SourceLoc Loc; DeclRefKind RefKind; bool IsSpecialized = false; public: - UnresolvedDeclRefExpr(Identifier name, DeclRefKind refKind, SourceLoc loc) + UnresolvedDeclRefExpr(DeclName name, DeclRefKind refKind, SourceLoc loc) : Expr(ExprKind::UnresolvedDeclRef, /*Implicit=*/loc.isInvalid()), Name(name), Loc(loc), RefKind(refKind) { } - bool hasName() const { return !Name.empty(); } - Identifier getName() const { return Name; } + bool hasName() const { return static_cast(Name); } + DeclName getName() const { return Name; } DeclRefKind getRefKind() const { return RefKind; } void setSpecialized(bool specialized) { IsSpecialized = specialized; } @@ -1401,17 +1401,17 @@ class DynamicSubscriptExpr : public DynamicLookupExpr { class UnresolvedMemberExpr : public Expr { SourceLoc DotLoc; SourceLoc NameLoc; - Identifier Name; + DeclName Name; Expr *Argument; public: UnresolvedMemberExpr(SourceLoc dotLoc, SourceLoc nameLoc, - Identifier name, Expr *argument) + DeclName name, Expr *argument) : Expr(ExprKind::UnresolvedMember, /*Implicit=*/false), DotLoc(dotLoc), NameLoc(nameLoc), Name(name), Argument(argument) { } - Identifier getName() const { return Name; } + DeclName getName() const { return Name; } SourceLoc getNameLoc() const { return NameLoc; } SourceLoc getDotLoc() const { return DotLoc; } Expr *getArgument() const { return Argument; } @@ -1898,9 +1898,9 @@ class UnresolvedDotExpr : public Expr { Expr *SubExpr; SourceLoc DotLoc; SourceLoc NameLoc; - Identifier Name; + DeclName Name; public: - UnresolvedDotExpr(Expr *subexpr, SourceLoc dotloc, Identifier name, + UnresolvedDotExpr(Expr *subexpr, SourceLoc dotloc, DeclName name, SourceLoc nameloc, bool Implicit) : Expr(ExprKind::UnresolvedDot, Implicit), SubExpr(subexpr), DotLoc(dotloc), NameLoc(nameloc), Name(name) {} @@ -1916,7 +1916,7 @@ class UnresolvedDotExpr : public Expr { Expr *getBase() const { return SubExpr; } void setBase(Expr *e) { SubExpr = e; } - Identifier getName() const { return Name; } + DeclName getName() const { return Name; } SourceLoc getNameLoc() const { return NameLoc; } static bool classof(const Expr *E) { diff --git a/include/swift/AST/Identifier.h b/include/swift/AST/Identifier.h index ff3b34699919a..c6a7631e27555 100644 --- a/include/swift/AST/Identifier.h +++ b/include/swift/AST/Identifier.h @@ -118,8 +118,12 @@ class Identifier { || (C >= 0xE0100 && C <= 0xE01EF); } + static bool isEditorPlaceholder(StringRef name) { + return name.startswith("<#"); + } + bool isEditorPlaceholder() const { - return !empty() && Pointer[0] == '<' && Pointer[1] == '#'; + return !empty() && isEditorPlaceholder(str()); } void *getAsOpaquePointer() const { return (void *)Pointer; } diff --git a/include/swift/Parse/Parser.h b/include/swift/Parse/Parser.h index c5b8f721fb041..ee78752c09975 100644 --- a/include/swift/Parse/Parser.h +++ b/include/swift/Parse/Parser.h @@ -373,13 +373,17 @@ class Parser { class BacktrackingScope { Parser &P; ParserPosition PP; + bool Backtrack = true; public: BacktrackingScope(Parser &P) : P(P), PP(P.getParserPosition()) {} ~BacktrackingScope() { - P.backtrackToPosition(PP); + if (Backtrack) + P.backtrackToPosition(PP); } + + void cancelBacktrack() { Backtrack = false; } }; /// RAII object that, when it is destructed, restores the parser and lexer to @@ -1096,7 +1100,24 @@ class Parser { ParserResult parseExprSuper(); ParserResult parseExprConfiguration(); Expr *parseExprStringLiteral(); - + + /// If the token is an escaped identifier being used as an argument + /// label, but doesn't need to be, diagnose it. + void diagnoseEscapedArgumentLabel(const Token &tok); + + /// Parse an unqualified-identifier. + /// + /// unqualified-identifier: + /// identifier + /// identifier '(' ((identifier | '_') ':') + ')' + /// + /// + /// \param allowInit Whether to allow 'init' for initializers. + /// \param loc Will be populated with the location of the name. + /// \param diag The diagnostic to emit if this is not a name. + DeclName parseUnqualifiedIdentifier(bool allowInit, SourceLoc &loc, + const Diagnostic &diag); + Expr *parseExprIdentifier(); Expr *parseExprEditorPlaceholder(Token PlaceholderTok, Identifier PlaceholderId); diff --git a/lib/IDE/SyntaxModel.cpp b/lib/IDE/SyntaxModel.cpp index ad4845b06a269..ba55bfc9567e8 100644 --- a/lib/IDE/SyntaxModel.cpp +++ b/lib/IDE/SyntaxModel.cpp @@ -996,7 +996,7 @@ class IdRefWalker : public ASTWalker { if (DRE->getRefKind() != DeclRefKind::Ordinary) return { true, E }; if (!Fn(CharSourceRange(DRE->getSourceRange().Start, - DRE->getName().getLength()))) + DRE->getName().getBaseName().getLength()))) return { false, nullptr }; } return { true, E }; diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 51c3f0e948def..ffdd282e30526 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -489,7 +489,7 @@ ParserResult Parser::parseExprUnary(Diag<> Message, bool isExprBasic) { // Check if we have a unary '-' with number literal sub-expression, for // example, "-42" or "-1.25". if (auto *LE = dyn_cast(SubExpr.get())) { - if (Operator->hasName() && Operator->getName().str() == "-") { + if (Operator->hasName() && Operator->getName().getBaseName().str() == "-") { LE->setNegative(Operator->getLoc()); return makeParserResult(LE); } @@ -587,6 +587,7 @@ ParserResult Parser::parseExprSuper() { SourceLoc ctorLoc = consumeToken(); // The constructor decl will be resolved by sema. + // FIXME: Extend representation with DeclName! Expr *result = new (Context) UnresolvedConstructorExpr(superRef, dotLoc, ctorLoc, /*Implicit=*/false); @@ -602,9 +603,11 @@ ParserResult Parser::parseExprSuper() { } else { // super.foo SourceLoc nameLoc; - Identifier name; - if (parseIdentifier(name, nameLoc, - diag::expected_identifier_after_super_dot_expr)) + DeclName name = parseUnqualifiedIdentifier( + /*allowInit=*/false, + nameLoc, + diag::expected_identifier_after_super_dot_expr); + if (!name) return nullptr; return makeParserResult(new (Context) UnresolvedDotExpr(superRef, dotLoc, @@ -905,7 +908,7 @@ ParserResult Parser::parseExprPostfix(Diag<> ID, bool isExprBasic) { break; } - Identifier Name; + DeclName Name; SourceLoc NameLoc; if (Tok.is(tok::code_complete)) { @@ -937,13 +940,9 @@ ParserResult Parser::parseExprPostfix(Diag<> ID, bool isExprBasic) { return Result; } - if (Tok.is(tok::kw_init)) { - Name = Context.Id_init; - NameLoc = consumeToken(tok::kw_init); - } else if (parseIdentifier(Name, NameLoc, - diag::expected_identifier_after_dot_expr)) { - return nullptr; - } + Name = parseUnqualifiedIdentifier(/*allowInit=*/true, NameLoc, + diag::expected_identifier_after_dot_expr); + if (!Name) return nullptr; ParserResult Arg; @@ -1064,6 +1063,7 @@ ParserResult Parser::parseExprPostfix(Diag<> ID, bool isExprBasic) { // expr-init ::= expr-postfix '.' 'init'. if (Tok.is(tok::kw_init)) { // Form the reference to the constructor. + // FIXME: Handle a full DeclName. Expr *initRef = new (Context) UnresolvedConstructorExpr( Result.get(), TokLoc, @@ -1101,50 +1101,19 @@ ParserResult Parser::parseExprPostfix(Diag<> ID, bool isExprBasic) { if (Result.isParseError()) continue; - Identifier Name = Context.getIdentifier(Tok.getText()); - SourceLoc NameLoc = Tok.getLoc(); + if (Tok.is(tok::identifier)) { - consumeToken(tok::identifier); - - // If this is a selector reference, collect the selector pieces. - bool IsSelector = false; - if (Tok.is(tok::colon) && peekToken().isIdentifierOrUnderscore()) { - BacktrackingScope BS(*this); - - consumeToken(); // ':' - consumeToken(); // identifier or '_' - IsSelector = consumeIf(tok::colon); - } - - if (IsSelector) { - // Collect the selector pieces. - SmallVector Locs; - SmallVector ArgumentNames; + SourceLoc NameLoc; + DeclName Name; + Name = parseUnqualifiedIdentifier(/*allowInit=*/false, + NameLoc, + diag::expected_member_name); + if (!Name) return nullptr; + + Result = makeParserResult( + new (Context) UnresolvedDotExpr(Result.get(), TokLoc, Name, + NameLoc, /*Implicit=*/false)); - Locs.push_back({NameLoc, consumeToken(tok::colon)}); - - // Add entry for the unwritten first argument name. - Locs.push_back({SourceLoc(), SourceLoc()}); - ArgumentNames.push_back(Identifier()); - while (Tok.isIdentifierOrUnderscore() && peekToken().is(tok::colon)) { - Identifier SelName; - if (Tok.is(tok::identifier)) - SelName = Context.getIdentifier(Tok.getText()); - SourceLoc SelLoc = consumeToken(); - SourceLoc ColonLoc = consumeToken(tok::colon); - Locs.push_back({SelLoc, ColonLoc}); - ArgumentNames.push_back(SelName); - } - auto FullName = DeclName(Context, Name, ArgumentNames); - Result = makeParserResult( - UnresolvedSelectorExpr::create(Context, Result.get(), TokLoc, - FullName, Locs)); - } else { - Result = makeParserResult( - new (Context) UnresolvedDotExpr(Result.get(), TokLoc, Name, NameLoc, - /*Implicit=*/false)); - } - if (canParseAsGenericArgumentList()) { SmallVector args; SourceLoc LAngleLoc, RAngleLoc; @@ -1156,22 +1125,21 @@ ParserResult Parser::parseExprPostfix(Diag<> ID, bool isExprBasic) { for (auto ty : args) locArgs.push_back(ty); Result = makeParserResult(new (Context) UnresolvedSpecializeExpr( - Result.get(), LAngleLoc, Context.AllocateCopy(locArgs), - RAngleLoc)); - } - - // If there is an expr-call-suffix, parse it and form a call. - if (Tok.isFollowingLParen()) { - Result = parseExprCallSuffix(Result); - continue; + Result.get(), LAngleLoc, Context.AllocateCopy(locArgs), + RAngleLoc)); } } else { + DeclName name = Context.getIdentifier(Tok.getText()); + SourceLoc nameLoc = consumeToken(tok::integer_literal); Result = makeParserResult( - new (Context) UnresolvedDotExpr(Result.get(), TokLoc, Name, NameLoc, + new (Context) UnresolvedDotExpr(Result.get(), TokLoc, name, nameLoc, /*Implicit=*/false)); - consumeToken(tok::integer_literal); } + // If there is an expr-call-suffix, parse it and form a call. + if (Tok.isFollowingLParen()) + Result = parseExprCallSuffix(Result); + continue; } @@ -1409,16 +1377,111 @@ Expr *Parser::parseExprStringLiteral() { return new (Context) InterpolatedStringLiteralExpr(Loc, Context.AllocateCopy(Exprs)); } - + +void Parser::diagnoseEscapedArgumentLabel(const Token &tok) { + assert(tok.isEscapedIdentifier() && "Only for escaped identifiers"); + if (!canBeArgumentLabel(tok.getText())) return; + + SourceLoc start = tok.getLoc(); + SourceLoc end = start.getAdvancedLoc(tok.getLength()); + diagnose(tok, diag::escaped_parameter_name, tok.getText()) + .fixItRemoveChars(start, start.getAdvancedLoc(1)) + .fixItRemoveChars(end.getAdvancedLoc(-1), end); +} + +DeclName Parser::parseUnqualifiedIdentifier(bool allowInit, + SourceLoc &loc, + const Diagnostic &diag) { + // Consume the base name. + Identifier baseName; + + if (Tok.is(tok::kw_init) && allowInit) { + baseName = Context.Id_init; + loc = consumeToken(tok::kw_init); + } else if (Tok.is(tok::identifier) || Tok.is(tok::kw_Self) || + Tok.is(tok::kw_self)) { + loc = consumeIdentifier(&baseName); + } else { + checkForInputIncomplete(); + diagnose(Tok, diag); + return DeclName(); + } + + // If the next token isn't a following '(', we don't have a compound name. + if (!Tok.isFollowingLParen()) return baseName; + + // If the token after that isn't an argument label or ':', we don't have a + // compound name. + if ((!peekToken().canBeArgumentLabel() && !peekToken().is(tok::colon)) || + Identifier::isEditorPlaceholder(peekToken().getText())) + return baseName; + + // Try to parse a compound name. + BacktrackingScope backtrack(*this); + + SmallVector argumentLabels; + SourceLoc lparenLoc = consumeToken(tok::l_paren); + SourceLoc rparenLoc; + while (true) { + // Terminate at ')'. + if (Tok.is(tok::r_paren)) { + rparenLoc = consumeToken(tok::r_paren); + break; + } + + // If we see a ':', the user forgot the '_'; + if (Tok.is(tok::colon)) { + diagnose(Tok, diag::empty_arg_label_underscore) + .fixItInsert(Tok.getLoc(), "_"); + argumentLabels.push_back(Identifier()); + (void)consumeToken(tok::colon); + } + + // If we see a potential argument label followed by a ':', consume + // it. + if (Tok.canBeArgumentLabel() && peekToken().is(tok::colon)) { + // If this was an escaped identifier that need not have been escaped, + // say so. + if (Tok.isEscapedIdentifier()) + diagnoseEscapedArgumentLabel(Tok); + + if (Tok.is(tok::kw__)) + argumentLabels.push_back(Identifier()); + else + argumentLabels.push_back(Context.getIdentifier(Tok.getText())); + (void)consumeToken(); + (void)consumeToken(tok::colon); + continue; + } + + // This is not a compound name. + // FIXME: Could recover better if we "know" it's a compound name. + return baseName; + } + + assert(!argumentLabels.empty() && "Logic above should prevent this"); + + // FIXME: Actually store + (void)lparenLoc; + + // We have a compound name. Cancel backtracking and build that name. + backtrack.cancelBacktrack(); + return DeclName(Context, baseName, argumentLabels); +} + /// expr-identifier: -/// identifier generic-args? +/// unqualified-identifier generic-args? Expr *Parser::parseExprIdentifier() { assert(Tok.is(tok::identifier) || Tok.is(tok::kw_self) || Tok.is(tok::kw_Self)); Token IdentTok = Tok; - Identifier name; - SourceLoc loc = consumeIdentifier(&name); + + // Pase the unqualified-identifier. + SourceLoc loc; + DeclName name = parseUnqualifiedIdentifier(/*allowInit=*/false, loc, + diag::expected_expr); + SmallVector args; SourceLoc LAngleLoc, RAngleLoc; bool hasGenericArgumentList = false; @@ -1439,7 +1502,7 @@ Expr *Parser::parseExprIdentifier() { hasGenericArgumentList = !args.empty(); } - ValueDecl *D = lookupInScope(name); + ValueDecl *D = lookupInScope(name.getBaseName()); // FIXME: We want this to work: "var x = { x() }", but for now it's better // to disallow it than to crash. if (D) { @@ -1451,7 +1514,7 @@ Expr *Parser::parseExprIdentifier() { } } else { for (auto activeVar : DisabledVars) { - if (activeVar->getName() == name) { + if (activeVar->getFullName() == name) { diagnose(loc, DisabledVarReason); return new (Context) ErrorExpr(loc); } @@ -1460,8 +1523,8 @@ Expr *Parser::parseExprIdentifier() { Expr *E; if (D == 0) { - if (name.isEditorPlaceholder()) - return parseExprEditorPlaceholder(IdentTok, name); + if (name.getBaseName().isEditorPlaceholder()) + return parseExprEditorPlaceholder(IdentTok, name.getBaseName()); auto refKind = DeclRefKind::Ordinary; auto unresolved = new (Context) UnresolvedDeclRefExpr(name, refKind, loc); @@ -2031,13 +2094,8 @@ ParserResult Parser::parseExprList(tok LeftTok, tok RightTok) { if (Tok.canBeArgumentLabel() && peekToken().is(tok::colon)) { // If this was an escaped identifier that need not have been escaped, // say so. - if (Tok.isEscapedIdentifier() && canBeArgumentLabel(Tok.getText())) { - SourceLoc start = Tok.getLoc(); - SourceLoc end = start.getAdvancedLoc(Tok.getLength()); - diagnose(Tok, diag::escaped_parameter_name, Tok.getText()) - .fixItRemoveChars(start, start.getAdvancedLoc(1)) - .fixItRemoveChars(end.getAdvancedLoc(-1), end); - } + if (Tok.isEscapedIdentifier()) + diagnoseEscapedArgumentLabel(Tok); if (!Tok.is(tok::kw__)) FieldName = Context.getIdentifier(Tok.getText()); diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 35ab6e7c750d9..c34e3b24238b0 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -1529,7 +1529,7 @@ ConfigParserState Parser::evaluateConfigConditionExpr(Expr *configExpr) { while (iOperand < numElements) { if (auto *UDREOp = dyn_cast(elements[iOperator])) { - auto name = UDREOp->getName().str(); + auto name = UDREOp->getName().getBaseName().str(); if (name.equals("||") || name.equals("&&")) { auto rhs = evaluateConfigConditionExpr(elements[iOperand]); @@ -1567,7 +1567,7 @@ ConfigParserState Parser::evaluateConfigConditionExpr(Expr *configExpr) { // Evaluate a named reference expression. if (auto *UDRE = dyn_cast(configExpr)) { - auto name = UDRE->getName().str(); + auto name = UDRE->getName().getBaseName().str(); return ConfigParserState(Context.LangOpts.hasBuildConfigOption(name), ConfigExprKind::DeclRef); } @@ -1580,7 +1580,8 @@ ConfigParserState Parser::evaluateConfigConditionExpr(Expr *configExpr) { // Evaluate a negation (unary "!") expression. if (auto *PUE = dyn_cast(configExpr)) { // If the PUE is not a negation expression, return false - auto name = cast(PUE->getFn())->getName().str(); + auto name = + cast(PUE->getFn())->getName().getBaseName().str(); if (name != "!") { diagnose(PUE->getLoc(), diag::unsupported_build_config_unary_expression); return ConfigParserState::error(); @@ -1601,7 +1602,7 @@ ConfigParserState Parser::evaluateConfigConditionExpr(Expr *configExpr) { return ConfigParserState::error(); } - auto fnName = fnNameExpr->getName().str(); + auto fnName = fnNameExpr->getName().getBaseName().str(); if (!fnName.equals("arch") && !fnName.equals("os") && !fnName.equals("_runtime") && @@ -1633,7 +1634,7 @@ ConfigParserState Parser::evaluateConfigConditionExpr(Expr *configExpr) { if (auto UDRE = dyn_cast(PE->getSubExpr())) { // The sub expression should be an UnresolvedDeclRefExpr (we won't // tolerate extra parens). - auto argument = UDRE->getName().str(); + auto argument = UDRE->getName().getBaseName().str(); // Error for values that don't make sense if there's a clear definition // of the possible values (as there is for _runtime). diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index b9d687f7060c7..d22deb9e6e4da 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -6084,7 +6084,7 @@ bool ConstraintSystem::applySolutionFix(Expr *expr, do { // We haven't found the reference to allZeros yet, look for it now. if ((allZerosRef = dyn_cast(current))) { - if (allZerosRef->getName().str() == "allZeros") + if (allZerosRef->getName().getBaseName().str() == "allZeros") break; allZerosRef = nullptr; } diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp index a25697eec4b87..ce9ab25bdb86a 100644 --- a/lib/Sema/CSDiag.cpp +++ b/lib/Sema/CSDiag.cpp @@ -1365,7 +1365,7 @@ void CalleeCandidateInfo::collectCalleeCandidates(Expr *fn) { // base uncurried by one level, and we refer to the name of the member, not to // the name of any base. if (auto UDE = dyn_cast(fn)) { - declName = UDE->getName().str().str(); + declName = UDE->getName().getBaseName().str().str(); uncurryLevel = 1; // If we actually resolved the member to use, return it. @@ -2346,11 +2346,7 @@ bool FailureDiagnosis::diagnoseGeneralOverloadFailure(Constraint *constraint) { bindOverload = constraint->getNestedConstraints().front(); auto overloadChoice = bindOverload->getOverloadChoice(); - std::string overloadName = overloadChoice.getDecl()->getNameStr(); - - if (auto *CD = dyn_cast(overloadChoice.getDecl())) - if (auto *SD = CD->getImplicitSelfDecl()) - overloadName = SD->getType()->getInOutObjectType().getString() + ".init"; + auto overloadName = overloadChoice.getDecl()->getFullName(); // Get the referenced expression from the failed constraint. auto anchor = expr; @@ -4630,7 +4626,7 @@ bool FailureDiagnosis::visitUnresolvedMemberExpr(UnresolvedMemberExpr *E) { SourceRange argRange; if (auto arg = E->getArgument()) argRange = arg->getSourceRange(); diagnose(E->getNameLoc(), diag::ambiguous_member_overload_set, - E->getName().str()) + E->getName()) .highlight(argRange); candidateInfo.suggestPotentialOverloads(E->getNameLoc()); return true; diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp index 3335e479e852f..fddbf6d30ce90 100644 --- a/lib/Sema/TypeCheckConstraints.cpp +++ b/lib/Sema/TypeCheckConstraints.cpp @@ -302,7 +302,7 @@ static void diagnoseBinOpSplit(UnresolvedDeclRefExpr *UDRE, unsigned splitLoc = splitCandidate.first; bool isBinOpFirst = splitCandidate.second; - StringRef nameStr = UDRE->getName().str(); + StringRef nameStr = UDRE->getName().getBaseName().str(); auto startStr = nameStr.substr(0, splitLoc); auto endStr = nameStr.drop_front(splitLoc); @@ -330,7 +330,7 @@ static void diagnoseBinOpSplit(UnresolvedDeclRefExpr *UDRE, static bool diagnoseOperatorJuxtaposition(UnresolvedDeclRefExpr *UDRE, DeclContext *DC, TypeChecker &TC) { - Identifier name = UDRE->getName(); + Identifier name = UDRE->getName().getBaseName(); StringRef nameStr = name.str(); if (!name.isOperator() || nameStr.size() < 2) return false; @@ -434,7 +434,7 @@ static bool diagnoseOperatorJuxtaposition(UnresolvedDeclRefExpr *UDRE, Expr *TypeChecker:: resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE, DeclContext *DC) { // Process UnresolvedDeclRefExpr by doing an unqualified lookup. - Identifier Name = UDRE->getName(); + DeclName Name = UDRE->getName(); SourceLoc Loc = UDRE->getLoc(); // Perform standard value name lookup. @@ -501,7 +501,7 @@ resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE, DeclContext *DC) { // Diagnose uses of operators that found no matching candidates. if (ResultValues.empty()) { assert(UDRE->getRefKind() != DeclRefKind::Ordinary); - diagnose(Loc, diag::use_nonmatching_operator, Name, + diagnose(Loc, diag::use_nonmatching_operator, Name.getBaseName(), UDRE->getRefKind() == DeclRefKind::BinaryOperator ? 0 : UDRE->getRefKind() == DeclRefKind::PrefixOperator ? 1 : 2); return new (Context) ErrorExpr(Loc); diff --git a/lib/Sema/TypeCheckPattern.cpp b/lib/Sema/TypeCheckPattern.cpp index 095afba500cfd..791418de9078a 100644 --- a/lib/Sema/TypeCheckPattern.cpp +++ b/lib/Sema/TypeCheckPattern.cpp @@ -156,7 +156,8 @@ struct ExprToIdentTypeRepr : public ASTVisitor assert(components.empty() && "decl ref should be root element of expr"); // Track the AST location of the component. components.push_back( - new (C) SimpleIdentTypeRepr(udre->getLoc(), udre->getName())); + new (C) SimpleIdentTypeRepr(udre->getLoc(), + udre->getName().getBaseName())); return true; } @@ -168,7 +169,7 @@ struct ExprToIdentTypeRepr : public ASTVisitor // Track the AST location of the new component. components.push_back( - new (C) SimpleIdentTypeRepr(ude->getLoc(), ude->getName())); + new (C) SimpleIdentTypeRepr(ude->getLoc(), ude->getName().getBaseName())); return true; } @@ -405,9 +406,10 @@ class ResolvePattern : public ASTVisitorgetDotLoc(), ume->getNameLoc(), - ume->getName(), + ume->getName().getBaseName(), nullptr, subPattern); } @@ -431,8 +433,9 @@ class ResolvePattern : public ASTVisitorgetName()); + = lookupEnumMemberElement(TC, DC, ty, ude->getName().getBaseName()); // Build a TypeRepr from the head of the full path. TypeLoc loc(repr); @@ -440,7 +443,7 @@ class ResolvePattern : public ASTVisitorgetDotLoc(), ude->getNameLoc(), - ude->getName(), + ude->getName().getBaseName(), referencedElement, nullptr); } @@ -467,14 +470,15 @@ class ResolvePattern : public ASTVisitorgetName())) { + = lookupUnqualifiedEnumMemberElement(TC, DC, + ude->getName().getBaseName())) { auto *enumDecl = referencedElement->getParentEnum(); auto enumTy = enumDecl->getDeclaredTypeInContext(); TypeLoc loc = TypeLoc::withoutLoc(enumTy); return new (TC.Context) EnumElementPattern(loc, SourceLoc(), ude->getLoc(), - ude->getName(), + ude->getName().getBaseName(), referencedElement, nullptr); } diff --git a/lib/Sema/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp index 19236ebd5b1c8..b80830aabd04c 100644 --- a/lib/Sema/TypeChecker.cpp +++ b/lib/Sema/TypeChecker.cpp @@ -2290,7 +2290,7 @@ void TypeChecker::checkForForbiddenPrefix(const Decl *D) { void TypeChecker::checkForForbiddenPrefix(const UnresolvedDeclRefExpr *E) { if (!hasEnabledForbiddenTypecheckPrefix()) return; - checkForForbiddenPrefix(E->getName()); + checkForForbiddenPrefix(E->getName().getBaseName()); } void TypeChecker::checkForForbiddenPrefix(Identifier Ident) { diff --git a/test/ClangModules/objc_parse.swift b/test/ClangModules/objc_parse.swift index 966a19efaab58..43fb81a44db03 100644 --- a/test/ClangModules/objc_parse.swift +++ b/test/ClangModules/objc_parse.swift @@ -85,22 +85,21 @@ func instanceMethodsInExtensions(b: B) { b.method(1, onExtB:2.5) b.method(1, separateExtMethod:3.5) - let m1 = b.method:onCat1: + let m1 = b.method(_:onCat1:) m1(1, onCat1: 2.5) - let m2 = b.method:onExtA: + let m2 = b.method(_:onExtA:) m2(1, onExtA: 2.5) - let m3 = b.method:onExtB: + let m3 = b.method(_:onExtB:) m3(1, onExtB: 2.5) - let m4 = b.method:separateExtMethod: + let m4 = b.method(_:separateExtMethod:) m4(1, separateExtMethod: 2.5) } func dynamicLookupMethod(b: AnyObject) { - // FIXME: Syntax will be replaced. - if let m5 = b.method:separateExtMethod: { + if let m5 = b.method(_:separateExtMethod:) { m5(1, separateExtMethod: 2.5) } } diff --git a/test/Constraints/fixes.swift b/test/Constraints/fixes.swift index fba21c068a02c..3662618993d12 100644 --- a/test/Constraints/fixes.swift +++ b/test/Constraints/fixes.swift @@ -37,7 +37,7 @@ func forgotCall() { f6(f4, f2) // expected-error{{function produces expected type 'B'; did you mean to call it with '()'?}}{{8-8=()}} // With overloading: only one succeeds. - a = createB // expected-error{{ambiguous reference to member 'createB'}} + a = createB // expected-error{{ambiguous reference to member 'createB()'}} // With overloading, pick the fewest number of fixes. var b = f7(f4, f1) // expected-error{{function produces expected type 'B'; did you mean to call it with '()'?}} diff --git a/test/TypeCoercion/overload_noncall.swift b/test/TypeCoercion/overload_noncall.swift index 162b51ec96be1..ab1c4db5cc2f2 100644 --- a/test/TypeCoercion/overload_noncall.swift +++ b/test/TypeCoercion/overload_noncall.swift @@ -16,7 +16,7 @@ func f2(g: (x: X) -> X) -> ((y: Y) -> Y) { } func test_conv() { var _ : (x1 : X, x2 : X) -> X = f0 var _ : (X, X) -> X = f0 - var _ : (Y, X) -> X = f0 // expected-error{{ambiguous reference to member 'f0'}} + var _ : (Y, X) -> X = f0 // expected-error{{ambiguous reference to member 'f0(_:x2:)'}} var _ : (X) -> X = f1 var a7 : (X) -> (X) = f1 var a8 : (x2 : X) -> (X) = f1 diff --git a/test/decl/ext/protocol.swift b/test/decl/ext/protocol.swift index 7ca79b94b2238..b4068033e1ea5 100644 --- a/test/decl/ext/protocol.swift +++ b/test/decl/ext/protocol.swift @@ -213,9 +213,9 @@ extension P4 where Self.AssocP4 == Bool { } func testP4(s4a: S4a, s4b: S4b, s4c: S4c, s4d: S4d) { - s4a.extP4a() // expected-error{{ambiguous reference to member 'extP4a'}} + s4a.extP4a() // expected-error{{ambiguous reference to member 'extP4a()'}} s4b.extP4a() // ok - s4c.extP4a() // expected-error{{ambiguous reference to member 'extP4a'}} + s4c.extP4a() // expected-error{{ambiguous reference to member 'extP4a()'}} s4c.extP4Int() // okay var b1 = s4d.extP4a() // okay, "Bool" version b1 = true // checks type above diff --git a/test/expr/postfix/dot/selector.swift b/test/expr/postfix/dot/selector.swift deleted file mode 100644 index 17347eb10d88b..0000000000000 --- a/test/expr/postfix/dot/selector.swift +++ /dev/null @@ -1,46 +0,0 @@ -// RUN: %target-parse-verify-swift - -class C { - class func classMethod(_: Int) {} // expected-note {{found this candidate}} - class func classMethod(_: Int, withArgument: Int) {} // expected-note {{found this candidate}} - class func classMethod(_: Int, withArgument: Int, argument: Int) {} // expected-note {{found this candidate}} - class func classMethod(_: Int, withArgument: Int, argument: Int, argument _:Int) {} // expected-note {{found this candidate}} - - func instMethod(_: Int) {} // expected-note {{found this candidate}} - func instMethod(_: Int, withArgument: Int) {} // expected-note {{found this candidate}} - func instMethod(_: Int, withArgument: Int, argument: Int) {} // expected-note {{found this candidate}} - func instMethod(_: Int, withArgument: Int, argument: Int, argument _:Int) {} // expected-note {{found this candidate}} - - func instMethod(_: Int, overloaded: String) {} // expected-note 2 {{found this candidate}} - func instMethod(_: Int, overloaded: Int) {} // expected-note 2 {{found this candidate}} -} - -let x = C() - -// TODO: Normal method lookup should not find keyword methods -let classM0: (Int) -> () = C.classMethod -let classM1 = C.classMethod:withArgument: -let classM2 = C.classMethod:withArgument:argument: -let classM3 = C.classMethod:withArgument:argument:argument: - -// TODO: recovery -let classMX = C.classMethod: // expected-error{{expected expression}} // expected-error{{ambiguous use of 'classMethod'}} // expected-error{{consecutive statements}} {{28-28=;}} - -// TODO: Normal method lookup should not find keyword methods -let instM0: (Int) -> () = x.instMethod -let instM1 = x.instMethod:withArgument: -let instM2 = x.instMethod:withArgument:argument: -let instM3 = x.instMethod:withArgument:argument:argument: - -let instM4: (Int, String) -> () = x.instMethod:overloaded: -let instM5: (Int, Int) -> () = x.instMethod:overloaded: -// ambiguous -let instM6 = x.instMethod:overloaded: // expected-error{{ambiguous use of 'instMethod(_:overloaded:)'}} - -x.instMethod:overloaded:(1, overloaded: 1) -x.instMethod:overloaded:(1, overloaded: "two") - -let instM7 = x.instMethod:nonexistent: // expected-error{{value of type 'C' has no member 'instMethod(_:nonexistent:)'}} - -// TODO: recovery -let instMX = x.instMethod: // expected-error{{expected expression}} // expected-error{{ambiguous use of 'instMethod'}} // expected-error{{consecutive statements}} {{26-26=;}} diff --git a/test/expr/primary/unqualified_name.swift b/test/expr/primary/unqualified_name.swift new file mode 100644 index 0000000000000..51018a382444d --- /dev/null +++ b/test/expr/primary/unqualified_name.swift @@ -0,0 +1,56 @@ +// RUN: %target-parse-verify-swift + +func f0(x: Int, y: Int, z: Int) { } +func f1(x: Int, while: Int) { } +func f2(x: Int, `let` _: Int) { } + +func test01() { + _ = f0(_:y:z:) + _ = f0(:y:z:) // expected-error{{an empty argument label is spelled with '_'}}{{10-10=_}} + _ = f1(_:`while`:) // expected-warning{{keyword 'while' does not need to be escaped in argument list}}{{12-13=}}{{18-19=}} + _ = f2(_:`let`:) +} + +struct S0 { + func f0(x: Int, y: Int, z: Int) { } + func f1(x: Int, while: Int) { } + func f2(x: Int, `let` _: Int) { } + + func testS0() { + _ = f0(_:y:z:) + _ = f0(:y:z:) // expected-error{{an empty argument label is spelled with '_'}}{{12-12=_}} + _ = f1(_:`while`:) // expected-warning{{keyword 'while' does not need to be escaped in argument list}}{{14-15=}}{{20-21=}} + _ = f2(_:`let`:) + + _ = self.f0(_:y:z:) + _ = self.f0(:y:z:) // expected-error{{an empty argument label is spelled with '_'}}{{17-17=_}} + _ = self.f1(_:`while`:) // expected-warning{{keyword 'while' does not need to be escaped in argument list}}{{19-20=}}{{25-26=}} + _ = self.f2(_:`let`:) + } + + static func f3(x: Int, y: Int, z: Int) -> S0 { return S0() } +} + +// Determine context from type. +let s0_static: S0 = .f3(_:y:z:)(0, y: 0, z: 0) + +class C0 { + func f0(x: Int, y: Int, z: Int) { } + func f1(x: Int, while: Int) { } + func f2(x: Int, `let` _: Int) { } +} + +class C1 : C0 { + func testC0() { + _ = f0(_:y:z:) + _ = f0(:y:z:) // expected-error{{an empty argument label is spelled with '_'}}{{12-12=_}} + _ = f1(_:`while`:) // expected-warning{{keyword 'while' does not need to be escaped in argument list}}{{14-15=}}{{20-21=}} + _ = f2(_:`let`:) + + _ = super.f0(_:y:z:) + _ = super.f0(:y:z:) // expected-error{{an empty argument label is spelled with '_'}}{{18-18=_}} + _ = super.f1(_:`while`:) // expected-warning{{keyword 'while' does not need to be escaped in argument list}}{{20-21=}}{{26-27=}} + _ = self.f2(_:`let`:) + } +} +