xref: /freebsd-src/contrib/llvm-project/clang/lib/Parse/ParseObjc.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===--- ParseObjC.cpp - Objective C Parsing ------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric //  This file implements the Objective-C portions of the Parser interface.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "clang/AST/ASTContext.h"
14bdd1243dSDimitry Andric #include "clang/AST/ODRDiagsEmitter.h"
150b57cec5SDimitry Andric #include "clang/AST/PrettyDeclStackTrace.h"
160b57cec5SDimitry Andric #include "clang/Basic/CharInfo.h"
175ffd83dbSDimitry Andric #include "clang/Basic/TargetInfo.h"
180b57cec5SDimitry Andric #include "clang/Parse/ParseDiagnostic.h"
195ffd83dbSDimitry Andric #include "clang/Parse/Parser.h"
200b57cec5SDimitry Andric #include "clang/Parse/RAIIObjectsForParser.h"
210b57cec5SDimitry Andric #include "clang/Sema/DeclSpec.h"
220b57cec5SDimitry Andric #include "clang/Sema/Scope.h"
23*0fca6ea1SDimitry Andric #include "clang/Sema/SemaCodeCompletion.h"
24*0fca6ea1SDimitry Andric #include "clang/Sema/SemaObjC.h"
250b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
260b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h"
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric using namespace clang;
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric /// Skips attributes after an Objective-C @ directive. Emits a diagnostic.
310b57cec5SDimitry Andric void Parser::MaybeSkipAttributes(tok::ObjCKeywordKind Kind) {
320b57cec5SDimitry Andric   ParsedAttributes attrs(AttrFactory);
330b57cec5SDimitry Andric   if (Tok.is(tok::kw___attribute)) {
340b57cec5SDimitry Andric     if (Kind == tok::objc_interface || Kind == tok::objc_protocol)
350b57cec5SDimitry Andric       Diag(Tok, diag::err_objc_postfix_attribute_hint)
360b57cec5SDimitry Andric           << (Kind == tok::objc_protocol);
370b57cec5SDimitry Andric     else
380b57cec5SDimitry Andric       Diag(Tok, diag::err_objc_postfix_attribute);
390b57cec5SDimitry Andric     ParseGNUAttributes(attrs);
400b57cec5SDimitry Andric   }
410b57cec5SDimitry Andric }
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric /// ParseObjCAtDirectives - Handle parts of the external-declaration production:
440b57cec5SDimitry Andric ///       external-declaration: [C99 6.9]
450b57cec5SDimitry Andric /// [OBJC]  objc-class-definition
460b57cec5SDimitry Andric /// [OBJC]  objc-class-declaration
470b57cec5SDimitry Andric /// [OBJC]  objc-alias-declaration
480b57cec5SDimitry Andric /// [OBJC]  objc-protocol-definition
490b57cec5SDimitry Andric /// [OBJC]  objc-method-definition
500b57cec5SDimitry Andric /// [OBJC]  '@' 'end'
51bdd1243dSDimitry Andric Parser::DeclGroupPtrTy
52bdd1243dSDimitry Andric Parser::ParseObjCAtDirectives(ParsedAttributes &DeclAttrs,
53bdd1243dSDimitry Andric                               ParsedAttributes &DeclSpecAttrs) {
54bdd1243dSDimitry Andric   DeclAttrs.takeAllFrom(DeclSpecAttrs);
55bdd1243dSDimitry Andric 
560b57cec5SDimitry Andric   SourceLocation AtLoc = ConsumeToken(); // the "@"
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric   if (Tok.is(tok::code_completion)) {
590b57cec5SDimitry Andric     cutOffParsing();
60*0fca6ea1SDimitry Andric     Actions.CodeCompletion().CodeCompleteObjCAtDirective(getCurScope());
610b57cec5SDimitry Andric     return nullptr;
620b57cec5SDimitry Andric   }
630b57cec5SDimitry Andric 
64bdd1243dSDimitry Andric   switch (Tok.getObjCKeywordID()) {
65bdd1243dSDimitry Andric   case tok::objc_interface:
66bdd1243dSDimitry Andric   case tok::objc_protocol:
67bdd1243dSDimitry Andric   case tok::objc_implementation:
68bdd1243dSDimitry Andric     break;
69bdd1243dSDimitry Andric   default:
705f757f3fSDimitry Andric     for (const auto &Attr : DeclAttrs) {
71bdd1243dSDimitry Andric       if (Attr.isGNUAttribute())
72bdd1243dSDimitry Andric         Diag(Tok.getLocation(), diag::err_objc_unexpected_attr);
735f757f3fSDimitry Andric     }
74bdd1243dSDimitry Andric   }
75bdd1243dSDimitry Andric 
760b57cec5SDimitry Andric   Decl *SingleDecl = nullptr;
770b57cec5SDimitry Andric   switch (Tok.getObjCKeywordID()) {
780b57cec5SDimitry Andric   case tok::objc_class:
790b57cec5SDimitry Andric     return ParseObjCAtClassDeclaration(AtLoc);
800b57cec5SDimitry Andric   case tok::objc_interface:
81bdd1243dSDimitry Andric     SingleDecl = ParseObjCAtInterfaceDeclaration(AtLoc, DeclAttrs);
820b57cec5SDimitry Andric     break;
830b57cec5SDimitry Andric   case tok::objc_protocol:
84bdd1243dSDimitry Andric     return ParseObjCAtProtocolDeclaration(AtLoc, DeclAttrs);
850b57cec5SDimitry Andric   case tok::objc_implementation:
86bdd1243dSDimitry Andric     return ParseObjCAtImplementationDeclaration(AtLoc, DeclAttrs);
870b57cec5SDimitry Andric   case tok::objc_end:
880b57cec5SDimitry Andric     return ParseObjCAtEndDeclaration(AtLoc);
890b57cec5SDimitry Andric   case tok::objc_compatibility_alias:
900b57cec5SDimitry Andric     SingleDecl = ParseObjCAtAliasDeclaration(AtLoc);
910b57cec5SDimitry Andric     break;
920b57cec5SDimitry Andric   case tok::objc_synthesize:
930b57cec5SDimitry Andric     SingleDecl = ParseObjCPropertySynthesize(AtLoc);
940b57cec5SDimitry Andric     break;
950b57cec5SDimitry Andric   case tok::objc_dynamic:
960b57cec5SDimitry Andric     SingleDecl = ParseObjCPropertyDynamic(AtLoc);
970b57cec5SDimitry Andric     break;
980b57cec5SDimitry Andric   case tok::objc_import:
990b57cec5SDimitry Andric     if (getLangOpts().Modules || getLangOpts().DebuggerSupport) {
10081ad6265SDimitry Andric       Sema::ModuleImportState IS = Sema::ModuleImportState::NotACXX20Module;
10181ad6265SDimitry Andric       SingleDecl = ParseModuleImport(AtLoc, IS);
1020b57cec5SDimitry Andric       break;
1030b57cec5SDimitry Andric     }
1040b57cec5SDimitry Andric     Diag(AtLoc, diag::err_atimport);
1050b57cec5SDimitry Andric     SkipUntil(tok::semi);
1060b57cec5SDimitry Andric     return Actions.ConvertDeclToDeclGroup(nullptr);
1070b57cec5SDimitry Andric   default:
1080b57cec5SDimitry Andric     Diag(AtLoc, diag::err_unexpected_at);
1090b57cec5SDimitry Andric     SkipUntil(tok::semi);
1100b57cec5SDimitry Andric     SingleDecl = nullptr;
1110b57cec5SDimitry Andric     break;
1120b57cec5SDimitry Andric   }
1130b57cec5SDimitry Andric   return Actions.ConvertDeclToDeclGroup(SingleDecl);
1140b57cec5SDimitry Andric }
1150b57cec5SDimitry Andric 
1160b57cec5SDimitry Andric /// Class to handle popping type parameters when leaving the scope.
1170b57cec5SDimitry Andric class Parser::ObjCTypeParamListScope {
1180b57cec5SDimitry Andric   Sema &Actions;
1190b57cec5SDimitry Andric   Scope *S;
1200b57cec5SDimitry Andric   ObjCTypeParamList *Params;
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric public:
1230b57cec5SDimitry Andric   ObjCTypeParamListScope(Sema &Actions, Scope *S)
1240b57cec5SDimitry Andric       : Actions(Actions), S(S), Params(nullptr) {}
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric   ~ObjCTypeParamListScope() {
1270b57cec5SDimitry Andric     leave();
1280b57cec5SDimitry Andric   }
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric   void enter(ObjCTypeParamList *P) {
1310b57cec5SDimitry Andric     assert(!Params);
1320b57cec5SDimitry Andric     Params = P;
1330b57cec5SDimitry Andric   }
1340b57cec5SDimitry Andric 
1350b57cec5SDimitry Andric   void leave() {
1360b57cec5SDimitry Andric     if (Params)
137*0fca6ea1SDimitry Andric       Actions.ObjC().popObjCTypeParamList(S, Params);
1380b57cec5SDimitry Andric     Params = nullptr;
1390b57cec5SDimitry Andric   }
1400b57cec5SDimitry Andric };
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric ///
1430b57cec5SDimitry Andric /// objc-class-declaration:
1440b57cec5SDimitry Andric ///    '@' 'class' objc-class-forward-decl (',' objc-class-forward-decl)* ';'
1450b57cec5SDimitry Andric ///
1460b57cec5SDimitry Andric /// objc-class-forward-decl:
1470b57cec5SDimitry Andric ///   identifier objc-type-parameter-list[opt]
1480b57cec5SDimitry Andric ///
1490b57cec5SDimitry Andric Parser::DeclGroupPtrTy
1500b57cec5SDimitry Andric Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
1510b57cec5SDimitry Andric   ConsumeToken(); // the identifier "class"
1520b57cec5SDimitry Andric   SmallVector<IdentifierInfo *, 8> ClassNames;
1530b57cec5SDimitry Andric   SmallVector<SourceLocation, 8> ClassLocs;
1540b57cec5SDimitry Andric   SmallVector<ObjCTypeParamList *, 8> ClassTypeParams;
1550b57cec5SDimitry Andric 
15604eeddc0SDimitry Andric   while (true) {
1570b57cec5SDimitry Andric     MaybeSkipAttributes(tok::objc_class);
15806c3fb27SDimitry Andric     if (Tok.is(tok::code_completion)) {
15906c3fb27SDimitry Andric       cutOffParsing();
160*0fca6ea1SDimitry Andric       Actions.CodeCompletion().CodeCompleteObjCClassForwardDecl(getCurScope());
16106c3fb27SDimitry Andric       return Actions.ConvertDeclToDeclGroup(nullptr);
16206c3fb27SDimitry Andric     }
1630b57cec5SDimitry Andric     if (expectIdentifier()) {
1640b57cec5SDimitry Andric       SkipUntil(tok::semi);
1650b57cec5SDimitry Andric       return Actions.ConvertDeclToDeclGroup(nullptr);
1660b57cec5SDimitry Andric     }
1670b57cec5SDimitry Andric     ClassNames.push_back(Tok.getIdentifierInfo());
1680b57cec5SDimitry Andric     ClassLocs.push_back(Tok.getLocation());
1690b57cec5SDimitry Andric     ConsumeToken();
1700b57cec5SDimitry Andric 
1710b57cec5SDimitry Andric     // Parse the optional objc-type-parameter-list.
1720b57cec5SDimitry Andric     ObjCTypeParamList *TypeParams = nullptr;
1730b57cec5SDimitry Andric     if (Tok.is(tok::less))
1740b57cec5SDimitry Andric       TypeParams = parseObjCTypeParamList();
1750b57cec5SDimitry Andric     ClassTypeParams.push_back(TypeParams);
1760b57cec5SDimitry Andric     if (!TryConsumeToken(tok::comma))
1770b57cec5SDimitry Andric       break;
1780b57cec5SDimitry Andric   }
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric   // Consume the ';'.
1810b57cec5SDimitry Andric   if (ExpectAndConsume(tok::semi, diag::err_expected_after, "@class"))
1820b57cec5SDimitry Andric     return Actions.ConvertDeclToDeclGroup(nullptr);
1830b57cec5SDimitry Andric 
184*0fca6ea1SDimitry Andric   return Actions.ObjC().ActOnForwardClassDeclaration(
185*0fca6ea1SDimitry Andric       atLoc, ClassNames.data(), ClassLocs.data(), ClassTypeParams,
1860b57cec5SDimitry Andric       ClassNames.size());
1870b57cec5SDimitry Andric }
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric void Parser::CheckNestedObjCContexts(SourceLocation AtLoc)
1900b57cec5SDimitry Andric {
191*0fca6ea1SDimitry Andric   SemaObjC::ObjCContainerKind ock = Actions.ObjC().getObjCContainerKind();
192*0fca6ea1SDimitry Andric   if (ock == SemaObjC::OCK_None)
1930b57cec5SDimitry Andric     return;
1940b57cec5SDimitry Andric 
195*0fca6ea1SDimitry Andric   Decl *Decl = Actions.ObjC().getObjCDeclContext();
1960b57cec5SDimitry Andric   if (CurParsedObjCImpl) {
1970b57cec5SDimitry Andric     CurParsedObjCImpl->finish(AtLoc);
1980b57cec5SDimitry Andric   } else {
199*0fca6ea1SDimitry Andric     Actions.ObjC().ActOnAtEnd(getCurScope(), AtLoc);
2000b57cec5SDimitry Andric   }
2010b57cec5SDimitry Andric   Diag(AtLoc, diag::err_objc_missing_end)
2020b57cec5SDimitry Andric       << FixItHint::CreateInsertion(AtLoc, "@end\n");
2030b57cec5SDimitry Andric   if (Decl)
2040b57cec5SDimitry Andric     Diag(Decl->getBeginLoc(), diag::note_objc_container_start) << (int)ock;
2050b57cec5SDimitry Andric }
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric ///
2080b57cec5SDimitry Andric ///   objc-interface:
2090b57cec5SDimitry Andric ///     objc-class-interface-attributes[opt] objc-class-interface
2100b57cec5SDimitry Andric ///     objc-category-interface
2110b57cec5SDimitry Andric ///
2120b57cec5SDimitry Andric ///   objc-class-interface:
2130b57cec5SDimitry Andric ///     '@' 'interface' identifier objc-type-parameter-list[opt]
2140b57cec5SDimitry Andric ///       objc-superclass[opt] objc-protocol-refs[opt]
2150b57cec5SDimitry Andric ///       objc-class-instance-variables[opt]
2160b57cec5SDimitry Andric ///       objc-interface-decl-list
2170b57cec5SDimitry Andric ///     @end
2180b57cec5SDimitry Andric ///
2190b57cec5SDimitry Andric ///   objc-category-interface:
2200b57cec5SDimitry Andric ///     '@' 'interface' identifier objc-type-parameter-list[opt]
2210b57cec5SDimitry Andric ///       '(' identifier[opt] ')' objc-protocol-refs[opt]
2220b57cec5SDimitry Andric ///       objc-interface-decl-list
2230b57cec5SDimitry Andric ///     @end
2240b57cec5SDimitry Andric ///
2250b57cec5SDimitry Andric ///   objc-superclass:
2260b57cec5SDimitry Andric ///     ':' identifier objc-type-arguments[opt]
2270b57cec5SDimitry Andric ///
2280b57cec5SDimitry Andric ///   objc-class-interface-attributes:
2290b57cec5SDimitry Andric ///     __attribute__((visibility("default")))
2300b57cec5SDimitry Andric ///     __attribute__((visibility("hidden")))
2310b57cec5SDimitry Andric ///     __attribute__((deprecated))
2320b57cec5SDimitry Andric ///     __attribute__((unavailable))
2330b57cec5SDimitry Andric ///     __attribute__((objc_exception)) - used by NSException on 64-bit
2340b57cec5SDimitry Andric ///     __attribute__((objc_root_class))
2350b57cec5SDimitry Andric ///
2360b57cec5SDimitry Andric Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
2370b57cec5SDimitry Andric                                               ParsedAttributes &attrs) {
2380b57cec5SDimitry Andric   assert(Tok.isObjCAtKeyword(tok::objc_interface) &&
2390b57cec5SDimitry Andric          "ParseObjCAtInterfaceDeclaration(): Expected @interface");
2400b57cec5SDimitry Andric   CheckNestedObjCContexts(AtLoc);
2410b57cec5SDimitry Andric   ConsumeToken(); // the "interface" identifier
2420b57cec5SDimitry Andric 
2430b57cec5SDimitry Andric   // Code completion after '@interface'.
2440b57cec5SDimitry Andric   if (Tok.is(tok::code_completion)) {
2450b57cec5SDimitry Andric     cutOffParsing();
246*0fca6ea1SDimitry Andric     Actions.CodeCompletion().CodeCompleteObjCInterfaceDecl(getCurScope());
2470b57cec5SDimitry Andric     return nullptr;
2480b57cec5SDimitry Andric   }
2490b57cec5SDimitry Andric 
2500b57cec5SDimitry Andric   MaybeSkipAttributes(tok::objc_interface);
2510b57cec5SDimitry Andric 
2520b57cec5SDimitry Andric   if (expectIdentifier())
2530b57cec5SDimitry Andric     return nullptr; // missing class or category name.
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric   // We have a class or category name - consume it.
2560b57cec5SDimitry Andric   IdentifierInfo *nameId = Tok.getIdentifierInfo();
2570b57cec5SDimitry Andric   SourceLocation nameLoc = ConsumeToken();
2580b57cec5SDimitry Andric 
2590b57cec5SDimitry Andric   // Parse the objc-type-parameter-list or objc-protocol-refs. For the latter
2600b57cec5SDimitry Andric   // case, LAngleLoc will be valid and ProtocolIdents will capture the
2610b57cec5SDimitry Andric   // protocol references (that have not yet been resolved).
2620b57cec5SDimitry Andric   SourceLocation LAngleLoc, EndProtoLoc;
2630b57cec5SDimitry Andric   SmallVector<IdentifierLocPair, 8> ProtocolIdents;
2640b57cec5SDimitry Andric   ObjCTypeParamList *typeParameterList = nullptr;
2650b57cec5SDimitry Andric   ObjCTypeParamListScope typeParamScope(Actions, getCurScope());
2660b57cec5SDimitry Andric   if (Tok.is(tok::less))
2670b57cec5SDimitry Andric     typeParameterList = parseObjCTypeParamListOrProtocolRefs(
2680b57cec5SDimitry Andric         typeParamScope, LAngleLoc, ProtocolIdents, EndProtoLoc);
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric   if (Tok.is(tok::l_paren) &&
2710b57cec5SDimitry Andric       !isKnownToBeTypeSpecifier(GetLookAheadToken(1))) { // we have a category.
2720b57cec5SDimitry Andric 
2730b57cec5SDimitry Andric     BalancedDelimiterTracker T(*this, tok::l_paren);
2740b57cec5SDimitry Andric     T.consumeOpen();
2750b57cec5SDimitry Andric 
2760b57cec5SDimitry Andric     SourceLocation categoryLoc;
2770b57cec5SDimitry Andric     IdentifierInfo *categoryId = nullptr;
2780b57cec5SDimitry Andric     if (Tok.is(tok::code_completion)) {
2790b57cec5SDimitry Andric       cutOffParsing();
280*0fca6ea1SDimitry Andric       Actions.CodeCompletion().CodeCompleteObjCInterfaceCategory(
281*0fca6ea1SDimitry Andric           getCurScope(), nameId, nameLoc);
2820b57cec5SDimitry Andric       return nullptr;
2830b57cec5SDimitry Andric     }
2840b57cec5SDimitry Andric 
2850b57cec5SDimitry Andric     // For ObjC2, the category name is optional (not an error).
2860b57cec5SDimitry Andric     if (Tok.is(tok::identifier)) {
2870b57cec5SDimitry Andric       categoryId = Tok.getIdentifierInfo();
2880b57cec5SDimitry Andric       categoryLoc = ConsumeToken();
2890b57cec5SDimitry Andric     }
2900b57cec5SDimitry Andric     else if (!getLangOpts().ObjC) {
2910b57cec5SDimitry Andric       Diag(Tok, diag::err_expected)
2920b57cec5SDimitry Andric           << tok::identifier; // missing category name.
2930b57cec5SDimitry Andric       return nullptr;
2940b57cec5SDimitry Andric     }
2950b57cec5SDimitry Andric 
2960b57cec5SDimitry Andric     T.consumeClose();
2970b57cec5SDimitry Andric     if (T.getCloseLocation().isInvalid())
2980b57cec5SDimitry Andric       return nullptr;
2990b57cec5SDimitry Andric 
3000b57cec5SDimitry Andric     // Next, we need to check for any protocol references.
3010b57cec5SDimitry Andric     assert(LAngleLoc.isInvalid() && "Cannot have already parsed protocols");
3020b57cec5SDimitry Andric     SmallVector<Decl *, 8> ProtocolRefs;
3030b57cec5SDimitry Andric     SmallVector<SourceLocation, 8> ProtocolLocs;
3040b57cec5SDimitry Andric     if (Tok.is(tok::less) &&
3050b57cec5SDimitry Andric         ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true, true,
3060b57cec5SDimitry Andric                                     LAngleLoc, EndProtoLoc,
3070b57cec5SDimitry Andric                                     /*consumeLastToken=*/true))
3080b57cec5SDimitry Andric       return nullptr;
3090b57cec5SDimitry Andric 
310*0fca6ea1SDimitry Andric     ObjCCategoryDecl *CategoryType = Actions.ObjC().ActOnStartCategoryInterface(
3110b57cec5SDimitry Andric         AtLoc, nameId, nameLoc, typeParameterList, categoryId, categoryLoc,
3120b57cec5SDimitry Andric         ProtocolRefs.data(), ProtocolRefs.size(), ProtocolLocs.data(),
3130b57cec5SDimitry Andric         EndProtoLoc, attrs);
3140b57cec5SDimitry Andric 
3150b57cec5SDimitry Andric     if (Tok.is(tok::l_brace))
3160b57cec5SDimitry Andric       ParseObjCClassInstanceVariables(CategoryType, tok::objc_private, AtLoc);
3170b57cec5SDimitry Andric 
3180b57cec5SDimitry Andric     ParseObjCInterfaceDeclList(tok::objc_not_keyword, CategoryType);
3190b57cec5SDimitry Andric 
3200b57cec5SDimitry Andric     return CategoryType;
3210b57cec5SDimitry Andric   }
3220b57cec5SDimitry Andric   // Parse a class interface.
3230b57cec5SDimitry Andric   IdentifierInfo *superClassId = nullptr;
3240b57cec5SDimitry Andric   SourceLocation superClassLoc;
3250b57cec5SDimitry Andric   SourceLocation typeArgsLAngleLoc;
3260b57cec5SDimitry Andric   SmallVector<ParsedType, 4> typeArgs;
3270b57cec5SDimitry Andric   SourceLocation typeArgsRAngleLoc;
3280b57cec5SDimitry Andric   SmallVector<Decl *, 4> protocols;
3290b57cec5SDimitry Andric   SmallVector<SourceLocation, 4> protocolLocs;
3300b57cec5SDimitry Andric   if (Tok.is(tok::colon)) { // a super class is specified.
3310b57cec5SDimitry Andric     ConsumeToken();
3320b57cec5SDimitry Andric 
3330b57cec5SDimitry Andric     // Code completion of superclass names.
3340b57cec5SDimitry Andric     if (Tok.is(tok::code_completion)) {
3350b57cec5SDimitry Andric       cutOffParsing();
336*0fca6ea1SDimitry Andric       Actions.CodeCompletion().CodeCompleteObjCSuperclass(getCurScope(), nameId,
337*0fca6ea1SDimitry Andric                                                           nameLoc);
3380b57cec5SDimitry Andric       return nullptr;
3390b57cec5SDimitry Andric     }
3400b57cec5SDimitry Andric 
3410b57cec5SDimitry Andric     if (expectIdentifier())
3420b57cec5SDimitry Andric       return nullptr; // missing super class name.
3430b57cec5SDimitry Andric     superClassId = Tok.getIdentifierInfo();
3440b57cec5SDimitry Andric     superClassLoc = ConsumeToken();
3450b57cec5SDimitry Andric 
3460b57cec5SDimitry Andric     // Type arguments for the superclass or protocol conformances.
3470b57cec5SDimitry Andric     if (Tok.is(tok::less)) {
3480b57cec5SDimitry Andric       parseObjCTypeArgsOrProtocolQualifiers(
3490b57cec5SDimitry Andric           nullptr, typeArgsLAngleLoc, typeArgs, typeArgsRAngleLoc, LAngleLoc,
3500b57cec5SDimitry Andric           protocols, protocolLocs, EndProtoLoc,
3510b57cec5SDimitry Andric           /*consumeLastToken=*/true,
3520b57cec5SDimitry Andric           /*warnOnIncompleteProtocols=*/true);
3530b57cec5SDimitry Andric       if (Tok.is(tok::eof))
3540b57cec5SDimitry Andric         return nullptr;
3550b57cec5SDimitry Andric     }
3560b57cec5SDimitry Andric   }
3570b57cec5SDimitry Andric 
3580b57cec5SDimitry Andric   // Next, we need to check for any protocol references.
3590b57cec5SDimitry Andric   if (LAngleLoc.isValid()) {
3600b57cec5SDimitry Andric     if (!ProtocolIdents.empty()) {
3610b57cec5SDimitry Andric       // We already parsed the protocols named when we thought we had a
3620b57cec5SDimitry Andric       // type parameter list. Translate them into actual protocol references.
3630b57cec5SDimitry Andric       for (const auto &pair : ProtocolIdents) {
3640b57cec5SDimitry Andric         protocolLocs.push_back(pair.second);
3650b57cec5SDimitry Andric       }
366*0fca6ea1SDimitry Andric       Actions.ObjC().FindProtocolDeclaration(/*WarnOnDeclarations=*/true,
3670b57cec5SDimitry Andric                                              /*ForObjCContainer=*/true,
3680b57cec5SDimitry Andric                                              ProtocolIdents, protocols);
3690b57cec5SDimitry Andric     }
3700b57cec5SDimitry Andric   } else if (protocols.empty() && Tok.is(tok::less) &&
3710b57cec5SDimitry Andric              ParseObjCProtocolReferences(protocols, protocolLocs, true, true,
3720b57cec5SDimitry Andric                                          LAngleLoc, EndProtoLoc,
3730b57cec5SDimitry Andric                                          /*consumeLastToken=*/true)) {
3740b57cec5SDimitry Andric     return nullptr;
3750b57cec5SDimitry Andric   }
3760b57cec5SDimitry Andric 
3770b57cec5SDimitry Andric   if (Tok.isNot(tok::less))
378*0fca6ea1SDimitry Andric     Actions.ObjC().ActOnTypedefedProtocols(protocols, protocolLocs,
3790b57cec5SDimitry Andric                                            superClassId, superClassLoc);
3800b57cec5SDimitry Andric 
381*0fca6ea1SDimitry Andric   SkipBodyInfo SkipBody;
382*0fca6ea1SDimitry Andric   ObjCInterfaceDecl *ClsType = Actions.ObjC().ActOnStartClassInterface(
3830b57cec5SDimitry Andric       getCurScope(), AtLoc, nameId, nameLoc, typeParameterList, superClassId,
3840b57cec5SDimitry Andric       superClassLoc, typeArgs,
3850b57cec5SDimitry Andric       SourceRange(typeArgsLAngleLoc, typeArgsRAngleLoc), protocols.data(),
386bdd1243dSDimitry Andric       protocols.size(), protocolLocs.data(), EndProtoLoc, attrs, &SkipBody);
3870b57cec5SDimitry Andric 
3880b57cec5SDimitry Andric   if (Tok.is(tok::l_brace))
3890b57cec5SDimitry Andric     ParseObjCClassInstanceVariables(ClsType, tok::objc_protected, AtLoc);
3900b57cec5SDimitry Andric 
3910b57cec5SDimitry Andric   ParseObjCInterfaceDeclList(tok::objc_interface, ClsType);
3920b57cec5SDimitry Andric 
393bdd1243dSDimitry Andric   if (SkipBody.CheckSameAsPrevious) {
394bdd1243dSDimitry Andric     auto *PreviousDef = cast<ObjCInterfaceDecl>(SkipBody.Previous);
395bdd1243dSDimitry Andric     if (Actions.ActOnDuplicateODRHashDefinition(ClsType, PreviousDef)) {
396bdd1243dSDimitry Andric       ClsType->mergeDuplicateDefinitionWithCommon(PreviousDef->getDefinition());
397bdd1243dSDimitry Andric     } else {
398bdd1243dSDimitry Andric       ODRDiagsEmitter DiagsEmitter(Diags, Actions.getASTContext(),
399bdd1243dSDimitry Andric                                    getPreprocessor().getLangOpts());
400bdd1243dSDimitry Andric       DiagsEmitter.diagnoseMismatch(PreviousDef, ClsType);
401bdd1243dSDimitry Andric       ClsType->setInvalidDecl();
402bdd1243dSDimitry Andric     }
403bdd1243dSDimitry Andric   }
404bdd1243dSDimitry Andric 
4050b57cec5SDimitry Andric   return ClsType;
4060b57cec5SDimitry Andric }
4070b57cec5SDimitry Andric 
4080b57cec5SDimitry Andric /// Add an attribute for a context-sensitive type nullability to the given
4090b57cec5SDimitry Andric /// declarator.
4100b57cec5SDimitry Andric static void addContextSensitiveTypeNullability(Parser &P,
4110b57cec5SDimitry Andric                                                Declarator &D,
4120b57cec5SDimitry Andric                                                NullabilityKind nullability,
4130b57cec5SDimitry Andric                                                SourceLocation nullabilityLoc,
4140b57cec5SDimitry Andric                                                bool &addedToDeclSpec) {
4150b57cec5SDimitry Andric   // Create the attribute.
4160b57cec5SDimitry Andric   auto getNullabilityAttr = [&](AttributePool &Pool) -> ParsedAttr * {
4170b57cec5SDimitry Andric     return Pool.create(P.getNullabilityKeyword(nullability),
4180b57cec5SDimitry Andric                        SourceRange(nullabilityLoc), nullptr, SourceLocation(),
41906c3fb27SDimitry Andric                        nullptr, 0, ParsedAttr::Form::ContextSensitiveKeyword());
4200b57cec5SDimitry Andric   };
4210b57cec5SDimitry Andric 
4220b57cec5SDimitry Andric   if (D.getNumTypeObjects() > 0) {
4230b57cec5SDimitry Andric     // Add the attribute to the declarator chunk nearest the declarator.
4240b57cec5SDimitry Andric     D.getTypeObject(0).getAttrs().addAtEnd(
4250b57cec5SDimitry Andric         getNullabilityAttr(D.getAttributePool()));
4260b57cec5SDimitry Andric   } else if (!addedToDeclSpec) {
4270b57cec5SDimitry Andric     // Otherwise, just put it on the declaration specifiers (if one
4280b57cec5SDimitry Andric     // isn't there already).
4290b57cec5SDimitry Andric     D.getMutableDeclSpec().getAttributes().addAtEnd(
4300b57cec5SDimitry Andric         getNullabilityAttr(D.getMutableDeclSpec().getAttributes().getPool()));
4310b57cec5SDimitry Andric     addedToDeclSpec = true;
4320b57cec5SDimitry Andric   }
4330b57cec5SDimitry Andric }
4340b57cec5SDimitry Andric 
4350b57cec5SDimitry Andric /// Parse an Objective-C type parameter list, if present, or capture
4360b57cec5SDimitry Andric /// the locations of the protocol identifiers for a list of protocol
4370b57cec5SDimitry Andric /// references.
4380b57cec5SDimitry Andric ///
4390b57cec5SDimitry Andric ///   objc-type-parameter-list:
4400b57cec5SDimitry Andric ///     '<' objc-type-parameter (',' objc-type-parameter)* '>'
4410b57cec5SDimitry Andric ///
4420b57cec5SDimitry Andric ///   objc-type-parameter:
4430b57cec5SDimitry Andric ///     objc-type-parameter-variance? identifier objc-type-parameter-bound[opt]
4440b57cec5SDimitry Andric ///
4450b57cec5SDimitry Andric ///   objc-type-parameter-bound:
4460b57cec5SDimitry Andric ///     ':' type-name
4470b57cec5SDimitry Andric ///
4480b57cec5SDimitry Andric ///   objc-type-parameter-variance:
4490b57cec5SDimitry Andric ///     '__covariant'
4500b57cec5SDimitry Andric ///     '__contravariant'
4510b57cec5SDimitry Andric ///
4520b57cec5SDimitry Andric /// \param lAngleLoc The location of the starting '<'.
4530b57cec5SDimitry Andric ///
4540b57cec5SDimitry Andric /// \param protocolIdents Will capture the list of identifiers, if the
4550b57cec5SDimitry Andric /// angle brackets contain a list of protocol references rather than a
4560b57cec5SDimitry Andric /// type parameter list.
4570b57cec5SDimitry Andric ///
4580b57cec5SDimitry Andric /// \param rAngleLoc The location of the ending '>'.
4590b57cec5SDimitry Andric ObjCTypeParamList *Parser::parseObjCTypeParamListOrProtocolRefs(
4600b57cec5SDimitry Andric     ObjCTypeParamListScope &Scope, SourceLocation &lAngleLoc,
4610b57cec5SDimitry Andric     SmallVectorImpl<IdentifierLocPair> &protocolIdents,
4620b57cec5SDimitry Andric     SourceLocation &rAngleLoc, bool mayBeProtocolList) {
4630b57cec5SDimitry Andric   assert(Tok.is(tok::less) && "Not at the beginning of a type parameter list");
4640b57cec5SDimitry Andric 
4650b57cec5SDimitry Andric   // Within the type parameter list, don't treat '>' as an operator.
4660b57cec5SDimitry Andric   GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);
4670b57cec5SDimitry Andric 
4680b57cec5SDimitry Andric   // Local function to "flush" the protocol identifiers, turning them into
4690b57cec5SDimitry Andric   // type parameters.
4700b57cec5SDimitry Andric   SmallVector<Decl *, 4> typeParams;
4710b57cec5SDimitry Andric   auto makeProtocolIdentsIntoTypeParameters = [&]() {
4720b57cec5SDimitry Andric     unsigned index = 0;
4730b57cec5SDimitry Andric     for (const auto &pair : protocolIdents) {
474*0fca6ea1SDimitry Andric       DeclResult typeParam = Actions.ObjC().actOnObjCTypeParam(
4750b57cec5SDimitry Andric           getCurScope(), ObjCTypeParamVariance::Invariant, SourceLocation(),
4760b57cec5SDimitry Andric           index++, pair.first, pair.second, SourceLocation(), nullptr);
4770b57cec5SDimitry Andric       if (typeParam.isUsable())
4780b57cec5SDimitry Andric         typeParams.push_back(typeParam.get());
4790b57cec5SDimitry Andric     }
4800b57cec5SDimitry Andric 
4810b57cec5SDimitry Andric     protocolIdents.clear();
4820b57cec5SDimitry Andric     mayBeProtocolList = false;
4830b57cec5SDimitry Andric   };
4840b57cec5SDimitry Andric 
4850b57cec5SDimitry Andric   bool invalid = false;
4860b57cec5SDimitry Andric   lAngleLoc = ConsumeToken();
4870b57cec5SDimitry Andric 
4880b57cec5SDimitry Andric   do {
4890b57cec5SDimitry Andric     // Parse the variance, if any.
4900b57cec5SDimitry Andric     SourceLocation varianceLoc;
4910b57cec5SDimitry Andric     ObjCTypeParamVariance variance = ObjCTypeParamVariance::Invariant;
4920b57cec5SDimitry Andric     if (Tok.is(tok::kw___covariant) || Tok.is(tok::kw___contravariant)) {
4930b57cec5SDimitry Andric       variance = Tok.is(tok::kw___covariant)
4940b57cec5SDimitry Andric                    ? ObjCTypeParamVariance::Covariant
4950b57cec5SDimitry Andric                    : ObjCTypeParamVariance::Contravariant;
4960b57cec5SDimitry Andric       varianceLoc = ConsumeToken();
4970b57cec5SDimitry Andric 
4980b57cec5SDimitry Andric       // Once we've seen a variance specific , we know this is not a
4990b57cec5SDimitry Andric       // list of protocol references.
5000b57cec5SDimitry Andric       if (mayBeProtocolList) {
5010b57cec5SDimitry Andric         // Up until now, we have been queuing up parameters because they
5020b57cec5SDimitry Andric         // might be protocol references. Turn them into parameters now.
5030b57cec5SDimitry Andric         makeProtocolIdentsIntoTypeParameters();
5040b57cec5SDimitry Andric       }
5050b57cec5SDimitry Andric     }
5060b57cec5SDimitry Andric 
5070b57cec5SDimitry Andric     // Parse the identifier.
5080b57cec5SDimitry Andric     if (!Tok.is(tok::identifier)) {
5090b57cec5SDimitry Andric       // Code completion.
5100b57cec5SDimitry Andric       if (Tok.is(tok::code_completion)) {
5110b57cec5SDimitry Andric         // FIXME: If these aren't protocol references, we'll need different
5120b57cec5SDimitry Andric         // completions.
5130b57cec5SDimitry Andric         cutOffParsing();
514*0fca6ea1SDimitry Andric         Actions.CodeCompletion().CodeCompleteObjCProtocolReferences(
515*0fca6ea1SDimitry Andric             protocolIdents);
5160b57cec5SDimitry Andric 
5170b57cec5SDimitry Andric         // FIXME: Better recovery here?.
5180b57cec5SDimitry Andric         return nullptr;
5190b57cec5SDimitry Andric       }
5200b57cec5SDimitry Andric 
5210b57cec5SDimitry Andric       Diag(Tok, diag::err_objc_expected_type_parameter);
5220b57cec5SDimitry Andric       invalid = true;
5230b57cec5SDimitry Andric       break;
5240b57cec5SDimitry Andric     }
5250b57cec5SDimitry Andric 
5260b57cec5SDimitry Andric     IdentifierInfo *paramName = Tok.getIdentifierInfo();
5270b57cec5SDimitry Andric     SourceLocation paramLoc = ConsumeToken();
5280b57cec5SDimitry Andric 
5290b57cec5SDimitry Andric     // If there is a bound, parse it.
5300b57cec5SDimitry Andric     SourceLocation colonLoc;
5310b57cec5SDimitry Andric     TypeResult boundType;
5320b57cec5SDimitry Andric     if (TryConsumeToken(tok::colon, colonLoc)) {
5330b57cec5SDimitry Andric       // Once we've seen a bound, we know this is not a list of protocol
5340b57cec5SDimitry Andric       // references.
5350b57cec5SDimitry Andric       if (mayBeProtocolList) {
5360b57cec5SDimitry Andric         // Up until now, we have been queuing up parameters because they
5370b57cec5SDimitry Andric         // might be protocol references. Turn them into parameters now.
5380b57cec5SDimitry Andric         makeProtocolIdentsIntoTypeParameters();
5390b57cec5SDimitry Andric       }
5400b57cec5SDimitry Andric 
5410b57cec5SDimitry Andric       // type-name
5420b57cec5SDimitry Andric       boundType = ParseTypeName();
5430b57cec5SDimitry Andric       if (boundType.isInvalid())
5440b57cec5SDimitry Andric         invalid = true;
5450b57cec5SDimitry Andric     } else if (mayBeProtocolList) {
5460b57cec5SDimitry Andric       // If this could still be a protocol list, just capture the identifier.
5470b57cec5SDimitry Andric       // We don't want to turn it into a parameter.
5480b57cec5SDimitry Andric       protocolIdents.push_back(std::make_pair(paramName, paramLoc));
5490b57cec5SDimitry Andric       continue;
5500b57cec5SDimitry Andric     }
5510b57cec5SDimitry Andric 
5520b57cec5SDimitry Andric     // Create the type parameter.
553*0fca6ea1SDimitry Andric     DeclResult typeParam = Actions.ObjC().actOnObjCTypeParam(
5540b57cec5SDimitry Andric         getCurScope(), variance, varianceLoc, typeParams.size(), paramName,
5550b57cec5SDimitry Andric         paramLoc, colonLoc, boundType.isUsable() ? boundType.get() : nullptr);
5560b57cec5SDimitry Andric     if (typeParam.isUsable())
5570b57cec5SDimitry Andric       typeParams.push_back(typeParam.get());
5580b57cec5SDimitry Andric   } while (TryConsumeToken(tok::comma));
5590b57cec5SDimitry Andric 
5600b57cec5SDimitry Andric   // Parse the '>'.
5610b57cec5SDimitry Andric   if (invalid) {
5620b57cec5SDimitry Andric     SkipUntil(tok::greater, tok::at, StopBeforeMatch);
5630b57cec5SDimitry Andric     if (Tok.is(tok::greater))
5640b57cec5SDimitry Andric       ConsumeToken();
5655ffd83dbSDimitry Andric   } else if (ParseGreaterThanInTemplateList(lAngleLoc, rAngleLoc,
5660b57cec5SDimitry Andric                                             /*ConsumeLastToken=*/true,
5670b57cec5SDimitry Andric                                             /*ObjCGenericList=*/true)) {
5680b57cec5SDimitry Andric     SkipUntil({tok::greater, tok::greaterequal, tok::at, tok::minus,
5690b57cec5SDimitry Andric                tok::minus, tok::plus, tok::colon, tok::l_paren, tok::l_brace,
5700b57cec5SDimitry Andric                tok::comma, tok::semi },
5710b57cec5SDimitry Andric               StopBeforeMatch);
5720b57cec5SDimitry Andric     if (Tok.is(tok::greater))
5730b57cec5SDimitry Andric       ConsumeToken();
5740b57cec5SDimitry Andric   }
5750b57cec5SDimitry Andric 
5760b57cec5SDimitry Andric   if (mayBeProtocolList) {
5770b57cec5SDimitry Andric     // A type parameter list must be followed by either a ':' (indicating the
5780b57cec5SDimitry Andric     // presence of a superclass) or a '(' (indicating that this is a category
5790b57cec5SDimitry Andric     // or extension). This disambiguates between an objc-type-parameter-list
5800b57cec5SDimitry Andric     // and a objc-protocol-refs.
5810b57cec5SDimitry Andric     if (Tok.isNot(tok::colon) && Tok.isNot(tok::l_paren)) {
5820b57cec5SDimitry Andric       // Returning null indicates that we don't have a type parameter list.
5830b57cec5SDimitry Andric       // The results the caller needs to handle the protocol references are
5840b57cec5SDimitry Andric       // captured in the reference parameters already.
5850b57cec5SDimitry Andric       return nullptr;
5860b57cec5SDimitry Andric     }
5870b57cec5SDimitry Andric 
5880b57cec5SDimitry Andric     // We have a type parameter list that looks like a list of protocol
5890b57cec5SDimitry Andric     // references. Turn that parameter list into type parameters.
5900b57cec5SDimitry Andric     makeProtocolIdentsIntoTypeParameters();
5910b57cec5SDimitry Andric   }
5920b57cec5SDimitry Andric 
5930b57cec5SDimitry Andric   // Form the type parameter list and enter its scope.
594*0fca6ea1SDimitry Andric   ObjCTypeParamList *list = Actions.ObjC().actOnObjCTypeParamList(
595*0fca6ea1SDimitry Andric       getCurScope(), lAngleLoc, typeParams, rAngleLoc);
5960b57cec5SDimitry Andric   Scope.enter(list);
5970b57cec5SDimitry Andric 
5980b57cec5SDimitry Andric   // Clear out the angle locations; they're used by the caller to indicate
5990b57cec5SDimitry Andric   // whether there are any protocol references.
6000b57cec5SDimitry Andric   lAngleLoc = SourceLocation();
6010b57cec5SDimitry Andric   rAngleLoc = SourceLocation();
6020b57cec5SDimitry Andric   return invalid ? nullptr : list;
6030b57cec5SDimitry Andric }
6040b57cec5SDimitry Andric 
6050b57cec5SDimitry Andric /// Parse an objc-type-parameter-list.
6060b57cec5SDimitry Andric ObjCTypeParamList *Parser::parseObjCTypeParamList() {
6070b57cec5SDimitry Andric   SourceLocation lAngleLoc;
6080b57cec5SDimitry Andric   SmallVector<IdentifierLocPair, 1> protocolIdents;
6090b57cec5SDimitry Andric   SourceLocation rAngleLoc;
6100b57cec5SDimitry Andric 
6110b57cec5SDimitry Andric   ObjCTypeParamListScope Scope(Actions, getCurScope());
6120b57cec5SDimitry Andric   return parseObjCTypeParamListOrProtocolRefs(Scope, lAngleLoc, protocolIdents,
6130b57cec5SDimitry Andric                                               rAngleLoc,
6140b57cec5SDimitry Andric                                               /*mayBeProtocolList=*/false);
6150b57cec5SDimitry Andric }
6160b57cec5SDimitry Andric 
6175f757f3fSDimitry Andric static bool isTopLevelObjCKeyword(tok::ObjCKeywordKind DirectiveKind) {
6185f757f3fSDimitry Andric   switch (DirectiveKind) {
6195f757f3fSDimitry Andric   case tok::objc_class:
6205f757f3fSDimitry Andric   case tok::objc_compatibility_alias:
6215f757f3fSDimitry Andric   case tok::objc_interface:
6225f757f3fSDimitry Andric   case tok::objc_implementation:
6235f757f3fSDimitry Andric   case tok::objc_protocol:
6245f757f3fSDimitry Andric     return true;
6255f757f3fSDimitry Andric   default:
6265f757f3fSDimitry Andric     return false;
6275f757f3fSDimitry Andric   }
6285f757f3fSDimitry Andric }
6295f757f3fSDimitry Andric 
6300b57cec5SDimitry Andric ///   objc-interface-decl-list:
6310b57cec5SDimitry Andric ///     empty
6320b57cec5SDimitry Andric ///     objc-interface-decl-list objc-property-decl [OBJC2]
6330b57cec5SDimitry Andric ///     objc-interface-decl-list objc-method-requirement [OBJC2]
6340b57cec5SDimitry Andric ///     objc-interface-decl-list objc-method-proto ';'
6350b57cec5SDimitry Andric ///     objc-interface-decl-list declaration
6360b57cec5SDimitry Andric ///     objc-interface-decl-list ';'
6370b57cec5SDimitry Andric ///
6380b57cec5SDimitry Andric ///   objc-method-requirement: [OBJC2]
6390b57cec5SDimitry Andric ///     @required
6400b57cec5SDimitry Andric ///     @optional
6410b57cec5SDimitry Andric ///
6420b57cec5SDimitry Andric void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
6430b57cec5SDimitry Andric                                         Decl *CDecl) {
6440b57cec5SDimitry Andric   SmallVector<Decl *, 32> allMethods;
6450b57cec5SDimitry Andric   SmallVector<DeclGroupPtrTy, 8> allTUVariables;
6460b57cec5SDimitry Andric   tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword;
6470b57cec5SDimitry Andric 
6480b57cec5SDimitry Andric   SourceRange AtEnd;
6490b57cec5SDimitry Andric 
65004eeddc0SDimitry Andric   while (true) {
6510b57cec5SDimitry Andric     // If this is a method prototype, parse it.
6520b57cec5SDimitry Andric     if (Tok.isOneOf(tok::minus, tok::plus)) {
6530b57cec5SDimitry Andric       if (Decl *methodPrototype =
6540b57cec5SDimitry Andric           ParseObjCMethodPrototype(MethodImplKind, false))
6550b57cec5SDimitry Andric         allMethods.push_back(methodPrototype);
6560b57cec5SDimitry Andric       // Consume the ';' here, since ParseObjCMethodPrototype() is re-used for
6570b57cec5SDimitry Andric       // method definitions.
6580b57cec5SDimitry Andric       if (ExpectAndConsumeSemi(diag::err_expected_semi_after_method_proto)) {
6590b57cec5SDimitry Andric         // We didn't find a semi and we error'ed out. Skip until a ';' or '@'.
6600b57cec5SDimitry Andric         SkipUntil(tok::at, StopAtSemi | StopBeforeMatch);
6610b57cec5SDimitry Andric         if (Tok.is(tok::semi))
6620b57cec5SDimitry Andric           ConsumeToken();
6630b57cec5SDimitry Andric       }
6640b57cec5SDimitry Andric       continue;
6650b57cec5SDimitry Andric     }
6660b57cec5SDimitry Andric     if (Tok.is(tok::l_paren)) {
6670b57cec5SDimitry Andric       Diag(Tok, diag::err_expected_minus_or_plus);
6680b57cec5SDimitry Andric       ParseObjCMethodDecl(Tok.getLocation(),
6690b57cec5SDimitry Andric                           tok::minus,
6700b57cec5SDimitry Andric                           MethodImplKind, false);
6710b57cec5SDimitry Andric       continue;
6720b57cec5SDimitry Andric     }
6730b57cec5SDimitry Andric     // Ignore excess semicolons.
6740b57cec5SDimitry Andric     if (Tok.is(tok::semi)) {
6750b57cec5SDimitry Andric       // FIXME: This should use ConsumeExtraSemi() for extraneous semicolons,
6760b57cec5SDimitry Andric       // to make -Wextra-semi diagnose them.
6770b57cec5SDimitry Andric       ConsumeToken();
6780b57cec5SDimitry Andric       continue;
6790b57cec5SDimitry Andric     }
6800b57cec5SDimitry Andric 
6810b57cec5SDimitry Andric     // If we got to the end of the file, exit the loop.
6820b57cec5SDimitry Andric     if (isEofOrEom())
6830b57cec5SDimitry Andric       break;
6840b57cec5SDimitry Andric 
6850b57cec5SDimitry Andric     // Code completion within an Objective-C interface.
6860b57cec5SDimitry Andric     if (Tok.is(tok::code_completion)) {
687fe6060f1SDimitry Andric       cutOffParsing();
688*0fca6ea1SDimitry Andric       Actions.CodeCompletion().CodeCompleteOrdinaryName(
689*0fca6ea1SDimitry Andric           getCurScope(), CurParsedObjCImpl
690*0fca6ea1SDimitry Andric                              ? SemaCodeCompletion::PCC_ObjCImplementation
691*0fca6ea1SDimitry Andric                              : SemaCodeCompletion::PCC_ObjCInterface);
692fe6060f1SDimitry Andric       return;
6930b57cec5SDimitry Andric     }
6940b57cec5SDimitry Andric 
6950b57cec5SDimitry Andric     // If we don't have an @ directive, parse it as a function definition.
6960b57cec5SDimitry Andric     if (Tok.isNot(tok::at)) {
6970b57cec5SDimitry Andric       // The code below does not consume '}'s because it is afraid of eating the
6980b57cec5SDimitry Andric       // end of a namespace.  Because of the way this code is structured, an
6990b57cec5SDimitry Andric       // erroneous r_brace would cause an infinite loop if not handled here.
7000b57cec5SDimitry Andric       if (Tok.is(tok::r_brace))
7010b57cec5SDimitry Andric         break;
7020b57cec5SDimitry Andric 
703bdd1243dSDimitry Andric       ParsedAttributes EmptyDeclAttrs(AttrFactory);
704bdd1243dSDimitry Andric       ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
7050b57cec5SDimitry Andric 
7060b57cec5SDimitry Andric       // Since we call ParseDeclarationOrFunctionDefinition() instead of
7070b57cec5SDimitry Andric       // ParseExternalDeclaration() below (so that this doesn't parse nested
7080b57cec5SDimitry Andric       // @interfaces), this needs to duplicate some code from the latter.
7090b57cec5SDimitry Andric       if (Tok.isOneOf(tok::kw_static_assert, tok::kw__Static_assert)) {
7100b57cec5SDimitry Andric         SourceLocation DeclEnd;
71181ad6265SDimitry Andric         ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
712bdd1243dSDimitry Andric         allTUVariables.push_back(ParseDeclaration(DeclaratorContext::File,
713bdd1243dSDimitry Andric                                                   DeclEnd, EmptyDeclAttrs,
714bdd1243dSDimitry Andric                                                   EmptyDeclSpecAttrs));
7150b57cec5SDimitry Andric         continue;
7160b57cec5SDimitry Andric       }
7170b57cec5SDimitry Andric 
718bdd1243dSDimitry Andric       allTUVariables.push_back(ParseDeclarationOrFunctionDefinition(
719bdd1243dSDimitry Andric           EmptyDeclAttrs, EmptyDeclSpecAttrs));
7200b57cec5SDimitry Andric       continue;
7210b57cec5SDimitry Andric     }
7220b57cec5SDimitry Andric 
7235f757f3fSDimitry Andric     // Otherwise, we have an @ directive, peak at the next token
7245f757f3fSDimitry Andric     SourceLocation AtLoc = Tok.getLocation();
7255f757f3fSDimitry Andric     const auto &NextTok = NextToken();
7265f757f3fSDimitry Andric     if (NextTok.is(tok::code_completion)) {
727fe6060f1SDimitry Andric       cutOffParsing();
728*0fca6ea1SDimitry Andric       Actions.CodeCompletion().CodeCompleteObjCAtDirective(getCurScope());
729fe6060f1SDimitry Andric       return;
7300b57cec5SDimitry Andric     }
7310b57cec5SDimitry Andric 
7325f757f3fSDimitry Andric     tok::ObjCKeywordKind DirectiveKind = NextTok.getObjCKeywordID();
7330b57cec5SDimitry Andric     if (DirectiveKind == tok::objc_end) { // @end -> terminate list
7345f757f3fSDimitry Andric       ConsumeToken();                     // the "@"
7350b57cec5SDimitry Andric       AtEnd.setBegin(AtLoc);
7360b57cec5SDimitry Andric       AtEnd.setEnd(Tok.getLocation());
7370b57cec5SDimitry Andric       break;
7380b57cec5SDimitry Andric     } else if (DirectiveKind == tok::objc_not_keyword) {
7395f757f3fSDimitry Andric       Diag(NextTok, diag::err_objc_unknown_at);
7400b57cec5SDimitry Andric       SkipUntil(tok::semi);
7410b57cec5SDimitry Andric       continue;
7420b57cec5SDimitry Andric     }
7430b57cec5SDimitry Andric 
7445f757f3fSDimitry Andric     // If we see something like '@interface' that's only allowed at the top
7455f757f3fSDimitry Andric     // level, bail out as if we saw an '@end'. We'll diagnose this below.
7465f757f3fSDimitry Andric     if (isTopLevelObjCKeyword(DirectiveKind))
7475f757f3fSDimitry Andric       break;
7485f757f3fSDimitry Andric 
7495f757f3fSDimitry Andric     // Otherwise parse it as part of the current declaration. Eat "@identifier".
7505f757f3fSDimitry Andric     ConsumeToken();
7510b57cec5SDimitry Andric     ConsumeToken();
7520b57cec5SDimitry Andric 
7530b57cec5SDimitry Andric     switch (DirectiveKind) {
7540b57cec5SDimitry Andric     default:
7550b57cec5SDimitry Andric       // FIXME: If someone forgets an @end on a protocol, this loop will
7560b57cec5SDimitry Andric       // continue to eat up tons of stuff and spew lots of nonsense errors.  It
7570b57cec5SDimitry Andric       // would probably be better to bail out if we saw an @class or @interface
7580b57cec5SDimitry Andric       // or something like that.
7590b57cec5SDimitry Andric       Diag(AtLoc, diag::err_objc_illegal_interface_qual);
7600b57cec5SDimitry Andric       // Skip until we see an '@' or '}' or ';'.
7610b57cec5SDimitry Andric       SkipUntil(tok::r_brace, tok::at, StopAtSemi);
7620b57cec5SDimitry Andric       break;
7630b57cec5SDimitry Andric 
7640b57cec5SDimitry Andric     case tok::objc_required:
7650b57cec5SDimitry Andric     case tok::objc_optional:
7660b57cec5SDimitry Andric       // This is only valid on protocols.
7670b57cec5SDimitry Andric       if (contextKey != tok::objc_protocol)
7680b57cec5SDimitry Andric         Diag(AtLoc, diag::err_objc_directive_only_in_protocol);
7690b57cec5SDimitry Andric       else
7700b57cec5SDimitry Andric         MethodImplKind = DirectiveKind;
7710b57cec5SDimitry Andric       break;
7720b57cec5SDimitry Andric 
7730b57cec5SDimitry Andric     case tok::objc_property:
7740b57cec5SDimitry Andric       ObjCDeclSpec OCDS;
7750b57cec5SDimitry Andric       SourceLocation LParenLoc;
7760b57cec5SDimitry Andric       // Parse property attribute list, if any.
7770b57cec5SDimitry Andric       if (Tok.is(tok::l_paren)) {
7780b57cec5SDimitry Andric         LParenLoc = Tok.getLocation();
7790b57cec5SDimitry Andric         ParseObjCPropertyAttribute(OCDS);
7800b57cec5SDimitry Andric       }
7810b57cec5SDimitry Andric 
7820b57cec5SDimitry Andric       bool addedToDeclSpec = false;
783*0fca6ea1SDimitry Andric       auto ObjCPropertyCallback = [&](ParsingFieldDeclarator &FD) -> Decl * {
7840b57cec5SDimitry Andric         if (FD.D.getIdentifier() == nullptr) {
7850b57cec5SDimitry Andric           Diag(AtLoc, diag::err_objc_property_requires_field_name)
7860b57cec5SDimitry Andric               << FD.D.getSourceRange();
787*0fca6ea1SDimitry Andric           return nullptr;
7880b57cec5SDimitry Andric         }
7890b57cec5SDimitry Andric         if (FD.BitfieldSize) {
7900b57cec5SDimitry Andric           Diag(AtLoc, diag::err_objc_property_bitfield)
7910b57cec5SDimitry Andric               << FD.D.getSourceRange();
792*0fca6ea1SDimitry Andric           return nullptr;
7930b57cec5SDimitry Andric         }
7940b57cec5SDimitry Andric 
7950b57cec5SDimitry Andric         // Map a nullability property attribute to a context-sensitive keyword
7960b57cec5SDimitry Andric         // attribute.
7975ffd83dbSDimitry Andric         if (OCDS.getPropertyAttributes() &
7985ffd83dbSDimitry Andric             ObjCPropertyAttribute::kind_nullability)
7990b57cec5SDimitry Andric           addContextSensitiveTypeNullability(*this, FD.D, OCDS.getNullability(),
8000b57cec5SDimitry Andric                                              OCDS.getNullabilityLoc(),
8010b57cec5SDimitry Andric                                              addedToDeclSpec);
8020b57cec5SDimitry Andric 
8030b57cec5SDimitry Andric         // Install the property declarator into interfaceDecl.
804*0fca6ea1SDimitry Andric         const IdentifierInfo *SelName =
8050b57cec5SDimitry Andric             OCDS.getGetterName() ? OCDS.getGetterName() : FD.D.getIdentifier();
8060b57cec5SDimitry Andric 
8070b57cec5SDimitry Andric         Selector GetterSel = PP.getSelectorTable().getNullarySelector(SelName);
808*0fca6ea1SDimitry Andric         const IdentifierInfo *SetterName = OCDS.getSetterName();
8090b57cec5SDimitry Andric         Selector SetterSel;
8100b57cec5SDimitry Andric         if (SetterName)
8110b57cec5SDimitry Andric           SetterSel = PP.getSelectorTable().getSelector(1, &SetterName);
8120b57cec5SDimitry Andric         else
8130b57cec5SDimitry Andric           SetterSel = SelectorTable::constructSetterSelector(
8140b57cec5SDimitry Andric               PP.getIdentifierTable(), PP.getSelectorTable(),
8150b57cec5SDimitry Andric               FD.D.getIdentifier());
816*0fca6ea1SDimitry Andric         Decl *Property = Actions.ObjC().ActOnProperty(
8170b57cec5SDimitry Andric             getCurScope(), AtLoc, LParenLoc, FD, OCDS, GetterSel, SetterSel,
8180b57cec5SDimitry Andric             MethodImplKind);
8190b57cec5SDimitry Andric 
8200b57cec5SDimitry Andric         FD.complete(Property);
821*0fca6ea1SDimitry Andric         return Property;
8220b57cec5SDimitry Andric       };
8230b57cec5SDimitry Andric 
8240b57cec5SDimitry Andric       // Parse all the comma separated declarators.
8250b57cec5SDimitry Andric       ParsingDeclSpec DS(*this);
8260b57cec5SDimitry Andric       ParseStructDeclaration(DS, ObjCPropertyCallback);
8270b57cec5SDimitry Andric 
8280b57cec5SDimitry Andric       ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list);
8290b57cec5SDimitry Andric       break;
8300b57cec5SDimitry Andric     }
8310b57cec5SDimitry Andric   }
8320b57cec5SDimitry Andric 
8335f757f3fSDimitry Andric   // We break out of the big loop in 3 cases: when we see @end or when we see
8345f757f3fSDimitry Andric   // top-level ObjC keyword or EOF. In the former case, eat the @end. In the
8355f757f3fSDimitry Andric   // later cases, emit an error.
8365f757f3fSDimitry Andric   if (Tok.isObjCAtKeyword(tok::objc_end)) {
8370b57cec5SDimitry Andric     ConsumeToken(); // the "end" identifier
8380b57cec5SDimitry Andric   } else {
8390b57cec5SDimitry Andric     Diag(Tok, diag::err_objc_missing_end)
8400b57cec5SDimitry Andric         << FixItHint::CreateInsertion(Tok.getLocation(), "\n@end\n");
8410b57cec5SDimitry Andric     Diag(CDecl->getBeginLoc(), diag::note_objc_container_start)
842*0fca6ea1SDimitry Andric         << (int)Actions.ObjC().getObjCContainerKind();
8430b57cec5SDimitry Andric     AtEnd.setBegin(Tok.getLocation());
8440b57cec5SDimitry Andric     AtEnd.setEnd(Tok.getLocation());
8450b57cec5SDimitry Andric   }
8460b57cec5SDimitry Andric 
8470b57cec5SDimitry Andric   // Insert collected methods declarations into the @interface object.
8480b57cec5SDimitry Andric   // This passes in an invalid SourceLocation for AtEndLoc when EOF is hit.
849*0fca6ea1SDimitry Andric   Actions.ObjC().ActOnAtEnd(getCurScope(), AtEnd, allMethods, allTUVariables);
8500b57cec5SDimitry Andric }
8510b57cec5SDimitry Andric 
8520b57cec5SDimitry Andric /// Diagnose redundant or conflicting nullability information.
8530b57cec5SDimitry Andric static void diagnoseRedundantPropertyNullability(Parser &P,
8540b57cec5SDimitry Andric                                                  ObjCDeclSpec &DS,
8550b57cec5SDimitry Andric                                                  NullabilityKind nullability,
8560b57cec5SDimitry Andric                                                  SourceLocation nullabilityLoc){
8570b57cec5SDimitry Andric   if (DS.getNullability() == nullability) {
8580b57cec5SDimitry Andric     P.Diag(nullabilityLoc, diag::warn_nullability_duplicate)
8590b57cec5SDimitry Andric       << DiagNullabilityKind(nullability, true)
8600b57cec5SDimitry Andric       << SourceRange(DS.getNullabilityLoc());
8610b57cec5SDimitry Andric     return;
8620b57cec5SDimitry Andric   }
8630b57cec5SDimitry Andric 
8640b57cec5SDimitry Andric   P.Diag(nullabilityLoc, diag::err_nullability_conflicting)
8650b57cec5SDimitry Andric     << DiagNullabilityKind(nullability, true)
8660b57cec5SDimitry Andric     << DiagNullabilityKind(DS.getNullability(), true)
8670b57cec5SDimitry Andric     << SourceRange(DS.getNullabilityLoc());
8680b57cec5SDimitry Andric }
8690b57cec5SDimitry Andric 
8700b57cec5SDimitry Andric ///   Parse property attribute declarations.
8710b57cec5SDimitry Andric ///
8720b57cec5SDimitry Andric ///   property-attr-decl: '(' property-attrlist ')'
8730b57cec5SDimitry Andric ///   property-attrlist:
8740b57cec5SDimitry Andric ///     property-attribute
8750b57cec5SDimitry Andric ///     property-attrlist ',' property-attribute
8760b57cec5SDimitry Andric ///   property-attribute:
8770b57cec5SDimitry Andric ///     getter '=' identifier
8780b57cec5SDimitry Andric ///     setter '=' identifier ':'
879480093f4SDimitry Andric ///     direct
8800b57cec5SDimitry Andric ///     readonly
8810b57cec5SDimitry Andric ///     readwrite
8820b57cec5SDimitry Andric ///     assign
8830b57cec5SDimitry Andric ///     retain
8840b57cec5SDimitry Andric ///     copy
8850b57cec5SDimitry Andric ///     nonatomic
8860b57cec5SDimitry Andric ///     atomic
8870b57cec5SDimitry Andric ///     strong
8880b57cec5SDimitry Andric ///     weak
8890b57cec5SDimitry Andric ///     unsafe_unretained
8900b57cec5SDimitry Andric ///     nonnull
8910b57cec5SDimitry Andric ///     nullable
8920b57cec5SDimitry Andric ///     null_unspecified
8930b57cec5SDimitry Andric ///     null_resettable
8940b57cec5SDimitry Andric ///     class
8950b57cec5SDimitry Andric ///
8960b57cec5SDimitry Andric void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) {
8970b57cec5SDimitry Andric   assert(Tok.getKind() == tok::l_paren);
8980b57cec5SDimitry Andric   BalancedDelimiterTracker T(*this, tok::l_paren);
8990b57cec5SDimitry Andric   T.consumeOpen();
9000b57cec5SDimitry Andric 
90104eeddc0SDimitry Andric   while (true) {
9020b57cec5SDimitry Andric     if (Tok.is(tok::code_completion)) {
903fe6060f1SDimitry Andric       cutOffParsing();
904*0fca6ea1SDimitry Andric       Actions.CodeCompletion().CodeCompleteObjCPropertyFlags(getCurScope(), DS);
905fe6060f1SDimitry Andric       return;
9060b57cec5SDimitry Andric     }
9070b57cec5SDimitry Andric     const IdentifierInfo *II = Tok.getIdentifierInfo();
9080b57cec5SDimitry Andric 
9090b57cec5SDimitry Andric     // If this is not an identifier at all, bail out early.
9100b57cec5SDimitry Andric     if (!II) {
9110b57cec5SDimitry Andric       T.consumeClose();
9120b57cec5SDimitry Andric       return;
9130b57cec5SDimitry Andric     }
9140b57cec5SDimitry Andric 
9150b57cec5SDimitry Andric     SourceLocation AttrName = ConsumeToken(); // consume last attribute name
9160b57cec5SDimitry Andric 
9170b57cec5SDimitry Andric     if (II->isStr("readonly"))
9185ffd83dbSDimitry Andric       DS.setPropertyAttributes(ObjCPropertyAttribute::kind_readonly);
9190b57cec5SDimitry Andric     else if (II->isStr("assign"))
9205ffd83dbSDimitry Andric       DS.setPropertyAttributes(ObjCPropertyAttribute::kind_assign);
9210b57cec5SDimitry Andric     else if (II->isStr("unsafe_unretained"))
9225ffd83dbSDimitry Andric       DS.setPropertyAttributes(ObjCPropertyAttribute::kind_unsafe_unretained);
9230b57cec5SDimitry Andric     else if (II->isStr("readwrite"))
9245ffd83dbSDimitry Andric       DS.setPropertyAttributes(ObjCPropertyAttribute::kind_readwrite);
9250b57cec5SDimitry Andric     else if (II->isStr("retain"))
9265ffd83dbSDimitry Andric       DS.setPropertyAttributes(ObjCPropertyAttribute::kind_retain);
9270b57cec5SDimitry Andric     else if (II->isStr("strong"))
9285ffd83dbSDimitry Andric       DS.setPropertyAttributes(ObjCPropertyAttribute::kind_strong);
9290b57cec5SDimitry Andric     else if (II->isStr("copy"))
9305ffd83dbSDimitry Andric       DS.setPropertyAttributes(ObjCPropertyAttribute::kind_copy);
9310b57cec5SDimitry Andric     else if (II->isStr("nonatomic"))
9325ffd83dbSDimitry Andric       DS.setPropertyAttributes(ObjCPropertyAttribute::kind_nonatomic);
9330b57cec5SDimitry Andric     else if (II->isStr("atomic"))
9345ffd83dbSDimitry Andric       DS.setPropertyAttributes(ObjCPropertyAttribute::kind_atomic);
9350b57cec5SDimitry Andric     else if (II->isStr("weak"))
9365ffd83dbSDimitry Andric       DS.setPropertyAttributes(ObjCPropertyAttribute::kind_weak);
9370b57cec5SDimitry Andric     else if (II->isStr("getter") || II->isStr("setter")) {
9380b57cec5SDimitry Andric       bool IsSetter = II->getNameStart()[0] == 's';
9390b57cec5SDimitry Andric 
9400b57cec5SDimitry Andric       // getter/setter require extra treatment.
9410b57cec5SDimitry Andric       unsigned DiagID = IsSetter ? diag::err_objc_expected_equal_for_setter :
9420b57cec5SDimitry Andric                                    diag::err_objc_expected_equal_for_getter;
9430b57cec5SDimitry Andric 
9440b57cec5SDimitry Andric       if (ExpectAndConsume(tok::equal, DiagID)) {
9450b57cec5SDimitry Andric         SkipUntil(tok::r_paren, StopAtSemi);
9460b57cec5SDimitry Andric         return;
9470b57cec5SDimitry Andric       }
9480b57cec5SDimitry Andric 
9490b57cec5SDimitry Andric       if (Tok.is(tok::code_completion)) {
950fe6060f1SDimitry Andric         cutOffParsing();
9510b57cec5SDimitry Andric         if (IsSetter)
952*0fca6ea1SDimitry Andric           Actions.CodeCompletion().CodeCompleteObjCPropertySetter(
953*0fca6ea1SDimitry Andric               getCurScope());
9540b57cec5SDimitry Andric         else
955*0fca6ea1SDimitry Andric           Actions.CodeCompletion().CodeCompleteObjCPropertyGetter(
956*0fca6ea1SDimitry Andric               getCurScope());
957fe6060f1SDimitry Andric         return;
9580b57cec5SDimitry Andric       }
9590b57cec5SDimitry Andric 
9600b57cec5SDimitry Andric       SourceLocation SelLoc;
9610b57cec5SDimitry Andric       IdentifierInfo *SelIdent = ParseObjCSelectorPiece(SelLoc);
9620b57cec5SDimitry Andric 
9630b57cec5SDimitry Andric       if (!SelIdent) {
9640b57cec5SDimitry Andric         Diag(Tok, diag::err_objc_expected_selector_for_getter_setter)
9650b57cec5SDimitry Andric           << IsSetter;
9660b57cec5SDimitry Andric         SkipUntil(tok::r_paren, StopAtSemi);
9670b57cec5SDimitry Andric         return;
9680b57cec5SDimitry Andric       }
9690b57cec5SDimitry Andric 
9700b57cec5SDimitry Andric       if (IsSetter) {
9715ffd83dbSDimitry Andric         DS.setPropertyAttributes(ObjCPropertyAttribute::kind_setter);
9720b57cec5SDimitry Andric         DS.setSetterName(SelIdent, SelLoc);
9730b57cec5SDimitry Andric 
9740b57cec5SDimitry Andric         if (ExpectAndConsume(tok::colon,
9750b57cec5SDimitry Andric                              diag::err_expected_colon_after_setter_name)) {
9760b57cec5SDimitry Andric           SkipUntil(tok::r_paren, StopAtSemi);
9770b57cec5SDimitry Andric           return;
9780b57cec5SDimitry Andric         }
9790b57cec5SDimitry Andric       } else {
9805ffd83dbSDimitry Andric         DS.setPropertyAttributes(ObjCPropertyAttribute::kind_getter);
9810b57cec5SDimitry Andric         DS.setGetterName(SelIdent, SelLoc);
9820b57cec5SDimitry Andric       }
9830b57cec5SDimitry Andric     } else if (II->isStr("nonnull")) {
9845ffd83dbSDimitry Andric       if (DS.getPropertyAttributes() & ObjCPropertyAttribute::kind_nullability)
9850b57cec5SDimitry Andric         diagnoseRedundantPropertyNullability(*this, DS,
9860b57cec5SDimitry Andric                                              NullabilityKind::NonNull,
9870b57cec5SDimitry Andric                                              Tok.getLocation());
9885ffd83dbSDimitry Andric       DS.setPropertyAttributes(ObjCPropertyAttribute::kind_nullability);
9890b57cec5SDimitry Andric       DS.setNullability(Tok.getLocation(), NullabilityKind::NonNull);
9900b57cec5SDimitry Andric     } else if (II->isStr("nullable")) {
9915ffd83dbSDimitry Andric       if (DS.getPropertyAttributes() & ObjCPropertyAttribute::kind_nullability)
9920b57cec5SDimitry Andric         diagnoseRedundantPropertyNullability(*this, DS,
9930b57cec5SDimitry Andric                                              NullabilityKind::Nullable,
9940b57cec5SDimitry Andric                                              Tok.getLocation());
9955ffd83dbSDimitry Andric       DS.setPropertyAttributes(ObjCPropertyAttribute::kind_nullability);
9960b57cec5SDimitry Andric       DS.setNullability(Tok.getLocation(), NullabilityKind::Nullable);
9970b57cec5SDimitry Andric     } else if (II->isStr("null_unspecified")) {
9985ffd83dbSDimitry Andric       if (DS.getPropertyAttributes() & ObjCPropertyAttribute::kind_nullability)
9990b57cec5SDimitry Andric         diagnoseRedundantPropertyNullability(*this, DS,
10000b57cec5SDimitry Andric                                              NullabilityKind::Unspecified,
10010b57cec5SDimitry Andric                                              Tok.getLocation());
10025ffd83dbSDimitry Andric       DS.setPropertyAttributes(ObjCPropertyAttribute::kind_nullability);
10030b57cec5SDimitry Andric       DS.setNullability(Tok.getLocation(), NullabilityKind::Unspecified);
10040b57cec5SDimitry Andric     } else if (II->isStr("null_resettable")) {
10055ffd83dbSDimitry Andric       if (DS.getPropertyAttributes() & ObjCPropertyAttribute::kind_nullability)
10060b57cec5SDimitry Andric         diagnoseRedundantPropertyNullability(*this, DS,
10070b57cec5SDimitry Andric                                              NullabilityKind::Unspecified,
10080b57cec5SDimitry Andric                                              Tok.getLocation());
10095ffd83dbSDimitry Andric       DS.setPropertyAttributes(ObjCPropertyAttribute::kind_nullability);
10100b57cec5SDimitry Andric       DS.setNullability(Tok.getLocation(), NullabilityKind::Unspecified);
10110b57cec5SDimitry Andric 
10120b57cec5SDimitry Andric       // Also set the null_resettable bit.
10135ffd83dbSDimitry Andric       DS.setPropertyAttributes(ObjCPropertyAttribute::kind_null_resettable);
10140b57cec5SDimitry Andric     } else if (II->isStr("class")) {
10155ffd83dbSDimitry Andric       DS.setPropertyAttributes(ObjCPropertyAttribute::kind_class);
1016480093f4SDimitry Andric     } else if (II->isStr("direct")) {
10175ffd83dbSDimitry Andric       DS.setPropertyAttributes(ObjCPropertyAttribute::kind_direct);
10180b57cec5SDimitry Andric     } else {
10190b57cec5SDimitry Andric       Diag(AttrName, diag::err_objc_expected_property_attr) << II;
10200b57cec5SDimitry Andric       SkipUntil(tok::r_paren, StopAtSemi);
10210b57cec5SDimitry Andric       return;
10220b57cec5SDimitry Andric     }
10230b57cec5SDimitry Andric 
10240b57cec5SDimitry Andric     if (Tok.isNot(tok::comma))
10250b57cec5SDimitry Andric       break;
10260b57cec5SDimitry Andric 
10270b57cec5SDimitry Andric     ConsumeToken();
10280b57cec5SDimitry Andric   }
10290b57cec5SDimitry Andric 
10300b57cec5SDimitry Andric   T.consumeClose();
10310b57cec5SDimitry Andric }
10320b57cec5SDimitry Andric 
10330b57cec5SDimitry Andric ///   objc-method-proto:
10340b57cec5SDimitry Andric ///     objc-instance-method objc-method-decl objc-method-attributes[opt]
10350b57cec5SDimitry Andric ///     objc-class-method objc-method-decl objc-method-attributes[opt]
10360b57cec5SDimitry Andric ///
10370b57cec5SDimitry Andric ///   objc-instance-method: '-'
10380b57cec5SDimitry Andric ///   objc-class-method: '+'
10390b57cec5SDimitry Andric ///
10400b57cec5SDimitry Andric ///   objc-method-attributes:         [OBJC2]
10410b57cec5SDimitry Andric ///     __attribute__((deprecated))
10420b57cec5SDimitry Andric ///
10430b57cec5SDimitry Andric Decl *Parser::ParseObjCMethodPrototype(tok::ObjCKeywordKind MethodImplKind,
10440b57cec5SDimitry Andric                                        bool MethodDefinition) {
10450b57cec5SDimitry Andric   assert(Tok.isOneOf(tok::minus, tok::plus) && "expected +/-");
10460b57cec5SDimitry Andric 
10470b57cec5SDimitry Andric   tok::TokenKind methodType = Tok.getKind();
10480b57cec5SDimitry Andric   SourceLocation mLoc = ConsumeToken();
10490b57cec5SDimitry Andric   Decl *MDecl = ParseObjCMethodDecl(mLoc, methodType, MethodImplKind,
10500b57cec5SDimitry Andric                                     MethodDefinition);
10510b57cec5SDimitry Andric   // Since this rule is used for both method declarations and definitions,
10520b57cec5SDimitry Andric   // the caller is (optionally) responsible for consuming the ';'.
10530b57cec5SDimitry Andric   return MDecl;
10540b57cec5SDimitry Andric }
10550b57cec5SDimitry Andric 
10560b57cec5SDimitry Andric ///   objc-selector:
10570b57cec5SDimitry Andric ///     identifier
10580b57cec5SDimitry Andric ///     one of
10590b57cec5SDimitry Andric ///       enum struct union if else while do for switch case default
10600b57cec5SDimitry Andric ///       break continue return goto asm sizeof typeof __alignof
10610b57cec5SDimitry Andric ///       unsigned long const short volatile signed restrict _Complex
10620b57cec5SDimitry Andric ///       in out inout bycopy byref oneway int char float double void _Bool
10630b57cec5SDimitry Andric ///
10640b57cec5SDimitry Andric IdentifierInfo *Parser::ParseObjCSelectorPiece(SourceLocation &SelectorLoc) {
10650b57cec5SDimitry Andric 
10660b57cec5SDimitry Andric   switch (Tok.getKind()) {
10670b57cec5SDimitry Andric   default:
10680b57cec5SDimitry Andric     return nullptr;
10690b57cec5SDimitry Andric   case tok::colon:
10700b57cec5SDimitry Andric     // Empty selector piece uses the location of the ':'.
10710b57cec5SDimitry Andric     SelectorLoc = Tok.getLocation();
10720b57cec5SDimitry Andric     return nullptr;
10730b57cec5SDimitry Andric   case tok::ampamp:
10740b57cec5SDimitry Andric   case tok::ampequal:
10750b57cec5SDimitry Andric   case tok::amp:
10760b57cec5SDimitry Andric   case tok::pipe:
10770b57cec5SDimitry Andric   case tok::tilde:
10780b57cec5SDimitry Andric   case tok::exclaim:
10790b57cec5SDimitry Andric   case tok::exclaimequal:
10800b57cec5SDimitry Andric   case tok::pipepipe:
10810b57cec5SDimitry Andric   case tok::pipeequal:
10820b57cec5SDimitry Andric   case tok::caret:
10830b57cec5SDimitry Andric   case tok::caretequal: {
10840b57cec5SDimitry Andric     std::string ThisTok(PP.getSpelling(Tok));
10850b57cec5SDimitry Andric     if (isLetter(ThisTok[0])) {
10860b57cec5SDimitry Andric       IdentifierInfo *II = &PP.getIdentifierTable().get(ThisTok);
10870b57cec5SDimitry Andric       Tok.setKind(tok::identifier);
10880b57cec5SDimitry Andric       SelectorLoc = ConsumeToken();
10890b57cec5SDimitry Andric       return II;
10900b57cec5SDimitry Andric     }
10910b57cec5SDimitry Andric     return nullptr;
10920b57cec5SDimitry Andric   }
10930b57cec5SDimitry Andric 
10940b57cec5SDimitry Andric   case tok::identifier:
10950b57cec5SDimitry Andric   case tok::kw_asm:
10960b57cec5SDimitry Andric   case tok::kw_auto:
10970b57cec5SDimitry Andric   case tok::kw_bool:
10980b57cec5SDimitry Andric   case tok::kw_break:
10990b57cec5SDimitry Andric   case tok::kw_case:
11000b57cec5SDimitry Andric   case tok::kw_catch:
11010b57cec5SDimitry Andric   case tok::kw_char:
11020b57cec5SDimitry Andric   case tok::kw_class:
11030b57cec5SDimitry Andric   case tok::kw_const:
11040b57cec5SDimitry Andric   case tok::kw_const_cast:
11050b57cec5SDimitry Andric   case tok::kw_continue:
11060b57cec5SDimitry Andric   case tok::kw_default:
11070b57cec5SDimitry Andric   case tok::kw_delete:
11080b57cec5SDimitry Andric   case tok::kw_do:
11090b57cec5SDimitry Andric   case tok::kw_double:
11100b57cec5SDimitry Andric   case tok::kw_dynamic_cast:
11110b57cec5SDimitry Andric   case tok::kw_else:
11120b57cec5SDimitry Andric   case tok::kw_enum:
11130b57cec5SDimitry Andric   case tok::kw_explicit:
11140b57cec5SDimitry Andric   case tok::kw_export:
11150b57cec5SDimitry Andric   case tok::kw_extern:
11160b57cec5SDimitry Andric   case tok::kw_false:
11170b57cec5SDimitry Andric   case tok::kw_float:
11180b57cec5SDimitry Andric   case tok::kw_for:
11190b57cec5SDimitry Andric   case tok::kw_friend:
11200b57cec5SDimitry Andric   case tok::kw_goto:
11210b57cec5SDimitry Andric   case tok::kw_if:
11220b57cec5SDimitry Andric   case tok::kw_inline:
11230b57cec5SDimitry Andric   case tok::kw_int:
11240b57cec5SDimitry Andric   case tok::kw_long:
11250b57cec5SDimitry Andric   case tok::kw_mutable:
11260b57cec5SDimitry Andric   case tok::kw_namespace:
11270b57cec5SDimitry Andric   case tok::kw_new:
11280b57cec5SDimitry Andric   case tok::kw_operator:
11290b57cec5SDimitry Andric   case tok::kw_private:
11300b57cec5SDimitry Andric   case tok::kw_protected:
11310b57cec5SDimitry Andric   case tok::kw_public:
11320b57cec5SDimitry Andric   case tok::kw_register:
11330b57cec5SDimitry Andric   case tok::kw_reinterpret_cast:
11340b57cec5SDimitry Andric   case tok::kw_restrict:
11350b57cec5SDimitry Andric   case tok::kw_return:
11360b57cec5SDimitry Andric   case tok::kw_short:
11370b57cec5SDimitry Andric   case tok::kw_signed:
11380b57cec5SDimitry Andric   case tok::kw_sizeof:
11390b57cec5SDimitry Andric   case tok::kw_static:
11400b57cec5SDimitry Andric   case tok::kw_static_cast:
11410b57cec5SDimitry Andric   case tok::kw_struct:
11420b57cec5SDimitry Andric   case tok::kw_switch:
11430b57cec5SDimitry Andric   case tok::kw_template:
11440b57cec5SDimitry Andric   case tok::kw_this:
11450b57cec5SDimitry Andric   case tok::kw_throw:
11460b57cec5SDimitry Andric   case tok::kw_true:
11470b57cec5SDimitry Andric   case tok::kw_try:
11480b57cec5SDimitry Andric   case tok::kw_typedef:
11490b57cec5SDimitry Andric   case tok::kw_typeid:
11500b57cec5SDimitry Andric   case tok::kw_typename:
11510b57cec5SDimitry Andric   case tok::kw_typeof:
11520b57cec5SDimitry Andric   case tok::kw_union:
11530b57cec5SDimitry Andric   case tok::kw_unsigned:
11540b57cec5SDimitry Andric   case tok::kw_using:
11550b57cec5SDimitry Andric   case tok::kw_virtual:
11560b57cec5SDimitry Andric   case tok::kw_void:
11570b57cec5SDimitry Andric   case tok::kw_volatile:
11580b57cec5SDimitry Andric   case tok::kw_wchar_t:
11590b57cec5SDimitry Andric   case tok::kw_while:
11600b57cec5SDimitry Andric   case tok::kw__Bool:
11610b57cec5SDimitry Andric   case tok::kw__Complex:
11620b57cec5SDimitry Andric   case tok::kw___alignof:
11630b57cec5SDimitry Andric   case tok::kw___auto_type:
11640b57cec5SDimitry Andric     IdentifierInfo *II = Tok.getIdentifierInfo();
11650b57cec5SDimitry Andric     SelectorLoc = ConsumeToken();
11660b57cec5SDimitry Andric     return II;
11670b57cec5SDimitry Andric   }
11680b57cec5SDimitry Andric }
11690b57cec5SDimitry Andric 
11700b57cec5SDimitry Andric ///  objc-for-collection-in: 'in'
11710b57cec5SDimitry Andric ///
11720b57cec5SDimitry Andric bool Parser::isTokIdentifier_in() const {
11730b57cec5SDimitry Andric   // FIXME: May have to do additional look-ahead to only allow for
11740b57cec5SDimitry Andric   // valid tokens following an 'in'; such as an identifier, unary operators,
11750b57cec5SDimitry Andric   // '[' etc.
11760b57cec5SDimitry Andric   return (getLangOpts().ObjC && Tok.is(tok::identifier) &&
11770b57cec5SDimitry Andric           Tok.getIdentifierInfo() == ObjCTypeQuals[objc_in]);
11780b57cec5SDimitry Andric }
11790b57cec5SDimitry Andric 
11800b57cec5SDimitry Andric /// ParseObjCTypeQualifierList - This routine parses the objective-c's type
11810b57cec5SDimitry Andric /// qualifier list and builds their bitmask representation in the input
11820b57cec5SDimitry Andric /// argument.
11830b57cec5SDimitry Andric ///
11840b57cec5SDimitry Andric ///   objc-type-qualifiers:
11850b57cec5SDimitry Andric ///     objc-type-qualifier
11860b57cec5SDimitry Andric ///     objc-type-qualifiers objc-type-qualifier
11870b57cec5SDimitry Andric ///
11880b57cec5SDimitry Andric ///   objc-type-qualifier:
11890b57cec5SDimitry Andric ///     'in'
11900b57cec5SDimitry Andric ///     'out'
11910b57cec5SDimitry Andric ///     'inout'
11920b57cec5SDimitry Andric ///     'oneway'
11930b57cec5SDimitry Andric ///     'bycopy'
11940b57cec5SDimitry Andric ///     'byref'
11950b57cec5SDimitry Andric ///     'nonnull'
11960b57cec5SDimitry Andric ///     'nullable'
11970b57cec5SDimitry Andric ///     'null_unspecified'
11980b57cec5SDimitry Andric ///
11990b57cec5SDimitry Andric void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS,
12000b57cec5SDimitry Andric                                         DeclaratorContext Context) {
1201e8d8bef9SDimitry Andric   assert(Context == DeclaratorContext::ObjCParameter ||
1202e8d8bef9SDimitry Andric          Context == DeclaratorContext::ObjCResult);
12030b57cec5SDimitry Andric 
120404eeddc0SDimitry Andric   while (true) {
12050b57cec5SDimitry Andric     if (Tok.is(tok::code_completion)) {
1206fe6060f1SDimitry Andric       cutOffParsing();
1207*0fca6ea1SDimitry Andric       Actions.CodeCompletion().CodeCompleteObjCPassingType(
1208e8d8bef9SDimitry Andric           getCurScope(), DS, Context == DeclaratorContext::ObjCParameter);
1209fe6060f1SDimitry Andric       return;
12100b57cec5SDimitry Andric     }
12110b57cec5SDimitry Andric 
12120b57cec5SDimitry Andric     if (Tok.isNot(tok::identifier))
12130b57cec5SDimitry Andric       return;
12140b57cec5SDimitry Andric 
12150b57cec5SDimitry Andric     const IdentifierInfo *II = Tok.getIdentifierInfo();
12160b57cec5SDimitry Andric     for (unsigned i = 0; i != objc_NumQuals; ++i) {
12170b57cec5SDimitry Andric       if (II != ObjCTypeQuals[i] ||
12180b57cec5SDimitry Andric           NextToken().is(tok::less) ||
12190b57cec5SDimitry Andric           NextToken().is(tok::coloncolon))
12200b57cec5SDimitry Andric         continue;
12210b57cec5SDimitry Andric 
12220b57cec5SDimitry Andric       ObjCDeclSpec::ObjCDeclQualifier Qual;
12230b57cec5SDimitry Andric       NullabilityKind Nullability;
12240b57cec5SDimitry Andric       switch (i) {
12250b57cec5SDimitry Andric       default: llvm_unreachable("Unknown decl qualifier");
12260b57cec5SDimitry Andric       case objc_in:     Qual = ObjCDeclSpec::DQ_In; break;
12270b57cec5SDimitry Andric       case objc_out:    Qual = ObjCDeclSpec::DQ_Out; break;
12280b57cec5SDimitry Andric       case objc_inout:  Qual = ObjCDeclSpec::DQ_Inout; break;
12290b57cec5SDimitry Andric       case objc_oneway: Qual = ObjCDeclSpec::DQ_Oneway; break;
12300b57cec5SDimitry Andric       case objc_bycopy: Qual = ObjCDeclSpec::DQ_Bycopy; break;
12310b57cec5SDimitry Andric       case objc_byref:  Qual = ObjCDeclSpec::DQ_Byref; break;
12320b57cec5SDimitry Andric 
12330b57cec5SDimitry Andric       case objc_nonnull:
12340b57cec5SDimitry Andric         Qual = ObjCDeclSpec::DQ_CSNullability;
12350b57cec5SDimitry Andric         Nullability = NullabilityKind::NonNull;
12360b57cec5SDimitry Andric         break;
12370b57cec5SDimitry Andric 
12380b57cec5SDimitry Andric       case objc_nullable:
12390b57cec5SDimitry Andric         Qual = ObjCDeclSpec::DQ_CSNullability;
12400b57cec5SDimitry Andric         Nullability = NullabilityKind::Nullable;
12410b57cec5SDimitry Andric         break;
12420b57cec5SDimitry Andric 
12430b57cec5SDimitry Andric       case objc_null_unspecified:
12440b57cec5SDimitry Andric         Qual = ObjCDeclSpec::DQ_CSNullability;
12450b57cec5SDimitry Andric         Nullability = NullabilityKind::Unspecified;
12460b57cec5SDimitry Andric         break;
12470b57cec5SDimitry Andric       }
12480b57cec5SDimitry Andric 
12490b57cec5SDimitry Andric       // FIXME: Diagnose redundant specifiers.
12500b57cec5SDimitry Andric       DS.setObjCDeclQualifier(Qual);
12510b57cec5SDimitry Andric       if (Qual == ObjCDeclSpec::DQ_CSNullability)
12520b57cec5SDimitry Andric         DS.setNullability(Tok.getLocation(), Nullability);
12530b57cec5SDimitry Andric 
12540b57cec5SDimitry Andric       ConsumeToken();
12550b57cec5SDimitry Andric       II = nullptr;
12560b57cec5SDimitry Andric       break;
12570b57cec5SDimitry Andric     }
12580b57cec5SDimitry Andric 
12590b57cec5SDimitry Andric     // If this wasn't a recognized qualifier, bail out.
12600b57cec5SDimitry Andric     if (II) return;
12610b57cec5SDimitry Andric   }
12620b57cec5SDimitry Andric }
12630b57cec5SDimitry Andric 
12640b57cec5SDimitry Andric /// Take all the decl attributes out of the given list and add
12650b57cec5SDimitry Andric /// them to the given attribute set.
12660b57cec5SDimitry Andric static void takeDeclAttributes(ParsedAttributesView &attrs,
12670b57cec5SDimitry Andric                                ParsedAttributesView &from) {
12680b57cec5SDimitry Andric   for (auto &AL : llvm::reverse(from)) {
12690b57cec5SDimitry Andric     if (!AL.isUsedAsTypeAttr()) {
12700b57cec5SDimitry Andric       from.remove(&AL);
12710b57cec5SDimitry Andric       attrs.addAtEnd(&AL);
12720b57cec5SDimitry Andric     }
12730b57cec5SDimitry Andric   }
12740b57cec5SDimitry Andric }
12750b57cec5SDimitry Andric 
12760b57cec5SDimitry Andric /// takeDeclAttributes - Take all the decl attributes from the given
12770b57cec5SDimitry Andric /// declarator and add them to the given list.
12780b57cec5SDimitry Andric static void takeDeclAttributes(ParsedAttributes &attrs,
12790b57cec5SDimitry Andric                                Declarator &D) {
128081ad6265SDimitry Andric   // This gets called only from Parser::ParseObjCTypeName(), and that should
128181ad6265SDimitry Andric   // never add declaration attributes to the Declarator.
128281ad6265SDimitry Andric   assert(D.getDeclarationAttributes().empty());
128381ad6265SDimitry Andric 
12840b57cec5SDimitry Andric   // First, take ownership of all attributes.
12850b57cec5SDimitry Andric   attrs.getPool().takeAllFrom(D.getAttributePool());
12860b57cec5SDimitry Andric   attrs.getPool().takeAllFrom(D.getDeclSpec().getAttributePool());
12870b57cec5SDimitry Andric 
12880b57cec5SDimitry Andric   // Now actually move the attributes over.
12890b57cec5SDimitry Andric   takeDeclAttributes(attrs, D.getMutableDeclSpec().getAttributes());
12900b57cec5SDimitry Andric   takeDeclAttributes(attrs, D.getAttributes());
12910b57cec5SDimitry Andric   for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i)
12920b57cec5SDimitry Andric     takeDeclAttributes(attrs, D.getTypeObject(i).getAttrs());
12930b57cec5SDimitry Andric }
12940b57cec5SDimitry Andric 
12950b57cec5SDimitry Andric ///   objc-type-name:
12960b57cec5SDimitry Andric ///     '(' objc-type-qualifiers[opt] type-name ')'
12970b57cec5SDimitry Andric ///     '(' objc-type-qualifiers[opt] ')'
12980b57cec5SDimitry Andric ///
12990b57cec5SDimitry Andric ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS,
13000b57cec5SDimitry Andric                                      DeclaratorContext context,
13010b57cec5SDimitry Andric                                      ParsedAttributes *paramAttrs) {
1302e8d8bef9SDimitry Andric   assert(context == DeclaratorContext::ObjCParameter ||
1303e8d8bef9SDimitry Andric          context == DeclaratorContext::ObjCResult);
13040b57cec5SDimitry Andric   assert((paramAttrs != nullptr) ==
1305e8d8bef9SDimitry Andric          (context == DeclaratorContext::ObjCParameter));
13060b57cec5SDimitry Andric 
13070b57cec5SDimitry Andric   assert(Tok.is(tok::l_paren) && "expected (");
13080b57cec5SDimitry Andric 
13090b57cec5SDimitry Andric   BalancedDelimiterTracker T(*this, tok::l_paren);
13100b57cec5SDimitry Andric   T.consumeOpen();
13110b57cec5SDimitry Andric 
13120b57cec5SDimitry Andric   ObjCDeclContextSwitch ObjCDC(*this);
13130b57cec5SDimitry Andric 
13140b57cec5SDimitry Andric   // Parse type qualifiers, in, inout, etc.
13150b57cec5SDimitry Andric   ParseObjCTypeQualifierList(DS, context);
13160b57cec5SDimitry Andric   SourceLocation TypeStartLoc = Tok.getLocation();
13170b57cec5SDimitry Andric 
13180b57cec5SDimitry Andric   ParsedType Ty;
13190b57cec5SDimitry Andric   if (isTypeSpecifierQualifier() || isObjCInstancetype()) {
13200b57cec5SDimitry Andric     // Parse an abstract declarator.
13210b57cec5SDimitry Andric     DeclSpec declSpec(AttrFactory);
13220b57cec5SDimitry Andric     declSpec.setObjCQualifiers(&DS);
13230b57cec5SDimitry Andric     DeclSpecContext dsContext = DeclSpecContext::DSC_normal;
1324e8d8bef9SDimitry Andric     if (context == DeclaratorContext::ObjCResult)
13250b57cec5SDimitry Andric       dsContext = DeclSpecContext::DSC_objc_method_result;
13260b57cec5SDimitry Andric     ParseSpecifierQualifierList(declSpec, AS_none, dsContext);
132781ad6265SDimitry Andric     Declarator declarator(declSpec, ParsedAttributesView::none(), context);
13280b57cec5SDimitry Andric     ParseDeclarator(declarator);
13290b57cec5SDimitry Andric 
13300b57cec5SDimitry Andric     // If that's not invalid, extract a type.
13310b57cec5SDimitry Andric     if (!declarator.isInvalidType()) {
13320b57cec5SDimitry Andric       // Map a nullability specifier to a context-sensitive keyword attribute.
13330b57cec5SDimitry Andric       bool addedToDeclSpec = false;
13340b57cec5SDimitry Andric       if (DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability)
13350b57cec5SDimitry Andric         addContextSensitiveTypeNullability(*this, declarator,
13360b57cec5SDimitry Andric                                            DS.getNullability(),
13370b57cec5SDimitry Andric                                            DS.getNullabilityLoc(),
13380b57cec5SDimitry Andric                                            addedToDeclSpec);
13390b57cec5SDimitry Andric 
13407a6dacacSDimitry Andric       TypeResult type = Actions.ActOnTypeName(declarator);
13410b57cec5SDimitry Andric       if (!type.isInvalid())
13420b57cec5SDimitry Andric         Ty = type.get();
13430b57cec5SDimitry Andric 
13440b57cec5SDimitry Andric       // If we're parsing a parameter, steal all the decl attributes
13450b57cec5SDimitry Andric       // and add them to the decl spec.
1346e8d8bef9SDimitry Andric       if (context == DeclaratorContext::ObjCParameter)
13470b57cec5SDimitry Andric         takeDeclAttributes(*paramAttrs, declarator);
13480b57cec5SDimitry Andric     }
13490b57cec5SDimitry Andric   }
13500b57cec5SDimitry Andric 
13510b57cec5SDimitry Andric   if (Tok.is(tok::r_paren))
13520b57cec5SDimitry Andric     T.consumeClose();
13530b57cec5SDimitry Andric   else if (Tok.getLocation() == TypeStartLoc) {
13540b57cec5SDimitry Andric     // If we didn't eat any tokens, then this isn't a type.
13550b57cec5SDimitry Andric     Diag(Tok, diag::err_expected_type);
13560b57cec5SDimitry Andric     SkipUntil(tok::r_paren, StopAtSemi);
13570b57cec5SDimitry Andric   } else {
13580b57cec5SDimitry Andric     // Otherwise, we found *something*, but didn't get a ')' in the right
13590b57cec5SDimitry Andric     // place.  Emit an error then return what we have as the type.
13600b57cec5SDimitry Andric     T.consumeClose();
13610b57cec5SDimitry Andric   }
13620b57cec5SDimitry Andric   return Ty;
13630b57cec5SDimitry Andric }
13640b57cec5SDimitry Andric 
13650b57cec5SDimitry Andric ///   objc-method-decl:
13660b57cec5SDimitry Andric ///     objc-selector
13670b57cec5SDimitry Andric ///     objc-keyword-selector objc-parmlist[opt]
13680b57cec5SDimitry Andric ///     objc-type-name objc-selector
13690b57cec5SDimitry Andric ///     objc-type-name objc-keyword-selector objc-parmlist[opt]
13700b57cec5SDimitry Andric ///
13710b57cec5SDimitry Andric ///   objc-keyword-selector:
13720b57cec5SDimitry Andric ///     objc-keyword-decl
13730b57cec5SDimitry Andric ///     objc-keyword-selector objc-keyword-decl
13740b57cec5SDimitry Andric ///
13750b57cec5SDimitry Andric ///   objc-keyword-decl:
13760b57cec5SDimitry Andric ///     objc-selector ':' objc-type-name objc-keyword-attributes[opt] identifier
13770b57cec5SDimitry Andric ///     objc-selector ':' objc-keyword-attributes[opt] identifier
13780b57cec5SDimitry Andric ///     ':' objc-type-name objc-keyword-attributes[opt] identifier
13790b57cec5SDimitry Andric ///     ':' objc-keyword-attributes[opt] identifier
13800b57cec5SDimitry Andric ///
13810b57cec5SDimitry Andric ///   objc-parmlist:
13820b57cec5SDimitry Andric ///     objc-parms objc-ellipsis[opt]
13830b57cec5SDimitry Andric ///
13840b57cec5SDimitry Andric ///   objc-parms:
13850b57cec5SDimitry Andric ///     objc-parms , parameter-declaration
13860b57cec5SDimitry Andric ///
13870b57cec5SDimitry Andric ///   objc-ellipsis:
13880b57cec5SDimitry Andric ///     , ...
13890b57cec5SDimitry Andric ///
13900b57cec5SDimitry Andric ///   objc-keyword-attributes:         [OBJC2]
13910b57cec5SDimitry Andric ///     __attribute__((unused))
13920b57cec5SDimitry Andric ///
13930b57cec5SDimitry Andric Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
13940b57cec5SDimitry Andric                                   tok::TokenKind mType,
13950b57cec5SDimitry Andric                                   tok::ObjCKeywordKind MethodImplKind,
13960b57cec5SDimitry Andric                                   bool MethodDefinition) {
13970b57cec5SDimitry Andric   ParsingDeclRAIIObject PD(*this, ParsingDeclRAIIObject::NoParent);
13980b57cec5SDimitry Andric 
13990b57cec5SDimitry Andric   if (Tok.is(tok::code_completion)) {
1400fe6060f1SDimitry Andric     cutOffParsing();
1401*0fca6ea1SDimitry Andric     Actions.CodeCompletion().CodeCompleteObjCMethodDecl(getCurScope(),
1402*0fca6ea1SDimitry Andric                                                         mType == tok::minus,
14030b57cec5SDimitry Andric                                                         /*ReturnType=*/nullptr);
14040b57cec5SDimitry Andric     return nullptr;
14050b57cec5SDimitry Andric   }
14060b57cec5SDimitry Andric 
14070b57cec5SDimitry Andric   // Parse the return type if present.
14080b57cec5SDimitry Andric   ParsedType ReturnType;
14090b57cec5SDimitry Andric   ObjCDeclSpec DSRet;
14100b57cec5SDimitry Andric   if (Tok.is(tok::l_paren))
1411e8d8bef9SDimitry Andric     ReturnType =
1412e8d8bef9SDimitry Andric         ParseObjCTypeName(DSRet, DeclaratorContext::ObjCResult, nullptr);
14130b57cec5SDimitry Andric 
14140b57cec5SDimitry Andric   // If attributes exist before the method, parse them.
14150b57cec5SDimitry Andric   ParsedAttributes methodAttrs(AttrFactory);
1416fe6060f1SDimitry Andric   MaybeParseAttributes(PAKM_CXX11 | (getLangOpts().ObjC ? PAKM_GNU : 0),
1417fe6060f1SDimitry Andric                        methodAttrs);
14180b57cec5SDimitry Andric 
14190b57cec5SDimitry Andric   if (Tok.is(tok::code_completion)) {
1420fe6060f1SDimitry Andric     cutOffParsing();
1421*0fca6ea1SDimitry Andric     Actions.CodeCompletion().CodeCompleteObjCMethodDecl(
1422*0fca6ea1SDimitry Andric         getCurScope(), mType == tok::minus, ReturnType);
14230b57cec5SDimitry Andric     return nullptr;
14240b57cec5SDimitry Andric   }
14250b57cec5SDimitry Andric 
14260b57cec5SDimitry Andric   // Now parse the selector.
14270b57cec5SDimitry Andric   SourceLocation selLoc;
14280b57cec5SDimitry Andric   IdentifierInfo *SelIdent = ParseObjCSelectorPiece(selLoc);
14290b57cec5SDimitry Andric 
14300b57cec5SDimitry Andric   // An unnamed colon is valid.
14310b57cec5SDimitry Andric   if (!SelIdent && Tok.isNot(tok::colon)) { // missing selector name.
14320b57cec5SDimitry Andric     Diag(Tok, diag::err_expected_selector_for_method)
14330b57cec5SDimitry Andric       << SourceRange(mLoc, Tok.getLocation());
14340b57cec5SDimitry Andric     // Skip until we get a ; or @.
14350b57cec5SDimitry Andric     SkipUntil(tok::at, StopAtSemi | StopBeforeMatch);
14360b57cec5SDimitry Andric     return nullptr;
14370b57cec5SDimitry Andric   }
14380b57cec5SDimitry Andric 
14390b57cec5SDimitry Andric   SmallVector<DeclaratorChunk::ParamInfo, 8> CParamInfo;
14400b57cec5SDimitry Andric   if (Tok.isNot(tok::colon)) {
14410b57cec5SDimitry Andric     // If attributes exist after the method, parse them.
1442fe6060f1SDimitry Andric     MaybeParseAttributes(PAKM_CXX11 | (getLangOpts().ObjC ? PAKM_GNU : 0),
1443fe6060f1SDimitry Andric                          methodAttrs);
14440b57cec5SDimitry Andric 
14450b57cec5SDimitry Andric     Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent);
1446*0fca6ea1SDimitry Andric     Decl *Result = Actions.ObjC().ActOnMethodDeclaration(
14470b57cec5SDimitry Andric         getCurScope(), mLoc, Tok.getLocation(), mType, DSRet, ReturnType,
14480b57cec5SDimitry Andric         selLoc, Sel, nullptr, CParamInfo.data(), CParamInfo.size(), methodAttrs,
14490b57cec5SDimitry Andric         MethodImplKind, false, MethodDefinition);
14500b57cec5SDimitry Andric     PD.complete(Result);
14510b57cec5SDimitry Andric     return Result;
14520b57cec5SDimitry Andric   }
14530b57cec5SDimitry Andric 
1454*0fca6ea1SDimitry Andric   SmallVector<const IdentifierInfo *, 12> KeyIdents;
14550b57cec5SDimitry Andric   SmallVector<SourceLocation, 12> KeyLocs;
1456*0fca6ea1SDimitry Andric   SmallVector<SemaObjC::ObjCArgInfo, 12> ArgInfos;
14570b57cec5SDimitry Andric   ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope |
14580b57cec5SDimitry Andric                             Scope::FunctionDeclarationScope | Scope::DeclScope);
14590b57cec5SDimitry Andric 
14600b57cec5SDimitry Andric   AttributePool allParamAttrs(AttrFactory);
146104eeddc0SDimitry Andric   while (true) {
14620b57cec5SDimitry Andric     ParsedAttributes paramAttrs(AttrFactory);
1463*0fca6ea1SDimitry Andric     SemaObjC::ObjCArgInfo ArgInfo;
14640b57cec5SDimitry Andric 
14650b57cec5SDimitry Andric     // Each iteration parses a single keyword argument.
14660b57cec5SDimitry Andric     if (ExpectAndConsume(tok::colon))
14670b57cec5SDimitry Andric       break;
14680b57cec5SDimitry Andric 
14690b57cec5SDimitry Andric     ArgInfo.Type = nullptr;
14700b57cec5SDimitry Andric     if (Tok.is(tok::l_paren)) // Parse the argument type if present.
1471e8d8bef9SDimitry Andric       ArgInfo.Type = ParseObjCTypeName(
1472e8d8bef9SDimitry Andric           ArgInfo.DeclSpec, DeclaratorContext::ObjCParameter, &paramAttrs);
14730b57cec5SDimitry Andric 
14740b57cec5SDimitry Andric     // If attributes exist before the argument name, parse them.
14750b57cec5SDimitry Andric     // Regardless, collect all the attributes we've parsed so far.
1476fe6060f1SDimitry Andric     MaybeParseAttributes(PAKM_CXX11 | (getLangOpts().ObjC ? PAKM_GNU : 0),
1477fe6060f1SDimitry Andric                          paramAttrs);
14780b57cec5SDimitry Andric     ArgInfo.ArgAttrs = paramAttrs;
14790b57cec5SDimitry Andric 
14800b57cec5SDimitry Andric     // Code completion for the next piece of the selector.
14810b57cec5SDimitry Andric     if (Tok.is(tok::code_completion)) {
1482fe6060f1SDimitry Andric       cutOffParsing();
14830b57cec5SDimitry Andric       KeyIdents.push_back(SelIdent);
1484*0fca6ea1SDimitry Andric       Actions.CodeCompletion().CodeCompleteObjCMethodDeclSelector(
1485*0fca6ea1SDimitry Andric           getCurScope(), mType == tok::minus,
1486*0fca6ea1SDimitry Andric           /*AtParameterName=*/true, ReturnType, KeyIdents);
14870b57cec5SDimitry Andric       return nullptr;
14880b57cec5SDimitry Andric     }
14890b57cec5SDimitry Andric 
14900b57cec5SDimitry Andric     if (expectIdentifier())
14910b57cec5SDimitry Andric       break; // missing argument name.
14920b57cec5SDimitry Andric 
14930b57cec5SDimitry Andric     ArgInfo.Name = Tok.getIdentifierInfo();
14940b57cec5SDimitry Andric     ArgInfo.NameLoc = Tok.getLocation();
14950b57cec5SDimitry Andric     ConsumeToken(); // Eat the identifier.
14960b57cec5SDimitry Andric 
14970b57cec5SDimitry Andric     ArgInfos.push_back(ArgInfo);
14980b57cec5SDimitry Andric     KeyIdents.push_back(SelIdent);
14990b57cec5SDimitry Andric     KeyLocs.push_back(selLoc);
15000b57cec5SDimitry Andric 
15010b57cec5SDimitry Andric     // Make sure the attributes persist.
15020b57cec5SDimitry Andric     allParamAttrs.takeAllFrom(paramAttrs.getPool());
15030b57cec5SDimitry Andric 
15040b57cec5SDimitry Andric     // Code completion for the next piece of the selector.
15050b57cec5SDimitry Andric     if (Tok.is(tok::code_completion)) {
1506fe6060f1SDimitry Andric       cutOffParsing();
1507*0fca6ea1SDimitry Andric       Actions.CodeCompletion().CodeCompleteObjCMethodDeclSelector(
1508*0fca6ea1SDimitry Andric           getCurScope(), mType == tok::minus,
1509*0fca6ea1SDimitry Andric           /*AtParameterName=*/false, ReturnType, KeyIdents);
15100b57cec5SDimitry Andric       return nullptr;
15110b57cec5SDimitry Andric     }
15120b57cec5SDimitry Andric 
15130b57cec5SDimitry Andric     // Check for another keyword selector.
15140b57cec5SDimitry Andric     SelIdent = ParseObjCSelectorPiece(selLoc);
15150b57cec5SDimitry Andric     if (!SelIdent && Tok.isNot(tok::colon))
15160b57cec5SDimitry Andric       break;
15170b57cec5SDimitry Andric     if (!SelIdent) {
15180b57cec5SDimitry Andric       SourceLocation ColonLoc = Tok.getLocation();
15190b57cec5SDimitry Andric       if (PP.getLocForEndOfToken(ArgInfo.NameLoc) == ColonLoc) {
15200b57cec5SDimitry Andric         Diag(ArgInfo.NameLoc, diag::warn_missing_selector_name) << ArgInfo.Name;
15210b57cec5SDimitry Andric         Diag(ArgInfo.NameLoc, diag::note_missing_selector_name) << ArgInfo.Name;
15220b57cec5SDimitry Andric         Diag(ColonLoc, diag::note_force_empty_selector_name) << ArgInfo.Name;
15230b57cec5SDimitry Andric       }
15240b57cec5SDimitry Andric     }
15250b57cec5SDimitry Andric     // We have a selector or a colon, continue parsing.
15260b57cec5SDimitry Andric   }
15270b57cec5SDimitry Andric 
15280b57cec5SDimitry Andric   bool isVariadic = false;
15290b57cec5SDimitry Andric   bool cStyleParamWarned = false;
15300b57cec5SDimitry Andric   // Parse the (optional) parameter list.
15310b57cec5SDimitry Andric   while (Tok.is(tok::comma)) {
15320b57cec5SDimitry Andric     ConsumeToken();
15330b57cec5SDimitry Andric     if (Tok.is(tok::ellipsis)) {
15340b57cec5SDimitry Andric       isVariadic = true;
15350b57cec5SDimitry Andric       ConsumeToken();
15360b57cec5SDimitry Andric       break;
15370b57cec5SDimitry Andric     }
15380b57cec5SDimitry Andric     if (!cStyleParamWarned) {
15390b57cec5SDimitry Andric       Diag(Tok, diag::warn_cstyle_param);
15400b57cec5SDimitry Andric       cStyleParamWarned = true;
15410b57cec5SDimitry Andric     }
15420b57cec5SDimitry Andric     DeclSpec DS(AttrFactory);
1543*0fca6ea1SDimitry Andric     ParsedTemplateInfo TemplateInfo;
1544*0fca6ea1SDimitry Andric     ParseDeclarationSpecifiers(DS, TemplateInfo);
15450b57cec5SDimitry Andric     // Parse the declarator.
154681ad6265SDimitry Andric     Declarator ParmDecl(DS, ParsedAttributesView::none(),
154781ad6265SDimitry Andric                         DeclaratorContext::Prototype);
15480b57cec5SDimitry Andric     ParseDeclarator(ParmDecl);
1549*0fca6ea1SDimitry Andric     const IdentifierInfo *ParmII = ParmDecl.getIdentifier();
15500b57cec5SDimitry Andric     Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDecl);
15510b57cec5SDimitry Andric     CParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,
15520b57cec5SDimitry Andric                                                     ParmDecl.getIdentifierLoc(),
15530b57cec5SDimitry Andric                                                     Param,
15540b57cec5SDimitry Andric                                                     nullptr));
15550b57cec5SDimitry Andric   }
15560b57cec5SDimitry Andric 
15570b57cec5SDimitry Andric   // FIXME: Add support for optional parameter list...
15580b57cec5SDimitry Andric   // If attributes exist after the method, parse them.
1559fe6060f1SDimitry Andric   MaybeParseAttributes(PAKM_CXX11 | (getLangOpts().ObjC ? PAKM_GNU : 0),
1560fe6060f1SDimitry Andric                        methodAttrs);
15610b57cec5SDimitry Andric 
15620b57cec5SDimitry Andric   if (KeyIdents.size() == 0)
15630b57cec5SDimitry Andric     return nullptr;
15640b57cec5SDimitry Andric 
15650b57cec5SDimitry Andric   Selector Sel = PP.getSelectorTable().getSelector(KeyIdents.size(),
15660b57cec5SDimitry Andric                                                    &KeyIdents[0]);
1567*0fca6ea1SDimitry Andric   Decl *Result = Actions.ObjC().ActOnMethodDeclaration(
15680b57cec5SDimitry Andric       getCurScope(), mLoc, Tok.getLocation(), mType, DSRet, ReturnType, KeyLocs,
15690b57cec5SDimitry Andric       Sel, &ArgInfos[0], CParamInfo.data(), CParamInfo.size(), methodAttrs,
15700b57cec5SDimitry Andric       MethodImplKind, isVariadic, MethodDefinition);
15710b57cec5SDimitry Andric 
15720b57cec5SDimitry Andric   PD.complete(Result);
15730b57cec5SDimitry Andric   return Result;
15740b57cec5SDimitry Andric }
15750b57cec5SDimitry Andric 
15760b57cec5SDimitry Andric ///   objc-protocol-refs:
15770b57cec5SDimitry Andric ///     '<' identifier-list '>'
15780b57cec5SDimitry Andric ///
15790b57cec5SDimitry Andric bool Parser::
15800b57cec5SDimitry Andric ParseObjCProtocolReferences(SmallVectorImpl<Decl *> &Protocols,
15810b57cec5SDimitry Andric                             SmallVectorImpl<SourceLocation> &ProtocolLocs,
15820b57cec5SDimitry Andric                             bool WarnOnDeclarations, bool ForObjCContainer,
15830b57cec5SDimitry Andric                             SourceLocation &LAngleLoc, SourceLocation &EndLoc,
15840b57cec5SDimitry Andric                             bool consumeLastToken) {
15850b57cec5SDimitry Andric   assert(Tok.is(tok::less) && "expected <");
15860b57cec5SDimitry Andric 
15870b57cec5SDimitry Andric   LAngleLoc = ConsumeToken(); // the "<"
15880b57cec5SDimitry Andric 
15890b57cec5SDimitry Andric   SmallVector<IdentifierLocPair, 8> ProtocolIdents;
15900b57cec5SDimitry Andric 
159104eeddc0SDimitry Andric   while (true) {
15920b57cec5SDimitry Andric     if (Tok.is(tok::code_completion)) {
15930b57cec5SDimitry Andric       cutOffParsing();
1594*0fca6ea1SDimitry Andric       Actions.CodeCompletion().CodeCompleteObjCProtocolReferences(
1595*0fca6ea1SDimitry Andric           ProtocolIdents);
15960b57cec5SDimitry Andric       return true;
15970b57cec5SDimitry Andric     }
15980b57cec5SDimitry Andric 
15990b57cec5SDimitry Andric     if (expectIdentifier()) {
16000b57cec5SDimitry Andric       SkipUntil(tok::greater, StopAtSemi);
16010b57cec5SDimitry Andric       return true;
16020b57cec5SDimitry Andric     }
16030b57cec5SDimitry Andric     ProtocolIdents.push_back(std::make_pair(Tok.getIdentifierInfo(),
16040b57cec5SDimitry Andric                                        Tok.getLocation()));
16050b57cec5SDimitry Andric     ProtocolLocs.push_back(Tok.getLocation());
16060b57cec5SDimitry Andric     ConsumeToken();
16070b57cec5SDimitry Andric 
16080b57cec5SDimitry Andric     if (!TryConsumeToken(tok::comma))
16090b57cec5SDimitry Andric       break;
16100b57cec5SDimitry Andric   }
16110b57cec5SDimitry Andric 
16120b57cec5SDimitry Andric   // Consume the '>'.
16135ffd83dbSDimitry Andric   if (ParseGreaterThanInTemplateList(LAngleLoc, EndLoc, consumeLastToken,
16140b57cec5SDimitry Andric                                      /*ObjCGenericList=*/false))
16150b57cec5SDimitry Andric     return true;
16160b57cec5SDimitry Andric 
16170b57cec5SDimitry Andric   // Convert the list of protocols identifiers into a list of protocol decls.
1618*0fca6ea1SDimitry Andric   Actions.ObjC().FindProtocolDeclaration(WarnOnDeclarations, ForObjCContainer,
16190b57cec5SDimitry Andric                                          ProtocolIdents, Protocols);
16200b57cec5SDimitry Andric   return false;
16210b57cec5SDimitry Andric }
16220b57cec5SDimitry Andric 
16230b57cec5SDimitry Andric TypeResult Parser::parseObjCProtocolQualifierType(SourceLocation &rAngleLoc) {
16240b57cec5SDimitry Andric   assert(Tok.is(tok::less) && "Protocol qualifiers start with '<'");
16250b57cec5SDimitry Andric   assert(getLangOpts().ObjC && "Protocol qualifiers only exist in Objective-C");
16260b57cec5SDimitry Andric 
16270b57cec5SDimitry Andric   SourceLocation lAngleLoc;
16280b57cec5SDimitry Andric   SmallVector<Decl *, 8> protocols;
16290b57cec5SDimitry Andric   SmallVector<SourceLocation, 8> protocolLocs;
16300b57cec5SDimitry Andric   (void)ParseObjCProtocolReferences(protocols, protocolLocs, false, false,
16310b57cec5SDimitry Andric                                     lAngleLoc, rAngleLoc,
16320b57cec5SDimitry Andric                                     /*consumeLastToken=*/true);
1633*0fca6ea1SDimitry Andric   TypeResult result = Actions.ObjC().actOnObjCProtocolQualifierType(
1634*0fca6ea1SDimitry Andric       lAngleLoc, protocols, protocolLocs, rAngleLoc);
16350b57cec5SDimitry Andric   if (result.isUsable()) {
16360b57cec5SDimitry Andric     Diag(lAngleLoc, diag::warn_objc_protocol_qualifier_missing_id)
16370b57cec5SDimitry Andric       << FixItHint::CreateInsertion(lAngleLoc, "id")
16380b57cec5SDimitry Andric       << SourceRange(lAngleLoc, rAngleLoc);
16390b57cec5SDimitry Andric   }
16400b57cec5SDimitry Andric 
16410b57cec5SDimitry Andric   return result;
16420b57cec5SDimitry Andric }
16430b57cec5SDimitry Andric 
16440b57cec5SDimitry Andric /// Parse Objective-C type arguments or protocol qualifiers.
16450b57cec5SDimitry Andric ///
16460b57cec5SDimitry Andric ///   objc-type-arguments:
16470b57cec5SDimitry Andric ///     '<' type-name '...'[opt] (',' type-name '...'[opt])* '>'
16480b57cec5SDimitry Andric ///
16490b57cec5SDimitry Andric void Parser::parseObjCTypeArgsOrProtocolQualifiers(
16500b57cec5SDimitry Andric        ParsedType baseType,
16510b57cec5SDimitry Andric        SourceLocation &typeArgsLAngleLoc,
16520b57cec5SDimitry Andric        SmallVectorImpl<ParsedType> &typeArgs,
16530b57cec5SDimitry Andric        SourceLocation &typeArgsRAngleLoc,
16540b57cec5SDimitry Andric        SourceLocation &protocolLAngleLoc,
16550b57cec5SDimitry Andric        SmallVectorImpl<Decl *> &protocols,
16560b57cec5SDimitry Andric        SmallVectorImpl<SourceLocation> &protocolLocs,
16570b57cec5SDimitry Andric        SourceLocation &protocolRAngleLoc,
16580b57cec5SDimitry Andric        bool consumeLastToken,
16590b57cec5SDimitry Andric        bool warnOnIncompleteProtocols) {
16600b57cec5SDimitry Andric   assert(Tok.is(tok::less) && "Not at the start of type args or protocols");
16610b57cec5SDimitry Andric   SourceLocation lAngleLoc = ConsumeToken();
16620b57cec5SDimitry Andric 
16630b57cec5SDimitry Andric   // Whether all of the elements we've parsed thus far are single
16640b57cec5SDimitry Andric   // identifiers, which might be types or might be protocols.
16650b57cec5SDimitry Andric   bool allSingleIdentifiers = true;
16660b57cec5SDimitry Andric   SmallVector<IdentifierInfo *, 4> identifiers;
16670b57cec5SDimitry Andric   SmallVectorImpl<SourceLocation> &identifierLocs = protocolLocs;
16680b57cec5SDimitry Andric 
16690b57cec5SDimitry Andric   // Parse a list of comma-separated identifiers, bailing out if we
16700b57cec5SDimitry Andric   // see something different.
16710b57cec5SDimitry Andric   do {
16720b57cec5SDimitry Andric     // Parse a single identifier.
16730b57cec5SDimitry Andric     if (Tok.is(tok::identifier) &&
16740b57cec5SDimitry Andric         (NextToken().is(tok::comma) ||
16750b57cec5SDimitry Andric          NextToken().is(tok::greater) ||
16760b57cec5SDimitry Andric          NextToken().is(tok::greatergreater))) {
16770b57cec5SDimitry Andric       identifiers.push_back(Tok.getIdentifierInfo());
16780b57cec5SDimitry Andric       identifierLocs.push_back(ConsumeToken());
16790b57cec5SDimitry Andric       continue;
16800b57cec5SDimitry Andric     }
16810b57cec5SDimitry Andric 
16820b57cec5SDimitry Andric     if (Tok.is(tok::code_completion)) {
16830b57cec5SDimitry Andric       // FIXME: Also include types here.
16840b57cec5SDimitry Andric       SmallVector<IdentifierLocPair, 4> identifierLocPairs;
16850b57cec5SDimitry Andric       for (unsigned i = 0, n = identifiers.size(); i != n; ++i) {
16860b57cec5SDimitry Andric         identifierLocPairs.push_back(IdentifierLocPair(identifiers[i],
16870b57cec5SDimitry Andric                                                        identifierLocs[i]));
16880b57cec5SDimitry Andric       }
16890b57cec5SDimitry Andric 
16900b57cec5SDimitry Andric       QualType BaseT = Actions.GetTypeFromParser(baseType);
1691fe6060f1SDimitry Andric       cutOffParsing();
16920b57cec5SDimitry Andric       if (!BaseT.isNull() && BaseT->acceptsObjCTypeParams()) {
1693*0fca6ea1SDimitry Andric         Actions.CodeCompletion().CodeCompleteOrdinaryName(
1694*0fca6ea1SDimitry Andric             getCurScope(), SemaCodeCompletion::PCC_Type);
16950b57cec5SDimitry Andric       } else {
1696*0fca6ea1SDimitry Andric         Actions.CodeCompletion().CodeCompleteObjCProtocolReferences(
1697*0fca6ea1SDimitry Andric             identifierLocPairs);
16980b57cec5SDimitry Andric       }
16990b57cec5SDimitry Andric       return;
17000b57cec5SDimitry Andric     }
17010b57cec5SDimitry Andric 
17020b57cec5SDimitry Andric     allSingleIdentifiers = false;
17030b57cec5SDimitry Andric     break;
17040b57cec5SDimitry Andric   } while (TryConsumeToken(tok::comma));
17050b57cec5SDimitry Andric 
17060b57cec5SDimitry Andric   // If we parsed an identifier list, semantic analysis sorts out
17070b57cec5SDimitry Andric   // whether it refers to protocols or to type arguments.
17080b57cec5SDimitry Andric   if (allSingleIdentifiers) {
17090b57cec5SDimitry Andric     // Parse the closing '>'.
17100b57cec5SDimitry Andric     SourceLocation rAngleLoc;
17115ffd83dbSDimitry Andric     (void)ParseGreaterThanInTemplateList(lAngleLoc, rAngleLoc, consumeLastToken,
17120b57cec5SDimitry Andric                                          /*ObjCGenericList=*/true);
17130b57cec5SDimitry Andric 
17140b57cec5SDimitry Andric     // Let Sema figure out what we parsed.
1715*0fca6ea1SDimitry Andric     Actions.ObjC().actOnObjCTypeArgsOrProtocolQualifiers(
1716*0fca6ea1SDimitry Andric         getCurScope(), baseType, lAngleLoc, identifiers, identifierLocs,
1717*0fca6ea1SDimitry Andric         rAngleLoc, typeArgsLAngleLoc, typeArgs, typeArgsRAngleLoc,
1718*0fca6ea1SDimitry Andric         protocolLAngleLoc, protocols, protocolRAngleLoc,
17190b57cec5SDimitry Andric         warnOnIncompleteProtocols);
17200b57cec5SDimitry Andric     return;
17210b57cec5SDimitry Andric   }
17220b57cec5SDimitry Andric 
17230b57cec5SDimitry Andric   // We parsed an identifier list but stumbled into non single identifiers, this
17240b57cec5SDimitry Andric   // means we might (a) check that what we already parsed is a legitimate type
17250b57cec5SDimitry Andric   // (not a protocol or unknown type) and (b) parse the remaining ones, which
17260b57cec5SDimitry Andric   // must all be type args.
17270b57cec5SDimitry Andric 
17280b57cec5SDimitry Andric   // Convert the identifiers into type arguments.
17290b57cec5SDimitry Andric   bool invalid = false;
17300b57cec5SDimitry Andric   IdentifierInfo *foundProtocolId = nullptr, *foundValidTypeId = nullptr;
17310b57cec5SDimitry Andric   SourceLocation foundProtocolSrcLoc, foundValidTypeSrcLoc;
17320b57cec5SDimitry Andric   SmallVector<IdentifierInfo *, 2> unknownTypeArgs;
17330b57cec5SDimitry Andric   SmallVector<SourceLocation, 2> unknownTypeArgsLoc;
17340b57cec5SDimitry Andric 
17350b57cec5SDimitry Andric   for (unsigned i = 0, n = identifiers.size(); i != n; ++i) {
17360b57cec5SDimitry Andric     ParsedType typeArg
17370b57cec5SDimitry Andric       = Actions.getTypeName(*identifiers[i], identifierLocs[i], getCurScope());
17380b57cec5SDimitry Andric     if (typeArg) {
17390b57cec5SDimitry Andric       DeclSpec DS(AttrFactory);
17400b57cec5SDimitry Andric       const char *prevSpec = nullptr;
17410b57cec5SDimitry Andric       unsigned diagID;
17420b57cec5SDimitry Andric       DS.SetTypeSpecType(TST_typename, identifierLocs[i], prevSpec, diagID,
17430b57cec5SDimitry Andric                          typeArg, Actions.getASTContext().getPrintingPolicy());
17440b57cec5SDimitry Andric 
17450b57cec5SDimitry Andric       // Form a declarator to turn this into a type.
174681ad6265SDimitry Andric       Declarator D(DS, ParsedAttributesView::none(),
174781ad6265SDimitry Andric                    DeclaratorContext::TypeName);
17487a6dacacSDimitry Andric       TypeResult fullTypeArg = Actions.ActOnTypeName(D);
17490b57cec5SDimitry Andric       if (fullTypeArg.isUsable()) {
17500b57cec5SDimitry Andric         typeArgs.push_back(fullTypeArg.get());
17510b57cec5SDimitry Andric         if (!foundValidTypeId) {
17520b57cec5SDimitry Andric           foundValidTypeId = identifiers[i];
17530b57cec5SDimitry Andric           foundValidTypeSrcLoc = identifierLocs[i];
17540b57cec5SDimitry Andric         }
17550b57cec5SDimitry Andric       } else {
17560b57cec5SDimitry Andric         invalid = true;
17570b57cec5SDimitry Andric         unknownTypeArgs.push_back(identifiers[i]);
17580b57cec5SDimitry Andric         unknownTypeArgsLoc.push_back(identifierLocs[i]);
17590b57cec5SDimitry Andric       }
17600b57cec5SDimitry Andric     } else {
17610b57cec5SDimitry Andric       invalid = true;
1762*0fca6ea1SDimitry Andric       if (!Actions.ObjC().LookupProtocol(identifiers[i], identifierLocs[i])) {
17630b57cec5SDimitry Andric         unknownTypeArgs.push_back(identifiers[i]);
17640b57cec5SDimitry Andric         unknownTypeArgsLoc.push_back(identifierLocs[i]);
17650b57cec5SDimitry Andric       } else if (!foundProtocolId) {
17660b57cec5SDimitry Andric         foundProtocolId = identifiers[i];
17670b57cec5SDimitry Andric         foundProtocolSrcLoc = identifierLocs[i];
17680b57cec5SDimitry Andric       }
17690b57cec5SDimitry Andric     }
17700b57cec5SDimitry Andric   }
17710b57cec5SDimitry Andric 
17720b57cec5SDimitry Andric   // Continue parsing type-names.
17730b57cec5SDimitry Andric   do {
17740b57cec5SDimitry Andric     Token CurTypeTok = Tok;
17750b57cec5SDimitry Andric     TypeResult typeArg = ParseTypeName();
17760b57cec5SDimitry Andric 
17770b57cec5SDimitry Andric     // Consume the '...' for a pack expansion.
17780b57cec5SDimitry Andric     SourceLocation ellipsisLoc;
17790b57cec5SDimitry Andric     TryConsumeToken(tok::ellipsis, ellipsisLoc);
17800b57cec5SDimitry Andric     if (typeArg.isUsable() && ellipsisLoc.isValid()) {
17810b57cec5SDimitry Andric       typeArg = Actions.ActOnPackExpansion(typeArg.get(), ellipsisLoc);
17820b57cec5SDimitry Andric     }
17830b57cec5SDimitry Andric 
17840b57cec5SDimitry Andric     if (typeArg.isUsable()) {
17850b57cec5SDimitry Andric       typeArgs.push_back(typeArg.get());
17860b57cec5SDimitry Andric       if (!foundValidTypeId) {
17870b57cec5SDimitry Andric         foundValidTypeId = CurTypeTok.getIdentifierInfo();
17880b57cec5SDimitry Andric         foundValidTypeSrcLoc = CurTypeTok.getLocation();
17890b57cec5SDimitry Andric       }
17900b57cec5SDimitry Andric     } else {
17910b57cec5SDimitry Andric       invalid = true;
17920b57cec5SDimitry Andric     }
17930b57cec5SDimitry Andric   } while (TryConsumeToken(tok::comma));
17940b57cec5SDimitry Andric 
17950b57cec5SDimitry Andric   // Diagnose the mix between type args and protocols.
17960b57cec5SDimitry Andric   if (foundProtocolId && foundValidTypeId)
1797*0fca6ea1SDimitry Andric     Actions.ObjC().DiagnoseTypeArgsAndProtocols(
1798*0fca6ea1SDimitry Andric         foundProtocolId, foundProtocolSrcLoc, foundValidTypeId,
17990b57cec5SDimitry Andric         foundValidTypeSrcLoc);
18000b57cec5SDimitry Andric 
18010b57cec5SDimitry Andric   // Diagnose unknown arg types.
18020b57cec5SDimitry Andric   ParsedType T;
18030b57cec5SDimitry Andric   if (unknownTypeArgs.size())
18040b57cec5SDimitry Andric     for (unsigned i = 0, e = unknownTypeArgsLoc.size(); i < e; ++i)
18050b57cec5SDimitry Andric       Actions.DiagnoseUnknownTypeName(unknownTypeArgs[i], unknownTypeArgsLoc[i],
18060b57cec5SDimitry Andric                                       getCurScope(), nullptr, T);
18070b57cec5SDimitry Andric 
18080b57cec5SDimitry Andric   // Parse the closing '>'.
18090b57cec5SDimitry Andric   SourceLocation rAngleLoc;
18105ffd83dbSDimitry Andric   (void)ParseGreaterThanInTemplateList(lAngleLoc, rAngleLoc, consumeLastToken,
18110b57cec5SDimitry Andric                                        /*ObjCGenericList=*/true);
18120b57cec5SDimitry Andric 
18130b57cec5SDimitry Andric   if (invalid) {
18140b57cec5SDimitry Andric     typeArgs.clear();
18150b57cec5SDimitry Andric     return;
18160b57cec5SDimitry Andric   }
18170b57cec5SDimitry Andric 
18180b57cec5SDimitry Andric   // Record left/right angle locations.
18190b57cec5SDimitry Andric   typeArgsLAngleLoc = lAngleLoc;
18200b57cec5SDimitry Andric   typeArgsRAngleLoc = rAngleLoc;
18210b57cec5SDimitry Andric }
18220b57cec5SDimitry Andric 
18230b57cec5SDimitry Andric void Parser::parseObjCTypeArgsAndProtocolQualifiers(
18240b57cec5SDimitry Andric        ParsedType baseType,
18250b57cec5SDimitry Andric        SourceLocation &typeArgsLAngleLoc,
18260b57cec5SDimitry Andric        SmallVectorImpl<ParsedType> &typeArgs,
18270b57cec5SDimitry Andric        SourceLocation &typeArgsRAngleLoc,
18280b57cec5SDimitry Andric        SourceLocation &protocolLAngleLoc,
18290b57cec5SDimitry Andric        SmallVectorImpl<Decl *> &protocols,
18300b57cec5SDimitry Andric        SmallVectorImpl<SourceLocation> &protocolLocs,
18310b57cec5SDimitry Andric        SourceLocation &protocolRAngleLoc,
18320b57cec5SDimitry Andric        bool consumeLastToken) {
18330b57cec5SDimitry Andric   assert(Tok.is(tok::less));
18340b57cec5SDimitry Andric 
18350b57cec5SDimitry Andric   // Parse the first angle-bracket-delimited clause.
18360b57cec5SDimitry Andric   parseObjCTypeArgsOrProtocolQualifiers(baseType,
18370b57cec5SDimitry Andric                                         typeArgsLAngleLoc,
18380b57cec5SDimitry Andric                                         typeArgs,
18390b57cec5SDimitry Andric                                         typeArgsRAngleLoc,
18400b57cec5SDimitry Andric                                         protocolLAngleLoc,
18410b57cec5SDimitry Andric                                         protocols,
18420b57cec5SDimitry Andric                                         protocolLocs,
18430b57cec5SDimitry Andric                                         protocolRAngleLoc,
18440b57cec5SDimitry Andric                                         consumeLastToken,
18450b57cec5SDimitry Andric                                         /*warnOnIncompleteProtocols=*/false);
18460b57cec5SDimitry Andric   if (Tok.is(tok::eof)) // Nothing else to do here...
18470b57cec5SDimitry Andric     return;
18480b57cec5SDimitry Andric 
18490b57cec5SDimitry Andric   // An Objective-C object pointer followed by type arguments
18500b57cec5SDimitry Andric   // can then be followed again by a set of protocol references, e.g.,
18510b57cec5SDimitry Andric   // \c NSArray<NSView><NSTextDelegate>
18520b57cec5SDimitry Andric   if ((consumeLastToken && Tok.is(tok::less)) ||
18530b57cec5SDimitry Andric       (!consumeLastToken && NextToken().is(tok::less))) {
18540b57cec5SDimitry Andric     // If we aren't consuming the last token, the prior '>' is still hanging
18550b57cec5SDimitry Andric     // there. Consume it before we parse the protocol qualifiers.
18560b57cec5SDimitry Andric     if (!consumeLastToken)
18570b57cec5SDimitry Andric       ConsumeToken();
18580b57cec5SDimitry Andric 
18590b57cec5SDimitry Andric     if (!protocols.empty()) {
18600b57cec5SDimitry Andric       SkipUntilFlags skipFlags = SkipUntilFlags();
18610b57cec5SDimitry Andric       if (!consumeLastToken)
18620b57cec5SDimitry Andric         skipFlags = skipFlags | StopBeforeMatch;
18630b57cec5SDimitry Andric       Diag(Tok, diag::err_objc_type_args_after_protocols)
18640b57cec5SDimitry Andric         << SourceRange(protocolLAngleLoc, protocolRAngleLoc);
18650b57cec5SDimitry Andric       SkipUntil(tok::greater, tok::greatergreater, skipFlags);
18660b57cec5SDimitry Andric     } else {
18670b57cec5SDimitry Andric       ParseObjCProtocolReferences(protocols, protocolLocs,
18680b57cec5SDimitry Andric                                   /*WarnOnDeclarations=*/false,
18690b57cec5SDimitry Andric                                   /*ForObjCContainer=*/false,
18700b57cec5SDimitry Andric                                   protocolLAngleLoc, protocolRAngleLoc,
18710b57cec5SDimitry Andric                                   consumeLastToken);
18720b57cec5SDimitry Andric     }
18730b57cec5SDimitry Andric   }
18740b57cec5SDimitry Andric }
18750b57cec5SDimitry Andric 
18760b57cec5SDimitry Andric TypeResult Parser::parseObjCTypeArgsAndProtocolQualifiers(
18770b57cec5SDimitry Andric              SourceLocation loc,
18780b57cec5SDimitry Andric              ParsedType type,
18790b57cec5SDimitry Andric              bool consumeLastToken,
18800b57cec5SDimitry Andric              SourceLocation &endLoc) {
18810b57cec5SDimitry Andric   assert(Tok.is(tok::less));
18820b57cec5SDimitry Andric   SourceLocation typeArgsLAngleLoc;
18830b57cec5SDimitry Andric   SmallVector<ParsedType, 4> typeArgs;
18840b57cec5SDimitry Andric   SourceLocation typeArgsRAngleLoc;
18850b57cec5SDimitry Andric   SourceLocation protocolLAngleLoc;
18860b57cec5SDimitry Andric   SmallVector<Decl *, 4> protocols;
18870b57cec5SDimitry Andric   SmallVector<SourceLocation, 4> protocolLocs;
18880b57cec5SDimitry Andric   SourceLocation protocolRAngleLoc;
18890b57cec5SDimitry Andric 
18900b57cec5SDimitry Andric   // Parse type arguments and protocol qualifiers.
18910b57cec5SDimitry Andric   parseObjCTypeArgsAndProtocolQualifiers(type, typeArgsLAngleLoc, typeArgs,
18920b57cec5SDimitry Andric                                          typeArgsRAngleLoc, protocolLAngleLoc,
18930b57cec5SDimitry Andric                                          protocols, protocolLocs,
18940b57cec5SDimitry Andric                                          protocolRAngleLoc, consumeLastToken);
18950b57cec5SDimitry Andric 
18960b57cec5SDimitry Andric   if (Tok.is(tok::eof))
18970b57cec5SDimitry Andric     return true; // Invalid type result.
18980b57cec5SDimitry Andric 
18990b57cec5SDimitry Andric   // Compute the location of the last token.
19000b57cec5SDimitry Andric   if (consumeLastToken)
19010b57cec5SDimitry Andric     endLoc = PrevTokLocation;
19020b57cec5SDimitry Andric   else
19030b57cec5SDimitry Andric     endLoc = Tok.getLocation();
19040b57cec5SDimitry Andric 
1905*0fca6ea1SDimitry Andric   return Actions.ObjC().actOnObjCTypeArgsAndProtocolQualifiers(
1906*0fca6ea1SDimitry Andric       getCurScope(), loc, type, typeArgsLAngleLoc, typeArgs, typeArgsRAngleLoc,
1907*0fca6ea1SDimitry Andric       protocolLAngleLoc, protocols, protocolLocs, protocolRAngleLoc);
19080b57cec5SDimitry Andric }
19090b57cec5SDimitry Andric 
191081ad6265SDimitry Andric void Parser::HelperActionsForIvarDeclarations(
191181ad6265SDimitry Andric     ObjCContainerDecl *interfaceDecl, SourceLocation atLoc,
191281ad6265SDimitry Andric     BalancedDelimiterTracker &T, SmallVectorImpl<Decl *> &AllIvarDecls,
19130b57cec5SDimitry Andric     bool RBraceMissing) {
19140b57cec5SDimitry Andric   if (!RBraceMissing)
19150b57cec5SDimitry Andric     T.consumeClose();
19160b57cec5SDimitry Andric 
191781ad6265SDimitry Andric   assert(getObjCDeclContext() == interfaceDecl &&
191881ad6265SDimitry Andric          "Ivars should have interfaceDecl as their decl context");
19190b57cec5SDimitry Andric   Actions.ActOnLastBitfield(T.getCloseLocation(), AllIvarDecls);
19200b57cec5SDimitry Andric   // Call ActOnFields() even if we don't have any decls. This is useful
19210b57cec5SDimitry Andric   // for code rewriting tools that need to be aware of the empty list.
19220b57cec5SDimitry Andric   Actions.ActOnFields(getCurScope(), atLoc, interfaceDecl, AllIvarDecls,
19230b57cec5SDimitry Andric                       T.getOpenLocation(), T.getCloseLocation(),
19240b57cec5SDimitry Andric                       ParsedAttributesView());
19250b57cec5SDimitry Andric }
19260b57cec5SDimitry Andric 
19270b57cec5SDimitry Andric ///   objc-class-instance-variables:
19280b57cec5SDimitry Andric ///     '{' objc-instance-variable-decl-list[opt] '}'
19290b57cec5SDimitry Andric ///
19300b57cec5SDimitry Andric ///   objc-instance-variable-decl-list:
19310b57cec5SDimitry Andric ///     objc-visibility-spec
19320b57cec5SDimitry Andric ///     objc-instance-variable-decl ';'
19330b57cec5SDimitry Andric ///     ';'
19340b57cec5SDimitry Andric ///     objc-instance-variable-decl-list objc-visibility-spec
19350b57cec5SDimitry Andric ///     objc-instance-variable-decl-list objc-instance-variable-decl ';'
19360b57cec5SDimitry Andric ///     objc-instance-variable-decl-list static_assert-declaration
19370b57cec5SDimitry Andric ///     objc-instance-variable-decl-list ';'
19380b57cec5SDimitry Andric ///
19390b57cec5SDimitry Andric ///   objc-visibility-spec:
19400b57cec5SDimitry Andric ///     @private
19410b57cec5SDimitry Andric ///     @protected
19420b57cec5SDimitry Andric ///     @public
19430b57cec5SDimitry Andric ///     @package [OBJC2]
19440b57cec5SDimitry Andric ///
19450b57cec5SDimitry Andric ///   objc-instance-variable-decl:
19460b57cec5SDimitry Andric ///     struct-declaration
19470b57cec5SDimitry Andric ///
194881ad6265SDimitry Andric void Parser::ParseObjCClassInstanceVariables(ObjCContainerDecl *interfaceDecl,
19490b57cec5SDimitry Andric                                              tok::ObjCKeywordKind visibility,
19500b57cec5SDimitry Andric                                              SourceLocation atLoc) {
19510b57cec5SDimitry Andric   assert(Tok.is(tok::l_brace) && "expected {");
19520b57cec5SDimitry Andric   SmallVector<Decl *, 32> AllIvarDecls;
19530b57cec5SDimitry Andric 
19540b57cec5SDimitry Andric   ParseScope ClassScope(this, Scope::DeclScope | Scope::ClassScope);
19550b57cec5SDimitry Andric 
19560b57cec5SDimitry Andric   BalancedDelimiterTracker T(*this, tok::l_brace);
19570b57cec5SDimitry Andric   T.consumeOpen();
19580b57cec5SDimitry Andric   // While we still have something to read, read the instance variables.
19590b57cec5SDimitry Andric   while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
19600b57cec5SDimitry Andric     // Each iteration of this loop reads one objc-instance-variable-decl.
19610b57cec5SDimitry Andric 
19620b57cec5SDimitry Andric     // Check for extraneous top-level semicolon.
19630b57cec5SDimitry Andric     if (Tok.is(tok::semi)) {
19640b57cec5SDimitry Andric       ConsumeExtraSemi(InstanceVariableList);
19650b57cec5SDimitry Andric       continue;
19660b57cec5SDimitry Andric     }
19670b57cec5SDimitry Andric 
19680b57cec5SDimitry Andric     // Set the default visibility to private.
19690b57cec5SDimitry Andric     if (TryConsumeToken(tok::at)) { // parse objc-visibility-spec
19700b57cec5SDimitry Andric       if (Tok.is(tok::code_completion)) {
1971fe6060f1SDimitry Andric         cutOffParsing();
1972*0fca6ea1SDimitry Andric         Actions.CodeCompletion().CodeCompleteObjCAtVisibility(getCurScope());
1973fe6060f1SDimitry Andric         return;
19740b57cec5SDimitry Andric       }
19750b57cec5SDimitry Andric 
19760b57cec5SDimitry Andric       switch (Tok.getObjCKeywordID()) {
19770b57cec5SDimitry Andric       case tok::objc_private:
19780b57cec5SDimitry Andric       case tok::objc_public:
19790b57cec5SDimitry Andric       case tok::objc_protected:
19800b57cec5SDimitry Andric       case tok::objc_package:
19810b57cec5SDimitry Andric         visibility = Tok.getObjCKeywordID();
19820b57cec5SDimitry Andric         ConsumeToken();
19830b57cec5SDimitry Andric         continue;
19840b57cec5SDimitry Andric 
19850b57cec5SDimitry Andric       case tok::objc_end:
19860b57cec5SDimitry Andric         Diag(Tok, diag::err_objc_unexpected_atend);
19870b57cec5SDimitry Andric         Tok.setLocation(Tok.getLocation().getLocWithOffset(-1));
19880b57cec5SDimitry Andric         Tok.setKind(tok::at);
19890b57cec5SDimitry Andric         Tok.setLength(1);
19900b57cec5SDimitry Andric         PP.EnterToken(Tok, /*IsReinject*/true);
19910b57cec5SDimitry Andric         HelperActionsForIvarDeclarations(interfaceDecl, atLoc,
19920b57cec5SDimitry Andric                                          T, AllIvarDecls, true);
19930b57cec5SDimitry Andric         return;
19940b57cec5SDimitry Andric 
19950b57cec5SDimitry Andric       default:
19960b57cec5SDimitry Andric         Diag(Tok, diag::err_objc_illegal_visibility_spec);
19970b57cec5SDimitry Andric         continue;
19980b57cec5SDimitry Andric       }
19990b57cec5SDimitry Andric     }
20000b57cec5SDimitry Andric 
20010b57cec5SDimitry Andric     if (Tok.is(tok::code_completion)) {
2002fe6060f1SDimitry Andric       cutOffParsing();
2003*0fca6ea1SDimitry Andric       Actions.CodeCompletion().CodeCompleteOrdinaryName(
2004*0fca6ea1SDimitry Andric           getCurScope(), SemaCodeCompletion::PCC_ObjCInstanceVariableList);
2005fe6060f1SDimitry Andric       return;
20060b57cec5SDimitry Andric     }
20070b57cec5SDimitry Andric 
20080b57cec5SDimitry Andric     // This needs to duplicate a small amount of code from
20090b57cec5SDimitry Andric     // ParseStructUnionBody() for things that should work in both
20100b57cec5SDimitry Andric     // C struct and in Objective-C class instance variables.
20110b57cec5SDimitry Andric     if (Tok.isOneOf(tok::kw_static_assert, tok::kw__Static_assert)) {
20120b57cec5SDimitry Andric       SourceLocation DeclEnd;
20130b57cec5SDimitry Andric       ParseStaticAssertDeclaration(DeclEnd);
20140b57cec5SDimitry Andric       continue;
20150b57cec5SDimitry Andric     }
20160b57cec5SDimitry Andric 
2017*0fca6ea1SDimitry Andric     auto ObjCIvarCallback = [&](ParsingFieldDeclarator &FD) -> Decl * {
201881ad6265SDimitry Andric       assert(getObjCDeclContext() == interfaceDecl &&
201981ad6265SDimitry Andric              "Ivar should have interfaceDecl as its decl context");
20200b57cec5SDimitry Andric       // Install the declarator into the interface decl.
20210b57cec5SDimitry Andric       FD.D.setObjCIvar(true);
2022*0fca6ea1SDimitry Andric       Decl *Field = Actions.ObjC().ActOnIvar(
20230b57cec5SDimitry Andric           getCurScope(), FD.D.getDeclSpec().getSourceRange().getBegin(), FD.D,
20240b57cec5SDimitry Andric           FD.BitfieldSize, visibility);
20250b57cec5SDimitry Andric       if (Field)
20260b57cec5SDimitry Andric         AllIvarDecls.push_back(Field);
20270b57cec5SDimitry Andric       FD.complete(Field);
2028*0fca6ea1SDimitry Andric       return Field;
20290b57cec5SDimitry Andric     };
20300b57cec5SDimitry Andric 
20310b57cec5SDimitry Andric     // Parse all the comma separated declarators.
20320b57cec5SDimitry Andric     ParsingDeclSpec DS(*this);
20330b57cec5SDimitry Andric     ParseStructDeclaration(DS, ObjCIvarCallback);
20340b57cec5SDimitry Andric 
20350b57cec5SDimitry Andric     if (Tok.is(tok::semi)) {
20360b57cec5SDimitry Andric       ConsumeToken();
20370b57cec5SDimitry Andric     } else {
20380b57cec5SDimitry Andric       Diag(Tok, diag::err_expected_semi_decl_list);
20390b57cec5SDimitry Andric       // Skip to end of block or statement
20400b57cec5SDimitry Andric       SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
20410b57cec5SDimitry Andric     }
20420b57cec5SDimitry Andric   }
20430b57cec5SDimitry Andric   HelperActionsForIvarDeclarations(interfaceDecl, atLoc,
20440b57cec5SDimitry Andric                                    T, AllIvarDecls, false);
20450b57cec5SDimitry Andric }
20460b57cec5SDimitry Andric 
20470b57cec5SDimitry Andric ///   objc-protocol-declaration:
20480b57cec5SDimitry Andric ///     objc-protocol-definition
20490b57cec5SDimitry Andric ///     objc-protocol-forward-reference
20500b57cec5SDimitry Andric ///
20510b57cec5SDimitry Andric ///   objc-protocol-definition:
20520b57cec5SDimitry Andric ///     \@protocol identifier
20530b57cec5SDimitry Andric ///       objc-protocol-refs[opt]
20540b57cec5SDimitry Andric ///       objc-interface-decl-list
20550b57cec5SDimitry Andric ///     \@end
20560b57cec5SDimitry Andric ///
20570b57cec5SDimitry Andric ///   objc-protocol-forward-reference:
20580b57cec5SDimitry Andric ///     \@protocol identifier-list ';'
20590b57cec5SDimitry Andric ///
20600b57cec5SDimitry Andric ///   "\@protocol identifier ;" should be resolved as "\@protocol
20610b57cec5SDimitry Andric ///   identifier-list ;": objc-interface-decl-list may not start with a
20620b57cec5SDimitry Andric ///   semicolon in the first alternative if objc-protocol-refs are omitted.
20630b57cec5SDimitry Andric Parser::DeclGroupPtrTy
20640b57cec5SDimitry Andric Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
20650b57cec5SDimitry Andric                                        ParsedAttributes &attrs) {
20660b57cec5SDimitry Andric   assert(Tok.isObjCAtKeyword(tok::objc_protocol) &&
20670b57cec5SDimitry Andric          "ParseObjCAtProtocolDeclaration(): Expected @protocol");
20680b57cec5SDimitry Andric   ConsumeToken(); // the "protocol" identifier
20690b57cec5SDimitry Andric 
20700b57cec5SDimitry Andric   if (Tok.is(tok::code_completion)) {
20710b57cec5SDimitry Andric     cutOffParsing();
2072*0fca6ea1SDimitry Andric     Actions.CodeCompletion().CodeCompleteObjCProtocolDecl(getCurScope());
20730b57cec5SDimitry Andric     return nullptr;
20740b57cec5SDimitry Andric   }
20750b57cec5SDimitry Andric 
20760b57cec5SDimitry Andric   MaybeSkipAttributes(tok::objc_protocol);
20770b57cec5SDimitry Andric 
20780b57cec5SDimitry Andric   if (expectIdentifier())
20790b57cec5SDimitry Andric     return nullptr; // missing protocol name.
20800b57cec5SDimitry Andric   // Save the protocol name, then consume it.
20810b57cec5SDimitry Andric   IdentifierInfo *protocolName = Tok.getIdentifierInfo();
20820b57cec5SDimitry Andric   SourceLocation nameLoc = ConsumeToken();
20830b57cec5SDimitry Andric 
20840b57cec5SDimitry Andric   if (TryConsumeToken(tok::semi)) { // forward declaration of one protocol.
20850b57cec5SDimitry Andric     IdentifierLocPair ProtoInfo(protocolName, nameLoc);
2086*0fca6ea1SDimitry Andric     return Actions.ObjC().ActOnForwardProtocolDeclaration(AtLoc, ProtoInfo,
2087*0fca6ea1SDimitry Andric                                                           attrs);
20880b57cec5SDimitry Andric   }
20890b57cec5SDimitry Andric 
20900b57cec5SDimitry Andric   CheckNestedObjCContexts(AtLoc);
20910b57cec5SDimitry Andric 
20920b57cec5SDimitry Andric   if (Tok.is(tok::comma)) { // list of forward declarations.
20930b57cec5SDimitry Andric     SmallVector<IdentifierLocPair, 8> ProtocolRefs;
20940b57cec5SDimitry Andric     ProtocolRefs.push_back(std::make_pair(protocolName, nameLoc));
20950b57cec5SDimitry Andric 
20960b57cec5SDimitry Andric     // Parse the list of forward declarations.
209704eeddc0SDimitry Andric     while (true) {
20980b57cec5SDimitry Andric       ConsumeToken(); // the ','
20990b57cec5SDimitry Andric       if (expectIdentifier()) {
21000b57cec5SDimitry Andric         SkipUntil(tok::semi);
21010b57cec5SDimitry Andric         return nullptr;
21020b57cec5SDimitry Andric       }
21030b57cec5SDimitry Andric       ProtocolRefs.push_back(IdentifierLocPair(Tok.getIdentifierInfo(),
21040b57cec5SDimitry Andric                                                Tok.getLocation()));
21050b57cec5SDimitry Andric       ConsumeToken(); // the identifier
21060b57cec5SDimitry Andric 
21070b57cec5SDimitry Andric       if (Tok.isNot(tok::comma))
21080b57cec5SDimitry Andric         break;
21090b57cec5SDimitry Andric     }
21100b57cec5SDimitry Andric     // Consume the ';'.
21110b57cec5SDimitry Andric     if (ExpectAndConsume(tok::semi, diag::err_expected_after, "@protocol"))
21120b57cec5SDimitry Andric       return nullptr;
21130b57cec5SDimitry Andric 
2114*0fca6ea1SDimitry Andric     return Actions.ObjC().ActOnForwardProtocolDeclaration(AtLoc, ProtocolRefs,
2115*0fca6ea1SDimitry Andric                                                           attrs);
21160b57cec5SDimitry Andric   }
21170b57cec5SDimitry Andric 
21180b57cec5SDimitry Andric   // Last, and definitely not least, parse a protocol declaration.
21190b57cec5SDimitry Andric   SourceLocation LAngleLoc, EndProtoLoc;
21200b57cec5SDimitry Andric 
21210b57cec5SDimitry Andric   SmallVector<Decl *, 8> ProtocolRefs;
21220b57cec5SDimitry Andric   SmallVector<SourceLocation, 8> ProtocolLocs;
21230b57cec5SDimitry Andric   if (Tok.is(tok::less) &&
21240b57cec5SDimitry Andric       ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, false, true,
21250b57cec5SDimitry Andric                                   LAngleLoc, EndProtoLoc,
21260b57cec5SDimitry Andric                                   /*consumeLastToken=*/true))
21270b57cec5SDimitry Andric     return nullptr;
21280b57cec5SDimitry Andric 
2129*0fca6ea1SDimitry Andric   SkipBodyInfo SkipBody;
2130*0fca6ea1SDimitry Andric   ObjCProtocolDecl *ProtoType = Actions.ObjC().ActOnStartProtocolInterface(
21310b57cec5SDimitry Andric       AtLoc, protocolName, nameLoc, ProtocolRefs.data(), ProtocolRefs.size(),
2132bdd1243dSDimitry Andric       ProtocolLocs.data(), EndProtoLoc, attrs, &SkipBody);
21330b57cec5SDimitry Andric 
21340b57cec5SDimitry Andric   ParseObjCInterfaceDeclList(tok::objc_protocol, ProtoType);
2135bdd1243dSDimitry Andric   if (SkipBody.CheckSameAsPrevious) {
2136bdd1243dSDimitry Andric     auto *PreviousDef = cast<ObjCProtocolDecl>(SkipBody.Previous);
2137bdd1243dSDimitry Andric     if (Actions.ActOnDuplicateODRHashDefinition(ProtoType, PreviousDef)) {
2138bdd1243dSDimitry Andric       ProtoType->mergeDuplicateDefinitionWithCommon(
2139bdd1243dSDimitry Andric           PreviousDef->getDefinition());
2140bdd1243dSDimitry Andric     } else {
2141bdd1243dSDimitry Andric       ODRDiagsEmitter DiagsEmitter(Diags, Actions.getASTContext(),
2142bdd1243dSDimitry Andric                                    getPreprocessor().getLangOpts());
2143bdd1243dSDimitry Andric       DiagsEmitter.diagnoseMismatch(PreviousDef, ProtoType);
2144bdd1243dSDimitry Andric     }
2145bdd1243dSDimitry Andric   }
21460b57cec5SDimitry Andric   return Actions.ConvertDeclToDeclGroup(ProtoType);
21470b57cec5SDimitry Andric }
21480b57cec5SDimitry Andric 
21490b57cec5SDimitry Andric ///   objc-implementation:
21500b57cec5SDimitry Andric ///     objc-class-implementation-prologue
21510b57cec5SDimitry Andric ///     objc-category-implementation-prologue
21520b57cec5SDimitry Andric ///
21530b57cec5SDimitry Andric ///   objc-class-implementation-prologue:
21540b57cec5SDimitry Andric ///     @implementation identifier objc-superclass[opt]
21550b57cec5SDimitry Andric ///       objc-class-instance-variables[opt]
21560b57cec5SDimitry Andric ///
21570b57cec5SDimitry Andric ///   objc-category-implementation-prologue:
21580b57cec5SDimitry Andric ///     @implementation identifier ( identifier )
21590b57cec5SDimitry Andric Parser::DeclGroupPtrTy
21600b57cec5SDimitry Andric Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc,
21610b57cec5SDimitry Andric                                              ParsedAttributes &Attrs) {
21620b57cec5SDimitry Andric   assert(Tok.isObjCAtKeyword(tok::objc_implementation) &&
21630b57cec5SDimitry Andric          "ParseObjCAtImplementationDeclaration(): Expected @implementation");
21640b57cec5SDimitry Andric   CheckNestedObjCContexts(AtLoc);
21650b57cec5SDimitry Andric   ConsumeToken(); // the "implementation" identifier
21660b57cec5SDimitry Andric 
21670b57cec5SDimitry Andric   // Code completion after '@implementation'.
21680b57cec5SDimitry Andric   if (Tok.is(tok::code_completion)) {
21690b57cec5SDimitry Andric     cutOffParsing();
2170*0fca6ea1SDimitry Andric     Actions.CodeCompletion().CodeCompleteObjCImplementationDecl(getCurScope());
21710b57cec5SDimitry Andric     return nullptr;
21720b57cec5SDimitry Andric   }
21730b57cec5SDimitry Andric 
21740b57cec5SDimitry Andric   MaybeSkipAttributes(tok::objc_implementation);
21750b57cec5SDimitry Andric 
21760b57cec5SDimitry Andric   if (expectIdentifier())
21770b57cec5SDimitry Andric     return nullptr; // missing class or category name.
21780b57cec5SDimitry Andric   // We have a class or category name - consume it.
21790b57cec5SDimitry Andric   IdentifierInfo *nameId = Tok.getIdentifierInfo();
21800b57cec5SDimitry Andric   SourceLocation nameLoc = ConsumeToken(); // consume class or category name
218181ad6265SDimitry Andric   ObjCImplDecl *ObjCImpDecl = nullptr;
21820b57cec5SDimitry Andric 
21830b57cec5SDimitry Andric   // Neither a type parameter list nor a list of protocol references is
21840b57cec5SDimitry Andric   // permitted here. Parse and diagnose them.
21850b57cec5SDimitry Andric   if (Tok.is(tok::less)) {
21860b57cec5SDimitry Andric     SourceLocation lAngleLoc, rAngleLoc;
21870b57cec5SDimitry Andric     SmallVector<IdentifierLocPair, 8> protocolIdents;
21880b57cec5SDimitry Andric     SourceLocation diagLoc = Tok.getLocation();
21890b57cec5SDimitry Andric     ObjCTypeParamListScope typeParamScope(Actions, getCurScope());
21900b57cec5SDimitry Andric     if (parseObjCTypeParamListOrProtocolRefs(typeParamScope, lAngleLoc,
21910b57cec5SDimitry Andric                                              protocolIdents, rAngleLoc)) {
21920b57cec5SDimitry Andric       Diag(diagLoc, diag::err_objc_parameterized_implementation)
21930b57cec5SDimitry Andric         << SourceRange(diagLoc, PrevTokLocation);
21940b57cec5SDimitry Andric     } else if (lAngleLoc.isValid()) {
21950b57cec5SDimitry Andric       Diag(lAngleLoc, diag::err_unexpected_protocol_qualifier)
21960b57cec5SDimitry Andric         << FixItHint::CreateRemoval(SourceRange(lAngleLoc, rAngleLoc));
21970b57cec5SDimitry Andric     }
21980b57cec5SDimitry Andric   }
21990b57cec5SDimitry Andric 
22000b57cec5SDimitry Andric   if (Tok.is(tok::l_paren)) {
22010b57cec5SDimitry Andric     // we have a category implementation.
22020b57cec5SDimitry Andric     ConsumeParen();
22030b57cec5SDimitry Andric     SourceLocation categoryLoc, rparenLoc;
22040b57cec5SDimitry Andric     IdentifierInfo *categoryId = nullptr;
22050b57cec5SDimitry Andric 
22060b57cec5SDimitry Andric     if (Tok.is(tok::code_completion)) {
22070b57cec5SDimitry Andric       cutOffParsing();
2208*0fca6ea1SDimitry Andric       Actions.CodeCompletion().CodeCompleteObjCImplementationCategory(
2209*0fca6ea1SDimitry Andric           getCurScope(), nameId, nameLoc);
22100b57cec5SDimitry Andric       return nullptr;
22110b57cec5SDimitry Andric     }
22120b57cec5SDimitry Andric 
22130b57cec5SDimitry Andric     if (Tok.is(tok::identifier)) {
22140b57cec5SDimitry Andric       categoryId = Tok.getIdentifierInfo();
22150b57cec5SDimitry Andric       categoryLoc = ConsumeToken();
22160b57cec5SDimitry Andric     } else {
22170b57cec5SDimitry Andric       Diag(Tok, diag::err_expected)
22180b57cec5SDimitry Andric           << tok::identifier; // missing category name.
22190b57cec5SDimitry Andric       return nullptr;
22200b57cec5SDimitry Andric     }
22210b57cec5SDimitry Andric     if (Tok.isNot(tok::r_paren)) {
22220b57cec5SDimitry Andric       Diag(Tok, diag::err_expected) << tok::r_paren;
22230b57cec5SDimitry Andric       SkipUntil(tok::r_paren); // don't stop at ';'
22240b57cec5SDimitry Andric       return nullptr;
22250b57cec5SDimitry Andric     }
22260b57cec5SDimitry Andric     rparenLoc = ConsumeParen();
22270b57cec5SDimitry Andric     if (Tok.is(tok::less)) { // we have illegal '<' try to recover
22280b57cec5SDimitry Andric       Diag(Tok, diag::err_unexpected_protocol_qualifier);
22290b57cec5SDimitry Andric       SourceLocation protocolLAngleLoc, protocolRAngleLoc;
22300b57cec5SDimitry Andric       SmallVector<Decl *, 4> protocols;
22310b57cec5SDimitry Andric       SmallVector<SourceLocation, 4> protocolLocs;
22320b57cec5SDimitry Andric       (void)ParseObjCProtocolReferences(protocols, protocolLocs,
22330b57cec5SDimitry Andric                                         /*warnOnIncompleteProtocols=*/false,
22340b57cec5SDimitry Andric                                         /*ForObjCContainer=*/false,
22350b57cec5SDimitry Andric                                         protocolLAngleLoc, protocolRAngleLoc,
22360b57cec5SDimitry Andric                                         /*consumeLastToken=*/true);
22370b57cec5SDimitry Andric     }
2238*0fca6ea1SDimitry Andric     ObjCImpDecl = Actions.ObjC().ActOnStartCategoryImplementation(
22390b57cec5SDimitry Andric         AtLoc, nameId, nameLoc, categoryId, categoryLoc, Attrs);
22400b57cec5SDimitry Andric 
22410b57cec5SDimitry Andric   } else {
22420b57cec5SDimitry Andric     // We have a class implementation
22430b57cec5SDimitry Andric     SourceLocation superClassLoc;
22440b57cec5SDimitry Andric     IdentifierInfo *superClassId = nullptr;
22450b57cec5SDimitry Andric     if (TryConsumeToken(tok::colon)) {
22460b57cec5SDimitry Andric       // We have a super class
22470b57cec5SDimitry Andric       if (expectIdentifier())
22480b57cec5SDimitry Andric         return nullptr; // missing super class name.
22490b57cec5SDimitry Andric       superClassId = Tok.getIdentifierInfo();
22500b57cec5SDimitry Andric       superClassLoc = ConsumeToken(); // Consume super class name
22510b57cec5SDimitry Andric     }
2252*0fca6ea1SDimitry Andric     ObjCImpDecl = Actions.ObjC().ActOnStartClassImplementation(
22530b57cec5SDimitry Andric         AtLoc, nameId, nameLoc, superClassId, superClassLoc, Attrs);
22540b57cec5SDimitry Andric 
22550b57cec5SDimitry Andric     if (Tok.is(tok::l_brace)) // we have ivars
22560b57cec5SDimitry Andric       ParseObjCClassInstanceVariables(ObjCImpDecl, tok::objc_private, AtLoc);
22570b57cec5SDimitry Andric     else if (Tok.is(tok::less)) { // we have illegal '<' try to recover
22580b57cec5SDimitry Andric       Diag(Tok, diag::err_unexpected_protocol_qualifier);
22590b57cec5SDimitry Andric 
22600b57cec5SDimitry Andric       SourceLocation protocolLAngleLoc, protocolRAngleLoc;
22610b57cec5SDimitry Andric       SmallVector<Decl *, 4> protocols;
22620b57cec5SDimitry Andric       SmallVector<SourceLocation, 4> protocolLocs;
22630b57cec5SDimitry Andric       (void)ParseObjCProtocolReferences(protocols, protocolLocs,
22640b57cec5SDimitry Andric                                         /*warnOnIncompleteProtocols=*/false,
22650b57cec5SDimitry Andric                                         /*ForObjCContainer=*/false,
22660b57cec5SDimitry Andric                                         protocolLAngleLoc, protocolRAngleLoc,
22670b57cec5SDimitry Andric                                         /*consumeLastToken=*/true);
22680b57cec5SDimitry Andric     }
22690b57cec5SDimitry Andric   }
22700b57cec5SDimitry Andric   assert(ObjCImpDecl);
22710b57cec5SDimitry Andric 
22720b57cec5SDimitry Andric   SmallVector<Decl *, 8> DeclsInGroup;
22730b57cec5SDimitry Andric 
22740b57cec5SDimitry Andric   {
22750b57cec5SDimitry Andric     ObjCImplParsingDataRAII ObjCImplParsing(*this, ObjCImpDecl);
22760b57cec5SDimitry Andric     while (!ObjCImplParsing.isFinished() && !isEofOrEom()) {
2277bdd1243dSDimitry Andric       ParsedAttributes DeclAttrs(AttrFactory);
2278bdd1243dSDimitry Andric       MaybeParseCXX11Attributes(DeclAttrs);
2279bdd1243dSDimitry Andric       ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
2280bdd1243dSDimitry Andric       if (DeclGroupPtrTy DGP =
2281bdd1243dSDimitry Andric               ParseExternalDeclaration(DeclAttrs, EmptyDeclSpecAttrs)) {
22820b57cec5SDimitry Andric         DeclGroupRef DG = DGP.get();
22830b57cec5SDimitry Andric         DeclsInGroup.append(DG.begin(), DG.end());
22840b57cec5SDimitry Andric       }
22850b57cec5SDimitry Andric     }
22860b57cec5SDimitry Andric   }
22870b57cec5SDimitry Andric 
2288*0fca6ea1SDimitry Andric   return Actions.ObjC().ActOnFinishObjCImplementation(ObjCImpDecl,
2289*0fca6ea1SDimitry Andric                                                       DeclsInGroup);
22900b57cec5SDimitry Andric }
22910b57cec5SDimitry Andric 
22920b57cec5SDimitry Andric Parser::DeclGroupPtrTy
22930b57cec5SDimitry Andric Parser::ParseObjCAtEndDeclaration(SourceRange atEnd) {
22940b57cec5SDimitry Andric   assert(Tok.isObjCAtKeyword(tok::objc_end) &&
22950b57cec5SDimitry Andric          "ParseObjCAtEndDeclaration(): Expected @end");
22960b57cec5SDimitry Andric   ConsumeToken(); // the "end" identifier
22970b57cec5SDimitry Andric   if (CurParsedObjCImpl)
22980b57cec5SDimitry Andric     CurParsedObjCImpl->finish(atEnd);
22990b57cec5SDimitry Andric   else
23000b57cec5SDimitry Andric     // missing @implementation
23010b57cec5SDimitry Andric     Diag(atEnd.getBegin(), diag::err_expected_objc_container);
23020b57cec5SDimitry Andric   return nullptr;
23030b57cec5SDimitry Andric }
23040b57cec5SDimitry Andric 
23050b57cec5SDimitry Andric Parser::ObjCImplParsingDataRAII::~ObjCImplParsingDataRAII() {
23060b57cec5SDimitry Andric   if (!Finished) {
23070b57cec5SDimitry Andric     finish(P.Tok.getLocation());
23080b57cec5SDimitry Andric     if (P.isEofOrEom()) {
23090b57cec5SDimitry Andric       P.Diag(P.Tok, diag::err_objc_missing_end)
23100b57cec5SDimitry Andric           << FixItHint::CreateInsertion(P.Tok.getLocation(), "\n@end\n");
23110b57cec5SDimitry Andric       P.Diag(Dcl->getBeginLoc(), diag::note_objc_container_start)
2312*0fca6ea1SDimitry Andric           << SemaObjC::OCK_Implementation;
23130b57cec5SDimitry Andric     }
23140b57cec5SDimitry Andric   }
23150b57cec5SDimitry Andric   P.CurParsedObjCImpl = nullptr;
23160b57cec5SDimitry Andric   assert(LateParsedObjCMethods.empty());
23170b57cec5SDimitry Andric }
23180b57cec5SDimitry Andric 
23190b57cec5SDimitry Andric void Parser::ObjCImplParsingDataRAII::finish(SourceRange AtEnd) {
23200b57cec5SDimitry Andric   assert(!Finished);
2321*0fca6ea1SDimitry Andric   P.Actions.ObjC().DefaultSynthesizeProperties(P.getCurScope(), Dcl,
2322*0fca6ea1SDimitry Andric                                                AtEnd.getBegin());
23230b57cec5SDimitry Andric   for (size_t i = 0; i < LateParsedObjCMethods.size(); ++i)
23240b57cec5SDimitry Andric     P.ParseLexedObjCMethodDefs(*LateParsedObjCMethods[i],
23250b57cec5SDimitry Andric                                true/*Methods*/);
23260b57cec5SDimitry Andric 
2327*0fca6ea1SDimitry Andric   P.Actions.ObjC().ActOnAtEnd(P.getCurScope(), AtEnd);
23280b57cec5SDimitry Andric 
23290b57cec5SDimitry Andric   if (HasCFunction)
23300b57cec5SDimitry Andric     for (size_t i = 0; i < LateParsedObjCMethods.size(); ++i)
23310b57cec5SDimitry Andric       P.ParseLexedObjCMethodDefs(*LateParsedObjCMethods[i],
23320b57cec5SDimitry Andric                                  false/*c-functions*/);
23330b57cec5SDimitry Andric 
23340b57cec5SDimitry Andric   /// Clear and free the cached objc methods.
23350b57cec5SDimitry Andric   for (LateParsedObjCMethodContainer::iterator
23360b57cec5SDimitry Andric          I = LateParsedObjCMethods.begin(),
23370b57cec5SDimitry Andric          E = LateParsedObjCMethods.end(); I != E; ++I)
23380b57cec5SDimitry Andric     delete *I;
23390b57cec5SDimitry Andric   LateParsedObjCMethods.clear();
23400b57cec5SDimitry Andric 
23410b57cec5SDimitry Andric   Finished = true;
23420b57cec5SDimitry Andric }
23430b57cec5SDimitry Andric 
23440b57cec5SDimitry Andric ///   compatibility-alias-decl:
23450b57cec5SDimitry Andric ///     @compatibility_alias alias-name  class-name ';'
23460b57cec5SDimitry Andric ///
23470b57cec5SDimitry Andric Decl *Parser::ParseObjCAtAliasDeclaration(SourceLocation atLoc) {
23480b57cec5SDimitry Andric   assert(Tok.isObjCAtKeyword(tok::objc_compatibility_alias) &&
23490b57cec5SDimitry Andric          "ParseObjCAtAliasDeclaration(): Expected @compatibility_alias");
23500b57cec5SDimitry Andric   ConsumeToken(); // consume compatibility_alias
23510b57cec5SDimitry Andric   if (expectIdentifier())
23520b57cec5SDimitry Andric     return nullptr;
23530b57cec5SDimitry Andric   IdentifierInfo *aliasId = Tok.getIdentifierInfo();
23540b57cec5SDimitry Andric   SourceLocation aliasLoc = ConsumeToken(); // consume alias-name
23550b57cec5SDimitry Andric   if (expectIdentifier())
23560b57cec5SDimitry Andric     return nullptr;
23570b57cec5SDimitry Andric   IdentifierInfo *classId = Tok.getIdentifierInfo();
23580b57cec5SDimitry Andric   SourceLocation classLoc = ConsumeToken(); // consume class-name;
23590b57cec5SDimitry Andric   ExpectAndConsume(tok::semi, diag::err_expected_after, "@compatibility_alias");
2360*0fca6ea1SDimitry Andric   return Actions.ObjC().ActOnCompatibilityAlias(atLoc, aliasId, aliasLoc,
23610b57cec5SDimitry Andric                                                 classId, classLoc);
23620b57cec5SDimitry Andric }
23630b57cec5SDimitry Andric 
23640b57cec5SDimitry Andric ///   property-synthesis:
23650b57cec5SDimitry Andric ///     @synthesize property-ivar-list ';'
23660b57cec5SDimitry Andric ///
23670b57cec5SDimitry Andric ///   property-ivar-list:
23680b57cec5SDimitry Andric ///     property-ivar
23690b57cec5SDimitry Andric ///     property-ivar-list ',' property-ivar
23700b57cec5SDimitry Andric ///
23710b57cec5SDimitry Andric ///   property-ivar:
23720b57cec5SDimitry Andric ///     identifier
23730b57cec5SDimitry Andric ///     identifier '=' identifier
23740b57cec5SDimitry Andric ///
23750b57cec5SDimitry Andric Decl *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
23760b57cec5SDimitry Andric   assert(Tok.isObjCAtKeyword(tok::objc_synthesize) &&
23770b57cec5SDimitry Andric          "ParseObjCPropertySynthesize(): Expected '@synthesize'");
23780b57cec5SDimitry Andric   ConsumeToken(); // consume synthesize
23790b57cec5SDimitry Andric 
23800b57cec5SDimitry Andric   while (true) {
23810b57cec5SDimitry Andric     if (Tok.is(tok::code_completion)) {
23820b57cec5SDimitry Andric       cutOffParsing();
2383*0fca6ea1SDimitry Andric       Actions.CodeCompletion().CodeCompleteObjCPropertyDefinition(
2384*0fca6ea1SDimitry Andric           getCurScope());
23850b57cec5SDimitry Andric       return nullptr;
23860b57cec5SDimitry Andric     }
23870b57cec5SDimitry Andric 
23880b57cec5SDimitry Andric     if (Tok.isNot(tok::identifier)) {
23890b57cec5SDimitry Andric       Diag(Tok, diag::err_synthesized_property_name);
23900b57cec5SDimitry Andric       SkipUntil(tok::semi);
23910b57cec5SDimitry Andric       return nullptr;
23920b57cec5SDimitry Andric     }
23930b57cec5SDimitry Andric 
23940b57cec5SDimitry Andric     IdentifierInfo *propertyIvar = nullptr;
23950b57cec5SDimitry Andric     IdentifierInfo *propertyId = Tok.getIdentifierInfo();
23960b57cec5SDimitry Andric     SourceLocation propertyLoc = ConsumeToken(); // consume property name
23970b57cec5SDimitry Andric     SourceLocation propertyIvarLoc;
23980b57cec5SDimitry Andric     if (TryConsumeToken(tok::equal)) {
23990b57cec5SDimitry Andric       // property '=' ivar-name
24000b57cec5SDimitry Andric       if (Tok.is(tok::code_completion)) {
24010b57cec5SDimitry Andric         cutOffParsing();
2402*0fca6ea1SDimitry Andric         Actions.CodeCompletion().CodeCompleteObjCPropertySynthesizeIvar(
2403*0fca6ea1SDimitry Andric             getCurScope(), propertyId);
24040b57cec5SDimitry Andric         return nullptr;
24050b57cec5SDimitry Andric       }
24060b57cec5SDimitry Andric 
24070b57cec5SDimitry Andric       if (expectIdentifier())
24080b57cec5SDimitry Andric         break;
24090b57cec5SDimitry Andric       propertyIvar = Tok.getIdentifierInfo();
24100b57cec5SDimitry Andric       propertyIvarLoc = ConsumeToken(); // consume ivar-name
24110b57cec5SDimitry Andric     }
2412*0fca6ea1SDimitry Andric     Actions.ObjC().ActOnPropertyImplDecl(
2413*0fca6ea1SDimitry Andric         getCurScope(), atLoc, propertyLoc, true, propertyId, propertyIvar,
2414*0fca6ea1SDimitry Andric         propertyIvarLoc, ObjCPropertyQueryKind::OBJC_PR_query_unknown);
24150b57cec5SDimitry Andric     if (Tok.isNot(tok::comma))
24160b57cec5SDimitry Andric       break;
24170b57cec5SDimitry Andric     ConsumeToken(); // consume ','
24180b57cec5SDimitry Andric   }
24190b57cec5SDimitry Andric   ExpectAndConsume(tok::semi, diag::err_expected_after, "@synthesize");
24200b57cec5SDimitry Andric   return nullptr;
24210b57cec5SDimitry Andric }
24220b57cec5SDimitry Andric 
24230b57cec5SDimitry Andric ///   property-dynamic:
24240b57cec5SDimitry Andric ///     @dynamic  property-list
24250b57cec5SDimitry Andric ///
24260b57cec5SDimitry Andric ///   property-list:
24270b57cec5SDimitry Andric ///     identifier
24280b57cec5SDimitry Andric ///     property-list ',' identifier
24290b57cec5SDimitry Andric ///
24300b57cec5SDimitry Andric Decl *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) {
24310b57cec5SDimitry Andric   assert(Tok.isObjCAtKeyword(tok::objc_dynamic) &&
24320b57cec5SDimitry Andric          "ParseObjCPropertyDynamic(): Expected '@dynamic'");
24330b57cec5SDimitry Andric   ConsumeToken(); // consume dynamic
24340b57cec5SDimitry Andric 
24350b57cec5SDimitry Andric   bool isClassProperty = false;
24360b57cec5SDimitry Andric   if (Tok.is(tok::l_paren)) {
24370b57cec5SDimitry Andric     ConsumeParen();
24380b57cec5SDimitry Andric     const IdentifierInfo *II = Tok.getIdentifierInfo();
24390b57cec5SDimitry Andric 
24400b57cec5SDimitry Andric     if (!II) {
24410b57cec5SDimitry Andric       Diag(Tok, diag::err_objc_expected_property_attr) << II;
24420b57cec5SDimitry Andric       SkipUntil(tok::r_paren, StopAtSemi);
24430b57cec5SDimitry Andric     } else {
24440b57cec5SDimitry Andric       SourceLocation AttrName = ConsumeToken(); // consume attribute name
24450b57cec5SDimitry Andric       if (II->isStr("class")) {
24460b57cec5SDimitry Andric         isClassProperty = true;
24470b57cec5SDimitry Andric         if (Tok.isNot(tok::r_paren)) {
24480b57cec5SDimitry Andric           Diag(Tok, diag::err_expected) << tok::r_paren;
24490b57cec5SDimitry Andric           SkipUntil(tok::r_paren, StopAtSemi);
24500b57cec5SDimitry Andric         } else
24510b57cec5SDimitry Andric           ConsumeParen();
24520b57cec5SDimitry Andric       } else {
24530b57cec5SDimitry Andric         Diag(AttrName, diag::err_objc_expected_property_attr) << II;
24540b57cec5SDimitry Andric         SkipUntil(tok::r_paren, StopAtSemi);
24550b57cec5SDimitry Andric       }
24560b57cec5SDimitry Andric     }
24570b57cec5SDimitry Andric   }
24580b57cec5SDimitry Andric 
24590b57cec5SDimitry Andric   while (true) {
24600b57cec5SDimitry Andric     if (Tok.is(tok::code_completion)) {
24610b57cec5SDimitry Andric       cutOffParsing();
2462*0fca6ea1SDimitry Andric       Actions.CodeCompletion().CodeCompleteObjCPropertyDefinition(
2463*0fca6ea1SDimitry Andric           getCurScope());
24640b57cec5SDimitry Andric       return nullptr;
24650b57cec5SDimitry Andric     }
24660b57cec5SDimitry Andric 
24670b57cec5SDimitry Andric     if (expectIdentifier()) {
24680b57cec5SDimitry Andric       SkipUntil(tok::semi);
24690b57cec5SDimitry Andric       return nullptr;
24700b57cec5SDimitry Andric     }
24710b57cec5SDimitry Andric 
24720b57cec5SDimitry Andric     IdentifierInfo *propertyId = Tok.getIdentifierInfo();
24730b57cec5SDimitry Andric     SourceLocation propertyLoc = ConsumeToken(); // consume property name
2474*0fca6ea1SDimitry Andric     Actions.ObjC().ActOnPropertyImplDecl(
2475*0fca6ea1SDimitry Andric         getCurScope(), atLoc, propertyLoc, false, propertyId, nullptr,
2476*0fca6ea1SDimitry Andric         SourceLocation(),
2477*0fca6ea1SDimitry Andric         isClassProperty ? ObjCPropertyQueryKind::OBJC_PR_query_class
2478*0fca6ea1SDimitry Andric                         : ObjCPropertyQueryKind::OBJC_PR_query_unknown);
24790b57cec5SDimitry Andric 
24800b57cec5SDimitry Andric     if (Tok.isNot(tok::comma))
24810b57cec5SDimitry Andric       break;
24820b57cec5SDimitry Andric     ConsumeToken(); // consume ','
24830b57cec5SDimitry Andric   }
24840b57cec5SDimitry Andric   ExpectAndConsume(tok::semi, diag::err_expected_after, "@dynamic");
24850b57cec5SDimitry Andric   return nullptr;
24860b57cec5SDimitry Andric }
24870b57cec5SDimitry Andric 
24880b57cec5SDimitry Andric ///  objc-throw-statement:
24890b57cec5SDimitry Andric ///    throw expression[opt];
24900b57cec5SDimitry Andric ///
24910b57cec5SDimitry Andric StmtResult Parser::ParseObjCThrowStmt(SourceLocation atLoc) {
24920b57cec5SDimitry Andric   ExprResult Res;
24930b57cec5SDimitry Andric   ConsumeToken(); // consume throw
24940b57cec5SDimitry Andric   if (Tok.isNot(tok::semi)) {
24950b57cec5SDimitry Andric     Res = ParseExpression();
24960b57cec5SDimitry Andric     if (Res.isInvalid()) {
24970b57cec5SDimitry Andric       SkipUntil(tok::semi);
24980b57cec5SDimitry Andric       return StmtError();
24990b57cec5SDimitry Andric     }
25000b57cec5SDimitry Andric   }
25010b57cec5SDimitry Andric   // consume ';'
25020b57cec5SDimitry Andric   ExpectAndConsume(tok::semi, diag::err_expected_after, "@throw");
2503*0fca6ea1SDimitry Andric   return Actions.ObjC().ActOnObjCAtThrowStmt(atLoc, Res.get(), getCurScope());
25040b57cec5SDimitry Andric }
25050b57cec5SDimitry Andric 
25060b57cec5SDimitry Andric /// objc-synchronized-statement:
25070b57cec5SDimitry Andric ///   @synchronized '(' expression ')' compound-statement
25080b57cec5SDimitry Andric ///
25090b57cec5SDimitry Andric StmtResult
25100b57cec5SDimitry Andric Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) {
25110b57cec5SDimitry Andric   ConsumeToken(); // consume synchronized
25120b57cec5SDimitry Andric   if (Tok.isNot(tok::l_paren)) {
25130b57cec5SDimitry Andric     Diag(Tok, diag::err_expected_lparen_after) << "@synchronized";
25140b57cec5SDimitry Andric     return StmtError();
25150b57cec5SDimitry Andric   }
25160b57cec5SDimitry Andric 
25170b57cec5SDimitry Andric   // The operand is surrounded with parentheses.
25180b57cec5SDimitry Andric   ConsumeParen();  // '('
25190b57cec5SDimitry Andric   ExprResult operand(ParseExpression());
25200b57cec5SDimitry Andric 
25210b57cec5SDimitry Andric   if (Tok.is(tok::r_paren)) {
25220b57cec5SDimitry Andric     ConsumeParen();  // ')'
25230b57cec5SDimitry Andric   } else {
25240b57cec5SDimitry Andric     if (!operand.isInvalid())
25250b57cec5SDimitry Andric       Diag(Tok, diag::err_expected) << tok::r_paren;
25260b57cec5SDimitry Andric 
25270b57cec5SDimitry Andric     // Skip forward until we see a left brace, but don't consume it.
25280b57cec5SDimitry Andric     SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch);
25290b57cec5SDimitry Andric   }
25300b57cec5SDimitry Andric 
25310b57cec5SDimitry Andric   // Require a compound statement.
25320b57cec5SDimitry Andric   if (Tok.isNot(tok::l_brace)) {
25330b57cec5SDimitry Andric     if (!operand.isInvalid())
25340b57cec5SDimitry Andric       Diag(Tok, diag::err_expected) << tok::l_brace;
25350b57cec5SDimitry Andric     return StmtError();
25360b57cec5SDimitry Andric   }
25370b57cec5SDimitry Andric 
25380b57cec5SDimitry Andric   // Check the @synchronized operand now.
25390b57cec5SDimitry Andric   if (!operand.isInvalid())
2540*0fca6ea1SDimitry Andric     operand =
2541*0fca6ea1SDimitry Andric         Actions.ObjC().ActOnObjCAtSynchronizedOperand(atLoc, operand.get());
25420b57cec5SDimitry Andric 
25430b57cec5SDimitry Andric   // Parse the compound statement within a new scope.
25440b57cec5SDimitry Andric   ParseScope bodyScope(this, Scope::DeclScope | Scope::CompoundStmtScope);
25450b57cec5SDimitry Andric   StmtResult body(ParseCompoundStatementBody());
25460b57cec5SDimitry Andric   bodyScope.Exit();
25470b57cec5SDimitry Andric 
25480b57cec5SDimitry Andric   // If there was a semantic or parse error earlier with the
25490b57cec5SDimitry Andric   // operand, fail now.
25500b57cec5SDimitry Andric   if (operand.isInvalid())
25510b57cec5SDimitry Andric     return StmtError();
25520b57cec5SDimitry Andric 
25530b57cec5SDimitry Andric   if (body.isInvalid())
25540b57cec5SDimitry Andric     body = Actions.ActOnNullStmt(Tok.getLocation());
25550b57cec5SDimitry Andric 
2556*0fca6ea1SDimitry Andric   return Actions.ObjC().ActOnObjCAtSynchronizedStmt(atLoc, operand.get(),
2557*0fca6ea1SDimitry Andric                                                     body.get());
25580b57cec5SDimitry Andric }
25590b57cec5SDimitry Andric 
25600b57cec5SDimitry Andric ///  objc-try-catch-statement:
25610b57cec5SDimitry Andric ///    @try compound-statement objc-catch-list[opt]
25620b57cec5SDimitry Andric ///    @try compound-statement objc-catch-list[opt] @finally compound-statement
25630b57cec5SDimitry Andric ///
25640b57cec5SDimitry Andric ///  objc-catch-list:
25650b57cec5SDimitry Andric ///    @catch ( parameter-declaration ) compound-statement
25660b57cec5SDimitry Andric ///    objc-catch-list @catch ( catch-parameter-declaration ) compound-statement
25670b57cec5SDimitry Andric ///  catch-parameter-declaration:
25680b57cec5SDimitry Andric ///     parameter-declaration
25690b57cec5SDimitry Andric ///     '...' [OBJC2]
25700b57cec5SDimitry Andric ///
25710b57cec5SDimitry Andric StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
25720b57cec5SDimitry Andric   bool catch_or_finally_seen = false;
25730b57cec5SDimitry Andric 
25740b57cec5SDimitry Andric   ConsumeToken(); // consume try
25750b57cec5SDimitry Andric   if (Tok.isNot(tok::l_brace)) {
25760b57cec5SDimitry Andric     Diag(Tok, diag::err_expected) << tok::l_brace;
25770b57cec5SDimitry Andric     return StmtError();
25780b57cec5SDimitry Andric   }
25790b57cec5SDimitry Andric   StmtVector CatchStmts;
25800b57cec5SDimitry Andric   StmtResult FinallyStmt;
25810b57cec5SDimitry Andric   ParseScope TryScope(this, Scope::DeclScope | Scope::CompoundStmtScope);
25820b57cec5SDimitry Andric   StmtResult TryBody(ParseCompoundStatementBody());
25830b57cec5SDimitry Andric   TryScope.Exit();
25840b57cec5SDimitry Andric   if (TryBody.isInvalid())
25850b57cec5SDimitry Andric     TryBody = Actions.ActOnNullStmt(Tok.getLocation());
25860b57cec5SDimitry Andric 
25870b57cec5SDimitry Andric   while (Tok.is(tok::at)) {
25880b57cec5SDimitry Andric     // At this point, we need to lookahead to determine if this @ is the start
25890b57cec5SDimitry Andric     // of an @catch or @finally.  We don't want to consume the @ token if this
25900b57cec5SDimitry Andric     // is an @try or @encode or something else.
25910b57cec5SDimitry Andric     Token AfterAt = GetLookAheadToken(1);
25920b57cec5SDimitry Andric     if (!AfterAt.isObjCAtKeyword(tok::objc_catch) &&
25930b57cec5SDimitry Andric         !AfterAt.isObjCAtKeyword(tok::objc_finally))
25940b57cec5SDimitry Andric       break;
25950b57cec5SDimitry Andric 
25960b57cec5SDimitry Andric     SourceLocation AtCatchFinallyLoc = ConsumeToken();
25970b57cec5SDimitry Andric     if (Tok.isObjCAtKeyword(tok::objc_catch)) {
25980b57cec5SDimitry Andric       Decl *FirstPart = nullptr;
25990b57cec5SDimitry Andric       ConsumeToken(); // consume catch
26000b57cec5SDimitry Andric       if (Tok.is(tok::l_paren)) {
26010b57cec5SDimitry Andric         ConsumeParen();
26020b57cec5SDimitry Andric         ParseScope CatchScope(this, Scope::DeclScope |
26030b57cec5SDimitry Andric                                         Scope::CompoundStmtScope |
26040b57cec5SDimitry Andric                                         Scope::AtCatchScope);
26050b57cec5SDimitry Andric         if (Tok.isNot(tok::ellipsis)) {
26060b57cec5SDimitry Andric           DeclSpec DS(AttrFactory);
2607*0fca6ea1SDimitry Andric           ParsedTemplateInfo TemplateInfo;
2608*0fca6ea1SDimitry Andric           ParseDeclarationSpecifiers(DS, TemplateInfo);
260981ad6265SDimitry Andric           Declarator ParmDecl(DS, ParsedAttributesView::none(),
261081ad6265SDimitry Andric                               DeclaratorContext::ObjCCatch);
26110b57cec5SDimitry Andric           ParseDeclarator(ParmDecl);
26120b57cec5SDimitry Andric 
26130b57cec5SDimitry Andric           // Inform the actions module about the declarator, so it
26140b57cec5SDimitry Andric           // gets added to the current scope.
2615*0fca6ea1SDimitry Andric           FirstPart =
2616*0fca6ea1SDimitry Andric               Actions.ObjC().ActOnObjCExceptionDecl(getCurScope(), ParmDecl);
26170b57cec5SDimitry Andric         } else
26180b57cec5SDimitry Andric           ConsumeToken(); // consume '...'
26190b57cec5SDimitry Andric 
26200b57cec5SDimitry Andric         SourceLocation RParenLoc;
26210b57cec5SDimitry Andric 
26220b57cec5SDimitry Andric         if (Tok.is(tok::r_paren))
26230b57cec5SDimitry Andric           RParenLoc = ConsumeParen();
26240b57cec5SDimitry Andric         else // Skip over garbage, until we get to ')'.  Eat the ')'.
26250b57cec5SDimitry Andric           SkipUntil(tok::r_paren, StopAtSemi);
26260b57cec5SDimitry Andric 
26270b57cec5SDimitry Andric         StmtResult CatchBody(true);
26280b57cec5SDimitry Andric         if (Tok.is(tok::l_brace))
26290b57cec5SDimitry Andric           CatchBody = ParseCompoundStatementBody();
26300b57cec5SDimitry Andric         else
26310b57cec5SDimitry Andric           Diag(Tok, diag::err_expected) << tok::l_brace;
26320b57cec5SDimitry Andric         if (CatchBody.isInvalid())
26330b57cec5SDimitry Andric           CatchBody = Actions.ActOnNullStmt(Tok.getLocation());
26340b57cec5SDimitry Andric 
2635*0fca6ea1SDimitry Andric         StmtResult Catch = Actions.ObjC().ActOnObjCAtCatchStmt(
2636*0fca6ea1SDimitry Andric             AtCatchFinallyLoc, RParenLoc, FirstPart, CatchBody.get());
26370b57cec5SDimitry Andric         if (!Catch.isInvalid())
26380b57cec5SDimitry Andric           CatchStmts.push_back(Catch.get());
26390b57cec5SDimitry Andric 
26400b57cec5SDimitry Andric       } else {
26410b57cec5SDimitry Andric         Diag(AtCatchFinallyLoc, diag::err_expected_lparen_after)
26420b57cec5SDimitry Andric           << "@catch clause";
26430b57cec5SDimitry Andric         return StmtError();
26440b57cec5SDimitry Andric       }
26450b57cec5SDimitry Andric       catch_or_finally_seen = true;
26460b57cec5SDimitry Andric     } else {
26470b57cec5SDimitry Andric       assert(Tok.isObjCAtKeyword(tok::objc_finally) && "Lookahead confused?");
26480b57cec5SDimitry Andric       ConsumeToken(); // consume finally
26490b57cec5SDimitry Andric       ParseScope FinallyScope(this,
26500b57cec5SDimitry Andric                               Scope::DeclScope | Scope::CompoundStmtScope);
26510b57cec5SDimitry Andric 
26520b57cec5SDimitry Andric       bool ShouldCapture =
26530b57cec5SDimitry Andric           getTargetInfo().getTriple().isWindowsMSVCEnvironment();
26540b57cec5SDimitry Andric       if (ShouldCapture)
26550b57cec5SDimitry Andric         Actions.ActOnCapturedRegionStart(Tok.getLocation(), getCurScope(),
26560b57cec5SDimitry Andric                                          CR_ObjCAtFinally, 1);
26570b57cec5SDimitry Andric 
26580b57cec5SDimitry Andric       StmtResult FinallyBody(true);
26590b57cec5SDimitry Andric       if (Tok.is(tok::l_brace))
26600b57cec5SDimitry Andric         FinallyBody = ParseCompoundStatementBody();
26610b57cec5SDimitry Andric       else
26620b57cec5SDimitry Andric         Diag(Tok, diag::err_expected) << tok::l_brace;
26630b57cec5SDimitry Andric 
26640b57cec5SDimitry Andric       if (FinallyBody.isInvalid()) {
26650b57cec5SDimitry Andric         FinallyBody = Actions.ActOnNullStmt(Tok.getLocation());
26660b57cec5SDimitry Andric         if (ShouldCapture)
26670b57cec5SDimitry Andric           Actions.ActOnCapturedRegionError();
26680b57cec5SDimitry Andric       } else if (ShouldCapture) {
26690b57cec5SDimitry Andric         FinallyBody = Actions.ActOnCapturedRegionEnd(FinallyBody.get());
26700b57cec5SDimitry Andric       }
26710b57cec5SDimitry Andric 
2672*0fca6ea1SDimitry Andric       FinallyStmt = Actions.ObjC().ActOnObjCAtFinallyStmt(AtCatchFinallyLoc,
26730b57cec5SDimitry Andric                                                           FinallyBody.get());
26740b57cec5SDimitry Andric       catch_or_finally_seen = true;
26750b57cec5SDimitry Andric       break;
26760b57cec5SDimitry Andric     }
26770b57cec5SDimitry Andric   }
26780b57cec5SDimitry Andric   if (!catch_or_finally_seen) {
26790b57cec5SDimitry Andric     Diag(atLoc, diag::err_missing_catch_finally);
26800b57cec5SDimitry Andric     return StmtError();
26810b57cec5SDimitry Andric   }
26820b57cec5SDimitry Andric 
2683*0fca6ea1SDimitry Andric   return Actions.ObjC().ActOnObjCAtTryStmt(atLoc, TryBody.get(), CatchStmts,
26840b57cec5SDimitry Andric                                            FinallyStmt.get());
26850b57cec5SDimitry Andric }
26860b57cec5SDimitry Andric 
26870b57cec5SDimitry Andric /// objc-autoreleasepool-statement:
26880b57cec5SDimitry Andric ///   @autoreleasepool compound-statement
26890b57cec5SDimitry Andric ///
26900b57cec5SDimitry Andric StmtResult
26910b57cec5SDimitry Andric Parser::ParseObjCAutoreleasePoolStmt(SourceLocation atLoc) {
26920b57cec5SDimitry Andric   ConsumeToken(); // consume autoreleasepool
26930b57cec5SDimitry Andric   if (Tok.isNot(tok::l_brace)) {
26940b57cec5SDimitry Andric     Diag(Tok, diag::err_expected) << tok::l_brace;
26950b57cec5SDimitry Andric     return StmtError();
26960b57cec5SDimitry Andric   }
26970b57cec5SDimitry Andric   // Enter a scope to hold everything within the compound stmt.  Compound
26980b57cec5SDimitry Andric   // statements can always hold declarations.
26990b57cec5SDimitry Andric   ParseScope BodyScope(this, Scope::DeclScope | Scope::CompoundStmtScope);
27000b57cec5SDimitry Andric 
27010b57cec5SDimitry Andric   StmtResult AutoreleasePoolBody(ParseCompoundStatementBody());
27020b57cec5SDimitry Andric 
27030b57cec5SDimitry Andric   BodyScope.Exit();
27040b57cec5SDimitry Andric   if (AutoreleasePoolBody.isInvalid())
27050b57cec5SDimitry Andric     AutoreleasePoolBody = Actions.ActOnNullStmt(Tok.getLocation());
2706*0fca6ea1SDimitry Andric   return Actions.ObjC().ActOnObjCAutoreleasePoolStmt(atLoc,
27070b57cec5SDimitry Andric                                                      AutoreleasePoolBody.get());
27080b57cec5SDimitry Andric }
27090b57cec5SDimitry Andric 
27100b57cec5SDimitry Andric /// StashAwayMethodOrFunctionBodyTokens -  Consume the tokens and store them
27110b57cec5SDimitry Andric /// for later parsing.
27120b57cec5SDimitry Andric void Parser::StashAwayMethodOrFunctionBodyTokens(Decl *MDecl) {
27130b57cec5SDimitry Andric   if (SkipFunctionBodies && (!MDecl || Actions.canSkipFunctionBody(MDecl)) &&
27140b57cec5SDimitry Andric       trySkippingFunctionBody()) {
27150b57cec5SDimitry Andric     Actions.ActOnSkippedFunctionBody(MDecl);
27160b57cec5SDimitry Andric     return;
27170b57cec5SDimitry Andric   }
27180b57cec5SDimitry Andric 
27190b57cec5SDimitry Andric   LexedMethod* LM = new LexedMethod(this, MDecl);
27200b57cec5SDimitry Andric   CurParsedObjCImpl->LateParsedObjCMethods.push_back(LM);
27210b57cec5SDimitry Andric   CachedTokens &Toks = LM->Toks;
27220b57cec5SDimitry Andric   // Begin by storing the '{' or 'try' or ':' token.
27230b57cec5SDimitry Andric   Toks.push_back(Tok);
27240b57cec5SDimitry Andric   if (Tok.is(tok::kw_try)) {
27250b57cec5SDimitry Andric     ConsumeToken();
27260b57cec5SDimitry Andric     if (Tok.is(tok::colon)) {
27270b57cec5SDimitry Andric       Toks.push_back(Tok);
27280b57cec5SDimitry Andric       ConsumeToken();
27290b57cec5SDimitry Andric       while (Tok.isNot(tok::l_brace)) {
27300b57cec5SDimitry Andric         ConsumeAndStoreUntil(tok::l_paren, Toks, /*StopAtSemi=*/false);
27310b57cec5SDimitry Andric         ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/false);
27320b57cec5SDimitry Andric       }
27330b57cec5SDimitry Andric     }
27340b57cec5SDimitry Andric     Toks.push_back(Tok); // also store '{'
27350b57cec5SDimitry Andric   }
27360b57cec5SDimitry Andric   else if (Tok.is(tok::colon)) {
27370b57cec5SDimitry Andric     ConsumeToken();
27380b57cec5SDimitry Andric     // FIXME: This is wrong, due to C++11 braced initialization.
27390b57cec5SDimitry Andric     while (Tok.isNot(tok::l_brace)) {
27400b57cec5SDimitry Andric       ConsumeAndStoreUntil(tok::l_paren, Toks, /*StopAtSemi=*/false);
27410b57cec5SDimitry Andric       ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/false);
27420b57cec5SDimitry Andric     }
27430b57cec5SDimitry Andric     Toks.push_back(Tok); // also store '{'
27440b57cec5SDimitry Andric   }
27450b57cec5SDimitry Andric   ConsumeBrace();
27460b57cec5SDimitry Andric   // Consume everything up to (and including) the matching right brace.
27470b57cec5SDimitry Andric   ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false);
27480b57cec5SDimitry Andric   while (Tok.is(tok::kw_catch)) {
27490b57cec5SDimitry Andric     ConsumeAndStoreUntil(tok::l_brace, Toks, /*StopAtSemi=*/false);
27500b57cec5SDimitry Andric     ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false);
27510b57cec5SDimitry Andric   }
27520b57cec5SDimitry Andric }
27530b57cec5SDimitry Andric 
27540b57cec5SDimitry Andric ///   objc-method-def: objc-method-proto ';'[opt] '{' body '}'
27550b57cec5SDimitry Andric ///
27560b57cec5SDimitry Andric Decl *Parser::ParseObjCMethodDefinition() {
27570b57cec5SDimitry Andric   Decl *MDecl = ParseObjCMethodPrototype();
27580b57cec5SDimitry Andric 
27590b57cec5SDimitry Andric   PrettyDeclStackTraceEntry CrashInfo(Actions.Context, MDecl, Tok.getLocation(),
27600b57cec5SDimitry Andric                                       "parsing Objective-C method");
27610b57cec5SDimitry Andric 
27620b57cec5SDimitry Andric   // parse optional ';'
27630b57cec5SDimitry Andric   if (Tok.is(tok::semi)) {
27640b57cec5SDimitry Andric     if (CurParsedObjCImpl) {
27650b57cec5SDimitry Andric       Diag(Tok, diag::warn_semicolon_before_method_body)
27660b57cec5SDimitry Andric         << FixItHint::CreateRemoval(Tok.getLocation());
27670b57cec5SDimitry Andric     }
27680b57cec5SDimitry Andric     ConsumeToken();
27690b57cec5SDimitry Andric   }
27700b57cec5SDimitry Andric 
27710b57cec5SDimitry Andric   // We should have an opening brace now.
27720b57cec5SDimitry Andric   if (Tok.isNot(tok::l_brace)) {
27730b57cec5SDimitry Andric     Diag(Tok, diag::err_expected_method_body);
27740b57cec5SDimitry Andric 
27750b57cec5SDimitry Andric     // Skip over garbage, until we get to '{'.  Don't eat the '{'.
27760b57cec5SDimitry Andric     SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch);
27770b57cec5SDimitry Andric 
27780b57cec5SDimitry Andric     // If we didn't find the '{', bail out.
27790b57cec5SDimitry Andric     if (Tok.isNot(tok::l_brace))
27800b57cec5SDimitry Andric       return nullptr;
27810b57cec5SDimitry Andric   }
27820b57cec5SDimitry Andric 
27830b57cec5SDimitry Andric   if (!MDecl) {
27840b57cec5SDimitry Andric     ConsumeBrace();
27850b57cec5SDimitry Andric     SkipUntil(tok::r_brace);
27860b57cec5SDimitry Andric     return nullptr;
27870b57cec5SDimitry Andric   }
27880b57cec5SDimitry Andric 
27890b57cec5SDimitry Andric   // Allow the rest of sema to find private method decl implementations.
2790*0fca6ea1SDimitry Andric   Actions.ObjC().AddAnyMethodToGlobalPool(MDecl);
27910b57cec5SDimitry Andric   assert (CurParsedObjCImpl
27920b57cec5SDimitry Andric           && "ParseObjCMethodDefinition - Method out of @implementation");
27930b57cec5SDimitry Andric   // Consume the tokens and store them for later parsing.
27940b57cec5SDimitry Andric   StashAwayMethodOrFunctionBodyTokens(MDecl);
27950b57cec5SDimitry Andric   return MDecl;
27960b57cec5SDimitry Andric }
27970b57cec5SDimitry Andric 
27980b57cec5SDimitry Andric StmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc,
27990b57cec5SDimitry Andric                                         ParsedStmtContext StmtCtx) {
28000b57cec5SDimitry Andric   if (Tok.is(tok::code_completion)) {
28010b57cec5SDimitry Andric     cutOffParsing();
2802*0fca6ea1SDimitry Andric     Actions.CodeCompletion().CodeCompleteObjCAtStatement(getCurScope());
28030b57cec5SDimitry Andric     return StmtError();
28040b57cec5SDimitry Andric   }
28050b57cec5SDimitry Andric 
28060b57cec5SDimitry Andric   if (Tok.isObjCAtKeyword(tok::objc_try))
28070b57cec5SDimitry Andric     return ParseObjCTryStmt(AtLoc);
28080b57cec5SDimitry Andric 
28090b57cec5SDimitry Andric   if (Tok.isObjCAtKeyword(tok::objc_throw))
28100b57cec5SDimitry Andric     return ParseObjCThrowStmt(AtLoc);
28110b57cec5SDimitry Andric 
28120b57cec5SDimitry Andric   if (Tok.isObjCAtKeyword(tok::objc_synchronized))
28130b57cec5SDimitry Andric     return ParseObjCSynchronizedStmt(AtLoc);
28140b57cec5SDimitry Andric 
28150b57cec5SDimitry Andric   if (Tok.isObjCAtKeyword(tok::objc_autoreleasepool))
28160b57cec5SDimitry Andric     return ParseObjCAutoreleasePoolStmt(AtLoc);
28170b57cec5SDimitry Andric 
28180b57cec5SDimitry Andric   if (Tok.isObjCAtKeyword(tok::objc_import) &&
28190b57cec5SDimitry Andric       getLangOpts().DebuggerSupport) {
28200b57cec5SDimitry Andric     SkipUntil(tok::semi);
28210b57cec5SDimitry Andric     return Actions.ActOnNullStmt(Tok.getLocation());
28220b57cec5SDimitry Andric   }
28230b57cec5SDimitry Andric 
28240b57cec5SDimitry Andric   ExprStatementTokLoc = AtLoc;
28250b57cec5SDimitry Andric   ExprResult Res(ParseExpressionWithLeadingAt(AtLoc));
28260b57cec5SDimitry Andric   if (Res.isInvalid()) {
28270b57cec5SDimitry Andric     // If the expression is invalid, skip ahead to the next semicolon. Not
28280b57cec5SDimitry Andric     // doing this opens us up to the possibility of infinite loops if
28290b57cec5SDimitry Andric     // ParseExpression does not consume any tokens.
28300b57cec5SDimitry Andric     SkipUntil(tok::semi);
28310b57cec5SDimitry Andric     return StmtError();
28320b57cec5SDimitry Andric   }
28330b57cec5SDimitry Andric 
28340b57cec5SDimitry Andric   // Otherwise, eat the semicolon.
28350b57cec5SDimitry Andric   ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
28360b57cec5SDimitry Andric   return handleExprStmt(Res, StmtCtx);
28370b57cec5SDimitry Andric }
28380b57cec5SDimitry Andric 
28390b57cec5SDimitry Andric ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
28400b57cec5SDimitry Andric   switch (Tok.getKind()) {
28410b57cec5SDimitry Andric   case tok::code_completion:
28420b57cec5SDimitry Andric     cutOffParsing();
2843*0fca6ea1SDimitry Andric     Actions.CodeCompletion().CodeCompleteObjCAtExpression(getCurScope());
28440b57cec5SDimitry Andric     return ExprError();
28450b57cec5SDimitry Andric 
28460b57cec5SDimitry Andric   case tok::minus:
28470b57cec5SDimitry Andric   case tok::plus: {
28480b57cec5SDimitry Andric     tok::TokenKind Kind = Tok.getKind();
28490b57cec5SDimitry Andric     SourceLocation OpLoc = ConsumeToken();
28500b57cec5SDimitry Andric 
28510b57cec5SDimitry Andric     if (!Tok.is(tok::numeric_constant)) {
28520b57cec5SDimitry Andric       const char *Symbol = nullptr;
28530b57cec5SDimitry Andric       switch (Kind) {
28540b57cec5SDimitry Andric       case tok::minus: Symbol = "-"; break;
28550b57cec5SDimitry Andric       case tok::plus: Symbol = "+"; break;
28560b57cec5SDimitry Andric       default: llvm_unreachable("missing unary operator case");
28570b57cec5SDimitry Andric       }
28580b57cec5SDimitry Andric       Diag(Tok, diag::err_nsnumber_nonliteral_unary)
28590b57cec5SDimitry Andric         << Symbol;
28600b57cec5SDimitry Andric       return ExprError();
28610b57cec5SDimitry Andric     }
28620b57cec5SDimitry Andric 
28630b57cec5SDimitry Andric     ExprResult Lit(Actions.ActOnNumericConstant(Tok));
28640b57cec5SDimitry Andric     if (Lit.isInvalid()) {
28650b57cec5SDimitry Andric       return Lit;
28660b57cec5SDimitry Andric     }
28670b57cec5SDimitry Andric     ConsumeToken(); // Consume the literal token.
28680b57cec5SDimitry Andric 
28690b57cec5SDimitry Andric     Lit = Actions.ActOnUnaryOp(getCurScope(), OpLoc, Kind, Lit.get());
28700b57cec5SDimitry Andric     if (Lit.isInvalid())
28710b57cec5SDimitry Andric       return Lit;
28720b57cec5SDimitry Andric 
28730b57cec5SDimitry Andric     return ParsePostfixExpressionSuffix(
2874*0fca6ea1SDimitry Andric         Actions.ObjC().BuildObjCNumericLiteral(AtLoc, Lit.get()));
28750b57cec5SDimitry Andric   }
28760b57cec5SDimitry Andric 
28770b57cec5SDimitry Andric   case tok::string_literal:    // primary-expression: string-literal
28780b57cec5SDimitry Andric   case tok::wide_string_literal:
28790b57cec5SDimitry Andric     return ParsePostfixExpressionSuffix(ParseObjCStringLiteral(AtLoc));
28800b57cec5SDimitry Andric 
28810b57cec5SDimitry Andric   case tok::char_constant:
28820b57cec5SDimitry Andric     return ParsePostfixExpressionSuffix(ParseObjCCharacterLiteral(AtLoc));
28830b57cec5SDimitry Andric 
28840b57cec5SDimitry Andric   case tok::numeric_constant:
28850b57cec5SDimitry Andric     return ParsePostfixExpressionSuffix(ParseObjCNumericLiteral(AtLoc));
28860b57cec5SDimitry Andric 
28870b57cec5SDimitry Andric   case tok::kw_true:  // Objective-C++, etc.
28880b57cec5SDimitry Andric   case tok::kw___objc_yes: // c/c++/objc/objc++ __objc_yes
28890b57cec5SDimitry Andric     return ParsePostfixExpressionSuffix(ParseObjCBooleanLiteral(AtLoc, true));
28900b57cec5SDimitry Andric   case tok::kw_false: // Objective-C++, etc.
28910b57cec5SDimitry Andric   case tok::kw___objc_no: // c/c++/objc/objc++ __objc_no
28920b57cec5SDimitry Andric     return ParsePostfixExpressionSuffix(ParseObjCBooleanLiteral(AtLoc, false));
28930b57cec5SDimitry Andric 
28940b57cec5SDimitry Andric   case tok::l_square:
28950b57cec5SDimitry Andric     // Objective-C array literal
28960b57cec5SDimitry Andric     return ParsePostfixExpressionSuffix(ParseObjCArrayLiteral(AtLoc));
28970b57cec5SDimitry Andric 
28980b57cec5SDimitry Andric   case tok::l_brace:
28990b57cec5SDimitry Andric     // Objective-C dictionary literal
29000b57cec5SDimitry Andric     return ParsePostfixExpressionSuffix(ParseObjCDictionaryLiteral(AtLoc));
29010b57cec5SDimitry Andric 
29020b57cec5SDimitry Andric   case tok::l_paren:
29030b57cec5SDimitry Andric     // Objective-C boxed expression
29040b57cec5SDimitry Andric     return ParsePostfixExpressionSuffix(ParseObjCBoxedExpr(AtLoc));
29050b57cec5SDimitry Andric 
29060b57cec5SDimitry Andric   default:
29070b57cec5SDimitry Andric     if (Tok.getIdentifierInfo() == nullptr)
29080b57cec5SDimitry Andric       return ExprError(Diag(AtLoc, diag::err_unexpected_at));
29090b57cec5SDimitry Andric 
29100b57cec5SDimitry Andric     switch (Tok.getIdentifierInfo()->getObjCKeywordID()) {
29110b57cec5SDimitry Andric     case tok::objc_encode:
29120b57cec5SDimitry Andric       return ParsePostfixExpressionSuffix(ParseObjCEncodeExpression(AtLoc));
29130b57cec5SDimitry Andric     case tok::objc_protocol:
29140b57cec5SDimitry Andric       return ParsePostfixExpressionSuffix(ParseObjCProtocolExpression(AtLoc));
29150b57cec5SDimitry Andric     case tok::objc_selector:
29160b57cec5SDimitry Andric       return ParsePostfixExpressionSuffix(ParseObjCSelectorExpression(AtLoc));
29170b57cec5SDimitry Andric     case tok::objc_available:
29180b57cec5SDimitry Andric       return ParseAvailabilityCheckExpr(AtLoc);
29190b57cec5SDimitry Andric       default: {
29200b57cec5SDimitry Andric         const char *str = nullptr;
29210b57cec5SDimitry Andric         // Only provide the @try/@finally/@autoreleasepool fixit when we're sure
29220b57cec5SDimitry Andric         // that this is a proper statement where such directives could actually
29230b57cec5SDimitry Andric         // occur.
29240b57cec5SDimitry Andric         if (GetLookAheadToken(1).is(tok::l_brace) &&
29250b57cec5SDimitry Andric             ExprStatementTokLoc == AtLoc) {
29260b57cec5SDimitry Andric           char ch = Tok.getIdentifierInfo()->getNameStart()[0];
29270b57cec5SDimitry Andric           str =
29280b57cec5SDimitry Andric             ch == 't' ? "try"
29290b57cec5SDimitry Andric                       : (ch == 'f' ? "finally"
29300b57cec5SDimitry Andric                                    : (ch == 'a' ? "autoreleasepool" : nullptr));
29310b57cec5SDimitry Andric         }
29320b57cec5SDimitry Andric         if (str) {
29330b57cec5SDimitry Andric           SourceLocation kwLoc = Tok.getLocation();
29340b57cec5SDimitry Andric           return ExprError(Diag(AtLoc, diag::err_unexpected_at) <<
29350b57cec5SDimitry Andric                              FixItHint::CreateReplacement(kwLoc, str));
29360b57cec5SDimitry Andric         }
29370b57cec5SDimitry Andric         else
29380b57cec5SDimitry Andric           return ExprError(Diag(AtLoc, diag::err_unexpected_at));
29390b57cec5SDimitry Andric       }
29400b57cec5SDimitry Andric     }
29410b57cec5SDimitry Andric   }
29420b57cec5SDimitry Andric }
29430b57cec5SDimitry Andric 
29440b57cec5SDimitry Andric /// Parse the receiver of an Objective-C++ message send.
29450b57cec5SDimitry Andric ///
29460b57cec5SDimitry Andric /// This routine parses the receiver of a message send in
29470b57cec5SDimitry Andric /// Objective-C++ either as a type or as an expression. Note that this
29480b57cec5SDimitry Andric /// routine must not be called to parse a send to 'super', since it
29490b57cec5SDimitry Andric /// has no way to return such a result.
29500b57cec5SDimitry Andric ///
29510b57cec5SDimitry Andric /// \param IsExpr Whether the receiver was parsed as an expression.
29520b57cec5SDimitry Andric ///
29530b57cec5SDimitry Andric /// \param TypeOrExpr If the receiver was parsed as an expression (\c
29540b57cec5SDimitry Andric /// IsExpr is true), the parsed expression. If the receiver was parsed
29550b57cec5SDimitry Andric /// as a type (\c IsExpr is false), the parsed type.
29560b57cec5SDimitry Andric ///
29570b57cec5SDimitry Andric /// \returns True if an error occurred during parsing or semantic
29580b57cec5SDimitry Andric /// analysis, in which case the arguments do not have valid
29590b57cec5SDimitry Andric /// values. Otherwise, returns false for a successful parse.
29600b57cec5SDimitry Andric ///
29610b57cec5SDimitry Andric ///   objc-receiver: [C++]
29620b57cec5SDimitry Andric ///     'super' [not parsed here]
29630b57cec5SDimitry Andric ///     expression
29640b57cec5SDimitry Andric ///     simple-type-specifier
29650b57cec5SDimitry Andric ///     typename-specifier
29660b57cec5SDimitry Andric bool Parser::ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr) {
29670b57cec5SDimitry Andric   InMessageExpressionRAIIObject InMessage(*this, true);
29680b57cec5SDimitry Andric 
29690b57cec5SDimitry Andric   if (Tok.isOneOf(tok::identifier, tok::coloncolon, tok::kw_typename,
29700b57cec5SDimitry Andric                   tok::annot_cxxscope))
29710b57cec5SDimitry Andric     TryAnnotateTypeOrScopeToken();
29720b57cec5SDimitry Andric 
2973*0fca6ea1SDimitry Andric   if (!Tok.isSimpleTypeSpecifier(getLangOpts())) {
29740b57cec5SDimitry Andric     //   objc-receiver:
29750b57cec5SDimitry Andric     //     expression
29760b57cec5SDimitry Andric     // Make sure any typos in the receiver are corrected or diagnosed, so that
29770b57cec5SDimitry Andric     // proper recovery can happen. FIXME: Perhaps filter the corrected expr to
29780b57cec5SDimitry Andric     // only the things that are valid ObjC receivers?
29790b57cec5SDimitry Andric     ExprResult Receiver = Actions.CorrectDelayedTyposInExpr(ParseExpression());
29800b57cec5SDimitry Andric     if (Receiver.isInvalid())
29810b57cec5SDimitry Andric       return true;
29820b57cec5SDimitry Andric 
29830b57cec5SDimitry Andric     IsExpr = true;
29840b57cec5SDimitry Andric     TypeOrExpr = Receiver.get();
29850b57cec5SDimitry Andric     return false;
29860b57cec5SDimitry Andric   }
29870b57cec5SDimitry Andric 
29880b57cec5SDimitry Andric   // objc-receiver:
29890b57cec5SDimitry Andric   //   typename-specifier
29900b57cec5SDimitry Andric   //   simple-type-specifier
29910b57cec5SDimitry Andric   //   expression (that starts with one of the above)
29920b57cec5SDimitry Andric   DeclSpec DS(AttrFactory);
29930b57cec5SDimitry Andric   ParseCXXSimpleTypeSpecifier(DS);
29940b57cec5SDimitry Andric 
29950b57cec5SDimitry Andric   if (Tok.is(tok::l_paren)) {
29960b57cec5SDimitry Andric     // If we see an opening parentheses at this point, we are
29970b57cec5SDimitry Andric     // actually parsing an expression that starts with a
29980b57cec5SDimitry Andric     // function-style cast, e.g.,
29990b57cec5SDimitry Andric     //
30000b57cec5SDimitry Andric     //   postfix-expression:
30010b57cec5SDimitry Andric     //     simple-type-specifier ( expression-list [opt] )
30020b57cec5SDimitry Andric     //     typename-specifier ( expression-list [opt] )
30030b57cec5SDimitry Andric     //
30040b57cec5SDimitry Andric     // Parse the remainder of this case, then the (optional)
30050b57cec5SDimitry Andric     // postfix-expression suffix, followed by the (optional)
30060b57cec5SDimitry Andric     // right-hand side of the binary expression. We have an
30070b57cec5SDimitry Andric     // instance method.
30080b57cec5SDimitry Andric     ExprResult Receiver = ParseCXXTypeConstructExpression(DS);
30090b57cec5SDimitry Andric     if (!Receiver.isInvalid())
30100b57cec5SDimitry Andric       Receiver = ParsePostfixExpressionSuffix(Receiver.get());
30110b57cec5SDimitry Andric     if (!Receiver.isInvalid())
30120b57cec5SDimitry Andric       Receiver = ParseRHSOfBinaryExpression(Receiver.get(), prec::Comma);
30130b57cec5SDimitry Andric     if (Receiver.isInvalid())
30140b57cec5SDimitry Andric       return true;
30150b57cec5SDimitry Andric 
30160b57cec5SDimitry Andric     IsExpr = true;
30170b57cec5SDimitry Andric     TypeOrExpr = Receiver.get();
30180b57cec5SDimitry Andric     return false;
30190b57cec5SDimitry Andric   }
30200b57cec5SDimitry Andric 
30210b57cec5SDimitry Andric   // We have a class message. Turn the simple-type-specifier or
30220b57cec5SDimitry Andric   // typename-specifier we parsed into a type and parse the
30230b57cec5SDimitry Andric   // remainder of the class message.
302481ad6265SDimitry Andric   Declarator DeclaratorInfo(DS, ParsedAttributesView::none(),
302581ad6265SDimitry Andric                             DeclaratorContext::TypeName);
30267a6dacacSDimitry Andric   TypeResult Type = Actions.ActOnTypeName(DeclaratorInfo);
30270b57cec5SDimitry Andric   if (Type.isInvalid())
30280b57cec5SDimitry Andric     return true;
30290b57cec5SDimitry Andric 
30300b57cec5SDimitry Andric   IsExpr = false;
30310b57cec5SDimitry Andric   TypeOrExpr = Type.get().getAsOpaquePtr();
30320b57cec5SDimitry Andric   return false;
30330b57cec5SDimitry Andric }
30340b57cec5SDimitry Andric 
30350b57cec5SDimitry Andric /// Determine whether the parser is currently referring to a an
30360b57cec5SDimitry Andric /// Objective-C message send, using a simplified heuristic to avoid overhead.
30370b57cec5SDimitry Andric ///
30380b57cec5SDimitry Andric /// This routine will only return true for a subset of valid message-send
30390b57cec5SDimitry Andric /// expressions.
30400b57cec5SDimitry Andric bool Parser::isSimpleObjCMessageExpression() {
30410b57cec5SDimitry Andric   assert(Tok.is(tok::l_square) && getLangOpts().ObjC &&
30420b57cec5SDimitry Andric          "Incorrect start for isSimpleObjCMessageExpression");
30430b57cec5SDimitry Andric   return GetLookAheadToken(1).is(tok::identifier) &&
30440b57cec5SDimitry Andric          GetLookAheadToken(2).is(tok::identifier);
30450b57cec5SDimitry Andric }
30460b57cec5SDimitry Andric 
30470b57cec5SDimitry Andric bool Parser::isStartOfObjCClassMessageMissingOpenBracket() {
30480b57cec5SDimitry Andric   if (!getLangOpts().ObjC || !NextToken().is(tok::identifier) ||
30490b57cec5SDimitry Andric       InMessageExpression)
30500b57cec5SDimitry Andric     return false;
30510b57cec5SDimitry Andric 
30525ffd83dbSDimitry Andric   TypeResult Type;
30530b57cec5SDimitry Andric 
30540b57cec5SDimitry Andric   if (Tok.is(tok::annot_typename))
30550b57cec5SDimitry Andric     Type = getTypeAnnotation(Tok);
30560b57cec5SDimitry Andric   else if (Tok.is(tok::identifier))
30570b57cec5SDimitry Andric     Type = Actions.getTypeName(*Tok.getIdentifierInfo(), Tok.getLocation(),
30580b57cec5SDimitry Andric                                getCurScope());
30590b57cec5SDimitry Andric   else
30600b57cec5SDimitry Andric     return false;
30610b57cec5SDimitry Andric 
30625ffd83dbSDimitry Andric   // FIXME: Should not be querying properties of types from the parser.
30635ffd83dbSDimitry Andric   if (Type.isUsable() && Type.get().get()->isObjCObjectOrInterfaceType()) {
30640b57cec5SDimitry Andric     const Token &AfterNext = GetLookAheadToken(2);
30650b57cec5SDimitry Andric     if (AfterNext.isOneOf(tok::colon, tok::r_square)) {
30660b57cec5SDimitry Andric       if (Tok.is(tok::identifier))
30670b57cec5SDimitry Andric         TryAnnotateTypeOrScopeToken();
30680b57cec5SDimitry Andric 
30690b57cec5SDimitry Andric       return Tok.is(tok::annot_typename);
30700b57cec5SDimitry Andric     }
30710b57cec5SDimitry Andric   }
30720b57cec5SDimitry Andric 
30730b57cec5SDimitry Andric   return false;
30740b57cec5SDimitry Andric }
30750b57cec5SDimitry Andric 
30760b57cec5SDimitry Andric ///   objc-message-expr:
30770b57cec5SDimitry Andric ///     '[' objc-receiver objc-message-args ']'
30780b57cec5SDimitry Andric ///
30790b57cec5SDimitry Andric ///   objc-receiver: [C]
30800b57cec5SDimitry Andric ///     'super'
30810b57cec5SDimitry Andric ///     expression
30820b57cec5SDimitry Andric ///     class-name
30830b57cec5SDimitry Andric ///     type-name
30840b57cec5SDimitry Andric ///
30850b57cec5SDimitry Andric ExprResult Parser::ParseObjCMessageExpression() {
30860b57cec5SDimitry Andric   assert(Tok.is(tok::l_square) && "'[' expected");
30870b57cec5SDimitry Andric   SourceLocation LBracLoc = ConsumeBracket(); // consume '['
30880b57cec5SDimitry Andric 
30890b57cec5SDimitry Andric   if (Tok.is(tok::code_completion)) {
30900b57cec5SDimitry Andric     cutOffParsing();
3091*0fca6ea1SDimitry Andric     Actions.CodeCompletion().CodeCompleteObjCMessageReceiver(getCurScope());
30920b57cec5SDimitry Andric     return ExprError();
30930b57cec5SDimitry Andric   }
30940b57cec5SDimitry Andric 
30950b57cec5SDimitry Andric   InMessageExpressionRAIIObject InMessage(*this, true);
30960b57cec5SDimitry Andric 
30970b57cec5SDimitry Andric   if (getLangOpts().CPlusPlus) {
30980b57cec5SDimitry Andric     // We completely separate the C and C++ cases because C++ requires
30990b57cec5SDimitry Andric     // more complicated (read: slower) parsing.
31000b57cec5SDimitry Andric 
31010b57cec5SDimitry Andric     // Handle send to super.
31020b57cec5SDimitry Andric     // FIXME: This doesn't benefit from the same typo-correction we
31030b57cec5SDimitry Andric     // get in Objective-C.
31040b57cec5SDimitry Andric     if (Tok.is(tok::identifier) && Tok.getIdentifierInfo() == Ident_super &&
31050b57cec5SDimitry Andric         NextToken().isNot(tok::period) && getCurScope()->isInObjcMethodScope())
31060b57cec5SDimitry Andric       return ParseObjCMessageExpressionBody(LBracLoc, ConsumeToken(), nullptr,
31070b57cec5SDimitry Andric                                             nullptr);
31080b57cec5SDimitry Andric 
31090b57cec5SDimitry Andric     // Parse the receiver, which is either a type or an expression.
31100b57cec5SDimitry Andric     bool IsExpr;
31110b57cec5SDimitry Andric     void *TypeOrExpr = nullptr;
31120b57cec5SDimitry Andric     if (ParseObjCXXMessageReceiver(IsExpr, TypeOrExpr)) {
31130b57cec5SDimitry Andric       SkipUntil(tok::r_square, StopAtSemi);
31140b57cec5SDimitry Andric       return ExprError();
31150b57cec5SDimitry Andric     }
31160b57cec5SDimitry Andric 
31170b57cec5SDimitry Andric     if (IsExpr)
31180b57cec5SDimitry Andric       return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(), nullptr,
31190b57cec5SDimitry Andric                                             static_cast<Expr *>(TypeOrExpr));
31200b57cec5SDimitry Andric 
31210b57cec5SDimitry Andric     return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(),
31220b57cec5SDimitry Andric                               ParsedType::getFromOpaquePtr(TypeOrExpr),
31230b57cec5SDimitry Andric                                           nullptr);
31240b57cec5SDimitry Andric   }
31250b57cec5SDimitry Andric 
31260b57cec5SDimitry Andric   if (Tok.is(tok::identifier)) {
31270b57cec5SDimitry Andric     IdentifierInfo *Name = Tok.getIdentifierInfo();
31280b57cec5SDimitry Andric     SourceLocation NameLoc = Tok.getLocation();
31290b57cec5SDimitry Andric     ParsedType ReceiverType;
3130*0fca6ea1SDimitry Andric     switch (Actions.ObjC().getObjCMessageKind(
3131*0fca6ea1SDimitry Andric         getCurScope(), Name, NameLoc, Name == Ident_super,
3132*0fca6ea1SDimitry Andric         NextToken().is(tok::period), ReceiverType)) {
3133*0fca6ea1SDimitry Andric     case SemaObjC::ObjCSuperMessage:
31340b57cec5SDimitry Andric       return ParseObjCMessageExpressionBody(LBracLoc, ConsumeToken(), nullptr,
31350b57cec5SDimitry Andric                                             nullptr);
31360b57cec5SDimitry Andric 
3137*0fca6ea1SDimitry Andric     case SemaObjC::ObjCClassMessage:
31380b57cec5SDimitry Andric       if (!ReceiverType) {
31390b57cec5SDimitry Andric         SkipUntil(tok::r_square, StopAtSemi);
31400b57cec5SDimitry Andric         return ExprError();
31410b57cec5SDimitry Andric       }
31420b57cec5SDimitry Andric 
31430b57cec5SDimitry Andric       ConsumeToken(); // the type name
31440b57cec5SDimitry Andric 
31450b57cec5SDimitry Andric       // Parse type arguments and protocol qualifiers.
31460b57cec5SDimitry Andric       if (Tok.is(tok::less)) {
31470b57cec5SDimitry Andric         SourceLocation NewEndLoc;
31480b57cec5SDimitry Andric         TypeResult NewReceiverType
31490b57cec5SDimitry Andric           = parseObjCTypeArgsAndProtocolQualifiers(NameLoc, ReceiverType,
31500b57cec5SDimitry Andric                                                    /*consumeLastToken=*/true,
31510b57cec5SDimitry Andric                                                    NewEndLoc);
31520b57cec5SDimitry Andric         if (!NewReceiverType.isUsable()) {
31530b57cec5SDimitry Andric           SkipUntil(tok::r_square, StopAtSemi);
31540b57cec5SDimitry Andric           return ExprError();
31550b57cec5SDimitry Andric         }
31560b57cec5SDimitry Andric 
31570b57cec5SDimitry Andric         ReceiverType = NewReceiverType.get();
31580b57cec5SDimitry Andric       }
31590b57cec5SDimitry Andric 
31600b57cec5SDimitry Andric       return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(),
31610b57cec5SDimitry Andric                                             ReceiverType, nullptr);
31620b57cec5SDimitry Andric 
3163*0fca6ea1SDimitry Andric     case SemaObjC::ObjCInstanceMessage:
31640b57cec5SDimitry Andric       // Fall through to parse an expression.
31650b57cec5SDimitry Andric       break;
31660b57cec5SDimitry Andric     }
31670b57cec5SDimitry Andric   }
31680b57cec5SDimitry Andric 
31690b57cec5SDimitry Andric   // Otherwise, an arbitrary expression can be the receiver of a send.
31700b57cec5SDimitry Andric   ExprResult Res = Actions.CorrectDelayedTyposInExpr(ParseExpression());
31710b57cec5SDimitry Andric   if (Res.isInvalid()) {
31720b57cec5SDimitry Andric     SkipUntil(tok::r_square, StopAtSemi);
31730b57cec5SDimitry Andric     return Res;
31740b57cec5SDimitry Andric   }
31750b57cec5SDimitry Andric 
31760b57cec5SDimitry Andric   return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(), nullptr,
31770b57cec5SDimitry Andric                                         Res.get());
31780b57cec5SDimitry Andric }
31790b57cec5SDimitry Andric 
31800b57cec5SDimitry Andric /// Parse the remainder of an Objective-C message following the
31810b57cec5SDimitry Andric /// '[' objc-receiver.
31820b57cec5SDimitry Andric ///
31830b57cec5SDimitry Andric /// This routine handles sends to super, class messages (sent to a
31840b57cec5SDimitry Andric /// class name), and instance messages (sent to an object), and the
31850b57cec5SDimitry Andric /// target is represented by \p SuperLoc, \p ReceiverType, or \p
31860b57cec5SDimitry Andric /// ReceiverExpr, respectively. Only one of these parameters may have
31870b57cec5SDimitry Andric /// a valid value.
31880b57cec5SDimitry Andric ///
31890b57cec5SDimitry Andric /// \param LBracLoc The location of the opening '['.
31900b57cec5SDimitry Andric ///
31910b57cec5SDimitry Andric /// \param SuperLoc If this is a send to 'super', the location of the
31920b57cec5SDimitry Andric /// 'super' keyword that indicates a send to the superclass.
31930b57cec5SDimitry Andric ///
31940b57cec5SDimitry Andric /// \param ReceiverType If this is a class message, the type of the
31950b57cec5SDimitry Andric /// class we are sending a message to.
31960b57cec5SDimitry Andric ///
31970b57cec5SDimitry Andric /// \param ReceiverExpr If this is an instance message, the expression
31980b57cec5SDimitry Andric /// used to compute the receiver object.
31990b57cec5SDimitry Andric ///
32000b57cec5SDimitry Andric ///   objc-message-args:
32010b57cec5SDimitry Andric ///     objc-selector
32020b57cec5SDimitry Andric ///     objc-keywordarg-list
32030b57cec5SDimitry Andric ///
32040b57cec5SDimitry Andric ///   objc-keywordarg-list:
32050b57cec5SDimitry Andric ///     objc-keywordarg
32060b57cec5SDimitry Andric ///     objc-keywordarg-list objc-keywordarg
32070b57cec5SDimitry Andric ///
32080b57cec5SDimitry Andric ///   objc-keywordarg:
32090b57cec5SDimitry Andric ///     selector-name[opt] ':' objc-keywordexpr
32100b57cec5SDimitry Andric ///
32110b57cec5SDimitry Andric ///   objc-keywordexpr:
32120b57cec5SDimitry Andric ///     nonempty-expr-list
32130b57cec5SDimitry Andric ///
32140b57cec5SDimitry Andric ///   nonempty-expr-list:
32150b57cec5SDimitry Andric ///     assignment-expression
32160b57cec5SDimitry Andric ///     nonempty-expr-list , assignment-expression
32170b57cec5SDimitry Andric ///
32180b57cec5SDimitry Andric ExprResult
32190b57cec5SDimitry Andric Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
32200b57cec5SDimitry Andric                                        SourceLocation SuperLoc,
32210b57cec5SDimitry Andric                                        ParsedType ReceiverType,
32220b57cec5SDimitry Andric                                        Expr *ReceiverExpr) {
32230b57cec5SDimitry Andric   InMessageExpressionRAIIObject InMessage(*this, true);
32240b57cec5SDimitry Andric 
32250b57cec5SDimitry Andric   if (Tok.is(tok::code_completion)) {
3226fe6060f1SDimitry Andric     cutOffParsing();
32270b57cec5SDimitry Andric     if (SuperLoc.isValid())
3228*0fca6ea1SDimitry Andric       Actions.CodeCompletion().CodeCompleteObjCSuperMessage(
3229*0fca6ea1SDimitry Andric           getCurScope(), SuperLoc, std::nullopt, false);
32300b57cec5SDimitry Andric     else if (ReceiverType)
3231*0fca6ea1SDimitry Andric       Actions.CodeCompletion().CodeCompleteObjCClassMessage(
3232*0fca6ea1SDimitry Andric           getCurScope(), ReceiverType, std::nullopt, false);
32330b57cec5SDimitry Andric     else
3234*0fca6ea1SDimitry Andric       Actions.CodeCompletion().CodeCompleteObjCInstanceMessage(
3235*0fca6ea1SDimitry Andric           getCurScope(), ReceiverExpr, std::nullopt, false);
32360b57cec5SDimitry Andric     return ExprError();
32370b57cec5SDimitry Andric   }
32380b57cec5SDimitry Andric 
32390b57cec5SDimitry Andric   // Parse objc-selector
32400b57cec5SDimitry Andric   SourceLocation Loc;
32410b57cec5SDimitry Andric   IdentifierInfo *selIdent = ParseObjCSelectorPiece(Loc);
32420b57cec5SDimitry Andric 
3243*0fca6ea1SDimitry Andric   SmallVector<const IdentifierInfo *, 12> KeyIdents;
32440b57cec5SDimitry Andric   SmallVector<SourceLocation, 12> KeyLocs;
32450b57cec5SDimitry Andric   ExprVector KeyExprs;
32460b57cec5SDimitry Andric 
32470b57cec5SDimitry Andric   if (Tok.is(tok::colon)) {
324804eeddc0SDimitry Andric     while (true) {
32490b57cec5SDimitry Andric       // Each iteration parses a single keyword argument.
32500b57cec5SDimitry Andric       KeyIdents.push_back(selIdent);
32510b57cec5SDimitry Andric       KeyLocs.push_back(Loc);
32520b57cec5SDimitry Andric 
32530b57cec5SDimitry Andric       if (ExpectAndConsume(tok::colon)) {
32540b57cec5SDimitry Andric         // We must manually skip to a ']', otherwise the expression skipper will
32550b57cec5SDimitry Andric         // stop at the ']' when it skips to the ';'.  We want it to skip beyond
32560b57cec5SDimitry Andric         // the enclosing expression.
32570b57cec5SDimitry Andric         SkipUntil(tok::r_square, StopAtSemi);
32580b57cec5SDimitry Andric         return ExprError();
32590b57cec5SDimitry Andric       }
32600b57cec5SDimitry Andric 
32610b57cec5SDimitry Andric       ///  Parse the expression after ':'
32620b57cec5SDimitry Andric 
32630b57cec5SDimitry Andric       if (Tok.is(tok::code_completion)) {
3264fe6060f1SDimitry Andric         cutOffParsing();
32650b57cec5SDimitry Andric         if (SuperLoc.isValid())
3266*0fca6ea1SDimitry Andric           Actions.CodeCompletion().CodeCompleteObjCSuperMessage(
3267*0fca6ea1SDimitry Andric               getCurScope(), SuperLoc, KeyIdents,
32680b57cec5SDimitry Andric               /*AtArgumentExpression=*/true);
32690b57cec5SDimitry Andric         else if (ReceiverType)
3270*0fca6ea1SDimitry Andric           Actions.CodeCompletion().CodeCompleteObjCClassMessage(
3271*0fca6ea1SDimitry Andric               getCurScope(), ReceiverType, KeyIdents,
32720b57cec5SDimitry Andric               /*AtArgumentExpression=*/true);
32730b57cec5SDimitry Andric         else
3274*0fca6ea1SDimitry Andric           Actions.CodeCompletion().CodeCompleteObjCInstanceMessage(
3275*0fca6ea1SDimitry Andric               getCurScope(), ReceiverExpr, KeyIdents,
32760b57cec5SDimitry Andric               /*AtArgumentExpression=*/true);
32770b57cec5SDimitry Andric 
32780b57cec5SDimitry Andric         return ExprError();
32790b57cec5SDimitry Andric       }
32800b57cec5SDimitry Andric 
32810b57cec5SDimitry Andric       ExprResult Expr;
32820b57cec5SDimitry Andric       if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
32830b57cec5SDimitry Andric         Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
32840b57cec5SDimitry Andric         Expr = ParseBraceInitializer();
32850b57cec5SDimitry Andric       } else
32860b57cec5SDimitry Andric         Expr = ParseAssignmentExpression();
32870b57cec5SDimitry Andric 
32880b57cec5SDimitry Andric       ExprResult Res(Expr);
32890b57cec5SDimitry Andric       if (Res.isInvalid()) {
32900b57cec5SDimitry Andric         // We must manually skip to a ']', otherwise the expression skipper will
32910b57cec5SDimitry Andric         // stop at the ']' when it skips to the ';'.  We want it to skip beyond
32920b57cec5SDimitry Andric         // the enclosing expression.
32930b57cec5SDimitry Andric         SkipUntil(tok::r_square, StopAtSemi);
32940b57cec5SDimitry Andric         return Res;
32950b57cec5SDimitry Andric       }
32960b57cec5SDimitry Andric 
32970b57cec5SDimitry Andric       // We have a valid expression.
32980b57cec5SDimitry Andric       KeyExprs.push_back(Res.get());
32990b57cec5SDimitry Andric 
33000b57cec5SDimitry Andric       // Code completion after each argument.
33010b57cec5SDimitry Andric       if (Tok.is(tok::code_completion)) {
3302fe6060f1SDimitry Andric         cutOffParsing();
33030b57cec5SDimitry Andric         if (SuperLoc.isValid())
3304*0fca6ea1SDimitry Andric           Actions.CodeCompletion().CodeCompleteObjCSuperMessage(
3305*0fca6ea1SDimitry Andric               getCurScope(), SuperLoc, KeyIdents,
33060b57cec5SDimitry Andric               /*AtArgumentExpression=*/false);
33070b57cec5SDimitry Andric         else if (ReceiverType)
3308*0fca6ea1SDimitry Andric           Actions.CodeCompletion().CodeCompleteObjCClassMessage(
3309*0fca6ea1SDimitry Andric               getCurScope(), ReceiverType, KeyIdents,
33100b57cec5SDimitry Andric               /*AtArgumentExpression=*/false);
33110b57cec5SDimitry Andric         else
3312*0fca6ea1SDimitry Andric           Actions.CodeCompletion().CodeCompleteObjCInstanceMessage(
3313*0fca6ea1SDimitry Andric               getCurScope(), ReceiverExpr, KeyIdents,
33140b57cec5SDimitry Andric               /*AtArgumentExpression=*/false);
33150b57cec5SDimitry Andric         return ExprError();
33160b57cec5SDimitry Andric       }
33170b57cec5SDimitry Andric 
33180b57cec5SDimitry Andric       // Check for another keyword selector.
33190b57cec5SDimitry Andric       selIdent = ParseObjCSelectorPiece(Loc);
33200b57cec5SDimitry Andric       if (!selIdent && Tok.isNot(tok::colon))
33210b57cec5SDimitry Andric         break;
33220b57cec5SDimitry Andric       // We have a selector or a colon, continue parsing.
33230b57cec5SDimitry Andric     }
33240b57cec5SDimitry Andric     // Parse the, optional, argument list, comma separated.
33250b57cec5SDimitry Andric     while (Tok.is(tok::comma)) {
33260b57cec5SDimitry Andric       SourceLocation commaLoc = ConsumeToken(); // Eat the ','.
33270b57cec5SDimitry Andric       ///  Parse the expression after ','
33280b57cec5SDimitry Andric       ExprResult Res(ParseAssignmentExpression());
33290b57cec5SDimitry Andric       if (Tok.is(tok::colon))
33300b57cec5SDimitry Andric         Res = Actions.CorrectDelayedTyposInExpr(Res);
33310b57cec5SDimitry Andric       if (Res.isInvalid()) {
33320b57cec5SDimitry Andric         if (Tok.is(tok::colon)) {
33330b57cec5SDimitry Andric           Diag(commaLoc, diag::note_extra_comma_message_arg) <<
33340b57cec5SDimitry Andric             FixItHint::CreateRemoval(commaLoc);
33350b57cec5SDimitry Andric         }
33360b57cec5SDimitry Andric         // We must manually skip to a ']', otherwise the expression skipper will
33370b57cec5SDimitry Andric         // stop at the ']' when it skips to the ';'.  We want it to skip beyond
33380b57cec5SDimitry Andric         // the enclosing expression.
33390b57cec5SDimitry Andric         SkipUntil(tok::r_square, StopAtSemi);
33400b57cec5SDimitry Andric         return Res;
33410b57cec5SDimitry Andric       }
33420b57cec5SDimitry Andric 
33430b57cec5SDimitry Andric       // We have a valid expression.
33440b57cec5SDimitry Andric       KeyExprs.push_back(Res.get());
33450b57cec5SDimitry Andric     }
33460b57cec5SDimitry Andric   } else if (!selIdent) {
33470b57cec5SDimitry Andric     Diag(Tok, diag::err_expected) << tok::identifier; // missing selector name.
33480b57cec5SDimitry Andric 
33490b57cec5SDimitry Andric     // We must manually skip to a ']', otherwise the expression skipper will
33500b57cec5SDimitry Andric     // stop at the ']' when it skips to the ';'.  We want it to skip beyond
33510b57cec5SDimitry Andric     // the enclosing expression.
33520b57cec5SDimitry Andric     SkipUntil(tok::r_square, StopAtSemi);
33530b57cec5SDimitry Andric     return ExprError();
33540b57cec5SDimitry Andric   }
33550b57cec5SDimitry Andric 
33560b57cec5SDimitry Andric   if (Tok.isNot(tok::r_square)) {
33570b57cec5SDimitry Andric     Diag(Tok, diag::err_expected)
33580b57cec5SDimitry Andric         << (Tok.is(tok::identifier) ? tok::colon : tok::r_square);
33590b57cec5SDimitry Andric     // We must manually skip to a ']', otherwise the expression skipper will
33600b57cec5SDimitry Andric     // stop at the ']' when it skips to the ';'.  We want it to skip beyond
33610b57cec5SDimitry Andric     // the enclosing expression.
33620b57cec5SDimitry Andric     SkipUntil(tok::r_square, StopAtSemi);
33630b57cec5SDimitry Andric     return ExprError();
33640b57cec5SDimitry Andric   }
33650b57cec5SDimitry Andric 
33660b57cec5SDimitry Andric   SourceLocation RBracLoc = ConsumeBracket(); // consume ']'
33670b57cec5SDimitry Andric 
33680b57cec5SDimitry Andric   unsigned nKeys = KeyIdents.size();
33690b57cec5SDimitry Andric   if (nKeys == 0) {
33700b57cec5SDimitry Andric     KeyIdents.push_back(selIdent);
33710b57cec5SDimitry Andric     KeyLocs.push_back(Loc);
33720b57cec5SDimitry Andric   }
33730b57cec5SDimitry Andric   Selector Sel = PP.getSelectorTable().getSelector(nKeys, &KeyIdents[0]);
33740b57cec5SDimitry Andric 
33750b57cec5SDimitry Andric   if (SuperLoc.isValid())
3376*0fca6ea1SDimitry Andric     return Actions.ObjC().ActOnSuperMessage(
3377*0fca6ea1SDimitry Andric         getCurScope(), SuperLoc, Sel, LBracLoc, KeyLocs, RBracLoc, KeyExprs);
33780b57cec5SDimitry Andric   else if (ReceiverType)
3379*0fca6ea1SDimitry Andric     return Actions.ObjC().ActOnClassMessage(getCurScope(), ReceiverType, Sel,
3380*0fca6ea1SDimitry Andric                                             LBracLoc, KeyLocs, RBracLoc,
3381*0fca6ea1SDimitry Andric                                             KeyExprs);
3382*0fca6ea1SDimitry Andric   return Actions.ObjC().ActOnInstanceMessage(
3383*0fca6ea1SDimitry Andric       getCurScope(), ReceiverExpr, Sel, LBracLoc, KeyLocs, RBracLoc, KeyExprs);
33840b57cec5SDimitry Andric }
33850b57cec5SDimitry Andric 
33860b57cec5SDimitry Andric ExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) {
33870b57cec5SDimitry Andric   ExprResult Res(ParseStringLiteralExpression());
33880b57cec5SDimitry Andric   if (Res.isInvalid()) return Res;
33890b57cec5SDimitry Andric 
33900b57cec5SDimitry Andric   // @"foo" @"bar" is a valid concatenated string.  Eat any subsequent string
33910b57cec5SDimitry Andric   // expressions.  At this point, we know that the only valid thing that starts
33920b57cec5SDimitry Andric   // with '@' is an @"".
33930b57cec5SDimitry Andric   SmallVector<SourceLocation, 4> AtLocs;
33940b57cec5SDimitry Andric   ExprVector AtStrings;
33950b57cec5SDimitry Andric   AtLocs.push_back(AtLoc);
33960b57cec5SDimitry Andric   AtStrings.push_back(Res.get());
33970b57cec5SDimitry Andric 
33980b57cec5SDimitry Andric   while (Tok.is(tok::at)) {
33990b57cec5SDimitry Andric     AtLocs.push_back(ConsumeToken()); // eat the @.
34000b57cec5SDimitry Andric 
34010b57cec5SDimitry Andric     // Invalid unless there is a string literal.
34020b57cec5SDimitry Andric     if (!isTokenStringLiteral())
34030b57cec5SDimitry Andric       return ExprError(Diag(Tok, diag::err_objc_concat_string));
34040b57cec5SDimitry Andric 
34050b57cec5SDimitry Andric     ExprResult Lit(ParseStringLiteralExpression());
34060b57cec5SDimitry Andric     if (Lit.isInvalid())
34070b57cec5SDimitry Andric       return Lit;
34080b57cec5SDimitry Andric 
34090b57cec5SDimitry Andric     AtStrings.push_back(Lit.get());
34100b57cec5SDimitry Andric   }
34110b57cec5SDimitry Andric 
3412*0fca6ea1SDimitry Andric   return Actions.ObjC().ParseObjCStringLiteral(AtLocs.data(), AtStrings);
34130b57cec5SDimitry Andric }
34140b57cec5SDimitry Andric 
34150b57cec5SDimitry Andric /// ParseObjCBooleanLiteral -
34160b57cec5SDimitry Andric /// objc-scalar-literal : '@' boolean-keyword
34170b57cec5SDimitry Andric ///                        ;
34180b57cec5SDimitry Andric /// boolean-keyword: 'true' | 'false' | '__objc_yes' | '__objc_no'
34190b57cec5SDimitry Andric ///                        ;
34200b57cec5SDimitry Andric ExprResult Parser::ParseObjCBooleanLiteral(SourceLocation AtLoc,
34210b57cec5SDimitry Andric                                            bool ArgValue) {
34220b57cec5SDimitry Andric   SourceLocation EndLoc = ConsumeToken();             // consume the keyword.
3423*0fca6ea1SDimitry Andric   return Actions.ObjC().ActOnObjCBoolLiteral(AtLoc, EndLoc, ArgValue);
34240b57cec5SDimitry Andric }
34250b57cec5SDimitry Andric 
34260b57cec5SDimitry Andric /// ParseObjCCharacterLiteral -
34270b57cec5SDimitry Andric /// objc-scalar-literal : '@' character-literal
34280b57cec5SDimitry Andric ///                        ;
34290b57cec5SDimitry Andric ExprResult Parser::ParseObjCCharacterLiteral(SourceLocation AtLoc) {
34300b57cec5SDimitry Andric   ExprResult Lit(Actions.ActOnCharacterConstant(Tok));
34310b57cec5SDimitry Andric   if (Lit.isInvalid()) {
34320b57cec5SDimitry Andric     return Lit;
34330b57cec5SDimitry Andric   }
34340b57cec5SDimitry Andric   ConsumeToken(); // Consume the literal token.
3435*0fca6ea1SDimitry Andric   return Actions.ObjC().BuildObjCNumericLiteral(AtLoc, Lit.get());
34360b57cec5SDimitry Andric }
34370b57cec5SDimitry Andric 
34380b57cec5SDimitry Andric /// ParseObjCNumericLiteral -
34390b57cec5SDimitry Andric /// objc-scalar-literal : '@' scalar-literal
34400b57cec5SDimitry Andric ///                        ;
34410b57cec5SDimitry Andric /// scalar-literal : | numeric-constant			/* any numeric constant. */
34420b57cec5SDimitry Andric ///                    ;
34430b57cec5SDimitry Andric ExprResult Parser::ParseObjCNumericLiteral(SourceLocation AtLoc) {
34440b57cec5SDimitry Andric   ExprResult Lit(Actions.ActOnNumericConstant(Tok));
34450b57cec5SDimitry Andric   if (Lit.isInvalid()) {
34460b57cec5SDimitry Andric     return Lit;
34470b57cec5SDimitry Andric   }
34480b57cec5SDimitry Andric   ConsumeToken(); // Consume the literal token.
3449*0fca6ea1SDimitry Andric   return Actions.ObjC().BuildObjCNumericLiteral(AtLoc, Lit.get());
34500b57cec5SDimitry Andric }
34510b57cec5SDimitry Andric 
34520b57cec5SDimitry Andric /// ParseObjCBoxedExpr -
34530b57cec5SDimitry Andric /// objc-box-expression:
34540b57cec5SDimitry Andric ///       @( assignment-expression )
34550b57cec5SDimitry Andric ExprResult
34560b57cec5SDimitry Andric Parser::ParseObjCBoxedExpr(SourceLocation AtLoc) {
34570b57cec5SDimitry Andric   if (Tok.isNot(tok::l_paren))
34580b57cec5SDimitry Andric     return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@");
34590b57cec5SDimitry Andric 
34600b57cec5SDimitry Andric   BalancedDelimiterTracker T(*this, tok::l_paren);
34610b57cec5SDimitry Andric   T.consumeOpen();
34620b57cec5SDimitry Andric   ExprResult ValueExpr(ParseAssignmentExpression());
34630b57cec5SDimitry Andric   if (T.consumeClose())
34640b57cec5SDimitry Andric     return ExprError();
34650b57cec5SDimitry Andric 
34660b57cec5SDimitry Andric   if (ValueExpr.isInvalid())
34670b57cec5SDimitry Andric     return ExprError();
34680b57cec5SDimitry Andric 
34690b57cec5SDimitry Andric   // Wrap the sub-expression in a parenthesized expression, to distinguish
34700b57cec5SDimitry Andric   // a boxed expression from a literal.
34710b57cec5SDimitry Andric   SourceLocation LPLoc = T.getOpenLocation(), RPLoc = T.getCloseLocation();
34720b57cec5SDimitry Andric   ValueExpr = Actions.ActOnParenExpr(LPLoc, RPLoc, ValueExpr.get());
3473*0fca6ea1SDimitry Andric   return Actions.ObjC().BuildObjCBoxedExpr(SourceRange(AtLoc, RPLoc),
34740b57cec5SDimitry Andric                                            ValueExpr.get());
34750b57cec5SDimitry Andric }
34760b57cec5SDimitry Andric 
34770b57cec5SDimitry Andric ExprResult Parser::ParseObjCArrayLiteral(SourceLocation AtLoc) {
34780b57cec5SDimitry Andric   ExprVector ElementExprs;                   // array elements.
34790b57cec5SDimitry Andric   ConsumeBracket(); // consume the l_square.
34800b57cec5SDimitry Andric 
34810b57cec5SDimitry Andric   bool HasInvalidEltExpr = false;
34820b57cec5SDimitry Andric   while (Tok.isNot(tok::r_square)) {
34830b57cec5SDimitry Andric     // Parse list of array element expressions (all must be id types).
34840b57cec5SDimitry Andric     ExprResult Res(ParseAssignmentExpression());
34850b57cec5SDimitry Andric     if (Res.isInvalid()) {
34860b57cec5SDimitry Andric       // We must manually skip to a ']', otherwise the expression skipper will
34870b57cec5SDimitry Andric       // stop at the ']' when it skips to the ';'.  We want it to skip beyond
34880b57cec5SDimitry Andric       // the enclosing expression.
34890b57cec5SDimitry Andric       SkipUntil(tok::r_square, StopAtSemi);
34900b57cec5SDimitry Andric       return Res;
34910b57cec5SDimitry Andric     }
34920b57cec5SDimitry Andric 
34930b57cec5SDimitry Andric     Res = Actions.CorrectDelayedTyposInExpr(Res.get());
34940b57cec5SDimitry Andric     if (Res.isInvalid())
34950b57cec5SDimitry Andric       HasInvalidEltExpr = true;
34960b57cec5SDimitry Andric 
34970b57cec5SDimitry Andric     // Parse the ellipsis that indicates a pack expansion.
34980b57cec5SDimitry Andric     if (Tok.is(tok::ellipsis))
34990b57cec5SDimitry Andric       Res = Actions.ActOnPackExpansion(Res.get(), ConsumeToken());
35000b57cec5SDimitry Andric     if (Res.isInvalid())
35010b57cec5SDimitry Andric       HasInvalidEltExpr = true;
35020b57cec5SDimitry Andric 
35030b57cec5SDimitry Andric     ElementExprs.push_back(Res.get());
35040b57cec5SDimitry Andric 
35050b57cec5SDimitry Andric     if (Tok.is(tok::comma))
35060b57cec5SDimitry Andric       ConsumeToken(); // Eat the ','.
35070b57cec5SDimitry Andric     else if (Tok.isNot(tok::r_square))
35080b57cec5SDimitry Andric       return ExprError(Diag(Tok, diag::err_expected_either) << tok::r_square
35090b57cec5SDimitry Andric                                                             << tok::comma);
35100b57cec5SDimitry Andric   }
35110b57cec5SDimitry Andric   SourceLocation EndLoc = ConsumeBracket(); // location of ']'
35120b57cec5SDimitry Andric 
35130b57cec5SDimitry Andric   if (HasInvalidEltExpr)
35140b57cec5SDimitry Andric     return ExprError();
35150b57cec5SDimitry Andric 
35160b57cec5SDimitry Andric   MultiExprArg Args(ElementExprs);
3517*0fca6ea1SDimitry Andric   return Actions.ObjC().BuildObjCArrayLiteral(SourceRange(AtLoc, EndLoc), Args);
35180b57cec5SDimitry Andric }
35190b57cec5SDimitry Andric 
35200b57cec5SDimitry Andric ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) {
35210b57cec5SDimitry Andric   SmallVector<ObjCDictionaryElement, 4> Elements; // dictionary elements.
35220b57cec5SDimitry Andric   ConsumeBrace(); // consume the l_square.
35230b57cec5SDimitry Andric   bool HasInvalidEltExpr = false;
35240b57cec5SDimitry Andric   while (Tok.isNot(tok::r_brace)) {
35250b57cec5SDimitry Andric     // Parse the comma separated key : value expressions.
35260b57cec5SDimitry Andric     ExprResult KeyExpr;
35270b57cec5SDimitry Andric     {
35280b57cec5SDimitry Andric       ColonProtectionRAIIObject X(*this);
35290b57cec5SDimitry Andric       KeyExpr = ParseAssignmentExpression();
35300b57cec5SDimitry Andric       if (KeyExpr.isInvalid()) {
35310b57cec5SDimitry Andric         // We must manually skip to a '}', otherwise the expression skipper will
35320b57cec5SDimitry Andric         // stop at the '}' when it skips to the ';'.  We want it to skip beyond
35330b57cec5SDimitry Andric         // the enclosing expression.
35340b57cec5SDimitry Andric         SkipUntil(tok::r_brace, StopAtSemi);
35350b57cec5SDimitry Andric         return KeyExpr;
35360b57cec5SDimitry Andric       }
35370b57cec5SDimitry Andric     }
35380b57cec5SDimitry Andric 
35390b57cec5SDimitry Andric     if (ExpectAndConsume(tok::colon)) {
35400b57cec5SDimitry Andric       SkipUntil(tok::r_brace, StopAtSemi);
35410b57cec5SDimitry Andric       return ExprError();
35420b57cec5SDimitry Andric     }
35430b57cec5SDimitry Andric 
35440b57cec5SDimitry Andric     ExprResult ValueExpr(ParseAssignmentExpression());
35450b57cec5SDimitry Andric     if (ValueExpr.isInvalid()) {
35460b57cec5SDimitry Andric       // We must manually skip to a '}', otherwise the expression skipper will
35470b57cec5SDimitry Andric       // stop at the '}' when it skips to the ';'.  We want it to skip beyond
35480b57cec5SDimitry Andric       // the enclosing expression.
35490b57cec5SDimitry Andric       SkipUntil(tok::r_brace, StopAtSemi);
35500b57cec5SDimitry Andric       return ValueExpr;
35510b57cec5SDimitry Andric     }
35520b57cec5SDimitry Andric 
35530b57cec5SDimitry Andric     // Check the key and value for possible typos
35540b57cec5SDimitry Andric     KeyExpr = Actions.CorrectDelayedTyposInExpr(KeyExpr.get());
35550b57cec5SDimitry Andric     ValueExpr = Actions.CorrectDelayedTyposInExpr(ValueExpr.get());
35560b57cec5SDimitry Andric     if (KeyExpr.isInvalid() || ValueExpr.isInvalid())
35570b57cec5SDimitry Andric       HasInvalidEltExpr = true;
35580b57cec5SDimitry Andric 
35590b57cec5SDimitry Andric     // Parse the ellipsis that designates this as a pack expansion. Do not
35600b57cec5SDimitry Andric     // ActOnPackExpansion here, leave it to template instantiation time where
35610b57cec5SDimitry Andric     // we can get better diagnostics.
35620b57cec5SDimitry Andric     SourceLocation EllipsisLoc;
35630b57cec5SDimitry Andric     if (getLangOpts().CPlusPlus)
35640b57cec5SDimitry Andric       TryConsumeToken(tok::ellipsis, EllipsisLoc);
35650b57cec5SDimitry Andric 
35660b57cec5SDimitry Andric     // We have a valid expression. Collect it in a vector so we can
35670b57cec5SDimitry Andric     // build the argument list.
3568bdd1243dSDimitry Andric     ObjCDictionaryElement Element = {KeyExpr.get(), ValueExpr.get(),
3569bdd1243dSDimitry Andric                                      EllipsisLoc, std::nullopt};
35700b57cec5SDimitry Andric     Elements.push_back(Element);
35710b57cec5SDimitry Andric 
35720b57cec5SDimitry Andric     if (!TryConsumeToken(tok::comma) && Tok.isNot(tok::r_brace))
35730b57cec5SDimitry Andric       return ExprError(Diag(Tok, diag::err_expected_either) << tok::r_brace
35740b57cec5SDimitry Andric                                                             << tok::comma);
35750b57cec5SDimitry Andric   }
35760b57cec5SDimitry Andric   SourceLocation EndLoc = ConsumeBrace();
35770b57cec5SDimitry Andric 
35780b57cec5SDimitry Andric   if (HasInvalidEltExpr)
35790b57cec5SDimitry Andric     return ExprError();
35800b57cec5SDimitry Andric 
35810b57cec5SDimitry Andric   // Create the ObjCDictionaryLiteral.
3582*0fca6ea1SDimitry Andric   return Actions.ObjC().BuildObjCDictionaryLiteral(SourceRange(AtLoc, EndLoc),
35830b57cec5SDimitry Andric                                                    Elements);
35840b57cec5SDimitry Andric }
35850b57cec5SDimitry Andric 
35860b57cec5SDimitry Andric ///    objc-encode-expression:
35870b57cec5SDimitry Andric ///      \@encode ( type-name )
35880b57cec5SDimitry Andric ExprResult
35890b57cec5SDimitry Andric Parser::ParseObjCEncodeExpression(SourceLocation AtLoc) {
35900b57cec5SDimitry Andric   assert(Tok.isObjCAtKeyword(tok::objc_encode) && "Not an @encode expression!");
35910b57cec5SDimitry Andric 
35920b57cec5SDimitry Andric   SourceLocation EncLoc = ConsumeToken();
35930b57cec5SDimitry Andric 
35940b57cec5SDimitry Andric   if (Tok.isNot(tok::l_paren))
35950b57cec5SDimitry Andric     return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@encode");
35960b57cec5SDimitry Andric 
35970b57cec5SDimitry Andric   BalancedDelimiterTracker T(*this, tok::l_paren);
35980b57cec5SDimitry Andric   T.consumeOpen();
35990b57cec5SDimitry Andric 
36000b57cec5SDimitry Andric   TypeResult Ty = ParseTypeName();
36010b57cec5SDimitry Andric 
36020b57cec5SDimitry Andric   T.consumeClose();
36030b57cec5SDimitry Andric 
36040b57cec5SDimitry Andric   if (Ty.isInvalid())
36050b57cec5SDimitry Andric     return ExprError();
36060b57cec5SDimitry Andric 
3607*0fca6ea1SDimitry Andric   return Actions.ObjC().ParseObjCEncodeExpression(
3608*0fca6ea1SDimitry Andric       AtLoc, EncLoc, T.getOpenLocation(), Ty.get(), T.getCloseLocation());
36090b57cec5SDimitry Andric }
36100b57cec5SDimitry Andric 
36110b57cec5SDimitry Andric ///     objc-protocol-expression
36120b57cec5SDimitry Andric ///       \@protocol ( protocol-name )
36130b57cec5SDimitry Andric ExprResult
36140b57cec5SDimitry Andric Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) {
36150b57cec5SDimitry Andric   SourceLocation ProtoLoc = ConsumeToken();
36160b57cec5SDimitry Andric 
36170b57cec5SDimitry Andric   if (Tok.isNot(tok::l_paren))
36180b57cec5SDimitry Andric     return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@protocol");
36190b57cec5SDimitry Andric 
36200b57cec5SDimitry Andric   BalancedDelimiterTracker T(*this, tok::l_paren);
36210b57cec5SDimitry Andric   T.consumeOpen();
36220b57cec5SDimitry Andric 
36230b57cec5SDimitry Andric   if (expectIdentifier())
36240b57cec5SDimitry Andric     return ExprError();
36250b57cec5SDimitry Andric 
36260b57cec5SDimitry Andric   IdentifierInfo *protocolId = Tok.getIdentifierInfo();
36270b57cec5SDimitry Andric   SourceLocation ProtoIdLoc = ConsumeToken();
36280b57cec5SDimitry Andric 
36290b57cec5SDimitry Andric   T.consumeClose();
36300b57cec5SDimitry Andric 
3631*0fca6ea1SDimitry Andric   return Actions.ObjC().ParseObjCProtocolExpression(
3632*0fca6ea1SDimitry Andric       protocolId, AtLoc, ProtoLoc, T.getOpenLocation(), ProtoIdLoc,
36330b57cec5SDimitry Andric       T.getCloseLocation());
36340b57cec5SDimitry Andric }
36350b57cec5SDimitry Andric 
36360b57cec5SDimitry Andric ///     objc-selector-expression
36370b57cec5SDimitry Andric ///       @selector '(' '('[opt] objc-keyword-selector ')'[opt] ')'
36380b57cec5SDimitry Andric ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) {
36390b57cec5SDimitry Andric   SourceLocation SelectorLoc = ConsumeToken();
36400b57cec5SDimitry Andric 
36410b57cec5SDimitry Andric   if (Tok.isNot(tok::l_paren))
36420b57cec5SDimitry Andric     return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@selector");
36430b57cec5SDimitry Andric 
3644*0fca6ea1SDimitry Andric   SmallVector<const IdentifierInfo *, 12> KeyIdents;
36450b57cec5SDimitry Andric   SourceLocation sLoc;
36460b57cec5SDimitry Andric 
36470b57cec5SDimitry Andric   BalancedDelimiterTracker T(*this, tok::l_paren);
36480b57cec5SDimitry Andric   T.consumeOpen();
36490b57cec5SDimitry Andric   bool HasOptionalParen = Tok.is(tok::l_paren);
36500b57cec5SDimitry Andric   if (HasOptionalParen)
36510b57cec5SDimitry Andric     ConsumeParen();
36520b57cec5SDimitry Andric 
36530b57cec5SDimitry Andric   if (Tok.is(tok::code_completion)) {
36540b57cec5SDimitry Andric     cutOffParsing();
3655*0fca6ea1SDimitry Andric     Actions.CodeCompletion().CodeCompleteObjCSelector(getCurScope(), KeyIdents);
36560b57cec5SDimitry Andric     return ExprError();
36570b57cec5SDimitry Andric   }
36580b57cec5SDimitry Andric 
36590b57cec5SDimitry Andric   IdentifierInfo *SelIdent = ParseObjCSelectorPiece(sLoc);
36600b57cec5SDimitry Andric   if (!SelIdent &&  // missing selector name.
36610b57cec5SDimitry Andric       Tok.isNot(tok::colon) && Tok.isNot(tok::coloncolon))
36620b57cec5SDimitry Andric     return ExprError(Diag(Tok, diag::err_expected) << tok::identifier);
36630b57cec5SDimitry Andric 
36640b57cec5SDimitry Andric   KeyIdents.push_back(SelIdent);
36650b57cec5SDimitry Andric 
36660b57cec5SDimitry Andric   unsigned nColons = 0;
36670b57cec5SDimitry Andric   if (Tok.isNot(tok::r_paren)) {
366804eeddc0SDimitry Andric     while (true) {
36690b57cec5SDimitry Andric       if (TryConsumeToken(tok::coloncolon)) { // Handle :: in C++.
36700b57cec5SDimitry Andric         ++nColons;
36710b57cec5SDimitry Andric         KeyIdents.push_back(nullptr);
36720b57cec5SDimitry Andric       } else if (ExpectAndConsume(tok::colon)) // Otherwise expect ':'.
36730b57cec5SDimitry Andric         return ExprError();
36740b57cec5SDimitry Andric       ++nColons;
36750b57cec5SDimitry Andric 
36760b57cec5SDimitry Andric       if (Tok.is(tok::r_paren))
36770b57cec5SDimitry Andric         break;
36780b57cec5SDimitry Andric 
36790b57cec5SDimitry Andric       if (Tok.is(tok::code_completion)) {
36800b57cec5SDimitry Andric         cutOffParsing();
3681*0fca6ea1SDimitry Andric         Actions.CodeCompletion().CodeCompleteObjCSelector(getCurScope(),
3682*0fca6ea1SDimitry Andric                                                           KeyIdents);
36830b57cec5SDimitry Andric         return ExprError();
36840b57cec5SDimitry Andric       }
36850b57cec5SDimitry Andric 
36860b57cec5SDimitry Andric       // Check for another keyword selector.
36870b57cec5SDimitry Andric       SourceLocation Loc;
36880b57cec5SDimitry Andric       SelIdent = ParseObjCSelectorPiece(Loc);
36890b57cec5SDimitry Andric       KeyIdents.push_back(SelIdent);
36900b57cec5SDimitry Andric       if (!SelIdent && Tok.isNot(tok::colon) && Tok.isNot(tok::coloncolon))
36910b57cec5SDimitry Andric         break;
36920b57cec5SDimitry Andric     }
36930b57cec5SDimitry Andric   }
36940b57cec5SDimitry Andric   if (HasOptionalParen && Tok.is(tok::r_paren))
36950b57cec5SDimitry Andric     ConsumeParen(); // ')'
36960b57cec5SDimitry Andric   T.consumeClose();
36970b57cec5SDimitry Andric   Selector Sel = PP.getSelectorTable().getSelector(nColons, &KeyIdents[0]);
3698*0fca6ea1SDimitry Andric   return Actions.ObjC().ParseObjCSelectorExpression(
3699*0fca6ea1SDimitry Andric       Sel, AtLoc, SelectorLoc, T.getOpenLocation(), T.getCloseLocation(),
37000b57cec5SDimitry Andric       !HasOptionalParen);
37010b57cec5SDimitry Andric }
37020b57cec5SDimitry Andric 
37030b57cec5SDimitry Andric void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) {
37040b57cec5SDimitry Andric   // MCDecl might be null due to error in method or c-function  prototype, etc.
37050b57cec5SDimitry Andric   Decl *MCDecl = LM.D;
3706*0fca6ea1SDimitry Andric   bool skip =
3707*0fca6ea1SDimitry Andric       MCDecl && ((parseMethod && !Actions.ObjC().isObjCMethodDecl(MCDecl)) ||
3708*0fca6ea1SDimitry Andric                  (!parseMethod && Actions.ObjC().isObjCMethodDecl(MCDecl)));
37090b57cec5SDimitry Andric   if (skip)
37100b57cec5SDimitry Andric     return;
37110b57cec5SDimitry Andric 
37120b57cec5SDimitry Andric   // Save the current token position.
37130b57cec5SDimitry Andric   SourceLocation OrigLoc = Tok.getLocation();
37140b57cec5SDimitry Andric 
37150b57cec5SDimitry Andric   assert(!LM.Toks.empty() && "ParseLexedObjCMethodDef - Empty body!");
37160b57cec5SDimitry Andric   // Store an artificial EOF token to ensure that we don't run off the end of
37170b57cec5SDimitry Andric   // the method's body when we come to parse it.
37180b57cec5SDimitry Andric   Token Eof;
37190b57cec5SDimitry Andric   Eof.startToken();
37200b57cec5SDimitry Andric   Eof.setKind(tok::eof);
37210b57cec5SDimitry Andric   Eof.setEofData(MCDecl);
37220b57cec5SDimitry Andric   Eof.setLocation(OrigLoc);
37230b57cec5SDimitry Andric   LM.Toks.push_back(Eof);
37240b57cec5SDimitry Andric   // Append the current token at the end of the new token stream so that it
37250b57cec5SDimitry Andric   // doesn't get lost.
37260b57cec5SDimitry Andric   LM.Toks.push_back(Tok);
37270b57cec5SDimitry Andric   PP.EnterTokenStream(LM.Toks, true, /*IsReinject*/true);
37280b57cec5SDimitry Andric 
37290b57cec5SDimitry Andric   // Consume the previously pushed token.
37300b57cec5SDimitry Andric   ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
37310b57cec5SDimitry Andric 
37320b57cec5SDimitry Andric   assert(Tok.isOneOf(tok::l_brace, tok::kw_try, tok::colon) &&
37330b57cec5SDimitry Andric          "Inline objective-c method not starting with '{' or 'try' or ':'");
37340b57cec5SDimitry Andric   // Enter a scope for the method or c-function body.
37350b57cec5SDimitry Andric   ParseScope BodyScope(this, (parseMethod ? Scope::ObjCMethodScope : 0) |
37360b57cec5SDimitry Andric                                  Scope::FnScope | Scope::DeclScope |
37370b57cec5SDimitry Andric                                  Scope::CompoundStmtScope);
3738*0fca6ea1SDimitry Andric   Sema::FPFeaturesStateRAII SaveFPFeatures(Actions);
37390b57cec5SDimitry Andric 
37400b57cec5SDimitry Andric   // Tell the actions module that we have entered a method or c-function definition
37410b57cec5SDimitry Andric   // with the specified Declarator for the method/function.
37420b57cec5SDimitry Andric   if (parseMethod)
3743*0fca6ea1SDimitry Andric     Actions.ObjC().ActOnStartOfObjCMethodDef(getCurScope(), MCDecl);
37440b57cec5SDimitry Andric   else
37450b57cec5SDimitry Andric     Actions.ActOnStartOfFunctionDef(getCurScope(), MCDecl);
37460b57cec5SDimitry Andric   if (Tok.is(tok::kw_try))
37470b57cec5SDimitry Andric     ParseFunctionTryBlock(MCDecl, BodyScope);
37480b57cec5SDimitry Andric   else {
37490b57cec5SDimitry Andric     if (Tok.is(tok::colon))
37500b57cec5SDimitry Andric       ParseConstructorInitializer(MCDecl);
37510b57cec5SDimitry Andric     else
37520b57cec5SDimitry Andric       Actions.ActOnDefaultCtorInitializers(MCDecl);
37530b57cec5SDimitry Andric     ParseFunctionStatementBody(MCDecl, BodyScope);
37540b57cec5SDimitry Andric   }
37550b57cec5SDimitry Andric 
37560b57cec5SDimitry Andric   if (Tok.getLocation() != OrigLoc) {
37570b57cec5SDimitry Andric     // Due to parsing error, we either went over the cached tokens or
37580b57cec5SDimitry Andric     // there are still cached tokens left. If it's the latter case skip the
37590b57cec5SDimitry Andric     // leftover tokens.
37600b57cec5SDimitry Andric     // Since this is an uncommon situation that should be avoided, use the
37610b57cec5SDimitry Andric     // expensive isBeforeInTranslationUnit call.
37620b57cec5SDimitry Andric     if (PP.getSourceManager().isBeforeInTranslationUnit(Tok.getLocation(),
37630b57cec5SDimitry Andric                                                      OrigLoc))
37640b57cec5SDimitry Andric       while (Tok.getLocation() != OrigLoc && Tok.isNot(tok::eof))
37650b57cec5SDimitry Andric         ConsumeAnyToken();
37660b57cec5SDimitry Andric   }
37675f757f3fSDimitry Andric   // Clean up the remaining EOF token, only if it's inserted by us. Otherwise
37685f757f3fSDimitry Andric   // this might be code-completion token, which must be propagated to callers.
37695f757f3fSDimitry Andric   if (Tok.is(tok::eof) && Tok.getEofData() == MCDecl)
37700b57cec5SDimitry Andric     ConsumeAnyToken();
37710b57cec5SDimitry Andric }
3772