xref: /netbsd-src/external/apache2/llvm/dist/clang/lib/Parse/ParseObjc.cpp (revision e038c9c4676b0f19b1b7dd08a940c6ed64a6d5ae)
17330f729Sjoerg //===--- ParseObjC.cpp - Objective C Parsing ------------------------------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg //  This file implements the Objective-C portions of the Parser interface.
107330f729Sjoerg //
117330f729Sjoerg //===----------------------------------------------------------------------===//
127330f729Sjoerg 
137330f729Sjoerg #include "clang/AST/ASTContext.h"
147330f729Sjoerg #include "clang/AST/PrettyDeclStackTrace.h"
157330f729Sjoerg #include "clang/Basic/CharInfo.h"
16*e038c9c4Sjoerg #include "clang/Basic/TargetInfo.h"
177330f729Sjoerg #include "clang/Parse/ParseDiagnostic.h"
18*e038c9c4Sjoerg #include "clang/Parse/Parser.h"
197330f729Sjoerg #include "clang/Parse/RAIIObjectsForParser.h"
207330f729Sjoerg #include "clang/Sema/DeclSpec.h"
217330f729Sjoerg #include "clang/Sema/Scope.h"
227330f729Sjoerg #include "llvm/ADT/SmallVector.h"
237330f729Sjoerg #include "llvm/ADT/StringExtras.h"
247330f729Sjoerg 
257330f729Sjoerg using namespace clang;
267330f729Sjoerg 
277330f729Sjoerg /// Skips attributes after an Objective-C @ directive. Emits a diagnostic.
MaybeSkipAttributes(tok::ObjCKeywordKind Kind)287330f729Sjoerg void Parser::MaybeSkipAttributes(tok::ObjCKeywordKind Kind) {
297330f729Sjoerg   ParsedAttributes attrs(AttrFactory);
307330f729Sjoerg   if (Tok.is(tok::kw___attribute)) {
317330f729Sjoerg     if (Kind == tok::objc_interface || Kind == tok::objc_protocol)
327330f729Sjoerg       Diag(Tok, diag::err_objc_postfix_attribute_hint)
337330f729Sjoerg           << (Kind == tok::objc_protocol);
347330f729Sjoerg     else
357330f729Sjoerg       Diag(Tok, diag::err_objc_postfix_attribute);
367330f729Sjoerg     ParseGNUAttributes(attrs);
377330f729Sjoerg   }
387330f729Sjoerg }
397330f729Sjoerg 
407330f729Sjoerg /// ParseObjCAtDirectives - Handle parts of the external-declaration production:
417330f729Sjoerg ///       external-declaration: [C99 6.9]
427330f729Sjoerg /// [OBJC]  objc-class-definition
437330f729Sjoerg /// [OBJC]  objc-class-declaration
447330f729Sjoerg /// [OBJC]  objc-alias-declaration
457330f729Sjoerg /// [OBJC]  objc-protocol-definition
467330f729Sjoerg /// [OBJC]  objc-method-definition
477330f729Sjoerg /// [OBJC]  '@' 'end'
487330f729Sjoerg Parser::DeclGroupPtrTy
ParseObjCAtDirectives(ParsedAttributesWithRange & Attrs)497330f729Sjoerg Parser::ParseObjCAtDirectives(ParsedAttributesWithRange &Attrs) {
507330f729Sjoerg   SourceLocation AtLoc = ConsumeToken(); // the "@"
517330f729Sjoerg 
527330f729Sjoerg   if (Tok.is(tok::code_completion)) {
537330f729Sjoerg     cutOffParsing();
54*e038c9c4Sjoerg     Actions.CodeCompleteObjCAtDirective(getCurScope());
557330f729Sjoerg     return nullptr;
567330f729Sjoerg   }
577330f729Sjoerg 
587330f729Sjoerg   Decl *SingleDecl = nullptr;
597330f729Sjoerg   switch (Tok.getObjCKeywordID()) {
607330f729Sjoerg   case tok::objc_class:
617330f729Sjoerg     return ParseObjCAtClassDeclaration(AtLoc);
627330f729Sjoerg   case tok::objc_interface:
637330f729Sjoerg     SingleDecl = ParseObjCAtInterfaceDeclaration(AtLoc, Attrs);
647330f729Sjoerg     break;
657330f729Sjoerg   case tok::objc_protocol:
667330f729Sjoerg     return ParseObjCAtProtocolDeclaration(AtLoc, Attrs);
677330f729Sjoerg   case tok::objc_implementation:
687330f729Sjoerg     return ParseObjCAtImplementationDeclaration(AtLoc, Attrs);
697330f729Sjoerg   case tok::objc_end:
707330f729Sjoerg     return ParseObjCAtEndDeclaration(AtLoc);
717330f729Sjoerg   case tok::objc_compatibility_alias:
727330f729Sjoerg     SingleDecl = ParseObjCAtAliasDeclaration(AtLoc);
737330f729Sjoerg     break;
747330f729Sjoerg   case tok::objc_synthesize:
757330f729Sjoerg     SingleDecl = ParseObjCPropertySynthesize(AtLoc);
767330f729Sjoerg     break;
777330f729Sjoerg   case tok::objc_dynamic:
787330f729Sjoerg     SingleDecl = ParseObjCPropertyDynamic(AtLoc);
797330f729Sjoerg     break;
807330f729Sjoerg   case tok::objc_import:
817330f729Sjoerg     if (getLangOpts().Modules || getLangOpts().DebuggerSupport) {
827330f729Sjoerg       SingleDecl = ParseModuleImport(AtLoc);
837330f729Sjoerg       break;
847330f729Sjoerg     }
857330f729Sjoerg     Diag(AtLoc, diag::err_atimport);
867330f729Sjoerg     SkipUntil(tok::semi);
877330f729Sjoerg     return Actions.ConvertDeclToDeclGroup(nullptr);
887330f729Sjoerg   default:
897330f729Sjoerg     Diag(AtLoc, diag::err_unexpected_at);
907330f729Sjoerg     SkipUntil(tok::semi);
917330f729Sjoerg     SingleDecl = nullptr;
927330f729Sjoerg     break;
937330f729Sjoerg   }
947330f729Sjoerg   return Actions.ConvertDeclToDeclGroup(SingleDecl);
957330f729Sjoerg }
967330f729Sjoerg 
977330f729Sjoerg /// Class to handle popping type parameters when leaving the scope.
987330f729Sjoerg class Parser::ObjCTypeParamListScope {
997330f729Sjoerg   Sema &Actions;
1007330f729Sjoerg   Scope *S;
1017330f729Sjoerg   ObjCTypeParamList *Params;
1027330f729Sjoerg 
1037330f729Sjoerg public:
ObjCTypeParamListScope(Sema & Actions,Scope * S)1047330f729Sjoerg   ObjCTypeParamListScope(Sema &Actions, Scope *S)
1057330f729Sjoerg       : Actions(Actions), S(S), Params(nullptr) {}
1067330f729Sjoerg 
~ObjCTypeParamListScope()1077330f729Sjoerg   ~ObjCTypeParamListScope() {
1087330f729Sjoerg     leave();
1097330f729Sjoerg   }
1107330f729Sjoerg 
enter(ObjCTypeParamList * P)1117330f729Sjoerg   void enter(ObjCTypeParamList *P) {
1127330f729Sjoerg     assert(!Params);
1137330f729Sjoerg     Params = P;
1147330f729Sjoerg   }
1157330f729Sjoerg 
leave()1167330f729Sjoerg   void leave() {
1177330f729Sjoerg     if (Params)
1187330f729Sjoerg       Actions.popObjCTypeParamList(S, Params);
1197330f729Sjoerg     Params = nullptr;
1207330f729Sjoerg   }
1217330f729Sjoerg };
1227330f729Sjoerg 
1237330f729Sjoerg ///
1247330f729Sjoerg /// objc-class-declaration:
1257330f729Sjoerg ///    '@' 'class' objc-class-forward-decl (',' objc-class-forward-decl)* ';'
1267330f729Sjoerg ///
1277330f729Sjoerg /// objc-class-forward-decl:
1287330f729Sjoerg ///   identifier objc-type-parameter-list[opt]
1297330f729Sjoerg ///
1307330f729Sjoerg Parser::DeclGroupPtrTy
ParseObjCAtClassDeclaration(SourceLocation atLoc)1317330f729Sjoerg Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
1327330f729Sjoerg   ConsumeToken(); // the identifier "class"
1337330f729Sjoerg   SmallVector<IdentifierInfo *, 8> ClassNames;
1347330f729Sjoerg   SmallVector<SourceLocation, 8> ClassLocs;
1357330f729Sjoerg   SmallVector<ObjCTypeParamList *, 8> ClassTypeParams;
1367330f729Sjoerg 
1377330f729Sjoerg   while (1) {
1387330f729Sjoerg     MaybeSkipAttributes(tok::objc_class);
1397330f729Sjoerg     if (expectIdentifier()) {
1407330f729Sjoerg       SkipUntil(tok::semi);
1417330f729Sjoerg       return Actions.ConvertDeclToDeclGroup(nullptr);
1427330f729Sjoerg     }
1437330f729Sjoerg     ClassNames.push_back(Tok.getIdentifierInfo());
1447330f729Sjoerg     ClassLocs.push_back(Tok.getLocation());
1457330f729Sjoerg     ConsumeToken();
1467330f729Sjoerg 
1477330f729Sjoerg     // Parse the optional objc-type-parameter-list.
1487330f729Sjoerg     ObjCTypeParamList *TypeParams = nullptr;
1497330f729Sjoerg     if (Tok.is(tok::less))
1507330f729Sjoerg       TypeParams = parseObjCTypeParamList();
1517330f729Sjoerg     ClassTypeParams.push_back(TypeParams);
1527330f729Sjoerg     if (!TryConsumeToken(tok::comma))
1537330f729Sjoerg       break;
1547330f729Sjoerg   }
1557330f729Sjoerg 
1567330f729Sjoerg   // Consume the ';'.
1577330f729Sjoerg   if (ExpectAndConsume(tok::semi, diag::err_expected_after, "@class"))
1587330f729Sjoerg     return Actions.ConvertDeclToDeclGroup(nullptr);
1597330f729Sjoerg 
1607330f729Sjoerg   return Actions.ActOnForwardClassDeclaration(atLoc, ClassNames.data(),
1617330f729Sjoerg                                               ClassLocs.data(),
1627330f729Sjoerg                                               ClassTypeParams,
1637330f729Sjoerg                                               ClassNames.size());
1647330f729Sjoerg }
1657330f729Sjoerg 
CheckNestedObjCContexts(SourceLocation AtLoc)1667330f729Sjoerg void Parser::CheckNestedObjCContexts(SourceLocation AtLoc)
1677330f729Sjoerg {
1687330f729Sjoerg   Sema::ObjCContainerKind ock = Actions.getObjCContainerKind();
1697330f729Sjoerg   if (ock == Sema::OCK_None)
1707330f729Sjoerg     return;
1717330f729Sjoerg 
1727330f729Sjoerg   Decl *Decl = Actions.getObjCDeclContext();
1737330f729Sjoerg   if (CurParsedObjCImpl) {
1747330f729Sjoerg     CurParsedObjCImpl->finish(AtLoc);
1757330f729Sjoerg   } else {
1767330f729Sjoerg     Actions.ActOnAtEnd(getCurScope(), AtLoc);
1777330f729Sjoerg   }
1787330f729Sjoerg   Diag(AtLoc, diag::err_objc_missing_end)
1797330f729Sjoerg       << FixItHint::CreateInsertion(AtLoc, "@end\n");
1807330f729Sjoerg   if (Decl)
1817330f729Sjoerg     Diag(Decl->getBeginLoc(), diag::note_objc_container_start) << (int)ock;
1827330f729Sjoerg }
1837330f729Sjoerg 
1847330f729Sjoerg ///
1857330f729Sjoerg ///   objc-interface:
1867330f729Sjoerg ///     objc-class-interface-attributes[opt] objc-class-interface
1877330f729Sjoerg ///     objc-category-interface
1887330f729Sjoerg ///
1897330f729Sjoerg ///   objc-class-interface:
1907330f729Sjoerg ///     '@' 'interface' identifier objc-type-parameter-list[opt]
1917330f729Sjoerg ///       objc-superclass[opt] objc-protocol-refs[opt]
1927330f729Sjoerg ///       objc-class-instance-variables[opt]
1937330f729Sjoerg ///       objc-interface-decl-list
1947330f729Sjoerg ///     @end
1957330f729Sjoerg ///
1967330f729Sjoerg ///   objc-category-interface:
1977330f729Sjoerg ///     '@' 'interface' identifier objc-type-parameter-list[opt]
1987330f729Sjoerg ///       '(' identifier[opt] ')' objc-protocol-refs[opt]
1997330f729Sjoerg ///       objc-interface-decl-list
2007330f729Sjoerg ///     @end
2017330f729Sjoerg ///
2027330f729Sjoerg ///   objc-superclass:
2037330f729Sjoerg ///     ':' identifier objc-type-arguments[opt]
2047330f729Sjoerg ///
2057330f729Sjoerg ///   objc-class-interface-attributes:
2067330f729Sjoerg ///     __attribute__((visibility("default")))
2077330f729Sjoerg ///     __attribute__((visibility("hidden")))
2087330f729Sjoerg ///     __attribute__((deprecated))
2097330f729Sjoerg ///     __attribute__((unavailable))
2107330f729Sjoerg ///     __attribute__((objc_exception)) - used by NSException on 64-bit
2117330f729Sjoerg ///     __attribute__((objc_root_class))
2127330f729Sjoerg ///
ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,ParsedAttributes & attrs)2137330f729Sjoerg Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
2147330f729Sjoerg                                               ParsedAttributes &attrs) {
2157330f729Sjoerg   assert(Tok.isObjCAtKeyword(tok::objc_interface) &&
2167330f729Sjoerg          "ParseObjCAtInterfaceDeclaration(): Expected @interface");
2177330f729Sjoerg   CheckNestedObjCContexts(AtLoc);
2187330f729Sjoerg   ConsumeToken(); // the "interface" identifier
2197330f729Sjoerg 
2207330f729Sjoerg   // Code completion after '@interface'.
2217330f729Sjoerg   if (Tok.is(tok::code_completion)) {
2227330f729Sjoerg     cutOffParsing();
223*e038c9c4Sjoerg     Actions.CodeCompleteObjCInterfaceDecl(getCurScope());
2247330f729Sjoerg     return nullptr;
2257330f729Sjoerg   }
2267330f729Sjoerg 
2277330f729Sjoerg   MaybeSkipAttributes(tok::objc_interface);
2287330f729Sjoerg 
2297330f729Sjoerg   if (expectIdentifier())
2307330f729Sjoerg     return nullptr; // missing class or category name.
2317330f729Sjoerg 
2327330f729Sjoerg   // We have a class or category name - consume it.
2337330f729Sjoerg   IdentifierInfo *nameId = Tok.getIdentifierInfo();
2347330f729Sjoerg   SourceLocation nameLoc = ConsumeToken();
2357330f729Sjoerg 
2367330f729Sjoerg   // Parse the objc-type-parameter-list or objc-protocol-refs. For the latter
2377330f729Sjoerg   // case, LAngleLoc will be valid and ProtocolIdents will capture the
2387330f729Sjoerg   // protocol references (that have not yet been resolved).
2397330f729Sjoerg   SourceLocation LAngleLoc, EndProtoLoc;
2407330f729Sjoerg   SmallVector<IdentifierLocPair, 8> ProtocolIdents;
2417330f729Sjoerg   ObjCTypeParamList *typeParameterList = nullptr;
2427330f729Sjoerg   ObjCTypeParamListScope typeParamScope(Actions, getCurScope());
2437330f729Sjoerg   if (Tok.is(tok::less))
2447330f729Sjoerg     typeParameterList = parseObjCTypeParamListOrProtocolRefs(
2457330f729Sjoerg         typeParamScope, LAngleLoc, ProtocolIdents, EndProtoLoc);
2467330f729Sjoerg 
2477330f729Sjoerg   if (Tok.is(tok::l_paren) &&
2487330f729Sjoerg       !isKnownToBeTypeSpecifier(GetLookAheadToken(1))) { // we have a category.
2497330f729Sjoerg 
2507330f729Sjoerg     BalancedDelimiterTracker T(*this, tok::l_paren);
2517330f729Sjoerg     T.consumeOpen();
2527330f729Sjoerg 
2537330f729Sjoerg     SourceLocation categoryLoc;
2547330f729Sjoerg     IdentifierInfo *categoryId = nullptr;
2557330f729Sjoerg     if (Tok.is(tok::code_completion)) {
2567330f729Sjoerg       cutOffParsing();
257*e038c9c4Sjoerg       Actions.CodeCompleteObjCInterfaceCategory(getCurScope(), nameId, nameLoc);
2587330f729Sjoerg       return nullptr;
2597330f729Sjoerg     }
2607330f729Sjoerg 
2617330f729Sjoerg     // For ObjC2, the category name is optional (not an error).
2627330f729Sjoerg     if (Tok.is(tok::identifier)) {
2637330f729Sjoerg       categoryId = Tok.getIdentifierInfo();
2647330f729Sjoerg       categoryLoc = ConsumeToken();
2657330f729Sjoerg     }
2667330f729Sjoerg     else if (!getLangOpts().ObjC) {
2677330f729Sjoerg       Diag(Tok, diag::err_expected)
2687330f729Sjoerg           << tok::identifier; // missing category name.
2697330f729Sjoerg       return nullptr;
2707330f729Sjoerg     }
2717330f729Sjoerg 
2727330f729Sjoerg     T.consumeClose();
2737330f729Sjoerg     if (T.getCloseLocation().isInvalid())
2747330f729Sjoerg       return nullptr;
2757330f729Sjoerg 
2767330f729Sjoerg     // Next, we need to check for any protocol references.
2777330f729Sjoerg     assert(LAngleLoc.isInvalid() && "Cannot have already parsed protocols");
2787330f729Sjoerg     SmallVector<Decl *, 8> ProtocolRefs;
2797330f729Sjoerg     SmallVector<SourceLocation, 8> ProtocolLocs;
2807330f729Sjoerg     if (Tok.is(tok::less) &&
2817330f729Sjoerg         ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true, true,
2827330f729Sjoerg                                     LAngleLoc, EndProtoLoc,
2837330f729Sjoerg                                     /*consumeLastToken=*/true))
2847330f729Sjoerg       return nullptr;
2857330f729Sjoerg 
2867330f729Sjoerg     Decl *CategoryType = Actions.ActOnStartCategoryInterface(
2877330f729Sjoerg         AtLoc, nameId, nameLoc, typeParameterList, categoryId, categoryLoc,
2887330f729Sjoerg         ProtocolRefs.data(), ProtocolRefs.size(), ProtocolLocs.data(),
2897330f729Sjoerg         EndProtoLoc, attrs);
2907330f729Sjoerg 
2917330f729Sjoerg     if (Tok.is(tok::l_brace))
2927330f729Sjoerg       ParseObjCClassInstanceVariables(CategoryType, tok::objc_private, AtLoc);
2937330f729Sjoerg 
2947330f729Sjoerg     ParseObjCInterfaceDeclList(tok::objc_not_keyword, CategoryType);
2957330f729Sjoerg 
2967330f729Sjoerg     return CategoryType;
2977330f729Sjoerg   }
2987330f729Sjoerg   // Parse a class interface.
2997330f729Sjoerg   IdentifierInfo *superClassId = nullptr;
3007330f729Sjoerg   SourceLocation superClassLoc;
3017330f729Sjoerg   SourceLocation typeArgsLAngleLoc;
3027330f729Sjoerg   SmallVector<ParsedType, 4> typeArgs;
3037330f729Sjoerg   SourceLocation typeArgsRAngleLoc;
3047330f729Sjoerg   SmallVector<Decl *, 4> protocols;
3057330f729Sjoerg   SmallVector<SourceLocation, 4> protocolLocs;
3067330f729Sjoerg   if (Tok.is(tok::colon)) { // a super class is specified.
3077330f729Sjoerg     ConsumeToken();
3087330f729Sjoerg 
3097330f729Sjoerg     // Code completion of superclass names.
3107330f729Sjoerg     if (Tok.is(tok::code_completion)) {
3117330f729Sjoerg       cutOffParsing();
312*e038c9c4Sjoerg       Actions.CodeCompleteObjCSuperclass(getCurScope(), nameId, nameLoc);
3137330f729Sjoerg       return nullptr;
3147330f729Sjoerg     }
3157330f729Sjoerg 
3167330f729Sjoerg     if (expectIdentifier())
3177330f729Sjoerg       return nullptr; // missing super class name.
3187330f729Sjoerg     superClassId = Tok.getIdentifierInfo();
3197330f729Sjoerg     superClassLoc = ConsumeToken();
3207330f729Sjoerg 
3217330f729Sjoerg     // Type arguments for the superclass or protocol conformances.
3227330f729Sjoerg     if (Tok.is(tok::less)) {
3237330f729Sjoerg       parseObjCTypeArgsOrProtocolQualifiers(
3247330f729Sjoerg           nullptr, typeArgsLAngleLoc, typeArgs, typeArgsRAngleLoc, LAngleLoc,
3257330f729Sjoerg           protocols, protocolLocs, EndProtoLoc,
3267330f729Sjoerg           /*consumeLastToken=*/true,
3277330f729Sjoerg           /*warnOnIncompleteProtocols=*/true);
3287330f729Sjoerg       if (Tok.is(tok::eof))
3297330f729Sjoerg         return nullptr;
3307330f729Sjoerg     }
3317330f729Sjoerg   }
3327330f729Sjoerg 
3337330f729Sjoerg   // Next, we need to check for any protocol references.
3347330f729Sjoerg   if (LAngleLoc.isValid()) {
3357330f729Sjoerg     if (!ProtocolIdents.empty()) {
3367330f729Sjoerg       // We already parsed the protocols named when we thought we had a
3377330f729Sjoerg       // type parameter list. Translate them into actual protocol references.
3387330f729Sjoerg       for (const auto &pair : ProtocolIdents) {
3397330f729Sjoerg         protocolLocs.push_back(pair.second);
3407330f729Sjoerg       }
3417330f729Sjoerg       Actions.FindProtocolDeclaration(/*WarnOnDeclarations=*/true,
3427330f729Sjoerg                                       /*ForObjCContainer=*/true,
3437330f729Sjoerg                                       ProtocolIdents, protocols);
3447330f729Sjoerg     }
3457330f729Sjoerg   } else if (protocols.empty() && Tok.is(tok::less) &&
3467330f729Sjoerg              ParseObjCProtocolReferences(protocols, protocolLocs, true, true,
3477330f729Sjoerg                                          LAngleLoc, EndProtoLoc,
3487330f729Sjoerg                                          /*consumeLastToken=*/true)) {
3497330f729Sjoerg     return nullptr;
3507330f729Sjoerg   }
3517330f729Sjoerg 
3527330f729Sjoerg   if (Tok.isNot(tok::less))
3537330f729Sjoerg     Actions.ActOnTypedefedProtocols(protocols, protocolLocs,
3547330f729Sjoerg                                     superClassId, superClassLoc);
3557330f729Sjoerg 
3567330f729Sjoerg   Decl *ClsType = Actions.ActOnStartClassInterface(
3577330f729Sjoerg       getCurScope(), AtLoc, nameId, nameLoc, typeParameterList, superClassId,
3587330f729Sjoerg       superClassLoc, typeArgs,
3597330f729Sjoerg       SourceRange(typeArgsLAngleLoc, typeArgsRAngleLoc), protocols.data(),
3607330f729Sjoerg       protocols.size(), protocolLocs.data(), EndProtoLoc, attrs);
3617330f729Sjoerg 
3627330f729Sjoerg   if (Tok.is(tok::l_brace))
3637330f729Sjoerg     ParseObjCClassInstanceVariables(ClsType, tok::objc_protected, AtLoc);
3647330f729Sjoerg 
3657330f729Sjoerg   ParseObjCInterfaceDeclList(tok::objc_interface, ClsType);
3667330f729Sjoerg 
3677330f729Sjoerg   return ClsType;
3687330f729Sjoerg }
3697330f729Sjoerg 
3707330f729Sjoerg /// Add an attribute for a context-sensitive type nullability to the given
3717330f729Sjoerg /// declarator.
addContextSensitiveTypeNullability(Parser & P,Declarator & D,NullabilityKind nullability,SourceLocation nullabilityLoc,bool & addedToDeclSpec)3727330f729Sjoerg static void addContextSensitiveTypeNullability(Parser &P,
3737330f729Sjoerg                                                Declarator &D,
3747330f729Sjoerg                                                NullabilityKind nullability,
3757330f729Sjoerg                                                SourceLocation nullabilityLoc,
3767330f729Sjoerg                                                bool &addedToDeclSpec) {
3777330f729Sjoerg   // Create the attribute.
3787330f729Sjoerg   auto getNullabilityAttr = [&](AttributePool &Pool) -> ParsedAttr * {
3797330f729Sjoerg     return Pool.create(P.getNullabilityKeyword(nullability),
3807330f729Sjoerg                        SourceRange(nullabilityLoc), nullptr, SourceLocation(),
3817330f729Sjoerg                        nullptr, 0, ParsedAttr::AS_ContextSensitiveKeyword);
3827330f729Sjoerg   };
3837330f729Sjoerg 
3847330f729Sjoerg   if (D.getNumTypeObjects() > 0) {
3857330f729Sjoerg     // Add the attribute to the declarator chunk nearest the declarator.
3867330f729Sjoerg     D.getTypeObject(0).getAttrs().addAtEnd(
3877330f729Sjoerg         getNullabilityAttr(D.getAttributePool()));
3887330f729Sjoerg   } else if (!addedToDeclSpec) {
3897330f729Sjoerg     // Otherwise, just put it on the declaration specifiers (if one
3907330f729Sjoerg     // isn't there already).
3917330f729Sjoerg     D.getMutableDeclSpec().getAttributes().addAtEnd(
3927330f729Sjoerg         getNullabilityAttr(D.getMutableDeclSpec().getAttributes().getPool()));
3937330f729Sjoerg     addedToDeclSpec = true;
3947330f729Sjoerg   }
3957330f729Sjoerg }
3967330f729Sjoerg 
3977330f729Sjoerg /// Parse an Objective-C type parameter list, if present, or capture
3987330f729Sjoerg /// the locations of the protocol identifiers for a list of protocol
3997330f729Sjoerg /// references.
4007330f729Sjoerg ///
4017330f729Sjoerg ///   objc-type-parameter-list:
4027330f729Sjoerg ///     '<' objc-type-parameter (',' objc-type-parameter)* '>'
4037330f729Sjoerg ///
4047330f729Sjoerg ///   objc-type-parameter:
4057330f729Sjoerg ///     objc-type-parameter-variance? identifier objc-type-parameter-bound[opt]
4067330f729Sjoerg ///
4077330f729Sjoerg ///   objc-type-parameter-bound:
4087330f729Sjoerg ///     ':' type-name
4097330f729Sjoerg ///
4107330f729Sjoerg ///   objc-type-parameter-variance:
4117330f729Sjoerg ///     '__covariant'
4127330f729Sjoerg ///     '__contravariant'
4137330f729Sjoerg ///
4147330f729Sjoerg /// \param lAngleLoc The location of the starting '<'.
4157330f729Sjoerg ///
4167330f729Sjoerg /// \param protocolIdents Will capture the list of identifiers, if the
4177330f729Sjoerg /// angle brackets contain a list of protocol references rather than a
4187330f729Sjoerg /// type parameter list.
4197330f729Sjoerg ///
4207330f729Sjoerg /// \param rAngleLoc The location of the ending '>'.
parseObjCTypeParamListOrProtocolRefs(ObjCTypeParamListScope & Scope,SourceLocation & lAngleLoc,SmallVectorImpl<IdentifierLocPair> & protocolIdents,SourceLocation & rAngleLoc,bool mayBeProtocolList)4217330f729Sjoerg ObjCTypeParamList *Parser::parseObjCTypeParamListOrProtocolRefs(
4227330f729Sjoerg     ObjCTypeParamListScope &Scope, SourceLocation &lAngleLoc,
4237330f729Sjoerg     SmallVectorImpl<IdentifierLocPair> &protocolIdents,
4247330f729Sjoerg     SourceLocation &rAngleLoc, bool mayBeProtocolList) {
4257330f729Sjoerg   assert(Tok.is(tok::less) && "Not at the beginning of a type parameter list");
4267330f729Sjoerg 
4277330f729Sjoerg   // Within the type parameter list, don't treat '>' as an operator.
4287330f729Sjoerg   GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);
4297330f729Sjoerg 
4307330f729Sjoerg   // Local function to "flush" the protocol identifiers, turning them into
4317330f729Sjoerg   // type parameters.
4327330f729Sjoerg   SmallVector<Decl *, 4> typeParams;
4337330f729Sjoerg   auto makeProtocolIdentsIntoTypeParameters = [&]() {
4347330f729Sjoerg     unsigned index = 0;
4357330f729Sjoerg     for (const auto &pair : protocolIdents) {
4367330f729Sjoerg       DeclResult typeParam = Actions.actOnObjCTypeParam(
4377330f729Sjoerg           getCurScope(), ObjCTypeParamVariance::Invariant, SourceLocation(),
4387330f729Sjoerg           index++, pair.first, pair.second, SourceLocation(), nullptr);
4397330f729Sjoerg       if (typeParam.isUsable())
4407330f729Sjoerg         typeParams.push_back(typeParam.get());
4417330f729Sjoerg     }
4427330f729Sjoerg 
4437330f729Sjoerg     protocolIdents.clear();
4447330f729Sjoerg     mayBeProtocolList = false;
4457330f729Sjoerg   };
4467330f729Sjoerg 
4477330f729Sjoerg   bool invalid = false;
4487330f729Sjoerg   lAngleLoc = ConsumeToken();
4497330f729Sjoerg 
4507330f729Sjoerg   do {
4517330f729Sjoerg     // Parse the variance, if any.
4527330f729Sjoerg     SourceLocation varianceLoc;
4537330f729Sjoerg     ObjCTypeParamVariance variance = ObjCTypeParamVariance::Invariant;
4547330f729Sjoerg     if (Tok.is(tok::kw___covariant) || Tok.is(tok::kw___contravariant)) {
4557330f729Sjoerg       variance = Tok.is(tok::kw___covariant)
4567330f729Sjoerg                    ? ObjCTypeParamVariance::Covariant
4577330f729Sjoerg                    : ObjCTypeParamVariance::Contravariant;
4587330f729Sjoerg       varianceLoc = ConsumeToken();
4597330f729Sjoerg 
4607330f729Sjoerg       // Once we've seen a variance specific , we know this is not a
4617330f729Sjoerg       // list of protocol references.
4627330f729Sjoerg       if (mayBeProtocolList) {
4637330f729Sjoerg         // Up until now, we have been queuing up parameters because they
4647330f729Sjoerg         // might be protocol references. Turn them into parameters now.
4657330f729Sjoerg         makeProtocolIdentsIntoTypeParameters();
4667330f729Sjoerg       }
4677330f729Sjoerg     }
4687330f729Sjoerg 
4697330f729Sjoerg     // Parse the identifier.
4707330f729Sjoerg     if (!Tok.is(tok::identifier)) {
4717330f729Sjoerg       // Code completion.
4727330f729Sjoerg       if (Tok.is(tok::code_completion)) {
4737330f729Sjoerg         // FIXME: If these aren't protocol references, we'll need different
4747330f729Sjoerg         // completions.
4757330f729Sjoerg         cutOffParsing();
476*e038c9c4Sjoerg         Actions.CodeCompleteObjCProtocolReferences(protocolIdents);
4777330f729Sjoerg 
4787330f729Sjoerg         // FIXME: Better recovery here?.
4797330f729Sjoerg         return nullptr;
4807330f729Sjoerg       }
4817330f729Sjoerg 
4827330f729Sjoerg       Diag(Tok, diag::err_objc_expected_type_parameter);
4837330f729Sjoerg       invalid = true;
4847330f729Sjoerg       break;
4857330f729Sjoerg     }
4867330f729Sjoerg 
4877330f729Sjoerg     IdentifierInfo *paramName = Tok.getIdentifierInfo();
4887330f729Sjoerg     SourceLocation paramLoc = ConsumeToken();
4897330f729Sjoerg 
4907330f729Sjoerg     // If there is a bound, parse it.
4917330f729Sjoerg     SourceLocation colonLoc;
4927330f729Sjoerg     TypeResult boundType;
4937330f729Sjoerg     if (TryConsumeToken(tok::colon, colonLoc)) {
4947330f729Sjoerg       // Once we've seen a bound, we know this is not a list of protocol
4957330f729Sjoerg       // references.
4967330f729Sjoerg       if (mayBeProtocolList) {
4977330f729Sjoerg         // Up until now, we have been queuing up parameters because they
4987330f729Sjoerg         // might be protocol references. Turn them into parameters now.
4997330f729Sjoerg         makeProtocolIdentsIntoTypeParameters();
5007330f729Sjoerg       }
5017330f729Sjoerg 
5027330f729Sjoerg       // type-name
5037330f729Sjoerg       boundType = ParseTypeName();
5047330f729Sjoerg       if (boundType.isInvalid())
5057330f729Sjoerg         invalid = true;
5067330f729Sjoerg     } else if (mayBeProtocolList) {
5077330f729Sjoerg       // If this could still be a protocol list, just capture the identifier.
5087330f729Sjoerg       // We don't want to turn it into a parameter.
5097330f729Sjoerg       protocolIdents.push_back(std::make_pair(paramName, paramLoc));
5107330f729Sjoerg       continue;
5117330f729Sjoerg     }
5127330f729Sjoerg 
5137330f729Sjoerg     // Create the type parameter.
5147330f729Sjoerg     DeclResult typeParam = Actions.actOnObjCTypeParam(
5157330f729Sjoerg         getCurScope(), variance, varianceLoc, typeParams.size(), paramName,
5167330f729Sjoerg         paramLoc, colonLoc, boundType.isUsable() ? boundType.get() : nullptr);
5177330f729Sjoerg     if (typeParam.isUsable())
5187330f729Sjoerg       typeParams.push_back(typeParam.get());
5197330f729Sjoerg   } while (TryConsumeToken(tok::comma));
5207330f729Sjoerg 
5217330f729Sjoerg   // Parse the '>'.
5227330f729Sjoerg   if (invalid) {
5237330f729Sjoerg     SkipUntil(tok::greater, tok::at, StopBeforeMatch);
5247330f729Sjoerg     if (Tok.is(tok::greater))
5257330f729Sjoerg       ConsumeToken();
526*e038c9c4Sjoerg   } else if (ParseGreaterThanInTemplateList(lAngleLoc, rAngleLoc,
5277330f729Sjoerg                                             /*ConsumeLastToken=*/true,
5287330f729Sjoerg                                             /*ObjCGenericList=*/true)) {
5297330f729Sjoerg     SkipUntil({tok::greater, tok::greaterequal, tok::at, tok::minus,
5307330f729Sjoerg                tok::minus, tok::plus, tok::colon, tok::l_paren, tok::l_brace,
5317330f729Sjoerg                tok::comma, tok::semi },
5327330f729Sjoerg               StopBeforeMatch);
5337330f729Sjoerg     if (Tok.is(tok::greater))
5347330f729Sjoerg       ConsumeToken();
5357330f729Sjoerg   }
5367330f729Sjoerg 
5377330f729Sjoerg   if (mayBeProtocolList) {
5387330f729Sjoerg     // A type parameter list must be followed by either a ':' (indicating the
5397330f729Sjoerg     // presence of a superclass) or a '(' (indicating that this is a category
5407330f729Sjoerg     // or extension). This disambiguates between an objc-type-parameter-list
5417330f729Sjoerg     // and a objc-protocol-refs.
5427330f729Sjoerg     if (Tok.isNot(tok::colon) && Tok.isNot(tok::l_paren)) {
5437330f729Sjoerg       // Returning null indicates that we don't have a type parameter list.
5447330f729Sjoerg       // The results the caller needs to handle the protocol references are
5457330f729Sjoerg       // captured in the reference parameters already.
5467330f729Sjoerg       return nullptr;
5477330f729Sjoerg     }
5487330f729Sjoerg 
5497330f729Sjoerg     // We have a type parameter list that looks like a list of protocol
5507330f729Sjoerg     // references. Turn that parameter list into type parameters.
5517330f729Sjoerg     makeProtocolIdentsIntoTypeParameters();
5527330f729Sjoerg   }
5537330f729Sjoerg 
5547330f729Sjoerg   // Form the type parameter list and enter its scope.
5557330f729Sjoerg   ObjCTypeParamList *list = Actions.actOnObjCTypeParamList(
5567330f729Sjoerg                               getCurScope(),
5577330f729Sjoerg                               lAngleLoc,
5587330f729Sjoerg                               typeParams,
5597330f729Sjoerg                               rAngleLoc);
5607330f729Sjoerg   Scope.enter(list);
5617330f729Sjoerg 
5627330f729Sjoerg   // Clear out the angle locations; they're used by the caller to indicate
5637330f729Sjoerg   // whether there are any protocol references.
5647330f729Sjoerg   lAngleLoc = SourceLocation();
5657330f729Sjoerg   rAngleLoc = SourceLocation();
5667330f729Sjoerg   return invalid ? nullptr : list;
5677330f729Sjoerg }
5687330f729Sjoerg 
5697330f729Sjoerg /// Parse an objc-type-parameter-list.
parseObjCTypeParamList()5707330f729Sjoerg ObjCTypeParamList *Parser::parseObjCTypeParamList() {
5717330f729Sjoerg   SourceLocation lAngleLoc;
5727330f729Sjoerg   SmallVector<IdentifierLocPair, 1> protocolIdents;
5737330f729Sjoerg   SourceLocation rAngleLoc;
5747330f729Sjoerg 
5757330f729Sjoerg   ObjCTypeParamListScope Scope(Actions, getCurScope());
5767330f729Sjoerg   return parseObjCTypeParamListOrProtocolRefs(Scope, lAngleLoc, protocolIdents,
5777330f729Sjoerg                                               rAngleLoc,
5787330f729Sjoerg                                               /*mayBeProtocolList=*/false);
5797330f729Sjoerg }
5807330f729Sjoerg 
5817330f729Sjoerg ///   objc-interface-decl-list:
5827330f729Sjoerg ///     empty
5837330f729Sjoerg ///     objc-interface-decl-list objc-property-decl [OBJC2]
5847330f729Sjoerg ///     objc-interface-decl-list objc-method-requirement [OBJC2]
5857330f729Sjoerg ///     objc-interface-decl-list objc-method-proto ';'
5867330f729Sjoerg ///     objc-interface-decl-list declaration
5877330f729Sjoerg ///     objc-interface-decl-list ';'
5887330f729Sjoerg ///
5897330f729Sjoerg ///   objc-method-requirement: [OBJC2]
5907330f729Sjoerg ///     @required
5917330f729Sjoerg ///     @optional
5927330f729Sjoerg ///
ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,Decl * CDecl)5937330f729Sjoerg void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
5947330f729Sjoerg                                         Decl *CDecl) {
5957330f729Sjoerg   SmallVector<Decl *, 32> allMethods;
5967330f729Sjoerg   SmallVector<DeclGroupPtrTy, 8> allTUVariables;
5977330f729Sjoerg   tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword;
5987330f729Sjoerg 
5997330f729Sjoerg   SourceRange AtEnd;
6007330f729Sjoerg 
6017330f729Sjoerg   while (1) {
6027330f729Sjoerg     // If this is a method prototype, parse it.
6037330f729Sjoerg     if (Tok.isOneOf(tok::minus, tok::plus)) {
6047330f729Sjoerg       if (Decl *methodPrototype =
6057330f729Sjoerg           ParseObjCMethodPrototype(MethodImplKind, false))
6067330f729Sjoerg         allMethods.push_back(methodPrototype);
6077330f729Sjoerg       // Consume the ';' here, since ParseObjCMethodPrototype() is re-used for
6087330f729Sjoerg       // method definitions.
6097330f729Sjoerg       if (ExpectAndConsumeSemi(diag::err_expected_semi_after_method_proto)) {
6107330f729Sjoerg         // We didn't find a semi and we error'ed out. Skip until a ';' or '@'.
6117330f729Sjoerg         SkipUntil(tok::at, StopAtSemi | StopBeforeMatch);
6127330f729Sjoerg         if (Tok.is(tok::semi))
6137330f729Sjoerg           ConsumeToken();
6147330f729Sjoerg       }
6157330f729Sjoerg       continue;
6167330f729Sjoerg     }
6177330f729Sjoerg     if (Tok.is(tok::l_paren)) {
6187330f729Sjoerg       Diag(Tok, diag::err_expected_minus_or_plus);
6197330f729Sjoerg       ParseObjCMethodDecl(Tok.getLocation(),
6207330f729Sjoerg                           tok::minus,
6217330f729Sjoerg                           MethodImplKind, false);
6227330f729Sjoerg       continue;
6237330f729Sjoerg     }
6247330f729Sjoerg     // Ignore excess semicolons.
6257330f729Sjoerg     if (Tok.is(tok::semi)) {
6267330f729Sjoerg       // FIXME: This should use ConsumeExtraSemi() for extraneous semicolons,
6277330f729Sjoerg       // to make -Wextra-semi diagnose them.
6287330f729Sjoerg       ConsumeToken();
6297330f729Sjoerg       continue;
6307330f729Sjoerg     }
6317330f729Sjoerg 
6327330f729Sjoerg     // If we got to the end of the file, exit the loop.
6337330f729Sjoerg     if (isEofOrEom())
6347330f729Sjoerg       break;
6357330f729Sjoerg 
6367330f729Sjoerg     // Code completion within an Objective-C interface.
6377330f729Sjoerg     if (Tok.is(tok::code_completion)) {
638*e038c9c4Sjoerg       cutOffParsing();
6397330f729Sjoerg       Actions.CodeCompleteOrdinaryName(getCurScope(),
6407330f729Sjoerg                             CurParsedObjCImpl? Sema::PCC_ObjCImplementation
6417330f729Sjoerg                                              : Sema::PCC_ObjCInterface);
642*e038c9c4Sjoerg       return;
6437330f729Sjoerg     }
6447330f729Sjoerg 
6457330f729Sjoerg     // If we don't have an @ directive, parse it as a function definition.
6467330f729Sjoerg     if (Tok.isNot(tok::at)) {
6477330f729Sjoerg       // The code below does not consume '}'s because it is afraid of eating the
6487330f729Sjoerg       // end of a namespace.  Because of the way this code is structured, an
6497330f729Sjoerg       // erroneous r_brace would cause an infinite loop if not handled here.
6507330f729Sjoerg       if (Tok.is(tok::r_brace))
6517330f729Sjoerg         break;
6527330f729Sjoerg 
6537330f729Sjoerg       ParsedAttributesWithRange attrs(AttrFactory);
6547330f729Sjoerg 
6557330f729Sjoerg       // Since we call ParseDeclarationOrFunctionDefinition() instead of
6567330f729Sjoerg       // ParseExternalDeclaration() below (so that this doesn't parse nested
6577330f729Sjoerg       // @interfaces), this needs to duplicate some code from the latter.
6587330f729Sjoerg       if (Tok.isOneOf(tok::kw_static_assert, tok::kw__Static_assert)) {
6597330f729Sjoerg         SourceLocation DeclEnd;
6607330f729Sjoerg         allTUVariables.push_back(
661*e038c9c4Sjoerg             ParseDeclaration(DeclaratorContext::File, DeclEnd, attrs));
6627330f729Sjoerg         continue;
6637330f729Sjoerg       }
6647330f729Sjoerg 
6657330f729Sjoerg       allTUVariables.push_back(ParseDeclarationOrFunctionDefinition(attrs));
6667330f729Sjoerg       continue;
6677330f729Sjoerg     }
6687330f729Sjoerg 
6697330f729Sjoerg     // Otherwise, we have an @ directive, eat the @.
6707330f729Sjoerg     SourceLocation AtLoc = ConsumeToken(); // the "@"
6717330f729Sjoerg     if (Tok.is(tok::code_completion)) {
672*e038c9c4Sjoerg       cutOffParsing();
6737330f729Sjoerg       Actions.CodeCompleteObjCAtDirective(getCurScope());
674*e038c9c4Sjoerg       return;
6757330f729Sjoerg     }
6767330f729Sjoerg 
6777330f729Sjoerg     tok::ObjCKeywordKind DirectiveKind = Tok.getObjCKeywordID();
6787330f729Sjoerg 
6797330f729Sjoerg     if (DirectiveKind == tok::objc_end) { // @end -> terminate list
6807330f729Sjoerg       AtEnd.setBegin(AtLoc);
6817330f729Sjoerg       AtEnd.setEnd(Tok.getLocation());
6827330f729Sjoerg       break;
6837330f729Sjoerg     } else if (DirectiveKind == tok::objc_not_keyword) {
6847330f729Sjoerg       Diag(Tok, diag::err_objc_unknown_at);
6857330f729Sjoerg       SkipUntil(tok::semi);
6867330f729Sjoerg       continue;
6877330f729Sjoerg     }
6887330f729Sjoerg 
6897330f729Sjoerg     // Eat the identifier.
6907330f729Sjoerg     ConsumeToken();
6917330f729Sjoerg 
6927330f729Sjoerg     switch (DirectiveKind) {
6937330f729Sjoerg     default:
6947330f729Sjoerg       // FIXME: If someone forgets an @end on a protocol, this loop will
6957330f729Sjoerg       // continue to eat up tons of stuff and spew lots of nonsense errors.  It
6967330f729Sjoerg       // would probably be better to bail out if we saw an @class or @interface
6977330f729Sjoerg       // or something like that.
6987330f729Sjoerg       Diag(AtLoc, diag::err_objc_illegal_interface_qual);
6997330f729Sjoerg       // Skip until we see an '@' or '}' or ';'.
7007330f729Sjoerg       SkipUntil(tok::r_brace, tok::at, StopAtSemi);
7017330f729Sjoerg       break;
7027330f729Sjoerg 
7037330f729Sjoerg     case tok::objc_implementation:
7047330f729Sjoerg     case tok::objc_interface:
7057330f729Sjoerg       Diag(AtLoc, diag::err_objc_missing_end)
7067330f729Sjoerg           << FixItHint::CreateInsertion(AtLoc, "@end\n");
7077330f729Sjoerg       Diag(CDecl->getBeginLoc(), diag::note_objc_container_start)
7087330f729Sjoerg           << (int)Actions.getObjCContainerKind();
7097330f729Sjoerg       ConsumeToken();
7107330f729Sjoerg       break;
7117330f729Sjoerg 
7127330f729Sjoerg     case tok::objc_required:
7137330f729Sjoerg     case tok::objc_optional:
7147330f729Sjoerg       // This is only valid on protocols.
7157330f729Sjoerg       if (contextKey != tok::objc_protocol)
7167330f729Sjoerg         Diag(AtLoc, diag::err_objc_directive_only_in_protocol);
7177330f729Sjoerg       else
7187330f729Sjoerg         MethodImplKind = DirectiveKind;
7197330f729Sjoerg       break;
7207330f729Sjoerg 
7217330f729Sjoerg     case tok::objc_property:
7227330f729Sjoerg       ObjCDeclSpec OCDS;
7237330f729Sjoerg       SourceLocation LParenLoc;
7247330f729Sjoerg       // Parse property attribute list, if any.
7257330f729Sjoerg       if (Tok.is(tok::l_paren)) {
7267330f729Sjoerg         LParenLoc = Tok.getLocation();
7277330f729Sjoerg         ParseObjCPropertyAttribute(OCDS);
7287330f729Sjoerg       }
7297330f729Sjoerg 
7307330f729Sjoerg       bool addedToDeclSpec = false;
7317330f729Sjoerg       auto ObjCPropertyCallback = [&](ParsingFieldDeclarator &FD) {
7327330f729Sjoerg         if (FD.D.getIdentifier() == nullptr) {
7337330f729Sjoerg           Diag(AtLoc, diag::err_objc_property_requires_field_name)
7347330f729Sjoerg               << FD.D.getSourceRange();
7357330f729Sjoerg           return;
7367330f729Sjoerg         }
7377330f729Sjoerg         if (FD.BitfieldSize) {
7387330f729Sjoerg           Diag(AtLoc, diag::err_objc_property_bitfield)
7397330f729Sjoerg               << FD.D.getSourceRange();
7407330f729Sjoerg           return;
7417330f729Sjoerg         }
7427330f729Sjoerg 
7437330f729Sjoerg         // Map a nullability property attribute to a context-sensitive keyword
7447330f729Sjoerg         // attribute.
745*e038c9c4Sjoerg         if (OCDS.getPropertyAttributes() &
746*e038c9c4Sjoerg             ObjCPropertyAttribute::kind_nullability)
7477330f729Sjoerg           addContextSensitiveTypeNullability(*this, FD.D, OCDS.getNullability(),
7487330f729Sjoerg                                              OCDS.getNullabilityLoc(),
7497330f729Sjoerg                                              addedToDeclSpec);
7507330f729Sjoerg 
7517330f729Sjoerg         // Install the property declarator into interfaceDecl.
7527330f729Sjoerg         IdentifierInfo *SelName =
7537330f729Sjoerg             OCDS.getGetterName() ? OCDS.getGetterName() : FD.D.getIdentifier();
7547330f729Sjoerg 
7557330f729Sjoerg         Selector GetterSel = PP.getSelectorTable().getNullarySelector(SelName);
7567330f729Sjoerg         IdentifierInfo *SetterName = OCDS.getSetterName();
7577330f729Sjoerg         Selector SetterSel;
7587330f729Sjoerg         if (SetterName)
7597330f729Sjoerg           SetterSel = PP.getSelectorTable().getSelector(1, &SetterName);
7607330f729Sjoerg         else
7617330f729Sjoerg           SetterSel = SelectorTable::constructSetterSelector(
7627330f729Sjoerg               PP.getIdentifierTable(), PP.getSelectorTable(),
7637330f729Sjoerg               FD.D.getIdentifier());
7647330f729Sjoerg         Decl *Property = Actions.ActOnProperty(
7657330f729Sjoerg             getCurScope(), AtLoc, LParenLoc, FD, OCDS, GetterSel, SetterSel,
7667330f729Sjoerg             MethodImplKind);
7677330f729Sjoerg 
7687330f729Sjoerg         FD.complete(Property);
7697330f729Sjoerg       };
7707330f729Sjoerg 
7717330f729Sjoerg       // Parse all the comma separated declarators.
7727330f729Sjoerg       ParsingDeclSpec DS(*this);
7737330f729Sjoerg       ParseStructDeclaration(DS, ObjCPropertyCallback);
7747330f729Sjoerg 
7757330f729Sjoerg       ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list);
7767330f729Sjoerg       break;
7777330f729Sjoerg     }
7787330f729Sjoerg   }
7797330f729Sjoerg 
7807330f729Sjoerg   // We break out of the big loop in two cases: when we see @end or when we see
7817330f729Sjoerg   // EOF.  In the former case, eat the @end.  In the later case, emit an error.
7827330f729Sjoerg   if (Tok.is(tok::code_completion)) {
783*e038c9c4Sjoerg     cutOffParsing();
7847330f729Sjoerg     Actions.CodeCompleteObjCAtDirective(getCurScope());
785*e038c9c4Sjoerg     return;
7867330f729Sjoerg   } else if (Tok.isObjCAtKeyword(tok::objc_end)) {
7877330f729Sjoerg     ConsumeToken(); // the "end" identifier
7887330f729Sjoerg   } else {
7897330f729Sjoerg     Diag(Tok, diag::err_objc_missing_end)
7907330f729Sjoerg         << FixItHint::CreateInsertion(Tok.getLocation(), "\n@end\n");
7917330f729Sjoerg     Diag(CDecl->getBeginLoc(), diag::note_objc_container_start)
7927330f729Sjoerg         << (int)Actions.getObjCContainerKind();
7937330f729Sjoerg     AtEnd.setBegin(Tok.getLocation());
7947330f729Sjoerg     AtEnd.setEnd(Tok.getLocation());
7957330f729Sjoerg   }
7967330f729Sjoerg 
7977330f729Sjoerg   // Insert collected methods declarations into the @interface object.
7987330f729Sjoerg   // This passes in an invalid SourceLocation for AtEndLoc when EOF is hit.
7997330f729Sjoerg   Actions.ActOnAtEnd(getCurScope(), AtEnd, allMethods, allTUVariables);
8007330f729Sjoerg }
8017330f729Sjoerg 
8027330f729Sjoerg /// Diagnose redundant or conflicting nullability information.
diagnoseRedundantPropertyNullability(Parser & P,ObjCDeclSpec & DS,NullabilityKind nullability,SourceLocation nullabilityLoc)8037330f729Sjoerg static void diagnoseRedundantPropertyNullability(Parser &P,
8047330f729Sjoerg                                                  ObjCDeclSpec &DS,
8057330f729Sjoerg                                                  NullabilityKind nullability,
8067330f729Sjoerg                                                  SourceLocation nullabilityLoc){
8077330f729Sjoerg   if (DS.getNullability() == nullability) {
8087330f729Sjoerg     P.Diag(nullabilityLoc, diag::warn_nullability_duplicate)
8097330f729Sjoerg       << DiagNullabilityKind(nullability, true)
8107330f729Sjoerg       << SourceRange(DS.getNullabilityLoc());
8117330f729Sjoerg     return;
8127330f729Sjoerg   }
8137330f729Sjoerg 
8147330f729Sjoerg   P.Diag(nullabilityLoc, diag::err_nullability_conflicting)
8157330f729Sjoerg     << DiagNullabilityKind(nullability, true)
8167330f729Sjoerg     << DiagNullabilityKind(DS.getNullability(), true)
8177330f729Sjoerg     << SourceRange(DS.getNullabilityLoc());
8187330f729Sjoerg }
8197330f729Sjoerg 
8207330f729Sjoerg ///   Parse property attribute declarations.
8217330f729Sjoerg ///
8227330f729Sjoerg ///   property-attr-decl: '(' property-attrlist ')'
8237330f729Sjoerg ///   property-attrlist:
8247330f729Sjoerg ///     property-attribute
8257330f729Sjoerg ///     property-attrlist ',' property-attribute
8267330f729Sjoerg ///   property-attribute:
8277330f729Sjoerg ///     getter '=' identifier
8287330f729Sjoerg ///     setter '=' identifier ':'
829*e038c9c4Sjoerg ///     direct
8307330f729Sjoerg ///     readonly
8317330f729Sjoerg ///     readwrite
8327330f729Sjoerg ///     assign
8337330f729Sjoerg ///     retain
8347330f729Sjoerg ///     copy
8357330f729Sjoerg ///     nonatomic
8367330f729Sjoerg ///     atomic
8377330f729Sjoerg ///     strong
8387330f729Sjoerg ///     weak
8397330f729Sjoerg ///     unsafe_unretained
8407330f729Sjoerg ///     nonnull
8417330f729Sjoerg ///     nullable
8427330f729Sjoerg ///     null_unspecified
8437330f729Sjoerg ///     null_resettable
8447330f729Sjoerg ///     class
8457330f729Sjoerg ///
ParseObjCPropertyAttribute(ObjCDeclSpec & DS)8467330f729Sjoerg void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) {
8477330f729Sjoerg   assert(Tok.getKind() == tok::l_paren);
8487330f729Sjoerg   BalancedDelimiterTracker T(*this, tok::l_paren);
8497330f729Sjoerg   T.consumeOpen();
8507330f729Sjoerg 
8517330f729Sjoerg   while (1) {
8527330f729Sjoerg     if (Tok.is(tok::code_completion)) {
853*e038c9c4Sjoerg       cutOffParsing();
8547330f729Sjoerg       Actions.CodeCompleteObjCPropertyFlags(getCurScope(), DS);
855*e038c9c4Sjoerg       return;
8567330f729Sjoerg     }
8577330f729Sjoerg     const IdentifierInfo *II = Tok.getIdentifierInfo();
8587330f729Sjoerg 
8597330f729Sjoerg     // If this is not an identifier at all, bail out early.
8607330f729Sjoerg     if (!II) {
8617330f729Sjoerg       T.consumeClose();
8627330f729Sjoerg       return;
8637330f729Sjoerg     }
8647330f729Sjoerg 
8657330f729Sjoerg     SourceLocation AttrName = ConsumeToken(); // consume last attribute name
8667330f729Sjoerg 
8677330f729Sjoerg     if (II->isStr("readonly"))
868*e038c9c4Sjoerg       DS.setPropertyAttributes(ObjCPropertyAttribute::kind_readonly);
8697330f729Sjoerg     else if (II->isStr("assign"))
870*e038c9c4Sjoerg       DS.setPropertyAttributes(ObjCPropertyAttribute::kind_assign);
8717330f729Sjoerg     else if (II->isStr("unsafe_unretained"))
872*e038c9c4Sjoerg       DS.setPropertyAttributes(ObjCPropertyAttribute::kind_unsafe_unretained);
8737330f729Sjoerg     else if (II->isStr("readwrite"))
874*e038c9c4Sjoerg       DS.setPropertyAttributes(ObjCPropertyAttribute::kind_readwrite);
8757330f729Sjoerg     else if (II->isStr("retain"))
876*e038c9c4Sjoerg       DS.setPropertyAttributes(ObjCPropertyAttribute::kind_retain);
8777330f729Sjoerg     else if (II->isStr("strong"))
878*e038c9c4Sjoerg       DS.setPropertyAttributes(ObjCPropertyAttribute::kind_strong);
8797330f729Sjoerg     else if (II->isStr("copy"))
880*e038c9c4Sjoerg       DS.setPropertyAttributes(ObjCPropertyAttribute::kind_copy);
8817330f729Sjoerg     else if (II->isStr("nonatomic"))
882*e038c9c4Sjoerg       DS.setPropertyAttributes(ObjCPropertyAttribute::kind_nonatomic);
8837330f729Sjoerg     else if (II->isStr("atomic"))
884*e038c9c4Sjoerg       DS.setPropertyAttributes(ObjCPropertyAttribute::kind_atomic);
8857330f729Sjoerg     else if (II->isStr("weak"))
886*e038c9c4Sjoerg       DS.setPropertyAttributes(ObjCPropertyAttribute::kind_weak);
8877330f729Sjoerg     else if (II->isStr("getter") || II->isStr("setter")) {
8887330f729Sjoerg       bool IsSetter = II->getNameStart()[0] == 's';
8897330f729Sjoerg 
8907330f729Sjoerg       // getter/setter require extra treatment.
8917330f729Sjoerg       unsigned DiagID = IsSetter ? diag::err_objc_expected_equal_for_setter :
8927330f729Sjoerg                                    diag::err_objc_expected_equal_for_getter;
8937330f729Sjoerg 
8947330f729Sjoerg       if (ExpectAndConsume(tok::equal, DiagID)) {
8957330f729Sjoerg         SkipUntil(tok::r_paren, StopAtSemi);
8967330f729Sjoerg         return;
8977330f729Sjoerg       }
8987330f729Sjoerg 
8997330f729Sjoerg       if (Tok.is(tok::code_completion)) {
900*e038c9c4Sjoerg         cutOffParsing();
9017330f729Sjoerg         if (IsSetter)
9027330f729Sjoerg           Actions.CodeCompleteObjCPropertySetter(getCurScope());
9037330f729Sjoerg         else
9047330f729Sjoerg           Actions.CodeCompleteObjCPropertyGetter(getCurScope());
905*e038c9c4Sjoerg         return;
9067330f729Sjoerg       }
9077330f729Sjoerg 
9087330f729Sjoerg       SourceLocation SelLoc;
9097330f729Sjoerg       IdentifierInfo *SelIdent = ParseObjCSelectorPiece(SelLoc);
9107330f729Sjoerg 
9117330f729Sjoerg       if (!SelIdent) {
9127330f729Sjoerg         Diag(Tok, diag::err_objc_expected_selector_for_getter_setter)
9137330f729Sjoerg           << IsSetter;
9147330f729Sjoerg         SkipUntil(tok::r_paren, StopAtSemi);
9157330f729Sjoerg         return;
9167330f729Sjoerg       }
9177330f729Sjoerg 
9187330f729Sjoerg       if (IsSetter) {
919*e038c9c4Sjoerg         DS.setPropertyAttributes(ObjCPropertyAttribute::kind_setter);
9207330f729Sjoerg         DS.setSetterName(SelIdent, SelLoc);
9217330f729Sjoerg 
9227330f729Sjoerg         if (ExpectAndConsume(tok::colon,
9237330f729Sjoerg                              diag::err_expected_colon_after_setter_name)) {
9247330f729Sjoerg           SkipUntil(tok::r_paren, StopAtSemi);
9257330f729Sjoerg           return;
9267330f729Sjoerg         }
9277330f729Sjoerg       } else {
928*e038c9c4Sjoerg         DS.setPropertyAttributes(ObjCPropertyAttribute::kind_getter);
9297330f729Sjoerg         DS.setGetterName(SelIdent, SelLoc);
9307330f729Sjoerg       }
9317330f729Sjoerg     } else if (II->isStr("nonnull")) {
932*e038c9c4Sjoerg       if (DS.getPropertyAttributes() & ObjCPropertyAttribute::kind_nullability)
9337330f729Sjoerg         diagnoseRedundantPropertyNullability(*this, DS,
9347330f729Sjoerg                                              NullabilityKind::NonNull,
9357330f729Sjoerg                                              Tok.getLocation());
936*e038c9c4Sjoerg       DS.setPropertyAttributes(ObjCPropertyAttribute::kind_nullability);
9377330f729Sjoerg       DS.setNullability(Tok.getLocation(), NullabilityKind::NonNull);
9387330f729Sjoerg     } else if (II->isStr("nullable")) {
939*e038c9c4Sjoerg       if (DS.getPropertyAttributes() & ObjCPropertyAttribute::kind_nullability)
9407330f729Sjoerg         diagnoseRedundantPropertyNullability(*this, DS,
9417330f729Sjoerg                                              NullabilityKind::Nullable,
9427330f729Sjoerg                                              Tok.getLocation());
943*e038c9c4Sjoerg       DS.setPropertyAttributes(ObjCPropertyAttribute::kind_nullability);
9447330f729Sjoerg       DS.setNullability(Tok.getLocation(), NullabilityKind::Nullable);
9457330f729Sjoerg     } else if (II->isStr("null_unspecified")) {
946*e038c9c4Sjoerg       if (DS.getPropertyAttributes() & ObjCPropertyAttribute::kind_nullability)
9477330f729Sjoerg         diagnoseRedundantPropertyNullability(*this, DS,
9487330f729Sjoerg                                              NullabilityKind::Unspecified,
9497330f729Sjoerg                                              Tok.getLocation());
950*e038c9c4Sjoerg       DS.setPropertyAttributes(ObjCPropertyAttribute::kind_nullability);
9517330f729Sjoerg       DS.setNullability(Tok.getLocation(), NullabilityKind::Unspecified);
9527330f729Sjoerg     } else if (II->isStr("null_resettable")) {
953*e038c9c4Sjoerg       if (DS.getPropertyAttributes() & ObjCPropertyAttribute::kind_nullability)
9547330f729Sjoerg         diagnoseRedundantPropertyNullability(*this, DS,
9557330f729Sjoerg                                              NullabilityKind::Unspecified,
9567330f729Sjoerg                                              Tok.getLocation());
957*e038c9c4Sjoerg       DS.setPropertyAttributes(ObjCPropertyAttribute::kind_nullability);
9587330f729Sjoerg       DS.setNullability(Tok.getLocation(), NullabilityKind::Unspecified);
9597330f729Sjoerg 
9607330f729Sjoerg       // Also set the null_resettable bit.
961*e038c9c4Sjoerg       DS.setPropertyAttributes(ObjCPropertyAttribute::kind_null_resettable);
9627330f729Sjoerg     } else if (II->isStr("class")) {
963*e038c9c4Sjoerg       DS.setPropertyAttributes(ObjCPropertyAttribute::kind_class);
964*e038c9c4Sjoerg     } else if (II->isStr("direct")) {
965*e038c9c4Sjoerg       DS.setPropertyAttributes(ObjCPropertyAttribute::kind_direct);
9667330f729Sjoerg     } else {
9677330f729Sjoerg       Diag(AttrName, diag::err_objc_expected_property_attr) << II;
9687330f729Sjoerg       SkipUntil(tok::r_paren, StopAtSemi);
9697330f729Sjoerg       return;
9707330f729Sjoerg     }
9717330f729Sjoerg 
9727330f729Sjoerg     if (Tok.isNot(tok::comma))
9737330f729Sjoerg       break;
9747330f729Sjoerg 
9757330f729Sjoerg     ConsumeToken();
9767330f729Sjoerg   }
9777330f729Sjoerg 
9787330f729Sjoerg   T.consumeClose();
9797330f729Sjoerg }
9807330f729Sjoerg 
9817330f729Sjoerg ///   objc-method-proto:
9827330f729Sjoerg ///     objc-instance-method objc-method-decl objc-method-attributes[opt]
9837330f729Sjoerg ///     objc-class-method objc-method-decl objc-method-attributes[opt]
9847330f729Sjoerg ///
9857330f729Sjoerg ///   objc-instance-method: '-'
9867330f729Sjoerg ///   objc-class-method: '+'
9877330f729Sjoerg ///
9887330f729Sjoerg ///   objc-method-attributes:         [OBJC2]
9897330f729Sjoerg ///     __attribute__((deprecated))
9907330f729Sjoerg ///
ParseObjCMethodPrototype(tok::ObjCKeywordKind MethodImplKind,bool MethodDefinition)9917330f729Sjoerg Decl *Parser::ParseObjCMethodPrototype(tok::ObjCKeywordKind MethodImplKind,
9927330f729Sjoerg                                        bool MethodDefinition) {
9937330f729Sjoerg   assert(Tok.isOneOf(tok::minus, tok::plus) && "expected +/-");
9947330f729Sjoerg 
9957330f729Sjoerg   tok::TokenKind methodType = Tok.getKind();
9967330f729Sjoerg   SourceLocation mLoc = ConsumeToken();
9977330f729Sjoerg   Decl *MDecl = ParseObjCMethodDecl(mLoc, methodType, MethodImplKind,
9987330f729Sjoerg                                     MethodDefinition);
9997330f729Sjoerg   // Since this rule is used for both method declarations and definitions,
10007330f729Sjoerg   // the caller is (optionally) responsible for consuming the ';'.
10017330f729Sjoerg   return MDecl;
10027330f729Sjoerg }
10037330f729Sjoerg 
10047330f729Sjoerg ///   objc-selector:
10057330f729Sjoerg ///     identifier
10067330f729Sjoerg ///     one of
10077330f729Sjoerg ///       enum struct union if else while do for switch case default
10087330f729Sjoerg ///       break continue return goto asm sizeof typeof __alignof
10097330f729Sjoerg ///       unsigned long const short volatile signed restrict _Complex
10107330f729Sjoerg ///       in out inout bycopy byref oneway int char float double void _Bool
10117330f729Sjoerg ///
ParseObjCSelectorPiece(SourceLocation & SelectorLoc)10127330f729Sjoerg IdentifierInfo *Parser::ParseObjCSelectorPiece(SourceLocation &SelectorLoc) {
10137330f729Sjoerg 
10147330f729Sjoerg   switch (Tok.getKind()) {
10157330f729Sjoerg   default:
10167330f729Sjoerg     return nullptr;
10177330f729Sjoerg   case tok::colon:
10187330f729Sjoerg     // Empty selector piece uses the location of the ':'.
10197330f729Sjoerg     SelectorLoc = Tok.getLocation();
10207330f729Sjoerg     return nullptr;
10217330f729Sjoerg   case tok::ampamp:
10227330f729Sjoerg   case tok::ampequal:
10237330f729Sjoerg   case tok::amp:
10247330f729Sjoerg   case tok::pipe:
10257330f729Sjoerg   case tok::tilde:
10267330f729Sjoerg   case tok::exclaim:
10277330f729Sjoerg   case tok::exclaimequal:
10287330f729Sjoerg   case tok::pipepipe:
10297330f729Sjoerg   case tok::pipeequal:
10307330f729Sjoerg   case tok::caret:
10317330f729Sjoerg   case tok::caretequal: {
10327330f729Sjoerg     std::string ThisTok(PP.getSpelling(Tok));
10337330f729Sjoerg     if (isLetter(ThisTok[0])) {
10347330f729Sjoerg       IdentifierInfo *II = &PP.getIdentifierTable().get(ThisTok);
10357330f729Sjoerg       Tok.setKind(tok::identifier);
10367330f729Sjoerg       SelectorLoc = ConsumeToken();
10377330f729Sjoerg       return II;
10387330f729Sjoerg     }
10397330f729Sjoerg     return nullptr;
10407330f729Sjoerg   }
10417330f729Sjoerg 
10427330f729Sjoerg   case tok::identifier:
10437330f729Sjoerg   case tok::kw_asm:
10447330f729Sjoerg   case tok::kw_auto:
10457330f729Sjoerg   case tok::kw_bool:
10467330f729Sjoerg   case tok::kw_break:
10477330f729Sjoerg   case tok::kw_case:
10487330f729Sjoerg   case tok::kw_catch:
10497330f729Sjoerg   case tok::kw_char:
10507330f729Sjoerg   case tok::kw_class:
10517330f729Sjoerg   case tok::kw_const:
10527330f729Sjoerg   case tok::kw_const_cast:
10537330f729Sjoerg   case tok::kw_continue:
10547330f729Sjoerg   case tok::kw_default:
10557330f729Sjoerg   case tok::kw_delete:
10567330f729Sjoerg   case tok::kw_do:
10577330f729Sjoerg   case tok::kw_double:
10587330f729Sjoerg   case tok::kw_dynamic_cast:
10597330f729Sjoerg   case tok::kw_else:
10607330f729Sjoerg   case tok::kw_enum:
10617330f729Sjoerg   case tok::kw_explicit:
10627330f729Sjoerg   case tok::kw_export:
10637330f729Sjoerg   case tok::kw_extern:
10647330f729Sjoerg   case tok::kw_false:
10657330f729Sjoerg   case tok::kw_float:
10667330f729Sjoerg   case tok::kw_for:
10677330f729Sjoerg   case tok::kw_friend:
10687330f729Sjoerg   case tok::kw_goto:
10697330f729Sjoerg   case tok::kw_if:
10707330f729Sjoerg   case tok::kw_inline:
10717330f729Sjoerg   case tok::kw_int:
10727330f729Sjoerg   case tok::kw_long:
10737330f729Sjoerg   case tok::kw_mutable:
10747330f729Sjoerg   case tok::kw_namespace:
10757330f729Sjoerg   case tok::kw_new:
10767330f729Sjoerg   case tok::kw_operator:
10777330f729Sjoerg   case tok::kw_private:
10787330f729Sjoerg   case tok::kw_protected:
10797330f729Sjoerg   case tok::kw_public:
10807330f729Sjoerg   case tok::kw_register:
10817330f729Sjoerg   case tok::kw_reinterpret_cast:
10827330f729Sjoerg   case tok::kw_restrict:
10837330f729Sjoerg   case tok::kw_return:
10847330f729Sjoerg   case tok::kw_short:
10857330f729Sjoerg   case tok::kw_signed:
10867330f729Sjoerg   case tok::kw_sizeof:
10877330f729Sjoerg   case tok::kw_static:
10887330f729Sjoerg   case tok::kw_static_cast:
10897330f729Sjoerg   case tok::kw_struct:
10907330f729Sjoerg   case tok::kw_switch:
10917330f729Sjoerg   case tok::kw_template:
10927330f729Sjoerg   case tok::kw_this:
10937330f729Sjoerg   case tok::kw_throw:
10947330f729Sjoerg   case tok::kw_true:
10957330f729Sjoerg   case tok::kw_try:
10967330f729Sjoerg   case tok::kw_typedef:
10977330f729Sjoerg   case tok::kw_typeid:
10987330f729Sjoerg   case tok::kw_typename:
10997330f729Sjoerg   case tok::kw_typeof:
11007330f729Sjoerg   case tok::kw_union:
11017330f729Sjoerg   case tok::kw_unsigned:
11027330f729Sjoerg   case tok::kw_using:
11037330f729Sjoerg   case tok::kw_virtual:
11047330f729Sjoerg   case tok::kw_void:
11057330f729Sjoerg   case tok::kw_volatile:
11067330f729Sjoerg   case tok::kw_wchar_t:
11077330f729Sjoerg   case tok::kw_while:
11087330f729Sjoerg   case tok::kw__Bool:
11097330f729Sjoerg   case tok::kw__Complex:
11107330f729Sjoerg   case tok::kw___alignof:
11117330f729Sjoerg   case tok::kw___auto_type:
11127330f729Sjoerg     IdentifierInfo *II = Tok.getIdentifierInfo();
11137330f729Sjoerg     SelectorLoc = ConsumeToken();
11147330f729Sjoerg     return II;
11157330f729Sjoerg   }
11167330f729Sjoerg }
11177330f729Sjoerg 
11187330f729Sjoerg ///  objc-for-collection-in: 'in'
11197330f729Sjoerg ///
isTokIdentifier_in() const11207330f729Sjoerg bool Parser::isTokIdentifier_in() const {
11217330f729Sjoerg   // FIXME: May have to do additional look-ahead to only allow for
11227330f729Sjoerg   // valid tokens following an 'in'; such as an identifier, unary operators,
11237330f729Sjoerg   // '[' etc.
11247330f729Sjoerg   return (getLangOpts().ObjC && Tok.is(tok::identifier) &&
11257330f729Sjoerg           Tok.getIdentifierInfo() == ObjCTypeQuals[objc_in]);
11267330f729Sjoerg }
11277330f729Sjoerg 
11287330f729Sjoerg /// ParseObjCTypeQualifierList - This routine parses the objective-c's type
11297330f729Sjoerg /// qualifier list and builds their bitmask representation in the input
11307330f729Sjoerg /// argument.
11317330f729Sjoerg ///
11327330f729Sjoerg ///   objc-type-qualifiers:
11337330f729Sjoerg ///     objc-type-qualifier
11347330f729Sjoerg ///     objc-type-qualifiers objc-type-qualifier
11357330f729Sjoerg ///
11367330f729Sjoerg ///   objc-type-qualifier:
11377330f729Sjoerg ///     'in'
11387330f729Sjoerg ///     'out'
11397330f729Sjoerg ///     'inout'
11407330f729Sjoerg ///     'oneway'
11417330f729Sjoerg ///     'bycopy'
11427330f729Sjoerg ///     'byref'
11437330f729Sjoerg ///     'nonnull'
11447330f729Sjoerg ///     'nullable'
11457330f729Sjoerg ///     'null_unspecified'
11467330f729Sjoerg ///
ParseObjCTypeQualifierList(ObjCDeclSpec & DS,DeclaratorContext Context)11477330f729Sjoerg void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS,
11487330f729Sjoerg                                         DeclaratorContext Context) {
1149*e038c9c4Sjoerg   assert(Context == DeclaratorContext::ObjCParameter ||
1150*e038c9c4Sjoerg          Context == DeclaratorContext::ObjCResult);
11517330f729Sjoerg 
11527330f729Sjoerg   while (1) {
11537330f729Sjoerg     if (Tok.is(tok::code_completion)) {
1154*e038c9c4Sjoerg       cutOffParsing();
1155*e038c9c4Sjoerg       Actions.CodeCompleteObjCPassingType(
1156*e038c9c4Sjoerg           getCurScope(), DS, Context == DeclaratorContext::ObjCParameter);
1157*e038c9c4Sjoerg       return;
11587330f729Sjoerg     }
11597330f729Sjoerg 
11607330f729Sjoerg     if (Tok.isNot(tok::identifier))
11617330f729Sjoerg       return;
11627330f729Sjoerg 
11637330f729Sjoerg     const IdentifierInfo *II = Tok.getIdentifierInfo();
11647330f729Sjoerg     for (unsigned i = 0; i != objc_NumQuals; ++i) {
11657330f729Sjoerg       if (II != ObjCTypeQuals[i] ||
11667330f729Sjoerg           NextToken().is(tok::less) ||
11677330f729Sjoerg           NextToken().is(tok::coloncolon))
11687330f729Sjoerg         continue;
11697330f729Sjoerg 
11707330f729Sjoerg       ObjCDeclSpec::ObjCDeclQualifier Qual;
11717330f729Sjoerg       NullabilityKind Nullability;
11727330f729Sjoerg       switch (i) {
11737330f729Sjoerg       default: llvm_unreachable("Unknown decl qualifier");
11747330f729Sjoerg       case objc_in:     Qual = ObjCDeclSpec::DQ_In; break;
11757330f729Sjoerg       case objc_out:    Qual = ObjCDeclSpec::DQ_Out; break;
11767330f729Sjoerg       case objc_inout:  Qual = ObjCDeclSpec::DQ_Inout; break;
11777330f729Sjoerg       case objc_oneway: Qual = ObjCDeclSpec::DQ_Oneway; break;
11787330f729Sjoerg       case objc_bycopy: Qual = ObjCDeclSpec::DQ_Bycopy; break;
11797330f729Sjoerg       case objc_byref:  Qual = ObjCDeclSpec::DQ_Byref; break;
11807330f729Sjoerg 
11817330f729Sjoerg       case objc_nonnull:
11827330f729Sjoerg         Qual = ObjCDeclSpec::DQ_CSNullability;
11837330f729Sjoerg         Nullability = NullabilityKind::NonNull;
11847330f729Sjoerg         break;
11857330f729Sjoerg 
11867330f729Sjoerg       case objc_nullable:
11877330f729Sjoerg         Qual = ObjCDeclSpec::DQ_CSNullability;
11887330f729Sjoerg         Nullability = NullabilityKind::Nullable;
11897330f729Sjoerg         break;
11907330f729Sjoerg 
11917330f729Sjoerg       case objc_null_unspecified:
11927330f729Sjoerg         Qual = ObjCDeclSpec::DQ_CSNullability;
11937330f729Sjoerg         Nullability = NullabilityKind::Unspecified;
11947330f729Sjoerg         break;
11957330f729Sjoerg       }
11967330f729Sjoerg 
11977330f729Sjoerg       // FIXME: Diagnose redundant specifiers.
11987330f729Sjoerg       DS.setObjCDeclQualifier(Qual);
11997330f729Sjoerg       if (Qual == ObjCDeclSpec::DQ_CSNullability)
12007330f729Sjoerg         DS.setNullability(Tok.getLocation(), Nullability);
12017330f729Sjoerg 
12027330f729Sjoerg       ConsumeToken();
12037330f729Sjoerg       II = nullptr;
12047330f729Sjoerg       break;
12057330f729Sjoerg     }
12067330f729Sjoerg 
12077330f729Sjoerg     // If this wasn't a recognized qualifier, bail out.
12087330f729Sjoerg     if (II) return;
12097330f729Sjoerg   }
12107330f729Sjoerg }
12117330f729Sjoerg 
12127330f729Sjoerg /// Take all the decl attributes out of the given list and add
12137330f729Sjoerg /// them to the given attribute set.
takeDeclAttributes(ParsedAttributesView & attrs,ParsedAttributesView & from)12147330f729Sjoerg static void takeDeclAttributes(ParsedAttributesView &attrs,
12157330f729Sjoerg                                ParsedAttributesView &from) {
12167330f729Sjoerg   for (auto &AL : llvm::reverse(from)) {
12177330f729Sjoerg     if (!AL.isUsedAsTypeAttr()) {
12187330f729Sjoerg       from.remove(&AL);
12197330f729Sjoerg       attrs.addAtEnd(&AL);
12207330f729Sjoerg     }
12217330f729Sjoerg   }
12227330f729Sjoerg }
12237330f729Sjoerg 
12247330f729Sjoerg /// takeDeclAttributes - Take all the decl attributes from the given
12257330f729Sjoerg /// declarator and add them to the given list.
takeDeclAttributes(ParsedAttributes & attrs,Declarator & D)12267330f729Sjoerg static void takeDeclAttributes(ParsedAttributes &attrs,
12277330f729Sjoerg                                Declarator &D) {
12287330f729Sjoerg   // First, take ownership of all attributes.
12297330f729Sjoerg   attrs.getPool().takeAllFrom(D.getAttributePool());
12307330f729Sjoerg   attrs.getPool().takeAllFrom(D.getDeclSpec().getAttributePool());
12317330f729Sjoerg 
12327330f729Sjoerg   // Now actually move the attributes over.
12337330f729Sjoerg   takeDeclAttributes(attrs, D.getMutableDeclSpec().getAttributes());
12347330f729Sjoerg   takeDeclAttributes(attrs, D.getAttributes());
12357330f729Sjoerg   for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i)
12367330f729Sjoerg     takeDeclAttributes(attrs, D.getTypeObject(i).getAttrs());
12377330f729Sjoerg }
12387330f729Sjoerg 
12397330f729Sjoerg ///   objc-type-name:
12407330f729Sjoerg ///     '(' objc-type-qualifiers[opt] type-name ')'
12417330f729Sjoerg ///     '(' objc-type-qualifiers[opt] ')'
12427330f729Sjoerg ///
ParseObjCTypeName(ObjCDeclSpec & DS,DeclaratorContext context,ParsedAttributes * paramAttrs)12437330f729Sjoerg ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS,
12447330f729Sjoerg                                      DeclaratorContext context,
12457330f729Sjoerg                                      ParsedAttributes *paramAttrs) {
1246*e038c9c4Sjoerg   assert(context == DeclaratorContext::ObjCParameter ||
1247*e038c9c4Sjoerg          context == DeclaratorContext::ObjCResult);
12487330f729Sjoerg   assert((paramAttrs != nullptr) ==
1249*e038c9c4Sjoerg          (context == DeclaratorContext::ObjCParameter));
12507330f729Sjoerg 
12517330f729Sjoerg   assert(Tok.is(tok::l_paren) && "expected (");
12527330f729Sjoerg 
12537330f729Sjoerg   BalancedDelimiterTracker T(*this, tok::l_paren);
12547330f729Sjoerg   T.consumeOpen();
12557330f729Sjoerg 
12567330f729Sjoerg   ObjCDeclContextSwitch ObjCDC(*this);
12577330f729Sjoerg 
12587330f729Sjoerg   // Parse type qualifiers, in, inout, etc.
12597330f729Sjoerg   ParseObjCTypeQualifierList(DS, context);
12607330f729Sjoerg   SourceLocation TypeStartLoc = Tok.getLocation();
12617330f729Sjoerg 
12627330f729Sjoerg   ParsedType Ty;
12637330f729Sjoerg   if (isTypeSpecifierQualifier() || isObjCInstancetype()) {
12647330f729Sjoerg     // Parse an abstract declarator.
12657330f729Sjoerg     DeclSpec declSpec(AttrFactory);
12667330f729Sjoerg     declSpec.setObjCQualifiers(&DS);
12677330f729Sjoerg     DeclSpecContext dsContext = DeclSpecContext::DSC_normal;
1268*e038c9c4Sjoerg     if (context == DeclaratorContext::ObjCResult)
12697330f729Sjoerg       dsContext = DeclSpecContext::DSC_objc_method_result;
12707330f729Sjoerg     ParseSpecifierQualifierList(declSpec, AS_none, dsContext);
12717330f729Sjoerg     Declarator declarator(declSpec, context);
12727330f729Sjoerg     ParseDeclarator(declarator);
12737330f729Sjoerg 
12747330f729Sjoerg     // If that's not invalid, extract a type.
12757330f729Sjoerg     if (!declarator.isInvalidType()) {
12767330f729Sjoerg       // Map a nullability specifier to a context-sensitive keyword attribute.
12777330f729Sjoerg       bool addedToDeclSpec = false;
12787330f729Sjoerg       if (DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability)
12797330f729Sjoerg         addContextSensitiveTypeNullability(*this, declarator,
12807330f729Sjoerg                                            DS.getNullability(),
12817330f729Sjoerg                                            DS.getNullabilityLoc(),
12827330f729Sjoerg                                            addedToDeclSpec);
12837330f729Sjoerg 
12847330f729Sjoerg       TypeResult type = Actions.ActOnTypeName(getCurScope(), declarator);
12857330f729Sjoerg       if (!type.isInvalid())
12867330f729Sjoerg         Ty = type.get();
12877330f729Sjoerg 
12887330f729Sjoerg       // If we're parsing a parameter, steal all the decl attributes
12897330f729Sjoerg       // and add them to the decl spec.
1290*e038c9c4Sjoerg       if (context == DeclaratorContext::ObjCParameter)
12917330f729Sjoerg         takeDeclAttributes(*paramAttrs, declarator);
12927330f729Sjoerg     }
12937330f729Sjoerg   }
12947330f729Sjoerg 
12957330f729Sjoerg   if (Tok.is(tok::r_paren))
12967330f729Sjoerg     T.consumeClose();
12977330f729Sjoerg   else if (Tok.getLocation() == TypeStartLoc) {
12987330f729Sjoerg     // If we didn't eat any tokens, then this isn't a type.
12997330f729Sjoerg     Diag(Tok, diag::err_expected_type);
13007330f729Sjoerg     SkipUntil(tok::r_paren, StopAtSemi);
13017330f729Sjoerg   } else {
13027330f729Sjoerg     // Otherwise, we found *something*, but didn't get a ')' in the right
13037330f729Sjoerg     // place.  Emit an error then return what we have as the type.
13047330f729Sjoerg     T.consumeClose();
13057330f729Sjoerg   }
13067330f729Sjoerg   return Ty;
13077330f729Sjoerg }
13087330f729Sjoerg 
13097330f729Sjoerg ///   objc-method-decl:
13107330f729Sjoerg ///     objc-selector
13117330f729Sjoerg ///     objc-keyword-selector objc-parmlist[opt]
13127330f729Sjoerg ///     objc-type-name objc-selector
13137330f729Sjoerg ///     objc-type-name objc-keyword-selector objc-parmlist[opt]
13147330f729Sjoerg ///
13157330f729Sjoerg ///   objc-keyword-selector:
13167330f729Sjoerg ///     objc-keyword-decl
13177330f729Sjoerg ///     objc-keyword-selector objc-keyword-decl
13187330f729Sjoerg ///
13197330f729Sjoerg ///   objc-keyword-decl:
13207330f729Sjoerg ///     objc-selector ':' objc-type-name objc-keyword-attributes[opt] identifier
13217330f729Sjoerg ///     objc-selector ':' objc-keyword-attributes[opt] identifier
13227330f729Sjoerg ///     ':' objc-type-name objc-keyword-attributes[opt] identifier
13237330f729Sjoerg ///     ':' objc-keyword-attributes[opt] identifier
13247330f729Sjoerg ///
13257330f729Sjoerg ///   objc-parmlist:
13267330f729Sjoerg ///     objc-parms objc-ellipsis[opt]
13277330f729Sjoerg ///
13287330f729Sjoerg ///   objc-parms:
13297330f729Sjoerg ///     objc-parms , parameter-declaration
13307330f729Sjoerg ///
13317330f729Sjoerg ///   objc-ellipsis:
13327330f729Sjoerg ///     , ...
13337330f729Sjoerg ///
13347330f729Sjoerg ///   objc-keyword-attributes:         [OBJC2]
13357330f729Sjoerg ///     __attribute__((unused))
13367330f729Sjoerg ///
ParseObjCMethodDecl(SourceLocation mLoc,tok::TokenKind mType,tok::ObjCKeywordKind MethodImplKind,bool MethodDefinition)13377330f729Sjoerg Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
13387330f729Sjoerg                                   tok::TokenKind mType,
13397330f729Sjoerg                                   tok::ObjCKeywordKind MethodImplKind,
13407330f729Sjoerg                                   bool MethodDefinition) {
13417330f729Sjoerg   ParsingDeclRAIIObject PD(*this, ParsingDeclRAIIObject::NoParent);
13427330f729Sjoerg 
13437330f729Sjoerg   if (Tok.is(tok::code_completion)) {
1344*e038c9c4Sjoerg     cutOffParsing();
13457330f729Sjoerg     Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus,
13467330f729Sjoerg                                        /*ReturnType=*/nullptr);
13477330f729Sjoerg     return nullptr;
13487330f729Sjoerg   }
13497330f729Sjoerg 
13507330f729Sjoerg   // Parse the return type if present.
13517330f729Sjoerg   ParsedType ReturnType;
13527330f729Sjoerg   ObjCDeclSpec DSRet;
13537330f729Sjoerg   if (Tok.is(tok::l_paren))
1354*e038c9c4Sjoerg     ReturnType =
1355*e038c9c4Sjoerg         ParseObjCTypeName(DSRet, DeclaratorContext::ObjCResult, nullptr);
13567330f729Sjoerg 
13577330f729Sjoerg   // If attributes exist before the method, parse them.
13587330f729Sjoerg   ParsedAttributes methodAttrs(AttrFactory);
1359*e038c9c4Sjoerg   MaybeParseAttributes(PAKM_CXX11 | (getLangOpts().ObjC ? PAKM_GNU : 0),
1360*e038c9c4Sjoerg                        methodAttrs);
13617330f729Sjoerg 
13627330f729Sjoerg   if (Tok.is(tok::code_completion)) {
1363*e038c9c4Sjoerg     cutOffParsing();
13647330f729Sjoerg     Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus,
13657330f729Sjoerg                                        ReturnType);
13667330f729Sjoerg     return nullptr;
13677330f729Sjoerg   }
13687330f729Sjoerg 
13697330f729Sjoerg   // Now parse the selector.
13707330f729Sjoerg   SourceLocation selLoc;
13717330f729Sjoerg   IdentifierInfo *SelIdent = ParseObjCSelectorPiece(selLoc);
13727330f729Sjoerg 
13737330f729Sjoerg   // An unnamed colon is valid.
13747330f729Sjoerg   if (!SelIdent && Tok.isNot(tok::colon)) { // missing selector name.
13757330f729Sjoerg     Diag(Tok, diag::err_expected_selector_for_method)
13767330f729Sjoerg       << SourceRange(mLoc, Tok.getLocation());
13777330f729Sjoerg     // Skip until we get a ; or @.
13787330f729Sjoerg     SkipUntil(tok::at, StopAtSemi | StopBeforeMatch);
13797330f729Sjoerg     return nullptr;
13807330f729Sjoerg   }
13817330f729Sjoerg 
13827330f729Sjoerg   SmallVector<DeclaratorChunk::ParamInfo, 8> CParamInfo;
13837330f729Sjoerg   if (Tok.isNot(tok::colon)) {
13847330f729Sjoerg     // If attributes exist after the method, parse them.
1385*e038c9c4Sjoerg     MaybeParseAttributes(PAKM_CXX11 | (getLangOpts().ObjC ? PAKM_GNU : 0),
1386*e038c9c4Sjoerg                          methodAttrs);
13877330f729Sjoerg 
13887330f729Sjoerg     Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent);
13897330f729Sjoerg     Decl *Result = Actions.ActOnMethodDeclaration(
13907330f729Sjoerg         getCurScope(), mLoc, Tok.getLocation(), mType, DSRet, ReturnType,
13917330f729Sjoerg         selLoc, Sel, nullptr, CParamInfo.data(), CParamInfo.size(), methodAttrs,
13927330f729Sjoerg         MethodImplKind, false, MethodDefinition);
13937330f729Sjoerg     PD.complete(Result);
13947330f729Sjoerg     return Result;
13957330f729Sjoerg   }
13967330f729Sjoerg 
13977330f729Sjoerg   SmallVector<IdentifierInfo *, 12> KeyIdents;
13987330f729Sjoerg   SmallVector<SourceLocation, 12> KeyLocs;
13997330f729Sjoerg   SmallVector<Sema::ObjCArgInfo, 12> ArgInfos;
14007330f729Sjoerg   ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope |
14017330f729Sjoerg                             Scope::FunctionDeclarationScope | Scope::DeclScope);
14027330f729Sjoerg 
14037330f729Sjoerg   AttributePool allParamAttrs(AttrFactory);
14047330f729Sjoerg   while (1) {
14057330f729Sjoerg     ParsedAttributes paramAttrs(AttrFactory);
14067330f729Sjoerg     Sema::ObjCArgInfo ArgInfo;
14077330f729Sjoerg 
14087330f729Sjoerg     // Each iteration parses a single keyword argument.
14097330f729Sjoerg     if (ExpectAndConsume(tok::colon))
14107330f729Sjoerg       break;
14117330f729Sjoerg 
14127330f729Sjoerg     ArgInfo.Type = nullptr;
14137330f729Sjoerg     if (Tok.is(tok::l_paren)) // Parse the argument type if present.
1414*e038c9c4Sjoerg       ArgInfo.Type = ParseObjCTypeName(
1415*e038c9c4Sjoerg           ArgInfo.DeclSpec, DeclaratorContext::ObjCParameter, &paramAttrs);
14167330f729Sjoerg 
14177330f729Sjoerg     // If attributes exist before the argument name, parse them.
14187330f729Sjoerg     // Regardless, collect all the attributes we've parsed so far.
1419*e038c9c4Sjoerg     MaybeParseAttributes(PAKM_CXX11 | (getLangOpts().ObjC ? PAKM_GNU : 0),
1420*e038c9c4Sjoerg                          paramAttrs);
14217330f729Sjoerg     ArgInfo.ArgAttrs = paramAttrs;
14227330f729Sjoerg 
14237330f729Sjoerg     // Code completion for the next piece of the selector.
14247330f729Sjoerg     if (Tok.is(tok::code_completion)) {
1425*e038c9c4Sjoerg       cutOffParsing();
14267330f729Sjoerg       KeyIdents.push_back(SelIdent);
14277330f729Sjoerg       Actions.CodeCompleteObjCMethodDeclSelector(getCurScope(),
14287330f729Sjoerg                                                  mType == tok::minus,
14297330f729Sjoerg                                                  /*AtParameterName=*/true,
14307330f729Sjoerg                                                  ReturnType, KeyIdents);
14317330f729Sjoerg       return nullptr;
14327330f729Sjoerg     }
14337330f729Sjoerg 
14347330f729Sjoerg     if (expectIdentifier())
14357330f729Sjoerg       break; // missing argument name.
14367330f729Sjoerg 
14377330f729Sjoerg     ArgInfo.Name = Tok.getIdentifierInfo();
14387330f729Sjoerg     ArgInfo.NameLoc = Tok.getLocation();
14397330f729Sjoerg     ConsumeToken(); // Eat the identifier.
14407330f729Sjoerg 
14417330f729Sjoerg     ArgInfos.push_back(ArgInfo);
14427330f729Sjoerg     KeyIdents.push_back(SelIdent);
14437330f729Sjoerg     KeyLocs.push_back(selLoc);
14447330f729Sjoerg 
14457330f729Sjoerg     // Make sure the attributes persist.
14467330f729Sjoerg     allParamAttrs.takeAllFrom(paramAttrs.getPool());
14477330f729Sjoerg 
14487330f729Sjoerg     // Code completion for the next piece of the selector.
14497330f729Sjoerg     if (Tok.is(tok::code_completion)) {
1450*e038c9c4Sjoerg       cutOffParsing();
14517330f729Sjoerg       Actions.CodeCompleteObjCMethodDeclSelector(getCurScope(),
14527330f729Sjoerg                                                  mType == tok::minus,
14537330f729Sjoerg                                                  /*AtParameterName=*/false,
14547330f729Sjoerg                                                  ReturnType, KeyIdents);
14557330f729Sjoerg       return nullptr;
14567330f729Sjoerg     }
14577330f729Sjoerg 
14587330f729Sjoerg     // Check for another keyword selector.
14597330f729Sjoerg     SelIdent = ParseObjCSelectorPiece(selLoc);
14607330f729Sjoerg     if (!SelIdent && Tok.isNot(tok::colon))
14617330f729Sjoerg       break;
14627330f729Sjoerg     if (!SelIdent) {
14637330f729Sjoerg       SourceLocation ColonLoc = Tok.getLocation();
14647330f729Sjoerg       if (PP.getLocForEndOfToken(ArgInfo.NameLoc) == ColonLoc) {
14657330f729Sjoerg         Diag(ArgInfo.NameLoc, diag::warn_missing_selector_name) << ArgInfo.Name;
14667330f729Sjoerg         Diag(ArgInfo.NameLoc, diag::note_missing_selector_name) << ArgInfo.Name;
14677330f729Sjoerg         Diag(ColonLoc, diag::note_force_empty_selector_name) << ArgInfo.Name;
14687330f729Sjoerg       }
14697330f729Sjoerg     }
14707330f729Sjoerg     // We have a selector or a colon, continue parsing.
14717330f729Sjoerg   }
14727330f729Sjoerg 
14737330f729Sjoerg   bool isVariadic = false;
14747330f729Sjoerg   bool cStyleParamWarned = false;
14757330f729Sjoerg   // Parse the (optional) parameter list.
14767330f729Sjoerg   while (Tok.is(tok::comma)) {
14777330f729Sjoerg     ConsumeToken();
14787330f729Sjoerg     if (Tok.is(tok::ellipsis)) {
14797330f729Sjoerg       isVariadic = true;
14807330f729Sjoerg       ConsumeToken();
14817330f729Sjoerg       break;
14827330f729Sjoerg     }
14837330f729Sjoerg     if (!cStyleParamWarned) {
14847330f729Sjoerg       Diag(Tok, diag::warn_cstyle_param);
14857330f729Sjoerg       cStyleParamWarned = true;
14867330f729Sjoerg     }
14877330f729Sjoerg     DeclSpec DS(AttrFactory);
14887330f729Sjoerg     ParseDeclarationSpecifiers(DS);
14897330f729Sjoerg     // Parse the declarator.
1490*e038c9c4Sjoerg     Declarator ParmDecl(DS, DeclaratorContext::Prototype);
14917330f729Sjoerg     ParseDeclarator(ParmDecl);
14927330f729Sjoerg     IdentifierInfo *ParmII = ParmDecl.getIdentifier();
14937330f729Sjoerg     Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDecl);
14947330f729Sjoerg     CParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,
14957330f729Sjoerg                                                     ParmDecl.getIdentifierLoc(),
14967330f729Sjoerg                                                     Param,
14977330f729Sjoerg                                                     nullptr));
14987330f729Sjoerg   }
14997330f729Sjoerg 
15007330f729Sjoerg   // FIXME: Add support for optional parameter list...
15017330f729Sjoerg   // If attributes exist after the method, parse them.
1502*e038c9c4Sjoerg   MaybeParseAttributes(PAKM_CXX11 | (getLangOpts().ObjC ? PAKM_GNU : 0),
1503*e038c9c4Sjoerg                        methodAttrs);
15047330f729Sjoerg 
15057330f729Sjoerg   if (KeyIdents.size() == 0)
15067330f729Sjoerg     return nullptr;
15077330f729Sjoerg 
15087330f729Sjoerg   Selector Sel = PP.getSelectorTable().getSelector(KeyIdents.size(),
15097330f729Sjoerg                                                    &KeyIdents[0]);
15107330f729Sjoerg   Decl *Result = Actions.ActOnMethodDeclaration(
15117330f729Sjoerg       getCurScope(), mLoc, Tok.getLocation(), mType, DSRet, ReturnType, KeyLocs,
15127330f729Sjoerg       Sel, &ArgInfos[0], CParamInfo.data(), CParamInfo.size(), methodAttrs,
15137330f729Sjoerg       MethodImplKind, isVariadic, MethodDefinition);
15147330f729Sjoerg 
15157330f729Sjoerg   PD.complete(Result);
15167330f729Sjoerg   return Result;
15177330f729Sjoerg }
15187330f729Sjoerg 
15197330f729Sjoerg ///   objc-protocol-refs:
15207330f729Sjoerg ///     '<' identifier-list '>'
15217330f729Sjoerg ///
15227330f729Sjoerg bool Parser::
ParseObjCProtocolReferences(SmallVectorImpl<Decl * > & Protocols,SmallVectorImpl<SourceLocation> & ProtocolLocs,bool WarnOnDeclarations,bool ForObjCContainer,SourceLocation & LAngleLoc,SourceLocation & EndLoc,bool consumeLastToken)15237330f729Sjoerg ParseObjCProtocolReferences(SmallVectorImpl<Decl *> &Protocols,
15247330f729Sjoerg                             SmallVectorImpl<SourceLocation> &ProtocolLocs,
15257330f729Sjoerg                             bool WarnOnDeclarations, bool ForObjCContainer,
15267330f729Sjoerg                             SourceLocation &LAngleLoc, SourceLocation &EndLoc,
15277330f729Sjoerg                             bool consumeLastToken) {
15287330f729Sjoerg   assert(Tok.is(tok::less) && "expected <");
15297330f729Sjoerg 
15307330f729Sjoerg   LAngleLoc = ConsumeToken(); // the "<"
15317330f729Sjoerg 
15327330f729Sjoerg   SmallVector<IdentifierLocPair, 8> ProtocolIdents;
15337330f729Sjoerg 
15347330f729Sjoerg   while (1) {
15357330f729Sjoerg     if (Tok.is(tok::code_completion)) {
15367330f729Sjoerg       cutOffParsing();
1537*e038c9c4Sjoerg       Actions.CodeCompleteObjCProtocolReferences(ProtocolIdents);
15387330f729Sjoerg       return true;
15397330f729Sjoerg     }
15407330f729Sjoerg 
15417330f729Sjoerg     if (expectIdentifier()) {
15427330f729Sjoerg       SkipUntil(tok::greater, StopAtSemi);
15437330f729Sjoerg       return true;
15447330f729Sjoerg     }
15457330f729Sjoerg     ProtocolIdents.push_back(std::make_pair(Tok.getIdentifierInfo(),
15467330f729Sjoerg                                        Tok.getLocation()));
15477330f729Sjoerg     ProtocolLocs.push_back(Tok.getLocation());
15487330f729Sjoerg     ConsumeToken();
15497330f729Sjoerg 
15507330f729Sjoerg     if (!TryConsumeToken(tok::comma))
15517330f729Sjoerg       break;
15527330f729Sjoerg   }
15537330f729Sjoerg 
15547330f729Sjoerg   // Consume the '>'.
1555*e038c9c4Sjoerg   if (ParseGreaterThanInTemplateList(LAngleLoc, EndLoc, consumeLastToken,
15567330f729Sjoerg                                      /*ObjCGenericList=*/false))
15577330f729Sjoerg     return true;
15587330f729Sjoerg 
15597330f729Sjoerg   // Convert the list of protocols identifiers into a list of protocol decls.
15607330f729Sjoerg   Actions.FindProtocolDeclaration(WarnOnDeclarations, ForObjCContainer,
15617330f729Sjoerg                                   ProtocolIdents, Protocols);
15627330f729Sjoerg   return false;
15637330f729Sjoerg }
15647330f729Sjoerg 
parseObjCProtocolQualifierType(SourceLocation & rAngleLoc)15657330f729Sjoerg TypeResult Parser::parseObjCProtocolQualifierType(SourceLocation &rAngleLoc) {
15667330f729Sjoerg   assert(Tok.is(tok::less) && "Protocol qualifiers start with '<'");
15677330f729Sjoerg   assert(getLangOpts().ObjC && "Protocol qualifiers only exist in Objective-C");
15687330f729Sjoerg 
15697330f729Sjoerg   SourceLocation lAngleLoc;
15707330f729Sjoerg   SmallVector<Decl *, 8> protocols;
15717330f729Sjoerg   SmallVector<SourceLocation, 8> protocolLocs;
15727330f729Sjoerg   (void)ParseObjCProtocolReferences(protocols, protocolLocs, false, false,
15737330f729Sjoerg                                     lAngleLoc, rAngleLoc,
15747330f729Sjoerg                                     /*consumeLastToken=*/true);
15757330f729Sjoerg   TypeResult result = Actions.actOnObjCProtocolQualifierType(lAngleLoc,
15767330f729Sjoerg                                                              protocols,
15777330f729Sjoerg                                                              protocolLocs,
15787330f729Sjoerg                                                              rAngleLoc);
15797330f729Sjoerg   if (result.isUsable()) {
15807330f729Sjoerg     Diag(lAngleLoc, diag::warn_objc_protocol_qualifier_missing_id)
15817330f729Sjoerg       << FixItHint::CreateInsertion(lAngleLoc, "id")
15827330f729Sjoerg       << SourceRange(lAngleLoc, rAngleLoc);
15837330f729Sjoerg   }
15847330f729Sjoerg 
15857330f729Sjoerg   return result;
15867330f729Sjoerg }
15877330f729Sjoerg 
15887330f729Sjoerg /// Parse Objective-C type arguments or protocol qualifiers.
15897330f729Sjoerg ///
15907330f729Sjoerg ///   objc-type-arguments:
15917330f729Sjoerg ///     '<' type-name '...'[opt] (',' type-name '...'[opt])* '>'
15927330f729Sjoerg ///
parseObjCTypeArgsOrProtocolQualifiers(ParsedType baseType,SourceLocation & typeArgsLAngleLoc,SmallVectorImpl<ParsedType> & typeArgs,SourceLocation & typeArgsRAngleLoc,SourceLocation & protocolLAngleLoc,SmallVectorImpl<Decl * > & protocols,SmallVectorImpl<SourceLocation> & protocolLocs,SourceLocation & protocolRAngleLoc,bool consumeLastToken,bool warnOnIncompleteProtocols)15937330f729Sjoerg void Parser::parseObjCTypeArgsOrProtocolQualifiers(
15947330f729Sjoerg        ParsedType baseType,
15957330f729Sjoerg        SourceLocation &typeArgsLAngleLoc,
15967330f729Sjoerg        SmallVectorImpl<ParsedType> &typeArgs,
15977330f729Sjoerg        SourceLocation &typeArgsRAngleLoc,
15987330f729Sjoerg        SourceLocation &protocolLAngleLoc,
15997330f729Sjoerg        SmallVectorImpl<Decl *> &protocols,
16007330f729Sjoerg        SmallVectorImpl<SourceLocation> &protocolLocs,
16017330f729Sjoerg        SourceLocation &protocolRAngleLoc,
16027330f729Sjoerg        bool consumeLastToken,
16037330f729Sjoerg        bool warnOnIncompleteProtocols) {
16047330f729Sjoerg   assert(Tok.is(tok::less) && "Not at the start of type args or protocols");
16057330f729Sjoerg   SourceLocation lAngleLoc = ConsumeToken();
16067330f729Sjoerg 
16077330f729Sjoerg   // Whether all of the elements we've parsed thus far are single
16087330f729Sjoerg   // identifiers, which might be types or might be protocols.
16097330f729Sjoerg   bool allSingleIdentifiers = true;
16107330f729Sjoerg   SmallVector<IdentifierInfo *, 4> identifiers;
16117330f729Sjoerg   SmallVectorImpl<SourceLocation> &identifierLocs = protocolLocs;
16127330f729Sjoerg 
16137330f729Sjoerg   // Parse a list of comma-separated identifiers, bailing out if we
16147330f729Sjoerg   // see something different.
16157330f729Sjoerg   do {
16167330f729Sjoerg     // Parse a single identifier.
16177330f729Sjoerg     if (Tok.is(tok::identifier) &&
16187330f729Sjoerg         (NextToken().is(tok::comma) ||
16197330f729Sjoerg          NextToken().is(tok::greater) ||
16207330f729Sjoerg          NextToken().is(tok::greatergreater))) {
16217330f729Sjoerg       identifiers.push_back(Tok.getIdentifierInfo());
16227330f729Sjoerg       identifierLocs.push_back(ConsumeToken());
16237330f729Sjoerg       continue;
16247330f729Sjoerg     }
16257330f729Sjoerg 
16267330f729Sjoerg     if (Tok.is(tok::code_completion)) {
16277330f729Sjoerg       // FIXME: Also include types here.
16287330f729Sjoerg       SmallVector<IdentifierLocPair, 4> identifierLocPairs;
16297330f729Sjoerg       for (unsigned i = 0, n = identifiers.size(); i != n; ++i) {
16307330f729Sjoerg         identifierLocPairs.push_back(IdentifierLocPair(identifiers[i],
16317330f729Sjoerg                                                        identifierLocs[i]));
16327330f729Sjoerg       }
16337330f729Sjoerg 
16347330f729Sjoerg       QualType BaseT = Actions.GetTypeFromParser(baseType);
1635*e038c9c4Sjoerg       cutOffParsing();
16367330f729Sjoerg       if (!BaseT.isNull() && BaseT->acceptsObjCTypeParams()) {
16377330f729Sjoerg         Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Type);
16387330f729Sjoerg       } else {
16397330f729Sjoerg         Actions.CodeCompleteObjCProtocolReferences(identifierLocPairs);
16407330f729Sjoerg       }
16417330f729Sjoerg       return;
16427330f729Sjoerg     }
16437330f729Sjoerg 
16447330f729Sjoerg     allSingleIdentifiers = false;
16457330f729Sjoerg     break;
16467330f729Sjoerg   } while (TryConsumeToken(tok::comma));
16477330f729Sjoerg 
16487330f729Sjoerg   // If we parsed an identifier list, semantic analysis sorts out
16497330f729Sjoerg   // whether it refers to protocols or to type arguments.
16507330f729Sjoerg   if (allSingleIdentifiers) {
16517330f729Sjoerg     // Parse the closing '>'.
16527330f729Sjoerg     SourceLocation rAngleLoc;
1653*e038c9c4Sjoerg     (void)ParseGreaterThanInTemplateList(lAngleLoc, rAngleLoc, consumeLastToken,
16547330f729Sjoerg                                          /*ObjCGenericList=*/true);
16557330f729Sjoerg 
16567330f729Sjoerg     // Let Sema figure out what we parsed.
16577330f729Sjoerg     Actions.actOnObjCTypeArgsOrProtocolQualifiers(getCurScope(),
16587330f729Sjoerg                                                   baseType,
16597330f729Sjoerg                                                   lAngleLoc,
16607330f729Sjoerg                                                   identifiers,
16617330f729Sjoerg                                                   identifierLocs,
16627330f729Sjoerg                                                   rAngleLoc,
16637330f729Sjoerg                                                   typeArgsLAngleLoc,
16647330f729Sjoerg                                                   typeArgs,
16657330f729Sjoerg                                                   typeArgsRAngleLoc,
16667330f729Sjoerg                                                   protocolLAngleLoc,
16677330f729Sjoerg                                                   protocols,
16687330f729Sjoerg                                                   protocolRAngleLoc,
16697330f729Sjoerg                                                   warnOnIncompleteProtocols);
16707330f729Sjoerg     return;
16717330f729Sjoerg   }
16727330f729Sjoerg 
16737330f729Sjoerg   // We parsed an identifier list but stumbled into non single identifiers, this
16747330f729Sjoerg   // means we might (a) check that what we already parsed is a legitimate type
16757330f729Sjoerg   // (not a protocol or unknown type) and (b) parse the remaining ones, which
16767330f729Sjoerg   // must all be type args.
16777330f729Sjoerg 
16787330f729Sjoerg   // Convert the identifiers into type arguments.
16797330f729Sjoerg   bool invalid = false;
16807330f729Sjoerg   IdentifierInfo *foundProtocolId = nullptr, *foundValidTypeId = nullptr;
16817330f729Sjoerg   SourceLocation foundProtocolSrcLoc, foundValidTypeSrcLoc;
16827330f729Sjoerg   SmallVector<IdentifierInfo *, 2> unknownTypeArgs;
16837330f729Sjoerg   SmallVector<SourceLocation, 2> unknownTypeArgsLoc;
16847330f729Sjoerg 
16857330f729Sjoerg   for (unsigned i = 0, n = identifiers.size(); i != n; ++i) {
16867330f729Sjoerg     ParsedType typeArg
16877330f729Sjoerg       = Actions.getTypeName(*identifiers[i], identifierLocs[i], getCurScope());
16887330f729Sjoerg     if (typeArg) {
16897330f729Sjoerg       DeclSpec DS(AttrFactory);
16907330f729Sjoerg       const char *prevSpec = nullptr;
16917330f729Sjoerg       unsigned diagID;
16927330f729Sjoerg       DS.SetTypeSpecType(TST_typename, identifierLocs[i], prevSpec, diagID,
16937330f729Sjoerg                          typeArg, Actions.getASTContext().getPrintingPolicy());
16947330f729Sjoerg 
16957330f729Sjoerg       // Form a declarator to turn this into a type.
1696*e038c9c4Sjoerg       Declarator D(DS, DeclaratorContext::TypeName);
16977330f729Sjoerg       TypeResult fullTypeArg = Actions.ActOnTypeName(getCurScope(), D);
16987330f729Sjoerg       if (fullTypeArg.isUsable()) {
16997330f729Sjoerg         typeArgs.push_back(fullTypeArg.get());
17007330f729Sjoerg         if (!foundValidTypeId) {
17017330f729Sjoerg           foundValidTypeId = identifiers[i];
17027330f729Sjoerg           foundValidTypeSrcLoc = identifierLocs[i];
17037330f729Sjoerg         }
17047330f729Sjoerg       } else {
17057330f729Sjoerg         invalid = true;
17067330f729Sjoerg         unknownTypeArgs.push_back(identifiers[i]);
17077330f729Sjoerg         unknownTypeArgsLoc.push_back(identifierLocs[i]);
17087330f729Sjoerg       }
17097330f729Sjoerg     } else {
17107330f729Sjoerg       invalid = true;
17117330f729Sjoerg       if (!Actions.LookupProtocol(identifiers[i], identifierLocs[i])) {
17127330f729Sjoerg         unknownTypeArgs.push_back(identifiers[i]);
17137330f729Sjoerg         unknownTypeArgsLoc.push_back(identifierLocs[i]);
17147330f729Sjoerg       } else if (!foundProtocolId) {
17157330f729Sjoerg         foundProtocolId = identifiers[i];
17167330f729Sjoerg         foundProtocolSrcLoc = identifierLocs[i];
17177330f729Sjoerg       }
17187330f729Sjoerg     }
17197330f729Sjoerg   }
17207330f729Sjoerg 
17217330f729Sjoerg   // Continue parsing type-names.
17227330f729Sjoerg   do {
17237330f729Sjoerg     Token CurTypeTok = Tok;
17247330f729Sjoerg     TypeResult typeArg = ParseTypeName();
17257330f729Sjoerg 
17267330f729Sjoerg     // Consume the '...' for a pack expansion.
17277330f729Sjoerg     SourceLocation ellipsisLoc;
17287330f729Sjoerg     TryConsumeToken(tok::ellipsis, ellipsisLoc);
17297330f729Sjoerg     if (typeArg.isUsable() && ellipsisLoc.isValid()) {
17307330f729Sjoerg       typeArg = Actions.ActOnPackExpansion(typeArg.get(), ellipsisLoc);
17317330f729Sjoerg     }
17327330f729Sjoerg 
17337330f729Sjoerg     if (typeArg.isUsable()) {
17347330f729Sjoerg       typeArgs.push_back(typeArg.get());
17357330f729Sjoerg       if (!foundValidTypeId) {
17367330f729Sjoerg         foundValidTypeId = CurTypeTok.getIdentifierInfo();
17377330f729Sjoerg         foundValidTypeSrcLoc = CurTypeTok.getLocation();
17387330f729Sjoerg       }
17397330f729Sjoerg     } else {
17407330f729Sjoerg       invalid = true;
17417330f729Sjoerg     }
17427330f729Sjoerg   } while (TryConsumeToken(tok::comma));
17437330f729Sjoerg 
17447330f729Sjoerg   // Diagnose the mix between type args and protocols.
17457330f729Sjoerg   if (foundProtocolId && foundValidTypeId)
17467330f729Sjoerg     Actions.DiagnoseTypeArgsAndProtocols(foundProtocolId, foundProtocolSrcLoc,
17477330f729Sjoerg                                          foundValidTypeId,
17487330f729Sjoerg                                          foundValidTypeSrcLoc);
17497330f729Sjoerg 
17507330f729Sjoerg   // Diagnose unknown arg types.
17517330f729Sjoerg   ParsedType T;
17527330f729Sjoerg   if (unknownTypeArgs.size())
17537330f729Sjoerg     for (unsigned i = 0, e = unknownTypeArgsLoc.size(); i < e; ++i)
17547330f729Sjoerg       Actions.DiagnoseUnknownTypeName(unknownTypeArgs[i], unknownTypeArgsLoc[i],
17557330f729Sjoerg                                       getCurScope(), nullptr, T);
17567330f729Sjoerg 
17577330f729Sjoerg   // Parse the closing '>'.
17587330f729Sjoerg   SourceLocation rAngleLoc;
1759*e038c9c4Sjoerg   (void)ParseGreaterThanInTemplateList(lAngleLoc, rAngleLoc, consumeLastToken,
17607330f729Sjoerg                                        /*ObjCGenericList=*/true);
17617330f729Sjoerg 
17627330f729Sjoerg   if (invalid) {
17637330f729Sjoerg     typeArgs.clear();
17647330f729Sjoerg     return;
17657330f729Sjoerg   }
17667330f729Sjoerg 
17677330f729Sjoerg   // Record left/right angle locations.
17687330f729Sjoerg   typeArgsLAngleLoc = lAngleLoc;
17697330f729Sjoerg   typeArgsRAngleLoc = rAngleLoc;
17707330f729Sjoerg }
17717330f729Sjoerg 
parseObjCTypeArgsAndProtocolQualifiers(ParsedType baseType,SourceLocation & typeArgsLAngleLoc,SmallVectorImpl<ParsedType> & typeArgs,SourceLocation & typeArgsRAngleLoc,SourceLocation & protocolLAngleLoc,SmallVectorImpl<Decl * > & protocols,SmallVectorImpl<SourceLocation> & protocolLocs,SourceLocation & protocolRAngleLoc,bool consumeLastToken)17727330f729Sjoerg void Parser::parseObjCTypeArgsAndProtocolQualifiers(
17737330f729Sjoerg        ParsedType baseType,
17747330f729Sjoerg        SourceLocation &typeArgsLAngleLoc,
17757330f729Sjoerg        SmallVectorImpl<ParsedType> &typeArgs,
17767330f729Sjoerg        SourceLocation &typeArgsRAngleLoc,
17777330f729Sjoerg        SourceLocation &protocolLAngleLoc,
17787330f729Sjoerg        SmallVectorImpl<Decl *> &protocols,
17797330f729Sjoerg        SmallVectorImpl<SourceLocation> &protocolLocs,
17807330f729Sjoerg        SourceLocation &protocolRAngleLoc,
17817330f729Sjoerg        bool consumeLastToken) {
17827330f729Sjoerg   assert(Tok.is(tok::less));
17837330f729Sjoerg 
17847330f729Sjoerg   // Parse the first angle-bracket-delimited clause.
17857330f729Sjoerg   parseObjCTypeArgsOrProtocolQualifiers(baseType,
17867330f729Sjoerg                                         typeArgsLAngleLoc,
17877330f729Sjoerg                                         typeArgs,
17887330f729Sjoerg                                         typeArgsRAngleLoc,
17897330f729Sjoerg                                         protocolLAngleLoc,
17907330f729Sjoerg                                         protocols,
17917330f729Sjoerg                                         protocolLocs,
17927330f729Sjoerg                                         protocolRAngleLoc,
17937330f729Sjoerg                                         consumeLastToken,
17947330f729Sjoerg                                         /*warnOnIncompleteProtocols=*/false);
17957330f729Sjoerg   if (Tok.is(tok::eof)) // Nothing else to do here...
17967330f729Sjoerg     return;
17977330f729Sjoerg 
17987330f729Sjoerg   // An Objective-C object pointer followed by type arguments
17997330f729Sjoerg   // can then be followed again by a set of protocol references, e.g.,
18007330f729Sjoerg   // \c NSArray<NSView><NSTextDelegate>
18017330f729Sjoerg   if ((consumeLastToken && Tok.is(tok::less)) ||
18027330f729Sjoerg       (!consumeLastToken && NextToken().is(tok::less))) {
18037330f729Sjoerg     // If we aren't consuming the last token, the prior '>' is still hanging
18047330f729Sjoerg     // there. Consume it before we parse the protocol qualifiers.
18057330f729Sjoerg     if (!consumeLastToken)
18067330f729Sjoerg       ConsumeToken();
18077330f729Sjoerg 
18087330f729Sjoerg     if (!protocols.empty()) {
18097330f729Sjoerg       SkipUntilFlags skipFlags = SkipUntilFlags();
18107330f729Sjoerg       if (!consumeLastToken)
18117330f729Sjoerg         skipFlags = skipFlags | StopBeforeMatch;
18127330f729Sjoerg       Diag(Tok, diag::err_objc_type_args_after_protocols)
18137330f729Sjoerg         << SourceRange(protocolLAngleLoc, protocolRAngleLoc);
18147330f729Sjoerg       SkipUntil(tok::greater, tok::greatergreater, skipFlags);
18157330f729Sjoerg     } else {
18167330f729Sjoerg       ParseObjCProtocolReferences(protocols, protocolLocs,
18177330f729Sjoerg                                   /*WarnOnDeclarations=*/false,
18187330f729Sjoerg                                   /*ForObjCContainer=*/false,
18197330f729Sjoerg                                   protocolLAngleLoc, protocolRAngleLoc,
18207330f729Sjoerg                                   consumeLastToken);
18217330f729Sjoerg     }
18227330f729Sjoerg   }
18237330f729Sjoerg }
18247330f729Sjoerg 
parseObjCTypeArgsAndProtocolQualifiers(SourceLocation loc,ParsedType type,bool consumeLastToken,SourceLocation & endLoc)18257330f729Sjoerg TypeResult Parser::parseObjCTypeArgsAndProtocolQualifiers(
18267330f729Sjoerg              SourceLocation loc,
18277330f729Sjoerg              ParsedType type,
18287330f729Sjoerg              bool consumeLastToken,
18297330f729Sjoerg              SourceLocation &endLoc) {
18307330f729Sjoerg   assert(Tok.is(tok::less));
18317330f729Sjoerg   SourceLocation typeArgsLAngleLoc;
18327330f729Sjoerg   SmallVector<ParsedType, 4> typeArgs;
18337330f729Sjoerg   SourceLocation typeArgsRAngleLoc;
18347330f729Sjoerg   SourceLocation protocolLAngleLoc;
18357330f729Sjoerg   SmallVector<Decl *, 4> protocols;
18367330f729Sjoerg   SmallVector<SourceLocation, 4> protocolLocs;
18377330f729Sjoerg   SourceLocation protocolRAngleLoc;
18387330f729Sjoerg 
18397330f729Sjoerg   // Parse type arguments and protocol qualifiers.
18407330f729Sjoerg   parseObjCTypeArgsAndProtocolQualifiers(type, typeArgsLAngleLoc, typeArgs,
18417330f729Sjoerg                                          typeArgsRAngleLoc, protocolLAngleLoc,
18427330f729Sjoerg                                          protocols, protocolLocs,
18437330f729Sjoerg                                          protocolRAngleLoc, consumeLastToken);
18447330f729Sjoerg 
18457330f729Sjoerg   if (Tok.is(tok::eof))
18467330f729Sjoerg     return true; // Invalid type result.
18477330f729Sjoerg 
18487330f729Sjoerg   // Compute the location of the last token.
18497330f729Sjoerg   if (consumeLastToken)
18507330f729Sjoerg     endLoc = PrevTokLocation;
18517330f729Sjoerg   else
18527330f729Sjoerg     endLoc = Tok.getLocation();
18537330f729Sjoerg 
18547330f729Sjoerg   return Actions.actOnObjCTypeArgsAndProtocolQualifiers(
18557330f729Sjoerg            getCurScope(),
18567330f729Sjoerg            loc,
18577330f729Sjoerg            type,
18587330f729Sjoerg            typeArgsLAngleLoc,
18597330f729Sjoerg            typeArgs,
18607330f729Sjoerg            typeArgsRAngleLoc,
18617330f729Sjoerg            protocolLAngleLoc,
18627330f729Sjoerg            protocols,
18637330f729Sjoerg            protocolLocs,
18647330f729Sjoerg            protocolRAngleLoc);
18657330f729Sjoerg }
18667330f729Sjoerg 
HelperActionsForIvarDeclarations(Decl * interfaceDecl,SourceLocation atLoc,BalancedDelimiterTracker & T,SmallVectorImpl<Decl * > & AllIvarDecls,bool RBraceMissing)18677330f729Sjoerg void Parser::HelperActionsForIvarDeclarations(Decl *interfaceDecl, SourceLocation atLoc,
18687330f729Sjoerg                                  BalancedDelimiterTracker &T,
18697330f729Sjoerg                                  SmallVectorImpl<Decl *> &AllIvarDecls,
18707330f729Sjoerg                                  bool RBraceMissing) {
18717330f729Sjoerg   if (!RBraceMissing)
18727330f729Sjoerg     T.consumeClose();
18737330f729Sjoerg 
18747330f729Sjoerg   Actions.ActOnObjCContainerStartDefinition(interfaceDecl);
18757330f729Sjoerg   Actions.ActOnLastBitfield(T.getCloseLocation(), AllIvarDecls);
18767330f729Sjoerg   Actions.ActOnObjCContainerFinishDefinition();
18777330f729Sjoerg   // Call ActOnFields() even if we don't have any decls. This is useful
18787330f729Sjoerg   // for code rewriting tools that need to be aware of the empty list.
18797330f729Sjoerg   Actions.ActOnFields(getCurScope(), atLoc, interfaceDecl, AllIvarDecls,
18807330f729Sjoerg                       T.getOpenLocation(), T.getCloseLocation(),
18817330f729Sjoerg                       ParsedAttributesView());
18827330f729Sjoerg }
18837330f729Sjoerg 
18847330f729Sjoerg ///   objc-class-instance-variables:
18857330f729Sjoerg ///     '{' objc-instance-variable-decl-list[opt] '}'
18867330f729Sjoerg ///
18877330f729Sjoerg ///   objc-instance-variable-decl-list:
18887330f729Sjoerg ///     objc-visibility-spec
18897330f729Sjoerg ///     objc-instance-variable-decl ';'
18907330f729Sjoerg ///     ';'
18917330f729Sjoerg ///     objc-instance-variable-decl-list objc-visibility-spec
18927330f729Sjoerg ///     objc-instance-variable-decl-list objc-instance-variable-decl ';'
18937330f729Sjoerg ///     objc-instance-variable-decl-list static_assert-declaration
18947330f729Sjoerg ///     objc-instance-variable-decl-list ';'
18957330f729Sjoerg ///
18967330f729Sjoerg ///   objc-visibility-spec:
18977330f729Sjoerg ///     @private
18987330f729Sjoerg ///     @protected
18997330f729Sjoerg ///     @public
19007330f729Sjoerg ///     @package [OBJC2]
19017330f729Sjoerg ///
19027330f729Sjoerg ///   objc-instance-variable-decl:
19037330f729Sjoerg ///     struct-declaration
19047330f729Sjoerg ///
ParseObjCClassInstanceVariables(Decl * interfaceDecl,tok::ObjCKeywordKind visibility,SourceLocation atLoc)19057330f729Sjoerg void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl,
19067330f729Sjoerg                                              tok::ObjCKeywordKind visibility,
19077330f729Sjoerg                                              SourceLocation atLoc) {
19087330f729Sjoerg   assert(Tok.is(tok::l_brace) && "expected {");
19097330f729Sjoerg   SmallVector<Decl *, 32> AllIvarDecls;
19107330f729Sjoerg 
19117330f729Sjoerg   ParseScope ClassScope(this, Scope::DeclScope|Scope::ClassScope);
19127330f729Sjoerg   ObjCDeclContextSwitch ObjCDC(*this);
19137330f729Sjoerg 
19147330f729Sjoerg   BalancedDelimiterTracker T(*this, tok::l_brace);
19157330f729Sjoerg   T.consumeOpen();
19167330f729Sjoerg   // While we still have something to read, read the instance variables.
19177330f729Sjoerg   while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
19187330f729Sjoerg     // Each iteration of this loop reads one objc-instance-variable-decl.
19197330f729Sjoerg 
19207330f729Sjoerg     // Check for extraneous top-level semicolon.
19217330f729Sjoerg     if (Tok.is(tok::semi)) {
19227330f729Sjoerg       ConsumeExtraSemi(InstanceVariableList);
19237330f729Sjoerg       continue;
19247330f729Sjoerg     }
19257330f729Sjoerg 
19267330f729Sjoerg     // Set the default visibility to private.
19277330f729Sjoerg     if (TryConsumeToken(tok::at)) { // parse objc-visibility-spec
19287330f729Sjoerg       if (Tok.is(tok::code_completion)) {
1929*e038c9c4Sjoerg         cutOffParsing();
19307330f729Sjoerg         Actions.CodeCompleteObjCAtVisibility(getCurScope());
1931*e038c9c4Sjoerg         return;
19327330f729Sjoerg       }
19337330f729Sjoerg 
19347330f729Sjoerg       switch (Tok.getObjCKeywordID()) {
19357330f729Sjoerg       case tok::objc_private:
19367330f729Sjoerg       case tok::objc_public:
19377330f729Sjoerg       case tok::objc_protected:
19387330f729Sjoerg       case tok::objc_package:
19397330f729Sjoerg         visibility = Tok.getObjCKeywordID();
19407330f729Sjoerg         ConsumeToken();
19417330f729Sjoerg         continue;
19427330f729Sjoerg 
19437330f729Sjoerg       case tok::objc_end:
19447330f729Sjoerg         Diag(Tok, diag::err_objc_unexpected_atend);
19457330f729Sjoerg         Tok.setLocation(Tok.getLocation().getLocWithOffset(-1));
19467330f729Sjoerg         Tok.setKind(tok::at);
19477330f729Sjoerg         Tok.setLength(1);
19487330f729Sjoerg         PP.EnterToken(Tok, /*IsReinject*/true);
19497330f729Sjoerg         HelperActionsForIvarDeclarations(interfaceDecl, atLoc,
19507330f729Sjoerg                                          T, AllIvarDecls, true);
19517330f729Sjoerg         return;
19527330f729Sjoerg 
19537330f729Sjoerg       default:
19547330f729Sjoerg         Diag(Tok, diag::err_objc_illegal_visibility_spec);
19557330f729Sjoerg         continue;
19567330f729Sjoerg       }
19577330f729Sjoerg     }
19587330f729Sjoerg 
19597330f729Sjoerg     if (Tok.is(tok::code_completion)) {
1960*e038c9c4Sjoerg       cutOffParsing();
19617330f729Sjoerg       Actions.CodeCompleteOrdinaryName(getCurScope(),
19627330f729Sjoerg                                        Sema::PCC_ObjCInstanceVariableList);
1963*e038c9c4Sjoerg       return;
19647330f729Sjoerg     }
19657330f729Sjoerg 
19667330f729Sjoerg     // This needs to duplicate a small amount of code from
19677330f729Sjoerg     // ParseStructUnionBody() for things that should work in both
19687330f729Sjoerg     // C struct and in Objective-C class instance variables.
19697330f729Sjoerg     if (Tok.isOneOf(tok::kw_static_assert, tok::kw__Static_assert)) {
19707330f729Sjoerg       SourceLocation DeclEnd;
19717330f729Sjoerg       ParseStaticAssertDeclaration(DeclEnd);
19727330f729Sjoerg       continue;
19737330f729Sjoerg     }
19747330f729Sjoerg 
19757330f729Sjoerg     auto ObjCIvarCallback = [&](ParsingFieldDeclarator &FD) {
19767330f729Sjoerg       Actions.ActOnObjCContainerStartDefinition(interfaceDecl);
19777330f729Sjoerg       // Install the declarator into the interface decl.
19787330f729Sjoerg       FD.D.setObjCIvar(true);
19797330f729Sjoerg       Decl *Field = Actions.ActOnIvar(
19807330f729Sjoerg           getCurScope(), FD.D.getDeclSpec().getSourceRange().getBegin(), FD.D,
19817330f729Sjoerg           FD.BitfieldSize, visibility);
19827330f729Sjoerg       Actions.ActOnObjCContainerFinishDefinition();
19837330f729Sjoerg       if (Field)
19847330f729Sjoerg         AllIvarDecls.push_back(Field);
19857330f729Sjoerg       FD.complete(Field);
19867330f729Sjoerg     };
19877330f729Sjoerg 
19887330f729Sjoerg     // Parse all the comma separated declarators.
19897330f729Sjoerg     ParsingDeclSpec DS(*this);
19907330f729Sjoerg     ParseStructDeclaration(DS, ObjCIvarCallback);
19917330f729Sjoerg 
19927330f729Sjoerg     if (Tok.is(tok::semi)) {
19937330f729Sjoerg       ConsumeToken();
19947330f729Sjoerg     } else {
19957330f729Sjoerg       Diag(Tok, diag::err_expected_semi_decl_list);
19967330f729Sjoerg       // Skip to end of block or statement
19977330f729Sjoerg       SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
19987330f729Sjoerg     }
19997330f729Sjoerg   }
20007330f729Sjoerg   HelperActionsForIvarDeclarations(interfaceDecl, atLoc,
20017330f729Sjoerg                                    T, AllIvarDecls, false);
20027330f729Sjoerg }
20037330f729Sjoerg 
20047330f729Sjoerg ///   objc-protocol-declaration:
20057330f729Sjoerg ///     objc-protocol-definition
20067330f729Sjoerg ///     objc-protocol-forward-reference
20077330f729Sjoerg ///
20087330f729Sjoerg ///   objc-protocol-definition:
20097330f729Sjoerg ///     \@protocol identifier
20107330f729Sjoerg ///       objc-protocol-refs[opt]
20117330f729Sjoerg ///       objc-interface-decl-list
20127330f729Sjoerg ///     \@end
20137330f729Sjoerg ///
20147330f729Sjoerg ///   objc-protocol-forward-reference:
20157330f729Sjoerg ///     \@protocol identifier-list ';'
20167330f729Sjoerg ///
20177330f729Sjoerg ///   "\@protocol identifier ;" should be resolved as "\@protocol
20187330f729Sjoerg ///   identifier-list ;": objc-interface-decl-list may not start with a
20197330f729Sjoerg ///   semicolon in the first alternative if objc-protocol-refs are omitted.
20207330f729Sjoerg Parser::DeclGroupPtrTy
ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,ParsedAttributes & attrs)20217330f729Sjoerg Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
20227330f729Sjoerg                                        ParsedAttributes &attrs) {
20237330f729Sjoerg   assert(Tok.isObjCAtKeyword(tok::objc_protocol) &&
20247330f729Sjoerg          "ParseObjCAtProtocolDeclaration(): Expected @protocol");
20257330f729Sjoerg   ConsumeToken(); // the "protocol" identifier
20267330f729Sjoerg 
20277330f729Sjoerg   if (Tok.is(tok::code_completion)) {
20287330f729Sjoerg     cutOffParsing();
2029*e038c9c4Sjoerg     Actions.CodeCompleteObjCProtocolDecl(getCurScope());
20307330f729Sjoerg     return nullptr;
20317330f729Sjoerg   }
20327330f729Sjoerg 
20337330f729Sjoerg   MaybeSkipAttributes(tok::objc_protocol);
20347330f729Sjoerg 
20357330f729Sjoerg   if (expectIdentifier())
20367330f729Sjoerg     return nullptr; // missing protocol name.
20377330f729Sjoerg   // Save the protocol name, then consume it.
20387330f729Sjoerg   IdentifierInfo *protocolName = Tok.getIdentifierInfo();
20397330f729Sjoerg   SourceLocation nameLoc = ConsumeToken();
20407330f729Sjoerg 
20417330f729Sjoerg   if (TryConsumeToken(tok::semi)) { // forward declaration of one protocol.
20427330f729Sjoerg     IdentifierLocPair ProtoInfo(protocolName, nameLoc);
20437330f729Sjoerg     return Actions.ActOnForwardProtocolDeclaration(AtLoc, ProtoInfo, attrs);
20447330f729Sjoerg   }
20457330f729Sjoerg 
20467330f729Sjoerg   CheckNestedObjCContexts(AtLoc);
20477330f729Sjoerg 
20487330f729Sjoerg   if (Tok.is(tok::comma)) { // list of forward declarations.
20497330f729Sjoerg     SmallVector<IdentifierLocPair, 8> ProtocolRefs;
20507330f729Sjoerg     ProtocolRefs.push_back(std::make_pair(protocolName, nameLoc));
20517330f729Sjoerg 
20527330f729Sjoerg     // Parse the list of forward declarations.
20537330f729Sjoerg     while (1) {
20547330f729Sjoerg       ConsumeToken(); // the ','
20557330f729Sjoerg       if (expectIdentifier()) {
20567330f729Sjoerg         SkipUntil(tok::semi);
20577330f729Sjoerg         return nullptr;
20587330f729Sjoerg       }
20597330f729Sjoerg       ProtocolRefs.push_back(IdentifierLocPair(Tok.getIdentifierInfo(),
20607330f729Sjoerg                                                Tok.getLocation()));
20617330f729Sjoerg       ConsumeToken(); // the identifier
20627330f729Sjoerg 
20637330f729Sjoerg       if (Tok.isNot(tok::comma))
20647330f729Sjoerg         break;
20657330f729Sjoerg     }
20667330f729Sjoerg     // Consume the ';'.
20677330f729Sjoerg     if (ExpectAndConsume(tok::semi, diag::err_expected_after, "@protocol"))
20687330f729Sjoerg       return nullptr;
20697330f729Sjoerg 
20707330f729Sjoerg     return Actions.ActOnForwardProtocolDeclaration(AtLoc, ProtocolRefs, attrs);
20717330f729Sjoerg   }
20727330f729Sjoerg 
20737330f729Sjoerg   // Last, and definitely not least, parse a protocol declaration.
20747330f729Sjoerg   SourceLocation LAngleLoc, EndProtoLoc;
20757330f729Sjoerg 
20767330f729Sjoerg   SmallVector<Decl *, 8> ProtocolRefs;
20777330f729Sjoerg   SmallVector<SourceLocation, 8> ProtocolLocs;
20787330f729Sjoerg   if (Tok.is(tok::less) &&
20797330f729Sjoerg       ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, false, true,
20807330f729Sjoerg                                   LAngleLoc, EndProtoLoc,
20817330f729Sjoerg                                   /*consumeLastToken=*/true))
20827330f729Sjoerg     return nullptr;
20837330f729Sjoerg 
20847330f729Sjoerg   Decl *ProtoType = Actions.ActOnStartProtocolInterface(
20857330f729Sjoerg       AtLoc, protocolName, nameLoc, ProtocolRefs.data(), ProtocolRefs.size(),
20867330f729Sjoerg       ProtocolLocs.data(), EndProtoLoc, attrs);
20877330f729Sjoerg 
20887330f729Sjoerg   ParseObjCInterfaceDeclList(tok::objc_protocol, ProtoType);
20897330f729Sjoerg   return Actions.ConvertDeclToDeclGroup(ProtoType);
20907330f729Sjoerg }
20917330f729Sjoerg 
20927330f729Sjoerg ///   objc-implementation:
20937330f729Sjoerg ///     objc-class-implementation-prologue
20947330f729Sjoerg ///     objc-category-implementation-prologue
20957330f729Sjoerg ///
20967330f729Sjoerg ///   objc-class-implementation-prologue:
20977330f729Sjoerg ///     @implementation identifier objc-superclass[opt]
20987330f729Sjoerg ///       objc-class-instance-variables[opt]
20997330f729Sjoerg ///
21007330f729Sjoerg ///   objc-category-implementation-prologue:
21017330f729Sjoerg ///     @implementation identifier ( identifier )
21027330f729Sjoerg Parser::DeclGroupPtrTy
ParseObjCAtImplementationDeclaration(SourceLocation AtLoc,ParsedAttributes & Attrs)21037330f729Sjoerg Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc,
21047330f729Sjoerg                                              ParsedAttributes &Attrs) {
21057330f729Sjoerg   assert(Tok.isObjCAtKeyword(tok::objc_implementation) &&
21067330f729Sjoerg          "ParseObjCAtImplementationDeclaration(): Expected @implementation");
21077330f729Sjoerg   CheckNestedObjCContexts(AtLoc);
21087330f729Sjoerg   ConsumeToken(); // the "implementation" identifier
21097330f729Sjoerg 
21107330f729Sjoerg   // Code completion after '@implementation'.
21117330f729Sjoerg   if (Tok.is(tok::code_completion)) {
21127330f729Sjoerg     cutOffParsing();
2113*e038c9c4Sjoerg     Actions.CodeCompleteObjCImplementationDecl(getCurScope());
21147330f729Sjoerg     return nullptr;
21157330f729Sjoerg   }
21167330f729Sjoerg 
21177330f729Sjoerg   MaybeSkipAttributes(tok::objc_implementation);
21187330f729Sjoerg 
21197330f729Sjoerg   if (expectIdentifier())
21207330f729Sjoerg     return nullptr; // missing class or category name.
21217330f729Sjoerg   // We have a class or category name - consume it.
21227330f729Sjoerg   IdentifierInfo *nameId = Tok.getIdentifierInfo();
21237330f729Sjoerg   SourceLocation nameLoc = ConsumeToken(); // consume class or category name
21247330f729Sjoerg   Decl *ObjCImpDecl = nullptr;
21257330f729Sjoerg 
21267330f729Sjoerg   // Neither a type parameter list nor a list of protocol references is
21277330f729Sjoerg   // permitted here. Parse and diagnose them.
21287330f729Sjoerg   if (Tok.is(tok::less)) {
21297330f729Sjoerg     SourceLocation lAngleLoc, rAngleLoc;
21307330f729Sjoerg     SmallVector<IdentifierLocPair, 8> protocolIdents;
21317330f729Sjoerg     SourceLocation diagLoc = Tok.getLocation();
21327330f729Sjoerg     ObjCTypeParamListScope typeParamScope(Actions, getCurScope());
21337330f729Sjoerg     if (parseObjCTypeParamListOrProtocolRefs(typeParamScope, lAngleLoc,
21347330f729Sjoerg                                              protocolIdents, rAngleLoc)) {
21357330f729Sjoerg       Diag(diagLoc, diag::err_objc_parameterized_implementation)
21367330f729Sjoerg         << SourceRange(diagLoc, PrevTokLocation);
21377330f729Sjoerg     } else if (lAngleLoc.isValid()) {
21387330f729Sjoerg       Diag(lAngleLoc, diag::err_unexpected_protocol_qualifier)
21397330f729Sjoerg         << FixItHint::CreateRemoval(SourceRange(lAngleLoc, rAngleLoc));
21407330f729Sjoerg     }
21417330f729Sjoerg   }
21427330f729Sjoerg 
21437330f729Sjoerg   if (Tok.is(tok::l_paren)) {
21447330f729Sjoerg     // we have a category implementation.
21457330f729Sjoerg     ConsumeParen();
21467330f729Sjoerg     SourceLocation categoryLoc, rparenLoc;
21477330f729Sjoerg     IdentifierInfo *categoryId = nullptr;
21487330f729Sjoerg 
21497330f729Sjoerg     if (Tok.is(tok::code_completion)) {
21507330f729Sjoerg       cutOffParsing();
2151*e038c9c4Sjoerg       Actions.CodeCompleteObjCImplementationCategory(getCurScope(), nameId, nameLoc);
21527330f729Sjoerg       return nullptr;
21537330f729Sjoerg     }
21547330f729Sjoerg 
21557330f729Sjoerg     if (Tok.is(tok::identifier)) {
21567330f729Sjoerg       categoryId = Tok.getIdentifierInfo();
21577330f729Sjoerg       categoryLoc = ConsumeToken();
21587330f729Sjoerg     } else {
21597330f729Sjoerg       Diag(Tok, diag::err_expected)
21607330f729Sjoerg           << tok::identifier; // missing category name.
21617330f729Sjoerg       return nullptr;
21627330f729Sjoerg     }
21637330f729Sjoerg     if (Tok.isNot(tok::r_paren)) {
21647330f729Sjoerg       Diag(Tok, diag::err_expected) << tok::r_paren;
21657330f729Sjoerg       SkipUntil(tok::r_paren); // don't stop at ';'
21667330f729Sjoerg       return nullptr;
21677330f729Sjoerg     }
21687330f729Sjoerg     rparenLoc = ConsumeParen();
21697330f729Sjoerg     if (Tok.is(tok::less)) { // we have illegal '<' try to recover
21707330f729Sjoerg       Diag(Tok, diag::err_unexpected_protocol_qualifier);
21717330f729Sjoerg       SourceLocation protocolLAngleLoc, protocolRAngleLoc;
21727330f729Sjoerg       SmallVector<Decl *, 4> protocols;
21737330f729Sjoerg       SmallVector<SourceLocation, 4> protocolLocs;
21747330f729Sjoerg       (void)ParseObjCProtocolReferences(protocols, protocolLocs,
21757330f729Sjoerg                                         /*warnOnIncompleteProtocols=*/false,
21767330f729Sjoerg                                         /*ForObjCContainer=*/false,
21777330f729Sjoerg                                         protocolLAngleLoc, protocolRAngleLoc,
21787330f729Sjoerg                                         /*consumeLastToken=*/true);
21797330f729Sjoerg     }
21807330f729Sjoerg     ObjCImpDecl = Actions.ActOnStartCategoryImplementation(
21817330f729Sjoerg         AtLoc, nameId, nameLoc, categoryId, categoryLoc, Attrs);
21827330f729Sjoerg 
21837330f729Sjoerg   } else {
21847330f729Sjoerg     // We have a class implementation
21857330f729Sjoerg     SourceLocation superClassLoc;
21867330f729Sjoerg     IdentifierInfo *superClassId = nullptr;
21877330f729Sjoerg     if (TryConsumeToken(tok::colon)) {
21887330f729Sjoerg       // We have a super class
21897330f729Sjoerg       if (expectIdentifier())
21907330f729Sjoerg         return nullptr; // missing super class name.
21917330f729Sjoerg       superClassId = Tok.getIdentifierInfo();
21927330f729Sjoerg       superClassLoc = ConsumeToken(); // Consume super class name
21937330f729Sjoerg     }
21947330f729Sjoerg     ObjCImpDecl = Actions.ActOnStartClassImplementation(
21957330f729Sjoerg         AtLoc, nameId, nameLoc, superClassId, superClassLoc, Attrs);
21967330f729Sjoerg 
21977330f729Sjoerg     if (Tok.is(tok::l_brace)) // we have ivars
21987330f729Sjoerg       ParseObjCClassInstanceVariables(ObjCImpDecl, tok::objc_private, AtLoc);
21997330f729Sjoerg     else if (Tok.is(tok::less)) { // we have illegal '<' try to recover
22007330f729Sjoerg       Diag(Tok, diag::err_unexpected_protocol_qualifier);
22017330f729Sjoerg 
22027330f729Sjoerg       SourceLocation protocolLAngleLoc, protocolRAngleLoc;
22037330f729Sjoerg       SmallVector<Decl *, 4> protocols;
22047330f729Sjoerg       SmallVector<SourceLocation, 4> protocolLocs;
22057330f729Sjoerg       (void)ParseObjCProtocolReferences(protocols, protocolLocs,
22067330f729Sjoerg                                         /*warnOnIncompleteProtocols=*/false,
22077330f729Sjoerg                                         /*ForObjCContainer=*/false,
22087330f729Sjoerg                                         protocolLAngleLoc, protocolRAngleLoc,
22097330f729Sjoerg                                         /*consumeLastToken=*/true);
22107330f729Sjoerg     }
22117330f729Sjoerg   }
22127330f729Sjoerg   assert(ObjCImpDecl);
22137330f729Sjoerg 
22147330f729Sjoerg   SmallVector<Decl *, 8> DeclsInGroup;
22157330f729Sjoerg 
22167330f729Sjoerg   {
22177330f729Sjoerg     ObjCImplParsingDataRAII ObjCImplParsing(*this, ObjCImpDecl);
22187330f729Sjoerg     while (!ObjCImplParsing.isFinished() && !isEofOrEom()) {
22197330f729Sjoerg       ParsedAttributesWithRange attrs(AttrFactory);
22207330f729Sjoerg       MaybeParseCXX11Attributes(attrs);
22217330f729Sjoerg       if (DeclGroupPtrTy DGP = ParseExternalDeclaration(attrs)) {
22227330f729Sjoerg         DeclGroupRef DG = DGP.get();
22237330f729Sjoerg         DeclsInGroup.append(DG.begin(), DG.end());
22247330f729Sjoerg       }
22257330f729Sjoerg     }
22267330f729Sjoerg   }
22277330f729Sjoerg 
22287330f729Sjoerg   return Actions.ActOnFinishObjCImplementation(ObjCImpDecl, DeclsInGroup);
22297330f729Sjoerg }
22307330f729Sjoerg 
22317330f729Sjoerg Parser::DeclGroupPtrTy
ParseObjCAtEndDeclaration(SourceRange atEnd)22327330f729Sjoerg Parser::ParseObjCAtEndDeclaration(SourceRange atEnd) {
22337330f729Sjoerg   assert(Tok.isObjCAtKeyword(tok::objc_end) &&
22347330f729Sjoerg          "ParseObjCAtEndDeclaration(): Expected @end");
22357330f729Sjoerg   ConsumeToken(); // the "end" identifier
22367330f729Sjoerg   if (CurParsedObjCImpl)
22377330f729Sjoerg     CurParsedObjCImpl->finish(atEnd);
22387330f729Sjoerg   else
22397330f729Sjoerg     // missing @implementation
22407330f729Sjoerg     Diag(atEnd.getBegin(), diag::err_expected_objc_container);
22417330f729Sjoerg   return nullptr;
22427330f729Sjoerg }
22437330f729Sjoerg 
~ObjCImplParsingDataRAII()22447330f729Sjoerg Parser::ObjCImplParsingDataRAII::~ObjCImplParsingDataRAII() {
22457330f729Sjoerg   if (!Finished) {
22467330f729Sjoerg     finish(P.Tok.getLocation());
22477330f729Sjoerg     if (P.isEofOrEom()) {
22487330f729Sjoerg       P.Diag(P.Tok, diag::err_objc_missing_end)
22497330f729Sjoerg           << FixItHint::CreateInsertion(P.Tok.getLocation(), "\n@end\n");
22507330f729Sjoerg       P.Diag(Dcl->getBeginLoc(), diag::note_objc_container_start)
22517330f729Sjoerg           << Sema::OCK_Implementation;
22527330f729Sjoerg     }
22537330f729Sjoerg   }
22547330f729Sjoerg   P.CurParsedObjCImpl = nullptr;
22557330f729Sjoerg   assert(LateParsedObjCMethods.empty());
22567330f729Sjoerg }
22577330f729Sjoerg 
finish(SourceRange AtEnd)22587330f729Sjoerg void Parser::ObjCImplParsingDataRAII::finish(SourceRange AtEnd) {
22597330f729Sjoerg   assert(!Finished);
22607330f729Sjoerg   P.Actions.DefaultSynthesizeProperties(P.getCurScope(), Dcl, AtEnd.getBegin());
22617330f729Sjoerg   for (size_t i = 0; i < LateParsedObjCMethods.size(); ++i)
22627330f729Sjoerg     P.ParseLexedObjCMethodDefs(*LateParsedObjCMethods[i],
22637330f729Sjoerg                                true/*Methods*/);
22647330f729Sjoerg 
22657330f729Sjoerg   P.Actions.ActOnAtEnd(P.getCurScope(), AtEnd);
22667330f729Sjoerg 
22677330f729Sjoerg   if (HasCFunction)
22687330f729Sjoerg     for (size_t i = 0; i < LateParsedObjCMethods.size(); ++i)
22697330f729Sjoerg       P.ParseLexedObjCMethodDefs(*LateParsedObjCMethods[i],
22707330f729Sjoerg                                  false/*c-functions*/);
22717330f729Sjoerg 
22727330f729Sjoerg   /// Clear and free the cached objc methods.
22737330f729Sjoerg   for (LateParsedObjCMethodContainer::iterator
22747330f729Sjoerg          I = LateParsedObjCMethods.begin(),
22757330f729Sjoerg          E = LateParsedObjCMethods.end(); I != E; ++I)
22767330f729Sjoerg     delete *I;
22777330f729Sjoerg   LateParsedObjCMethods.clear();
22787330f729Sjoerg 
22797330f729Sjoerg   Finished = true;
22807330f729Sjoerg }
22817330f729Sjoerg 
22827330f729Sjoerg ///   compatibility-alias-decl:
22837330f729Sjoerg ///     @compatibility_alias alias-name  class-name ';'
22847330f729Sjoerg ///
ParseObjCAtAliasDeclaration(SourceLocation atLoc)22857330f729Sjoerg Decl *Parser::ParseObjCAtAliasDeclaration(SourceLocation atLoc) {
22867330f729Sjoerg   assert(Tok.isObjCAtKeyword(tok::objc_compatibility_alias) &&
22877330f729Sjoerg          "ParseObjCAtAliasDeclaration(): Expected @compatibility_alias");
22887330f729Sjoerg   ConsumeToken(); // consume compatibility_alias
22897330f729Sjoerg   if (expectIdentifier())
22907330f729Sjoerg     return nullptr;
22917330f729Sjoerg   IdentifierInfo *aliasId = Tok.getIdentifierInfo();
22927330f729Sjoerg   SourceLocation aliasLoc = ConsumeToken(); // consume alias-name
22937330f729Sjoerg   if (expectIdentifier())
22947330f729Sjoerg     return nullptr;
22957330f729Sjoerg   IdentifierInfo *classId = Tok.getIdentifierInfo();
22967330f729Sjoerg   SourceLocation classLoc = ConsumeToken(); // consume class-name;
22977330f729Sjoerg   ExpectAndConsume(tok::semi, diag::err_expected_after, "@compatibility_alias");
22987330f729Sjoerg   return Actions.ActOnCompatibilityAlias(atLoc, aliasId, aliasLoc,
22997330f729Sjoerg                                          classId, classLoc);
23007330f729Sjoerg }
23017330f729Sjoerg 
23027330f729Sjoerg ///   property-synthesis:
23037330f729Sjoerg ///     @synthesize property-ivar-list ';'
23047330f729Sjoerg ///
23057330f729Sjoerg ///   property-ivar-list:
23067330f729Sjoerg ///     property-ivar
23077330f729Sjoerg ///     property-ivar-list ',' property-ivar
23087330f729Sjoerg ///
23097330f729Sjoerg ///   property-ivar:
23107330f729Sjoerg ///     identifier
23117330f729Sjoerg ///     identifier '=' identifier
23127330f729Sjoerg ///
ParseObjCPropertySynthesize(SourceLocation atLoc)23137330f729Sjoerg Decl *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
23147330f729Sjoerg   assert(Tok.isObjCAtKeyword(tok::objc_synthesize) &&
23157330f729Sjoerg          "ParseObjCPropertySynthesize(): Expected '@synthesize'");
23167330f729Sjoerg   ConsumeToken(); // consume synthesize
23177330f729Sjoerg 
23187330f729Sjoerg   while (true) {
23197330f729Sjoerg     if (Tok.is(tok::code_completion)) {
23207330f729Sjoerg       cutOffParsing();
2321*e038c9c4Sjoerg       Actions.CodeCompleteObjCPropertyDefinition(getCurScope());
23227330f729Sjoerg       return nullptr;
23237330f729Sjoerg     }
23247330f729Sjoerg 
23257330f729Sjoerg     if (Tok.isNot(tok::identifier)) {
23267330f729Sjoerg       Diag(Tok, diag::err_synthesized_property_name);
23277330f729Sjoerg       SkipUntil(tok::semi);
23287330f729Sjoerg       return nullptr;
23297330f729Sjoerg     }
23307330f729Sjoerg 
23317330f729Sjoerg     IdentifierInfo *propertyIvar = nullptr;
23327330f729Sjoerg     IdentifierInfo *propertyId = Tok.getIdentifierInfo();
23337330f729Sjoerg     SourceLocation propertyLoc = ConsumeToken(); // consume property name
23347330f729Sjoerg     SourceLocation propertyIvarLoc;
23357330f729Sjoerg     if (TryConsumeToken(tok::equal)) {
23367330f729Sjoerg       // property '=' ivar-name
23377330f729Sjoerg       if (Tok.is(tok::code_completion)) {
23387330f729Sjoerg         cutOffParsing();
2339*e038c9c4Sjoerg         Actions.CodeCompleteObjCPropertySynthesizeIvar(getCurScope(), propertyId);
23407330f729Sjoerg         return nullptr;
23417330f729Sjoerg       }
23427330f729Sjoerg 
23437330f729Sjoerg       if (expectIdentifier())
23447330f729Sjoerg         break;
23457330f729Sjoerg       propertyIvar = Tok.getIdentifierInfo();
23467330f729Sjoerg       propertyIvarLoc = ConsumeToken(); // consume ivar-name
23477330f729Sjoerg     }
23487330f729Sjoerg     Actions.ActOnPropertyImplDecl(
23497330f729Sjoerg         getCurScope(), atLoc, propertyLoc, true,
23507330f729Sjoerg         propertyId, propertyIvar, propertyIvarLoc,
23517330f729Sjoerg         ObjCPropertyQueryKind::OBJC_PR_query_unknown);
23527330f729Sjoerg     if (Tok.isNot(tok::comma))
23537330f729Sjoerg       break;
23547330f729Sjoerg     ConsumeToken(); // consume ','
23557330f729Sjoerg   }
23567330f729Sjoerg   ExpectAndConsume(tok::semi, diag::err_expected_after, "@synthesize");
23577330f729Sjoerg   return nullptr;
23587330f729Sjoerg }
23597330f729Sjoerg 
23607330f729Sjoerg ///   property-dynamic:
23617330f729Sjoerg ///     @dynamic  property-list
23627330f729Sjoerg ///
23637330f729Sjoerg ///   property-list:
23647330f729Sjoerg ///     identifier
23657330f729Sjoerg ///     property-list ',' identifier
23667330f729Sjoerg ///
ParseObjCPropertyDynamic(SourceLocation atLoc)23677330f729Sjoerg Decl *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) {
23687330f729Sjoerg   assert(Tok.isObjCAtKeyword(tok::objc_dynamic) &&
23697330f729Sjoerg          "ParseObjCPropertyDynamic(): Expected '@dynamic'");
23707330f729Sjoerg   ConsumeToken(); // consume dynamic
23717330f729Sjoerg 
23727330f729Sjoerg   bool isClassProperty = false;
23737330f729Sjoerg   if (Tok.is(tok::l_paren)) {
23747330f729Sjoerg     ConsumeParen();
23757330f729Sjoerg     const IdentifierInfo *II = Tok.getIdentifierInfo();
23767330f729Sjoerg 
23777330f729Sjoerg     if (!II) {
23787330f729Sjoerg       Diag(Tok, diag::err_objc_expected_property_attr) << II;
23797330f729Sjoerg       SkipUntil(tok::r_paren, StopAtSemi);
23807330f729Sjoerg     } else {
23817330f729Sjoerg       SourceLocation AttrName = ConsumeToken(); // consume attribute name
23827330f729Sjoerg       if (II->isStr("class")) {
23837330f729Sjoerg         isClassProperty = true;
23847330f729Sjoerg         if (Tok.isNot(tok::r_paren)) {
23857330f729Sjoerg           Diag(Tok, diag::err_expected) << tok::r_paren;
23867330f729Sjoerg           SkipUntil(tok::r_paren, StopAtSemi);
23877330f729Sjoerg         } else
23887330f729Sjoerg           ConsumeParen();
23897330f729Sjoerg       } else {
23907330f729Sjoerg         Diag(AttrName, diag::err_objc_expected_property_attr) << II;
23917330f729Sjoerg         SkipUntil(tok::r_paren, StopAtSemi);
23927330f729Sjoerg       }
23937330f729Sjoerg     }
23947330f729Sjoerg   }
23957330f729Sjoerg 
23967330f729Sjoerg   while (true) {
23977330f729Sjoerg     if (Tok.is(tok::code_completion)) {
23987330f729Sjoerg       cutOffParsing();
2399*e038c9c4Sjoerg       Actions.CodeCompleteObjCPropertyDefinition(getCurScope());
24007330f729Sjoerg       return nullptr;
24017330f729Sjoerg     }
24027330f729Sjoerg 
24037330f729Sjoerg     if (expectIdentifier()) {
24047330f729Sjoerg       SkipUntil(tok::semi);
24057330f729Sjoerg       return nullptr;
24067330f729Sjoerg     }
24077330f729Sjoerg 
24087330f729Sjoerg     IdentifierInfo *propertyId = Tok.getIdentifierInfo();
24097330f729Sjoerg     SourceLocation propertyLoc = ConsumeToken(); // consume property name
24107330f729Sjoerg     Actions.ActOnPropertyImplDecl(
24117330f729Sjoerg         getCurScope(), atLoc, propertyLoc, false,
24127330f729Sjoerg         propertyId, nullptr, SourceLocation(),
24137330f729Sjoerg         isClassProperty ? ObjCPropertyQueryKind::OBJC_PR_query_class :
24147330f729Sjoerg         ObjCPropertyQueryKind::OBJC_PR_query_unknown);
24157330f729Sjoerg 
24167330f729Sjoerg     if (Tok.isNot(tok::comma))
24177330f729Sjoerg       break;
24187330f729Sjoerg     ConsumeToken(); // consume ','
24197330f729Sjoerg   }
24207330f729Sjoerg   ExpectAndConsume(tok::semi, diag::err_expected_after, "@dynamic");
24217330f729Sjoerg   return nullptr;
24227330f729Sjoerg }
24237330f729Sjoerg 
24247330f729Sjoerg ///  objc-throw-statement:
24257330f729Sjoerg ///    throw expression[opt];
24267330f729Sjoerg ///
ParseObjCThrowStmt(SourceLocation atLoc)24277330f729Sjoerg StmtResult Parser::ParseObjCThrowStmt(SourceLocation atLoc) {
24287330f729Sjoerg   ExprResult Res;
24297330f729Sjoerg   ConsumeToken(); // consume throw
24307330f729Sjoerg   if (Tok.isNot(tok::semi)) {
24317330f729Sjoerg     Res = ParseExpression();
24327330f729Sjoerg     if (Res.isInvalid()) {
24337330f729Sjoerg       SkipUntil(tok::semi);
24347330f729Sjoerg       return StmtError();
24357330f729Sjoerg     }
24367330f729Sjoerg   }
24377330f729Sjoerg   // consume ';'
24387330f729Sjoerg   ExpectAndConsume(tok::semi, diag::err_expected_after, "@throw");
24397330f729Sjoerg   return Actions.ActOnObjCAtThrowStmt(atLoc, Res.get(), getCurScope());
24407330f729Sjoerg }
24417330f729Sjoerg 
24427330f729Sjoerg /// objc-synchronized-statement:
24437330f729Sjoerg ///   @synchronized '(' expression ')' compound-statement
24447330f729Sjoerg ///
24457330f729Sjoerg StmtResult
ParseObjCSynchronizedStmt(SourceLocation atLoc)24467330f729Sjoerg Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) {
24477330f729Sjoerg   ConsumeToken(); // consume synchronized
24487330f729Sjoerg   if (Tok.isNot(tok::l_paren)) {
24497330f729Sjoerg     Diag(Tok, diag::err_expected_lparen_after) << "@synchronized";
24507330f729Sjoerg     return StmtError();
24517330f729Sjoerg   }
24527330f729Sjoerg 
24537330f729Sjoerg   // The operand is surrounded with parentheses.
24547330f729Sjoerg   ConsumeParen();  // '('
24557330f729Sjoerg   ExprResult operand(ParseExpression());
24567330f729Sjoerg 
24577330f729Sjoerg   if (Tok.is(tok::r_paren)) {
24587330f729Sjoerg     ConsumeParen();  // ')'
24597330f729Sjoerg   } else {
24607330f729Sjoerg     if (!operand.isInvalid())
24617330f729Sjoerg       Diag(Tok, diag::err_expected) << tok::r_paren;
24627330f729Sjoerg 
24637330f729Sjoerg     // Skip forward until we see a left brace, but don't consume it.
24647330f729Sjoerg     SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch);
24657330f729Sjoerg   }
24667330f729Sjoerg 
24677330f729Sjoerg   // Require a compound statement.
24687330f729Sjoerg   if (Tok.isNot(tok::l_brace)) {
24697330f729Sjoerg     if (!operand.isInvalid())
24707330f729Sjoerg       Diag(Tok, diag::err_expected) << tok::l_brace;
24717330f729Sjoerg     return StmtError();
24727330f729Sjoerg   }
24737330f729Sjoerg 
24747330f729Sjoerg   // Check the @synchronized operand now.
24757330f729Sjoerg   if (!operand.isInvalid())
24767330f729Sjoerg     operand = Actions.ActOnObjCAtSynchronizedOperand(atLoc, operand.get());
24777330f729Sjoerg 
24787330f729Sjoerg   // Parse the compound statement within a new scope.
24797330f729Sjoerg   ParseScope bodyScope(this, Scope::DeclScope | Scope::CompoundStmtScope);
24807330f729Sjoerg   StmtResult body(ParseCompoundStatementBody());
24817330f729Sjoerg   bodyScope.Exit();
24827330f729Sjoerg 
24837330f729Sjoerg   // If there was a semantic or parse error earlier with the
24847330f729Sjoerg   // operand, fail now.
24857330f729Sjoerg   if (operand.isInvalid())
24867330f729Sjoerg     return StmtError();
24877330f729Sjoerg 
24887330f729Sjoerg   if (body.isInvalid())
24897330f729Sjoerg     body = Actions.ActOnNullStmt(Tok.getLocation());
24907330f729Sjoerg 
24917330f729Sjoerg   return Actions.ActOnObjCAtSynchronizedStmt(atLoc, operand.get(), body.get());
24927330f729Sjoerg }
24937330f729Sjoerg 
24947330f729Sjoerg ///  objc-try-catch-statement:
24957330f729Sjoerg ///    @try compound-statement objc-catch-list[opt]
24967330f729Sjoerg ///    @try compound-statement objc-catch-list[opt] @finally compound-statement
24977330f729Sjoerg ///
24987330f729Sjoerg ///  objc-catch-list:
24997330f729Sjoerg ///    @catch ( parameter-declaration ) compound-statement
25007330f729Sjoerg ///    objc-catch-list @catch ( catch-parameter-declaration ) compound-statement
25017330f729Sjoerg ///  catch-parameter-declaration:
25027330f729Sjoerg ///     parameter-declaration
25037330f729Sjoerg ///     '...' [OBJC2]
25047330f729Sjoerg ///
ParseObjCTryStmt(SourceLocation atLoc)25057330f729Sjoerg StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
25067330f729Sjoerg   bool catch_or_finally_seen = false;
25077330f729Sjoerg 
25087330f729Sjoerg   ConsumeToken(); // consume try
25097330f729Sjoerg   if (Tok.isNot(tok::l_brace)) {
25107330f729Sjoerg     Diag(Tok, diag::err_expected) << tok::l_brace;
25117330f729Sjoerg     return StmtError();
25127330f729Sjoerg   }
25137330f729Sjoerg   StmtVector CatchStmts;
25147330f729Sjoerg   StmtResult FinallyStmt;
25157330f729Sjoerg   ParseScope TryScope(this, Scope::DeclScope | Scope::CompoundStmtScope);
25167330f729Sjoerg   StmtResult TryBody(ParseCompoundStatementBody());
25177330f729Sjoerg   TryScope.Exit();
25187330f729Sjoerg   if (TryBody.isInvalid())
25197330f729Sjoerg     TryBody = Actions.ActOnNullStmt(Tok.getLocation());
25207330f729Sjoerg 
25217330f729Sjoerg   while (Tok.is(tok::at)) {
25227330f729Sjoerg     // At this point, we need to lookahead to determine if this @ is the start
25237330f729Sjoerg     // of an @catch or @finally.  We don't want to consume the @ token if this
25247330f729Sjoerg     // is an @try or @encode or something else.
25257330f729Sjoerg     Token AfterAt = GetLookAheadToken(1);
25267330f729Sjoerg     if (!AfterAt.isObjCAtKeyword(tok::objc_catch) &&
25277330f729Sjoerg         !AfterAt.isObjCAtKeyword(tok::objc_finally))
25287330f729Sjoerg       break;
25297330f729Sjoerg 
25307330f729Sjoerg     SourceLocation AtCatchFinallyLoc = ConsumeToken();
25317330f729Sjoerg     if (Tok.isObjCAtKeyword(tok::objc_catch)) {
25327330f729Sjoerg       Decl *FirstPart = nullptr;
25337330f729Sjoerg       ConsumeToken(); // consume catch
25347330f729Sjoerg       if (Tok.is(tok::l_paren)) {
25357330f729Sjoerg         ConsumeParen();
25367330f729Sjoerg         ParseScope CatchScope(this, Scope::DeclScope |
25377330f729Sjoerg                                         Scope::CompoundStmtScope |
25387330f729Sjoerg                                         Scope::AtCatchScope);
25397330f729Sjoerg         if (Tok.isNot(tok::ellipsis)) {
25407330f729Sjoerg           DeclSpec DS(AttrFactory);
25417330f729Sjoerg           ParseDeclarationSpecifiers(DS);
2542*e038c9c4Sjoerg           Declarator ParmDecl(DS, DeclaratorContext::ObjCCatch);
25437330f729Sjoerg           ParseDeclarator(ParmDecl);
25447330f729Sjoerg 
25457330f729Sjoerg           // Inform the actions module about the declarator, so it
25467330f729Sjoerg           // gets added to the current scope.
25477330f729Sjoerg           FirstPart = Actions.ActOnObjCExceptionDecl(getCurScope(), ParmDecl);
25487330f729Sjoerg         } else
25497330f729Sjoerg           ConsumeToken(); // consume '...'
25507330f729Sjoerg 
25517330f729Sjoerg         SourceLocation RParenLoc;
25527330f729Sjoerg 
25537330f729Sjoerg         if (Tok.is(tok::r_paren))
25547330f729Sjoerg           RParenLoc = ConsumeParen();
25557330f729Sjoerg         else // Skip over garbage, until we get to ')'.  Eat the ')'.
25567330f729Sjoerg           SkipUntil(tok::r_paren, StopAtSemi);
25577330f729Sjoerg 
25587330f729Sjoerg         StmtResult CatchBody(true);
25597330f729Sjoerg         if (Tok.is(tok::l_brace))
25607330f729Sjoerg           CatchBody = ParseCompoundStatementBody();
25617330f729Sjoerg         else
25627330f729Sjoerg           Diag(Tok, diag::err_expected) << tok::l_brace;
25637330f729Sjoerg         if (CatchBody.isInvalid())
25647330f729Sjoerg           CatchBody = Actions.ActOnNullStmt(Tok.getLocation());
25657330f729Sjoerg 
25667330f729Sjoerg         StmtResult Catch = Actions.ActOnObjCAtCatchStmt(AtCatchFinallyLoc,
25677330f729Sjoerg                                                               RParenLoc,
25687330f729Sjoerg                                                               FirstPart,
25697330f729Sjoerg                                                               CatchBody.get());
25707330f729Sjoerg         if (!Catch.isInvalid())
25717330f729Sjoerg           CatchStmts.push_back(Catch.get());
25727330f729Sjoerg 
25737330f729Sjoerg       } else {
25747330f729Sjoerg         Diag(AtCatchFinallyLoc, diag::err_expected_lparen_after)
25757330f729Sjoerg           << "@catch clause";
25767330f729Sjoerg         return StmtError();
25777330f729Sjoerg       }
25787330f729Sjoerg       catch_or_finally_seen = true;
25797330f729Sjoerg     } else {
25807330f729Sjoerg       assert(Tok.isObjCAtKeyword(tok::objc_finally) && "Lookahead confused?");
25817330f729Sjoerg       ConsumeToken(); // consume finally
25827330f729Sjoerg       ParseScope FinallyScope(this,
25837330f729Sjoerg                               Scope::DeclScope | Scope::CompoundStmtScope);
25847330f729Sjoerg 
25857330f729Sjoerg       bool ShouldCapture =
25867330f729Sjoerg           getTargetInfo().getTriple().isWindowsMSVCEnvironment();
25877330f729Sjoerg       if (ShouldCapture)
25887330f729Sjoerg         Actions.ActOnCapturedRegionStart(Tok.getLocation(), getCurScope(),
25897330f729Sjoerg                                          CR_ObjCAtFinally, 1);
25907330f729Sjoerg 
25917330f729Sjoerg       StmtResult FinallyBody(true);
25927330f729Sjoerg       if (Tok.is(tok::l_brace))
25937330f729Sjoerg         FinallyBody = ParseCompoundStatementBody();
25947330f729Sjoerg       else
25957330f729Sjoerg         Diag(Tok, diag::err_expected) << tok::l_brace;
25967330f729Sjoerg 
25977330f729Sjoerg       if (FinallyBody.isInvalid()) {
25987330f729Sjoerg         FinallyBody = Actions.ActOnNullStmt(Tok.getLocation());
25997330f729Sjoerg         if (ShouldCapture)
26007330f729Sjoerg           Actions.ActOnCapturedRegionError();
26017330f729Sjoerg       } else if (ShouldCapture) {
26027330f729Sjoerg         FinallyBody = Actions.ActOnCapturedRegionEnd(FinallyBody.get());
26037330f729Sjoerg       }
26047330f729Sjoerg 
26057330f729Sjoerg       FinallyStmt = Actions.ActOnObjCAtFinallyStmt(AtCatchFinallyLoc,
26067330f729Sjoerg                                                    FinallyBody.get());
26077330f729Sjoerg       catch_or_finally_seen = true;
26087330f729Sjoerg       break;
26097330f729Sjoerg     }
26107330f729Sjoerg   }
26117330f729Sjoerg   if (!catch_or_finally_seen) {
26127330f729Sjoerg     Diag(atLoc, diag::err_missing_catch_finally);
26137330f729Sjoerg     return StmtError();
26147330f729Sjoerg   }
26157330f729Sjoerg 
26167330f729Sjoerg   return Actions.ActOnObjCAtTryStmt(atLoc, TryBody.get(),
26177330f729Sjoerg                                     CatchStmts,
26187330f729Sjoerg                                     FinallyStmt.get());
26197330f729Sjoerg }
26207330f729Sjoerg 
26217330f729Sjoerg /// objc-autoreleasepool-statement:
26227330f729Sjoerg ///   @autoreleasepool compound-statement
26237330f729Sjoerg ///
26247330f729Sjoerg StmtResult
ParseObjCAutoreleasePoolStmt(SourceLocation atLoc)26257330f729Sjoerg Parser::ParseObjCAutoreleasePoolStmt(SourceLocation atLoc) {
26267330f729Sjoerg   ConsumeToken(); // consume autoreleasepool
26277330f729Sjoerg   if (Tok.isNot(tok::l_brace)) {
26287330f729Sjoerg     Diag(Tok, diag::err_expected) << tok::l_brace;
26297330f729Sjoerg     return StmtError();
26307330f729Sjoerg   }
26317330f729Sjoerg   // Enter a scope to hold everything within the compound stmt.  Compound
26327330f729Sjoerg   // statements can always hold declarations.
26337330f729Sjoerg   ParseScope BodyScope(this, Scope::DeclScope | Scope::CompoundStmtScope);
26347330f729Sjoerg 
26357330f729Sjoerg   StmtResult AutoreleasePoolBody(ParseCompoundStatementBody());
26367330f729Sjoerg 
26377330f729Sjoerg   BodyScope.Exit();
26387330f729Sjoerg   if (AutoreleasePoolBody.isInvalid())
26397330f729Sjoerg     AutoreleasePoolBody = Actions.ActOnNullStmt(Tok.getLocation());
26407330f729Sjoerg   return Actions.ActOnObjCAutoreleasePoolStmt(atLoc,
26417330f729Sjoerg                                                 AutoreleasePoolBody.get());
26427330f729Sjoerg }
26437330f729Sjoerg 
26447330f729Sjoerg /// StashAwayMethodOrFunctionBodyTokens -  Consume the tokens and store them
26457330f729Sjoerg /// for later parsing.
StashAwayMethodOrFunctionBodyTokens(Decl * MDecl)26467330f729Sjoerg void Parser::StashAwayMethodOrFunctionBodyTokens(Decl *MDecl) {
26477330f729Sjoerg   if (SkipFunctionBodies && (!MDecl || Actions.canSkipFunctionBody(MDecl)) &&
26487330f729Sjoerg       trySkippingFunctionBody()) {
26497330f729Sjoerg     Actions.ActOnSkippedFunctionBody(MDecl);
26507330f729Sjoerg     return;
26517330f729Sjoerg   }
26527330f729Sjoerg 
26537330f729Sjoerg   LexedMethod* LM = new LexedMethod(this, MDecl);
26547330f729Sjoerg   CurParsedObjCImpl->LateParsedObjCMethods.push_back(LM);
26557330f729Sjoerg   CachedTokens &Toks = LM->Toks;
26567330f729Sjoerg   // Begin by storing the '{' or 'try' or ':' token.
26577330f729Sjoerg   Toks.push_back(Tok);
26587330f729Sjoerg   if (Tok.is(tok::kw_try)) {
26597330f729Sjoerg     ConsumeToken();
26607330f729Sjoerg     if (Tok.is(tok::colon)) {
26617330f729Sjoerg       Toks.push_back(Tok);
26627330f729Sjoerg       ConsumeToken();
26637330f729Sjoerg       while (Tok.isNot(tok::l_brace)) {
26647330f729Sjoerg         ConsumeAndStoreUntil(tok::l_paren, Toks, /*StopAtSemi=*/false);
26657330f729Sjoerg         ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/false);
26667330f729Sjoerg       }
26677330f729Sjoerg     }
26687330f729Sjoerg     Toks.push_back(Tok); // also store '{'
26697330f729Sjoerg   }
26707330f729Sjoerg   else if (Tok.is(tok::colon)) {
26717330f729Sjoerg     ConsumeToken();
26727330f729Sjoerg     // FIXME: This is wrong, due to C++11 braced initialization.
26737330f729Sjoerg     while (Tok.isNot(tok::l_brace)) {
26747330f729Sjoerg       ConsumeAndStoreUntil(tok::l_paren, Toks, /*StopAtSemi=*/false);
26757330f729Sjoerg       ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/false);
26767330f729Sjoerg     }
26777330f729Sjoerg     Toks.push_back(Tok); // also store '{'
26787330f729Sjoerg   }
26797330f729Sjoerg   ConsumeBrace();
26807330f729Sjoerg   // Consume everything up to (and including) the matching right brace.
26817330f729Sjoerg   ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false);
26827330f729Sjoerg   while (Tok.is(tok::kw_catch)) {
26837330f729Sjoerg     ConsumeAndStoreUntil(tok::l_brace, Toks, /*StopAtSemi=*/false);
26847330f729Sjoerg     ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false);
26857330f729Sjoerg   }
26867330f729Sjoerg }
26877330f729Sjoerg 
26887330f729Sjoerg ///   objc-method-def: objc-method-proto ';'[opt] '{' body '}'
26897330f729Sjoerg ///
ParseObjCMethodDefinition()26907330f729Sjoerg Decl *Parser::ParseObjCMethodDefinition() {
26917330f729Sjoerg   Decl *MDecl = ParseObjCMethodPrototype();
26927330f729Sjoerg 
26937330f729Sjoerg   PrettyDeclStackTraceEntry CrashInfo(Actions.Context, MDecl, Tok.getLocation(),
26947330f729Sjoerg                                       "parsing Objective-C method");
26957330f729Sjoerg 
26967330f729Sjoerg   // parse optional ';'
26977330f729Sjoerg   if (Tok.is(tok::semi)) {
26987330f729Sjoerg     if (CurParsedObjCImpl) {
26997330f729Sjoerg       Diag(Tok, diag::warn_semicolon_before_method_body)
27007330f729Sjoerg         << FixItHint::CreateRemoval(Tok.getLocation());
27017330f729Sjoerg     }
27027330f729Sjoerg     ConsumeToken();
27037330f729Sjoerg   }
27047330f729Sjoerg 
27057330f729Sjoerg   // We should have an opening brace now.
27067330f729Sjoerg   if (Tok.isNot(tok::l_brace)) {
27077330f729Sjoerg     Diag(Tok, diag::err_expected_method_body);
27087330f729Sjoerg 
27097330f729Sjoerg     // Skip over garbage, until we get to '{'.  Don't eat the '{'.
27107330f729Sjoerg     SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch);
27117330f729Sjoerg 
27127330f729Sjoerg     // If we didn't find the '{', bail out.
27137330f729Sjoerg     if (Tok.isNot(tok::l_brace))
27147330f729Sjoerg       return nullptr;
27157330f729Sjoerg   }
27167330f729Sjoerg 
27177330f729Sjoerg   if (!MDecl) {
27187330f729Sjoerg     ConsumeBrace();
27197330f729Sjoerg     SkipUntil(tok::r_brace);
27207330f729Sjoerg     return nullptr;
27217330f729Sjoerg   }
27227330f729Sjoerg 
27237330f729Sjoerg   // Allow the rest of sema to find private method decl implementations.
27247330f729Sjoerg   Actions.AddAnyMethodToGlobalPool(MDecl);
27257330f729Sjoerg   assert (CurParsedObjCImpl
27267330f729Sjoerg           && "ParseObjCMethodDefinition - Method out of @implementation");
27277330f729Sjoerg   // Consume the tokens and store them for later parsing.
27287330f729Sjoerg   StashAwayMethodOrFunctionBodyTokens(MDecl);
27297330f729Sjoerg   return MDecl;
27307330f729Sjoerg }
27317330f729Sjoerg 
ParseObjCAtStatement(SourceLocation AtLoc,ParsedStmtContext StmtCtx)27327330f729Sjoerg StmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc,
27337330f729Sjoerg                                         ParsedStmtContext StmtCtx) {
27347330f729Sjoerg   if (Tok.is(tok::code_completion)) {
27357330f729Sjoerg     cutOffParsing();
2736*e038c9c4Sjoerg     Actions.CodeCompleteObjCAtStatement(getCurScope());
27377330f729Sjoerg     return StmtError();
27387330f729Sjoerg   }
27397330f729Sjoerg 
27407330f729Sjoerg   if (Tok.isObjCAtKeyword(tok::objc_try))
27417330f729Sjoerg     return ParseObjCTryStmt(AtLoc);
27427330f729Sjoerg 
27437330f729Sjoerg   if (Tok.isObjCAtKeyword(tok::objc_throw))
27447330f729Sjoerg     return ParseObjCThrowStmt(AtLoc);
27457330f729Sjoerg 
27467330f729Sjoerg   if (Tok.isObjCAtKeyword(tok::objc_synchronized))
27477330f729Sjoerg     return ParseObjCSynchronizedStmt(AtLoc);
27487330f729Sjoerg 
27497330f729Sjoerg   if (Tok.isObjCAtKeyword(tok::objc_autoreleasepool))
27507330f729Sjoerg     return ParseObjCAutoreleasePoolStmt(AtLoc);
27517330f729Sjoerg 
27527330f729Sjoerg   if (Tok.isObjCAtKeyword(tok::objc_import) &&
27537330f729Sjoerg       getLangOpts().DebuggerSupport) {
27547330f729Sjoerg     SkipUntil(tok::semi);
27557330f729Sjoerg     return Actions.ActOnNullStmt(Tok.getLocation());
27567330f729Sjoerg   }
27577330f729Sjoerg 
27587330f729Sjoerg   ExprStatementTokLoc = AtLoc;
27597330f729Sjoerg   ExprResult Res(ParseExpressionWithLeadingAt(AtLoc));
27607330f729Sjoerg   if (Res.isInvalid()) {
27617330f729Sjoerg     // If the expression is invalid, skip ahead to the next semicolon. Not
27627330f729Sjoerg     // doing this opens us up to the possibility of infinite loops if
27637330f729Sjoerg     // ParseExpression does not consume any tokens.
27647330f729Sjoerg     SkipUntil(tok::semi);
27657330f729Sjoerg     return StmtError();
27667330f729Sjoerg   }
27677330f729Sjoerg 
27687330f729Sjoerg   // Otherwise, eat the semicolon.
27697330f729Sjoerg   ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
27707330f729Sjoerg   return handleExprStmt(Res, StmtCtx);
27717330f729Sjoerg }
27727330f729Sjoerg 
ParseObjCAtExpression(SourceLocation AtLoc)27737330f729Sjoerg ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
27747330f729Sjoerg   switch (Tok.getKind()) {
27757330f729Sjoerg   case tok::code_completion:
27767330f729Sjoerg     cutOffParsing();
2777*e038c9c4Sjoerg     Actions.CodeCompleteObjCAtExpression(getCurScope());
27787330f729Sjoerg     return ExprError();
27797330f729Sjoerg 
27807330f729Sjoerg   case tok::minus:
27817330f729Sjoerg   case tok::plus: {
27827330f729Sjoerg     tok::TokenKind Kind = Tok.getKind();
27837330f729Sjoerg     SourceLocation OpLoc = ConsumeToken();
27847330f729Sjoerg 
27857330f729Sjoerg     if (!Tok.is(tok::numeric_constant)) {
27867330f729Sjoerg       const char *Symbol = nullptr;
27877330f729Sjoerg       switch (Kind) {
27887330f729Sjoerg       case tok::minus: Symbol = "-"; break;
27897330f729Sjoerg       case tok::plus: Symbol = "+"; break;
27907330f729Sjoerg       default: llvm_unreachable("missing unary operator case");
27917330f729Sjoerg       }
27927330f729Sjoerg       Diag(Tok, diag::err_nsnumber_nonliteral_unary)
27937330f729Sjoerg         << Symbol;
27947330f729Sjoerg       return ExprError();
27957330f729Sjoerg     }
27967330f729Sjoerg 
27977330f729Sjoerg     ExprResult Lit(Actions.ActOnNumericConstant(Tok));
27987330f729Sjoerg     if (Lit.isInvalid()) {
27997330f729Sjoerg       return Lit;
28007330f729Sjoerg     }
28017330f729Sjoerg     ConsumeToken(); // Consume the literal token.
28027330f729Sjoerg 
28037330f729Sjoerg     Lit = Actions.ActOnUnaryOp(getCurScope(), OpLoc, Kind, Lit.get());
28047330f729Sjoerg     if (Lit.isInvalid())
28057330f729Sjoerg       return Lit;
28067330f729Sjoerg 
28077330f729Sjoerg     return ParsePostfixExpressionSuffix(
28087330f729Sjoerg              Actions.BuildObjCNumericLiteral(AtLoc, Lit.get()));
28097330f729Sjoerg   }
28107330f729Sjoerg 
28117330f729Sjoerg   case tok::string_literal:    // primary-expression: string-literal
28127330f729Sjoerg   case tok::wide_string_literal:
28137330f729Sjoerg     return ParsePostfixExpressionSuffix(ParseObjCStringLiteral(AtLoc));
28147330f729Sjoerg 
28157330f729Sjoerg   case tok::char_constant:
28167330f729Sjoerg     return ParsePostfixExpressionSuffix(ParseObjCCharacterLiteral(AtLoc));
28177330f729Sjoerg 
28187330f729Sjoerg   case tok::numeric_constant:
28197330f729Sjoerg     return ParsePostfixExpressionSuffix(ParseObjCNumericLiteral(AtLoc));
28207330f729Sjoerg 
28217330f729Sjoerg   case tok::kw_true:  // Objective-C++, etc.
28227330f729Sjoerg   case tok::kw___objc_yes: // c/c++/objc/objc++ __objc_yes
28237330f729Sjoerg     return ParsePostfixExpressionSuffix(ParseObjCBooleanLiteral(AtLoc, true));
28247330f729Sjoerg   case tok::kw_false: // Objective-C++, etc.
28257330f729Sjoerg   case tok::kw___objc_no: // c/c++/objc/objc++ __objc_no
28267330f729Sjoerg     return ParsePostfixExpressionSuffix(ParseObjCBooleanLiteral(AtLoc, false));
28277330f729Sjoerg 
28287330f729Sjoerg   case tok::l_square:
28297330f729Sjoerg     // Objective-C array literal
28307330f729Sjoerg     return ParsePostfixExpressionSuffix(ParseObjCArrayLiteral(AtLoc));
28317330f729Sjoerg 
28327330f729Sjoerg   case tok::l_brace:
28337330f729Sjoerg     // Objective-C dictionary literal
28347330f729Sjoerg     return ParsePostfixExpressionSuffix(ParseObjCDictionaryLiteral(AtLoc));
28357330f729Sjoerg 
28367330f729Sjoerg   case tok::l_paren:
28377330f729Sjoerg     // Objective-C boxed expression
28387330f729Sjoerg     return ParsePostfixExpressionSuffix(ParseObjCBoxedExpr(AtLoc));
28397330f729Sjoerg 
28407330f729Sjoerg   default:
28417330f729Sjoerg     if (Tok.getIdentifierInfo() == nullptr)
28427330f729Sjoerg       return ExprError(Diag(AtLoc, diag::err_unexpected_at));
28437330f729Sjoerg 
28447330f729Sjoerg     switch (Tok.getIdentifierInfo()->getObjCKeywordID()) {
28457330f729Sjoerg     case tok::objc_encode:
28467330f729Sjoerg       return ParsePostfixExpressionSuffix(ParseObjCEncodeExpression(AtLoc));
28477330f729Sjoerg     case tok::objc_protocol:
28487330f729Sjoerg       return ParsePostfixExpressionSuffix(ParseObjCProtocolExpression(AtLoc));
28497330f729Sjoerg     case tok::objc_selector:
28507330f729Sjoerg       return ParsePostfixExpressionSuffix(ParseObjCSelectorExpression(AtLoc));
28517330f729Sjoerg     case tok::objc_available:
28527330f729Sjoerg       return ParseAvailabilityCheckExpr(AtLoc);
28537330f729Sjoerg       default: {
28547330f729Sjoerg         const char *str = nullptr;
28557330f729Sjoerg         // Only provide the @try/@finally/@autoreleasepool fixit when we're sure
28567330f729Sjoerg         // that this is a proper statement where such directives could actually
28577330f729Sjoerg         // occur.
28587330f729Sjoerg         if (GetLookAheadToken(1).is(tok::l_brace) &&
28597330f729Sjoerg             ExprStatementTokLoc == AtLoc) {
28607330f729Sjoerg           char ch = Tok.getIdentifierInfo()->getNameStart()[0];
28617330f729Sjoerg           str =
28627330f729Sjoerg             ch == 't' ? "try"
28637330f729Sjoerg                       : (ch == 'f' ? "finally"
28647330f729Sjoerg                                    : (ch == 'a' ? "autoreleasepool" : nullptr));
28657330f729Sjoerg         }
28667330f729Sjoerg         if (str) {
28677330f729Sjoerg           SourceLocation kwLoc = Tok.getLocation();
28687330f729Sjoerg           return ExprError(Diag(AtLoc, diag::err_unexpected_at) <<
28697330f729Sjoerg                              FixItHint::CreateReplacement(kwLoc, str));
28707330f729Sjoerg         }
28717330f729Sjoerg         else
28727330f729Sjoerg           return ExprError(Diag(AtLoc, diag::err_unexpected_at));
28737330f729Sjoerg       }
28747330f729Sjoerg     }
28757330f729Sjoerg   }
28767330f729Sjoerg }
28777330f729Sjoerg 
28787330f729Sjoerg /// Parse the receiver of an Objective-C++ message send.
28797330f729Sjoerg ///
28807330f729Sjoerg /// This routine parses the receiver of a message send in
28817330f729Sjoerg /// Objective-C++ either as a type or as an expression. Note that this
28827330f729Sjoerg /// routine must not be called to parse a send to 'super', since it
28837330f729Sjoerg /// has no way to return such a result.
28847330f729Sjoerg ///
28857330f729Sjoerg /// \param IsExpr Whether the receiver was parsed as an expression.
28867330f729Sjoerg ///
28877330f729Sjoerg /// \param TypeOrExpr If the receiver was parsed as an expression (\c
28887330f729Sjoerg /// IsExpr is true), the parsed expression. If the receiver was parsed
28897330f729Sjoerg /// as a type (\c IsExpr is false), the parsed type.
28907330f729Sjoerg ///
28917330f729Sjoerg /// \returns True if an error occurred during parsing or semantic
28927330f729Sjoerg /// analysis, in which case the arguments do not have valid
28937330f729Sjoerg /// values. Otherwise, returns false for a successful parse.
28947330f729Sjoerg ///
28957330f729Sjoerg ///   objc-receiver: [C++]
28967330f729Sjoerg ///     'super' [not parsed here]
28977330f729Sjoerg ///     expression
28987330f729Sjoerg ///     simple-type-specifier
28997330f729Sjoerg ///     typename-specifier
ParseObjCXXMessageReceiver(bool & IsExpr,void * & TypeOrExpr)29007330f729Sjoerg bool Parser::ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr) {
29017330f729Sjoerg   InMessageExpressionRAIIObject InMessage(*this, true);
29027330f729Sjoerg 
29037330f729Sjoerg   if (Tok.isOneOf(tok::identifier, tok::coloncolon, tok::kw_typename,
29047330f729Sjoerg                   tok::annot_cxxscope))
29057330f729Sjoerg     TryAnnotateTypeOrScopeToken();
29067330f729Sjoerg 
29077330f729Sjoerg   if (!Actions.isSimpleTypeSpecifier(Tok.getKind())) {
29087330f729Sjoerg     //   objc-receiver:
29097330f729Sjoerg     //     expression
29107330f729Sjoerg     // Make sure any typos in the receiver are corrected or diagnosed, so that
29117330f729Sjoerg     // proper recovery can happen. FIXME: Perhaps filter the corrected expr to
29127330f729Sjoerg     // only the things that are valid ObjC receivers?
29137330f729Sjoerg     ExprResult Receiver = Actions.CorrectDelayedTyposInExpr(ParseExpression());
29147330f729Sjoerg     if (Receiver.isInvalid())
29157330f729Sjoerg       return true;
29167330f729Sjoerg 
29177330f729Sjoerg     IsExpr = true;
29187330f729Sjoerg     TypeOrExpr = Receiver.get();
29197330f729Sjoerg     return false;
29207330f729Sjoerg   }
29217330f729Sjoerg 
29227330f729Sjoerg   // objc-receiver:
29237330f729Sjoerg   //   typename-specifier
29247330f729Sjoerg   //   simple-type-specifier
29257330f729Sjoerg   //   expression (that starts with one of the above)
29267330f729Sjoerg   DeclSpec DS(AttrFactory);
29277330f729Sjoerg   ParseCXXSimpleTypeSpecifier(DS);
29287330f729Sjoerg 
29297330f729Sjoerg   if (Tok.is(tok::l_paren)) {
29307330f729Sjoerg     // If we see an opening parentheses at this point, we are
29317330f729Sjoerg     // actually parsing an expression that starts with a
29327330f729Sjoerg     // function-style cast, e.g.,
29337330f729Sjoerg     //
29347330f729Sjoerg     //   postfix-expression:
29357330f729Sjoerg     //     simple-type-specifier ( expression-list [opt] )
29367330f729Sjoerg     //     typename-specifier ( expression-list [opt] )
29377330f729Sjoerg     //
29387330f729Sjoerg     // Parse the remainder of this case, then the (optional)
29397330f729Sjoerg     // postfix-expression suffix, followed by the (optional)
29407330f729Sjoerg     // right-hand side of the binary expression. We have an
29417330f729Sjoerg     // instance method.
29427330f729Sjoerg     ExprResult Receiver = ParseCXXTypeConstructExpression(DS);
29437330f729Sjoerg     if (!Receiver.isInvalid())
29447330f729Sjoerg       Receiver = ParsePostfixExpressionSuffix(Receiver.get());
29457330f729Sjoerg     if (!Receiver.isInvalid())
29467330f729Sjoerg       Receiver = ParseRHSOfBinaryExpression(Receiver.get(), prec::Comma);
29477330f729Sjoerg     if (Receiver.isInvalid())
29487330f729Sjoerg       return true;
29497330f729Sjoerg 
29507330f729Sjoerg     IsExpr = true;
29517330f729Sjoerg     TypeOrExpr = Receiver.get();
29527330f729Sjoerg     return false;
29537330f729Sjoerg   }
29547330f729Sjoerg 
29557330f729Sjoerg   // We have a class message. Turn the simple-type-specifier or
29567330f729Sjoerg   // typename-specifier we parsed into a type and parse the
29577330f729Sjoerg   // remainder of the class message.
2958*e038c9c4Sjoerg   Declarator DeclaratorInfo(DS, DeclaratorContext::TypeName);
29597330f729Sjoerg   TypeResult Type = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
29607330f729Sjoerg   if (Type.isInvalid())
29617330f729Sjoerg     return true;
29627330f729Sjoerg 
29637330f729Sjoerg   IsExpr = false;
29647330f729Sjoerg   TypeOrExpr = Type.get().getAsOpaquePtr();
29657330f729Sjoerg   return false;
29667330f729Sjoerg }
29677330f729Sjoerg 
29687330f729Sjoerg /// Determine whether the parser is currently referring to a an
29697330f729Sjoerg /// Objective-C message send, using a simplified heuristic to avoid overhead.
29707330f729Sjoerg ///
29717330f729Sjoerg /// This routine will only return true for a subset of valid message-send
29727330f729Sjoerg /// expressions.
isSimpleObjCMessageExpression()29737330f729Sjoerg bool Parser::isSimpleObjCMessageExpression() {
29747330f729Sjoerg   assert(Tok.is(tok::l_square) && getLangOpts().ObjC &&
29757330f729Sjoerg          "Incorrect start for isSimpleObjCMessageExpression");
29767330f729Sjoerg   return GetLookAheadToken(1).is(tok::identifier) &&
29777330f729Sjoerg          GetLookAheadToken(2).is(tok::identifier);
29787330f729Sjoerg }
29797330f729Sjoerg 
isStartOfObjCClassMessageMissingOpenBracket()29807330f729Sjoerg bool Parser::isStartOfObjCClassMessageMissingOpenBracket() {
29817330f729Sjoerg   if (!getLangOpts().ObjC || !NextToken().is(tok::identifier) ||
29827330f729Sjoerg       InMessageExpression)
29837330f729Sjoerg     return false;
29847330f729Sjoerg 
2985*e038c9c4Sjoerg   TypeResult Type;
29867330f729Sjoerg 
29877330f729Sjoerg   if (Tok.is(tok::annot_typename))
29887330f729Sjoerg     Type = getTypeAnnotation(Tok);
29897330f729Sjoerg   else if (Tok.is(tok::identifier))
29907330f729Sjoerg     Type = Actions.getTypeName(*Tok.getIdentifierInfo(), Tok.getLocation(),
29917330f729Sjoerg                                getCurScope());
29927330f729Sjoerg   else
29937330f729Sjoerg     return false;
29947330f729Sjoerg 
2995*e038c9c4Sjoerg   // FIXME: Should not be querying properties of types from the parser.
2996*e038c9c4Sjoerg   if (Type.isUsable() && Type.get().get()->isObjCObjectOrInterfaceType()) {
29977330f729Sjoerg     const Token &AfterNext = GetLookAheadToken(2);
29987330f729Sjoerg     if (AfterNext.isOneOf(tok::colon, tok::r_square)) {
29997330f729Sjoerg       if (Tok.is(tok::identifier))
30007330f729Sjoerg         TryAnnotateTypeOrScopeToken();
30017330f729Sjoerg 
30027330f729Sjoerg       return Tok.is(tok::annot_typename);
30037330f729Sjoerg     }
30047330f729Sjoerg   }
30057330f729Sjoerg 
30067330f729Sjoerg   return false;
30077330f729Sjoerg }
30087330f729Sjoerg 
30097330f729Sjoerg ///   objc-message-expr:
30107330f729Sjoerg ///     '[' objc-receiver objc-message-args ']'
30117330f729Sjoerg ///
30127330f729Sjoerg ///   objc-receiver: [C]
30137330f729Sjoerg ///     'super'
30147330f729Sjoerg ///     expression
30157330f729Sjoerg ///     class-name
30167330f729Sjoerg ///     type-name
30177330f729Sjoerg ///
ParseObjCMessageExpression()30187330f729Sjoerg ExprResult Parser::ParseObjCMessageExpression() {
30197330f729Sjoerg   assert(Tok.is(tok::l_square) && "'[' expected");
30207330f729Sjoerg   SourceLocation LBracLoc = ConsumeBracket(); // consume '['
30217330f729Sjoerg 
30227330f729Sjoerg   if (Tok.is(tok::code_completion)) {
30237330f729Sjoerg     cutOffParsing();
3024*e038c9c4Sjoerg     Actions.CodeCompleteObjCMessageReceiver(getCurScope());
30257330f729Sjoerg     return ExprError();
30267330f729Sjoerg   }
30277330f729Sjoerg 
30287330f729Sjoerg   InMessageExpressionRAIIObject InMessage(*this, true);
30297330f729Sjoerg 
30307330f729Sjoerg   if (getLangOpts().CPlusPlus) {
30317330f729Sjoerg     // We completely separate the C and C++ cases because C++ requires
30327330f729Sjoerg     // more complicated (read: slower) parsing.
30337330f729Sjoerg 
30347330f729Sjoerg     // Handle send to super.
30357330f729Sjoerg     // FIXME: This doesn't benefit from the same typo-correction we
30367330f729Sjoerg     // get in Objective-C.
30377330f729Sjoerg     if (Tok.is(tok::identifier) && Tok.getIdentifierInfo() == Ident_super &&
30387330f729Sjoerg         NextToken().isNot(tok::period) && getCurScope()->isInObjcMethodScope())
30397330f729Sjoerg       return ParseObjCMessageExpressionBody(LBracLoc, ConsumeToken(), nullptr,
30407330f729Sjoerg                                             nullptr);
30417330f729Sjoerg 
30427330f729Sjoerg     // Parse the receiver, which is either a type or an expression.
30437330f729Sjoerg     bool IsExpr;
30447330f729Sjoerg     void *TypeOrExpr = nullptr;
30457330f729Sjoerg     if (ParseObjCXXMessageReceiver(IsExpr, TypeOrExpr)) {
30467330f729Sjoerg       SkipUntil(tok::r_square, StopAtSemi);
30477330f729Sjoerg       return ExprError();
30487330f729Sjoerg     }
30497330f729Sjoerg 
30507330f729Sjoerg     if (IsExpr)
30517330f729Sjoerg       return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(), nullptr,
30527330f729Sjoerg                                             static_cast<Expr *>(TypeOrExpr));
30537330f729Sjoerg 
30547330f729Sjoerg     return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(),
30557330f729Sjoerg                               ParsedType::getFromOpaquePtr(TypeOrExpr),
30567330f729Sjoerg                                           nullptr);
30577330f729Sjoerg   }
30587330f729Sjoerg 
30597330f729Sjoerg   if (Tok.is(tok::identifier)) {
30607330f729Sjoerg     IdentifierInfo *Name = Tok.getIdentifierInfo();
30617330f729Sjoerg     SourceLocation NameLoc = Tok.getLocation();
30627330f729Sjoerg     ParsedType ReceiverType;
30637330f729Sjoerg     switch (Actions.getObjCMessageKind(getCurScope(), Name, NameLoc,
30647330f729Sjoerg                                        Name == Ident_super,
30657330f729Sjoerg                                        NextToken().is(tok::period),
30667330f729Sjoerg                                        ReceiverType)) {
30677330f729Sjoerg     case Sema::ObjCSuperMessage:
30687330f729Sjoerg       return ParseObjCMessageExpressionBody(LBracLoc, ConsumeToken(), nullptr,
30697330f729Sjoerg                                             nullptr);
30707330f729Sjoerg 
30717330f729Sjoerg     case Sema::ObjCClassMessage:
30727330f729Sjoerg       if (!ReceiverType) {
30737330f729Sjoerg         SkipUntil(tok::r_square, StopAtSemi);
30747330f729Sjoerg         return ExprError();
30757330f729Sjoerg       }
30767330f729Sjoerg 
30777330f729Sjoerg       ConsumeToken(); // the type name
30787330f729Sjoerg 
30797330f729Sjoerg       // Parse type arguments and protocol qualifiers.
30807330f729Sjoerg       if (Tok.is(tok::less)) {
30817330f729Sjoerg         SourceLocation NewEndLoc;
30827330f729Sjoerg         TypeResult NewReceiverType
30837330f729Sjoerg           = parseObjCTypeArgsAndProtocolQualifiers(NameLoc, ReceiverType,
30847330f729Sjoerg                                                    /*consumeLastToken=*/true,
30857330f729Sjoerg                                                    NewEndLoc);
30867330f729Sjoerg         if (!NewReceiverType.isUsable()) {
30877330f729Sjoerg           SkipUntil(tok::r_square, StopAtSemi);
30887330f729Sjoerg           return ExprError();
30897330f729Sjoerg         }
30907330f729Sjoerg 
30917330f729Sjoerg         ReceiverType = NewReceiverType.get();
30927330f729Sjoerg       }
30937330f729Sjoerg 
30947330f729Sjoerg       return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(),
30957330f729Sjoerg                                             ReceiverType, nullptr);
30967330f729Sjoerg 
30977330f729Sjoerg     case Sema::ObjCInstanceMessage:
30987330f729Sjoerg       // Fall through to parse an expression.
30997330f729Sjoerg       break;
31007330f729Sjoerg     }
31017330f729Sjoerg   }
31027330f729Sjoerg 
31037330f729Sjoerg   // Otherwise, an arbitrary expression can be the receiver of a send.
31047330f729Sjoerg   ExprResult Res = Actions.CorrectDelayedTyposInExpr(ParseExpression());
31057330f729Sjoerg   if (Res.isInvalid()) {
31067330f729Sjoerg     SkipUntil(tok::r_square, StopAtSemi);
31077330f729Sjoerg     return Res;
31087330f729Sjoerg   }
31097330f729Sjoerg 
31107330f729Sjoerg   return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(), nullptr,
31117330f729Sjoerg                                         Res.get());
31127330f729Sjoerg }
31137330f729Sjoerg 
31147330f729Sjoerg /// Parse the remainder of an Objective-C message following the
31157330f729Sjoerg /// '[' objc-receiver.
31167330f729Sjoerg ///
31177330f729Sjoerg /// This routine handles sends to super, class messages (sent to a
31187330f729Sjoerg /// class name), and instance messages (sent to an object), and the
31197330f729Sjoerg /// target is represented by \p SuperLoc, \p ReceiverType, or \p
31207330f729Sjoerg /// ReceiverExpr, respectively. Only one of these parameters may have
31217330f729Sjoerg /// a valid value.
31227330f729Sjoerg ///
31237330f729Sjoerg /// \param LBracLoc The location of the opening '['.
31247330f729Sjoerg ///
31257330f729Sjoerg /// \param SuperLoc If this is a send to 'super', the location of the
31267330f729Sjoerg /// 'super' keyword that indicates a send to the superclass.
31277330f729Sjoerg ///
31287330f729Sjoerg /// \param ReceiverType If this is a class message, the type of the
31297330f729Sjoerg /// class we are sending a message to.
31307330f729Sjoerg ///
31317330f729Sjoerg /// \param ReceiverExpr If this is an instance message, the expression
31327330f729Sjoerg /// used to compute the receiver object.
31337330f729Sjoerg ///
31347330f729Sjoerg ///   objc-message-args:
31357330f729Sjoerg ///     objc-selector
31367330f729Sjoerg ///     objc-keywordarg-list
31377330f729Sjoerg ///
31387330f729Sjoerg ///   objc-keywordarg-list:
31397330f729Sjoerg ///     objc-keywordarg
31407330f729Sjoerg ///     objc-keywordarg-list objc-keywordarg
31417330f729Sjoerg ///
31427330f729Sjoerg ///   objc-keywordarg:
31437330f729Sjoerg ///     selector-name[opt] ':' objc-keywordexpr
31447330f729Sjoerg ///
31457330f729Sjoerg ///   objc-keywordexpr:
31467330f729Sjoerg ///     nonempty-expr-list
31477330f729Sjoerg ///
31487330f729Sjoerg ///   nonempty-expr-list:
31497330f729Sjoerg ///     assignment-expression
31507330f729Sjoerg ///     nonempty-expr-list , assignment-expression
31517330f729Sjoerg ///
31527330f729Sjoerg ExprResult
ParseObjCMessageExpressionBody(SourceLocation LBracLoc,SourceLocation SuperLoc,ParsedType ReceiverType,Expr * ReceiverExpr)31537330f729Sjoerg Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
31547330f729Sjoerg                                        SourceLocation SuperLoc,
31557330f729Sjoerg                                        ParsedType ReceiverType,
31567330f729Sjoerg                                        Expr *ReceiverExpr) {
31577330f729Sjoerg   InMessageExpressionRAIIObject InMessage(*this, true);
31587330f729Sjoerg 
31597330f729Sjoerg   if (Tok.is(tok::code_completion)) {
3160*e038c9c4Sjoerg     cutOffParsing();
31617330f729Sjoerg     if (SuperLoc.isValid())
31627330f729Sjoerg       Actions.CodeCompleteObjCSuperMessage(getCurScope(), SuperLoc, None,
31637330f729Sjoerg                                            false);
31647330f729Sjoerg     else if (ReceiverType)
31657330f729Sjoerg       Actions.CodeCompleteObjCClassMessage(getCurScope(), ReceiverType, None,
31667330f729Sjoerg                                            false);
31677330f729Sjoerg     else
31687330f729Sjoerg       Actions.CodeCompleteObjCInstanceMessage(getCurScope(), ReceiverExpr,
31697330f729Sjoerg                                               None, false);
31707330f729Sjoerg     return ExprError();
31717330f729Sjoerg   }
31727330f729Sjoerg 
31737330f729Sjoerg   // Parse objc-selector
31747330f729Sjoerg   SourceLocation Loc;
31757330f729Sjoerg   IdentifierInfo *selIdent = ParseObjCSelectorPiece(Loc);
31767330f729Sjoerg 
31777330f729Sjoerg   SmallVector<IdentifierInfo *, 12> KeyIdents;
31787330f729Sjoerg   SmallVector<SourceLocation, 12> KeyLocs;
31797330f729Sjoerg   ExprVector KeyExprs;
31807330f729Sjoerg 
31817330f729Sjoerg   if (Tok.is(tok::colon)) {
31827330f729Sjoerg     while (1) {
31837330f729Sjoerg       // Each iteration parses a single keyword argument.
31847330f729Sjoerg       KeyIdents.push_back(selIdent);
31857330f729Sjoerg       KeyLocs.push_back(Loc);
31867330f729Sjoerg 
31877330f729Sjoerg       if (ExpectAndConsume(tok::colon)) {
31887330f729Sjoerg         // We must manually skip to a ']', otherwise the expression skipper will
31897330f729Sjoerg         // stop at the ']' when it skips to the ';'.  We want it to skip beyond
31907330f729Sjoerg         // the enclosing expression.
31917330f729Sjoerg         SkipUntil(tok::r_square, StopAtSemi);
31927330f729Sjoerg         return ExprError();
31937330f729Sjoerg       }
31947330f729Sjoerg 
31957330f729Sjoerg       ///  Parse the expression after ':'
31967330f729Sjoerg 
31977330f729Sjoerg       if (Tok.is(tok::code_completion)) {
3198*e038c9c4Sjoerg         cutOffParsing();
31997330f729Sjoerg         if (SuperLoc.isValid())
32007330f729Sjoerg           Actions.CodeCompleteObjCSuperMessage(getCurScope(), SuperLoc,
32017330f729Sjoerg                                                KeyIdents,
32027330f729Sjoerg                                                /*AtArgumentExpression=*/true);
32037330f729Sjoerg         else if (ReceiverType)
32047330f729Sjoerg           Actions.CodeCompleteObjCClassMessage(getCurScope(), ReceiverType,
32057330f729Sjoerg                                                KeyIdents,
32067330f729Sjoerg                                                /*AtArgumentExpression=*/true);
32077330f729Sjoerg         else
32087330f729Sjoerg           Actions.CodeCompleteObjCInstanceMessage(getCurScope(), ReceiverExpr,
32097330f729Sjoerg                                                   KeyIdents,
32107330f729Sjoerg                                                   /*AtArgumentExpression=*/true);
32117330f729Sjoerg 
32127330f729Sjoerg         return ExprError();
32137330f729Sjoerg       }
32147330f729Sjoerg 
32157330f729Sjoerg       ExprResult Expr;
32167330f729Sjoerg       if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
32177330f729Sjoerg         Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
32187330f729Sjoerg         Expr = ParseBraceInitializer();
32197330f729Sjoerg       } else
32207330f729Sjoerg         Expr = ParseAssignmentExpression();
32217330f729Sjoerg 
32227330f729Sjoerg       ExprResult Res(Expr);
32237330f729Sjoerg       if (Res.isInvalid()) {
32247330f729Sjoerg         // We must manually skip to a ']', otherwise the expression skipper will
32257330f729Sjoerg         // stop at the ']' when it skips to the ';'.  We want it to skip beyond
32267330f729Sjoerg         // the enclosing expression.
32277330f729Sjoerg         SkipUntil(tok::r_square, StopAtSemi);
32287330f729Sjoerg         return Res;
32297330f729Sjoerg       }
32307330f729Sjoerg 
32317330f729Sjoerg       // We have a valid expression.
32327330f729Sjoerg       KeyExprs.push_back(Res.get());
32337330f729Sjoerg 
32347330f729Sjoerg       // Code completion after each argument.
32357330f729Sjoerg       if (Tok.is(tok::code_completion)) {
3236*e038c9c4Sjoerg         cutOffParsing();
32377330f729Sjoerg         if (SuperLoc.isValid())
32387330f729Sjoerg           Actions.CodeCompleteObjCSuperMessage(getCurScope(), SuperLoc,
32397330f729Sjoerg                                                KeyIdents,
32407330f729Sjoerg                                                /*AtArgumentExpression=*/false);
32417330f729Sjoerg         else if (ReceiverType)
32427330f729Sjoerg           Actions.CodeCompleteObjCClassMessage(getCurScope(), ReceiverType,
32437330f729Sjoerg                                                KeyIdents,
32447330f729Sjoerg                                                /*AtArgumentExpression=*/false);
32457330f729Sjoerg         else
32467330f729Sjoerg           Actions.CodeCompleteObjCInstanceMessage(getCurScope(), ReceiverExpr,
32477330f729Sjoerg                                                   KeyIdents,
32487330f729Sjoerg                                                 /*AtArgumentExpression=*/false);
32497330f729Sjoerg         return ExprError();
32507330f729Sjoerg       }
32517330f729Sjoerg 
32527330f729Sjoerg       // Check for another keyword selector.
32537330f729Sjoerg       selIdent = ParseObjCSelectorPiece(Loc);
32547330f729Sjoerg       if (!selIdent && Tok.isNot(tok::colon))
32557330f729Sjoerg         break;
32567330f729Sjoerg       // We have a selector or a colon, continue parsing.
32577330f729Sjoerg     }
32587330f729Sjoerg     // Parse the, optional, argument list, comma separated.
32597330f729Sjoerg     while (Tok.is(tok::comma)) {
32607330f729Sjoerg       SourceLocation commaLoc = ConsumeToken(); // Eat the ','.
32617330f729Sjoerg       ///  Parse the expression after ','
32627330f729Sjoerg       ExprResult Res(ParseAssignmentExpression());
32637330f729Sjoerg       if (Tok.is(tok::colon))
32647330f729Sjoerg         Res = Actions.CorrectDelayedTyposInExpr(Res);
32657330f729Sjoerg       if (Res.isInvalid()) {
32667330f729Sjoerg         if (Tok.is(tok::colon)) {
32677330f729Sjoerg           Diag(commaLoc, diag::note_extra_comma_message_arg) <<
32687330f729Sjoerg             FixItHint::CreateRemoval(commaLoc);
32697330f729Sjoerg         }
32707330f729Sjoerg         // We must manually skip to a ']', otherwise the expression skipper will
32717330f729Sjoerg         // stop at the ']' when it skips to the ';'.  We want it to skip beyond
32727330f729Sjoerg         // the enclosing expression.
32737330f729Sjoerg         SkipUntil(tok::r_square, StopAtSemi);
32747330f729Sjoerg         return Res;
32757330f729Sjoerg       }
32767330f729Sjoerg 
32777330f729Sjoerg       // We have a valid expression.
32787330f729Sjoerg       KeyExprs.push_back(Res.get());
32797330f729Sjoerg     }
32807330f729Sjoerg   } else if (!selIdent) {
32817330f729Sjoerg     Diag(Tok, diag::err_expected) << tok::identifier; // missing selector name.
32827330f729Sjoerg 
32837330f729Sjoerg     // We must manually skip to a ']', otherwise the expression skipper will
32847330f729Sjoerg     // stop at the ']' when it skips to the ';'.  We want it to skip beyond
32857330f729Sjoerg     // the enclosing expression.
32867330f729Sjoerg     SkipUntil(tok::r_square, StopAtSemi);
32877330f729Sjoerg     return ExprError();
32887330f729Sjoerg   }
32897330f729Sjoerg 
32907330f729Sjoerg   if (Tok.isNot(tok::r_square)) {
32917330f729Sjoerg     Diag(Tok, diag::err_expected)
32927330f729Sjoerg         << (Tok.is(tok::identifier) ? tok::colon : tok::r_square);
32937330f729Sjoerg     // We must manually skip to a ']', otherwise the expression skipper will
32947330f729Sjoerg     // stop at the ']' when it skips to the ';'.  We want it to skip beyond
32957330f729Sjoerg     // the enclosing expression.
32967330f729Sjoerg     SkipUntil(tok::r_square, StopAtSemi);
32977330f729Sjoerg     return ExprError();
32987330f729Sjoerg   }
32997330f729Sjoerg 
33007330f729Sjoerg   SourceLocation RBracLoc = ConsumeBracket(); // consume ']'
33017330f729Sjoerg 
33027330f729Sjoerg   unsigned nKeys = KeyIdents.size();
33037330f729Sjoerg   if (nKeys == 0) {
33047330f729Sjoerg     KeyIdents.push_back(selIdent);
33057330f729Sjoerg     KeyLocs.push_back(Loc);
33067330f729Sjoerg   }
33077330f729Sjoerg   Selector Sel = PP.getSelectorTable().getSelector(nKeys, &KeyIdents[0]);
33087330f729Sjoerg 
33097330f729Sjoerg   if (SuperLoc.isValid())
33107330f729Sjoerg     return Actions.ActOnSuperMessage(getCurScope(), SuperLoc, Sel,
33117330f729Sjoerg                                      LBracLoc, KeyLocs, RBracLoc, KeyExprs);
33127330f729Sjoerg   else if (ReceiverType)
33137330f729Sjoerg     return Actions.ActOnClassMessage(getCurScope(), ReceiverType, Sel,
33147330f729Sjoerg                                      LBracLoc, KeyLocs, RBracLoc, KeyExprs);
33157330f729Sjoerg   return Actions.ActOnInstanceMessage(getCurScope(), ReceiverExpr, Sel,
33167330f729Sjoerg                                       LBracLoc, KeyLocs, RBracLoc, KeyExprs);
33177330f729Sjoerg }
33187330f729Sjoerg 
ParseObjCStringLiteral(SourceLocation AtLoc)33197330f729Sjoerg ExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) {
33207330f729Sjoerg   ExprResult Res(ParseStringLiteralExpression());
33217330f729Sjoerg   if (Res.isInvalid()) return Res;
33227330f729Sjoerg 
33237330f729Sjoerg   // @"foo" @"bar" is a valid concatenated string.  Eat any subsequent string
33247330f729Sjoerg   // expressions.  At this point, we know that the only valid thing that starts
33257330f729Sjoerg   // with '@' is an @"".
33267330f729Sjoerg   SmallVector<SourceLocation, 4> AtLocs;
33277330f729Sjoerg   ExprVector AtStrings;
33287330f729Sjoerg   AtLocs.push_back(AtLoc);
33297330f729Sjoerg   AtStrings.push_back(Res.get());
33307330f729Sjoerg 
33317330f729Sjoerg   while (Tok.is(tok::at)) {
33327330f729Sjoerg     AtLocs.push_back(ConsumeToken()); // eat the @.
33337330f729Sjoerg 
33347330f729Sjoerg     // Invalid unless there is a string literal.
33357330f729Sjoerg     if (!isTokenStringLiteral())
33367330f729Sjoerg       return ExprError(Diag(Tok, diag::err_objc_concat_string));
33377330f729Sjoerg 
33387330f729Sjoerg     ExprResult Lit(ParseStringLiteralExpression());
33397330f729Sjoerg     if (Lit.isInvalid())
33407330f729Sjoerg       return Lit;
33417330f729Sjoerg 
33427330f729Sjoerg     AtStrings.push_back(Lit.get());
33437330f729Sjoerg   }
33447330f729Sjoerg 
33457330f729Sjoerg   return Actions.ParseObjCStringLiteral(AtLocs.data(), AtStrings);
33467330f729Sjoerg }
33477330f729Sjoerg 
33487330f729Sjoerg /// ParseObjCBooleanLiteral -
33497330f729Sjoerg /// objc-scalar-literal : '@' boolean-keyword
33507330f729Sjoerg ///                        ;
33517330f729Sjoerg /// boolean-keyword: 'true' | 'false' | '__objc_yes' | '__objc_no'
33527330f729Sjoerg ///                        ;
ParseObjCBooleanLiteral(SourceLocation AtLoc,bool ArgValue)33537330f729Sjoerg ExprResult Parser::ParseObjCBooleanLiteral(SourceLocation AtLoc,
33547330f729Sjoerg                                            bool ArgValue) {
33557330f729Sjoerg   SourceLocation EndLoc = ConsumeToken();             // consume the keyword.
33567330f729Sjoerg   return Actions.ActOnObjCBoolLiteral(AtLoc, EndLoc, ArgValue);
33577330f729Sjoerg }
33587330f729Sjoerg 
33597330f729Sjoerg /// ParseObjCCharacterLiteral -
33607330f729Sjoerg /// objc-scalar-literal : '@' character-literal
33617330f729Sjoerg ///                        ;
ParseObjCCharacterLiteral(SourceLocation AtLoc)33627330f729Sjoerg ExprResult Parser::ParseObjCCharacterLiteral(SourceLocation AtLoc) {
33637330f729Sjoerg   ExprResult Lit(Actions.ActOnCharacterConstant(Tok));
33647330f729Sjoerg   if (Lit.isInvalid()) {
33657330f729Sjoerg     return Lit;
33667330f729Sjoerg   }
33677330f729Sjoerg   ConsumeToken(); // Consume the literal token.
33687330f729Sjoerg   return Actions.BuildObjCNumericLiteral(AtLoc, Lit.get());
33697330f729Sjoerg }
33707330f729Sjoerg 
33717330f729Sjoerg /// ParseObjCNumericLiteral -
33727330f729Sjoerg /// objc-scalar-literal : '@' scalar-literal
33737330f729Sjoerg ///                        ;
33747330f729Sjoerg /// scalar-literal : | numeric-constant			/* any numeric constant. */
33757330f729Sjoerg ///                    ;
ParseObjCNumericLiteral(SourceLocation AtLoc)33767330f729Sjoerg ExprResult Parser::ParseObjCNumericLiteral(SourceLocation AtLoc) {
33777330f729Sjoerg   ExprResult Lit(Actions.ActOnNumericConstant(Tok));
33787330f729Sjoerg   if (Lit.isInvalid()) {
33797330f729Sjoerg     return Lit;
33807330f729Sjoerg   }
33817330f729Sjoerg   ConsumeToken(); // Consume the literal token.
33827330f729Sjoerg   return Actions.BuildObjCNumericLiteral(AtLoc, Lit.get());
33837330f729Sjoerg }
33847330f729Sjoerg 
33857330f729Sjoerg /// ParseObjCBoxedExpr -
33867330f729Sjoerg /// objc-box-expression:
33877330f729Sjoerg ///       @( assignment-expression )
33887330f729Sjoerg ExprResult
ParseObjCBoxedExpr(SourceLocation AtLoc)33897330f729Sjoerg Parser::ParseObjCBoxedExpr(SourceLocation AtLoc) {
33907330f729Sjoerg   if (Tok.isNot(tok::l_paren))
33917330f729Sjoerg     return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@");
33927330f729Sjoerg 
33937330f729Sjoerg   BalancedDelimiterTracker T(*this, tok::l_paren);
33947330f729Sjoerg   T.consumeOpen();
33957330f729Sjoerg   ExprResult ValueExpr(ParseAssignmentExpression());
33967330f729Sjoerg   if (T.consumeClose())
33977330f729Sjoerg     return ExprError();
33987330f729Sjoerg 
33997330f729Sjoerg   if (ValueExpr.isInvalid())
34007330f729Sjoerg     return ExprError();
34017330f729Sjoerg 
34027330f729Sjoerg   // Wrap the sub-expression in a parenthesized expression, to distinguish
34037330f729Sjoerg   // a boxed expression from a literal.
34047330f729Sjoerg   SourceLocation LPLoc = T.getOpenLocation(), RPLoc = T.getCloseLocation();
34057330f729Sjoerg   ValueExpr = Actions.ActOnParenExpr(LPLoc, RPLoc, ValueExpr.get());
34067330f729Sjoerg   return Actions.BuildObjCBoxedExpr(SourceRange(AtLoc, RPLoc),
34077330f729Sjoerg                                     ValueExpr.get());
34087330f729Sjoerg }
34097330f729Sjoerg 
ParseObjCArrayLiteral(SourceLocation AtLoc)34107330f729Sjoerg ExprResult Parser::ParseObjCArrayLiteral(SourceLocation AtLoc) {
34117330f729Sjoerg   ExprVector ElementExprs;                   // array elements.
34127330f729Sjoerg   ConsumeBracket(); // consume the l_square.
34137330f729Sjoerg 
34147330f729Sjoerg   bool HasInvalidEltExpr = false;
34157330f729Sjoerg   while (Tok.isNot(tok::r_square)) {
34167330f729Sjoerg     // Parse list of array element expressions (all must be id types).
34177330f729Sjoerg     ExprResult Res(ParseAssignmentExpression());
34187330f729Sjoerg     if (Res.isInvalid()) {
34197330f729Sjoerg       // We must manually skip to a ']', otherwise the expression skipper will
34207330f729Sjoerg       // stop at the ']' when it skips to the ';'.  We want it to skip beyond
34217330f729Sjoerg       // the enclosing expression.
34227330f729Sjoerg       SkipUntil(tok::r_square, StopAtSemi);
34237330f729Sjoerg       return Res;
34247330f729Sjoerg     }
34257330f729Sjoerg 
34267330f729Sjoerg     Res = Actions.CorrectDelayedTyposInExpr(Res.get());
34277330f729Sjoerg     if (Res.isInvalid())
34287330f729Sjoerg       HasInvalidEltExpr = true;
34297330f729Sjoerg 
34307330f729Sjoerg     // Parse the ellipsis that indicates a pack expansion.
34317330f729Sjoerg     if (Tok.is(tok::ellipsis))
34327330f729Sjoerg       Res = Actions.ActOnPackExpansion(Res.get(), ConsumeToken());
34337330f729Sjoerg     if (Res.isInvalid())
34347330f729Sjoerg       HasInvalidEltExpr = true;
34357330f729Sjoerg 
34367330f729Sjoerg     ElementExprs.push_back(Res.get());
34377330f729Sjoerg 
34387330f729Sjoerg     if (Tok.is(tok::comma))
34397330f729Sjoerg       ConsumeToken(); // Eat the ','.
34407330f729Sjoerg     else if (Tok.isNot(tok::r_square))
34417330f729Sjoerg       return ExprError(Diag(Tok, diag::err_expected_either) << tok::r_square
34427330f729Sjoerg                                                             << tok::comma);
34437330f729Sjoerg   }
34447330f729Sjoerg   SourceLocation EndLoc = ConsumeBracket(); // location of ']'
34457330f729Sjoerg 
34467330f729Sjoerg   if (HasInvalidEltExpr)
34477330f729Sjoerg     return ExprError();
34487330f729Sjoerg 
34497330f729Sjoerg   MultiExprArg Args(ElementExprs);
34507330f729Sjoerg   return Actions.BuildObjCArrayLiteral(SourceRange(AtLoc, EndLoc), Args);
34517330f729Sjoerg }
34527330f729Sjoerg 
ParseObjCDictionaryLiteral(SourceLocation AtLoc)34537330f729Sjoerg ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) {
34547330f729Sjoerg   SmallVector<ObjCDictionaryElement, 4> Elements; // dictionary elements.
34557330f729Sjoerg   ConsumeBrace(); // consume the l_square.
34567330f729Sjoerg   bool HasInvalidEltExpr = false;
34577330f729Sjoerg   while (Tok.isNot(tok::r_brace)) {
34587330f729Sjoerg     // Parse the comma separated key : value expressions.
34597330f729Sjoerg     ExprResult KeyExpr;
34607330f729Sjoerg     {
34617330f729Sjoerg       ColonProtectionRAIIObject X(*this);
34627330f729Sjoerg       KeyExpr = ParseAssignmentExpression();
34637330f729Sjoerg       if (KeyExpr.isInvalid()) {
34647330f729Sjoerg         // We must manually skip to a '}', otherwise the expression skipper will
34657330f729Sjoerg         // stop at the '}' when it skips to the ';'.  We want it to skip beyond
34667330f729Sjoerg         // the enclosing expression.
34677330f729Sjoerg         SkipUntil(tok::r_brace, StopAtSemi);
34687330f729Sjoerg         return KeyExpr;
34697330f729Sjoerg       }
34707330f729Sjoerg     }
34717330f729Sjoerg 
34727330f729Sjoerg     if (ExpectAndConsume(tok::colon)) {
34737330f729Sjoerg       SkipUntil(tok::r_brace, StopAtSemi);
34747330f729Sjoerg       return ExprError();
34757330f729Sjoerg     }
34767330f729Sjoerg 
34777330f729Sjoerg     ExprResult ValueExpr(ParseAssignmentExpression());
34787330f729Sjoerg     if (ValueExpr.isInvalid()) {
34797330f729Sjoerg       // We must manually skip to a '}', otherwise the expression skipper will
34807330f729Sjoerg       // stop at the '}' when it skips to the ';'.  We want it to skip beyond
34817330f729Sjoerg       // the enclosing expression.
34827330f729Sjoerg       SkipUntil(tok::r_brace, StopAtSemi);
34837330f729Sjoerg       return ValueExpr;
34847330f729Sjoerg     }
34857330f729Sjoerg 
34867330f729Sjoerg     // Check the key and value for possible typos
34877330f729Sjoerg     KeyExpr = Actions.CorrectDelayedTyposInExpr(KeyExpr.get());
34887330f729Sjoerg     ValueExpr = Actions.CorrectDelayedTyposInExpr(ValueExpr.get());
34897330f729Sjoerg     if (KeyExpr.isInvalid() || ValueExpr.isInvalid())
34907330f729Sjoerg       HasInvalidEltExpr = true;
34917330f729Sjoerg 
34927330f729Sjoerg     // Parse the ellipsis that designates this as a pack expansion. Do not
34937330f729Sjoerg     // ActOnPackExpansion here, leave it to template instantiation time where
34947330f729Sjoerg     // we can get better diagnostics.
34957330f729Sjoerg     SourceLocation EllipsisLoc;
34967330f729Sjoerg     if (getLangOpts().CPlusPlus)
34977330f729Sjoerg       TryConsumeToken(tok::ellipsis, EllipsisLoc);
34987330f729Sjoerg 
34997330f729Sjoerg     // We have a valid expression. Collect it in a vector so we can
35007330f729Sjoerg     // build the argument list.
35017330f729Sjoerg     ObjCDictionaryElement Element = {
35027330f729Sjoerg       KeyExpr.get(), ValueExpr.get(), EllipsisLoc, None
35037330f729Sjoerg     };
35047330f729Sjoerg     Elements.push_back(Element);
35057330f729Sjoerg 
35067330f729Sjoerg     if (!TryConsumeToken(tok::comma) && Tok.isNot(tok::r_brace))
35077330f729Sjoerg       return ExprError(Diag(Tok, diag::err_expected_either) << tok::r_brace
35087330f729Sjoerg                                                             << tok::comma);
35097330f729Sjoerg   }
35107330f729Sjoerg   SourceLocation EndLoc = ConsumeBrace();
35117330f729Sjoerg 
35127330f729Sjoerg   if (HasInvalidEltExpr)
35137330f729Sjoerg     return ExprError();
35147330f729Sjoerg 
35157330f729Sjoerg   // Create the ObjCDictionaryLiteral.
35167330f729Sjoerg   return Actions.BuildObjCDictionaryLiteral(SourceRange(AtLoc, EndLoc),
35177330f729Sjoerg                                             Elements);
35187330f729Sjoerg }
35197330f729Sjoerg 
35207330f729Sjoerg ///    objc-encode-expression:
35217330f729Sjoerg ///      \@encode ( type-name )
35227330f729Sjoerg ExprResult
ParseObjCEncodeExpression(SourceLocation AtLoc)35237330f729Sjoerg Parser::ParseObjCEncodeExpression(SourceLocation AtLoc) {
35247330f729Sjoerg   assert(Tok.isObjCAtKeyword(tok::objc_encode) && "Not an @encode expression!");
35257330f729Sjoerg 
35267330f729Sjoerg   SourceLocation EncLoc = ConsumeToken();
35277330f729Sjoerg 
35287330f729Sjoerg   if (Tok.isNot(tok::l_paren))
35297330f729Sjoerg     return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@encode");
35307330f729Sjoerg 
35317330f729Sjoerg   BalancedDelimiterTracker T(*this, tok::l_paren);
35327330f729Sjoerg   T.consumeOpen();
35337330f729Sjoerg 
35347330f729Sjoerg   TypeResult Ty = ParseTypeName();
35357330f729Sjoerg 
35367330f729Sjoerg   T.consumeClose();
35377330f729Sjoerg 
35387330f729Sjoerg   if (Ty.isInvalid())
35397330f729Sjoerg     return ExprError();
35407330f729Sjoerg 
35417330f729Sjoerg   return Actions.ParseObjCEncodeExpression(AtLoc, EncLoc, T.getOpenLocation(),
35427330f729Sjoerg                                            Ty.get(), T.getCloseLocation());
35437330f729Sjoerg }
35447330f729Sjoerg 
35457330f729Sjoerg ///     objc-protocol-expression
35467330f729Sjoerg ///       \@protocol ( protocol-name )
35477330f729Sjoerg ExprResult
ParseObjCProtocolExpression(SourceLocation AtLoc)35487330f729Sjoerg Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) {
35497330f729Sjoerg   SourceLocation ProtoLoc = ConsumeToken();
35507330f729Sjoerg 
35517330f729Sjoerg   if (Tok.isNot(tok::l_paren))
35527330f729Sjoerg     return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@protocol");
35537330f729Sjoerg 
35547330f729Sjoerg   BalancedDelimiterTracker T(*this, tok::l_paren);
35557330f729Sjoerg   T.consumeOpen();
35567330f729Sjoerg 
35577330f729Sjoerg   if (expectIdentifier())
35587330f729Sjoerg     return ExprError();
35597330f729Sjoerg 
35607330f729Sjoerg   IdentifierInfo *protocolId = Tok.getIdentifierInfo();
35617330f729Sjoerg   SourceLocation ProtoIdLoc = ConsumeToken();
35627330f729Sjoerg 
35637330f729Sjoerg   T.consumeClose();
35647330f729Sjoerg 
35657330f729Sjoerg   return Actions.ParseObjCProtocolExpression(protocolId, AtLoc, ProtoLoc,
35667330f729Sjoerg                                              T.getOpenLocation(), ProtoIdLoc,
35677330f729Sjoerg                                              T.getCloseLocation());
35687330f729Sjoerg }
35697330f729Sjoerg 
35707330f729Sjoerg ///     objc-selector-expression
35717330f729Sjoerg ///       @selector '(' '('[opt] objc-keyword-selector ')'[opt] ')'
ParseObjCSelectorExpression(SourceLocation AtLoc)35727330f729Sjoerg ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) {
35737330f729Sjoerg   SourceLocation SelectorLoc = ConsumeToken();
35747330f729Sjoerg 
35757330f729Sjoerg   if (Tok.isNot(tok::l_paren))
35767330f729Sjoerg     return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@selector");
35777330f729Sjoerg 
35787330f729Sjoerg   SmallVector<IdentifierInfo *, 12> KeyIdents;
35797330f729Sjoerg   SourceLocation sLoc;
35807330f729Sjoerg 
35817330f729Sjoerg   BalancedDelimiterTracker T(*this, tok::l_paren);
35827330f729Sjoerg   T.consumeOpen();
35837330f729Sjoerg   bool HasOptionalParen = Tok.is(tok::l_paren);
35847330f729Sjoerg   if (HasOptionalParen)
35857330f729Sjoerg     ConsumeParen();
35867330f729Sjoerg 
35877330f729Sjoerg   if (Tok.is(tok::code_completion)) {
35887330f729Sjoerg     cutOffParsing();
3589*e038c9c4Sjoerg     Actions.CodeCompleteObjCSelector(getCurScope(), KeyIdents);
35907330f729Sjoerg     return ExprError();
35917330f729Sjoerg   }
35927330f729Sjoerg 
35937330f729Sjoerg   IdentifierInfo *SelIdent = ParseObjCSelectorPiece(sLoc);
35947330f729Sjoerg   if (!SelIdent &&  // missing selector name.
35957330f729Sjoerg       Tok.isNot(tok::colon) && Tok.isNot(tok::coloncolon))
35967330f729Sjoerg     return ExprError(Diag(Tok, diag::err_expected) << tok::identifier);
35977330f729Sjoerg 
35987330f729Sjoerg   KeyIdents.push_back(SelIdent);
35997330f729Sjoerg 
36007330f729Sjoerg   unsigned nColons = 0;
36017330f729Sjoerg   if (Tok.isNot(tok::r_paren)) {
36027330f729Sjoerg     while (1) {
36037330f729Sjoerg       if (TryConsumeToken(tok::coloncolon)) { // Handle :: in C++.
36047330f729Sjoerg         ++nColons;
36057330f729Sjoerg         KeyIdents.push_back(nullptr);
36067330f729Sjoerg       } else if (ExpectAndConsume(tok::colon)) // Otherwise expect ':'.
36077330f729Sjoerg         return ExprError();
36087330f729Sjoerg       ++nColons;
36097330f729Sjoerg 
36107330f729Sjoerg       if (Tok.is(tok::r_paren))
36117330f729Sjoerg         break;
36127330f729Sjoerg 
36137330f729Sjoerg       if (Tok.is(tok::code_completion)) {
36147330f729Sjoerg         cutOffParsing();
3615*e038c9c4Sjoerg         Actions.CodeCompleteObjCSelector(getCurScope(), KeyIdents);
36167330f729Sjoerg         return ExprError();
36177330f729Sjoerg       }
36187330f729Sjoerg 
36197330f729Sjoerg       // Check for another keyword selector.
36207330f729Sjoerg       SourceLocation Loc;
36217330f729Sjoerg       SelIdent = ParseObjCSelectorPiece(Loc);
36227330f729Sjoerg       KeyIdents.push_back(SelIdent);
36237330f729Sjoerg       if (!SelIdent && Tok.isNot(tok::colon) && Tok.isNot(tok::coloncolon))
36247330f729Sjoerg         break;
36257330f729Sjoerg     }
36267330f729Sjoerg   }
36277330f729Sjoerg   if (HasOptionalParen && Tok.is(tok::r_paren))
36287330f729Sjoerg     ConsumeParen(); // ')'
36297330f729Sjoerg   T.consumeClose();
36307330f729Sjoerg   Selector Sel = PP.getSelectorTable().getSelector(nColons, &KeyIdents[0]);
36317330f729Sjoerg   return Actions.ParseObjCSelectorExpression(Sel, AtLoc, SelectorLoc,
36327330f729Sjoerg                                              T.getOpenLocation(),
36337330f729Sjoerg                                              T.getCloseLocation(),
36347330f729Sjoerg                                              !HasOptionalParen);
36357330f729Sjoerg }
36367330f729Sjoerg 
ParseLexedObjCMethodDefs(LexedMethod & LM,bool parseMethod)36377330f729Sjoerg void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) {
36387330f729Sjoerg   // MCDecl might be null due to error in method or c-function  prototype, etc.
36397330f729Sjoerg   Decl *MCDecl = LM.D;
36407330f729Sjoerg   bool skip = MCDecl &&
36417330f729Sjoerg               ((parseMethod && !Actions.isObjCMethodDecl(MCDecl)) ||
36427330f729Sjoerg               (!parseMethod && Actions.isObjCMethodDecl(MCDecl)));
36437330f729Sjoerg   if (skip)
36447330f729Sjoerg     return;
36457330f729Sjoerg 
36467330f729Sjoerg   // Save the current token position.
36477330f729Sjoerg   SourceLocation OrigLoc = Tok.getLocation();
36487330f729Sjoerg 
36497330f729Sjoerg   assert(!LM.Toks.empty() && "ParseLexedObjCMethodDef - Empty body!");
36507330f729Sjoerg   // Store an artificial EOF token to ensure that we don't run off the end of
36517330f729Sjoerg   // the method's body when we come to parse it.
36527330f729Sjoerg   Token Eof;
36537330f729Sjoerg   Eof.startToken();
36547330f729Sjoerg   Eof.setKind(tok::eof);
36557330f729Sjoerg   Eof.setEofData(MCDecl);
36567330f729Sjoerg   Eof.setLocation(OrigLoc);
36577330f729Sjoerg   LM.Toks.push_back(Eof);
36587330f729Sjoerg   // Append the current token at the end of the new token stream so that it
36597330f729Sjoerg   // doesn't get lost.
36607330f729Sjoerg   LM.Toks.push_back(Tok);
36617330f729Sjoerg   PP.EnterTokenStream(LM.Toks, true, /*IsReinject*/true);
36627330f729Sjoerg 
36637330f729Sjoerg   // Consume the previously pushed token.
36647330f729Sjoerg   ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
36657330f729Sjoerg 
36667330f729Sjoerg   assert(Tok.isOneOf(tok::l_brace, tok::kw_try, tok::colon) &&
36677330f729Sjoerg          "Inline objective-c method not starting with '{' or 'try' or ':'");
36687330f729Sjoerg   // Enter a scope for the method or c-function body.
36697330f729Sjoerg   ParseScope BodyScope(this, (parseMethod ? Scope::ObjCMethodScope : 0) |
36707330f729Sjoerg                                  Scope::FnScope | Scope::DeclScope |
36717330f729Sjoerg                                  Scope::CompoundStmtScope);
36727330f729Sjoerg 
36737330f729Sjoerg   // Tell the actions module that we have entered a method or c-function definition
36747330f729Sjoerg   // with the specified Declarator for the method/function.
36757330f729Sjoerg   if (parseMethod)
36767330f729Sjoerg     Actions.ActOnStartOfObjCMethodDef(getCurScope(), MCDecl);
36777330f729Sjoerg   else
36787330f729Sjoerg     Actions.ActOnStartOfFunctionDef(getCurScope(), MCDecl);
36797330f729Sjoerg   if (Tok.is(tok::kw_try))
36807330f729Sjoerg     ParseFunctionTryBlock(MCDecl, BodyScope);
36817330f729Sjoerg   else {
36827330f729Sjoerg     if (Tok.is(tok::colon))
36837330f729Sjoerg       ParseConstructorInitializer(MCDecl);
36847330f729Sjoerg     else
36857330f729Sjoerg       Actions.ActOnDefaultCtorInitializers(MCDecl);
36867330f729Sjoerg     ParseFunctionStatementBody(MCDecl, BodyScope);
36877330f729Sjoerg   }
36887330f729Sjoerg 
36897330f729Sjoerg   if (Tok.getLocation() != OrigLoc) {
36907330f729Sjoerg     // Due to parsing error, we either went over the cached tokens or
36917330f729Sjoerg     // there are still cached tokens left. If it's the latter case skip the
36927330f729Sjoerg     // leftover tokens.
36937330f729Sjoerg     // Since this is an uncommon situation that should be avoided, use the
36947330f729Sjoerg     // expensive isBeforeInTranslationUnit call.
36957330f729Sjoerg     if (PP.getSourceManager().isBeforeInTranslationUnit(Tok.getLocation(),
36967330f729Sjoerg                                                      OrigLoc))
36977330f729Sjoerg       while (Tok.getLocation() != OrigLoc && Tok.isNot(tok::eof))
36987330f729Sjoerg         ConsumeAnyToken();
36997330f729Sjoerg   }
37007330f729Sjoerg   // Clean up the remaining EOF token.
37017330f729Sjoerg   ConsumeAnyToken();
37027330f729Sjoerg }
3703