@@ -2078,12 +2078,87 @@ void Parser::parseOptionalArgumentLabel(Identifier &name, SourceLoc &loc) {
2078
2078
}
2079
2079
}
2080
2080
2081
- DeclNameRef Parser::parseUnqualifiedDeclBaseName (
2082
- bool afterDot,
2083
- DeclNameLoc &loc,
2084
- const Diagnostic &diag,
2085
- bool allowOperators,
2086
- bool allowDeinitAndSubscript) {
2081
+ static bool tryParseArgLabelList (Parser &P, Parser::DeclNameOptions flags,
2082
+ SourceLoc &lparenLoc,
2083
+ SmallVectorImpl<Identifier> &argumentLabels,
2084
+ SmallVectorImpl<SourceLoc> &argumentLabelLocs,
2085
+ SourceLoc &rparenLoc) {
2086
+ if (!flags.contains (Parser::DeclNameFlag::AllowCompoundNames))
2087
+ return false ;
2088
+
2089
+ // Is the current token a left paren?
2090
+ if (!P.Tok .isFollowingLParen ())
2091
+ return false ;
2092
+
2093
+ // Okay, let's look ahead and see if the next token is something that could
2094
+ // be in an arg label list...
2095
+ const Token &next = P.peekToken ();
2096
+
2097
+ // A close parenthesis, if empty lists are allowed.
2098
+ bool nextIsRParen =
2099
+ flags.contains (Parser::DeclNameFlag::AllowZeroArgCompoundNames) &&
2100
+ next.is (tok::r_paren);
2101
+ // An argument label.
2102
+ bool nextIsArgLabel = next.canBeArgumentLabel () || next.is (tok::colon);
2103
+ // An editor placeholder.
2104
+ bool nextIsPlaceholder = Identifier::isEditorPlaceholder (next.getText ());
2105
+
2106
+ if (!(nextIsRParen || nextIsArgLabel || nextIsPlaceholder))
2107
+ return false ;
2108
+
2109
+ // Try to parse a compound name.
2110
+ SyntaxParsingContext ArgsCtxt (P.SyntaxContext , SyntaxKind::DeclNameArguments);
2111
+ Parser::BacktrackingScope backtrack (P);
2112
+
2113
+ lparenLoc = P.consumeToken (tok::l_paren);
2114
+ while (P.Tok .isNot (tok::r_paren)) {
2115
+ SyntaxParsingContext ArgCtxt (P.SyntaxContext , SyntaxKind::DeclNameArgument);
2116
+
2117
+ // If we see a ':', the user forgot the '_';
2118
+ if (P.Tok .is (tok::colon)) {
2119
+ P.diagnose (P.Tok , diag::empty_arg_label_underscore)
2120
+ .fixItInsert (P.Tok .getLoc (), " _" );
2121
+ argumentLabels.push_back (Identifier ());
2122
+ argumentLabelLocs.push_back (P.consumeToken (tok::colon));
2123
+ }
2124
+
2125
+ Identifier argName;
2126
+ SourceLoc argLoc;
2127
+ P.parseOptionalArgumentLabel (argName, argLoc);
2128
+ if (argLoc.isValid ()) {
2129
+ argumentLabels.push_back (argName);
2130
+ argumentLabelLocs.push_back (argLoc);
2131
+ continue ;
2132
+ }
2133
+
2134
+ // This is not a compound name.
2135
+ // FIXME: Could recover better if we "know" it's a compound name.
2136
+ ArgCtxt.setBackTracking ();
2137
+ ArgsCtxt.setBackTracking ();
2138
+
2139
+ return false ;
2140
+ }
2141
+
2142
+ // We have a compound name. Cancel backtracking and build that name.
2143
+ backtrack.cancelBacktrack ();
2144
+
2145
+ if (argumentLabels.empty () && P.SyntaxContext ->isEnabled ())
2146
+ P.SyntaxContext ->addSyntax (
2147
+ ParsedSyntaxRecorder::makeBlankDeclNameArgumentList (
2148
+ P.leadingTriviaLoc (), *P.SyntaxContext ));
2149
+ else
2150
+ ArgsCtxt.collectNodesInPlace (SyntaxKind::DeclNameArgumentList);
2151
+
2152
+ rparenLoc = P.consumeToken (tok::r_paren);
2153
+
2154
+ assert (argumentLabels.size () == argumentLabelLocs.size ());
2155
+
2156
+ return true ;
2157
+ }
2158
+
2159
+ DeclNameRef Parser::parseDeclNameRef (DeclNameLoc &loc,
2160
+ const Diagnostic &diag,
2161
+ DeclNameOptions flags) {
2087
2162
// Consume the base name.
2088
2163
DeclBaseName baseName;
2089
2164
SourceLoc baseNameLoc;
@@ -2092,17 +2167,21 @@ DeclNameRef Parser::parseUnqualifiedDeclBaseName(
2092
2167
baseNameLoc = consumeIdentifier (
2093
2168
&baseNameId, /* allowDollarIdentifier=*/ true );
2094
2169
baseName = baseNameId;
2095
- } else if (allowOperators && Tok.isAnyOperator ()) {
2170
+ } else if (flags.contains (DeclNameFlag::AllowOperators) &&
2171
+ Tok.isAnyOperator ()) {
2096
2172
baseName = Context.getIdentifier (Tok.getText ());
2097
2173
baseNameLoc = consumeToken ();
2098
- } else if (afterDot && Tok.isKeyword ()) {
2174
+ } else if (flags.contains (DeclNameFlag::AllowKeywords) && Tok.isKeyword ()) {
2175
+ bool specialDeinitAndSubscript =
2176
+ flags.contains (DeclNameFlag::UseSpecialNamesForDeinitAndSubscript);
2177
+
2099
2178
// Syntax highlighting should treat this token as an identifier and
2100
2179
// not as a keyword.
2101
2180
if (Tok.is (tok::kw_init))
2102
2181
baseName = DeclBaseName::createConstructor ();
2103
- else if (allowDeinitAndSubscript &&Tok.is (tok::kw_deinit))
2182
+ else if (specialDeinitAndSubscript && Tok.is (tok::kw_deinit))
2104
2183
baseName = DeclBaseName::createDestructor ();
2105
- else if (allowDeinitAndSubscript &&Tok.is (tok::kw_subscript))
2184
+ else if (specialDeinitAndSubscript && Tok.is (tok::kw_subscript))
2106
2185
baseName = DeclBaseName::createSubscript ();
2107
2186
else
2108
2187
baseName = Context.getIdentifier (Tok.getText ());
@@ -2115,95 +2194,67 @@ DeclNameRef Parser::parseUnqualifiedDeclBaseName(
2115
2194
return DeclNameRef ();
2116
2195
}
2117
2196
2118
- loc = DeclNameLoc (baseNameLoc);
2119
- return DeclNameRef (baseName);
2120
- }
2121
-
2122
-
2123
- DeclNameRef Parser::parseUnqualifiedDeclName (bool afterDot,
2124
- DeclNameLoc &loc,
2125
- const Diagnostic &diag,
2126
- bool allowOperators,
2127
- bool allowZeroArgCompoundNames,
2128
- bool allowDeinitAndSubscript) {
2129
- // Consume the base name.
2130
- auto baseName = parseUnqualifiedDeclBaseName (afterDot, loc, diag,
2131
- allowOperators,
2132
- allowDeinitAndSubscript);
2133
-
2134
- // If the next token isn't a following '(', we don't have a compound name.
2135
- if (!baseName || !Tok.isFollowingLParen ())
2136
- return baseName;
2137
-
2138
- // If the next token is a ')' then we have a 0-arg compound name. This is
2139
- // explicitly differentiated from "simple" (non-compound) name in DeclName.
2140
- // Unfortunately only some places in the grammar are ok with accepting this
2141
- // kind of name; in other places it's ambiguous with trailing calls.
2142
- if (allowZeroArgCompoundNames && peekToken ().is (tok::r_paren)) {
2143
- SyntaxParsingContext ArgsCtxt (SyntaxContext, SyntaxKind::DeclNameArguments);
2144
- consumeToken (tok::l_paren);
2145
- if (SyntaxContext->isEnabled ())
2146
- SyntaxContext->addSyntax (
2147
- ParsedSyntaxRecorder::makeBlankDeclNameArgumentList (
2148
- leadingTriviaLoc (), *SyntaxContext));
2149
- consumeToken (tok::r_paren);
2150
- SmallVector<Identifier, 2 > argumentLabels;
2151
- return baseName.withArgumentLabels (Context, argumentLabels);
2152
- }
2153
-
2154
- // If the token after that isn't an argument label or ':', we don't have a
2155
- // compound name.
2156
- if ((!peekToken ().canBeArgumentLabel () && !peekToken ().is (tok::colon)) ||
2157
- Identifier::isEditorPlaceholder (peekToken ().getText ())) {
2158
- return baseName;
2159
- }
2160
-
2161
- // Try to parse a compound name.
2162
- SyntaxParsingContext ArgsCtxt (SyntaxContext, SyntaxKind::DeclNameArguments);
2163
- BacktrackingScope backtrack (*this );
2164
-
2197
+ // Parse an argument list, if the flags allow it and it's present.
2165
2198
SmallVector<Identifier, 2 > argumentLabels;
2166
2199
SmallVector<SourceLoc, 2 > argumentLabelLocs;
2167
- SourceLoc lparenLoc = consumeToken (tok::l_paren) ;
2200
+ SourceLoc lparenLoc;
2168
2201
SourceLoc rparenLoc;
2169
- while (Tok.isNot (tok::r_paren)) {
2170
- SyntaxParsingContext ArgCtxt (SyntaxContext, SyntaxKind::DeclNameArgument);
2171
2202
2172
- // If we see a ':', the user forgot the '_';
2173
- if (Tok.is (tok::colon)) {
2174
- diagnose (Tok, diag::empty_arg_label_underscore)
2175
- .fixItInsert (Tok.getLoc (), " _" );
2176
- argumentLabels.push_back (Identifier ());
2177
- argumentLabelLocs.push_back (consumeToken (tok::colon));
2178
- }
2203
+ bool hadArgList = tryParseArgLabelList (*this , flags, lparenLoc,
2204
+ argumentLabels, argumentLabelLocs,
2205
+ rparenLoc);
2179
2206
2180
- Identifier argName;
2181
- SourceLoc argLoc;
2182
- parseOptionalArgumentLabel (argName, argLoc);
2183
- if (argLoc.isValid ()) {
2184
- argumentLabels.push_back (argName);
2185
- argumentLabelLocs.push_back (argLoc);
2186
- continue ;
2187
- }
2207
+ if (argumentLabelLocs.empty () || !hadArgList)
2208
+ loc = DeclNameLoc (baseNameLoc);
2209
+ else
2210
+ loc = DeclNameLoc (Context, baseNameLoc, lparenLoc, argumentLabelLocs,
2211
+ rparenLoc);
2188
2212
2189
- // This is not a compound name.
2190
- // FIXME: Could recover better if we "know" it's a compound name.
2191
- ArgCtxt.setBackTracking ();
2192
- ArgsCtxt.setBackTracking ();
2193
- return baseName;
2213
+ if (!hadArgList)
2214
+ return DeclNameRef (baseName);
2215
+
2216
+ return DeclNameRef ({ Context, baseName, argumentLabels });
2217
+ }
2218
+
2219
+ DeclNameRef Parser::parseUnqualifiedDeclBaseName (
2220
+ bool afterDot,
2221
+ DeclNameLoc &loc,
2222
+ const Diagnostic &diag,
2223
+ bool allowOperators,
2224
+ bool allowDeinitAndSubscript) {
2225
+ DeclNameOptions flags = {};
2226
+ if (afterDot)
2227
+ flags |= DeclNameFlag::AllowKeywords;
2228
+ if (allowOperators)
2229
+ flags |= DeclNameFlag::AllowOperators;
2230
+ if (allowDeinitAndSubscript) {
2231
+ assert (afterDot);
2232
+ flags |= DeclNameFlag::UseSpecialNamesForDeinitAndSubscript;
2194
2233
}
2195
- // We have a compound name. Cancel backtracking and build that name.
2196
- backtrack.cancelBacktrack ();
2197
2234
2198
- ArgsCtxt. collectNodesInPlace (SyntaxKind::DeclNameArgumentList );
2199
- rparenLoc = consumeToken (tok::r_paren);
2235
+ return parseDeclNameRef (loc, diag, flags );
2236
+ }
2200
2237
2201
- assert (!argumentLabels.empty () && " Logic above should prevent this" );
2202
- assert (argumentLabels.size () == argumentLabelLocs.size ());
2203
2238
2204
- loc = DeclNameLoc (Context, loc.getBaseNameLoc (), lparenLoc, argumentLabelLocs,
2205
- rparenLoc);
2206
- return baseName.withArgumentLabels (Context, argumentLabels);
2239
+ DeclNameRef Parser::parseUnqualifiedDeclName (bool afterDot,
2240
+ DeclNameLoc &loc,
2241
+ const Diagnostic &diag,
2242
+ bool allowOperators,
2243
+ bool allowZeroArgCompoundNames,
2244
+ bool allowDeinitAndSubscript) {
2245
+ DeclNameOptions flags = DeclNameFlag::AllowCompoundNames;
2246
+ if (afterDot)
2247
+ flags |= DeclNameFlag::AllowKeywords;
2248
+ if (allowOperators)
2249
+ flags |= DeclNameFlag::AllowOperators;
2250
+ if (allowDeinitAndSubscript) {
2251
+ assert (afterDot);
2252
+ flags |= DeclNameFlag::UseSpecialNamesForDeinitAndSubscript;
2253
+ }
2254
+ if (allowZeroArgCompoundNames)
2255
+ flags |= DeclNameFlag::AllowZeroArgCompoundNames;
2256
+
2257
+ return parseDeclNameRef (loc, diag, flags);
2207
2258
}
2208
2259
2209
2260
// / expr-identifier:
0 commit comments