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

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of clang/lib/Parse/ParseObjc.cpp