Mercurial > hg > CbC > CbC_llvm
comparison clang/lib/Parse/ParseObjc.cpp @ 150:1d019706d866
LLVM10
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 15:10:13 +0900 |
parents | |
children | 0572611fdcc8 |
comparison
equal
deleted
inserted
replaced
147:c2174574ed3a | 150:1d019706d866 |
---|---|
1 //===--- ParseObjC.cpp - Objective C Parsing ------------------------------===// | |
2 // | |
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
4 // See https://llvm.org/LICENSE.txt for license information. | |
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
6 // | |
7 //===----------------------------------------------------------------------===// | |
8 // | |
9 // This file implements the Objective-C portions of the Parser interface. | |
10 // | |
11 //===----------------------------------------------------------------------===// | |
12 | |
13 #include "clang/Parse/Parser.h" | |
14 #include "clang/AST/ASTContext.h" | |
15 #include "clang/AST/PrettyDeclStackTrace.h" | |
16 #include "clang/Basic/CharInfo.h" | |
17 #include "clang/Parse/ParseDiagnostic.h" | |
18 #include "clang/Parse/RAIIObjectsForParser.h" | |
19 #include "clang/Sema/DeclSpec.h" | |
20 #include "clang/Sema/Scope.h" | |
21 #include "llvm/ADT/SmallVector.h" | |
22 #include "llvm/ADT/StringExtras.h" | |
23 | |
24 using namespace clang; | |
25 | |
26 /// Skips attributes after an Objective-C @ directive. Emits a diagnostic. | |
27 void Parser::MaybeSkipAttributes(tok::ObjCKeywordKind Kind) { | |
28 ParsedAttributes attrs(AttrFactory); | |
29 if (Tok.is(tok::kw___attribute)) { | |
30 if (Kind == tok::objc_interface || Kind == tok::objc_protocol) | |
31 Diag(Tok, diag::err_objc_postfix_attribute_hint) | |
32 << (Kind == tok::objc_protocol); | |
33 else | |
34 Diag(Tok, diag::err_objc_postfix_attribute); | |
35 ParseGNUAttributes(attrs); | |
36 } | |
37 } | |
38 | |
39 /// ParseObjCAtDirectives - Handle parts of the external-declaration production: | |
40 /// external-declaration: [C99 6.9] | |
41 /// [OBJC] objc-class-definition | |
42 /// [OBJC] objc-class-declaration | |
43 /// [OBJC] objc-alias-declaration | |
44 /// [OBJC] objc-protocol-definition | |
45 /// [OBJC] objc-method-definition | |
46 /// [OBJC] '@' 'end' | |
47 Parser::DeclGroupPtrTy | |
48 Parser::ParseObjCAtDirectives(ParsedAttributesWithRange &Attrs) { | |
49 SourceLocation AtLoc = ConsumeToken(); // the "@" | |
50 | |
51 if (Tok.is(tok::code_completion)) { | |
52 Actions.CodeCompleteObjCAtDirective(getCurScope()); | |
53 cutOffParsing(); | |
54 return nullptr; | |
55 } | |
56 | |
57 Decl *SingleDecl = nullptr; | |
58 switch (Tok.getObjCKeywordID()) { | |
59 case tok::objc_class: | |
60 return ParseObjCAtClassDeclaration(AtLoc); | |
61 case tok::objc_interface: | |
62 SingleDecl = ParseObjCAtInterfaceDeclaration(AtLoc, Attrs); | |
63 break; | |
64 case tok::objc_protocol: | |
65 return ParseObjCAtProtocolDeclaration(AtLoc, Attrs); | |
66 case tok::objc_implementation: | |
67 return ParseObjCAtImplementationDeclaration(AtLoc, Attrs); | |
68 case tok::objc_end: | |
69 return ParseObjCAtEndDeclaration(AtLoc); | |
70 case tok::objc_compatibility_alias: | |
71 SingleDecl = ParseObjCAtAliasDeclaration(AtLoc); | |
72 break; | |
73 case tok::objc_synthesize: | |
74 SingleDecl = ParseObjCPropertySynthesize(AtLoc); | |
75 break; | |
76 case tok::objc_dynamic: | |
77 SingleDecl = ParseObjCPropertyDynamic(AtLoc); | |
78 break; | |
79 case tok::objc_import: | |
80 if (getLangOpts().Modules || getLangOpts().DebuggerSupport) { | |
81 SingleDecl = ParseModuleImport(AtLoc); | |
82 break; | |
83 } | |
84 Diag(AtLoc, diag::err_atimport); | |
85 SkipUntil(tok::semi); | |
86 return Actions.ConvertDeclToDeclGroup(nullptr); | |
87 default: | |
88 Diag(AtLoc, diag::err_unexpected_at); | |
89 SkipUntil(tok::semi); | |
90 SingleDecl = nullptr; | |
91 break; | |
92 } | |
93 return Actions.ConvertDeclToDeclGroup(SingleDecl); | |
94 } | |
95 | |
96 /// Class to handle popping type parameters when leaving the scope. | |
97 class Parser::ObjCTypeParamListScope { | |
98 Sema &Actions; | |
99 Scope *S; | |
100 ObjCTypeParamList *Params; | |
101 | |
102 public: | |
103 ObjCTypeParamListScope(Sema &Actions, Scope *S) | |
104 : Actions(Actions), S(S), Params(nullptr) {} | |
105 | |
106 ~ObjCTypeParamListScope() { | |
107 leave(); | |
108 } | |
109 | |
110 void enter(ObjCTypeParamList *P) { | |
111 assert(!Params); | |
112 Params = P; | |
113 } | |
114 | |
115 void leave() { | |
116 if (Params) | |
117 Actions.popObjCTypeParamList(S, Params); | |
118 Params = nullptr; | |
119 } | |
120 }; | |
121 | |
122 /// | |
123 /// objc-class-declaration: | |
124 /// '@' 'class' objc-class-forward-decl (',' objc-class-forward-decl)* ';' | |
125 /// | |
126 /// objc-class-forward-decl: | |
127 /// identifier objc-type-parameter-list[opt] | |
128 /// | |
129 Parser::DeclGroupPtrTy | |
130 Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) { | |
131 ConsumeToken(); // the identifier "class" | |
132 SmallVector<IdentifierInfo *, 8> ClassNames; | |
133 SmallVector<SourceLocation, 8> ClassLocs; | |
134 SmallVector<ObjCTypeParamList *, 8> ClassTypeParams; | |
135 | |
136 while (1) { | |
137 MaybeSkipAttributes(tok::objc_class); | |
138 if (expectIdentifier()) { | |
139 SkipUntil(tok::semi); | |
140 return Actions.ConvertDeclToDeclGroup(nullptr); | |
141 } | |
142 ClassNames.push_back(Tok.getIdentifierInfo()); | |
143 ClassLocs.push_back(Tok.getLocation()); | |
144 ConsumeToken(); | |
145 | |
146 // Parse the optional objc-type-parameter-list. | |
147 ObjCTypeParamList *TypeParams = nullptr; | |
148 if (Tok.is(tok::less)) | |
149 TypeParams = parseObjCTypeParamList(); | |
150 ClassTypeParams.push_back(TypeParams); | |
151 if (!TryConsumeToken(tok::comma)) | |
152 break; | |
153 } | |
154 | |
155 // Consume the ';'. | |
156 if (ExpectAndConsume(tok::semi, diag::err_expected_after, "@class")) | |
157 return Actions.ConvertDeclToDeclGroup(nullptr); | |
158 | |
159 return Actions.ActOnForwardClassDeclaration(atLoc, ClassNames.data(), | |
160 ClassLocs.data(), | |
161 ClassTypeParams, | |
162 ClassNames.size()); | |
163 } | |
164 | |
165 void Parser::CheckNestedObjCContexts(SourceLocation AtLoc) | |
166 { | |
167 Sema::ObjCContainerKind ock = Actions.getObjCContainerKind(); | |
168 if (ock == Sema::OCK_None) | |
169 return; | |
170 | |
171 Decl *Decl = Actions.getObjCDeclContext(); | |
172 if (CurParsedObjCImpl) { | |
173 CurParsedObjCImpl->finish(AtLoc); | |
174 } else { | |
175 Actions.ActOnAtEnd(getCurScope(), AtLoc); | |
176 } | |
177 Diag(AtLoc, diag::err_objc_missing_end) | |
178 << FixItHint::CreateInsertion(AtLoc, "@end\n"); | |
179 if (Decl) | |
180 Diag(Decl->getBeginLoc(), diag::note_objc_container_start) << (int)ock; | |
181 } | |
182 | |
183 /// | |
184 /// objc-interface: | |
185 /// objc-class-interface-attributes[opt] objc-class-interface | |
186 /// objc-category-interface | |
187 /// | |
188 /// objc-class-interface: | |
189 /// '@' 'interface' identifier objc-type-parameter-list[opt] | |
190 /// objc-superclass[opt] objc-protocol-refs[opt] | |
191 /// objc-class-instance-variables[opt] | |
192 /// objc-interface-decl-list | |
193 /// @end | |
194 /// | |
195 /// objc-category-interface: | |
196 /// '@' 'interface' identifier objc-type-parameter-list[opt] | |
197 /// '(' identifier[opt] ')' objc-protocol-refs[opt] | |
198 /// objc-interface-decl-list | |
199 /// @end | |
200 /// | |
201 /// objc-superclass: | |
202 /// ':' identifier objc-type-arguments[opt] | |
203 /// | |
204 /// objc-class-interface-attributes: | |
205 /// __attribute__((visibility("default"))) | |
206 /// __attribute__((visibility("hidden"))) | |
207 /// __attribute__((deprecated)) | |
208 /// __attribute__((unavailable)) | |
209 /// __attribute__((objc_exception)) - used by NSException on 64-bit | |
210 /// __attribute__((objc_root_class)) | |
211 /// | |
212 Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, | |
213 ParsedAttributes &attrs) { | |
214 assert(Tok.isObjCAtKeyword(tok::objc_interface) && | |
215 "ParseObjCAtInterfaceDeclaration(): Expected @interface"); | |
216 CheckNestedObjCContexts(AtLoc); | |
217 ConsumeToken(); // the "interface" identifier | |
218 | |
219 // Code completion after '@interface'. | |
220 if (Tok.is(tok::code_completion)) { | |
221 Actions.CodeCompleteObjCInterfaceDecl(getCurScope()); | |
222 cutOffParsing(); | |
223 return nullptr; | |
224 } | |
225 | |
226 MaybeSkipAttributes(tok::objc_interface); | |
227 | |
228 if (expectIdentifier()) | |
229 return nullptr; // missing class or category name. | |
230 | |
231 // We have a class or category name - consume it. | |
232 IdentifierInfo *nameId = Tok.getIdentifierInfo(); | |
233 SourceLocation nameLoc = ConsumeToken(); | |
234 | |
235 // Parse the objc-type-parameter-list or objc-protocol-refs. For the latter | |
236 // case, LAngleLoc will be valid and ProtocolIdents will capture the | |
237 // protocol references (that have not yet been resolved). | |
238 SourceLocation LAngleLoc, EndProtoLoc; | |
239 SmallVector<IdentifierLocPair, 8> ProtocolIdents; | |
240 ObjCTypeParamList *typeParameterList = nullptr; | |
241 ObjCTypeParamListScope typeParamScope(Actions, getCurScope()); | |
242 if (Tok.is(tok::less)) | |
243 typeParameterList = parseObjCTypeParamListOrProtocolRefs( | |
244 typeParamScope, LAngleLoc, ProtocolIdents, EndProtoLoc); | |
245 | |
246 if (Tok.is(tok::l_paren) && | |
247 !isKnownToBeTypeSpecifier(GetLookAheadToken(1))) { // we have a category. | |
248 | |
249 BalancedDelimiterTracker T(*this, tok::l_paren); | |
250 T.consumeOpen(); | |
251 | |
252 SourceLocation categoryLoc; | |
253 IdentifierInfo *categoryId = nullptr; | |
254 if (Tok.is(tok::code_completion)) { | |
255 Actions.CodeCompleteObjCInterfaceCategory(getCurScope(), nameId, nameLoc); | |
256 cutOffParsing(); | |
257 return nullptr; | |
258 } | |
259 | |
260 // For ObjC2, the category name is optional (not an error). | |
261 if (Tok.is(tok::identifier)) { | |
262 categoryId = Tok.getIdentifierInfo(); | |
263 categoryLoc = ConsumeToken(); | |
264 } | |
265 else if (!getLangOpts().ObjC) { | |
266 Diag(Tok, diag::err_expected) | |
267 << tok::identifier; // missing category name. | |
268 return nullptr; | |
269 } | |
270 | |
271 T.consumeClose(); | |
272 if (T.getCloseLocation().isInvalid()) | |
273 return nullptr; | |
274 | |
275 // Next, we need to check for any protocol references. | |
276 assert(LAngleLoc.isInvalid() && "Cannot have already parsed protocols"); | |
277 SmallVector<Decl *, 8> ProtocolRefs; | |
278 SmallVector<SourceLocation, 8> ProtocolLocs; | |
279 if (Tok.is(tok::less) && | |
280 ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true, true, | |
281 LAngleLoc, EndProtoLoc, | |
282 /*consumeLastToken=*/true)) | |
283 return nullptr; | |
284 | |
285 Decl *CategoryType = Actions.ActOnStartCategoryInterface( | |
286 AtLoc, nameId, nameLoc, typeParameterList, categoryId, categoryLoc, | |
287 ProtocolRefs.data(), ProtocolRefs.size(), ProtocolLocs.data(), | |
288 EndProtoLoc, attrs); | |
289 | |
290 if (Tok.is(tok::l_brace)) | |
291 ParseObjCClassInstanceVariables(CategoryType, tok::objc_private, AtLoc); | |
292 | |
293 ParseObjCInterfaceDeclList(tok::objc_not_keyword, CategoryType); | |
294 | |
295 return CategoryType; | |
296 } | |
297 // Parse a class interface. | |
298 IdentifierInfo *superClassId = nullptr; | |
299 SourceLocation superClassLoc; | |
300 SourceLocation typeArgsLAngleLoc; | |
301 SmallVector<ParsedType, 4> typeArgs; | |
302 SourceLocation typeArgsRAngleLoc; | |
303 SmallVector<Decl *, 4> protocols; | |
304 SmallVector<SourceLocation, 4> protocolLocs; | |
305 if (Tok.is(tok::colon)) { // a super class is specified. | |
306 ConsumeToken(); | |
307 | |
308 // Code completion of superclass names. | |
309 if (Tok.is(tok::code_completion)) { | |
310 Actions.CodeCompleteObjCSuperclass(getCurScope(), nameId, nameLoc); | |
311 cutOffParsing(); | |
312 return nullptr; | |
313 } | |
314 | |
315 if (expectIdentifier()) | |
316 return nullptr; // missing super class name. | |
317 superClassId = Tok.getIdentifierInfo(); | |
318 superClassLoc = ConsumeToken(); | |
319 | |
320 // Type arguments for the superclass or protocol conformances. | |
321 if (Tok.is(tok::less)) { | |
322 parseObjCTypeArgsOrProtocolQualifiers( | |
323 nullptr, typeArgsLAngleLoc, typeArgs, typeArgsRAngleLoc, LAngleLoc, | |
324 protocols, protocolLocs, EndProtoLoc, | |
325 /*consumeLastToken=*/true, | |
326 /*warnOnIncompleteProtocols=*/true); | |
327 if (Tok.is(tok::eof)) | |
328 return nullptr; | |
329 } | |
330 } | |
331 | |
332 // Next, we need to check for any protocol references. | |
333 if (LAngleLoc.isValid()) { | |
334 if (!ProtocolIdents.empty()) { | |
335 // We already parsed the protocols named when we thought we had a | |
336 // type parameter list. Translate them into actual protocol references. | |
337 for (const auto &pair : ProtocolIdents) { | |
338 protocolLocs.push_back(pair.second); | |
339 } | |
340 Actions.FindProtocolDeclaration(/*WarnOnDeclarations=*/true, | |
341 /*ForObjCContainer=*/true, | |
342 ProtocolIdents, protocols); | |
343 } | |
344 } else if (protocols.empty() && Tok.is(tok::less) && | |
345 ParseObjCProtocolReferences(protocols, protocolLocs, true, true, | |
346 LAngleLoc, EndProtoLoc, | |
347 /*consumeLastToken=*/true)) { | |
348 return nullptr; | |
349 } | |
350 | |
351 if (Tok.isNot(tok::less)) | |
352 Actions.ActOnTypedefedProtocols(protocols, protocolLocs, | |
353 superClassId, superClassLoc); | |
354 | |
355 Decl *ClsType = Actions.ActOnStartClassInterface( | |
356 getCurScope(), AtLoc, nameId, nameLoc, typeParameterList, superClassId, | |
357 superClassLoc, typeArgs, | |
358 SourceRange(typeArgsLAngleLoc, typeArgsRAngleLoc), protocols.data(), | |
359 protocols.size(), protocolLocs.data(), EndProtoLoc, attrs); | |
360 | |
361 if (Tok.is(tok::l_brace)) | |
362 ParseObjCClassInstanceVariables(ClsType, tok::objc_protected, AtLoc); | |
363 | |
364 ParseObjCInterfaceDeclList(tok::objc_interface, ClsType); | |
365 | |
366 return ClsType; | |
367 } | |
368 | |
369 /// Add an attribute for a context-sensitive type nullability to the given | |
370 /// declarator. | |
371 static void addContextSensitiveTypeNullability(Parser &P, | |
372 Declarator &D, | |
373 NullabilityKind nullability, | |
374 SourceLocation nullabilityLoc, | |
375 bool &addedToDeclSpec) { | |
376 // Create the attribute. | |
377 auto getNullabilityAttr = [&](AttributePool &Pool) -> ParsedAttr * { | |
378 return Pool.create(P.getNullabilityKeyword(nullability), | |
379 SourceRange(nullabilityLoc), nullptr, SourceLocation(), | |
380 nullptr, 0, ParsedAttr::AS_ContextSensitiveKeyword); | |
381 }; | |
382 | |
383 if (D.getNumTypeObjects() > 0) { | |
384 // Add the attribute to the declarator chunk nearest the declarator. | |
385 D.getTypeObject(0).getAttrs().addAtEnd( | |
386 getNullabilityAttr(D.getAttributePool())); | |
387 } else if (!addedToDeclSpec) { | |
388 // Otherwise, just put it on the declaration specifiers (if one | |
389 // isn't there already). | |
390 D.getMutableDeclSpec().getAttributes().addAtEnd( | |
391 getNullabilityAttr(D.getMutableDeclSpec().getAttributes().getPool())); | |
392 addedToDeclSpec = true; | |
393 } | |
394 } | |
395 | |
396 /// Parse an Objective-C type parameter list, if present, or capture | |
397 /// the locations of the protocol identifiers for a list of protocol | |
398 /// references. | |
399 /// | |
400 /// objc-type-parameter-list: | |
401 /// '<' objc-type-parameter (',' objc-type-parameter)* '>' | |
402 /// | |
403 /// objc-type-parameter: | |
404 /// objc-type-parameter-variance? identifier objc-type-parameter-bound[opt] | |
405 /// | |
406 /// objc-type-parameter-bound: | |
407 /// ':' type-name | |
408 /// | |
409 /// objc-type-parameter-variance: | |
410 /// '__covariant' | |
411 /// '__contravariant' | |
412 /// | |
413 /// \param lAngleLoc The location of the starting '<'. | |
414 /// | |
415 /// \param protocolIdents Will capture the list of identifiers, if the | |
416 /// angle brackets contain a list of protocol references rather than a | |
417 /// type parameter list. | |
418 /// | |
419 /// \param rAngleLoc The location of the ending '>'. | |
420 ObjCTypeParamList *Parser::parseObjCTypeParamListOrProtocolRefs( | |
421 ObjCTypeParamListScope &Scope, SourceLocation &lAngleLoc, | |
422 SmallVectorImpl<IdentifierLocPair> &protocolIdents, | |
423 SourceLocation &rAngleLoc, bool mayBeProtocolList) { | |
424 assert(Tok.is(tok::less) && "Not at the beginning of a type parameter list"); | |
425 | |
426 // Within the type parameter list, don't treat '>' as an operator. | |
427 GreaterThanIsOperatorScope G(GreaterThanIsOperator, false); | |
428 | |
429 // Local function to "flush" the protocol identifiers, turning them into | |
430 // type parameters. | |
431 SmallVector<Decl *, 4> typeParams; | |
432 auto makeProtocolIdentsIntoTypeParameters = [&]() { | |
433 unsigned index = 0; | |
434 for (const auto &pair : protocolIdents) { | |
435 DeclResult typeParam = Actions.actOnObjCTypeParam( | |
436 getCurScope(), ObjCTypeParamVariance::Invariant, SourceLocation(), | |
437 index++, pair.first, pair.second, SourceLocation(), nullptr); | |
438 if (typeParam.isUsable()) | |
439 typeParams.push_back(typeParam.get()); | |
440 } | |
441 | |
442 protocolIdents.clear(); | |
443 mayBeProtocolList = false; | |
444 }; | |
445 | |
446 bool invalid = false; | |
447 lAngleLoc = ConsumeToken(); | |
448 | |
449 do { | |
450 // Parse the variance, if any. | |
451 SourceLocation varianceLoc; | |
452 ObjCTypeParamVariance variance = ObjCTypeParamVariance::Invariant; | |
453 if (Tok.is(tok::kw___covariant) || Tok.is(tok::kw___contravariant)) { | |
454 variance = Tok.is(tok::kw___covariant) | |
455 ? ObjCTypeParamVariance::Covariant | |
456 : ObjCTypeParamVariance::Contravariant; | |
457 varianceLoc = ConsumeToken(); | |
458 | |
459 // Once we've seen a variance specific , we know this is not a | |
460 // list of protocol references. | |
461 if (mayBeProtocolList) { | |
462 // Up until now, we have been queuing up parameters because they | |
463 // might be protocol references. Turn them into parameters now. | |
464 makeProtocolIdentsIntoTypeParameters(); | |
465 } | |
466 } | |
467 | |
468 // Parse the identifier. | |
469 if (!Tok.is(tok::identifier)) { | |
470 // Code completion. | |
471 if (Tok.is(tok::code_completion)) { | |
472 // FIXME: If these aren't protocol references, we'll need different | |
473 // completions. | |
474 Actions.CodeCompleteObjCProtocolReferences(protocolIdents); | |
475 cutOffParsing(); | |
476 | |
477 // FIXME: Better recovery here?. | |
478 return nullptr; | |
479 } | |
480 | |
481 Diag(Tok, diag::err_objc_expected_type_parameter); | |
482 invalid = true; | |
483 break; | |
484 } | |
485 | |
486 IdentifierInfo *paramName = Tok.getIdentifierInfo(); | |
487 SourceLocation paramLoc = ConsumeToken(); | |
488 | |
489 // If there is a bound, parse it. | |
490 SourceLocation colonLoc; | |
491 TypeResult boundType; | |
492 if (TryConsumeToken(tok::colon, colonLoc)) { | |
493 // Once we've seen a bound, we know this is not a list of protocol | |
494 // references. | |
495 if (mayBeProtocolList) { | |
496 // Up until now, we have been queuing up parameters because they | |
497 // might be protocol references. Turn them into parameters now. | |
498 makeProtocolIdentsIntoTypeParameters(); | |
499 } | |
500 | |
501 // type-name | |
502 boundType = ParseTypeName(); | |
503 if (boundType.isInvalid()) | |
504 invalid = true; | |
505 } else if (mayBeProtocolList) { | |
506 // If this could still be a protocol list, just capture the identifier. | |
507 // We don't want to turn it into a parameter. | |
508 protocolIdents.push_back(std::make_pair(paramName, paramLoc)); | |
509 continue; | |
510 } | |
511 | |
512 // Create the type parameter. | |
513 DeclResult typeParam = Actions.actOnObjCTypeParam( | |
514 getCurScope(), variance, varianceLoc, typeParams.size(), paramName, | |
515 paramLoc, colonLoc, boundType.isUsable() ? boundType.get() : nullptr); | |
516 if (typeParam.isUsable()) | |
517 typeParams.push_back(typeParam.get()); | |
518 } while (TryConsumeToken(tok::comma)); | |
519 | |
520 // Parse the '>'. | |
521 if (invalid) { | |
522 SkipUntil(tok::greater, tok::at, StopBeforeMatch); | |
523 if (Tok.is(tok::greater)) | |
524 ConsumeToken(); | |
525 } else if (ParseGreaterThanInTemplateList(rAngleLoc, | |
526 /*ConsumeLastToken=*/true, | |
527 /*ObjCGenericList=*/true)) { | |
528 Diag(lAngleLoc, diag::note_matching) << "'<'"; | |
529 SkipUntil({tok::greater, tok::greaterequal, tok::at, tok::minus, | |
530 tok::minus, tok::plus, tok::colon, tok::l_paren, tok::l_brace, | |
531 tok::comma, tok::semi }, | |
532 StopBeforeMatch); | |
533 if (Tok.is(tok::greater)) | |
534 ConsumeToken(); | |
535 } | |
536 | |
537 if (mayBeProtocolList) { | |
538 // A type parameter list must be followed by either a ':' (indicating the | |
539 // presence of a superclass) or a '(' (indicating that this is a category | |
540 // or extension). This disambiguates between an objc-type-parameter-list | |
541 // and a objc-protocol-refs. | |
542 if (Tok.isNot(tok::colon) && Tok.isNot(tok::l_paren)) { | |
543 // Returning null indicates that we don't have a type parameter list. | |
544 // The results the caller needs to handle the protocol references are | |
545 // captured in the reference parameters already. | |
546 return nullptr; | |
547 } | |
548 | |
549 // We have a type parameter list that looks like a list of protocol | |
550 // references. Turn that parameter list into type parameters. | |
551 makeProtocolIdentsIntoTypeParameters(); | |
552 } | |
553 | |
554 // Form the type parameter list and enter its scope. | |
555 ObjCTypeParamList *list = Actions.actOnObjCTypeParamList( | |
556 getCurScope(), | |
557 lAngleLoc, | |
558 typeParams, | |
559 rAngleLoc); | |
560 Scope.enter(list); | |
561 | |
562 // Clear out the angle locations; they're used by the caller to indicate | |
563 // whether there are any protocol references. | |
564 lAngleLoc = SourceLocation(); | |
565 rAngleLoc = SourceLocation(); | |
566 return invalid ? nullptr : list; | |
567 } | |
568 | |
569 /// Parse an objc-type-parameter-list. | |
570 ObjCTypeParamList *Parser::parseObjCTypeParamList() { | |
571 SourceLocation lAngleLoc; | |
572 SmallVector<IdentifierLocPair, 1> protocolIdents; | |
573 SourceLocation rAngleLoc; | |
574 | |
575 ObjCTypeParamListScope Scope(Actions, getCurScope()); | |
576 return parseObjCTypeParamListOrProtocolRefs(Scope, lAngleLoc, protocolIdents, | |
577 rAngleLoc, | |
578 /*mayBeProtocolList=*/false); | |
579 } | |
580 | |
581 /// objc-interface-decl-list: | |
582 /// empty | |
583 /// objc-interface-decl-list objc-property-decl [OBJC2] | |
584 /// objc-interface-decl-list objc-method-requirement [OBJC2] | |
585 /// objc-interface-decl-list objc-method-proto ';' | |
586 /// objc-interface-decl-list declaration | |
587 /// objc-interface-decl-list ';' | |
588 /// | |
589 /// objc-method-requirement: [OBJC2] | |
590 /// @required | |
591 /// @optional | |
592 /// | |
593 void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey, | |
594 Decl *CDecl) { | |
595 SmallVector<Decl *, 32> allMethods; | |
596 SmallVector<DeclGroupPtrTy, 8> allTUVariables; | |
597 tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword; | |
598 | |
599 SourceRange AtEnd; | |
600 | |
601 while (1) { | |
602 // If this is a method prototype, parse it. | |
603 if (Tok.isOneOf(tok::minus, tok::plus)) { | |
604 if (Decl *methodPrototype = | |
605 ParseObjCMethodPrototype(MethodImplKind, false)) | |
606 allMethods.push_back(methodPrototype); | |
607 // Consume the ';' here, since ParseObjCMethodPrototype() is re-used for | |
608 // method definitions. | |
609 if (ExpectAndConsumeSemi(diag::err_expected_semi_after_method_proto)) { | |
610 // We didn't find a semi and we error'ed out. Skip until a ';' or '@'. | |
611 SkipUntil(tok::at, StopAtSemi | StopBeforeMatch); | |
612 if (Tok.is(tok::semi)) | |
613 ConsumeToken(); | |
614 } | |
615 continue; | |
616 } | |
617 if (Tok.is(tok::l_paren)) { | |
618 Diag(Tok, diag::err_expected_minus_or_plus); | |
619 ParseObjCMethodDecl(Tok.getLocation(), | |
620 tok::minus, | |
621 MethodImplKind, false); | |
622 continue; | |
623 } | |
624 // Ignore excess semicolons. | |
625 if (Tok.is(tok::semi)) { | |
626 // FIXME: This should use ConsumeExtraSemi() for extraneous semicolons, | |
627 // to make -Wextra-semi diagnose them. | |
628 ConsumeToken(); | |
629 continue; | |
630 } | |
631 | |
632 // If we got to the end of the file, exit the loop. | |
633 if (isEofOrEom()) | |
634 break; | |
635 | |
636 // Code completion within an Objective-C interface. | |
637 if (Tok.is(tok::code_completion)) { | |
638 Actions.CodeCompleteOrdinaryName(getCurScope(), | |
639 CurParsedObjCImpl? Sema::PCC_ObjCImplementation | |
640 : Sema::PCC_ObjCInterface); | |
641 return cutOffParsing(); | |
642 } | |
643 | |
644 // If we don't have an @ directive, parse it as a function definition. | |
645 if (Tok.isNot(tok::at)) { | |
646 // The code below does not consume '}'s because it is afraid of eating the | |
647 // end of a namespace. Because of the way this code is structured, an | |
648 // erroneous r_brace would cause an infinite loop if not handled here. | |
649 if (Tok.is(tok::r_brace)) | |
650 break; | |
651 | |
652 ParsedAttributesWithRange attrs(AttrFactory); | |
653 | |
654 // Since we call ParseDeclarationOrFunctionDefinition() instead of | |
655 // ParseExternalDeclaration() below (so that this doesn't parse nested | |
656 // @interfaces), this needs to duplicate some code from the latter. | |
657 if (Tok.isOneOf(tok::kw_static_assert, tok::kw__Static_assert)) { | |
658 SourceLocation DeclEnd; | |
659 allTUVariables.push_back( | |
660 ParseDeclaration(DeclaratorContext::FileContext, DeclEnd, attrs)); | |
661 continue; | |
662 } | |
663 | |
664 allTUVariables.push_back(ParseDeclarationOrFunctionDefinition(attrs)); | |
665 continue; | |
666 } | |
667 | |
668 // Otherwise, we have an @ directive, eat the @. | |
669 SourceLocation AtLoc = ConsumeToken(); // the "@" | |
670 if (Tok.is(tok::code_completion)) { | |
671 Actions.CodeCompleteObjCAtDirective(getCurScope()); | |
672 return cutOffParsing(); | |
673 } | |
674 | |
675 tok::ObjCKeywordKind DirectiveKind = Tok.getObjCKeywordID(); | |
676 | |
677 if (DirectiveKind == tok::objc_end) { // @end -> terminate list | |
678 AtEnd.setBegin(AtLoc); | |
679 AtEnd.setEnd(Tok.getLocation()); | |
680 break; | |
681 } else if (DirectiveKind == tok::objc_not_keyword) { | |
682 Diag(Tok, diag::err_objc_unknown_at); | |
683 SkipUntil(tok::semi); | |
684 continue; | |
685 } | |
686 | |
687 // Eat the identifier. | |
688 ConsumeToken(); | |
689 | |
690 switch (DirectiveKind) { | |
691 default: | |
692 // FIXME: If someone forgets an @end on a protocol, this loop will | |
693 // continue to eat up tons of stuff and spew lots of nonsense errors. It | |
694 // would probably be better to bail out if we saw an @class or @interface | |
695 // or something like that. | |
696 Diag(AtLoc, diag::err_objc_illegal_interface_qual); | |
697 // Skip until we see an '@' or '}' or ';'. | |
698 SkipUntil(tok::r_brace, tok::at, StopAtSemi); | |
699 break; | |
700 | |
701 case tok::objc_implementation: | |
702 case tok::objc_interface: | |
703 Diag(AtLoc, diag::err_objc_missing_end) | |
704 << FixItHint::CreateInsertion(AtLoc, "@end\n"); | |
705 Diag(CDecl->getBeginLoc(), diag::note_objc_container_start) | |
706 << (int)Actions.getObjCContainerKind(); | |
707 ConsumeToken(); | |
708 break; | |
709 | |
710 case tok::objc_required: | |
711 case tok::objc_optional: | |
712 // This is only valid on protocols. | |
713 if (contextKey != tok::objc_protocol) | |
714 Diag(AtLoc, diag::err_objc_directive_only_in_protocol); | |
715 else | |
716 MethodImplKind = DirectiveKind; | |
717 break; | |
718 | |
719 case tok::objc_property: | |
720 ObjCDeclSpec OCDS; | |
721 SourceLocation LParenLoc; | |
722 // Parse property attribute list, if any. | |
723 if (Tok.is(tok::l_paren)) { | |
724 LParenLoc = Tok.getLocation(); | |
725 ParseObjCPropertyAttribute(OCDS); | |
726 } | |
727 | |
728 bool addedToDeclSpec = false; | |
729 auto ObjCPropertyCallback = [&](ParsingFieldDeclarator &FD) { | |
730 if (FD.D.getIdentifier() == nullptr) { | |
731 Diag(AtLoc, diag::err_objc_property_requires_field_name) | |
732 << FD.D.getSourceRange(); | |
733 return; | |
734 } | |
735 if (FD.BitfieldSize) { | |
736 Diag(AtLoc, diag::err_objc_property_bitfield) | |
737 << FD.D.getSourceRange(); | |
738 return; | |
739 } | |
740 | |
741 // Map a nullability property attribute to a context-sensitive keyword | |
742 // attribute. | |
743 if (OCDS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_nullability) | |
744 addContextSensitiveTypeNullability(*this, FD.D, OCDS.getNullability(), | |
745 OCDS.getNullabilityLoc(), | |
746 addedToDeclSpec); | |
747 | |
748 // Install the property declarator into interfaceDecl. | |
749 IdentifierInfo *SelName = | |
750 OCDS.getGetterName() ? OCDS.getGetterName() : FD.D.getIdentifier(); | |
751 | |
752 Selector GetterSel = PP.getSelectorTable().getNullarySelector(SelName); | |
753 IdentifierInfo *SetterName = OCDS.getSetterName(); | |
754 Selector SetterSel; | |
755 if (SetterName) | |
756 SetterSel = PP.getSelectorTable().getSelector(1, &SetterName); | |
757 else | |
758 SetterSel = SelectorTable::constructSetterSelector( | |
759 PP.getIdentifierTable(), PP.getSelectorTable(), | |
760 FD.D.getIdentifier()); | |
761 Decl *Property = Actions.ActOnProperty( | |
762 getCurScope(), AtLoc, LParenLoc, FD, OCDS, GetterSel, SetterSel, | |
763 MethodImplKind); | |
764 | |
765 FD.complete(Property); | |
766 }; | |
767 | |
768 // Parse all the comma separated declarators. | |
769 ParsingDeclSpec DS(*this); | |
770 ParseStructDeclaration(DS, ObjCPropertyCallback); | |
771 | |
772 ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list); | |
773 break; | |
774 } | |
775 } | |
776 | |
777 // We break out of the big loop in two cases: when we see @end or when we see | |
778 // EOF. In the former case, eat the @end. In the later case, emit an error. | |
779 if (Tok.is(tok::code_completion)) { | |
780 Actions.CodeCompleteObjCAtDirective(getCurScope()); | |
781 return cutOffParsing(); | |
782 } else if (Tok.isObjCAtKeyword(tok::objc_end)) { | |
783 ConsumeToken(); // the "end" identifier | |
784 } else { | |
785 Diag(Tok, diag::err_objc_missing_end) | |
786 << FixItHint::CreateInsertion(Tok.getLocation(), "\n@end\n"); | |
787 Diag(CDecl->getBeginLoc(), diag::note_objc_container_start) | |
788 << (int)Actions.getObjCContainerKind(); | |
789 AtEnd.setBegin(Tok.getLocation()); | |
790 AtEnd.setEnd(Tok.getLocation()); | |
791 } | |
792 | |
793 // Insert collected methods declarations into the @interface object. | |
794 // This passes in an invalid SourceLocation for AtEndLoc when EOF is hit. | |
795 Actions.ActOnAtEnd(getCurScope(), AtEnd, allMethods, allTUVariables); | |
796 } | |
797 | |
798 /// Diagnose redundant or conflicting nullability information. | |
799 static void diagnoseRedundantPropertyNullability(Parser &P, | |
800 ObjCDeclSpec &DS, | |
801 NullabilityKind nullability, | |
802 SourceLocation nullabilityLoc){ | |
803 if (DS.getNullability() == nullability) { | |
804 P.Diag(nullabilityLoc, diag::warn_nullability_duplicate) | |
805 << DiagNullabilityKind(nullability, true) | |
806 << SourceRange(DS.getNullabilityLoc()); | |
807 return; | |
808 } | |
809 | |
810 P.Diag(nullabilityLoc, diag::err_nullability_conflicting) | |
811 << DiagNullabilityKind(nullability, true) | |
812 << DiagNullabilityKind(DS.getNullability(), true) | |
813 << SourceRange(DS.getNullabilityLoc()); | |
814 } | |
815 | |
816 /// Parse property attribute declarations. | |
817 /// | |
818 /// property-attr-decl: '(' property-attrlist ')' | |
819 /// property-attrlist: | |
820 /// property-attribute | |
821 /// property-attrlist ',' property-attribute | |
822 /// property-attribute: | |
823 /// getter '=' identifier | |
824 /// setter '=' identifier ':' | |
825 /// direct | |
826 /// readonly | |
827 /// readwrite | |
828 /// assign | |
829 /// retain | |
830 /// copy | |
831 /// nonatomic | |
832 /// atomic | |
833 /// strong | |
834 /// weak | |
835 /// unsafe_unretained | |
836 /// nonnull | |
837 /// nullable | |
838 /// null_unspecified | |
839 /// null_resettable | |
840 /// class | |
841 /// | |
842 void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) { | |
843 assert(Tok.getKind() == tok::l_paren); | |
844 BalancedDelimiterTracker T(*this, tok::l_paren); | |
845 T.consumeOpen(); | |
846 | |
847 while (1) { | |
848 if (Tok.is(tok::code_completion)) { | |
849 Actions.CodeCompleteObjCPropertyFlags(getCurScope(), DS); | |
850 return cutOffParsing(); | |
851 } | |
852 const IdentifierInfo *II = Tok.getIdentifierInfo(); | |
853 | |
854 // If this is not an identifier at all, bail out early. | |
855 if (!II) { | |
856 T.consumeClose(); | |
857 return; | |
858 } | |
859 | |
860 SourceLocation AttrName = ConsumeToken(); // consume last attribute name | |
861 | |
862 if (II->isStr("readonly")) | |
863 DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_readonly); | |
864 else if (II->isStr("assign")) | |
865 DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_assign); | |
866 else if (II->isStr("unsafe_unretained")) | |
867 DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_unsafe_unretained); | |
868 else if (II->isStr("readwrite")) | |
869 DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_readwrite); | |
870 else if (II->isStr("retain")) | |
871 DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_retain); | |
872 else if (II->isStr("strong")) | |
873 DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_strong); | |
874 else if (II->isStr("copy")) | |
875 DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_copy); | |
876 else if (II->isStr("nonatomic")) | |
877 DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_nonatomic); | |
878 else if (II->isStr("atomic")) | |
879 DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_atomic); | |
880 else if (II->isStr("weak")) | |
881 DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_weak); | |
882 else if (II->isStr("getter") || II->isStr("setter")) { | |
883 bool IsSetter = II->getNameStart()[0] == 's'; | |
884 | |
885 // getter/setter require extra treatment. | |
886 unsigned DiagID = IsSetter ? diag::err_objc_expected_equal_for_setter : | |
887 diag::err_objc_expected_equal_for_getter; | |
888 | |
889 if (ExpectAndConsume(tok::equal, DiagID)) { | |
890 SkipUntil(tok::r_paren, StopAtSemi); | |
891 return; | |
892 } | |
893 | |
894 if (Tok.is(tok::code_completion)) { | |
895 if (IsSetter) | |
896 Actions.CodeCompleteObjCPropertySetter(getCurScope()); | |
897 else | |
898 Actions.CodeCompleteObjCPropertyGetter(getCurScope()); | |
899 return cutOffParsing(); | |
900 } | |
901 | |
902 SourceLocation SelLoc; | |
903 IdentifierInfo *SelIdent = ParseObjCSelectorPiece(SelLoc); | |
904 | |
905 if (!SelIdent) { | |
906 Diag(Tok, diag::err_objc_expected_selector_for_getter_setter) | |
907 << IsSetter; | |
908 SkipUntil(tok::r_paren, StopAtSemi); | |
909 return; | |
910 } | |
911 | |
912 if (IsSetter) { | |
913 DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_setter); | |
914 DS.setSetterName(SelIdent, SelLoc); | |
915 | |
916 if (ExpectAndConsume(tok::colon, | |
917 diag::err_expected_colon_after_setter_name)) { | |
918 SkipUntil(tok::r_paren, StopAtSemi); | |
919 return; | |
920 } | |
921 } else { | |
922 DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_getter); | |
923 DS.setGetterName(SelIdent, SelLoc); | |
924 } | |
925 } else if (II->isStr("nonnull")) { | |
926 if (DS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_nullability) | |
927 diagnoseRedundantPropertyNullability(*this, DS, | |
928 NullabilityKind::NonNull, | |
929 Tok.getLocation()); | |
930 DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_nullability); | |
931 DS.setNullability(Tok.getLocation(), NullabilityKind::NonNull); | |
932 } else if (II->isStr("nullable")) { | |
933 if (DS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_nullability) | |
934 diagnoseRedundantPropertyNullability(*this, DS, | |
935 NullabilityKind::Nullable, | |
936 Tok.getLocation()); | |
937 DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_nullability); | |
938 DS.setNullability(Tok.getLocation(), NullabilityKind::Nullable); | |
939 } else if (II->isStr("null_unspecified")) { | |
940 if (DS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_nullability) | |
941 diagnoseRedundantPropertyNullability(*this, DS, | |
942 NullabilityKind::Unspecified, | |
943 Tok.getLocation()); | |
944 DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_nullability); | |
945 DS.setNullability(Tok.getLocation(), NullabilityKind::Unspecified); | |
946 } else if (II->isStr("null_resettable")) { | |
947 if (DS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_nullability) | |
948 diagnoseRedundantPropertyNullability(*this, DS, | |
949 NullabilityKind::Unspecified, | |
950 Tok.getLocation()); | |
951 DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_nullability); | |
952 DS.setNullability(Tok.getLocation(), NullabilityKind::Unspecified); | |
953 | |
954 // Also set the null_resettable bit. | |
955 DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_null_resettable); | |
956 } else if (II->isStr("class")) { | |
957 DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_class); | |
958 } else if (II->isStr("direct")) { | |
959 DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_direct); | |
960 } else { | |
961 Diag(AttrName, diag::err_objc_expected_property_attr) << II; | |
962 SkipUntil(tok::r_paren, StopAtSemi); | |
963 return; | |
964 } | |
965 | |
966 if (Tok.isNot(tok::comma)) | |
967 break; | |
968 | |
969 ConsumeToken(); | |
970 } | |
971 | |
972 T.consumeClose(); | |
973 } | |
974 | |
975 /// objc-method-proto: | |
976 /// objc-instance-method objc-method-decl objc-method-attributes[opt] | |
977 /// objc-class-method objc-method-decl objc-method-attributes[opt] | |
978 /// | |
979 /// objc-instance-method: '-' | |
980 /// objc-class-method: '+' | |
981 /// | |
982 /// objc-method-attributes: [OBJC2] | |
983 /// __attribute__((deprecated)) | |
984 /// | |
985 Decl *Parser::ParseObjCMethodPrototype(tok::ObjCKeywordKind MethodImplKind, | |
986 bool MethodDefinition) { | |
987 assert(Tok.isOneOf(tok::minus, tok::plus) && "expected +/-"); | |
988 | |
989 tok::TokenKind methodType = Tok.getKind(); | |
990 SourceLocation mLoc = ConsumeToken(); | |
991 Decl *MDecl = ParseObjCMethodDecl(mLoc, methodType, MethodImplKind, | |
992 MethodDefinition); | |
993 // Since this rule is used for both method declarations and definitions, | |
994 // the caller is (optionally) responsible for consuming the ';'. | |
995 return MDecl; | |
996 } | |
997 | |
998 /// objc-selector: | |
999 /// identifier | |
1000 /// one of | |
1001 /// enum struct union if else while do for switch case default | |
1002 /// break continue return goto asm sizeof typeof __alignof | |
1003 /// unsigned long const short volatile signed restrict _Complex | |
1004 /// in out inout bycopy byref oneway int char float double void _Bool | |
1005 /// | |
1006 IdentifierInfo *Parser::ParseObjCSelectorPiece(SourceLocation &SelectorLoc) { | |
1007 | |
1008 switch (Tok.getKind()) { | |
1009 default: | |
1010 return nullptr; | |
1011 case tok::colon: | |
1012 // Empty selector piece uses the location of the ':'. | |
1013 SelectorLoc = Tok.getLocation(); | |
1014 return nullptr; | |
1015 case tok::ampamp: | |
1016 case tok::ampequal: | |
1017 case tok::amp: | |
1018 case tok::pipe: | |
1019 case tok::tilde: | |
1020 case tok::exclaim: | |
1021 case tok::exclaimequal: | |
1022 case tok::pipepipe: | |
1023 case tok::pipeequal: | |
1024 case tok::caret: | |
1025 case tok::caretequal: { | |
1026 std::string ThisTok(PP.getSpelling(Tok)); | |
1027 if (isLetter(ThisTok[0])) { | |
1028 IdentifierInfo *II = &PP.getIdentifierTable().get(ThisTok); | |
1029 Tok.setKind(tok::identifier); | |
1030 SelectorLoc = ConsumeToken(); | |
1031 return II; | |
1032 } | |
1033 return nullptr; | |
1034 } | |
1035 | |
1036 case tok::identifier: | |
1037 case tok::kw_asm: | |
1038 case tok::kw_auto: | |
1039 case tok::kw_bool: | |
1040 case tok::kw_break: | |
1041 case tok::kw_case: | |
1042 case tok::kw_catch: | |
1043 case tok::kw_char: | |
1044 case tok::kw_class: | |
1045 case tok::kw_const: | |
1046 case tok::kw_const_cast: | |
1047 case tok::kw_continue: | |
1048 case tok::kw_default: | |
1049 case tok::kw_delete: | |
1050 case tok::kw_do: | |
1051 case tok::kw_double: | |
1052 case tok::kw_dynamic_cast: | |
1053 case tok::kw_else: | |
1054 case tok::kw_enum: | |
1055 case tok::kw_explicit: | |
1056 case tok::kw_export: | |
1057 case tok::kw_extern: | |
1058 case tok::kw_false: | |
1059 case tok::kw_float: | |
1060 case tok::kw_for: | |
1061 case tok::kw_friend: | |
1062 case tok::kw_goto: | |
1063 case tok::kw_if: | |
1064 case tok::kw_inline: | |
1065 case tok::kw_int: | |
1066 case tok::kw_long: | |
1067 case tok::kw_mutable: | |
1068 case tok::kw_namespace: | |
1069 case tok::kw_new: | |
1070 case tok::kw_operator: | |
1071 case tok::kw_private: | |
1072 case tok::kw_protected: | |
1073 case tok::kw_public: | |
1074 case tok::kw_register: | |
1075 case tok::kw_reinterpret_cast: | |
1076 case tok::kw_restrict: | |
1077 case tok::kw_return: | |
1078 case tok::kw_short: | |
1079 case tok::kw_signed: | |
1080 case tok::kw_sizeof: | |
1081 case tok::kw_static: | |
1082 case tok::kw_static_cast: | |
1083 case tok::kw_struct: | |
1084 case tok::kw_switch: | |
1085 case tok::kw_template: | |
1086 case tok::kw_this: | |
1087 case tok::kw_throw: | |
1088 case tok::kw_true: | |
1089 case tok::kw_try: | |
1090 case tok::kw_typedef: | |
1091 case tok::kw_typeid: | |
1092 case tok::kw_typename: | |
1093 case tok::kw_typeof: | |
1094 case tok::kw_union: | |
1095 case tok::kw_unsigned: | |
1096 case tok::kw_using: | |
1097 case tok::kw_virtual: | |
1098 case tok::kw_void: | |
1099 case tok::kw_volatile: | |
1100 case tok::kw_wchar_t: | |
1101 case tok::kw_while: | |
1102 case tok::kw__Bool: | |
1103 case tok::kw__Complex: | |
1104 case tok::kw___alignof: | |
1105 case tok::kw___auto_type: | |
1106 IdentifierInfo *II = Tok.getIdentifierInfo(); | |
1107 SelectorLoc = ConsumeToken(); | |
1108 return II; | |
1109 } | |
1110 } | |
1111 | |
1112 /// objc-for-collection-in: 'in' | |
1113 /// | |
1114 bool Parser::isTokIdentifier_in() const { | |
1115 // FIXME: May have to do additional look-ahead to only allow for | |
1116 // valid tokens following an 'in'; such as an identifier, unary operators, | |
1117 // '[' etc. | |
1118 return (getLangOpts().ObjC && Tok.is(tok::identifier) && | |
1119 Tok.getIdentifierInfo() == ObjCTypeQuals[objc_in]); | |
1120 } | |
1121 | |
1122 /// ParseObjCTypeQualifierList - This routine parses the objective-c's type | |
1123 /// qualifier list and builds their bitmask representation in the input | |
1124 /// argument. | |
1125 /// | |
1126 /// objc-type-qualifiers: | |
1127 /// objc-type-qualifier | |
1128 /// objc-type-qualifiers objc-type-qualifier | |
1129 /// | |
1130 /// objc-type-qualifier: | |
1131 /// 'in' | |
1132 /// 'out' | |
1133 /// 'inout' | |
1134 /// 'oneway' | |
1135 /// 'bycopy' | |
1136 /// 'byref' | |
1137 /// 'nonnull' | |
1138 /// 'nullable' | |
1139 /// 'null_unspecified' | |
1140 /// | |
1141 void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS, | |
1142 DeclaratorContext Context) { | |
1143 assert(Context == DeclaratorContext::ObjCParameterContext || | |
1144 Context == DeclaratorContext::ObjCResultContext); | |
1145 | |
1146 while (1) { | |
1147 if (Tok.is(tok::code_completion)) { | |
1148 Actions.CodeCompleteObjCPassingType(getCurScope(), DS, | |
1149 Context == DeclaratorContext::ObjCParameterContext); | |
1150 return cutOffParsing(); | |
1151 } | |
1152 | |
1153 if (Tok.isNot(tok::identifier)) | |
1154 return; | |
1155 | |
1156 const IdentifierInfo *II = Tok.getIdentifierInfo(); | |
1157 for (unsigned i = 0; i != objc_NumQuals; ++i) { | |
1158 if (II != ObjCTypeQuals[i] || | |
1159 NextToken().is(tok::less) || | |
1160 NextToken().is(tok::coloncolon)) | |
1161 continue; | |
1162 | |
1163 ObjCDeclSpec::ObjCDeclQualifier Qual; | |
1164 NullabilityKind Nullability; | |
1165 switch (i) { | |
1166 default: llvm_unreachable("Unknown decl qualifier"); | |
1167 case objc_in: Qual = ObjCDeclSpec::DQ_In; break; | |
1168 case objc_out: Qual = ObjCDeclSpec::DQ_Out; break; | |
1169 case objc_inout: Qual = ObjCDeclSpec::DQ_Inout; break; | |
1170 case objc_oneway: Qual = ObjCDeclSpec::DQ_Oneway; break; | |
1171 case objc_bycopy: Qual = ObjCDeclSpec::DQ_Bycopy; break; | |
1172 case objc_byref: Qual = ObjCDeclSpec::DQ_Byref; break; | |
1173 | |
1174 case objc_nonnull: | |
1175 Qual = ObjCDeclSpec::DQ_CSNullability; | |
1176 Nullability = NullabilityKind::NonNull; | |
1177 break; | |
1178 | |
1179 case objc_nullable: | |
1180 Qual = ObjCDeclSpec::DQ_CSNullability; | |
1181 Nullability = NullabilityKind::Nullable; | |
1182 break; | |
1183 | |
1184 case objc_null_unspecified: | |
1185 Qual = ObjCDeclSpec::DQ_CSNullability; | |
1186 Nullability = NullabilityKind::Unspecified; | |
1187 break; | |
1188 } | |
1189 | |
1190 // FIXME: Diagnose redundant specifiers. | |
1191 DS.setObjCDeclQualifier(Qual); | |
1192 if (Qual == ObjCDeclSpec::DQ_CSNullability) | |
1193 DS.setNullability(Tok.getLocation(), Nullability); | |
1194 | |
1195 ConsumeToken(); | |
1196 II = nullptr; | |
1197 break; | |
1198 } | |
1199 | |
1200 // If this wasn't a recognized qualifier, bail out. | |
1201 if (II) return; | |
1202 } | |
1203 } | |
1204 | |
1205 /// Take all the decl attributes out of the given list and add | |
1206 /// them to the given attribute set. | |
1207 static void takeDeclAttributes(ParsedAttributesView &attrs, | |
1208 ParsedAttributesView &from) { | |
1209 for (auto &AL : llvm::reverse(from)) { | |
1210 if (!AL.isUsedAsTypeAttr()) { | |
1211 from.remove(&AL); | |
1212 attrs.addAtEnd(&AL); | |
1213 } | |
1214 } | |
1215 } | |
1216 | |
1217 /// takeDeclAttributes - Take all the decl attributes from the given | |
1218 /// declarator and add them to the given list. | |
1219 static void takeDeclAttributes(ParsedAttributes &attrs, | |
1220 Declarator &D) { | |
1221 // First, take ownership of all attributes. | |
1222 attrs.getPool().takeAllFrom(D.getAttributePool()); | |
1223 attrs.getPool().takeAllFrom(D.getDeclSpec().getAttributePool()); | |
1224 | |
1225 // Now actually move the attributes over. | |
1226 takeDeclAttributes(attrs, D.getMutableDeclSpec().getAttributes()); | |
1227 takeDeclAttributes(attrs, D.getAttributes()); | |
1228 for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) | |
1229 takeDeclAttributes(attrs, D.getTypeObject(i).getAttrs()); | |
1230 } | |
1231 | |
1232 /// objc-type-name: | |
1233 /// '(' objc-type-qualifiers[opt] type-name ')' | |
1234 /// '(' objc-type-qualifiers[opt] ')' | |
1235 /// | |
1236 ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS, | |
1237 DeclaratorContext context, | |
1238 ParsedAttributes *paramAttrs) { | |
1239 assert(context == DeclaratorContext::ObjCParameterContext || | |
1240 context == DeclaratorContext::ObjCResultContext); | |
1241 assert((paramAttrs != nullptr) == | |
1242 (context == DeclaratorContext::ObjCParameterContext)); | |
1243 | |
1244 assert(Tok.is(tok::l_paren) && "expected ("); | |
1245 | |
1246 BalancedDelimiterTracker T(*this, tok::l_paren); | |
1247 T.consumeOpen(); | |
1248 | |
1249 ObjCDeclContextSwitch ObjCDC(*this); | |
1250 | |
1251 // Parse type qualifiers, in, inout, etc. | |
1252 ParseObjCTypeQualifierList(DS, context); | |
1253 SourceLocation TypeStartLoc = Tok.getLocation(); | |
1254 | |
1255 ParsedType Ty; | |
1256 if (isTypeSpecifierQualifier() || isObjCInstancetype()) { | |
1257 // Parse an abstract declarator. | |
1258 DeclSpec declSpec(AttrFactory); | |
1259 declSpec.setObjCQualifiers(&DS); | |
1260 DeclSpecContext dsContext = DeclSpecContext::DSC_normal; | |
1261 if (context == DeclaratorContext::ObjCResultContext) | |
1262 dsContext = DeclSpecContext::DSC_objc_method_result; | |
1263 ParseSpecifierQualifierList(declSpec, AS_none, dsContext); | |
1264 Declarator declarator(declSpec, context); | |
1265 ParseDeclarator(declarator); | |
1266 | |
1267 // If that's not invalid, extract a type. | |
1268 if (!declarator.isInvalidType()) { | |
1269 // Map a nullability specifier to a context-sensitive keyword attribute. | |
1270 bool addedToDeclSpec = false; | |
1271 if (DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability) | |
1272 addContextSensitiveTypeNullability(*this, declarator, | |
1273 DS.getNullability(), | |
1274 DS.getNullabilityLoc(), | |
1275 addedToDeclSpec); | |
1276 | |
1277 TypeResult type = Actions.ActOnTypeName(getCurScope(), declarator); | |
1278 if (!type.isInvalid()) | |
1279 Ty = type.get(); | |
1280 | |
1281 // If we're parsing a parameter, steal all the decl attributes | |
1282 // and add them to the decl spec. | |
1283 if (context == DeclaratorContext::ObjCParameterContext) | |
1284 takeDeclAttributes(*paramAttrs, declarator); | |
1285 } | |
1286 } | |
1287 | |
1288 if (Tok.is(tok::r_paren)) | |
1289 T.consumeClose(); | |
1290 else if (Tok.getLocation() == TypeStartLoc) { | |
1291 // If we didn't eat any tokens, then this isn't a type. | |
1292 Diag(Tok, diag::err_expected_type); | |
1293 SkipUntil(tok::r_paren, StopAtSemi); | |
1294 } else { | |
1295 // Otherwise, we found *something*, but didn't get a ')' in the right | |
1296 // place. Emit an error then return what we have as the type. | |
1297 T.consumeClose(); | |
1298 } | |
1299 return Ty; | |
1300 } | |
1301 | |
1302 /// objc-method-decl: | |
1303 /// objc-selector | |
1304 /// objc-keyword-selector objc-parmlist[opt] | |
1305 /// objc-type-name objc-selector | |
1306 /// objc-type-name objc-keyword-selector objc-parmlist[opt] | |
1307 /// | |
1308 /// objc-keyword-selector: | |
1309 /// objc-keyword-decl | |
1310 /// objc-keyword-selector objc-keyword-decl | |
1311 /// | |
1312 /// objc-keyword-decl: | |
1313 /// objc-selector ':' objc-type-name objc-keyword-attributes[opt] identifier | |
1314 /// objc-selector ':' objc-keyword-attributes[opt] identifier | |
1315 /// ':' objc-type-name objc-keyword-attributes[opt] identifier | |
1316 /// ':' objc-keyword-attributes[opt] identifier | |
1317 /// | |
1318 /// objc-parmlist: | |
1319 /// objc-parms objc-ellipsis[opt] | |
1320 /// | |
1321 /// objc-parms: | |
1322 /// objc-parms , parameter-declaration | |
1323 /// | |
1324 /// objc-ellipsis: | |
1325 /// , ... | |
1326 /// | |
1327 /// objc-keyword-attributes: [OBJC2] | |
1328 /// __attribute__((unused)) | |
1329 /// | |
1330 Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, | |
1331 tok::TokenKind mType, | |
1332 tok::ObjCKeywordKind MethodImplKind, | |
1333 bool MethodDefinition) { | |
1334 ParsingDeclRAIIObject PD(*this, ParsingDeclRAIIObject::NoParent); | |
1335 | |
1336 if (Tok.is(tok::code_completion)) { | |
1337 Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus, | |
1338 /*ReturnType=*/nullptr); | |
1339 cutOffParsing(); | |
1340 return nullptr; | |
1341 } | |
1342 | |
1343 // Parse the return type if present. | |
1344 ParsedType ReturnType; | |
1345 ObjCDeclSpec DSRet; | |
1346 if (Tok.is(tok::l_paren)) | |
1347 ReturnType = ParseObjCTypeName(DSRet, DeclaratorContext::ObjCResultContext, | |
1348 nullptr); | |
1349 | |
1350 // If attributes exist before the method, parse them. | |
1351 ParsedAttributes methodAttrs(AttrFactory); | |
1352 if (getLangOpts().ObjC) | |
1353 MaybeParseGNUAttributes(methodAttrs); | |
1354 MaybeParseCXX11Attributes(methodAttrs); | |
1355 | |
1356 if (Tok.is(tok::code_completion)) { | |
1357 Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus, | |
1358 ReturnType); | |
1359 cutOffParsing(); | |
1360 return nullptr; | |
1361 } | |
1362 | |
1363 // Now parse the selector. | |
1364 SourceLocation selLoc; | |
1365 IdentifierInfo *SelIdent = ParseObjCSelectorPiece(selLoc); | |
1366 | |
1367 // An unnamed colon is valid. | |
1368 if (!SelIdent && Tok.isNot(tok::colon)) { // missing selector name. | |
1369 Diag(Tok, diag::err_expected_selector_for_method) | |
1370 << SourceRange(mLoc, Tok.getLocation()); | |
1371 // Skip until we get a ; or @. | |
1372 SkipUntil(tok::at, StopAtSemi | StopBeforeMatch); | |
1373 return nullptr; | |
1374 } | |
1375 | |
1376 SmallVector<DeclaratorChunk::ParamInfo, 8> CParamInfo; | |
1377 if (Tok.isNot(tok::colon)) { | |
1378 // If attributes exist after the method, parse them. | |
1379 if (getLangOpts().ObjC) | |
1380 MaybeParseGNUAttributes(methodAttrs); | |
1381 MaybeParseCXX11Attributes(methodAttrs); | |
1382 | |
1383 Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent); | |
1384 Decl *Result = Actions.ActOnMethodDeclaration( | |
1385 getCurScope(), mLoc, Tok.getLocation(), mType, DSRet, ReturnType, | |
1386 selLoc, Sel, nullptr, CParamInfo.data(), CParamInfo.size(), methodAttrs, | |
1387 MethodImplKind, false, MethodDefinition); | |
1388 PD.complete(Result); | |
1389 return Result; | |
1390 } | |
1391 | |
1392 SmallVector<IdentifierInfo *, 12> KeyIdents; | |
1393 SmallVector<SourceLocation, 12> KeyLocs; | |
1394 SmallVector<Sema::ObjCArgInfo, 12> ArgInfos; | |
1395 ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope | | |
1396 Scope::FunctionDeclarationScope | Scope::DeclScope); | |
1397 | |
1398 AttributePool allParamAttrs(AttrFactory); | |
1399 while (1) { | |
1400 ParsedAttributes paramAttrs(AttrFactory); | |
1401 Sema::ObjCArgInfo ArgInfo; | |
1402 | |
1403 // Each iteration parses a single keyword argument. | |
1404 if (ExpectAndConsume(tok::colon)) | |
1405 break; | |
1406 | |
1407 ArgInfo.Type = nullptr; | |
1408 if (Tok.is(tok::l_paren)) // Parse the argument type if present. | |
1409 ArgInfo.Type = ParseObjCTypeName(ArgInfo.DeclSpec, | |
1410 DeclaratorContext::ObjCParameterContext, | |
1411 ¶mAttrs); | |
1412 | |
1413 // If attributes exist before the argument name, parse them. | |
1414 // Regardless, collect all the attributes we've parsed so far. | |
1415 if (getLangOpts().ObjC) | |
1416 MaybeParseGNUAttributes(paramAttrs); | |
1417 MaybeParseCXX11Attributes(paramAttrs); | |
1418 ArgInfo.ArgAttrs = paramAttrs; | |
1419 | |
1420 // Code completion for the next piece of the selector. | |
1421 if (Tok.is(tok::code_completion)) { | |
1422 KeyIdents.push_back(SelIdent); | |
1423 Actions.CodeCompleteObjCMethodDeclSelector(getCurScope(), | |
1424 mType == tok::minus, | |
1425 /*AtParameterName=*/true, | |
1426 ReturnType, KeyIdents); | |
1427 cutOffParsing(); | |
1428 return nullptr; | |
1429 } | |
1430 | |
1431 if (expectIdentifier()) | |
1432 break; // missing argument name. | |
1433 | |
1434 ArgInfo.Name = Tok.getIdentifierInfo(); | |
1435 ArgInfo.NameLoc = Tok.getLocation(); | |
1436 ConsumeToken(); // Eat the identifier. | |
1437 | |
1438 ArgInfos.push_back(ArgInfo); | |
1439 KeyIdents.push_back(SelIdent); | |
1440 KeyLocs.push_back(selLoc); | |
1441 | |
1442 // Make sure the attributes persist. | |
1443 allParamAttrs.takeAllFrom(paramAttrs.getPool()); | |
1444 | |
1445 // Code completion for the next piece of the selector. | |
1446 if (Tok.is(tok::code_completion)) { | |
1447 Actions.CodeCompleteObjCMethodDeclSelector(getCurScope(), | |
1448 mType == tok::minus, | |
1449 /*AtParameterName=*/false, | |
1450 ReturnType, KeyIdents); | |
1451 cutOffParsing(); | |
1452 return nullptr; | |
1453 } | |
1454 | |
1455 // Check for another keyword selector. | |
1456 SelIdent = ParseObjCSelectorPiece(selLoc); | |
1457 if (!SelIdent && Tok.isNot(tok::colon)) | |
1458 break; | |
1459 if (!SelIdent) { | |
1460 SourceLocation ColonLoc = Tok.getLocation(); | |
1461 if (PP.getLocForEndOfToken(ArgInfo.NameLoc) == ColonLoc) { | |
1462 Diag(ArgInfo.NameLoc, diag::warn_missing_selector_name) << ArgInfo.Name; | |
1463 Diag(ArgInfo.NameLoc, diag::note_missing_selector_name) << ArgInfo.Name; | |
1464 Diag(ColonLoc, diag::note_force_empty_selector_name) << ArgInfo.Name; | |
1465 } | |
1466 } | |
1467 // We have a selector or a colon, continue parsing. | |
1468 } | |
1469 | |
1470 bool isVariadic = false; | |
1471 bool cStyleParamWarned = false; | |
1472 // Parse the (optional) parameter list. | |
1473 while (Tok.is(tok::comma)) { | |
1474 ConsumeToken(); | |
1475 if (Tok.is(tok::ellipsis)) { | |
1476 isVariadic = true; | |
1477 ConsumeToken(); | |
1478 break; | |
1479 } | |
1480 if (!cStyleParamWarned) { | |
1481 Diag(Tok, diag::warn_cstyle_param); | |
1482 cStyleParamWarned = true; | |
1483 } | |
1484 DeclSpec DS(AttrFactory); | |
1485 ParseDeclarationSpecifiers(DS); | |
1486 // Parse the declarator. | |
1487 Declarator ParmDecl(DS, DeclaratorContext::PrototypeContext); | |
1488 ParseDeclarator(ParmDecl); | |
1489 IdentifierInfo *ParmII = ParmDecl.getIdentifier(); | |
1490 Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDecl); | |
1491 CParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII, | |
1492 ParmDecl.getIdentifierLoc(), | |
1493 Param, | |
1494 nullptr)); | |
1495 } | |
1496 | |
1497 // FIXME: Add support for optional parameter list... | |
1498 // If attributes exist after the method, parse them. | |
1499 if (getLangOpts().ObjC) | |
1500 MaybeParseGNUAttributes(methodAttrs); | |
1501 MaybeParseCXX11Attributes(methodAttrs); | |
1502 | |
1503 if (KeyIdents.size() == 0) | |
1504 return nullptr; | |
1505 | |
1506 Selector Sel = PP.getSelectorTable().getSelector(KeyIdents.size(), | |
1507 &KeyIdents[0]); | |
1508 Decl *Result = Actions.ActOnMethodDeclaration( | |
1509 getCurScope(), mLoc, Tok.getLocation(), mType, DSRet, ReturnType, KeyLocs, | |
1510 Sel, &ArgInfos[0], CParamInfo.data(), CParamInfo.size(), methodAttrs, | |
1511 MethodImplKind, isVariadic, MethodDefinition); | |
1512 | |
1513 PD.complete(Result); | |
1514 return Result; | |
1515 } | |
1516 | |
1517 /// objc-protocol-refs: | |
1518 /// '<' identifier-list '>' | |
1519 /// | |
1520 bool Parser:: | |
1521 ParseObjCProtocolReferences(SmallVectorImpl<Decl *> &Protocols, | |
1522 SmallVectorImpl<SourceLocation> &ProtocolLocs, | |
1523 bool WarnOnDeclarations, bool ForObjCContainer, | |
1524 SourceLocation &LAngleLoc, SourceLocation &EndLoc, | |
1525 bool consumeLastToken) { | |
1526 assert(Tok.is(tok::less) && "expected <"); | |
1527 | |
1528 LAngleLoc = ConsumeToken(); // the "<" | |
1529 | |
1530 SmallVector<IdentifierLocPair, 8> ProtocolIdents; | |
1531 | |
1532 while (1) { | |
1533 if (Tok.is(tok::code_completion)) { | |
1534 Actions.CodeCompleteObjCProtocolReferences(ProtocolIdents); | |
1535 cutOffParsing(); | |
1536 return true; | |
1537 } | |
1538 | |
1539 if (expectIdentifier()) { | |
1540 SkipUntil(tok::greater, StopAtSemi); | |
1541 return true; | |
1542 } | |
1543 ProtocolIdents.push_back(std::make_pair(Tok.getIdentifierInfo(), | |
1544 Tok.getLocation())); | |
1545 ProtocolLocs.push_back(Tok.getLocation()); | |
1546 ConsumeToken(); | |
1547 | |
1548 if (!TryConsumeToken(tok::comma)) | |
1549 break; | |
1550 } | |
1551 | |
1552 // Consume the '>'. | |
1553 if (ParseGreaterThanInTemplateList(EndLoc, consumeLastToken, | |
1554 /*ObjCGenericList=*/false)) | |
1555 return true; | |
1556 | |
1557 // Convert the list of protocols identifiers into a list of protocol decls. | |
1558 Actions.FindProtocolDeclaration(WarnOnDeclarations, ForObjCContainer, | |
1559 ProtocolIdents, Protocols); | |
1560 return false; | |
1561 } | |
1562 | |
1563 TypeResult Parser::parseObjCProtocolQualifierType(SourceLocation &rAngleLoc) { | |
1564 assert(Tok.is(tok::less) && "Protocol qualifiers start with '<'"); | |
1565 assert(getLangOpts().ObjC && "Protocol qualifiers only exist in Objective-C"); | |
1566 | |
1567 SourceLocation lAngleLoc; | |
1568 SmallVector<Decl *, 8> protocols; | |
1569 SmallVector<SourceLocation, 8> protocolLocs; | |
1570 (void)ParseObjCProtocolReferences(protocols, protocolLocs, false, false, | |
1571 lAngleLoc, rAngleLoc, | |
1572 /*consumeLastToken=*/true); | |
1573 TypeResult result = Actions.actOnObjCProtocolQualifierType(lAngleLoc, | |
1574 protocols, | |
1575 protocolLocs, | |
1576 rAngleLoc); | |
1577 if (result.isUsable()) { | |
1578 Diag(lAngleLoc, diag::warn_objc_protocol_qualifier_missing_id) | |
1579 << FixItHint::CreateInsertion(lAngleLoc, "id") | |
1580 << SourceRange(lAngleLoc, rAngleLoc); | |
1581 } | |
1582 | |
1583 return result; | |
1584 } | |
1585 | |
1586 /// Parse Objective-C type arguments or protocol qualifiers. | |
1587 /// | |
1588 /// objc-type-arguments: | |
1589 /// '<' type-name '...'[opt] (',' type-name '...'[opt])* '>' | |
1590 /// | |
1591 void Parser::parseObjCTypeArgsOrProtocolQualifiers( | |
1592 ParsedType baseType, | |
1593 SourceLocation &typeArgsLAngleLoc, | |
1594 SmallVectorImpl<ParsedType> &typeArgs, | |
1595 SourceLocation &typeArgsRAngleLoc, | |
1596 SourceLocation &protocolLAngleLoc, | |
1597 SmallVectorImpl<Decl *> &protocols, | |
1598 SmallVectorImpl<SourceLocation> &protocolLocs, | |
1599 SourceLocation &protocolRAngleLoc, | |
1600 bool consumeLastToken, | |
1601 bool warnOnIncompleteProtocols) { | |
1602 assert(Tok.is(tok::less) && "Not at the start of type args or protocols"); | |
1603 SourceLocation lAngleLoc = ConsumeToken(); | |
1604 | |
1605 // Whether all of the elements we've parsed thus far are single | |
1606 // identifiers, which might be types or might be protocols. | |
1607 bool allSingleIdentifiers = true; | |
1608 SmallVector<IdentifierInfo *, 4> identifiers; | |
1609 SmallVectorImpl<SourceLocation> &identifierLocs = protocolLocs; | |
1610 | |
1611 // Parse a list of comma-separated identifiers, bailing out if we | |
1612 // see something different. | |
1613 do { | |
1614 // Parse a single identifier. | |
1615 if (Tok.is(tok::identifier) && | |
1616 (NextToken().is(tok::comma) || | |
1617 NextToken().is(tok::greater) || | |
1618 NextToken().is(tok::greatergreater))) { | |
1619 identifiers.push_back(Tok.getIdentifierInfo()); | |
1620 identifierLocs.push_back(ConsumeToken()); | |
1621 continue; | |
1622 } | |
1623 | |
1624 if (Tok.is(tok::code_completion)) { | |
1625 // FIXME: Also include types here. | |
1626 SmallVector<IdentifierLocPair, 4> identifierLocPairs; | |
1627 for (unsigned i = 0, n = identifiers.size(); i != n; ++i) { | |
1628 identifierLocPairs.push_back(IdentifierLocPair(identifiers[i], | |
1629 identifierLocs[i])); | |
1630 } | |
1631 | |
1632 QualType BaseT = Actions.GetTypeFromParser(baseType); | |
1633 if (!BaseT.isNull() && BaseT->acceptsObjCTypeParams()) { | |
1634 Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Type); | |
1635 } else { | |
1636 Actions.CodeCompleteObjCProtocolReferences(identifierLocPairs); | |
1637 } | |
1638 cutOffParsing(); | |
1639 return; | |
1640 } | |
1641 | |
1642 allSingleIdentifiers = false; | |
1643 break; | |
1644 } while (TryConsumeToken(tok::comma)); | |
1645 | |
1646 // If we parsed an identifier list, semantic analysis sorts out | |
1647 // whether it refers to protocols or to type arguments. | |
1648 if (allSingleIdentifiers) { | |
1649 // Parse the closing '>'. | |
1650 SourceLocation rAngleLoc; | |
1651 (void)ParseGreaterThanInTemplateList(rAngleLoc, consumeLastToken, | |
1652 /*ObjCGenericList=*/true); | |
1653 | |
1654 // Let Sema figure out what we parsed. | |
1655 Actions.actOnObjCTypeArgsOrProtocolQualifiers(getCurScope(), | |
1656 baseType, | |
1657 lAngleLoc, | |
1658 identifiers, | |
1659 identifierLocs, | |
1660 rAngleLoc, | |
1661 typeArgsLAngleLoc, | |
1662 typeArgs, | |
1663 typeArgsRAngleLoc, | |
1664 protocolLAngleLoc, | |
1665 protocols, | |
1666 protocolRAngleLoc, | |
1667 warnOnIncompleteProtocols); | |
1668 return; | |
1669 } | |
1670 | |
1671 // We parsed an identifier list but stumbled into non single identifiers, this | |
1672 // means we might (a) check that what we already parsed is a legitimate type | |
1673 // (not a protocol or unknown type) and (b) parse the remaining ones, which | |
1674 // must all be type args. | |
1675 | |
1676 // Convert the identifiers into type arguments. | |
1677 bool invalid = false; | |
1678 IdentifierInfo *foundProtocolId = nullptr, *foundValidTypeId = nullptr; | |
1679 SourceLocation foundProtocolSrcLoc, foundValidTypeSrcLoc; | |
1680 SmallVector<IdentifierInfo *, 2> unknownTypeArgs; | |
1681 SmallVector<SourceLocation, 2> unknownTypeArgsLoc; | |
1682 | |
1683 for (unsigned i = 0, n = identifiers.size(); i != n; ++i) { | |
1684 ParsedType typeArg | |
1685 = Actions.getTypeName(*identifiers[i], identifierLocs[i], getCurScope()); | |
1686 if (typeArg) { | |
1687 DeclSpec DS(AttrFactory); | |
1688 const char *prevSpec = nullptr; | |
1689 unsigned diagID; | |
1690 DS.SetTypeSpecType(TST_typename, identifierLocs[i], prevSpec, diagID, | |
1691 typeArg, Actions.getASTContext().getPrintingPolicy()); | |
1692 | |
1693 // Form a declarator to turn this into a type. | |
1694 Declarator D(DS, DeclaratorContext::TypeNameContext); | |
1695 TypeResult fullTypeArg = Actions.ActOnTypeName(getCurScope(), D); | |
1696 if (fullTypeArg.isUsable()) { | |
1697 typeArgs.push_back(fullTypeArg.get()); | |
1698 if (!foundValidTypeId) { | |
1699 foundValidTypeId = identifiers[i]; | |
1700 foundValidTypeSrcLoc = identifierLocs[i]; | |
1701 } | |
1702 } else { | |
1703 invalid = true; | |
1704 unknownTypeArgs.push_back(identifiers[i]); | |
1705 unknownTypeArgsLoc.push_back(identifierLocs[i]); | |
1706 } | |
1707 } else { | |
1708 invalid = true; | |
1709 if (!Actions.LookupProtocol(identifiers[i], identifierLocs[i])) { | |
1710 unknownTypeArgs.push_back(identifiers[i]); | |
1711 unknownTypeArgsLoc.push_back(identifierLocs[i]); | |
1712 } else if (!foundProtocolId) { | |
1713 foundProtocolId = identifiers[i]; | |
1714 foundProtocolSrcLoc = identifierLocs[i]; | |
1715 } | |
1716 } | |
1717 } | |
1718 | |
1719 // Continue parsing type-names. | |
1720 do { | |
1721 Token CurTypeTok = Tok; | |
1722 TypeResult typeArg = ParseTypeName(); | |
1723 | |
1724 // Consume the '...' for a pack expansion. | |
1725 SourceLocation ellipsisLoc; | |
1726 TryConsumeToken(tok::ellipsis, ellipsisLoc); | |
1727 if (typeArg.isUsable() && ellipsisLoc.isValid()) { | |
1728 typeArg = Actions.ActOnPackExpansion(typeArg.get(), ellipsisLoc); | |
1729 } | |
1730 | |
1731 if (typeArg.isUsable()) { | |
1732 typeArgs.push_back(typeArg.get()); | |
1733 if (!foundValidTypeId) { | |
1734 foundValidTypeId = CurTypeTok.getIdentifierInfo(); | |
1735 foundValidTypeSrcLoc = CurTypeTok.getLocation(); | |
1736 } | |
1737 } else { | |
1738 invalid = true; | |
1739 } | |
1740 } while (TryConsumeToken(tok::comma)); | |
1741 | |
1742 // Diagnose the mix between type args and protocols. | |
1743 if (foundProtocolId && foundValidTypeId) | |
1744 Actions.DiagnoseTypeArgsAndProtocols(foundProtocolId, foundProtocolSrcLoc, | |
1745 foundValidTypeId, | |
1746 foundValidTypeSrcLoc); | |
1747 | |
1748 // Diagnose unknown arg types. | |
1749 ParsedType T; | |
1750 if (unknownTypeArgs.size()) | |
1751 for (unsigned i = 0, e = unknownTypeArgsLoc.size(); i < e; ++i) | |
1752 Actions.DiagnoseUnknownTypeName(unknownTypeArgs[i], unknownTypeArgsLoc[i], | |
1753 getCurScope(), nullptr, T); | |
1754 | |
1755 // Parse the closing '>'. | |
1756 SourceLocation rAngleLoc; | |
1757 (void)ParseGreaterThanInTemplateList(rAngleLoc, consumeLastToken, | |
1758 /*ObjCGenericList=*/true); | |
1759 | |
1760 if (invalid) { | |
1761 typeArgs.clear(); | |
1762 return; | |
1763 } | |
1764 | |
1765 // Record left/right angle locations. | |
1766 typeArgsLAngleLoc = lAngleLoc; | |
1767 typeArgsRAngleLoc = rAngleLoc; | |
1768 } | |
1769 | |
1770 void Parser::parseObjCTypeArgsAndProtocolQualifiers( | |
1771 ParsedType baseType, | |
1772 SourceLocation &typeArgsLAngleLoc, | |
1773 SmallVectorImpl<ParsedType> &typeArgs, | |
1774 SourceLocation &typeArgsRAngleLoc, | |
1775 SourceLocation &protocolLAngleLoc, | |
1776 SmallVectorImpl<Decl *> &protocols, | |
1777 SmallVectorImpl<SourceLocation> &protocolLocs, | |
1778 SourceLocation &protocolRAngleLoc, | |
1779 bool consumeLastToken) { | |
1780 assert(Tok.is(tok::less)); | |
1781 | |
1782 // Parse the first angle-bracket-delimited clause. | |
1783 parseObjCTypeArgsOrProtocolQualifiers(baseType, | |
1784 typeArgsLAngleLoc, | |
1785 typeArgs, | |
1786 typeArgsRAngleLoc, | |
1787 protocolLAngleLoc, | |
1788 protocols, | |
1789 protocolLocs, | |
1790 protocolRAngleLoc, | |
1791 consumeLastToken, | |
1792 /*warnOnIncompleteProtocols=*/false); | |
1793 if (Tok.is(tok::eof)) // Nothing else to do here... | |
1794 return; | |
1795 | |
1796 // An Objective-C object pointer followed by type arguments | |
1797 // can then be followed again by a set of protocol references, e.g., | |
1798 // \c NSArray<NSView><NSTextDelegate> | |
1799 if ((consumeLastToken && Tok.is(tok::less)) || | |
1800 (!consumeLastToken && NextToken().is(tok::less))) { | |
1801 // If we aren't consuming the last token, the prior '>' is still hanging | |
1802 // there. Consume it before we parse the protocol qualifiers. | |
1803 if (!consumeLastToken) | |
1804 ConsumeToken(); | |
1805 | |
1806 if (!protocols.empty()) { | |
1807 SkipUntilFlags skipFlags = SkipUntilFlags(); | |
1808 if (!consumeLastToken) | |
1809 skipFlags = skipFlags | StopBeforeMatch; | |
1810 Diag(Tok, diag::err_objc_type_args_after_protocols) | |
1811 << SourceRange(protocolLAngleLoc, protocolRAngleLoc); | |
1812 SkipUntil(tok::greater, tok::greatergreater, skipFlags); | |
1813 } else { | |
1814 ParseObjCProtocolReferences(protocols, protocolLocs, | |
1815 /*WarnOnDeclarations=*/false, | |
1816 /*ForObjCContainer=*/false, | |
1817 protocolLAngleLoc, protocolRAngleLoc, | |
1818 consumeLastToken); | |
1819 } | |
1820 } | |
1821 } | |
1822 | |
1823 TypeResult Parser::parseObjCTypeArgsAndProtocolQualifiers( | |
1824 SourceLocation loc, | |
1825 ParsedType type, | |
1826 bool consumeLastToken, | |
1827 SourceLocation &endLoc) { | |
1828 assert(Tok.is(tok::less)); | |
1829 SourceLocation typeArgsLAngleLoc; | |
1830 SmallVector<ParsedType, 4> typeArgs; | |
1831 SourceLocation typeArgsRAngleLoc; | |
1832 SourceLocation protocolLAngleLoc; | |
1833 SmallVector<Decl *, 4> protocols; | |
1834 SmallVector<SourceLocation, 4> protocolLocs; | |
1835 SourceLocation protocolRAngleLoc; | |
1836 | |
1837 // Parse type arguments and protocol qualifiers. | |
1838 parseObjCTypeArgsAndProtocolQualifiers(type, typeArgsLAngleLoc, typeArgs, | |
1839 typeArgsRAngleLoc, protocolLAngleLoc, | |
1840 protocols, protocolLocs, | |
1841 protocolRAngleLoc, consumeLastToken); | |
1842 | |
1843 if (Tok.is(tok::eof)) | |
1844 return true; // Invalid type result. | |
1845 | |
1846 // Compute the location of the last token. | |
1847 if (consumeLastToken) | |
1848 endLoc = PrevTokLocation; | |
1849 else | |
1850 endLoc = Tok.getLocation(); | |
1851 | |
1852 return Actions.actOnObjCTypeArgsAndProtocolQualifiers( | |
1853 getCurScope(), | |
1854 loc, | |
1855 type, | |
1856 typeArgsLAngleLoc, | |
1857 typeArgs, | |
1858 typeArgsRAngleLoc, | |
1859 protocolLAngleLoc, | |
1860 protocols, | |
1861 protocolLocs, | |
1862 protocolRAngleLoc); | |
1863 } | |
1864 | |
1865 void Parser::HelperActionsForIvarDeclarations(Decl *interfaceDecl, SourceLocation atLoc, | |
1866 BalancedDelimiterTracker &T, | |
1867 SmallVectorImpl<Decl *> &AllIvarDecls, | |
1868 bool RBraceMissing) { | |
1869 if (!RBraceMissing) | |
1870 T.consumeClose(); | |
1871 | |
1872 Actions.ActOnObjCContainerStartDefinition(interfaceDecl); | |
1873 Actions.ActOnLastBitfield(T.getCloseLocation(), AllIvarDecls); | |
1874 Actions.ActOnObjCContainerFinishDefinition(); | |
1875 // Call ActOnFields() even if we don't have any decls. This is useful | |
1876 // for code rewriting tools that need to be aware of the empty list. | |
1877 Actions.ActOnFields(getCurScope(), atLoc, interfaceDecl, AllIvarDecls, | |
1878 T.getOpenLocation(), T.getCloseLocation(), | |
1879 ParsedAttributesView()); | |
1880 } | |
1881 | |
1882 /// objc-class-instance-variables: | |
1883 /// '{' objc-instance-variable-decl-list[opt] '}' | |
1884 /// | |
1885 /// objc-instance-variable-decl-list: | |
1886 /// objc-visibility-spec | |
1887 /// objc-instance-variable-decl ';' | |
1888 /// ';' | |
1889 /// objc-instance-variable-decl-list objc-visibility-spec | |
1890 /// objc-instance-variable-decl-list objc-instance-variable-decl ';' | |
1891 /// objc-instance-variable-decl-list static_assert-declaration | |
1892 /// objc-instance-variable-decl-list ';' | |
1893 /// | |
1894 /// objc-visibility-spec: | |
1895 /// @private | |
1896 /// @protected | |
1897 /// @public | |
1898 /// @package [OBJC2] | |
1899 /// | |
1900 /// objc-instance-variable-decl: | |
1901 /// struct-declaration | |
1902 /// | |
1903 void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl, | |
1904 tok::ObjCKeywordKind visibility, | |
1905 SourceLocation atLoc) { | |
1906 assert(Tok.is(tok::l_brace) && "expected {"); | |
1907 SmallVector<Decl *, 32> AllIvarDecls; | |
1908 | |
1909 ParseScope ClassScope(this, Scope::DeclScope|Scope::ClassScope); | |
1910 ObjCDeclContextSwitch ObjCDC(*this); | |
1911 | |
1912 BalancedDelimiterTracker T(*this, tok::l_brace); | |
1913 T.consumeOpen(); | |
1914 // While we still have something to read, read the instance variables. | |
1915 while (Tok.isNot(tok::r_brace) && !isEofOrEom()) { | |
1916 // Each iteration of this loop reads one objc-instance-variable-decl. | |
1917 | |
1918 // Check for extraneous top-level semicolon. | |
1919 if (Tok.is(tok::semi)) { | |
1920 ConsumeExtraSemi(InstanceVariableList); | |
1921 continue; | |
1922 } | |
1923 | |
1924 // Set the default visibility to private. | |
1925 if (TryConsumeToken(tok::at)) { // parse objc-visibility-spec | |
1926 if (Tok.is(tok::code_completion)) { | |
1927 Actions.CodeCompleteObjCAtVisibility(getCurScope()); | |
1928 return cutOffParsing(); | |
1929 } | |
1930 | |
1931 switch (Tok.getObjCKeywordID()) { | |
1932 case tok::objc_private: | |
1933 case tok::objc_public: | |
1934 case tok::objc_protected: | |
1935 case tok::objc_package: | |
1936 visibility = Tok.getObjCKeywordID(); | |
1937 ConsumeToken(); | |
1938 continue; | |
1939 | |
1940 case tok::objc_end: | |
1941 Diag(Tok, diag::err_objc_unexpected_atend); | |
1942 Tok.setLocation(Tok.getLocation().getLocWithOffset(-1)); | |
1943 Tok.setKind(tok::at); | |
1944 Tok.setLength(1); | |
1945 PP.EnterToken(Tok, /*IsReinject*/true); | |
1946 HelperActionsForIvarDeclarations(interfaceDecl, atLoc, | |
1947 T, AllIvarDecls, true); | |
1948 return; | |
1949 | |
1950 default: | |
1951 Diag(Tok, diag::err_objc_illegal_visibility_spec); | |
1952 continue; | |
1953 } | |
1954 } | |
1955 | |
1956 if (Tok.is(tok::code_completion)) { | |
1957 Actions.CodeCompleteOrdinaryName(getCurScope(), | |
1958 Sema::PCC_ObjCInstanceVariableList); | |
1959 return cutOffParsing(); | |
1960 } | |
1961 | |
1962 // This needs to duplicate a small amount of code from | |
1963 // ParseStructUnionBody() for things that should work in both | |
1964 // C struct and in Objective-C class instance variables. | |
1965 if (Tok.isOneOf(tok::kw_static_assert, tok::kw__Static_assert)) { | |
1966 SourceLocation DeclEnd; | |
1967 ParseStaticAssertDeclaration(DeclEnd); | |
1968 continue; | |
1969 } | |
1970 | |
1971 auto ObjCIvarCallback = [&](ParsingFieldDeclarator &FD) { | |
1972 Actions.ActOnObjCContainerStartDefinition(interfaceDecl); | |
1973 // Install the declarator into the interface decl. | |
1974 FD.D.setObjCIvar(true); | |
1975 Decl *Field = Actions.ActOnIvar( | |
1976 getCurScope(), FD.D.getDeclSpec().getSourceRange().getBegin(), FD.D, | |
1977 FD.BitfieldSize, visibility); | |
1978 Actions.ActOnObjCContainerFinishDefinition(); | |
1979 if (Field) | |
1980 AllIvarDecls.push_back(Field); | |
1981 FD.complete(Field); | |
1982 }; | |
1983 | |
1984 // Parse all the comma separated declarators. | |
1985 ParsingDeclSpec DS(*this); | |
1986 ParseStructDeclaration(DS, ObjCIvarCallback); | |
1987 | |
1988 if (Tok.is(tok::semi)) { | |
1989 ConsumeToken(); | |
1990 } else { | |
1991 Diag(Tok, diag::err_expected_semi_decl_list); | |
1992 // Skip to end of block or statement | |
1993 SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch); | |
1994 } | |
1995 } | |
1996 HelperActionsForIvarDeclarations(interfaceDecl, atLoc, | |
1997 T, AllIvarDecls, false); | |
1998 } | |
1999 | |
2000 /// objc-protocol-declaration: | |
2001 /// objc-protocol-definition | |
2002 /// objc-protocol-forward-reference | |
2003 /// | |
2004 /// objc-protocol-definition: | |
2005 /// \@protocol identifier | |
2006 /// objc-protocol-refs[opt] | |
2007 /// objc-interface-decl-list | |
2008 /// \@end | |
2009 /// | |
2010 /// objc-protocol-forward-reference: | |
2011 /// \@protocol identifier-list ';' | |
2012 /// | |
2013 /// "\@protocol identifier ;" should be resolved as "\@protocol | |
2014 /// identifier-list ;": objc-interface-decl-list may not start with a | |
2015 /// semicolon in the first alternative if objc-protocol-refs are omitted. | |
2016 Parser::DeclGroupPtrTy | |
2017 Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc, | |
2018 ParsedAttributes &attrs) { | |
2019 assert(Tok.isObjCAtKeyword(tok::objc_protocol) && | |
2020 "ParseObjCAtProtocolDeclaration(): Expected @protocol"); | |
2021 ConsumeToken(); // the "protocol" identifier | |
2022 | |
2023 if (Tok.is(tok::code_completion)) { | |
2024 Actions.CodeCompleteObjCProtocolDecl(getCurScope()); | |
2025 cutOffParsing(); | |
2026 return nullptr; | |
2027 } | |
2028 | |
2029 MaybeSkipAttributes(tok::objc_protocol); | |
2030 | |
2031 if (expectIdentifier()) | |
2032 return nullptr; // missing protocol name. | |
2033 // Save the protocol name, then consume it. | |
2034 IdentifierInfo *protocolName = Tok.getIdentifierInfo(); | |
2035 SourceLocation nameLoc = ConsumeToken(); | |
2036 | |
2037 if (TryConsumeToken(tok::semi)) { // forward declaration of one protocol. | |
2038 IdentifierLocPair ProtoInfo(protocolName, nameLoc); | |
2039 return Actions.ActOnForwardProtocolDeclaration(AtLoc, ProtoInfo, attrs); | |
2040 } | |
2041 | |
2042 CheckNestedObjCContexts(AtLoc); | |
2043 | |
2044 if (Tok.is(tok::comma)) { // list of forward declarations. | |
2045 SmallVector<IdentifierLocPair, 8> ProtocolRefs; | |
2046 ProtocolRefs.push_back(std::make_pair(protocolName, nameLoc)); | |
2047 | |
2048 // Parse the list of forward declarations. | |
2049 while (1) { | |
2050 ConsumeToken(); // the ',' | |
2051 if (expectIdentifier()) { | |
2052 SkipUntil(tok::semi); | |
2053 return nullptr; | |
2054 } | |
2055 ProtocolRefs.push_back(IdentifierLocPair(Tok.getIdentifierInfo(), | |
2056 Tok.getLocation())); | |
2057 ConsumeToken(); // the identifier | |
2058 | |
2059 if (Tok.isNot(tok::comma)) | |
2060 break; | |
2061 } | |
2062 // Consume the ';'. | |
2063 if (ExpectAndConsume(tok::semi, diag::err_expected_after, "@protocol")) | |
2064 return nullptr; | |
2065 | |
2066 return Actions.ActOnForwardProtocolDeclaration(AtLoc, ProtocolRefs, attrs); | |
2067 } | |
2068 | |
2069 // Last, and definitely not least, parse a protocol declaration. | |
2070 SourceLocation LAngleLoc, EndProtoLoc; | |
2071 | |
2072 SmallVector<Decl *, 8> ProtocolRefs; | |
2073 SmallVector<SourceLocation, 8> ProtocolLocs; | |
2074 if (Tok.is(tok::less) && | |
2075 ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, false, true, | |
2076 LAngleLoc, EndProtoLoc, | |
2077 /*consumeLastToken=*/true)) | |
2078 return nullptr; | |
2079 | |
2080 Decl *ProtoType = Actions.ActOnStartProtocolInterface( | |
2081 AtLoc, protocolName, nameLoc, ProtocolRefs.data(), ProtocolRefs.size(), | |
2082 ProtocolLocs.data(), EndProtoLoc, attrs); | |
2083 | |
2084 ParseObjCInterfaceDeclList(tok::objc_protocol, ProtoType); | |
2085 return Actions.ConvertDeclToDeclGroup(ProtoType); | |
2086 } | |
2087 | |
2088 /// objc-implementation: | |
2089 /// objc-class-implementation-prologue | |
2090 /// objc-category-implementation-prologue | |
2091 /// | |
2092 /// objc-class-implementation-prologue: | |
2093 /// @implementation identifier objc-superclass[opt] | |
2094 /// objc-class-instance-variables[opt] | |
2095 /// | |
2096 /// objc-category-implementation-prologue: | |
2097 /// @implementation identifier ( identifier ) | |
2098 Parser::DeclGroupPtrTy | |
2099 Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc, | |
2100 ParsedAttributes &Attrs) { | |
2101 assert(Tok.isObjCAtKeyword(tok::objc_implementation) && | |
2102 "ParseObjCAtImplementationDeclaration(): Expected @implementation"); | |
2103 CheckNestedObjCContexts(AtLoc); | |
2104 ConsumeToken(); // the "implementation" identifier | |
2105 | |
2106 // Code completion after '@implementation'. | |
2107 if (Tok.is(tok::code_completion)) { | |
2108 Actions.CodeCompleteObjCImplementationDecl(getCurScope()); | |
2109 cutOffParsing(); | |
2110 return nullptr; | |
2111 } | |
2112 | |
2113 MaybeSkipAttributes(tok::objc_implementation); | |
2114 | |
2115 if (expectIdentifier()) | |
2116 return nullptr; // missing class or category name. | |
2117 // We have a class or category name - consume it. | |
2118 IdentifierInfo *nameId = Tok.getIdentifierInfo(); | |
2119 SourceLocation nameLoc = ConsumeToken(); // consume class or category name | |
2120 Decl *ObjCImpDecl = nullptr; | |
2121 | |
2122 // Neither a type parameter list nor a list of protocol references is | |
2123 // permitted here. Parse and diagnose them. | |
2124 if (Tok.is(tok::less)) { | |
2125 SourceLocation lAngleLoc, rAngleLoc; | |
2126 SmallVector<IdentifierLocPair, 8> protocolIdents; | |
2127 SourceLocation diagLoc = Tok.getLocation(); | |
2128 ObjCTypeParamListScope typeParamScope(Actions, getCurScope()); | |
2129 if (parseObjCTypeParamListOrProtocolRefs(typeParamScope, lAngleLoc, | |
2130 protocolIdents, rAngleLoc)) { | |
2131 Diag(diagLoc, diag::err_objc_parameterized_implementation) | |
2132 << SourceRange(diagLoc, PrevTokLocation); | |
2133 } else if (lAngleLoc.isValid()) { | |
2134 Diag(lAngleLoc, diag::err_unexpected_protocol_qualifier) | |
2135 << FixItHint::CreateRemoval(SourceRange(lAngleLoc, rAngleLoc)); | |
2136 } | |
2137 } | |
2138 | |
2139 if (Tok.is(tok::l_paren)) { | |
2140 // we have a category implementation. | |
2141 ConsumeParen(); | |
2142 SourceLocation categoryLoc, rparenLoc; | |
2143 IdentifierInfo *categoryId = nullptr; | |
2144 | |
2145 if (Tok.is(tok::code_completion)) { | |
2146 Actions.CodeCompleteObjCImplementationCategory(getCurScope(), nameId, nameLoc); | |
2147 cutOffParsing(); | |
2148 return nullptr; | |
2149 } | |
2150 | |
2151 if (Tok.is(tok::identifier)) { | |
2152 categoryId = Tok.getIdentifierInfo(); | |
2153 categoryLoc = ConsumeToken(); | |
2154 } else { | |
2155 Diag(Tok, diag::err_expected) | |
2156 << tok::identifier; // missing category name. | |
2157 return nullptr; | |
2158 } | |
2159 if (Tok.isNot(tok::r_paren)) { | |
2160 Diag(Tok, diag::err_expected) << tok::r_paren; | |
2161 SkipUntil(tok::r_paren); // don't stop at ';' | |
2162 return nullptr; | |
2163 } | |
2164 rparenLoc = ConsumeParen(); | |
2165 if (Tok.is(tok::less)) { // we have illegal '<' try to recover | |
2166 Diag(Tok, diag::err_unexpected_protocol_qualifier); | |
2167 SourceLocation protocolLAngleLoc, protocolRAngleLoc; | |
2168 SmallVector<Decl *, 4> protocols; | |
2169 SmallVector<SourceLocation, 4> protocolLocs; | |
2170 (void)ParseObjCProtocolReferences(protocols, protocolLocs, | |
2171 /*warnOnIncompleteProtocols=*/false, | |
2172 /*ForObjCContainer=*/false, | |
2173 protocolLAngleLoc, protocolRAngleLoc, | |
2174 /*consumeLastToken=*/true); | |
2175 } | |
2176 ObjCImpDecl = Actions.ActOnStartCategoryImplementation( | |
2177 AtLoc, nameId, nameLoc, categoryId, categoryLoc, Attrs); | |
2178 | |
2179 } else { | |
2180 // We have a class implementation | |
2181 SourceLocation superClassLoc; | |
2182 IdentifierInfo *superClassId = nullptr; | |
2183 if (TryConsumeToken(tok::colon)) { | |
2184 // We have a super class | |
2185 if (expectIdentifier()) | |
2186 return nullptr; // missing super class name. | |
2187 superClassId = Tok.getIdentifierInfo(); | |
2188 superClassLoc = ConsumeToken(); // Consume super class name | |
2189 } | |
2190 ObjCImpDecl = Actions.ActOnStartClassImplementation( | |
2191 AtLoc, nameId, nameLoc, superClassId, superClassLoc, Attrs); | |
2192 | |
2193 if (Tok.is(tok::l_brace)) // we have ivars | |
2194 ParseObjCClassInstanceVariables(ObjCImpDecl, tok::objc_private, AtLoc); | |
2195 else if (Tok.is(tok::less)) { // we have illegal '<' try to recover | |
2196 Diag(Tok, diag::err_unexpected_protocol_qualifier); | |
2197 | |
2198 SourceLocation protocolLAngleLoc, protocolRAngleLoc; | |
2199 SmallVector<Decl *, 4> protocols; | |
2200 SmallVector<SourceLocation, 4> protocolLocs; | |
2201 (void)ParseObjCProtocolReferences(protocols, protocolLocs, | |
2202 /*warnOnIncompleteProtocols=*/false, | |
2203 /*ForObjCContainer=*/false, | |
2204 protocolLAngleLoc, protocolRAngleLoc, | |
2205 /*consumeLastToken=*/true); | |
2206 } | |
2207 } | |
2208 assert(ObjCImpDecl); | |
2209 | |
2210 SmallVector<Decl *, 8> DeclsInGroup; | |
2211 | |
2212 { | |
2213 ObjCImplParsingDataRAII ObjCImplParsing(*this, ObjCImpDecl); | |
2214 while (!ObjCImplParsing.isFinished() && !isEofOrEom()) { | |
2215 ParsedAttributesWithRange attrs(AttrFactory); | |
2216 MaybeParseCXX11Attributes(attrs); | |
2217 if (DeclGroupPtrTy DGP = ParseExternalDeclaration(attrs)) { | |
2218 DeclGroupRef DG = DGP.get(); | |
2219 DeclsInGroup.append(DG.begin(), DG.end()); | |
2220 } | |
2221 } | |
2222 } | |
2223 | |
2224 return Actions.ActOnFinishObjCImplementation(ObjCImpDecl, DeclsInGroup); | |
2225 } | |
2226 | |
2227 Parser::DeclGroupPtrTy | |
2228 Parser::ParseObjCAtEndDeclaration(SourceRange atEnd) { | |
2229 assert(Tok.isObjCAtKeyword(tok::objc_end) && | |
2230 "ParseObjCAtEndDeclaration(): Expected @end"); | |
2231 ConsumeToken(); // the "end" identifier | |
2232 if (CurParsedObjCImpl) | |
2233 CurParsedObjCImpl->finish(atEnd); | |
2234 else | |
2235 // missing @implementation | |
2236 Diag(atEnd.getBegin(), diag::err_expected_objc_container); | |
2237 return nullptr; | |
2238 } | |
2239 | |
2240 Parser::ObjCImplParsingDataRAII::~ObjCImplParsingDataRAII() { | |
2241 if (!Finished) { | |
2242 finish(P.Tok.getLocation()); | |
2243 if (P.isEofOrEom()) { | |
2244 P.Diag(P.Tok, diag::err_objc_missing_end) | |
2245 << FixItHint::CreateInsertion(P.Tok.getLocation(), "\n@end\n"); | |
2246 P.Diag(Dcl->getBeginLoc(), diag::note_objc_container_start) | |
2247 << Sema::OCK_Implementation; | |
2248 } | |
2249 } | |
2250 P.CurParsedObjCImpl = nullptr; | |
2251 assert(LateParsedObjCMethods.empty()); | |
2252 } | |
2253 | |
2254 void Parser::ObjCImplParsingDataRAII::finish(SourceRange AtEnd) { | |
2255 assert(!Finished); | |
2256 P.Actions.DefaultSynthesizeProperties(P.getCurScope(), Dcl, AtEnd.getBegin()); | |
2257 for (size_t i = 0; i < LateParsedObjCMethods.size(); ++i) | |
2258 P.ParseLexedObjCMethodDefs(*LateParsedObjCMethods[i], | |
2259 true/*Methods*/); | |
2260 | |
2261 P.Actions.ActOnAtEnd(P.getCurScope(), AtEnd); | |
2262 | |
2263 if (HasCFunction) | |
2264 for (size_t i = 0; i < LateParsedObjCMethods.size(); ++i) | |
2265 P.ParseLexedObjCMethodDefs(*LateParsedObjCMethods[i], | |
2266 false/*c-functions*/); | |
2267 | |
2268 /// Clear and free the cached objc methods. | |
2269 for (LateParsedObjCMethodContainer::iterator | |
2270 I = LateParsedObjCMethods.begin(), | |
2271 E = LateParsedObjCMethods.end(); I != E; ++I) | |
2272 delete *I; | |
2273 LateParsedObjCMethods.clear(); | |
2274 | |
2275 Finished = true; | |
2276 } | |
2277 | |
2278 /// compatibility-alias-decl: | |
2279 /// @compatibility_alias alias-name class-name ';' | |
2280 /// | |
2281 Decl *Parser::ParseObjCAtAliasDeclaration(SourceLocation atLoc) { | |
2282 assert(Tok.isObjCAtKeyword(tok::objc_compatibility_alias) && | |
2283 "ParseObjCAtAliasDeclaration(): Expected @compatibility_alias"); | |
2284 ConsumeToken(); // consume compatibility_alias | |
2285 if (expectIdentifier()) | |
2286 return nullptr; | |
2287 IdentifierInfo *aliasId = Tok.getIdentifierInfo(); | |
2288 SourceLocation aliasLoc = ConsumeToken(); // consume alias-name | |
2289 if (expectIdentifier()) | |
2290 return nullptr; | |
2291 IdentifierInfo *classId = Tok.getIdentifierInfo(); | |
2292 SourceLocation classLoc = ConsumeToken(); // consume class-name; | |
2293 ExpectAndConsume(tok::semi, diag::err_expected_after, "@compatibility_alias"); | |
2294 return Actions.ActOnCompatibilityAlias(atLoc, aliasId, aliasLoc, | |
2295 classId, classLoc); | |
2296 } | |
2297 | |
2298 /// property-synthesis: | |
2299 /// @synthesize property-ivar-list ';' | |
2300 /// | |
2301 /// property-ivar-list: | |
2302 /// property-ivar | |
2303 /// property-ivar-list ',' property-ivar | |
2304 /// | |
2305 /// property-ivar: | |
2306 /// identifier | |
2307 /// identifier '=' identifier | |
2308 /// | |
2309 Decl *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) { | |
2310 assert(Tok.isObjCAtKeyword(tok::objc_synthesize) && | |
2311 "ParseObjCPropertySynthesize(): Expected '@synthesize'"); | |
2312 ConsumeToken(); // consume synthesize | |
2313 | |
2314 while (true) { | |
2315 if (Tok.is(tok::code_completion)) { | |
2316 Actions.CodeCompleteObjCPropertyDefinition(getCurScope()); | |
2317 cutOffParsing(); | |
2318 return nullptr; | |
2319 } | |
2320 | |
2321 if (Tok.isNot(tok::identifier)) { | |
2322 Diag(Tok, diag::err_synthesized_property_name); | |
2323 SkipUntil(tok::semi); | |
2324 return nullptr; | |
2325 } | |
2326 | |
2327 IdentifierInfo *propertyIvar = nullptr; | |
2328 IdentifierInfo *propertyId = Tok.getIdentifierInfo(); | |
2329 SourceLocation propertyLoc = ConsumeToken(); // consume property name | |
2330 SourceLocation propertyIvarLoc; | |
2331 if (TryConsumeToken(tok::equal)) { | |
2332 // property '=' ivar-name | |
2333 if (Tok.is(tok::code_completion)) { | |
2334 Actions.CodeCompleteObjCPropertySynthesizeIvar(getCurScope(), propertyId); | |
2335 cutOffParsing(); | |
2336 return nullptr; | |
2337 } | |
2338 | |
2339 if (expectIdentifier()) | |
2340 break; | |
2341 propertyIvar = Tok.getIdentifierInfo(); | |
2342 propertyIvarLoc = ConsumeToken(); // consume ivar-name | |
2343 } | |
2344 Actions.ActOnPropertyImplDecl( | |
2345 getCurScope(), atLoc, propertyLoc, true, | |
2346 propertyId, propertyIvar, propertyIvarLoc, | |
2347 ObjCPropertyQueryKind::OBJC_PR_query_unknown); | |
2348 if (Tok.isNot(tok::comma)) | |
2349 break; | |
2350 ConsumeToken(); // consume ',' | |
2351 } | |
2352 ExpectAndConsume(tok::semi, diag::err_expected_after, "@synthesize"); | |
2353 return nullptr; | |
2354 } | |
2355 | |
2356 /// property-dynamic: | |
2357 /// @dynamic property-list | |
2358 /// | |
2359 /// property-list: | |
2360 /// identifier | |
2361 /// property-list ',' identifier | |
2362 /// | |
2363 Decl *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) { | |
2364 assert(Tok.isObjCAtKeyword(tok::objc_dynamic) && | |
2365 "ParseObjCPropertyDynamic(): Expected '@dynamic'"); | |
2366 ConsumeToken(); // consume dynamic | |
2367 | |
2368 bool isClassProperty = false; | |
2369 if (Tok.is(tok::l_paren)) { | |
2370 ConsumeParen(); | |
2371 const IdentifierInfo *II = Tok.getIdentifierInfo(); | |
2372 | |
2373 if (!II) { | |
2374 Diag(Tok, diag::err_objc_expected_property_attr) << II; | |
2375 SkipUntil(tok::r_paren, StopAtSemi); | |
2376 } else { | |
2377 SourceLocation AttrName = ConsumeToken(); // consume attribute name | |
2378 if (II->isStr("class")) { | |
2379 isClassProperty = true; | |
2380 if (Tok.isNot(tok::r_paren)) { | |
2381 Diag(Tok, diag::err_expected) << tok::r_paren; | |
2382 SkipUntil(tok::r_paren, StopAtSemi); | |
2383 } else | |
2384 ConsumeParen(); | |
2385 } else { | |
2386 Diag(AttrName, diag::err_objc_expected_property_attr) << II; | |
2387 SkipUntil(tok::r_paren, StopAtSemi); | |
2388 } | |
2389 } | |
2390 } | |
2391 | |
2392 while (true) { | |
2393 if (Tok.is(tok::code_completion)) { | |
2394 Actions.CodeCompleteObjCPropertyDefinition(getCurScope()); | |
2395 cutOffParsing(); | |
2396 return nullptr; | |
2397 } | |
2398 | |
2399 if (expectIdentifier()) { | |
2400 SkipUntil(tok::semi); | |
2401 return nullptr; | |
2402 } | |
2403 | |
2404 IdentifierInfo *propertyId = Tok.getIdentifierInfo(); | |
2405 SourceLocation propertyLoc = ConsumeToken(); // consume property name | |
2406 Actions.ActOnPropertyImplDecl( | |
2407 getCurScope(), atLoc, propertyLoc, false, | |
2408 propertyId, nullptr, SourceLocation(), | |
2409 isClassProperty ? ObjCPropertyQueryKind::OBJC_PR_query_class : | |
2410 ObjCPropertyQueryKind::OBJC_PR_query_unknown); | |
2411 | |
2412 if (Tok.isNot(tok::comma)) | |
2413 break; | |
2414 ConsumeToken(); // consume ',' | |
2415 } | |
2416 ExpectAndConsume(tok::semi, diag::err_expected_after, "@dynamic"); | |
2417 return nullptr; | |
2418 } | |
2419 | |
2420 /// objc-throw-statement: | |
2421 /// throw expression[opt]; | |
2422 /// | |
2423 StmtResult Parser::ParseObjCThrowStmt(SourceLocation atLoc) { | |
2424 ExprResult Res; | |
2425 ConsumeToken(); // consume throw | |
2426 if (Tok.isNot(tok::semi)) { | |
2427 Res = ParseExpression(); | |
2428 if (Res.isInvalid()) { | |
2429 SkipUntil(tok::semi); | |
2430 return StmtError(); | |
2431 } | |
2432 } | |
2433 // consume ';' | |
2434 ExpectAndConsume(tok::semi, diag::err_expected_after, "@throw"); | |
2435 return Actions.ActOnObjCAtThrowStmt(atLoc, Res.get(), getCurScope()); | |
2436 } | |
2437 | |
2438 /// objc-synchronized-statement: | |
2439 /// @synchronized '(' expression ')' compound-statement | |
2440 /// | |
2441 StmtResult | |
2442 Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) { | |
2443 ConsumeToken(); // consume synchronized | |
2444 if (Tok.isNot(tok::l_paren)) { | |
2445 Diag(Tok, diag::err_expected_lparen_after) << "@synchronized"; | |
2446 return StmtError(); | |
2447 } | |
2448 | |
2449 // The operand is surrounded with parentheses. | |
2450 ConsumeParen(); // '(' | |
2451 ExprResult operand(ParseExpression()); | |
2452 | |
2453 if (Tok.is(tok::r_paren)) { | |
2454 ConsumeParen(); // ')' | |
2455 } else { | |
2456 if (!operand.isInvalid()) | |
2457 Diag(Tok, diag::err_expected) << tok::r_paren; | |
2458 | |
2459 // Skip forward until we see a left brace, but don't consume it. | |
2460 SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch); | |
2461 } | |
2462 | |
2463 // Require a compound statement. | |
2464 if (Tok.isNot(tok::l_brace)) { | |
2465 if (!operand.isInvalid()) | |
2466 Diag(Tok, diag::err_expected) << tok::l_brace; | |
2467 return StmtError(); | |
2468 } | |
2469 | |
2470 // Check the @synchronized operand now. | |
2471 if (!operand.isInvalid()) | |
2472 operand = Actions.ActOnObjCAtSynchronizedOperand(atLoc, operand.get()); | |
2473 | |
2474 // Parse the compound statement within a new scope. | |
2475 ParseScope bodyScope(this, Scope::DeclScope | Scope::CompoundStmtScope); | |
2476 StmtResult body(ParseCompoundStatementBody()); | |
2477 bodyScope.Exit(); | |
2478 | |
2479 // If there was a semantic or parse error earlier with the | |
2480 // operand, fail now. | |
2481 if (operand.isInvalid()) | |
2482 return StmtError(); | |
2483 | |
2484 if (body.isInvalid()) | |
2485 body = Actions.ActOnNullStmt(Tok.getLocation()); | |
2486 | |
2487 return Actions.ActOnObjCAtSynchronizedStmt(atLoc, operand.get(), body.get()); | |
2488 } | |
2489 | |
2490 /// objc-try-catch-statement: | |
2491 /// @try compound-statement objc-catch-list[opt] | |
2492 /// @try compound-statement objc-catch-list[opt] @finally compound-statement | |
2493 /// | |
2494 /// objc-catch-list: | |
2495 /// @catch ( parameter-declaration ) compound-statement | |
2496 /// objc-catch-list @catch ( catch-parameter-declaration ) compound-statement | |
2497 /// catch-parameter-declaration: | |
2498 /// parameter-declaration | |
2499 /// '...' [OBJC2] | |
2500 /// | |
2501 StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) { | |
2502 bool catch_or_finally_seen = false; | |
2503 | |
2504 ConsumeToken(); // consume try | |
2505 if (Tok.isNot(tok::l_brace)) { | |
2506 Diag(Tok, diag::err_expected) << tok::l_brace; | |
2507 return StmtError(); | |
2508 } | |
2509 StmtVector CatchStmts; | |
2510 StmtResult FinallyStmt; | |
2511 ParseScope TryScope(this, Scope::DeclScope | Scope::CompoundStmtScope); | |
2512 StmtResult TryBody(ParseCompoundStatementBody()); | |
2513 TryScope.Exit(); | |
2514 if (TryBody.isInvalid()) | |
2515 TryBody = Actions.ActOnNullStmt(Tok.getLocation()); | |
2516 | |
2517 while (Tok.is(tok::at)) { | |
2518 // At this point, we need to lookahead to determine if this @ is the start | |
2519 // of an @catch or @finally. We don't want to consume the @ token if this | |
2520 // is an @try or @encode or something else. | |
2521 Token AfterAt = GetLookAheadToken(1); | |
2522 if (!AfterAt.isObjCAtKeyword(tok::objc_catch) && | |
2523 !AfterAt.isObjCAtKeyword(tok::objc_finally)) | |
2524 break; | |
2525 | |
2526 SourceLocation AtCatchFinallyLoc = ConsumeToken(); | |
2527 if (Tok.isObjCAtKeyword(tok::objc_catch)) { | |
2528 Decl *FirstPart = nullptr; | |
2529 ConsumeToken(); // consume catch | |
2530 if (Tok.is(tok::l_paren)) { | |
2531 ConsumeParen(); | |
2532 ParseScope CatchScope(this, Scope::DeclScope | | |
2533 Scope::CompoundStmtScope | | |
2534 Scope::AtCatchScope); | |
2535 if (Tok.isNot(tok::ellipsis)) { | |
2536 DeclSpec DS(AttrFactory); | |
2537 ParseDeclarationSpecifiers(DS); | |
2538 Declarator ParmDecl(DS, DeclaratorContext::ObjCCatchContext); | |
2539 ParseDeclarator(ParmDecl); | |
2540 | |
2541 // Inform the actions module about the declarator, so it | |
2542 // gets added to the current scope. | |
2543 FirstPart = Actions.ActOnObjCExceptionDecl(getCurScope(), ParmDecl); | |
2544 } else | |
2545 ConsumeToken(); // consume '...' | |
2546 | |
2547 SourceLocation RParenLoc; | |
2548 | |
2549 if (Tok.is(tok::r_paren)) | |
2550 RParenLoc = ConsumeParen(); | |
2551 else // Skip over garbage, until we get to ')'. Eat the ')'. | |
2552 SkipUntil(tok::r_paren, StopAtSemi); | |
2553 | |
2554 StmtResult CatchBody(true); | |
2555 if (Tok.is(tok::l_brace)) | |
2556 CatchBody = ParseCompoundStatementBody(); | |
2557 else | |
2558 Diag(Tok, diag::err_expected) << tok::l_brace; | |
2559 if (CatchBody.isInvalid()) | |
2560 CatchBody = Actions.ActOnNullStmt(Tok.getLocation()); | |
2561 | |
2562 StmtResult Catch = Actions.ActOnObjCAtCatchStmt(AtCatchFinallyLoc, | |
2563 RParenLoc, | |
2564 FirstPart, | |
2565 CatchBody.get()); | |
2566 if (!Catch.isInvalid()) | |
2567 CatchStmts.push_back(Catch.get()); | |
2568 | |
2569 } else { | |
2570 Diag(AtCatchFinallyLoc, diag::err_expected_lparen_after) | |
2571 << "@catch clause"; | |
2572 return StmtError(); | |
2573 } | |
2574 catch_or_finally_seen = true; | |
2575 } else { | |
2576 assert(Tok.isObjCAtKeyword(tok::objc_finally) && "Lookahead confused?"); | |
2577 ConsumeToken(); // consume finally | |
2578 ParseScope FinallyScope(this, | |
2579 Scope::DeclScope | Scope::CompoundStmtScope); | |
2580 | |
2581 bool ShouldCapture = | |
2582 getTargetInfo().getTriple().isWindowsMSVCEnvironment(); | |
2583 if (ShouldCapture) | |
2584 Actions.ActOnCapturedRegionStart(Tok.getLocation(), getCurScope(), | |
2585 CR_ObjCAtFinally, 1); | |
2586 | |
2587 StmtResult FinallyBody(true); | |
2588 if (Tok.is(tok::l_brace)) | |
2589 FinallyBody = ParseCompoundStatementBody(); | |
2590 else | |
2591 Diag(Tok, diag::err_expected) << tok::l_brace; | |
2592 | |
2593 if (FinallyBody.isInvalid()) { | |
2594 FinallyBody = Actions.ActOnNullStmt(Tok.getLocation()); | |
2595 if (ShouldCapture) | |
2596 Actions.ActOnCapturedRegionError(); | |
2597 } else if (ShouldCapture) { | |
2598 FinallyBody = Actions.ActOnCapturedRegionEnd(FinallyBody.get()); | |
2599 } | |
2600 | |
2601 FinallyStmt = Actions.ActOnObjCAtFinallyStmt(AtCatchFinallyLoc, | |
2602 FinallyBody.get()); | |
2603 catch_or_finally_seen = true; | |
2604 break; | |
2605 } | |
2606 } | |
2607 if (!catch_or_finally_seen) { | |
2608 Diag(atLoc, diag::err_missing_catch_finally); | |
2609 return StmtError(); | |
2610 } | |
2611 | |
2612 return Actions.ActOnObjCAtTryStmt(atLoc, TryBody.get(), | |
2613 CatchStmts, | |
2614 FinallyStmt.get()); | |
2615 } | |
2616 | |
2617 /// objc-autoreleasepool-statement: | |
2618 /// @autoreleasepool compound-statement | |
2619 /// | |
2620 StmtResult | |
2621 Parser::ParseObjCAutoreleasePoolStmt(SourceLocation atLoc) { | |
2622 ConsumeToken(); // consume autoreleasepool | |
2623 if (Tok.isNot(tok::l_brace)) { | |
2624 Diag(Tok, diag::err_expected) << tok::l_brace; | |
2625 return StmtError(); | |
2626 } | |
2627 // Enter a scope to hold everything within the compound stmt. Compound | |
2628 // statements can always hold declarations. | |
2629 ParseScope BodyScope(this, Scope::DeclScope | Scope::CompoundStmtScope); | |
2630 | |
2631 StmtResult AutoreleasePoolBody(ParseCompoundStatementBody()); | |
2632 | |
2633 BodyScope.Exit(); | |
2634 if (AutoreleasePoolBody.isInvalid()) | |
2635 AutoreleasePoolBody = Actions.ActOnNullStmt(Tok.getLocation()); | |
2636 return Actions.ActOnObjCAutoreleasePoolStmt(atLoc, | |
2637 AutoreleasePoolBody.get()); | |
2638 } | |
2639 | |
2640 /// StashAwayMethodOrFunctionBodyTokens - Consume the tokens and store them | |
2641 /// for later parsing. | |
2642 void Parser::StashAwayMethodOrFunctionBodyTokens(Decl *MDecl) { | |
2643 if (SkipFunctionBodies && (!MDecl || Actions.canSkipFunctionBody(MDecl)) && | |
2644 trySkippingFunctionBody()) { | |
2645 Actions.ActOnSkippedFunctionBody(MDecl); | |
2646 return; | |
2647 } | |
2648 | |
2649 LexedMethod* LM = new LexedMethod(this, MDecl); | |
2650 CurParsedObjCImpl->LateParsedObjCMethods.push_back(LM); | |
2651 CachedTokens &Toks = LM->Toks; | |
2652 // Begin by storing the '{' or 'try' or ':' token. | |
2653 Toks.push_back(Tok); | |
2654 if (Tok.is(tok::kw_try)) { | |
2655 ConsumeToken(); | |
2656 if (Tok.is(tok::colon)) { | |
2657 Toks.push_back(Tok); | |
2658 ConsumeToken(); | |
2659 while (Tok.isNot(tok::l_brace)) { | |
2660 ConsumeAndStoreUntil(tok::l_paren, Toks, /*StopAtSemi=*/false); | |
2661 ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/false); | |
2662 } | |
2663 } | |
2664 Toks.push_back(Tok); // also store '{' | |
2665 } | |
2666 else if (Tok.is(tok::colon)) { | |
2667 ConsumeToken(); | |
2668 // FIXME: This is wrong, due to C++11 braced initialization. | |
2669 while (Tok.isNot(tok::l_brace)) { | |
2670 ConsumeAndStoreUntil(tok::l_paren, Toks, /*StopAtSemi=*/false); | |
2671 ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/false); | |
2672 } | |
2673 Toks.push_back(Tok); // also store '{' | |
2674 } | |
2675 ConsumeBrace(); | |
2676 // Consume everything up to (and including) the matching right brace. | |
2677 ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false); | |
2678 while (Tok.is(tok::kw_catch)) { | |
2679 ConsumeAndStoreUntil(tok::l_brace, Toks, /*StopAtSemi=*/false); | |
2680 ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false); | |
2681 } | |
2682 } | |
2683 | |
2684 /// objc-method-def: objc-method-proto ';'[opt] '{' body '}' | |
2685 /// | |
2686 Decl *Parser::ParseObjCMethodDefinition() { | |
2687 Decl *MDecl = ParseObjCMethodPrototype(); | |
2688 | |
2689 PrettyDeclStackTraceEntry CrashInfo(Actions.Context, MDecl, Tok.getLocation(), | |
2690 "parsing Objective-C method"); | |
2691 | |
2692 // parse optional ';' | |
2693 if (Tok.is(tok::semi)) { | |
2694 if (CurParsedObjCImpl) { | |
2695 Diag(Tok, diag::warn_semicolon_before_method_body) | |
2696 << FixItHint::CreateRemoval(Tok.getLocation()); | |
2697 } | |
2698 ConsumeToken(); | |
2699 } | |
2700 | |
2701 // We should have an opening brace now. | |
2702 if (Tok.isNot(tok::l_brace)) { | |
2703 Diag(Tok, diag::err_expected_method_body); | |
2704 | |
2705 // Skip over garbage, until we get to '{'. Don't eat the '{'. | |
2706 SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch); | |
2707 | |
2708 // If we didn't find the '{', bail out. | |
2709 if (Tok.isNot(tok::l_brace)) | |
2710 return nullptr; | |
2711 } | |
2712 | |
2713 if (!MDecl) { | |
2714 ConsumeBrace(); | |
2715 SkipUntil(tok::r_brace); | |
2716 return nullptr; | |
2717 } | |
2718 | |
2719 // Allow the rest of sema to find private method decl implementations. | |
2720 Actions.AddAnyMethodToGlobalPool(MDecl); | |
2721 assert (CurParsedObjCImpl | |
2722 && "ParseObjCMethodDefinition - Method out of @implementation"); | |
2723 // Consume the tokens and store them for later parsing. | |
2724 StashAwayMethodOrFunctionBodyTokens(MDecl); | |
2725 return MDecl; | |
2726 } | |
2727 | |
2728 StmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc, | |
2729 ParsedStmtContext StmtCtx) { | |
2730 if (Tok.is(tok::code_completion)) { | |
2731 Actions.CodeCompleteObjCAtStatement(getCurScope()); | |
2732 cutOffParsing(); | |
2733 return StmtError(); | |
2734 } | |
2735 | |
2736 if (Tok.isObjCAtKeyword(tok::objc_try)) | |
2737 return ParseObjCTryStmt(AtLoc); | |
2738 | |
2739 if (Tok.isObjCAtKeyword(tok::objc_throw)) | |
2740 return ParseObjCThrowStmt(AtLoc); | |
2741 | |
2742 if (Tok.isObjCAtKeyword(tok::objc_synchronized)) | |
2743 return ParseObjCSynchronizedStmt(AtLoc); | |
2744 | |
2745 if (Tok.isObjCAtKeyword(tok::objc_autoreleasepool)) | |
2746 return ParseObjCAutoreleasePoolStmt(AtLoc); | |
2747 | |
2748 if (Tok.isObjCAtKeyword(tok::objc_import) && | |
2749 getLangOpts().DebuggerSupport) { | |
2750 SkipUntil(tok::semi); | |
2751 return Actions.ActOnNullStmt(Tok.getLocation()); | |
2752 } | |
2753 | |
2754 ExprStatementTokLoc = AtLoc; | |
2755 ExprResult Res(ParseExpressionWithLeadingAt(AtLoc)); | |
2756 if (Res.isInvalid()) { | |
2757 // If the expression is invalid, skip ahead to the next semicolon. Not | |
2758 // doing this opens us up to the possibility of infinite loops if | |
2759 // ParseExpression does not consume any tokens. | |
2760 SkipUntil(tok::semi); | |
2761 return StmtError(); | |
2762 } | |
2763 | |
2764 // Otherwise, eat the semicolon. | |
2765 ExpectAndConsumeSemi(diag::err_expected_semi_after_expr); | |
2766 return handleExprStmt(Res, StmtCtx); | |
2767 } | |
2768 | |
2769 ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) { | |
2770 switch (Tok.getKind()) { | |
2771 case tok::code_completion: | |
2772 Actions.CodeCompleteObjCAtExpression(getCurScope()); | |
2773 cutOffParsing(); | |
2774 return ExprError(); | |
2775 | |
2776 case tok::minus: | |
2777 case tok::plus: { | |
2778 tok::TokenKind Kind = Tok.getKind(); | |
2779 SourceLocation OpLoc = ConsumeToken(); | |
2780 | |
2781 if (!Tok.is(tok::numeric_constant)) { | |
2782 const char *Symbol = nullptr; | |
2783 switch (Kind) { | |
2784 case tok::minus: Symbol = "-"; break; | |
2785 case tok::plus: Symbol = "+"; break; | |
2786 default: llvm_unreachable("missing unary operator case"); | |
2787 } | |
2788 Diag(Tok, diag::err_nsnumber_nonliteral_unary) | |
2789 << Symbol; | |
2790 return ExprError(); | |
2791 } | |
2792 | |
2793 ExprResult Lit(Actions.ActOnNumericConstant(Tok)); | |
2794 if (Lit.isInvalid()) { | |
2795 return Lit; | |
2796 } | |
2797 ConsumeToken(); // Consume the literal token. | |
2798 | |
2799 Lit = Actions.ActOnUnaryOp(getCurScope(), OpLoc, Kind, Lit.get()); | |
2800 if (Lit.isInvalid()) | |
2801 return Lit; | |
2802 | |
2803 return ParsePostfixExpressionSuffix( | |
2804 Actions.BuildObjCNumericLiteral(AtLoc, Lit.get())); | |
2805 } | |
2806 | |
2807 case tok::string_literal: // primary-expression: string-literal | |
2808 case tok::wide_string_literal: | |
2809 return ParsePostfixExpressionSuffix(ParseObjCStringLiteral(AtLoc)); | |
2810 | |
2811 case tok::char_constant: | |
2812 return ParsePostfixExpressionSuffix(ParseObjCCharacterLiteral(AtLoc)); | |
2813 | |
2814 case tok::numeric_constant: | |
2815 return ParsePostfixExpressionSuffix(ParseObjCNumericLiteral(AtLoc)); | |
2816 | |
2817 case tok::kw_true: // Objective-C++, etc. | |
2818 case tok::kw___objc_yes: // c/c++/objc/objc++ __objc_yes | |
2819 return ParsePostfixExpressionSuffix(ParseObjCBooleanLiteral(AtLoc, true)); | |
2820 case tok::kw_false: // Objective-C++, etc. | |
2821 case tok::kw___objc_no: // c/c++/objc/objc++ __objc_no | |
2822 return ParsePostfixExpressionSuffix(ParseObjCBooleanLiteral(AtLoc, false)); | |
2823 | |
2824 case tok::l_square: | |
2825 // Objective-C array literal | |
2826 return ParsePostfixExpressionSuffix(ParseObjCArrayLiteral(AtLoc)); | |
2827 | |
2828 case tok::l_brace: | |
2829 // Objective-C dictionary literal | |
2830 return ParsePostfixExpressionSuffix(ParseObjCDictionaryLiteral(AtLoc)); | |
2831 | |
2832 case tok::l_paren: | |
2833 // Objective-C boxed expression | |
2834 return ParsePostfixExpressionSuffix(ParseObjCBoxedExpr(AtLoc)); | |
2835 | |
2836 default: | |
2837 if (Tok.getIdentifierInfo() == nullptr) | |
2838 return ExprError(Diag(AtLoc, diag::err_unexpected_at)); | |
2839 | |
2840 switch (Tok.getIdentifierInfo()->getObjCKeywordID()) { | |
2841 case tok::objc_encode: | |
2842 return ParsePostfixExpressionSuffix(ParseObjCEncodeExpression(AtLoc)); | |
2843 case tok::objc_protocol: | |
2844 return ParsePostfixExpressionSuffix(ParseObjCProtocolExpression(AtLoc)); | |
2845 case tok::objc_selector: | |
2846 return ParsePostfixExpressionSuffix(ParseObjCSelectorExpression(AtLoc)); | |
2847 case tok::objc_available: | |
2848 return ParseAvailabilityCheckExpr(AtLoc); | |
2849 default: { | |
2850 const char *str = nullptr; | |
2851 // Only provide the @try/@finally/@autoreleasepool fixit when we're sure | |
2852 // that this is a proper statement where such directives could actually | |
2853 // occur. | |
2854 if (GetLookAheadToken(1).is(tok::l_brace) && | |
2855 ExprStatementTokLoc == AtLoc) { | |
2856 char ch = Tok.getIdentifierInfo()->getNameStart()[0]; | |
2857 str = | |
2858 ch == 't' ? "try" | |
2859 : (ch == 'f' ? "finally" | |
2860 : (ch == 'a' ? "autoreleasepool" : nullptr)); | |
2861 } | |
2862 if (str) { | |
2863 SourceLocation kwLoc = Tok.getLocation(); | |
2864 return ExprError(Diag(AtLoc, diag::err_unexpected_at) << | |
2865 FixItHint::CreateReplacement(kwLoc, str)); | |
2866 } | |
2867 else | |
2868 return ExprError(Diag(AtLoc, diag::err_unexpected_at)); | |
2869 } | |
2870 } | |
2871 } | |
2872 } | |
2873 | |
2874 /// Parse the receiver of an Objective-C++ message send. | |
2875 /// | |
2876 /// This routine parses the receiver of a message send in | |
2877 /// Objective-C++ either as a type or as an expression. Note that this | |
2878 /// routine must not be called to parse a send to 'super', since it | |
2879 /// has no way to return such a result. | |
2880 /// | |
2881 /// \param IsExpr Whether the receiver was parsed as an expression. | |
2882 /// | |
2883 /// \param TypeOrExpr If the receiver was parsed as an expression (\c | |
2884 /// IsExpr is true), the parsed expression. If the receiver was parsed | |
2885 /// as a type (\c IsExpr is false), the parsed type. | |
2886 /// | |
2887 /// \returns True if an error occurred during parsing or semantic | |
2888 /// analysis, in which case the arguments do not have valid | |
2889 /// values. Otherwise, returns false for a successful parse. | |
2890 /// | |
2891 /// objc-receiver: [C++] | |
2892 /// 'super' [not parsed here] | |
2893 /// expression | |
2894 /// simple-type-specifier | |
2895 /// typename-specifier | |
2896 bool Parser::ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr) { | |
2897 InMessageExpressionRAIIObject InMessage(*this, true); | |
2898 | |
2899 if (Tok.isOneOf(tok::identifier, tok::coloncolon, tok::kw_typename, | |
2900 tok::annot_cxxscope)) | |
2901 TryAnnotateTypeOrScopeToken(); | |
2902 | |
2903 if (!Actions.isSimpleTypeSpecifier(Tok.getKind())) { | |
2904 // objc-receiver: | |
2905 // expression | |
2906 // Make sure any typos in the receiver are corrected or diagnosed, so that | |
2907 // proper recovery can happen. FIXME: Perhaps filter the corrected expr to | |
2908 // only the things that are valid ObjC receivers? | |
2909 ExprResult Receiver = Actions.CorrectDelayedTyposInExpr(ParseExpression()); | |
2910 if (Receiver.isInvalid()) | |
2911 return true; | |
2912 | |
2913 IsExpr = true; | |
2914 TypeOrExpr = Receiver.get(); | |
2915 return false; | |
2916 } | |
2917 | |
2918 // objc-receiver: | |
2919 // typename-specifier | |
2920 // simple-type-specifier | |
2921 // expression (that starts with one of the above) | |
2922 DeclSpec DS(AttrFactory); | |
2923 ParseCXXSimpleTypeSpecifier(DS); | |
2924 | |
2925 if (Tok.is(tok::l_paren)) { | |
2926 // If we see an opening parentheses at this point, we are | |
2927 // actually parsing an expression that starts with a | |
2928 // function-style cast, e.g., | |
2929 // | |
2930 // postfix-expression: | |
2931 // simple-type-specifier ( expression-list [opt] ) | |
2932 // typename-specifier ( expression-list [opt] ) | |
2933 // | |
2934 // Parse the remainder of this case, then the (optional) | |
2935 // postfix-expression suffix, followed by the (optional) | |
2936 // right-hand side of the binary expression. We have an | |
2937 // instance method. | |
2938 ExprResult Receiver = ParseCXXTypeConstructExpression(DS); | |
2939 if (!Receiver.isInvalid()) | |
2940 Receiver = ParsePostfixExpressionSuffix(Receiver.get()); | |
2941 if (!Receiver.isInvalid()) | |
2942 Receiver = ParseRHSOfBinaryExpression(Receiver.get(), prec::Comma); | |
2943 if (Receiver.isInvalid()) | |
2944 return true; | |
2945 | |
2946 IsExpr = true; | |
2947 TypeOrExpr = Receiver.get(); | |
2948 return false; | |
2949 } | |
2950 | |
2951 // We have a class message. Turn the simple-type-specifier or | |
2952 // typename-specifier we parsed into a type and parse the | |
2953 // remainder of the class message. | |
2954 Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext); | |
2955 TypeResult Type = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo); | |
2956 if (Type.isInvalid()) | |
2957 return true; | |
2958 | |
2959 IsExpr = false; | |
2960 TypeOrExpr = Type.get().getAsOpaquePtr(); | |
2961 return false; | |
2962 } | |
2963 | |
2964 /// Determine whether the parser is currently referring to a an | |
2965 /// Objective-C message send, using a simplified heuristic to avoid overhead. | |
2966 /// | |
2967 /// This routine will only return true for a subset of valid message-send | |
2968 /// expressions. | |
2969 bool Parser::isSimpleObjCMessageExpression() { | |
2970 assert(Tok.is(tok::l_square) && getLangOpts().ObjC && | |
2971 "Incorrect start for isSimpleObjCMessageExpression"); | |
2972 return GetLookAheadToken(1).is(tok::identifier) && | |
2973 GetLookAheadToken(2).is(tok::identifier); | |
2974 } | |
2975 | |
2976 bool Parser::isStartOfObjCClassMessageMissingOpenBracket() { | |
2977 if (!getLangOpts().ObjC || !NextToken().is(tok::identifier) || | |
2978 InMessageExpression) | |
2979 return false; | |
2980 | |
2981 ParsedType Type; | |
2982 | |
2983 if (Tok.is(tok::annot_typename)) | |
2984 Type = getTypeAnnotation(Tok); | |
2985 else if (Tok.is(tok::identifier)) | |
2986 Type = Actions.getTypeName(*Tok.getIdentifierInfo(), Tok.getLocation(), | |
2987 getCurScope()); | |
2988 else | |
2989 return false; | |
2990 | |
2991 if (!Type.get().isNull() && Type.get()->isObjCObjectOrInterfaceType()) { | |
2992 const Token &AfterNext = GetLookAheadToken(2); | |
2993 if (AfterNext.isOneOf(tok::colon, tok::r_square)) { | |
2994 if (Tok.is(tok::identifier)) | |
2995 TryAnnotateTypeOrScopeToken(); | |
2996 | |
2997 return Tok.is(tok::annot_typename); | |
2998 } | |
2999 } | |
3000 | |
3001 return false; | |
3002 } | |
3003 | |
3004 /// objc-message-expr: | |
3005 /// '[' objc-receiver objc-message-args ']' | |
3006 /// | |
3007 /// objc-receiver: [C] | |
3008 /// 'super' | |
3009 /// expression | |
3010 /// class-name | |
3011 /// type-name | |
3012 /// | |
3013 ExprResult Parser::ParseObjCMessageExpression() { | |
3014 assert(Tok.is(tok::l_square) && "'[' expected"); | |
3015 SourceLocation LBracLoc = ConsumeBracket(); // consume '[' | |
3016 | |
3017 if (Tok.is(tok::code_completion)) { | |
3018 Actions.CodeCompleteObjCMessageReceiver(getCurScope()); | |
3019 cutOffParsing(); | |
3020 return ExprError(); | |
3021 } | |
3022 | |
3023 InMessageExpressionRAIIObject InMessage(*this, true); | |
3024 | |
3025 if (getLangOpts().CPlusPlus) { | |
3026 // We completely separate the C and C++ cases because C++ requires | |
3027 // more complicated (read: slower) parsing. | |
3028 | |
3029 // Handle send to super. | |
3030 // FIXME: This doesn't benefit from the same typo-correction we | |
3031 // get in Objective-C. | |
3032 if (Tok.is(tok::identifier) && Tok.getIdentifierInfo() == Ident_super && | |
3033 NextToken().isNot(tok::period) && getCurScope()->isInObjcMethodScope()) | |
3034 return ParseObjCMessageExpressionBody(LBracLoc, ConsumeToken(), nullptr, | |
3035 nullptr); | |
3036 | |
3037 // Parse the receiver, which is either a type or an expression. | |
3038 bool IsExpr; | |
3039 void *TypeOrExpr = nullptr; | |
3040 if (ParseObjCXXMessageReceiver(IsExpr, TypeOrExpr)) { | |
3041 SkipUntil(tok::r_square, StopAtSemi); | |
3042 return ExprError(); | |
3043 } | |
3044 | |
3045 if (IsExpr) | |
3046 return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(), nullptr, | |
3047 static_cast<Expr *>(TypeOrExpr)); | |
3048 | |
3049 return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(), | |
3050 ParsedType::getFromOpaquePtr(TypeOrExpr), | |
3051 nullptr); | |
3052 } | |
3053 | |
3054 if (Tok.is(tok::identifier)) { | |
3055 IdentifierInfo *Name = Tok.getIdentifierInfo(); | |
3056 SourceLocation NameLoc = Tok.getLocation(); | |
3057 ParsedType ReceiverType; | |
3058 switch (Actions.getObjCMessageKind(getCurScope(), Name, NameLoc, | |
3059 Name == Ident_super, | |
3060 NextToken().is(tok::period), | |
3061 ReceiverType)) { | |
3062 case Sema::ObjCSuperMessage: | |
3063 return ParseObjCMessageExpressionBody(LBracLoc, ConsumeToken(), nullptr, | |
3064 nullptr); | |
3065 | |
3066 case Sema::ObjCClassMessage: | |
3067 if (!ReceiverType) { | |
3068 SkipUntil(tok::r_square, StopAtSemi); | |
3069 return ExprError(); | |
3070 } | |
3071 | |
3072 ConsumeToken(); // the type name | |
3073 | |
3074 // Parse type arguments and protocol qualifiers. | |
3075 if (Tok.is(tok::less)) { | |
3076 SourceLocation NewEndLoc; | |
3077 TypeResult NewReceiverType | |
3078 = parseObjCTypeArgsAndProtocolQualifiers(NameLoc, ReceiverType, | |
3079 /*consumeLastToken=*/true, | |
3080 NewEndLoc); | |
3081 if (!NewReceiverType.isUsable()) { | |
3082 SkipUntil(tok::r_square, StopAtSemi); | |
3083 return ExprError(); | |
3084 } | |
3085 | |
3086 ReceiverType = NewReceiverType.get(); | |
3087 } | |
3088 | |
3089 return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(), | |
3090 ReceiverType, nullptr); | |
3091 | |
3092 case Sema::ObjCInstanceMessage: | |
3093 // Fall through to parse an expression. | |
3094 break; | |
3095 } | |
3096 } | |
3097 | |
3098 // Otherwise, an arbitrary expression can be the receiver of a send. | |
3099 ExprResult Res = Actions.CorrectDelayedTyposInExpr(ParseExpression()); | |
3100 if (Res.isInvalid()) { | |
3101 SkipUntil(tok::r_square, StopAtSemi); | |
3102 return Res; | |
3103 } | |
3104 | |
3105 return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(), nullptr, | |
3106 Res.get()); | |
3107 } | |
3108 | |
3109 /// Parse the remainder of an Objective-C message following the | |
3110 /// '[' objc-receiver. | |
3111 /// | |
3112 /// This routine handles sends to super, class messages (sent to a | |
3113 /// class name), and instance messages (sent to an object), and the | |
3114 /// target is represented by \p SuperLoc, \p ReceiverType, or \p | |
3115 /// ReceiverExpr, respectively. Only one of these parameters may have | |
3116 /// a valid value. | |
3117 /// | |
3118 /// \param LBracLoc The location of the opening '['. | |
3119 /// | |
3120 /// \param SuperLoc If this is a send to 'super', the location of the | |
3121 /// 'super' keyword that indicates a send to the superclass. | |
3122 /// | |
3123 /// \param ReceiverType If this is a class message, the type of the | |
3124 /// class we are sending a message to. | |
3125 /// | |
3126 /// \param ReceiverExpr If this is an instance message, the expression | |
3127 /// used to compute the receiver object. | |
3128 /// | |
3129 /// objc-message-args: | |
3130 /// objc-selector | |
3131 /// objc-keywordarg-list | |
3132 /// | |
3133 /// objc-keywordarg-list: | |
3134 /// objc-keywordarg | |
3135 /// objc-keywordarg-list objc-keywordarg | |
3136 /// | |
3137 /// objc-keywordarg: | |
3138 /// selector-name[opt] ':' objc-keywordexpr | |
3139 /// | |
3140 /// objc-keywordexpr: | |
3141 /// nonempty-expr-list | |
3142 /// | |
3143 /// nonempty-expr-list: | |
3144 /// assignment-expression | |
3145 /// nonempty-expr-list , assignment-expression | |
3146 /// | |
3147 ExprResult | |
3148 Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, | |
3149 SourceLocation SuperLoc, | |
3150 ParsedType ReceiverType, | |
3151 Expr *ReceiverExpr) { | |
3152 InMessageExpressionRAIIObject InMessage(*this, true); | |
3153 | |
3154 if (Tok.is(tok::code_completion)) { | |
3155 if (SuperLoc.isValid()) | |
3156 Actions.CodeCompleteObjCSuperMessage(getCurScope(), SuperLoc, None, | |
3157 false); | |
3158 else if (ReceiverType) | |
3159 Actions.CodeCompleteObjCClassMessage(getCurScope(), ReceiverType, None, | |
3160 false); | |
3161 else | |
3162 Actions.CodeCompleteObjCInstanceMessage(getCurScope(), ReceiverExpr, | |
3163 None, false); | |
3164 cutOffParsing(); | |
3165 return ExprError(); | |
3166 } | |
3167 | |
3168 // Parse objc-selector | |
3169 SourceLocation Loc; | |
3170 IdentifierInfo *selIdent = ParseObjCSelectorPiece(Loc); | |
3171 | |
3172 SmallVector<IdentifierInfo *, 12> KeyIdents; | |
3173 SmallVector<SourceLocation, 12> KeyLocs; | |
3174 ExprVector KeyExprs; | |
3175 | |
3176 if (Tok.is(tok::colon)) { | |
3177 while (1) { | |
3178 // Each iteration parses a single keyword argument. | |
3179 KeyIdents.push_back(selIdent); | |
3180 KeyLocs.push_back(Loc); | |
3181 | |
3182 if (ExpectAndConsume(tok::colon)) { | |
3183 // We must manually skip to a ']', otherwise the expression skipper will | |
3184 // stop at the ']' when it skips to the ';'. We want it to skip beyond | |
3185 // the enclosing expression. | |
3186 SkipUntil(tok::r_square, StopAtSemi); | |
3187 return ExprError(); | |
3188 } | |
3189 | |
3190 /// Parse the expression after ':' | |
3191 | |
3192 if (Tok.is(tok::code_completion)) { | |
3193 if (SuperLoc.isValid()) | |
3194 Actions.CodeCompleteObjCSuperMessage(getCurScope(), SuperLoc, | |
3195 KeyIdents, | |
3196 /*AtArgumentExpression=*/true); | |
3197 else if (ReceiverType) | |
3198 Actions.CodeCompleteObjCClassMessage(getCurScope(), ReceiverType, | |
3199 KeyIdents, | |
3200 /*AtArgumentExpression=*/true); | |
3201 else | |
3202 Actions.CodeCompleteObjCInstanceMessage(getCurScope(), ReceiverExpr, | |
3203 KeyIdents, | |
3204 /*AtArgumentExpression=*/true); | |
3205 | |
3206 cutOffParsing(); | |
3207 return ExprError(); | |
3208 } | |
3209 | |
3210 ExprResult Expr; | |
3211 if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { | |
3212 Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists); | |
3213 Expr = ParseBraceInitializer(); | |
3214 } else | |
3215 Expr = ParseAssignmentExpression(); | |
3216 | |
3217 ExprResult Res(Expr); | |
3218 if (Res.isInvalid()) { | |
3219 // We must manually skip to a ']', otherwise the expression skipper will | |
3220 // stop at the ']' when it skips to the ';'. We want it to skip beyond | |
3221 // the enclosing expression. | |
3222 SkipUntil(tok::r_square, StopAtSemi); | |
3223 return Res; | |
3224 } | |
3225 | |
3226 // We have a valid expression. | |
3227 KeyExprs.push_back(Res.get()); | |
3228 | |
3229 // Code completion after each argument. | |
3230 if (Tok.is(tok::code_completion)) { | |
3231 if (SuperLoc.isValid()) | |
3232 Actions.CodeCompleteObjCSuperMessage(getCurScope(), SuperLoc, | |
3233 KeyIdents, | |
3234 /*AtArgumentExpression=*/false); | |
3235 else if (ReceiverType) | |
3236 Actions.CodeCompleteObjCClassMessage(getCurScope(), ReceiverType, | |
3237 KeyIdents, | |
3238 /*AtArgumentExpression=*/false); | |
3239 else | |
3240 Actions.CodeCompleteObjCInstanceMessage(getCurScope(), ReceiverExpr, | |
3241 KeyIdents, | |
3242 /*AtArgumentExpression=*/false); | |
3243 cutOffParsing(); | |
3244 return ExprError(); | |
3245 } | |
3246 | |
3247 // Check for another keyword selector. | |
3248 selIdent = ParseObjCSelectorPiece(Loc); | |
3249 if (!selIdent && Tok.isNot(tok::colon)) | |
3250 break; | |
3251 // We have a selector or a colon, continue parsing. | |
3252 } | |
3253 // Parse the, optional, argument list, comma separated. | |
3254 while (Tok.is(tok::comma)) { | |
3255 SourceLocation commaLoc = ConsumeToken(); // Eat the ','. | |
3256 /// Parse the expression after ',' | |
3257 ExprResult Res(ParseAssignmentExpression()); | |
3258 if (Tok.is(tok::colon)) | |
3259 Res = Actions.CorrectDelayedTyposInExpr(Res); | |
3260 if (Res.isInvalid()) { | |
3261 if (Tok.is(tok::colon)) { | |
3262 Diag(commaLoc, diag::note_extra_comma_message_arg) << | |
3263 FixItHint::CreateRemoval(commaLoc); | |
3264 } | |
3265 // We must manually skip to a ']', otherwise the expression skipper will | |
3266 // stop at the ']' when it skips to the ';'. We want it to skip beyond | |
3267 // the enclosing expression. | |
3268 SkipUntil(tok::r_square, StopAtSemi); | |
3269 return Res; | |
3270 } | |
3271 | |
3272 // We have a valid expression. | |
3273 KeyExprs.push_back(Res.get()); | |
3274 } | |
3275 } else if (!selIdent) { | |
3276 Diag(Tok, diag::err_expected) << tok::identifier; // missing selector name. | |
3277 | |
3278 // We must manually skip to a ']', otherwise the expression skipper will | |
3279 // stop at the ']' when it skips to the ';'. We want it to skip beyond | |
3280 // the enclosing expression. | |
3281 SkipUntil(tok::r_square, StopAtSemi); | |
3282 return ExprError(); | |
3283 } | |
3284 | |
3285 if (Tok.isNot(tok::r_square)) { | |
3286 Diag(Tok, diag::err_expected) | |
3287 << (Tok.is(tok::identifier) ? tok::colon : tok::r_square); | |
3288 // We must manually skip to a ']', otherwise the expression skipper will | |
3289 // stop at the ']' when it skips to the ';'. We want it to skip beyond | |
3290 // the enclosing expression. | |
3291 SkipUntil(tok::r_square, StopAtSemi); | |
3292 return ExprError(); | |
3293 } | |
3294 | |
3295 SourceLocation RBracLoc = ConsumeBracket(); // consume ']' | |
3296 | |
3297 unsigned nKeys = KeyIdents.size(); | |
3298 if (nKeys == 0) { | |
3299 KeyIdents.push_back(selIdent); | |
3300 KeyLocs.push_back(Loc); | |
3301 } | |
3302 Selector Sel = PP.getSelectorTable().getSelector(nKeys, &KeyIdents[0]); | |
3303 | |
3304 if (SuperLoc.isValid()) | |
3305 return Actions.ActOnSuperMessage(getCurScope(), SuperLoc, Sel, | |
3306 LBracLoc, KeyLocs, RBracLoc, KeyExprs); | |
3307 else if (ReceiverType) | |
3308 return Actions.ActOnClassMessage(getCurScope(), ReceiverType, Sel, | |
3309 LBracLoc, KeyLocs, RBracLoc, KeyExprs); | |
3310 return Actions.ActOnInstanceMessage(getCurScope(), ReceiverExpr, Sel, | |
3311 LBracLoc, KeyLocs, RBracLoc, KeyExprs); | |
3312 } | |
3313 | |
3314 ExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) { | |
3315 ExprResult Res(ParseStringLiteralExpression()); | |
3316 if (Res.isInvalid()) return Res; | |
3317 | |
3318 // @"foo" @"bar" is a valid concatenated string. Eat any subsequent string | |
3319 // expressions. At this point, we know that the only valid thing that starts | |
3320 // with '@' is an @"". | |
3321 SmallVector<SourceLocation, 4> AtLocs; | |
3322 ExprVector AtStrings; | |
3323 AtLocs.push_back(AtLoc); | |
3324 AtStrings.push_back(Res.get()); | |
3325 | |
3326 while (Tok.is(tok::at)) { | |
3327 AtLocs.push_back(ConsumeToken()); // eat the @. | |
3328 | |
3329 // Invalid unless there is a string literal. | |
3330 if (!isTokenStringLiteral()) | |
3331 return ExprError(Diag(Tok, diag::err_objc_concat_string)); | |
3332 | |
3333 ExprResult Lit(ParseStringLiteralExpression()); | |
3334 if (Lit.isInvalid()) | |
3335 return Lit; | |
3336 | |
3337 AtStrings.push_back(Lit.get()); | |
3338 } | |
3339 | |
3340 return Actions.ParseObjCStringLiteral(AtLocs.data(), AtStrings); | |
3341 } | |
3342 | |
3343 /// ParseObjCBooleanLiteral - | |
3344 /// objc-scalar-literal : '@' boolean-keyword | |
3345 /// ; | |
3346 /// boolean-keyword: 'true' | 'false' | '__objc_yes' | '__objc_no' | |
3347 /// ; | |
3348 ExprResult Parser::ParseObjCBooleanLiteral(SourceLocation AtLoc, | |
3349 bool ArgValue) { | |
3350 SourceLocation EndLoc = ConsumeToken(); // consume the keyword. | |
3351 return Actions.ActOnObjCBoolLiteral(AtLoc, EndLoc, ArgValue); | |
3352 } | |
3353 | |
3354 /// ParseObjCCharacterLiteral - | |
3355 /// objc-scalar-literal : '@' character-literal | |
3356 /// ; | |
3357 ExprResult Parser::ParseObjCCharacterLiteral(SourceLocation AtLoc) { | |
3358 ExprResult Lit(Actions.ActOnCharacterConstant(Tok)); | |
3359 if (Lit.isInvalid()) { | |
3360 return Lit; | |
3361 } | |
3362 ConsumeToken(); // Consume the literal token. | |
3363 return Actions.BuildObjCNumericLiteral(AtLoc, Lit.get()); | |
3364 } | |
3365 | |
3366 /// ParseObjCNumericLiteral - | |
3367 /// objc-scalar-literal : '@' scalar-literal | |
3368 /// ; | |
3369 /// scalar-literal : | numeric-constant /* any numeric constant. */ | |
3370 /// ; | |
3371 ExprResult Parser::ParseObjCNumericLiteral(SourceLocation AtLoc) { | |
3372 ExprResult Lit(Actions.ActOnNumericConstant(Tok)); | |
3373 if (Lit.isInvalid()) { | |
3374 return Lit; | |
3375 } | |
3376 ConsumeToken(); // Consume the literal token. | |
3377 return Actions.BuildObjCNumericLiteral(AtLoc, Lit.get()); | |
3378 } | |
3379 | |
3380 /// ParseObjCBoxedExpr - | |
3381 /// objc-box-expression: | |
3382 /// @( assignment-expression ) | |
3383 ExprResult | |
3384 Parser::ParseObjCBoxedExpr(SourceLocation AtLoc) { | |
3385 if (Tok.isNot(tok::l_paren)) | |
3386 return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@"); | |
3387 | |
3388 BalancedDelimiterTracker T(*this, tok::l_paren); | |
3389 T.consumeOpen(); | |
3390 ExprResult ValueExpr(ParseAssignmentExpression()); | |
3391 if (T.consumeClose()) | |
3392 return ExprError(); | |
3393 | |
3394 if (ValueExpr.isInvalid()) | |
3395 return ExprError(); | |
3396 | |
3397 // Wrap the sub-expression in a parenthesized expression, to distinguish | |
3398 // a boxed expression from a literal. | |
3399 SourceLocation LPLoc = T.getOpenLocation(), RPLoc = T.getCloseLocation(); | |
3400 ValueExpr = Actions.ActOnParenExpr(LPLoc, RPLoc, ValueExpr.get()); | |
3401 return Actions.BuildObjCBoxedExpr(SourceRange(AtLoc, RPLoc), | |
3402 ValueExpr.get()); | |
3403 } | |
3404 | |
3405 ExprResult Parser::ParseObjCArrayLiteral(SourceLocation AtLoc) { | |
3406 ExprVector ElementExprs; // array elements. | |
3407 ConsumeBracket(); // consume the l_square. | |
3408 | |
3409 bool HasInvalidEltExpr = false; | |
3410 while (Tok.isNot(tok::r_square)) { | |
3411 // Parse list of array element expressions (all must be id types). | |
3412 ExprResult Res(ParseAssignmentExpression()); | |
3413 if (Res.isInvalid()) { | |
3414 // We must manually skip to a ']', otherwise the expression skipper will | |
3415 // stop at the ']' when it skips to the ';'. We want it to skip beyond | |
3416 // the enclosing expression. | |
3417 SkipUntil(tok::r_square, StopAtSemi); | |
3418 return Res; | |
3419 } | |
3420 | |
3421 Res = Actions.CorrectDelayedTyposInExpr(Res.get()); | |
3422 if (Res.isInvalid()) | |
3423 HasInvalidEltExpr = true; | |
3424 | |
3425 // Parse the ellipsis that indicates a pack expansion. | |
3426 if (Tok.is(tok::ellipsis)) | |
3427 Res = Actions.ActOnPackExpansion(Res.get(), ConsumeToken()); | |
3428 if (Res.isInvalid()) | |
3429 HasInvalidEltExpr = true; | |
3430 | |
3431 ElementExprs.push_back(Res.get()); | |
3432 | |
3433 if (Tok.is(tok::comma)) | |
3434 ConsumeToken(); // Eat the ','. | |
3435 else if (Tok.isNot(tok::r_square)) | |
3436 return ExprError(Diag(Tok, diag::err_expected_either) << tok::r_square | |
3437 << tok::comma); | |
3438 } | |
3439 SourceLocation EndLoc = ConsumeBracket(); // location of ']' | |
3440 | |
3441 if (HasInvalidEltExpr) | |
3442 return ExprError(); | |
3443 | |
3444 MultiExprArg Args(ElementExprs); | |
3445 return Actions.BuildObjCArrayLiteral(SourceRange(AtLoc, EndLoc), Args); | |
3446 } | |
3447 | |
3448 ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) { | |
3449 SmallVector<ObjCDictionaryElement, 4> Elements; // dictionary elements. | |
3450 ConsumeBrace(); // consume the l_square. | |
3451 bool HasInvalidEltExpr = false; | |
3452 while (Tok.isNot(tok::r_brace)) { | |
3453 // Parse the comma separated key : value expressions. | |
3454 ExprResult KeyExpr; | |
3455 { | |
3456 ColonProtectionRAIIObject X(*this); | |
3457 KeyExpr = ParseAssignmentExpression(); | |
3458 if (KeyExpr.isInvalid()) { | |
3459 // We must manually skip to a '}', otherwise the expression skipper will | |
3460 // stop at the '}' when it skips to the ';'. We want it to skip beyond | |
3461 // the enclosing expression. | |
3462 SkipUntil(tok::r_brace, StopAtSemi); | |
3463 return KeyExpr; | |
3464 } | |
3465 } | |
3466 | |
3467 if (ExpectAndConsume(tok::colon)) { | |
3468 SkipUntil(tok::r_brace, StopAtSemi); | |
3469 return ExprError(); | |
3470 } | |
3471 | |
3472 ExprResult ValueExpr(ParseAssignmentExpression()); | |
3473 if (ValueExpr.isInvalid()) { | |
3474 // We must manually skip to a '}', otherwise the expression skipper will | |
3475 // stop at the '}' when it skips to the ';'. We want it to skip beyond | |
3476 // the enclosing expression. | |
3477 SkipUntil(tok::r_brace, StopAtSemi); | |
3478 return ValueExpr; | |
3479 } | |
3480 | |
3481 // Check the key and value for possible typos | |
3482 KeyExpr = Actions.CorrectDelayedTyposInExpr(KeyExpr.get()); | |
3483 ValueExpr = Actions.CorrectDelayedTyposInExpr(ValueExpr.get()); | |
3484 if (KeyExpr.isInvalid() || ValueExpr.isInvalid()) | |
3485 HasInvalidEltExpr = true; | |
3486 | |
3487 // Parse the ellipsis that designates this as a pack expansion. Do not | |
3488 // ActOnPackExpansion here, leave it to template instantiation time where | |
3489 // we can get better diagnostics. | |
3490 SourceLocation EllipsisLoc; | |
3491 if (getLangOpts().CPlusPlus) | |
3492 TryConsumeToken(tok::ellipsis, EllipsisLoc); | |
3493 | |
3494 // We have a valid expression. Collect it in a vector so we can | |
3495 // build the argument list. | |
3496 ObjCDictionaryElement Element = { | |
3497 KeyExpr.get(), ValueExpr.get(), EllipsisLoc, None | |
3498 }; | |
3499 Elements.push_back(Element); | |
3500 | |
3501 if (!TryConsumeToken(tok::comma) && Tok.isNot(tok::r_brace)) | |
3502 return ExprError(Diag(Tok, diag::err_expected_either) << tok::r_brace | |
3503 << tok::comma); | |
3504 } | |
3505 SourceLocation EndLoc = ConsumeBrace(); | |
3506 | |
3507 if (HasInvalidEltExpr) | |
3508 return ExprError(); | |
3509 | |
3510 // Create the ObjCDictionaryLiteral. | |
3511 return Actions.BuildObjCDictionaryLiteral(SourceRange(AtLoc, EndLoc), | |
3512 Elements); | |
3513 } | |
3514 | |
3515 /// objc-encode-expression: | |
3516 /// \@encode ( type-name ) | |
3517 ExprResult | |
3518 Parser::ParseObjCEncodeExpression(SourceLocation AtLoc) { | |
3519 assert(Tok.isObjCAtKeyword(tok::objc_encode) && "Not an @encode expression!"); | |
3520 | |
3521 SourceLocation EncLoc = ConsumeToken(); | |
3522 | |
3523 if (Tok.isNot(tok::l_paren)) | |
3524 return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@encode"); | |
3525 | |
3526 BalancedDelimiterTracker T(*this, tok::l_paren); | |
3527 T.consumeOpen(); | |
3528 | |
3529 TypeResult Ty = ParseTypeName(); | |
3530 | |
3531 T.consumeClose(); | |
3532 | |
3533 if (Ty.isInvalid()) | |
3534 return ExprError(); | |
3535 | |
3536 return Actions.ParseObjCEncodeExpression(AtLoc, EncLoc, T.getOpenLocation(), | |
3537 Ty.get(), T.getCloseLocation()); | |
3538 } | |
3539 | |
3540 /// objc-protocol-expression | |
3541 /// \@protocol ( protocol-name ) | |
3542 ExprResult | |
3543 Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) { | |
3544 SourceLocation ProtoLoc = ConsumeToken(); | |
3545 | |
3546 if (Tok.isNot(tok::l_paren)) | |
3547 return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@protocol"); | |
3548 | |
3549 BalancedDelimiterTracker T(*this, tok::l_paren); | |
3550 T.consumeOpen(); | |
3551 | |
3552 if (expectIdentifier()) | |
3553 return ExprError(); | |
3554 | |
3555 IdentifierInfo *protocolId = Tok.getIdentifierInfo(); | |
3556 SourceLocation ProtoIdLoc = ConsumeToken(); | |
3557 | |
3558 T.consumeClose(); | |
3559 | |
3560 return Actions.ParseObjCProtocolExpression(protocolId, AtLoc, ProtoLoc, | |
3561 T.getOpenLocation(), ProtoIdLoc, | |
3562 T.getCloseLocation()); | |
3563 } | |
3564 | |
3565 /// objc-selector-expression | |
3566 /// @selector '(' '('[opt] objc-keyword-selector ')'[opt] ')' | |
3567 ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) { | |
3568 SourceLocation SelectorLoc = ConsumeToken(); | |
3569 | |
3570 if (Tok.isNot(tok::l_paren)) | |
3571 return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@selector"); | |
3572 | |
3573 SmallVector<IdentifierInfo *, 12> KeyIdents; | |
3574 SourceLocation sLoc; | |
3575 | |
3576 BalancedDelimiterTracker T(*this, tok::l_paren); | |
3577 T.consumeOpen(); | |
3578 bool HasOptionalParen = Tok.is(tok::l_paren); | |
3579 if (HasOptionalParen) | |
3580 ConsumeParen(); | |
3581 | |
3582 if (Tok.is(tok::code_completion)) { | |
3583 Actions.CodeCompleteObjCSelector(getCurScope(), KeyIdents); | |
3584 cutOffParsing(); | |
3585 return ExprError(); | |
3586 } | |
3587 | |
3588 IdentifierInfo *SelIdent = ParseObjCSelectorPiece(sLoc); | |
3589 if (!SelIdent && // missing selector name. | |
3590 Tok.isNot(tok::colon) && Tok.isNot(tok::coloncolon)) | |
3591 return ExprError(Diag(Tok, diag::err_expected) << tok::identifier); | |
3592 | |
3593 KeyIdents.push_back(SelIdent); | |
3594 | |
3595 unsigned nColons = 0; | |
3596 if (Tok.isNot(tok::r_paren)) { | |
3597 while (1) { | |
3598 if (TryConsumeToken(tok::coloncolon)) { // Handle :: in C++. | |
3599 ++nColons; | |
3600 KeyIdents.push_back(nullptr); | |
3601 } else if (ExpectAndConsume(tok::colon)) // Otherwise expect ':'. | |
3602 return ExprError(); | |
3603 ++nColons; | |
3604 | |
3605 if (Tok.is(tok::r_paren)) | |
3606 break; | |
3607 | |
3608 if (Tok.is(tok::code_completion)) { | |
3609 Actions.CodeCompleteObjCSelector(getCurScope(), KeyIdents); | |
3610 cutOffParsing(); | |
3611 return ExprError(); | |
3612 } | |
3613 | |
3614 // Check for another keyword selector. | |
3615 SourceLocation Loc; | |
3616 SelIdent = ParseObjCSelectorPiece(Loc); | |
3617 KeyIdents.push_back(SelIdent); | |
3618 if (!SelIdent && Tok.isNot(tok::colon) && Tok.isNot(tok::coloncolon)) | |
3619 break; | |
3620 } | |
3621 } | |
3622 if (HasOptionalParen && Tok.is(tok::r_paren)) | |
3623 ConsumeParen(); // ')' | |
3624 T.consumeClose(); | |
3625 Selector Sel = PP.getSelectorTable().getSelector(nColons, &KeyIdents[0]); | |
3626 return Actions.ParseObjCSelectorExpression(Sel, AtLoc, SelectorLoc, | |
3627 T.getOpenLocation(), | |
3628 T.getCloseLocation(), | |
3629 !HasOptionalParen); | |
3630 } | |
3631 | |
3632 void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) { | |
3633 // MCDecl might be null due to error in method or c-function prototype, etc. | |
3634 Decl *MCDecl = LM.D; | |
3635 bool skip = MCDecl && | |
3636 ((parseMethod && !Actions.isObjCMethodDecl(MCDecl)) || | |
3637 (!parseMethod && Actions.isObjCMethodDecl(MCDecl))); | |
3638 if (skip) | |
3639 return; | |
3640 | |
3641 // Save the current token position. | |
3642 SourceLocation OrigLoc = Tok.getLocation(); | |
3643 | |
3644 assert(!LM.Toks.empty() && "ParseLexedObjCMethodDef - Empty body!"); | |
3645 // Store an artificial EOF token to ensure that we don't run off the end of | |
3646 // the method's body when we come to parse it. | |
3647 Token Eof; | |
3648 Eof.startToken(); | |
3649 Eof.setKind(tok::eof); | |
3650 Eof.setEofData(MCDecl); | |
3651 Eof.setLocation(OrigLoc); | |
3652 LM.Toks.push_back(Eof); | |
3653 // Append the current token at the end of the new token stream so that it | |
3654 // doesn't get lost. | |
3655 LM.Toks.push_back(Tok); | |
3656 PP.EnterTokenStream(LM.Toks, true, /*IsReinject*/true); | |
3657 | |
3658 // Consume the previously pushed token. | |
3659 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); | |
3660 | |
3661 assert(Tok.isOneOf(tok::l_brace, tok::kw_try, tok::colon) && | |
3662 "Inline objective-c method not starting with '{' or 'try' or ':'"); | |
3663 // Enter a scope for the method or c-function body. | |
3664 ParseScope BodyScope(this, (parseMethod ? Scope::ObjCMethodScope : 0) | | |
3665 Scope::FnScope | Scope::DeclScope | | |
3666 Scope::CompoundStmtScope); | |
3667 | |
3668 // Tell the actions module that we have entered a method or c-function definition | |
3669 // with the specified Declarator for the method/function. | |
3670 if (parseMethod) | |
3671 Actions.ActOnStartOfObjCMethodDef(getCurScope(), MCDecl); | |
3672 else | |
3673 Actions.ActOnStartOfFunctionDef(getCurScope(), MCDecl); | |
3674 if (Tok.is(tok::kw_try)) | |
3675 ParseFunctionTryBlock(MCDecl, BodyScope); | |
3676 else { | |
3677 if (Tok.is(tok::colon)) | |
3678 ParseConstructorInitializer(MCDecl); | |
3679 else | |
3680 Actions.ActOnDefaultCtorInitializers(MCDecl); | |
3681 ParseFunctionStatementBody(MCDecl, BodyScope); | |
3682 } | |
3683 | |
3684 if (Tok.getLocation() != OrigLoc) { | |
3685 // Due to parsing error, we either went over the cached tokens or | |
3686 // there are still cached tokens left. If it's the latter case skip the | |
3687 // leftover tokens. | |
3688 // Since this is an uncommon situation that should be avoided, use the | |
3689 // expensive isBeforeInTranslationUnit call. | |
3690 if (PP.getSourceManager().isBeforeInTranslationUnit(Tok.getLocation(), | |
3691 OrigLoc)) | |
3692 while (Tok.getLocation() != OrigLoc && Tok.isNot(tok::eof)) | |
3693 ConsumeAnyToken(); | |
3694 } | |
3695 // Clean up the remaining EOF token. | |
3696 ConsumeAnyToken(); | |
3697 } |