1f4a2713aSLionel Sambuc //===--- ParseObjC.cpp - Objective C Parsing ------------------------------===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc //  This file implements the Objective-C portions of the Parser interface.
11f4a2713aSLionel Sambuc //
12f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
13f4a2713aSLionel Sambuc 
14f4a2713aSLionel Sambuc #include "clang/Parse/Parser.h"
15f4a2713aSLionel Sambuc #include "RAIIObjectsForParser.h"
16f4a2713aSLionel Sambuc #include "clang/Basic/CharInfo.h"
17f4a2713aSLionel Sambuc #include "clang/Parse/ParseDiagnostic.h"
18f4a2713aSLionel Sambuc #include "clang/Sema/DeclSpec.h"
19f4a2713aSLionel Sambuc #include "clang/Sema/PrettyDeclStackTrace.h"
20f4a2713aSLionel Sambuc #include "clang/Sema/Scope.h"
21f4a2713aSLionel Sambuc #include "llvm/ADT/SmallVector.h"
22f4a2713aSLionel Sambuc #include "llvm/ADT/StringExtras.h"
23f4a2713aSLionel Sambuc using namespace clang;
24f4a2713aSLionel Sambuc 
25f4a2713aSLionel Sambuc /// Skips attributes after an Objective-C @ directive. Emits a diagnostic.
MaybeSkipAttributes(tok::ObjCKeywordKind Kind)26f4a2713aSLionel Sambuc void Parser::MaybeSkipAttributes(tok::ObjCKeywordKind Kind) {
27f4a2713aSLionel Sambuc   ParsedAttributes attrs(AttrFactory);
28f4a2713aSLionel Sambuc   if (Tok.is(tok::kw___attribute)) {
29f4a2713aSLionel Sambuc     if (Kind == tok::objc_interface || Kind == tok::objc_protocol)
30f4a2713aSLionel Sambuc       Diag(Tok, diag::err_objc_postfix_attribute_hint)
31f4a2713aSLionel Sambuc           << (Kind == tok::objc_protocol);
32f4a2713aSLionel Sambuc     else
33f4a2713aSLionel Sambuc       Diag(Tok, diag::err_objc_postfix_attribute);
34f4a2713aSLionel Sambuc     ParseGNUAttributes(attrs);
35f4a2713aSLionel Sambuc   }
36f4a2713aSLionel Sambuc }
37f4a2713aSLionel Sambuc 
38f4a2713aSLionel Sambuc /// ParseObjCAtDirectives - Handle parts of the external-declaration production:
39f4a2713aSLionel Sambuc ///       external-declaration: [C99 6.9]
40f4a2713aSLionel Sambuc /// [OBJC]  objc-class-definition
41f4a2713aSLionel Sambuc /// [OBJC]  objc-class-declaration
42f4a2713aSLionel Sambuc /// [OBJC]  objc-alias-declaration
43f4a2713aSLionel Sambuc /// [OBJC]  objc-protocol-definition
44f4a2713aSLionel Sambuc /// [OBJC]  objc-method-definition
45f4a2713aSLionel Sambuc /// [OBJC]  '@' 'end'
ParseObjCAtDirectives()46f4a2713aSLionel Sambuc Parser::DeclGroupPtrTy Parser::ParseObjCAtDirectives() {
47f4a2713aSLionel Sambuc   SourceLocation AtLoc = ConsumeToken(); // the "@"
48f4a2713aSLionel Sambuc 
49f4a2713aSLionel Sambuc   if (Tok.is(tok::code_completion)) {
50f4a2713aSLionel Sambuc     Actions.CodeCompleteObjCAtDirective(getCurScope());
51f4a2713aSLionel Sambuc     cutOffParsing();
52f4a2713aSLionel Sambuc     return DeclGroupPtrTy();
53f4a2713aSLionel Sambuc   }
54f4a2713aSLionel Sambuc 
55*0a6a1f1dSLionel Sambuc   Decl *SingleDecl = nullptr;
56f4a2713aSLionel Sambuc   switch (Tok.getObjCKeywordID()) {
57f4a2713aSLionel Sambuc   case tok::objc_class:
58f4a2713aSLionel Sambuc     return ParseObjCAtClassDeclaration(AtLoc);
59f4a2713aSLionel Sambuc   case tok::objc_interface: {
60f4a2713aSLionel Sambuc     ParsedAttributes attrs(AttrFactory);
61f4a2713aSLionel Sambuc     SingleDecl = ParseObjCAtInterfaceDeclaration(AtLoc, attrs);
62f4a2713aSLionel Sambuc     break;
63f4a2713aSLionel Sambuc   }
64f4a2713aSLionel Sambuc   case tok::objc_protocol: {
65f4a2713aSLionel Sambuc     ParsedAttributes attrs(AttrFactory);
66f4a2713aSLionel Sambuc     return ParseObjCAtProtocolDeclaration(AtLoc, attrs);
67f4a2713aSLionel Sambuc   }
68f4a2713aSLionel Sambuc   case tok::objc_implementation:
69f4a2713aSLionel Sambuc     return ParseObjCAtImplementationDeclaration(AtLoc);
70f4a2713aSLionel Sambuc   case tok::objc_end:
71f4a2713aSLionel Sambuc     return ParseObjCAtEndDeclaration(AtLoc);
72f4a2713aSLionel Sambuc   case tok::objc_compatibility_alias:
73f4a2713aSLionel Sambuc     SingleDecl = ParseObjCAtAliasDeclaration(AtLoc);
74f4a2713aSLionel Sambuc     break;
75f4a2713aSLionel Sambuc   case tok::objc_synthesize:
76f4a2713aSLionel Sambuc     SingleDecl = ParseObjCPropertySynthesize(AtLoc);
77f4a2713aSLionel Sambuc     break;
78f4a2713aSLionel Sambuc   case tok::objc_dynamic:
79f4a2713aSLionel Sambuc     SingleDecl = ParseObjCPropertyDynamic(AtLoc);
80f4a2713aSLionel Sambuc     break;
81f4a2713aSLionel Sambuc   case tok::objc_import:
82*0a6a1f1dSLionel Sambuc     if (getLangOpts().Modules || getLangOpts().DebuggerSupport)
83f4a2713aSLionel Sambuc       return ParseModuleImport(AtLoc);
84*0a6a1f1dSLionel Sambuc     Diag(AtLoc, diag::err_atimport);
85*0a6a1f1dSLionel Sambuc     SkipUntil(tok::semi);
86*0a6a1f1dSLionel Sambuc     return Actions.ConvertDeclToDeclGroup(nullptr);
87f4a2713aSLionel Sambuc   default:
88f4a2713aSLionel Sambuc     Diag(AtLoc, diag::err_unexpected_at);
89f4a2713aSLionel Sambuc     SkipUntil(tok::semi);
90*0a6a1f1dSLionel Sambuc     SingleDecl = nullptr;
91f4a2713aSLionel Sambuc     break;
92f4a2713aSLionel Sambuc   }
93f4a2713aSLionel Sambuc   return Actions.ConvertDeclToDeclGroup(SingleDecl);
94f4a2713aSLionel Sambuc }
95f4a2713aSLionel Sambuc 
96f4a2713aSLionel Sambuc ///
97f4a2713aSLionel Sambuc /// objc-class-declaration:
98f4a2713aSLionel Sambuc ///    '@' 'class' identifier-list ';'
99f4a2713aSLionel Sambuc ///
100f4a2713aSLionel Sambuc Parser::DeclGroupPtrTy
ParseObjCAtClassDeclaration(SourceLocation atLoc)101f4a2713aSLionel Sambuc Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
102f4a2713aSLionel Sambuc   ConsumeToken(); // the identifier "class"
103f4a2713aSLionel Sambuc   SmallVector<IdentifierInfo *, 8> ClassNames;
104f4a2713aSLionel Sambuc   SmallVector<SourceLocation, 8> ClassLocs;
105f4a2713aSLionel Sambuc 
106f4a2713aSLionel Sambuc 
107f4a2713aSLionel Sambuc   while (1) {
108f4a2713aSLionel Sambuc     MaybeSkipAttributes(tok::objc_class);
109f4a2713aSLionel Sambuc     if (Tok.isNot(tok::identifier)) {
110*0a6a1f1dSLionel Sambuc       Diag(Tok, diag::err_expected) << tok::identifier;
111f4a2713aSLionel Sambuc       SkipUntil(tok::semi);
112*0a6a1f1dSLionel Sambuc       return Actions.ConvertDeclToDeclGroup(nullptr);
113f4a2713aSLionel Sambuc     }
114f4a2713aSLionel Sambuc     ClassNames.push_back(Tok.getIdentifierInfo());
115f4a2713aSLionel Sambuc     ClassLocs.push_back(Tok.getLocation());
116f4a2713aSLionel Sambuc     ConsumeToken();
117f4a2713aSLionel Sambuc 
118*0a6a1f1dSLionel Sambuc     if (!TryConsumeToken(tok::comma))
119f4a2713aSLionel Sambuc       break;
120f4a2713aSLionel Sambuc   }
121f4a2713aSLionel Sambuc 
122f4a2713aSLionel Sambuc   // Consume the ';'.
123*0a6a1f1dSLionel Sambuc   if (ExpectAndConsume(tok::semi, diag::err_expected_after, "@class"))
124*0a6a1f1dSLionel Sambuc     return Actions.ConvertDeclToDeclGroup(nullptr);
125f4a2713aSLionel Sambuc 
126f4a2713aSLionel Sambuc   return Actions.ActOnForwardClassDeclaration(atLoc, ClassNames.data(),
127f4a2713aSLionel Sambuc                                               ClassLocs.data(),
128f4a2713aSLionel Sambuc                                               ClassNames.size());
129f4a2713aSLionel Sambuc }
130f4a2713aSLionel Sambuc 
CheckNestedObjCContexts(SourceLocation AtLoc)131f4a2713aSLionel Sambuc void Parser::CheckNestedObjCContexts(SourceLocation AtLoc)
132f4a2713aSLionel Sambuc {
133f4a2713aSLionel Sambuc   Sema::ObjCContainerKind ock = Actions.getObjCContainerKind();
134f4a2713aSLionel Sambuc   if (ock == Sema::OCK_None)
135f4a2713aSLionel Sambuc     return;
136f4a2713aSLionel Sambuc 
137f4a2713aSLionel Sambuc   Decl *Decl = Actions.getObjCDeclContext();
138f4a2713aSLionel Sambuc   if (CurParsedObjCImpl) {
139f4a2713aSLionel Sambuc     CurParsedObjCImpl->finish(AtLoc);
140f4a2713aSLionel Sambuc   } else {
141f4a2713aSLionel Sambuc     Actions.ActOnAtEnd(getCurScope(), AtLoc);
142f4a2713aSLionel Sambuc   }
143f4a2713aSLionel Sambuc   Diag(AtLoc, diag::err_objc_missing_end)
144f4a2713aSLionel Sambuc       << FixItHint::CreateInsertion(AtLoc, "@end\n");
145f4a2713aSLionel Sambuc   if (Decl)
146f4a2713aSLionel Sambuc     Diag(Decl->getLocStart(), diag::note_objc_container_start)
147f4a2713aSLionel Sambuc         << (int) ock;
148f4a2713aSLionel Sambuc }
149f4a2713aSLionel Sambuc 
150f4a2713aSLionel Sambuc ///
151f4a2713aSLionel Sambuc ///   objc-interface:
152f4a2713aSLionel Sambuc ///     objc-class-interface-attributes[opt] objc-class-interface
153f4a2713aSLionel Sambuc ///     objc-category-interface
154f4a2713aSLionel Sambuc ///
155f4a2713aSLionel Sambuc ///   objc-class-interface:
156f4a2713aSLionel Sambuc ///     '@' 'interface' identifier objc-superclass[opt]
157f4a2713aSLionel Sambuc ///       objc-protocol-refs[opt]
158f4a2713aSLionel Sambuc ///       objc-class-instance-variables[opt]
159f4a2713aSLionel Sambuc ///       objc-interface-decl-list
160f4a2713aSLionel Sambuc ///     @end
161f4a2713aSLionel Sambuc ///
162f4a2713aSLionel Sambuc ///   objc-category-interface:
163f4a2713aSLionel Sambuc ///     '@' 'interface' identifier '(' identifier[opt] ')'
164f4a2713aSLionel Sambuc ///       objc-protocol-refs[opt]
165f4a2713aSLionel Sambuc ///       objc-interface-decl-list
166f4a2713aSLionel Sambuc ///     @end
167f4a2713aSLionel Sambuc ///
168f4a2713aSLionel Sambuc ///   objc-superclass:
169f4a2713aSLionel Sambuc ///     ':' identifier
170f4a2713aSLionel Sambuc ///
171f4a2713aSLionel Sambuc ///   objc-class-interface-attributes:
172f4a2713aSLionel Sambuc ///     __attribute__((visibility("default")))
173f4a2713aSLionel Sambuc ///     __attribute__((visibility("hidden")))
174f4a2713aSLionel Sambuc ///     __attribute__((deprecated))
175f4a2713aSLionel Sambuc ///     __attribute__((unavailable))
176f4a2713aSLionel Sambuc ///     __attribute__((objc_exception)) - used by NSException on 64-bit
177f4a2713aSLionel Sambuc ///     __attribute__((objc_root_class))
178f4a2713aSLionel Sambuc ///
ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,ParsedAttributes & attrs)179f4a2713aSLionel Sambuc Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
180f4a2713aSLionel Sambuc                                               ParsedAttributes &attrs) {
181f4a2713aSLionel Sambuc   assert(Tok.isObjCAtKeyword(tok::objc_interface) &&
182f4a2713aSLionel Sambuc          "ParseObjCAtInterfaceDeclaration(): Expected @interface");
183f4a2713aSLionel Sambuc   CheckNestedObjCContexts(AtLoc);
184f4a2713aSLionel Sambuc   ConsumeToken(); // the "interface" identifier
185f4a2713aSLionel Sambuc 
186f4a2713aSLionel Sambuc   // Code completion after '@interface'.
187f4a2713aSLionel Sambuc   if (Tok.is(tok::code_completion)) {
188f4a2713aSLionel Sambuc     Actions.CodeCompleteObjCInterfaceDecl(getCurScope());
189f4a2713aSLionel Sambuc     cutOffParsing();
190*0a6a1f1dSLionel Sambuc     return nullptr;
191f4a2713aSLionel Sambuc   }
192f4a2713aSLionel Sambuc 
193f4a2713aSLionel Sambuc   MaybeSkipAttributes(tok::objc_interface);
194f4a2713aSLionel Sambuc 
195f4a2713aSLionel Sambuc   if (Tok.isNot(tok::identifier)) {
196*0a6a1f1dSLionel Sambuc     Diag(Tok, diag::err_expected)
197*0a6a1f1dSLionel Sambuc         << tok::identifier; // missing class or category name.
198*0a6a1f1dSLionel Sambuc     return nullptr;
199f4a2713aSLionel Sambuc   }
200f4a2713aSLionel Sambuc 
201f4a2713aSLionel Sambuc   // We have a class or category name - consume it.
202f4a2713aSLionel Sambuc   IdentifierInfo *nameId = Tok.getIdentifierInfo();
203f4a2713aSLionel Sambuc   SourceLocation nameLoc = ConsumeToken();
204f4a2713aSLionel Sambuc   if (Tok.is(tok::l_paren) &&
205f4a2713aSLionel Sambuc       !isKnownToBeTypeSpecifier(GetLookAheadToken(1))) { // we have a category.
206f4a2713aSLionel Sambuc 
207f4a2713aSLionel Sambuc     BalancedDelimiterTracker T(*this, tok::l_paren);
208f4a2713aSLionel Sambuc     T.consumeOpen();
209f4a2713aSLionel Sambuc 
210f4a2713aSLionel Sambuc     SourceLocation categoryLoc;
211*0a6a1f1dSLionel Sambuc     IdentifierInfo *categoryId = nullptr;
212f4a2713aSLionel Sambuc     if (Tok.is(tok::code_completion)) {
213f4a2713aSLionel Sambuc       Actions.CodeCompleteObjCInterfaceCategory(getCurScope(), nameId, nameLoc);
214f4a2713aSLionel Sambuc       cutOffParsing();
215*0a6a1f1dSLionel Sambuc       return nullptr;
216f4a2713aSLionel Sambuc     }
217f4a2713aSLionel Sambuc 
218f4a2713aSLionel Sambuc     // For ObjC2, the category name is optional (not an error).
219f4a2713aSLionel Sambuc     if (Tok.is(tok::identifier)) {
220f4a2713aSLionel Sambuc       categoryId = Tok.getIdentifierInfo();
221f4a2713aSLionel Sambuc       categoryLoc = ConsumeToken();
222f4a2713aSLionel Sambuc     }
223f4a2713aSLionel Sambuc     else if (!getLangOpts().ObjC2) {
224*0a6a1f1dSLionel Sambuc       Diag(Tok, diag::err_expected)
225*0a6a1f1dSLionel Sambuc           << tok::identifier; // missing category name.
226*0a6a1f1dSLionel Sambuc       return nullptr;
227f4a2713aSLionel Sambuc     }
228f4a2713aSLionel Sambuc 
229f4a2713aSLionel Sambuc     T.consumeClose();
230f4a2713aSLionel Sambuc     if (T.getCloseLocation().isInvalid())
231*0a6a1f1dSLionel Sambuc       return nullptr;
232f4a2713aSLionel Sambuc 
233f4a2713aSLionel Sambuc     if (!attrs.empty()) { // categories don't support attributes.
234f4a2713aSLionel Sambuc       Diag(nameLoc, diag::err_objc_no_attributes_on_category);
235f4a2713aSLionel Sambuc       attrs.clear();
236f4a2713aSLionel Sambuc     }
237f4a2713aSLionel Sambuc 
238f4a2713aSLionel Sambuc     // Next, we need to check for any protocol references.
239f4a2713aSLionel Sambuc     SourceLocation LAngleLoc, EndProtoLoc;
240f4a2713aSLionel Sambuc     SmallVector<Decl *, 8> ProtocolRefs;
241f4a2713aSLionel Sambuc     SmallVector<SourceLocation, 8> ProtocolLocs;
242f4a2713aSLionel Sambuc     if (Tok.is(tok::less) &&
243f4a2713aSLionel Sambuc         ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true,
244f4a2713aSLionel Sambuc                                     LAngleLoc, EndProtoLoc))
245*0a6a1f1dSLionel Sambuc       return nullptr;
246f4a2713aSLionel Sambuc 
247f4a2713aSLionel Sambuc     Decl *CategoryType =
248f4a2713aSLionel Sambuc     Actions.ActOnStartCategoryInterface(AtLoc,
249f4a2713aSLionel Sambuc                                         nameId, nameLoc,
250f4a2713aSLionel Sambuc                                         categoryId, categoryLoc,
251f4a2713aSLionel Sambuc                                         ProtocolRefs.data(),
252f4a2713aSLionel Sambuc                                         ProtocolRefs.size(),
253f4a2713aSLionel Sambuc                                         ProtocolLocs.data(),
254f4a2713aSLionel Sambuc                                         EndProtoLoc);
255f4a2713aSLionel Sambuc 
256f4a2713aSLionel Sambuc     if (Tok.is(tok::l_brace))
257f4a2713aSLionel Sambuc       ParseObjCClassInstanceVariables(CategoryType, tok::objc_private, AtLoc);
258f4a2713aSLionel Sambuc 
259f4a2713aSLionel Sambuc     ParseObjCInterfaceDeclList(tok::objc_not_keyword, CategoryType);
260f4a2713aSLionel Sambuc     return CategoryType;
261f4a2713aSLionel Sambuc   }
262f4a2713aSLionel Sambuc   // Parse a class interface.
263*0a6a1f1dSLionel Sambuc   IdentifierInfo *superClassId = nullptr;
264f4a2713aSLionel Sambuc   SourceLocation superClassLoc;
265f4a2713aSLionel Sambuc 
266f4a2713aSLionel Sambuc   if (Tok.is(tok::colon)) { // a super class is specified.
267f4a2713aSLionel Sambuc     ConsumeToken();
268f4a2713aSLionel Sambuc 
269f4a2713aSLionel Sambuc     // Code completion of superclass names.
270f4a2713aSLionel Sambuc     if (Tok.is(tok::code_completion)) {
271f4a2713aSLionel Sambuc       Actions.CodeCompleteObjCSuperclass(getCurScope(), nameId, nameLoc);
272f4a2713aSLionel Sambuc       cutOffParsing();
273*0a6a1f1dSLionel Sambuc       return nullptr;
274f4a2713aSLionel Sambuc     }
275f4a2713aSLionel Sambuc 
276f4a2713aSLionel Sambuc     if (Tok.isNot(tok::identifier)) {
277*0a6a1f1dSLionel Sambuc       Diag(Tok, diag::err_expected)
278*0a6a1f1dSLionel Sambuc           << tok::identifier; // missing super class name.
279*0a6a1f1dSLionel Sambuc       return nullptr;
280f4a2713aSLionel Sambuc     }
281f4a2713aSLionel Sambuc     superClassId = Tok.getIdentifierInfo();
282f4a2713aSLionel Sambuc     superClassLoc = ConsumeToken();
283f4a2713aSLionel Sambuc   }
284f4a2713aSLionel Sambuc   // Next, we need to check for any protocol references.
285f4a2713aSLionel Sambuc   SmallVector<Decl *, 8> ProtocolRefs;
286f4a2713aSLionel Sambuc   SmallVector<SourceLocation, 8> ProtocolLocs;
287f4a2713aSLionel Sambuc   SourceLocation LAngleLoc, EndProtoLoc;
288f4a2713aSLionel Sambuc   if (Tok.is(tok::less) &&
289f4a2713aSLionel Sambuc       ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true,
290f4a2713aSLionel Sambuc                                   LAngleLoc, EndProtoLoc))
291*0a6a1f1dSLionel Sambuc     return nullptr;
292f4a2713aSLionel Sambuc 
293f4a2713aSLionel Sambuc   if (Tok.isNot(tok::less))
294f4a2713aSLionel Sambuc     Actions.ActOnTypedefedProtocols(ProtocolRefs, superClassId, superClassLoc);
295f4a2713aSLionel Sambuc 
296f4a2713aSLionel Sambuc   Decl *ClsType =
297f4a2713aSLionel Sambuc     Actions.ActOnStartClassInterface(AtLoc, nameId, nameLoc,
298f4a2713aSLionel Sambuc                                      superClassId, superClassLoc,
299f4a2713aSLionel Sambuc                                      ProtocolRefs.data(), ProtocolRefs.size(),
300f4a2713aSLionel Sambuc                                      ProtocolLocs.data(),
301f4a2713aSLionel Sambuc                                      EndProtoLoc, attrs.getList());
302f4a2713aSLionel Sambuc 
303f4a2713aSLionel Sambuc   if (Tok.is(tok::l_brace))
304f4a2713aSLionel Sambuc     ParseObjCClassInstanceVariables(ClsType, tok::objc_protected, AtLoc);
305f4a2713aSLionel Sambuc 
306f4a2713aSLionel Sambuc   ParseObjCInterfaceDeclList(tok::objc_interface, ClsType);
307f4a2713aSLionel Sambuc   return ClsType;
308f4a2713aSLionel Sambuc }
309f4a2713aSLionel Sambuc 
310f4a2713aSLionel Sambuc ///   objc-interface-decl-list:
311f4a2713aSLionel Sambuc ///     empty
312f4a2713aSLionel Sambuc ///     objc-interface-decl-list objc-property-decl [OBJC2]
313f4a2713aSLionel Sambuc ///     objc-interface-decl-list objc-method-requirement [OBJC2]
314f4a2713aSLionel Sambuc ///     objc-interface-decl-list objc-method-proto ';'
315f4a2713aSLionel Sambuc ///     objc-interface-decl-list declaration
316f4a2713aSLionel Sambuc ///     objc-interface-decl-list ';'
317f4a2713aSLionel Sambuc ///
318f4a2713aSLionel Sambuc ///   objc-method-requirement: [OBJC2]
319f4a2713aSLionel Sambuc ///     @required
320f4a2713aSLionel Sambuc ///     @optional
321f4a2713aSLionel Sambuc ///
ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,Decl * CDecl)322f4a2713aSLionel Sambuc void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
323f4a2713aSLionel Sambuc                                         Decl *CDecl) {
324f4a2713aSLionel Sambuc   SmallVector<Decl *, 32> allMethods;
325f4a2713aSLionel Sambuc   SmallVector<Decl *, 16> allProperties;
326f4a2713aSLionel Sambuc   SmallVector<DeclGroupPtrTy, 8> allTUVariables;
327f4a2713aSLionel Sambuc   tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword;
328f4a2713aSLionel Sambuc 
329f4a2713aSLionel Sambuc   SourceRange AtEnd;
330f4a2713aSLionel Sambuc 
331f4a2713aSLionel Sambuc   while (1) {
332f4a2713aSLionel Sambuc     // If this is a method prototype, parse it.
333f4a2713aSLionel Sambuc     if (Tok.is(tok::minus) || Tok.is(tok::plus)) {
334f4a2713aSLionel Sambuc       if (Decl *methodPrototype =
335f4a2713aSLionel Sambuc           ParseObjCMethodPrototype(MethodImplKind, false))
336f4a2713aSLionel Sambuc         allMethods.push_back(methodPrototype);
337f4a2713aSLionel Sambuc       // Consume the ';' here, since ParseObjCMethodPrototype() is re-used for
338f4a2713aSLionel Sambuc       // method definitions.
339f4a2713aSLionel Sambuc       if (ExpectAndConsumeSemi(diag::err_expected_semi_after_method_proto)) {
340f4a2713aSLionel Sambuc         // We didn't find a semi and we error'ed out. Skip until a ';' or '@'.
341f4a2713aSLionel Sambuc         SkipUntil(tok::at, StopAtSemi | StopBeforeMatch);
342f4a2713aSLionel Sambuc         if (Tok.is(tok::semi))
343f4a2713aSLionel Sambuc           ConsumeToken();
344f4a2713aSLionel Sambuc       }
345f4a2713aSLionel Sambuc       continue;
346f4a2713aSLionel Sambuc     }
347f4a2713aSLionel Sambuc     if (Tok.is(tok::l_paren)) {
348f4a2713aSLionel Sambuc       Diag(Tok, diag::err_expected_minus_or_plus);
349f4a2713aSLionel Sambuc       ParseObjCMethodDecl(Tok.getLocation(),
350f4a2713aSLionel Sambuc                           tok::minus,
351f4a2713aSLionel Sambuc                           MethodImplKind, false);
352f4a2713aSLionel Sambuc       continue;
353f4a2713aSLionel Sambuc     }
354f4a2713aSLionel Sambuc     // Ignore excess semicolons.
355f4a2713aSLionel Sambuc     if (Tok.is(tok::semi)) {
356f4a2713aSLionel Sambuc       ConsumeToken();
357f4a2713aSLionel Sambuc       continue;
358f4a2713aSLionel Sambuc     }
359f4a2713aSLionel Sambuc 
360f4a2713aSLionel Sambuc     // If we got to the end of the file, exit the loop.
361*0a6a1f1dSLionel Sambuc     if (isEofOrEom())
362f4a2713aSLionel Sambuc       break;
363f4a2713aSLionel Sambuc 
364f4a2713aSLionel Sambuc     // Code completion within an Objective-C interface.
365f4a2713aSLionel Sambuc     if (Tok.is(tok::code_completion)) {
366f4a2713aSLionel Sambuc       Actions.CodeCompleteOrdinaryName(getCurScope(),
367f4a2713aSLionel Sambuc                             CurParsedObjCImpl? Sema::PCC_ObjCImplementation
368f4a2713aSLionel Sambuc                                              : Sema::PCC_ObjCInterface);
369f4a2713aSLionel Sambuc       return cutOffParsing();
370f4a2713aSLionel Sambuc     }
371f4a2713aSLionel Sambuc 
372f4a2713aSLionel Sambuc     // If we don't have an @ directive, parse it as a function definition.
373f4a2713aSLionel Sambuc     if (Tok.isNot(tok::at)) {
374f4a2713aSLionel Sambuc       // The code below does not consume '}'s because it is afraid of eating the
375f4a2713aSLionel Sambuc       // end of a namespace.  Because of the way this code is structured, an
376f4a2713aSLionel Sambuc       // erroneous r_brace would cause an infinite loop if not handled here.
377f4a2713aSLionel Sambuc       if (Tok.is(tok::r_brace))
378f4a2713aSLionel Sambuc         break;
379f4a2713aSLionel Sambuc       ParsedAttributesWithRange attrs(AttrFactory);
380f4a2713aSLionel Sambuc       allTUVariables.push_back(ParseDeclarationOrFunctionDefinition(attrs));
381f4a2713aSLionel Sambuc       continue;
382f4a2713aSLionel Sambuc     }
383f4a2713aSLionel Sambuc 
384f4a2713aSLionel Sambuc     // Otherwise, we have an @ directive, eat the @.
385f4a2713aSLionel Sambuc     SourceLocation AtLoc = ConsumeToken(); // the "@"
386f4a2713aSLionel Sambuc     if (Tok.is(tok::code_completion)) {
387f4a2713aSLionel Sambuc       Actions.CodeCompleteObjCAtDirective(getCurScope());
388f4a2713aSLionel Sambuc       return cutOffParsing();
389f4a2713aSLionel Sambuc     }
390f4a2713aSLionel Sambuc 
391f4a2713aSLionel Sambuc     tok::ObjCKeywordKind DirectiveKind = Tok.getObjCKeywordID();
392f4a2713aSLionel Sambuc 
393f4a2713aSLionel Sambuc     if (DirectiveKind == tok::objc_end) { // @end -> terminate list
394f4a2713aSLionel Sambuc       AtEnd.setBegin(AtLoc);
395f4a2713aSLionel Sambuc       AtEnd.setEnd(Tok.getLocation());
396f4a2713aSLionel Sambuc       break;
397f4a2713aSLionel Sambuc     } else if (DirectiveKind == tok::objc_not_keyword) {
398f4a2713aSLionel Sambuc       Diag(Tok, diag::err_objc_unknown_at);
399f4a2713aSLionel Sambuc       SkipUntil(tok::semi);
400f4a2713aSLionel Sambuc       continue;
401f4a2713aSLionel Sambuc     }
402f4a2713aSLionel Sambuc 
403f4a2713aSLionel Sambuc     // Eat the identifier.
404f4a2713aSLionel Sambuc     ConsumeToken();
405f4a2713aSLionel Sambuc 
406f4a2713aSLionel Sambuc     switch (DirectiveKind) {
407f4a2713aSLionel Sambuc     default:
408f4a2713aSLionel Sambuc       // FIXME: If someone forgets an @end on a protocol, this loop will
409f4a2713aSLionel Sambuc       // continue to eat up tons of stuff and spew lots of nonsense errors.  It
410f4a2713aSLionel Sambuc       // would probably be better to bail out if we saw an @class or @interface
411f4a2713aSLionel Sambuc       // or something like that.
412f4a2713aSLionel Sambuc       Diag(AtLoc, diag::err_objc_illegal_interface_qual);
413f4a2713aSLionel Sambuc       // Skip until we see an '@' or '}' or ';'.
414f4a2713aSLionel Sambuc       SkipUntil(tok::r_brace, tok::at, StopAtSemi);
415f4a2713aSLionel Sambuc       break;
416f4a2713aSLionel Sambuc 
417f4a2713aSLionel Sambuc     case tok::objc_implementation:
418f4a2713aSLionel Sambuc     case tok::objc_interface:
419f4a2713aSLionel Sambuc       Diag(AtLoc, diag::err_objc_missing_end)
420f4a2713aSLionel Sambuc           << FixItHint::CreateInsertion(AtLoc, "@end\n");
421f4a2713aSLionel Sambuc       Diag(CDecl->getLocStart(), diag::note_objc_container_start)
422f4a2713aSLionel Sambuc           << (int) Actions.getObjCContainerKind();
423f4a2713aSLionel Sambuc       ConsumeToken();
424f4a2713aSLionel Sambuc       break;
425f4a2713aSLionel Sambuc 
426f4a2713aSLionel Sambuc     case tok::objc_required:
427f4a2713aSLionel Sambuc     case tok::objc_optional:
428f4a2713aSLionel Sambuc       // This is only valid on protocols.
429f4a2713aSLionel Sambuc       // FIXME: Should this check for ObjC2 being enabled?
430f4a2713aSLionel Sambuc       if (contextKey != tok::objc_protocol)
431f4a2713aSLionel Sambuc         Diag(AtLoc, diag::err_objc_directive_only_in_protocol);
432f4a2713aSLionel Sambuc       else
433f4a2713aSLionel Sambuc         MethodImplKind = DirectiveKind;
434f4a2713aSLionel Sambuc       break;
435f4a2713aSLionel Sambuc 
436f4a2713aSLionel Sambuc     case tok::objc_property:
437f4a2713aSLionel Sambuc       if (!getLangOpts().ObjC2)
438f4a2713aSLionel Sambuc         Diag(AtLoc, diag::err_objc_properties_require_objc2);
439f4a2713aSLionel Sambuc 
440f4a2713aSLionel Sambuc       ObjCDeclSpec OCDS;
441f4a2713aSLionel Sambuc       SourceLocation LParenLoc;
442f4a2713aSLionel Sambuc       // Parse property attribute list, if any.
443f4a2713aSLionel Sambuc       if (Tok.is(tok::l_paren)) {
444f4a2713aSLionel Sambuc         LParenLoc = Tok.getLocation();
445f4a2713aSLionel Sambuc         ParseObjCPropertyAttribute(OCDS);
446f4a2713aSLionel Sambuc       }
447f4a2713aSLionel Sambuc 
448*0a6a1f1dSLionel Sambuc       auto ObjCPropertyCallback = [&](ParsingFieldDeclarator &FD) {
449*0a6a1f1dSLionel Sambuc         if (FD.D.getIdentifier() == nullptr) {
450*0a6a1f1dSLionel Sambuc           Diag(AtLoc, diag::err_objc_property_requires_field_name)
451*0a6a1f1dSLionel Sambuc               << FD.D.getSourceRange();
452*0a6a1f1dSLionel Sambuc           return;
453*0a6a1f1dSLionel Sambuc         }
454*0a6a1f1dSLionel Sambuc         if (FD.BitfieldSize) {
455*0a6a1f1dSLionel Sambuc           Diag(AtLoc, diag::err_objc_property_bitfield)
456*0a6a1f1dSLionel Sambuc               << FD.D.getSourceRange();
457*0a6a1f1dSLionel Sambuc           return;
458*0a6a1f1dSLionel Sambuc         }
459*0a6a1f1dSLionel Sambuc 
460*0a6a1f1dSLionel Sambuc         // Install the property declarator into interfaceDecl.
461*0a6a1f1dSLionel Sambuc         IdentifierInfo *SelName =
462*0a6a1f1dSLionel Sambuc             OCDS.getGetterName() ? OCDS.getGetterName() : FD.D.getIdentifier();
463*0a6a1f1dSLionel Sambuc 
464*0a6a1f1dSLionel Sambuc         Selector GetterSel = PP.getSelectorTable().getNullarySelector(SelName);
465*0a6a1f1dSLionel Sambuc         IdentifierInfo *SetterName = OCDS.getSetterName();
466*0a6a1f1dSLionel Sambuc         Selector SetterSel;
467*0a6a1f1dSLionel Sambuc         if (SetterName)
468*0a6a1f1dSLionel Sambuc           SetterSel = PP.getSelectorTable().getSelector(1, &SetterName);
469*0a6a1f1dSLionel Sambuc         else
470*0a6a1f1dSLionel Sambuc           SetterSel = SelectorTable::constructSetterSelector(
471*0a6a1f1dSLionel Sambuc               PP.getIdentifierTable(), PP.getSelectorTable(),
472*0a6a1f1dSLionel Sambuc               FD.D.getIdentifier());
473*0a6a1f1dSLionel Sambuc         bool isOverridingProperty = false;
474*0a6a1f1dSLionel Sambuc         Decl *Property = Actions.ActOnProperty(
475*0a6a1f1dSLionel Sambuc             getCurScope(), AtLoc, LParenLoc, FD, OCDS, GetterSel, SetterSel,
476*0a6a1f1dSLionel Sambuc             &isOverridingProperty, MethodImplKind);
477*0a6a1f1dSLionel Sambuc         if (!isOverridingProperty)
478*0a6a1f1dSLionel Sambuc           allProperties.push_back(Property);
479*0a6a1f1dSLionel Sambuc 
480*0a6a1f1dSLionel Sambuc         FD.complete(Property);
481*0a6a1f1dSLionel Sambuc       };
482f4a2713aSLionel Sambuc 
483f4a2713aSLionel Sambuc       // Parse all the comma separated declarators.
484f4a2713aSLionel Sambuc       ParsingDeclSpec DS(*this);
485*0a6a1f1dSLionel Sambuc       ParseStructDeclaration(DS, ObjCPropertyCallback);
486f4a2713aSLionel Sambuc 
487f4a2713aSLionel Sambuc       ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list);
488f4a2713aSLionel Sambuc       break;
489f4a2713aSLionel Sambuc     }
490f4a2713aSLionel Sambuc   }
491f4a2713aSLionel Sambuc 
492f4a2713aSLionel Sambuc   // We break out of the big loop in two cases: when we see @end or when we see
493f4a2713aSLionel Sambuc   // EOF.  In the former case, eat the @end.  In the later case, emit an error.
494f4a2713aSLionel Sambuc   if (Tok.is(tok::code_completion)) {
495f4a2713aSLionel Sambuc     Actions.CodeCompleteObjCAtDirective(getCurScope());
496f4a2713aSLionel Sambuc     return cutOffParsing();
497f4a2713aSLionel Sambuc   } else if (Tok.isObjCAtKeyword(tok::objc_end)) {
498f4a2713aSLionel Sambuc     ConsumeToken(); // the "end" identifier
499f4a2713aSLionel Sambuc   } else {
500f4a2713aSLionel Sambuc     Diag(Tok, diag::err_objc_missing_end)
501f4a2713aSLionel Sambuc         << FixItHint::CreateInsertion(Tok.getLocation(), "\n@end\n");
502f4a2713aSLionel Sambuc     Diag(CDecl->getLocStart(), diag::note_objc_container_start)
503f4a2713aSLionel Sambuc         << (int) Actions.getObjCContainerKind();
504f4a2713aSLionel Sambuc     AtEnd.setBegin(Tok.getLocation());
505f4a2713aSLionel Sambuc     AtEnd.setEnd(Tok.getLocation());
506f4a2713aSLionel Sambuc   }
507f4a2713aSLionel Sambuc 
508f4a2713aSLionel Sambuc   // Insert collected methods declarations into the @interface object.
509f4a2713aSLionel Sambuc   // This passes in an invalid SourceLocation for AtEndLoc when EOF is hit.
510f4a2713aSLionel Sambuc   Actions.ActOnAtEnd(getCurScope(), AtEnd, allMethods, allTUVariables);
511f4a2713aSLionel Sambuc }
512f4a2713aSLionel Sambuc 
513f4a2713aSLionel Sambuc ///   Parse property attribute declarations.
514f4a2713aSLionel Sambuc ///
515f4a2713aSLionel Sambuc ///   property-attr-decl: '(' property-attrlist ')'
516f4a2713aSLionel Sambuc ///   property-attrlist:
517f4a2713aSLionel Sambuc ///     property-attribute
518f4a2713aSLionel Sambuc ///     property-attrlist ',' property-attribute
519f4a2713aSLionel Sambuc ///   property-attribute:
520f4a2713aSLionel Sambuc ///     getter '=' identifier
521f4a2713aSLionel Sambuc ///     setter '=' identifier ':'
522f4a2713aSLionel Sambuc ///     readonly
523f4a2713aSLionel Sambuc ///     readwrite
524f4a2713aSLionel Sambuc ///     assign
525f4a2713aSLionel Sambuc ///     retain
526f4a2713aSLionel Sambuc ///     copy
527f4a2713aSLionel Sambuc ///     nonatomic
528f4a2713aSLionel Sambuc ///     atomic
529f4a2713aSLionel Sambuc ///     strong
530f4a2713aSLionel Sambuc ///     weak
531f4a2713aSLionel Sambuc ///     unsafe_unretained
532f4a2713aSLionel Sambuc ///
ParseObjCPropertyAttribute(ObjCDeclSpec & DS)533f4a2713aSLionel Sambuc void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) {
534f4a2713aSLionel Sambuc   assert(Tok.getKind() == tok::l_paren);
535f4a2713aSLionel Sambuc   BalancedDelimiterTracker T(*this, tok::l_paren);
536f4a2713aSLionel Sambuc   T.consumeOpen();
537f4a2713aSLionel Sambuc 
538f4a2713aSLionel Sambuc   while (1) {
539f4a2713aSLionel Sambuc     if (Tok.is(tok::code_completion)) {
540f4a2713aSLionel Sambuc       Actions.CodeCompleteObjCPropertyFlags(getCurScope(), DS);
541f4a2713aSLionel Sambuc       return cutOffParsing();
542f4a2713aSLionel Sambuc     }
543f4a2713aSLionel Sambuc     const IdentifierInfo *II = Tok.getIdentifierInfo();
544f4a2713aSLionel Sambuc 
545f4a2713aSLionel Sambuc     // If this is not an identifier at all, bail out early.
546*0a6a1f1dSLionel Sambuc     if (!II) {
547f4a2713aSLionel Sambuc       T.consumeClose();
548f4a2713aSLionel Sambuc       return;
549f4a2713aSLionel Sambuc     }
550f4a2713aSLionel Sambuc 
551f4a2713aSLionel Sambuc     SourceLocation AttrName = ConsumeToken(); // consume last attribute name
552f4a2713aSLionel Sambuc 
553f4a2713aSLionel Sambuc     if (II->isStr("readonly"))
554f4a2713aSLionel Sambuc       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_readonly);
555f4a2713aSLionel Sambuc     else if (II->isStr("assign"))
556f4a2713aSLionel Sambuc       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_assign);
557f4a2713aSLionel Sambuc     else if (II->isStr("unsafe_unretained"))
558f4a2713aSLionel Sambuc       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_unsafe_unretained);
559f4a2713aSLionel Sambuc     else if (II->isStr("readwrite"))
560f4a2713aSLionel Sambuc       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_readwrite);
561f4a2713aSLionel Sambuc     else if (II->isStr("retain"))
562f4a2713aSLionel Sambuc       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_retain);
563f4a2713aSLionel Sambuc     else if (II->isStr("strong"))
564f4a2713aSLionel Sambuc       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_strong);
565f4a2713aSLionel Sambuc     else if (II->isStr("copy"))
566f4a2713aSLionel Sambuc       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_copy);
567f4a2713aSLionel Sambuc     else if (II->isStr("nonatomic"))
568f4a2713aSLionel Sambuc       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_nonatomic);
569f4a2713aSLionel Sambuc     else if (II->isStr("atomic"))
570f4a2713aSLionel Sambuc       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_atomic);
571f4a2713aSLionel Sambuc     else if (II->isStr("weak"))
572f4a2713aSLionel Sambuc       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_weak);
573f4a2713aSLionel Sambuc     else if (II->isStr("getter") || II->isStr("setter")) {
574f4a2713aSLionel Sambuc       bool IsSetter = II->getNameStart()[0] == 's';
575f4a2713aSLionel Sambuc 
576f4a2713aSLionel Sambuc       // getter/setter require extra treatment.
577f4a2713aSLionel Sambuc       unsigned DiagID = IsSetter ? diag::err_objc_expected_equal_for_setter :
578f4a2713aSLionel Sambuc         diag::err_objc_expected_equal_for_getter;
579f4a2713aSLionel Sambuc 
580*0a6a1f1dSLionel Sambuc       if (ExpectAndConsume(tok::equal, DiagID)) {
581*0a6a1f1dSLionel Sambuc         SkipUntil(tok::r_paren, StopAtSemi);
582f4a2713aSLionel Sambuc         return;
583*0a6a1f1dSLionel Sambuc       }
584f4a2713aSLionel Sambuc 
585f4a2713aSLionel Sambuc       if (Tok.is(tok::code_completion)) {
586f4a2713aSLionel Sambuc         if (IsSetter)
587f4a2713aSLionel Sambuc           Actions.CodeCompleteObjCPropertySetter(getCurScope());
588f4a2713aSLionel Sambuc         else
589f4a2713aSLionel Sambuc           Actions.CodeCompleteObjCPropertyGetter(getCurScope());
590f4a2713aSLionel Sambuc         return cutOffParsing();
591f4a2713aSLionel Sambuc       }
592f4a2713aSLionel Sambuc 
593f4a2713aSLionel Sambuc 
594f4a2713aSLionel Sambuc       SourceLocation SelLoc;
595f4a2713aSLionel Sambuc       IdentifierInfo *SelIdent = ParseObjCSelectorPiece(SelLoc);
596f4a2713aSLionel Sambuc 
597f4a2713aSLionel Sambuc       if (!SelIdent) {
598f4a2713aSLionel Sambuc         Diag(Tok, diag::err_objc_expected_selector_for_getter_setter)
599f4a2713aSLionel Sambuc           << IsSetter;
600f4a2713aSLionel Sambuc         SkipUntil(tok::r_paren, StopAtSemi);
601f4a2713aSLionel Sambuc         return;
602f4a2713aSLionel Sambuc       }
603f4a2713aSLionel Sambuc 
604f4a2713aSLionel Sambuc       if (IsSetter) {
605f4a2713aSLionel Sambuc         DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_setter);
606f4a2713aSLionel Sambuc         DS.setSetterName(SelIdent);
607f4a2713aSLionel Sambuc 
608f4a2713aSLionel Sambuc         if (ExpectAndConsume(tok::colon,
609*0a6a1f1dSLionel Sambuc                              diag::err_expected_colon_after_setter_name)) {
610*0a6a1f1dSLionel Sambuc           SkipUntil(tok::r_paren, StopAtSemi);
611f4a2713aSLionel Sambuc           return;
612*0a6a1f1dSLionel Sambuc         }
613f4a2713aSLionel Sambuc       } else {
614f4a2713aSLionel Sambuc         DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_getter);
615f4a2713aSLionel Sambuc         DS.setGetterName(SelIdent);
616f4a2713aSLionel Sambuc       }
617f4a2713aSLionel Sambuc     } else {
618f4a2713aSLionel Sambuc       Diag(AttrName, diag::err_objc_expected_property_attr) << II;
619f4a2713aSLionel Sambuc       SkipUntil(tok::r_paren, StopAtSemi);
620f4a2713aSLionel Sambuc       return;
621f4a2713aSLionel Sambuc     }
622f4a2713aSLionel Sambuc 
623f4a2713aSLionel Sambuc     if (Tok.isNot(tok::comma))
624f4a2713aSLionel Sambuc       break;
625f4a2713aSLionel Sambuc 
626f4a2713aSLionel Sambuc     ConsumeToken();
627f4a2713aSLionel Sambuc   }
628f4a2713aSLionel Sambuc 
629f4a2713aSLionel Sambuc   T.consumeClose();
630f4a2713aSLionel Sambuc }
631f4a2713aSLionel Sambuc 
632f4a2713aSLionel Sambuc ///   objc-method-proto:
633f4a2713aSLionel Sambuc ///     objc-instance-method objc-method-decl objc-method-attributes[opt]
634f4a2713aSLionel Sambuc ///     objc-class-method objc-method-decl objc-method-attributes[opt]
635f4a2713aSLionel Sambuc ///
636f4a2713aSLionel Sambuc ///   objc-instance-method: '-'
637f4a2713aSLionel Sambuc ///   objc-class-method: '+'
638f4a2713aSLionel Sambuc ///
639f4a2713aSLionel Sambuc ///   objc-method-attributes:         [OBJC2]
640f4a2713aSLionel Sambuc ///     __attribute__((deprecated))
641f4a2713aSLionel Sambuc ///
ParseObjCMethodPrototype(tok::ObjCKeywordKind MethodImplKind,bool MethodDefinition)642f4a2713aSLionel Sambuc Decl *Parser::ParseObjCMethodPrototype(tok::ObjCKeywordKind MethodImplKind,
643f4a2713aSLionel Sambuc                                        bool MethodDefinition) {
644f4a2713aSLionel Sambuc   assert((Tok.is(tok::minus) || Tok.is(tok::plus)) && "expected +/-");
645f4a2713aSLionel Sambuc 
646f4a2713aSLionel Sambuc   tok::TokenKind methodType = Tok.getKind();
647f4a2713aSLionel Sambuc   SourceLocation mLoc = ConsumeToken();
648f4a2713aSLionel Sambuc   Decl *MDecl = ParseObjCMethodDecl(mLoc, methodType, MethodImplKind,
649f4a2713aSLionel Sambuc                                     MethodDefinition);
650f4a2713aSLionel Sambuc   // Since this rule is used for both method declarations and definitions,
651f4a2713aSLionel Sambuc   // the caller is (optionally) responsible for consuming the ';'.
652f4a2713aSLionel Sambuc   return MDecl;
653f4a2713aSLionel Sambuc }
654f4a2713aSLionel Sambuc 
655f4a2713aSLionel Sambuc ///   objc-selector:
656f4a2713aSLionel Sambuc ///     identifier
657f4a2713aSLionel Sambuc ///     one of
658f4a2713aSLionel Sambuc ///       enum struct union if else while do for switch case default
659f4a2713aSLionel Sambuc ///       break continue return goto asm sizeof typeof __alignof
660f4a2713aSLionel Sambuc ///       unsigned long const short volatile signed restrict _Complex
661f4a2713aSLionel Sambuc ///       in out inout bycopy byref oneway int char float double void _Bool
662f4a2713aSLionel Sambuc ///
ParseObjCSelectorPiece(SourceLocation & SelectorLoc)663f4a2713aSLionel Sambuc IdentifierInfo *Parser::ParseObjCSelectorPiece(SourceLocation &SelectorLoc) {
664f4a2713aSLionel Sambuc 
665f4a2713aSLionel Sambuc   switch (Tok.getKind()) {
666f4a2713aSLionel Sambuc   default:
667*0a6a1f1dSLionel Sambuc     return nullptr;
668f4a2713aSLionel Sambuc   case tok::ampamp:
669f4a2713aSLionel Sambuc   case tok::ampequal:
670f4a2713aSLionel Sambuc   case tok::amp:
671f4a2713aSLionel Sambuc   case tok::pipe:
672f4a2713aSLionel Sambuc   case tok::tilde:
673f4a2713aSLionel Sambuc   case tok::exclaim:
674f4a2713aSLionel Sambuc   case tok::exclaimequal:
675f4a2713aSLionel Sambuc   case tok::pipepipe:
676f4a2713aSLionel Sambuc   case tok::pipeequal:
677f4a2713aSLionel Sambuc   case tok::caret:
678f4a2713aSLionel Sambuc   case tok::caretequal: {
679f4a2713aSLionel Sambuc     std::string ThisTok(PP.getSpelling(Tok));
680f4a2713aSLionel Sambuc     if (isLetter(ThisTok[0])) {
681f4a2713aSLionel Sambuc       IdentifierInfo *II = &PP.getIdentifierTable().get(ThisTok.data());
682f4a2713aSLionel Sambuc       Tok.setKind(tok::identifier);
683f4a2713aSLionel Sambuc       SelectorLoc = ConsumeToken();
684f4a2713aSLionel Sambuc       return II;
685f4a2713aSLionel Sambuc     }
686*0a6a1f1dSLionel Sambuc     return nullptr;
687f4a2713aSLionel Sambuc   }
688f4a2713aSLionel Sambuc 
689f4a2713aSLionel Sambuc   case tok::identifier:
690f4a2713aSLionel Sambuc   case tok::kw_asm:
691f4a2713aSLionel Sambuc   case tok::kw_auto:
692f4a2713aSLionel Sambuc   case tok::kw_bool:
693f4a2713aSLionel Sambuc   case tok::kw_break:
694f4a2713aSLionel Sambuc   case tok::kw_case:
695f4a2713aSLionel Sambuc   case tok::kw_catch:
696f4a2713aSLionel Sambuc   case tok::kw_char:
697f4a2713aSLionel Sambuc   case tok::kw_class:
698f4a2713aSLionel Sambuc   case tok::kw_const:
699f4a2713aSLionel Sambuc   case tok::kw_const_cast:
700f4a2713aSLionel Sambuc   case tok::kw_continue:
701f4a2713aSLionel Sambuc   case tok::kw_default:
702f4a2713aSLionel Sambuc   case tok::kw_delete:
703f4a2713aSLionel Sambuc   case tok::kw_do:
704f4a2713aSLionel Sambuc   case tok::kw_double:
705f4a2713aSLionel Sambuc   case tok::kw_dynamic_cast:
706f4a2713aSLionel Sambuc   case tok::kw_else:
707f4a2713aSLionel Sambuc   case tok::kw_enum:
708f4a2713aSLionel Sambuc   case tok::kw_explicit:
709f4a2713aSLionel Sambuc   case tok::kw_export:
710f4a2713aSLionel Sambuc   case tok::kw_extern:
711f4a2713aSLionel Sambuc   case tok::kw_false:
712f4a2713aSLionel Sambuc   case tok::kw_float:
713f4a2713aSLionel Sambuc   case tok::kw_for:
714f4a2713aSLionel Sambuc   case tok::kw_friend:
715f4a2713aSLionel Sambuc   case tok::kw_goto:
716f4a2713aSLionel Sambuc   case tok::kw_if:
717f4a2713aSLionel Sambuc   case tok::kw_inline:
718f4a2713aSLionel Sambuc   case tok::kw_int:
719f4a2713aSLionel Sambuc   case tok::kw_long:
720f4a2713aSLionel Sambuc   case tok::kw_mutable:
721f4a2713aSLionel Sambuc   case tok::kw_namespace:
722f4a2713aSLionel Sambuc   case tok::kw_new:
723f4a2713aSLionel Sambuc   case tok::kw_operator:
724f4a2713aSLionel Sambuc   case tok::kw_private:
725f4a2713aSLionel Sambuc   case tok::kw_protected:
726f4a2713aSLionel Sambuc   case tok::kw_public:
727f4a2713aSLionel Sambuc   case tok::kw_register:
728f4a2713aSLionel Sambuc   case tok::kw_reinterpret_cast:
729f4a2713aSLionel Sambuc   case tok::kw_restrict:
730f4a2713aSLionel Sambuc   case tok::kw_return:
731f4a2713aSLionel Sambuc   case tok::kw_short:
732f4a2713aSLionel Sambuc   case tok::kw_signed:
733f4a2713aSLionel Sambuc   case tok::kw_sizeof:
734f4a2713aSLionel Sambuc   case tok::kw_static:
735f4a2713aSLionel Sambuc   case tok::kw_static_cast:
736f4a2713aSLionel Sambuc   case tok::kw_struct:
737f4a2713aSLionel Sambuc   case tok::kw_switch:
738f4a2713aSLionel Sambuc   case tok::kw_template:
739f4a2713aSLionel Sambuc   case tok::kw_this:
740f4a2713aSLionel Sambuc   case tok::kw_throw:
741f4a2713aSLionel Sambuc   case tok::kw_true:
742f4a2713aSLionel Sambuc   case tok::kw_try:
743f4a2713aSLionel Sambuc   case tok::kw_typedef:
744f4a2713aSLionel Sambuc   case tok::kw_typeid:
745f4a2713aSLionel Sambuc   case tok::kw_typename:
746f4a2713aSLionel Sambuc   case tok::kw_typeof:
747f4a2713aSLionel Sambuc   case tok::kw_union:
748f4a2713aSLionel Sambuc   case tok::kw_unsigned:
749f4a2713aSLionel Sambuc   case tok::kw_using:
750f4a2713aSLionel Sambuc   case tok::kw_virtual:
751f4a2713aSLionel Sambuc   case tok::kw_void:
752f4a2713aSLionel Sambuc   case tok::kw_volatile:
753f4a2713aSLionel Sambuc   case tok::kw_wchar_t:
754f4a2713aSLionel Sambuc   case tok::kw_while:
755f4a2713aSLionel Sambuc   case tok::kw__Bool:
756f4a2713aSLionel Sambuc   case tok::kw__Complex:
757f4a2713aSLionel Sambuc   case tok::kw___alignof:
758f4a2713aSLionel Sambuc     IdentifierInfo *II = Tok.getIdentifierInfo();
759f4a2713aSLionel Sambuc     SelectorLoc = ConsumeToken();
760f4a2713aSLionel Sambuc     return II;
761f4a2713aSLionel Sambuc   }
762f4a2713aSLionel Sambuc }
763f4a2713aSLionel Sambuc 
764f4a2713aSLionel Sambuc ///  objc-for-collection-in: 'in'
765f4a2713aSLionel Sambuc ///
isTokIdentifier_in() const766f4a2713aSLionel Sambuc bool Parser::isTokIdentifier_in() const {
767f4a2713aSLionel Sambuc   // FIXME: May have to do additional look-ahead to only allow for
768f4a2713aSLionel Sambuc   // valid tokens following an 'in'; such as an identifier, unary operators,
769f4a2713aSLionel Sambuc   // '[' etc.
770f4a2713aSLionel Sambuc   return (getLangOpts().ObjC2 && Tok.is(tok::identifier) &&
771f4a2713aSLionel Sambuc           Tok.getIdentifierInfo() == ObjCTypeQuals[objc_in]);
772f4a2713aSLionel Sambuc }
773f4a2713aSLionel Sambuc 
774f4a2713aSLionel Sambuc /// ParseObjCTypeQualifierList - This routine parses the objective-c's type
775f4a2713aSLionel Sambuc /// qualifier list and builds their bitmask representation in the input
776f4a2713aSLionel Sambuc /// argument.
777f4a2713aSLionel Sambuc ///
778f4a2713aSLionel Sambuc ///   objc-type-qualifiers:
779f4a2713aSLionel Sambuc ///     objc-type-qualifier
780f4a2713aSLionel Sambuc ///     objc-type-qualifiers objc-type-qualifier
781f4a2713aSLionel Sambuc ///
ParseObjCTypeQualifierList(ObjCDeclSpec & DS,Declarator::TheContext Context)782f4a2713aSLionel Sambuc void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS,
783f4a2713aSLionel Sambuc                                         Declarator::TheContext Context) {
784f4a2713aSLionel Sambuc   assert(Context == Declarator::ObjCParameterContext ||
785f4a2713aSLionel Sambuc          Context == Declarator::ObjCResultContext);
786f4a2713aSLionel Sambuc 
787f4a2713aSLionel Sambuc   while (1) {
788f4a2713aSLionel Sambuc     if (Tok.is(tok::code_completion)) {
789f4a2713aSLionel Sambuc       Actions.CodeCompleteObjCPassingType(getCurScope(), DS,
790f4a2713aSLionel Sambuc                           Context == Declarator::ObjCParameterContext);
791f4a2713aSLionel Sambuc       return cutOffParsing();
792f4a2713aSLionel Sambuc     }
793f4a2713aSLionel Sambuc 
794f4a2713aSLionel Sambuc     if (Tok.isNot(tok::identifier))
795f4a2713aSLionel Sambuc       return;
796f4a2713aSLionel Sambuc 
797f4a2713aSLionel Sambuc     const IdentifierInfo *II = Tok.getIdentifierInfo();
798f4a2713aSLionel Sambuc     for (unsigned i = 0; i != objc_NumQuals; ++i) {
799f4a2713aSLionel Sambuc       if (II != ObjCTypeQuals[i])
800f4a2713aSLionel Sambuc         continue;
801f4a2713aSLionel Sambuc 
802f4a2713aSLionel Sambuc       ObjCDeclSpec::ObjCDeclQualifier Qual;
803f4a2713aSLionel Sambuc       switch (i) {
804f4a2713aSLionel Sambuc       default: llvm_unreachable("Unknown decl qualifier");
805f4a2713aSLionel Sambuc       case objc_in:     Qual = ObjCDeclSpec::DQ_In; break;
806f4a2713aSLionel Sambuc       case objc_out:    Qual = ObjCDeclSpec::DQ_Out; break;
807f4a2713aSLionel Sambuc       case objc_inout:  Qual = ObjCDeclSpec::DQ_Inout; break;
808f4a2713aSLionel Sambuc       case objc_oneway: Qual = ObjCDeclSpec::DQ_Oneway; break;
809f4a2713aSLionel Sambuc       case objc_bycopy: Qual = ObjCDeclSpec::DQ_Bycopy; break;
810f4a2713aSLionel Sambuc       case objc_byref:  Qual = ObjCDeclSpec::DQ_Byref; break;
811f4a2713aSLionel Sambuc       }
812f4a2713aSLionel Sambuc       DS.setObjCDeclQualifier(Qual);
813f4a2713aSLionel Sambuc       ConsumeToken();
814*0a6a1f1dSLionel Sambuc       II = nullptr;
815f4a2713aSLionel Sambuc       break;
816f4a2713aSLionel Sambuc     }
817f4a2713aSLionel Sambuc 
818f4a2713aSLionel Sambuc     // If this wasn't a recognized qualifier, bail out.
819f4a2713aSLionel Sambuc     if (II) return;
820f4a2713aSLionel Sambuc   }
821f4a2713aSLionel Sambuc }
822f4a2713aSLionel Sambuc 
823f4a2713aSLionel Sambuc /// Take all the decl attributes out of the given list and add
824f4a2713aSLionel Sambuc /// them to the given attribute set.
takeDeclAttributes(ParsedAttributes & attrs,AttributeList * list)825f4a2713aSLionel Sambuc static void takeDeclAttributes(ParsedAttributes &attrs,
826f4a2713aSLionel Sambuc                                AttributeList *list) {
827f4a2713aSLionel Sambuc   while (list) {
828f4a2713aSLionel Sambuc     AttributeList *cur = list;
829f4a2713aSLionel Sambuc     list = cur->getNext();
830f4a2713aSLionel Sambuc 
831f4a2713aSLionel Sambuc     if (!cur->isUsedAsTypeAttr()) {
832f4a2713aSLionel Sambuc       // Clear out the next pointer.  We're really completely
833f4a2713aSLionel Sambuc       // destroying the internal invariants of the declarator here,
834f4a2713aSLionel Sambuc       // but it doesn't matter because we're done with it.
835*0a6a1f1dSLionel Sambuc       cur->setNext(nullptr);
836f4a2713aSLionel Sambuc       attrs.add(cur);
837f4a2713aSLionel Sambuc     }
838f4a2713aSLionel Sambuc   }
839f4a2713aSLionel Sambuc }
840f4a2713aSLionel Sambuc 
841f4a2713aSLionel Sambuc /// takeDeclAttributes - Take all the decl attributes from the given
842f4a2713aSLionel Sambuc /// declarator and add them to the given list.
takeDeclAttributes(ParsedAttributes & attrs,Declarator & D)843f4a2713aSLionel Sambuc static void takeDeclAttributes(ParsedAttributes &attrs,
844f4a2713aSLionel Sambuc                                Declarator &D) {
845f4a2713aSLionel Sambuc   // First, take ownership of all attributes.
846f4a2713aSLionel Sambuc   attrs.getPool().takeAllFrom(D.getAttributePool());
847f4a2713aSLionel Sambuc   attrs.getPool().takeAllFrom(D.getDeclSpec().getAttributePool());
848f4a2713aSLionel Sambuc 
849f4a2713aSLionel Sambuc   // Now actually move the attributes over.
850f4a2713aSLionel Sambuc   takeDeclAttributes(attrs, D.getDeclSpec().getAttributes().getList());
851f4a2713aSLionel Sambuc   takeDeclAttributes(attrs, D.getAttributes());
852f4a2713aSLionel Sambuc   for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i)
853f4a2713aSLionel Sambuc     takeDeclAttributes(attrs,
854f4a2713aSLionel Sambuc                   const_cast<AttributeList*>(D.getTypeObject(i).getAttrs()));
855f4a2713aSLionel Sambuc }
856f4a2713aSLionel Sambuc 
857f4a2713aSLionel Sambuc ///   objc-type-name:
858f4a2713aSLionel Sambuc ///     '(' objc-type-qualifiers[opt] type-name ')'
859f4a2713aSLionel Sambuc ///     '(' objc-type-qualifiers[opt] ')'
860f4a2713aSLionel Sambuc ///
ParseObjCTypeName(ObjCDeclSpec & DS,Declarator::TheContext context,ParsedAttributes * paramAttrs)861f4a2713aSLionel Sambuc ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS,
862f4a2713aSLionel Sambuc                                      Declarator::TheContext context,
863f4a2713aSLionel Sambuc                                      ParsedAttributes *paramAttrs) {
864f4a2713aSLionel Sambuc   assert(context == Declarator::ObjCParameterContext ||
865f4a2713aSLionel Sambuc          context == Declarator::ObjCResultContext);
866*0a6a1f1dSLionel Sambuc   assert((paramAttrs != nullptr) ==
867*0a6a1f1dSLionel Sambuc          (context == Declarator::ObjCParameterContext));
868f4a2713aSLionel Sambuc 
869f4a2713aSLionel Sambuc   assert(Tok.is(tok::l_paren) && "expected (");
870f4a2713aSLionel Sambuc 
871f4a2713aSLionel Sambuc   BalancedDelimiterTracker T(*this, tok::l_paren);
872f4a2713aSLionel Sambuc   T.consumeOpen();
873f4a2713aSLionel Sambuc 
874f4a2713aSLionel Sambuc   SourceLocation TypeStartLoc = Tok.getLocation();
875f4a2713aSLionel Sambuc   ObjCDeclContextSwitch ObjCDC(*this);
876f4a2713aSLionel Sambuc 
877f4a2713aSLionel Sambuc   // Parse type qualifiers, in, inout, etc.
878f4a2713aSLionel Sambuc   ParseObjCTypeQualifierList(DS, context);
879f4a2713aSLionel Sambuc 
880f4a2713aSLionel Sambuc   ParsedType Ty;
881f4a2713aSLionel Sambuc   if (isTypeSpecifierQualifier()) {
882f4a2713aSLionel Sambuc     // Parse an abstract declarator.
883f4a2713aSLionel Sambuc     DeclSpec declSpec(AttrFactory);
884f4a2713aSLionel Sambuc     declSpec.setObjCQualifiers(&DS);
885f4a2713aSLionel Sambuc     ParseSpecifierQualifierList(declSpec);
886f4a2713aSLionel Sambuc     declSpec.SetRangeEnd(Tok.getLocation());
887f4a2713aSLionel Sambuc     Declarator declarator(declSpec, context);
888f4a2713aSLionel Sambuc     ParseDeclarator(declarator);
889f4a2713aSLionel Sambuc 
890f4a2713aSLionel Sambuc     // If that's not invalid, extract a type.
891f4a2713aSLionel Sambuc     if (!declarator.isInvalidType()) {
892f4a2713aSLionel Sambuc       TypeResult type = Actions.ActOnTypeName(getCurScope(), declarator);
893f4a2713aSLionel Sambuc       if (!type.isInvalid())
894f4a2713aSLionel Sambuc         Ty = type.get();
895f4a2713aSLionel Sambuc 
896f4a2713aSLionel Sambuc       // If we're parsing a parameter, steal all the decl attributes
897f4a2713aSLionel Sambuc       // and add them to the decl spec.
898f4a2713aSLionel Sambuc       if (context == Declarator::ObjCParameterContext)
899f4a2713aSLionel Sambuc         takeDeclAttributes(*paramAttrs, declarator);
900f4a2713aSLionel Sambuc     }
901f4a2713aSLionel Sambuc   } else if (context == Declarator::ObjCResultContext &&
902f4a2713aSLionel Sambuc              Tok.is(tok::identifier)) {
903f4a2713aSLionel Sambuc     if (!Ident_instancetype)
904f4a2713aSLionel Sambuc       Ident_instancetype = PP.getIdentifierInfo("instancetype");
905f4a2713aSLionel Sambuc 
906f4a2713aSLionel Sambuc     if (Tok.getIdentifierInfo() == Ident_instancetype) {
907f4a2713aSLionel Sambuc       Ty = Actions.ActOnObjCInstanceType(Tok.getLocation());
908f4a2713aSLionel Sambuc       ConsumeToken();
909f4a2713aSLionel Sambuc     }
910f4a2713aSLionel Sambuc   }
911f4a2713aSLionel Sambuc 
912f4a2713aSLionel Sambuc   if (Tok.is(tok::r_paren))
913f4a2713aSLionel Sambuc     T.consumeClose();
914f4a2713aSLionel Sambuc   else if (Tok.getLocation() == TypeStartLoc) {
915f4a2713aSLionel Sambuc     // If we didn't eat any tokens, then this isn't a type.
916f4a2713aSLionel Sambuc     Diag(Tok, diag::err_expected_type);
917f4a2713aSLionel Sambuc     SkipUntil(tok::r_paren, StopAtSemi);
918f4a2713aSLionel Sambuc   } else {
919f4a2713aSLionel Sambuc     // Otherwise, we found *something*, but didn't get a ')' in the right
920f4a2713aSLionel Sambuc     // place.  Emit an error then return what we have as the type.
921f4a2713aSLionel Sambuc     T.consumeClose();
922f4a2713aSLionel Sambuc   }
923f4a2713aSLionel Sambuc   return Ty;
924f4a2713aSLionel Sambuc }
925f4a2713aSLionel Sambuc 
926f4a2713aSLionel Sambuc ///   objc-method-decl:
927f4a2713aSLionel Sambuc ///     objc-selector
928f4a2713aSLionel Sambuc ///     objc-keyword-selector objc-parmlist[opt]
929f4a2713aSLionel Sambuc ///     objc-type-name objc-selector
930f4a2713aSLionel Sambuc ///     objc-type-name objc-keyword-selector objc-parmlist[opt]
931f4a2713aSLionel Sambuc ///
932f4a2713aSLionel Sambuc ///   objc-keyword-selector:
933f4a2713aSLionel Sambuc ///     objc-keyword-decl
934f4a2713aSLionel Sambuc ///     objc-keyword-selector objc-keyword-decl
935f4a2713aSLionel Sambuc ///
936f4a2713aSLionel Sambuc ///   objc-keyword-decl:
937f4a2713aSLionel Sambuc ///     objc-selector ':' objc-type-name objc-keyword-attributes[opt] identifier
938f4a2713aSLionel Sambuc ///     objc-selector ':' objc-keyword-attributes[opt] identifier
939f4a2713aSLionel Sambuc ///     ':' objc-type-name objc-keyword-attributes[opt] identifier
940f4a2713aSLionel Sambuc ///     ':' objc-keyword-attributes[opt] identifier
941f4a2713aSLionel Sambuc ///
942f4a2713aSLionel Sambuc ///   objc-parmlist:
943f4a2713aSLionel Sambuc ///     objc-parms objc-ellipsis[opt]
944f4a2713aSLionel Sambuc ///
945f4a2713aSLionel Sambuc ///   objc-parms:
946f4a2713aSLionel Sambuc ///     objc-parms , parameter-declaration
947f4a2713aSLionel Sambuc ///
948f4a2713aSLionel Sambuc ///   objc-ellipsis:
949f4a2713aSLionel Sambuc ///     , ...
950f4a2713aSLionel Sambuc ///
951f4a2713aSLionel Sambuc ///   objc-keyword-attributes:         [OBJC2]
952f4a2713aSLionel Sambuc ///     __attribute__((unused))
953f4a2713aSLionel Sambuc ///
ParseObjCMethodDecl(SourceLocation mLoc,tok::TokenKind mType,tok::ObjCKeywordKind MethodImplKind,bool MethodDefinition)954f4a2713aSLionel Sambuc Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
955f4a2713aSLionel Sambuc                                   tok::TokenKind mType,
956f4a2713aSLionel Sambuc                                   tok::ObjCKeywordKind MethodImplKind,
957f4a2713aSLionel Sambuc                                   bool MethodDefinition) {
958f4a2713aSLionel Sambuc   ParsingDeclRAIIObject PD(*this, ParsingDeclRAIIObject::NoParent);
959f4a2713aSLionel Sambuc 
960f4a2713aSLionel Sambuc   if (Tok.is(tok::code_completion)) {
961f4a2713aSLionel Sambuc     Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus,
962f4a2713aSLionel Sambuc                                        /*ReturnType=*/ ParsedType());
963f4a2713aSLionel Sambuc     cutOffParsing();
964*0a6a1f1dSLionel Sambuc     return nullptr;
965f4a2713aSLionel Sambuc   }
966f4a2713aSLionel Sambuc 
967f4a2713aSLionel Sambuc   // Parse the return type if present.
968f4a2713aSLionel Sambuc   ParsedType ReturnType;
969f4a2713aSLionel Sambuc   ObjCDeclSpec DSRet;
970f4a2713aSLionel Sambuc   if (Tok.is(tok::l_paren))
971*0a6a1f1dSLionel Sambuc     ReturnType = ParseObjCTypeName(DSRet, Declarator::ObjCResultContext,
972*0a6a1f1dSLionel Sambuc                                    nullptr);
973f4a2713aSLionel Sambuc 
974f4a2713aSLionel Sambuc   // If attributes exist before the method, parse them.
975f4a2713aSLionel Sambuc   ParsedAttributes methodAttrs(AttrFactory);
976f4a2713aSLionel Sambuc   if (getLangOpts().ObjC2)
977f4a2713aSLionel Sambuc     MaybeParseGNUAttributes(methodAttrs);
978f4a2713aSLionel Sambuc 
979f4a2713aSLionel Sambuc   if (Tok.is(tok::code_completion)) {
980f4a2713aSLionel Sambuc     Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus,
981f4a2713aSLionel Sambuc                                        ReturnType);
982f4a2713aSLionel Sambuc     cutOffParsing();
983*0a6a1f1dSLionel Sambuc     return nullptr;
984f4a2713aSLionel Sambuc   }
985f4a2713aSLionel Sambuc 
986f4a2713aSLionel Sambuc   // Now parse the selector.
987f4a2713aSLionel Sambuc   SourceLocation selLoc;
988f4a2713aSLionel Sambuc   IdentifierInfo *SelIdent = ParseObjCSelectorPiece(selLoc);
989f4a2713aSLionel Sambuc 
990f4a2713aSLionel Sambuc   // An unnamed colon is valid.
991f4a2713aSLionel Sambuc   if (!SelIdent && Tok.isNot(tok::colon)) { // missing selector name.
992f4a2713aSLionel Sambuc     Diag(Tok, diag::err_expected_selector_for_method)
993f4a2713aSLionel Sambuc       << SourceRange(mLoc, Tok.getLocation());
994f4a2713aSLionel Sambuc     // Skip until we get a ; or @.
995f4a2713aSLionel Sambuc     SkipUntil(tok::at, StopAtSemi | StopBeforeMatch);
996*0a6a1f1dSLionel Sambuc     return nullptr;
997f4a2713aSLionel Sambuc   }
998f4a2713aSLionel Sambuc 
999f4a2713aSLionel Sambuc   SmallVector<DeclaratorChunk::ParamInfo, 8> CParamInfo;
1000f4a2713aSLionel Sambuc   if (Tok.isNot(tok::colon)) {
1001f4a2713aSLionel Sambuc     // If attributes exist after the method, parse them.
1002f4a2713aSLionel Sambuc     if (getLangOpts().ObjC2)
1003f4a2713aSLionel Sambuc       MaybeParseGNUAttributes(methodAttrs);
1004f4a2713aSLionel Sambuc 
1005f4a2713aSLionel Sambuc     Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent);
1006f4a2713aSLionel Sambuc     Decl *Result
1007f4a2713aSLionel Sambuc          = Actions.ActOnMethodDeclaration(getCurScope(), mLoc, Tok.getLocation(),
1008f4a2713aSLionel Sambuc                                           mType, DSRet, ReturnType,
1009*0a6a1f1dSLionel Sambuc                                           selLoc, Sel, nullptr,
1010f4a2713aSLionel Sambuc                                           CParamInfo.data(), CParamInfo.size(),
1011f4a2713aSLionel Sambuc                                           methodAttrs.getList(), MethodImplKind,
1012f4a2713aSLionel Sambuc                                           false, MethodDefinition);
1013f4a2713aSLionel Sambuc     PD.complete(Result);
1014f4a2713aSLionel Sambuc     return Result;
1015f4a2713aSLionel Sambuc   }
1016f4a2713aSLionel Sambuc 
1017f4a2713aSLionel Sambuc   SmallVector<IdentifierInfo *, 12> KeyIdents;
1018f4a2713aSLionel Sambuc   SmallVector<SourceLocation, 12> KeyLocs;
1019f4a2713aSLionel Sambuc   SmallVector<Sema::ObjCArgInfo, 12> ArgInfos;
1020f4a2713aSLionel Sambuc   ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope |
1021f4a2713aSLionel Sambuc                             Scope::FunctionDeclarationScope | Scope::DeclScope);
1022f4a2713aSLionel Sambuc 
1023f4a2713aSLionel Sambuc   AttributePool allParamAttrs(AttrFactory);
1024f4a2713aSLionel Sambuc   while (1) {
1025f4a2713aSLionel Sambuc     ParsedAttributes paramAttrs(AttrFactory);
1026f4a2713aSLionel Sambuc     Sema::ObjCArgInfo ArgInfo;
1027f4a2713aSLionel Sambuc 
1028f4a2713aSLionel Sambuc     // Each iteration parses a single keyword argument.
1029*0a6a1f1dSLionel Sambuc     if (ExpectAndConsume(tok::colon))
1030f4a2713aSLionel Sambuc       break;
1031f4a2713aSLionel Sambuc 
1032f4a2713aSLionel Sambuc     ArgInfo.Type = ParsedType();
1033f4a2713aSLionel Sambuc     if (Tok.is(tok::l_paren)) // Parse the argument type if present.
1034f4a2713aSLionel Sambuc       ArgInfo.Type = ParseObjCTypeName(ArgInfo.DeclSpec,
1035f4a2713aSLionel Sambuc                                        Declarator::ObjCParameterContext,
1036f4a2713aSLionel Sambuc                                        &paramAttrs);
1037f4a2713aSLionel Sambuc 
1038f4a2713aSLionel Sambuc     // If attributes exist before the argument name, parse them.
1039f4a2713aSLionel Sambuc     // Regardless, collect all the attributes we've parsed so far.
1040*0a6a1f1dSLionel Sambuc     ArgInfo.ArgAttrs = nullptr;
1041f4a2713aSLionel Sambuc     if (getLangOpts().ObjC2) {
1042f4a2713aSLionel Sambuc       MaybeParseGNUAttributes(paramAttrs);
1043f4a2713aSLionel Sambuc       ArgInfo.ArgAttrs = paramAttrs.getList();
1044f4a2713aSLionel Sambuc     }
1045f4a2713aSLionel Sambuc 
1046f4a2713aSLionel Sambuc     // Code completion for the next piece of the selector.
1047f4a2713aSLionel Sambuc     if (Tok.is(tok::code_completion)) {
1048f4a2713aSLionel Sambuc       KeyIdents.push_back(SelIdent);
1049f4a2713aSLionel Sambuc       Actions.CodeCompleteObjCMethodDeclSelector(getCurScope(),
1050f4a2713aSLionel Sambuc                                                  mType == tok::minus,
1051f4a2713aSLionel Sambuc                                                  /*AtParameterName=*/true,
1052f4a2713aSLionel Sambuc                                                  ReturnType, KeyIdents);
1053f4a2713aSLionel Sambuc       cutOffParsing();
1054*0a6a1f1dSLionel Sambuc       return nullptr;
1055f4a2713aSLionel Sambuc     }
1056f4a2713aSLionel Sambuc 
1057f4a2713aSLionel Sambuc     if (Tok.isNot(tok::identifier)) {
1058*0a6a1f1dSLionel Sambuc       Diag(Tok, diag::err_expected)
1059*0a6a1f1dSLionel Sambuc           << tok::identifier; // missing argument name.
1060f4a2713aSLionel Sambuc       break;
1061f4a2713aSLionel Sambuc     }
1062f4a2713aSLionel Sambuc 
1063f4a2713aSLionel Sambuc     ArgInfo.Name = Tok.getIdentifierInfo();
1064f4a2713aSLionel Sambuc     ArgInfo.NameLoc = Tok.getLocation();
1065f4a2713aSLionel Sambuc     ConsumeToken(); // Eat the identifier.
1066f4a2713aSLionel Sambuc 
1067f4a2713aSLionel Sambuc     ArgInfos.push_back(ArgInfo);
1068f4a2713aSLionel Sambuc     KeyIdents.push_back(SelIdent);
1069f4a2713aSLionel Sambuc     KeyLocs.push_back(selLoc);
1070f4a2713aSLionel Sambuc 
1071f4a2713aSLionel Sambuc     // Make sure the attributes persist.
1072f4a2713aSLionel Sambuc     allParamAttrs.takeAllFrom(paramAttrs.getPool());
1073f4a2713aSLionel Sambuc 
1074f4a2713aSLionel Sambuc     // Code completion for the next piece of the selector.
1075f4a2713aSLionel Sambuc     if (Tok.is(tok::code_completion)) {
1076f4a2713aSLionel Sambuc       Actions.CodeCompleteObjCMethodDeclSelector(getCurScope(),
1077f4a2713aSLionel Sambuc                                                  mType == tok::minus,
1078f4a2713aSLionel Sambuc                                                  /*AtParameterName=*/false,
1079f4a2713aSLionel Sambuc                                                  ReturnType, KeyIdents);
1080f4a2713aSLionel Sambuc       cutOffParsing();
1081*0a6a1f1dSLionel Sambuc       return nullptr;
1082f4a2713aSLionel Sambuc     }
1083f4a2713aSLionel Sambuc 
1084f4a2713aSLionel Sambuc     // Check for another keyword selector.
1085f4a2713aSLionel Sambuc     SelIdent = ParseObjCSelectorPiece(selLoc);
1086f4a2713aSLionel Sambuc     if (!SelIdent && Tok.isNot(tok::colon))
1087f4a2713aSLionel Sambuc       break;
1088f4a2713aSLionel Sambuc     if (!SelIdent) {
1089f4a2713aSLionel Sambuc       SourceLocation ColonLoc = Tok.getLocation();
1090f4a2713aSLionel Sambuc       if (PP.getLocForEndOfToken(ArgInfo.NameLoc) == ColonLoc) {
1091f4a2713aSLionel Sambuc         Diag(ArgInfo.NameLoc, diag::warn_missing_selector_name) << ArgInfo.Name;
1092f4a2713aSLionel Sambuc         Diag(ArgInfo.NameLoc, diag::note_missing_selector_name) << ArgInfo.Name;
1093f4a2713aSLionel Sambuc         Diag(ColonLoc, diag::note_force_empty_selector_name) << ArgInfo.Name;
1094f4a2713aSLionel Sambuc       }
1095f4a2713aSLionel Sambuc     }
1096f4a2713aSLionel Sambuc     // We have a selector or a colon, continue parsing.
1097f4a2713aSLionel Sambuc   }
1098f4a2713aSLionel Sambuc 
1099f4a2713aSLionel Sambuc   bool isVariadic = false;
1100f4a2713aSLionel Sambuc   bool cStyleParamWarned = false;
1101f4a2713aSLionel Sambuc   // Parse the (optional) parameter list.
1102f4a2713aSLionel Sambuc   while (Tok.is(tok::comma)) {
1103f4a2713aSLionel Sambuc     ConsumeToken();
1104f4a2713aSLionel Sambuc     if (Tok.is(tok::ellipsis)) {
1105f4a2713aSLionel Sambuc       isVariadic = true;
1106f4a2713aSLionel Sambuc       ConsumeToken();
1107f4a2713aSLionel Sambuc       break;
1108f4a2713aSLionel Sambuc     }
1109f4a2713aSLionel Sambuc     if (!cStyleParamWarned) {
1110f4a2713aSLionel Sambuc       Diag(Tok, diag::warn_cstyle_param);
1111f4a2713aSLionel Sambuc       cStyleParamWarned = true;
1112f4a2713aSLionel Sambuc     }
1113f4a2713aSLionel Sambuc     DeclSpec DS(AttrFactory);
1114f4a2713aSLionel Sambuc     ParseDeclarationSpecifiers(DS);
1115f4a2713aSLionel Sambuc     // Parse the declarator.
1116f4a2713aSLionel Sambuc     Declarator ParmDecl(DS, Declarator::PrototypeContext);
1117f4a2713aSLionel Sambuc     ParseDeclarator(ParmDecl);
1118f4a2713aSLionel Sambuc     IdentifierInfo *ParmII = ParmDecl.getIdentifier();
1119f4a2713aSLionel Sambuc     Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDecl);
1120f4a2713aSLionel Sambuc     CParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,
1121f4a2713aSLionel Sambuc                                                     ParmDecl.getIdentifierLoc(),
1122f4a2713aSLionel Sambuc                                                     Param,
1123*0a6a1f1dSLionel Sambuc                                                     nullptr));
1124f4a2713aSLionel Sambuc   }
1125f4a2713aSLionel Sambuc 
1126f4a2713aSLionel Sambuc   // FIXME: Add support for optional parameter list...
1127f4a2713aSLionel Sambuc   // If attributes exist after the method, parse them.
1128f4a2713aSLionel Sambuc   if (getLangOpts().ObjC2)
1129f4a2713aSLionel Sambuc     MaybeParseGNUAttributes(methodAttrs);
1130f4a2713aSLionel Sambuc 
1131f4a2713aSLionel Sambuc   if (KeyIdents.size() == 0)
1132*0a6a1f1dSLionel Sambuc     return nullptr;
1133f4a2713aSLionel Sambuc 
1134f4a2713aSLionel Sambuc   Selector Sel = PP.getSelectorTable().getSelector(KeyIdents.size(),
1135f4a2713aSLionel Sambuc                                                    &KeyIdents[0]);
1136f4a2713aSLionel Sambuc   Decl *Result
1137f4a2713aSLionel Sambuc        = Actions.ActOnMethodDeclaration(getCurScope(), mLoc, Tok.getLocation(),
1138f4a2713aSLionel Sambuc                                         mType, DSRet, ReturnType,
1139f4a2713aSLionel Sambuc                                         KeyLocs, Sel, &ArgInfos[0],
1140f4a2713aSLionel Sambuc                                         CParamInfo.data(), CParamInfo.size(),
1141f4a2713aSLionel Sambuc                                         methodAttrs.getList(),
1142f4a2713aSLionel Sambuc                                         MethodImplKind, isVariadic, MethodDefinition);
1143f4a2713aSLionel Sambuc 
1144f4a2713aSLionel Sambuc   PD.complete(Result);
1145f4a2713aSLionel Sambuc   return Result;
1146f4a2713aSLionel Sambuc }
1147f4a2713aSLionel Sambuc 
1148f4a2713aSLionel Sambuc ///   objc-protocol-refs:
1149f4a2713aSLionel Sambuc ///     '<' identifier-list '>'
1150f4a2713aSLionel Sambuc ///
1151f4a2713aSLionel Sambuc bool Parser::
ParseObjCProtocolReferences(SmallVectorImpl<Decl * > & Protocols,SmallVectorImpl<SourceLocation> & ProtocolLocs,bool WarnOnDeclarations,SourceLocation & LAngleLoc,SourceLocation & EndLoc)1152f4a2713aSLionel Sambuc ParseObjCProtocolReferences(SmallVectorImpl<Decl *> &Protocols,
1153f4a2713aSLionel Sambuc                             SmallVectorImpl<SourceLocation> &ProtocolLocs,
1154f4a2713aSLionel Sambuc                             bool WarnOnDeclarations,
1155f4a2713aSLionel Sambuc                             SourceLocation &LAngleLoc, SourceLocation &EndLoc) {
1156f4a2713aSLionel Sambuc   assert(Tok.is(tok::less) && "expected <");
1157f4a2713aSLionel Sambuc 
1158f4a2713aSLionel Sambuc   LAngleLoc = ConsumeToken(); // the "<"
1159f4a2713aSLionel Sambuc 
1160f4a2713aSLionel Sambuc   SmallVector<IdentifierLocPair, 8> ProtocolIdents;
1161f4a2713aSLionel Sambuc 
1162f4a2713aSLionel Sambuc   while (1) {
1163f4a2713aSLionel Sambuc     if (Tok.is(tok::code_completion)) {
1164f4a2713aSLionel Sambuc       Actions.CodeCompleteObjCProtocolReferences(ProtocolIdents.data(),
1165f4a2713aSLionel Sambuc                                                  ProtocolIdents.size());
1166f4a2713aSLionel Sambuc       cutOffParsing();
1167f4a2713aSLionel Sambuc       return true;
1168f4a2713aSLionel Sambuc     }
1169f4a2713aSLionel Sambuc 
1170f4a2713aSLionel Sambuc     if (Tok.isNot(tok::identifier)) {
1171*0a6a1f1dSLionel Sambuc       Diag(Tok, diag::err_expected) << tok::identifier;
1172f4a2713aSLionel Sambuc       SkipUntil(tok::greater, StopAtSemi);
1173f4a2713aSLionel Sambuc       return true;
1174f4a2713aSLionel Sambuc     }
1175f4a2713aSLionel Sambuc     ProtocolIdents.push_back(std::make_pair(Tok.getIdentifierInfo(),
1176f4a2713aSLionel Sambuc                                        Tok.getLocation()));
1177f4a2713aSLionel Sambuc     ProtocolLocs.push_back(Tok.getLocation());
1178f4a2713aSLionel Sambuc     ConsumeToken();
1179f4a2713aSLionel Sambuc 
1180*0a6a1f1dSLionel Sambuc     if (!TryConsumeToken(tok::comma))
1181f4a2713aSLionel Sambuc       break;
1182f4a2713aSLionel Sambuc   }
1183f4a2713aSLionel Sambuc 
1184f4a2713aSLionel Sambuc   // Consume the '>'.
1185f4a2713aSLionel Sambuc   if (ParseGreaterThanInTemplateList(EndLoc, /*ConsumeLastToken=*/true))
1186f4a2713aSLionel Sambuc     return true;
1187f4a2713aSLionel Sambuc 
1188f4a2713aSLionel Sambuc   // Convert the list of protocols identifiers into a list of protocol decls.
1189f4a2713aSLionel Sambuc   Actions.FindProtocolDeclaration(WarnOnDeclarations,
1190f4a2713aSLionel Sambuc                                   &ProtocolIdents[0], ProtocolIdents.size(),
1191f4a2713aSLionel Sambuc                                   Protocols);
1192f4a2713aSLionel Sambuc   return false;
1193f4a2713aSLionel Sambuc }
1194f4a2713aSLionel Sambuc 
1195f4a2713aSLionel Sambuc /// \brief Parse the Objective-C protocol qualifiers that follow a typename
1196f4a2713aSLionel Sambuc /// in a decl-specifier-seq, starting at the '<'.
ParseObjCProtocolQualifiers(DeclSpec & DS)1197f4a2713aSLionel Sambuc bool Parser::ParseObjCProtocolQualifiers(DeclSpec &DS) {
1198f4a2713aSLionel Sambuc   assert(Tok.is(tok::less) && "Protocol qualifiers start with '<'");
1199f4a2713aSLionel Sambuc   assert(getLangOpts().ObjC1 && "Protocol qualifiers only exist in Objective-C");
1200f4a2713aSLionel Sambuc   SourceLocation LAngleLoc, EndProtoLoc;
1201f4a2713aSLionel Sambuc   SmallVector<Decl *, 8> ProtocolDecl;
1202f4a2713aSLionel Sambuc   SmallVector<SourceLocation, 8> ProtocolLocs;
1203f4a2713aSLionel Sambuc   bool Result = ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false,
1204f4a2713aSLionel Sambuc                                             LAngleLoc, EndProtoLoc);
1205f4a2713aSLionel Sambuc   DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size(),
1206f4a2713aSLionel Sambuc                            ProtocolLocs.data(), LAngleLoc);
1207f4a2713aSLionel Sambuc   if (EndProtoLoc.isValid())
1208f4a2713aSLionel Sambuc     DS.SetRangeEnd(EndProtoLoc);
1209f4a2713aSLionel Sambuc   return Result;
1210f4a2713aSLionel Sambuc }
1211f4a2713aSLionel Sambuc 
HelperActionsForIvarDeclarations(Decl * interfaceDecl,SourceLocation atLoc,BalancedDelimiterTracker & T,SmallVectorImpl<Decl * > & AllIvarDecls,bool RBraceMissing)1212f4a2713aSLionel Sambuc void Parser::HelperActionsForIvarDeclarations(Decl *interfaceDecl, SourceLocation atLoc,
1213f4a2713aSLionel Sambuc                                  BalancedDelimiterTracker &T,
1214f4a2713aSLionel Sambuc                                  SmallVectorImpl<Decl *> &AllIvarDecls,
1215f4a2713aSLionel Sambuc                                  bool RBraceMissing) {
1216f4a2713aSLionel Sambuc   if (!RBraceMissing)
1217f4a2713aSLionel Sambuc     T.consumeClose();
1218f4a2713aSLionel Sambuc 
1219f4a2713aSLionel Sambuc   Actions.ActOnObjCContainerStartDefinition(interfaceDecl);
1220f4a2713aSLionel Sambuc   Actions.ActOnLastBitfield(T.getCloseLocation(), AllIvarDecls);
1221f4a2713aSLionel Sambuc   Actions.ActOnObjCContainerFinishDefinition();
1222f4a2713aSLionel Sambuc   // Call ActOnFields() even if we don't have any decls. This is useful
1223f4a2713aSLionel Sambuc   // for code rewriting tools that need to be aware of the empty list.
1224f4a2713aSLionel Sambuc   Actions.ActOnFields(getCurScope(), atLoc, interfaceDecl,
1225f4a2713aSLionel Sambuc                       AllIvarDecls,
1226*0a6a1f1dSLionel Sambuc                       T.getOpenLocation(), T.getCloseLocation(), nullptr);
1227f4a2713aSLionel Sambuc }
1228f4a2713aSLionel Sambuc 
1229f4a2713aSLionel Sambuc ///   objc-class-instance-variables:
1230f4a2713aSLionel Sambuc ///     '{' objc-instance-variable-decl-list[opt] '}'
1231f4a2713aSLionel Sambuc ///
1232f4a2713aSLionel Sambuc ///   objc-instance-variable-decl-list:
1233f4a2713aSLionel Sambuc ///     objc-visibility-spec
1234f4a2713aSLionel Sambuc ///     objc-instance-variable-decl ';'
1235f4a2713aSLionel Sambuc ///     ';'
1236f4a2713aSLionel Sambuc ///     objc-instance-variable-decl-list objc-visibility-spec
1237f4a2713aSLionel Sambuc ///     objc-instance-variable-decl-list objc-instance-variable-decl ';'
1238f4a2713aSLionel Sambuc ///     objc-instance-variable-decl-list ';'
1239f4a2713aSLionel Sambuc ///
1240f4a2713aSLionel Sambuc ///   objc-visibility-spec:
1241f4a2713aSLionel Sambuc ///     @private
1242f4a2713aSLionel Sambuc ///     @protected
1243f4a2713aSLionel Sambuc ///     @public
1244f4a2713aSLionel Sambuc ///     @package [OBJC2]
1245f4a2713aSLionel Sambuc ///
1246f4a2713aSLionel Sambuc ///   objc-instance-variable-decl:
1247f4a2713aSLionel Sambuc ///     struct-declaration
1248f4a2713aSLionel Sambuc ///
ParseObjCClassInstanceVariables(Decl * interfaceDecl,tok::ObjCKeywordKind visibility,SourceLocation atLoc)1249f4a2713aSLionel Sambuc void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl,
1250f4a2713aSLionel Sambuc                                              tok::ObjCKeywordKind visibility,
1251f4a2713aSLionel Sambuc                                              SourceLocation atLoc) {
1252f4a2713aSLionel Sambuc   assert(Tok.is(tok::l_brace) && "expected {");
1253f4a2713aSLionel Sambuc   SmallVector<Decl *, 32> AllIvarDecls;
1254f4a2713aSLionel Sambuc 
1255f4a2713aSLionel Sambuc   ParseScope ClassScope(this, Scope::DeclScope|Scope::ClassScope);
1256f4a2713aSLionel Sambuc   ObjCDeclContextSwitch ObjCDC(*this);
1257f4a2713aSLionel Sambuc 
1258f4a2713aSLionel Sambuc   BalancedDelimiterTracker T(*this, tok::l_brace);
1259f4a2713aSLionel Sambuc   T.consumeOpen();
1260f4a2713aSLionel Sambuc   // While we still have something to read, read the instance variables.
1261*0a6a1f1dSLionel Sambuc   while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
1262f4a2713aSLionel Sambuc     // Each iteration of this loop reads one objc-instance-variable-decl.
1263f4a2713aSLionel Sambuc 
1264f4a2713aSLionel Sambuc     // Check for extraneous top-level semicolon.
1265f4a2713aSLionel Sambuc     if (Tok.is(tok::semi)) {
1266f4a2713aSLionel Sambuc       ConsumeExtraSemi(InstanceVariableList);
1267f4a2713aSLionel Sambuc       continue;
1268f4a2713aSLionel Sambuc     }
1269f4a2713aSLionel Sambuc 
1270f4a2713aSLionel Sambuc     // Set the default visibility to private.
1271*0a6a1f1dSLionel Sambuc     if (TryConsumeToken(tok::at)) { // parse objc-visibility-spec
1272f4a2713aSLionel Sambuc       if (Tok.is(tok::code_completion)) {
1273f4a2713aSLionel Sambuc         Actions.CodeCompleteObjCAtVisibility(getCurScope());
1274f4a2713aSLionel Sambuc         return cutOffParsing();
1275f4a2713aSLionel Sambuc       }
1276f4a2713aSLionel Sambuc 
1277f4a2713aSLionel Sambuc       switch (Tok.getObjCKeywordID()) {
1278f4a2713aSLionel Sambuc       case tok::objc_private:
1279f4a2713aSLionel Sambuc       case tok::objc_public:
1280f4a2713aSLionel Sambuc       case tok::objc_protected:
1281f4a2713aSLionel Sambuc       case tok::objc_package:
1282f4a2713aSLionel Sambuc         visibility = Tok.getObjCKeywordID();
1283f4a2713aSLionel Sambuc         ConsumeToken();
1284f4a2713aSLionel Sambuc         continue;
1285f4a2713aSLionel Sambuc 
1286f4a2713aSLionel Sambuc       case tok::objc_end:
1287f4a2713aSLionel Sambuc         Diag(Tok, diag::err_objc_unexpected_atend);
1288f4a2713aSLionel Sambuc         Tok.setLocation(Tok.getLocation().getLocWithOffset(-1));
1289f4a2713aSLionel Sambuc         Tok.setKind(tok::at);
1290f4a2713aSLionel Sambuc         Tok.setLength(1);
1291f4a2713aSLionel Sambuc         PP.EnterToken(Tok);
1292f4a2713aSLionel Sambuc         HelperActionsForIvarDeclarations(interfaceDecl, atLoc,
1293f4a2713aSLionel Sambuc                                          T, AllIvarDecls, true);
1294f4a2713aSLionel Sambuc         return;
1295f4a2713aSLionel Sambuc 
1296f4a2713aSLionel Sambuc       default:
1297f4a2713aSLionel Sambuc         Diag(Tok, diag::err_objc_illegal_visibility_spec);
1298f4a2713aSLionel Sambuc         continue;
1299f4a2713aSLionel Sambuc       }
1300f4a2713aSLionel Sambuc     }
1301f4a2713aSLionel Sambuc 
1302f4a2713aSLionel Sambuc     if (Tok.is(tok::code_completion)) {
1303f4a2713aSLionel Sambuc       Actions.CodeCompleteOrdinaryName(getCurScope(),
1304f4a2713aSLionel Sambuc                                        Sema::PCC_ObjCInstanceVariableList);
1305f4a2713aSLionel Sambuc       return cutOffParsing();
1306f4a2713aSLionel Sambuc     }
1307f4a2713aSLionel Sambuc 
1308*0a6a1f1dSLionel Sambuc     auto ObjCIvarCallback = [&](ParsingFieldDeclarator &FD) {
1309*0a6a1f1dSLionel Sambuc       Actions.ActOnObjCContainerStartDefinition(interfaceDecl);
1310f4a2713aSLionel Sambuc       // Install the declarator into the interface decl.
1311*0a6a1f1dSLionel Sambuc       Decl *Field = Actions.ActOnIvar(
1312*0a6a1f1dSLionel Sambuc           getCurScope(), FD.D.getDeclSpec().getSourceRange().getBegin(), FD.D,
1313*0a6a1f1dSLionel Sambuc           FD.BitfieldSize, visibility);
1314*0a6a1f1dSLionel Sambuc       Actions.ActOnObjCContainerFinishDefinition();
1315f4a2713aSLionel Sambuc       if (Field)
1316f4a2713aSLionel Sambuc         AllIvarDecls.push_back(Field);
1317f4a2713aSLionel Sambuc       FD.complete(Field);
1318*0a6a1f1dSLionel Sambuc     };
1319f4a2713aSLionel Sambuc 
1320f4a2713aSLionel Sambuc     // Parse all the comma separated declarators.
1321f4a2713aSLionel Sambuc     ParsingDeclSpec DS(*this);
1322*0a6a1f1dSLionel Sambuc     ParseStructDeclaration(DS, ObjCIvarCallback);
1323f4a2713aSLionel Sambuc 
1324f4a2713aSLionel Sambuc     if (Tok.is(tok::semi)) {
1325f4a2713aSLionel Sambuc       ConsumeToken();
1326f4a2713aSLionel Sambuc     } else {
1327f4a2713aSLionel Sambuc       Diag(Tok, diag::err_expected_semi_decl_list);
1328f4a2713aSLionel Sambuc       // Skip to end of block or statement
1329f4a2713aSLionel Sambuc       SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
1330f4a2713aSLionel Sambuc     }
1331f4a2713aSLionel Sambuc   }
1332f4a2713aSLionel Sambuc   HelperActionsForIvarDeclarations(interfaceDecl, atLoc,
1333f4a2713aSLionel Sambuc                                    T, AllIvarDecls, false);
1334f4a2713aSLionel Sambuc   return;
1335f4a2713aSLionel Sambuc }
1336f4a2713aSLionel Sambuc 
1337f4a2713aSLionel Sambuc ///   objc-protocol-declaration:
1338f4a2713aSLionel Sambuc ///     objc-protocol-definition
1339f4a2713aSLionel Sambuc ///     objc-protocol-forward-reference
1340f4a2713aSLionel Sambuc ///
1341f4a2713aSLionel Sambuc ///   objc-protocol-definition:
1342f4a2713aSLionel Sambuc ///     \@protocol identifier
1343f4a2713aSLionel Sambuc ///       objc-protocol-refs[opt]
1344f4a2713aSLionel Sambuc ///       objc-interface-decl-list
1345f4a2713aSLionel Sambuc ///     \@end
1346f4a2713aSLionel Sambuc ///
1347f4a2713aSLionel Sambuc ///   objc-protocol-forward-reference:
1348f4a2713aSLionel Sambuc ///     \@protocol identifier-list ';'
1349f4a2713aSLionel Sambuc ///
1350f4a2713aSLionel Sambuc ///   "\@protocol identifier ;" should be resolved as "\@protocol
1351f4a2713aSLionel Sambuc ///   identifier-list ;": objc-interface-decl-list may not start with a
1352f4a2713aSLionel Sambuc ///   semicolon in the first alternative if objc-protocol-refs are omitted.
1353f4a2713aSLionel Sambuc Parser::DeclGroupPtrTy
ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,ParsedAttributes & attrs)1354f4a2713aSLionel Sambuc Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
1355f4a2713aSLionel Sambuc                                        ParsedAttributes &attrs) {
1356f4a2713aSLionel Sambuc   assert(Tok.isObjCAtKeyword(tok::objc_protocol) &&
1357f4a2713aSLionel Sambuc          "ParseObjCAtProtocolDeclaration(): Expected @protocol");
1358f4a2713aSLionel Sambuc   ConsumeToken(); // the "protocol" identifier
1359f4a2713aSLionel Sambuc 
1360f4a2713aSLionel Sambuc   if (Tok.is(tok::code_completion)) {
1361f4a2713aSLionel Sambuc     Actions.CodeCompleteObjCProtocolDecl(getCurScope());
1362f4a2713aSLionel Sambuc     cutOffParsing();
1363f4a2713aSLionel Sambuc     return DeclGroupPtrTy();
1364f4a2713aSLionel Sambuc   }
1365f4a2713aSLionel Sambuc 
1366f4a2713aSLionel Sambuc   MaybeSkipAttributes(tok::objc_protocol);
1367f4a2713aSLionel Sambuc 
1368f4a2713aSLionel Sambuc   if (Tok.isNot(tok::identifier)) {
1369*0a6a1f1dSLionel Sambuc     Diag(Tok, diag::err_expected) << tok::identifier; // missing protocol name.
1370f4a2713aSLionel Sambuc     return DeclGroupPtrTy();
1371f4a2713aSLionel Sambuc   }
1372f4a2713aSLionel Sambuc   // Save the protocol name, then consume it.
1373f4a2713aSLionel Sambuc   IdentifierInfo *protocolName = Tok.getIdentifierInfo();
1374f4a2713aSLionel Sambuc   SourceLocation nameLoc = ConsumeToken();
1375f4a2713aSLionel Sambuc 
1376*0a6a1f1dSLionel Sambuc   if (TryConsumeToken(tok::semi)) { // forward declaration of one protocol.
1377f4a2713aSLionel Sambuc     IdentifierLocPair ProtoInfo(protocolName, nameLoc);
1378f4a2713aSLionel Sambuc     return Actions.ActOnForwardProtocolDeclaration(AtLoc, &ProtoInfo, 1,
1379f4a2713aSLionel Sambuc                                                    attrs.getList());
1380f4a2713aSLionel Sambuc   }
1381f4a2713aSLionel Sambuc 
1382f4a2713aSLionel Sambuc   CheckNestedObjCContexts(AtLoc);
1383f4a2713aSLionel Sambuc 
1384f4a2713aSLionel Sambuc   if (Tok.is(tok::comma)) { // list of forward declarations.
1385f4a2713aSLionel Sambuc     SmallVector<IdentifierLocPair, 8> ProtocolRefs;
1386f4a2713aSLionel Sambuc     ProtocolRefs.push_back(std::make_pair(protocolName, nameLoc));
1387f4a2713aSLionel Sambuc 
1388f4a2713aSLionel Sambuc     // Parse the list of forward declarations.
1389f4a2713aSLionel Sambuc     while (1) {
1390f4a2713aSLionel Sambuc       ConsumeToken(); // the ','
1391f4a2713aSLionel Sambuc       if (Tok.isNot(tok::identifier)) {
1392*0a6a1f1dSLionel Sambuc         Diag(Tok, diag::err_expected) << tok::identifier;
1393f4a2713aSLionel Sambuc         SkipUntil(tok::semi);
1394f4a2713aSLionel Sambuc         return DeclGroupPtrTy();
1395f4a2713aSLionel Sambuc       }
1396f4a2713aSLionel Sambuc       ProtocolRefs.push_back(IdentifierLocPair(Tok.getIdentifierInfo(),
1397f4a2713aSLionel Sambuc                                                Tok.getLocation()));
1398f4a2713aSLionel Sambuc       ConsumeToken(); // the identifier
1399f4a2713aSLionel Sambuc 
1400f4a2713aSLionel Sambuc       if (Tok.isNot(tok::comma))
1401f4a2713aSLionel Sambuc         break;
1402f4a2713aSLionel Sambuc     }
1403f4a2713aSLionel Sambuc     // Consume the ';'.
1404*0a6a1f1dSLionel Sambuc     if (ExpectAndConsume(tok::semi, diag::err_expected_after, "@protocol"))
1405f4a2713aSLionel Sambuc       return DeclGroupPtrTy();
1406f4a2713aSLionel Sambuc 
1407f4a2713aSLionel Sambuc     return Actions.ActOnForwardProtocolDeclaration(AtLoc,
1408f4a2713aSLionel Sambuc                                                    &ProtocolRefs[0],
1409f4a2713aSLionel Sambuc                                                    ProtocolRefs.size(),
1410f4a2713aSLionel Sambuc                                                    attrs.getList());
1411f4a2713aSLionel Sambuc   }
1412f4a2713aSLionel Sambuc 
1413f4a2713aSLionel Sambuc   // Last, and definitely not least, parse a protocol declaration.
1414f4a2713aSLionel Sambuc   SourceLocation LAngleLoc, EndProtoLoc;
1415f4a2713aSLionel Sambuc 
1416f4a2713aSLionel Sambuc   SmallVector<Decl *, 8> ProtocolRefs;
1417f4a2713aSLionel Sambuc   SmallVector<SourceLocation, 8> ProtocolLocs;
1418f4a2713aSLionel Sambuc   if (Tok.is(tok::less) &&
1419f4a2713aSLionel Sambuc       ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, false,
1420f4a2713aSLionel Sambuc                                   LAngleLoc, EndProtoLoc))
1421f4a2713aSLionel Sambuc     return DeclGroupPtrTy();
1422f4a2713aSLionel Sambuc 
1423f4a2713aSLionel Sambuc   Decl *ProtoType =
1424f4a2713aSLionel Sambuc     Actions.ActOnStartProtocolInterface(AtLoc, protocolName, nameLoc,
1425f4a2713aSLionel Sambuc                                         ProtocolRefs.data(),
1426f4a2713aSLionel Sambuc                                         ProtocolRefs.size(),
1427f4a2713aSLionel Sambuc                                         ProtocolLocs.data(),
1428f4a2713aSLionel Sambuc                                         EndProtoLoc, attrs.getList());
1429f4a2713aSLionel Sambuc 
1430f4a2713aSLionel Sambuc   ParseObjCInterfaceDeclList(tok::objc_protocol, ProtoType);
1431f4a2713aSLionel Sambuc   return Actions.ConvertDeclToDeclGroup(ProtoType);
1432f4a2713aSLionel Sambuc }
1433f4a2713aSLionel Sambuc 
1434f4a2713aSLionel Sambuc ///   objc-implementation:
1435f4a2713aSLionel Sambuc ///     objc-class-implementation-prologue
1436f4a2713aSLionel Sambuc ///     objc-category-implementation-prologue
1437f4a2713aSLionel Sambuc ///
1438f4a2713aSLionel Sambuc ///   objc-class-implementation-prologue:
1439f4a2713aSLionel Sambuc ///     @implementation identifier objc-superclass[opt]
1440f4a2713aSLionel Sambuc ///       objc-class-instance-variables[opt]
1441f4a2713aSLionel Sambuc ///
1442f4a2713aSLionel Sambuc ///   objc-category-implementation-prologue:
1443f4a2713aSLionel Sambuc ///     @implementation identifier ( identifier )
1444f4a2713aSLionel Sambuc Parser::DeclGroupPtrTy
ParseObjCAtImplementationDeclaration(SourceLocation AtLoc)1445f4a2713aSLionel Sambuc Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc) {
1446f4a2713aSLionel Sambuc   assert(Tok.isObjCAtKeyword(tok::objc_implementation) &&
1447f4a2713aSLionel Sambuc          "ParseObjCAtImplementationDeclaration(): Expected @implementation");
1448f4a2713aSLionel Sambuc   CheckNestedObjCContexts(AtLoc);
1449f4a2713aSLionel Sambuc   ConsumeToken(); // the "implementation" identifier
1450f4a2713aSLionel Sambuc 
1451f4a2713aSLionel Sambuc   // Code completion after '@implementation'.
1452f4a2713aSLionel Sambuc   if (Tok.is(tok::code_completion)) {
1453f4a2713aSLionel Sambuc     Actions.CodeCompleteObjCImplementationDecl(getCurScope());
1454f4a2713aSLionel Sambuc     cutOffParsing();
1455f4a2713aSLionel Sambuc     return DeclGroupPtrTy();
1456f4a2713aSLionel Sambuc   }
1457f4a2713aSLionel Sambuc 
1458f4a2713aSLionel Sambuc   MaybeSkipAttributes(tok::objc_implementation);
1459f4a2713aSLionel Sambuc 
1460f4a2713aSLionel Sambuc   if (Tok.isNot(tok::identifier)) {
1461*0a6a1f1dSLionel Sambuc     Diag(Tok, diag::err_expected)
1462*0a6a1f1dSLionel Sambuc         << tok::identifier; // missing class or category name.
1463f4a2713aSLionel Sambuc     return DeclGroupPtrTy();
1464f4a2713aSLionel Sambuc   }
1465f4a2713aSLionel Sambuc   // We have a class or category name - consume it.
1466f4a2713aSLionel Sambuc   IdentifierInfo *nameId = Tok.getIdentifierInfo();
1467f4a2713aSLionel Sambuc   SourceLocation nameLoc = ConsumeToken(); // consume class or category name
1468*0a6a1f1dSLionel Sambuc   Decl *ObjCImpDecl = nullptr;
1469f4a2713aSLionel Sambuc 
1470f4a2713aSLionel Sambuc   if (Tok.is(tok::l_paren)) {
1471f4a2713aSLionel Sambuc     // we have a category implementation.
1472f4a2713aSLionel Sambuc     ConsumeParen();
1473f4a2713aSLionel Sambuc     SourceLocation categoryLoc, rparenLoc;
1474*0a6a1f1dSLionel Sambuc     IdentifierInfo *categoryId = nullptr;
1475f4a2713aSLionel Sambuc 
1476f4a2713aSLionel Sambuc     if (Tok.is(tok::code_completion)) {
1477f4a2713aSLionel Sambuc       Actions.CodeCompleteObjCImplementationCategory(getCurScope(), nameId, nameLoc);
1478f4a2713aSLionel Sambuc       cutOffParsing();
1479f4a2713aSLionel Sambuc       return DeclGroupPtrTy();
1480f4a2713aSLionel Sambuc     }
1481f4a2713aSLionel Sambuc 
1482f4a2713aSLionel Sambuc     if (Tok.is(tok::identifier)) {
1483f4a2713aSLionel Sambuc       categoryId = Tok.getIdentifierInfo();
1484f4a2713aSLionel Sambuc       categoryLoc = ConsumeToken();
1485f4a2713aSLionel Sambuc     } else {
1486*0a6a1f1dSLionel Sambuc       Diag(Tok, diag::err_expected)
1487*0a6a1f1dSLionel Sambuc           << tok::identifier; // missing category name.
1488f4a2713aSLionel Sambuc       return DeclGroupPtrTy();
1489f4a2713aSLionel Sambuc     }
1490f4a2713aSLionel Sambuc     if (Tok.isNot(tok::r_paren)) {
1491*0a6a1f1dSLionel Sambuc       Diag(Tok, diag::err_expected) << tok::r_paren;
1492f4a2713aSLionel Sambuc       SkipUntil(tok::r_paren); // don't stop at ';'
1493f4a2713aSLionel Sambuc       return DeclGroupPtrTy();
1494f4a2713aSLionel Sambuc     }
1495f4a2713aSLionel Sambuc     rparenLoc = ConsumeParen();
1496f4a2713aSLionel Sambuc     if (Tok.is(tok::less)) { // we have illegal '<' try to recover
1497f4a2713aSLionel Sambuc       Diag(Tok, diag::err_unexpected_protocol_qualifier);
1498f4a2713aSLionel Sambuc       AttributeFactory attr;
1499f4a2713aSLionel Sambuc       DeclSpec DS(attr);
1500f4a2713aSLionel Sambuc       (void)ParseObjCProtocolQualifiers(DS);
1501f4a2713aSLionel Sambuc     }
1502f4a2713aSLionel Sambuc     ObjCImpDecl = Actions.ActOnStartCategoryImplementation(
1503f4a2713aSLionel Sambuc                                     AtLoc, nameId, nameLoc, categoryId,
1504f4a2713aSLionel Sambuc                                     categoryLoc);
1505f4a2713aSLionel Sambuc 
1506f4a2713aSLionel Sambuc   } else {
1507f4a2713aSLionel Sambuc     // We have a class implementation
1508f4a2713aSLionel Sambuc     SourceLocation superClassLoc;
1509*0a6a1f1dSLionel Sambuc     IdentifierInfo *superClassId = nullptr;
1510*0a6a1f1dSLionel Sambuc     if (TryConsumeToken(tok::colon)) {
1511f4a2713aSLionel Sambuc       // We have a super class
1512f4a2713aSLionel Sambuc       if (Tok.isNot(tok::identifier)) {
1513*0a6a1f1dSLionel Sambuc         Diag(Tok, diag::err_expected)
1514*0a6a1f1dSLionel Sambuc             << tok::identifier; // missing super class name.
1515f4a2713aSLionel Sambuc         return DeclGroupPtrTy();
1516f4a2713aSLionel Sambuc       }
1517f4a2713aSLionel Sambuc       superClassId = Tok.getIdentifierInfo();
1518f4a2713aSLionel Sambuc       superClassLoc = ConsumeToken(); // Consume super class name
1519f4a2713aSLionel Sambuc     }
1520f4a2713aSLionel Sambuc     ObjCImpDecl = Actions.ActOnStartClassImplementation(
1521f4a2713aSLionel Sambuc                                     AtLoc, nameId, nameLoc,
1522f4a2713aSLionel Sambuc                                     superClassId, superClassLoc);
1523f4a2713aSLionel Sambuc 
1524f4a2713aSLionel Sambuc     if (Tok.is(tok::l_brace)) // we have ivars
1525f4a2713aSLionel Sambuc       ParseObjCClassInstanceVariables(ObjCImpDecl, tok::objc_private, AtLoc);
1526f4a2713aSLionel Sambuc     else if (Tok.is(tok::less)) { // we have illegal '<' try to recover
1527f4a2713aSLionel Sambuc       Diag(Tok, diag::err_unexpected_protocol_qualifier);
1528f4a2713aSLionel Sambuc       // try to recover.
1529f4a2713aSLionel Sambuc       AttributeFactory attr;
1530f4a2713aSLionel Sambuc       DeclSpec DS(attr);
1531f4a2713aSLionel Sambuc       (void)ParseObjCProtocolQualifiers(DS);
1532f4a2713aSLionel Sambuc     }
1533f4a2713aSLionel Sambuc   }
1534f4a2713aSLionel Sambuc   assert(ObjCImpDecl);
1535f4a2713aSLionel Sambuc 
1536f4a2713aSLionel Sambuc   SmallVector<Decl *, 8> DeclsInGroup;
1537f4a2713aSLionel Sambuc 
1538f4a2713aSLionel Sambuc   {
1539f4a2713aSLionel Sambuc     ObjCImplParsingDataRAII ObjCImplParsing(*this, ObjCImpDecl);
1540*0a6a1f1dSLionel Sambuc     while (!ObjCImplParsing.isFinished() && !isEofOrEom()) {
1541f4a2713aSLionel Sambuc       ParsedAttributesWithRange attrs(AttrFactory);
1542f4a2713aSLionel Sambuc       MaybeParseCXX11Attributes(attrs);
1543f4a2713aSLionel Sambuc       MaybeParseMicrosoftAttributes(attrs);
1544f4a2713aSLionel Sambuc       if (DeclGroupPtrTy DGP = ParseExternalDeclaration(attrs)) {
1545f4a2713aSLionel Sambuc         DeclGroupRef DG = DGP.get();
1546f4a2713aSLionel Sambuc         DeclsInGroup.append(DG.begin(), DG.end());
1547f4a2713aSLionel Sambuc       }
1548f4a2713aSLionel Sambuc     }
1549f4a2713aSLionel Sambuc   }
1550f4a2713aSLionel Sambuc 
1551f4a2713aSLionel Sambuc   return Actions.ActOnFinishObjCImplementation(ObjCImpDecl, DeclsInGroup);
1552f4a2713aSLionel Sambuc }
1553f4a2713aSLionel Sambuc 
1554f4a2713aSLionel Sambuc Parser::DeclGroupPtrTy
ParseObjCAtEndDeclaration(SourceRange atEnd)1555f4a2713aSLionel Sambuc Parser::ParseObjCAtEndDeclaration(SourceRange atEnd) {
1556f4a2713aSLionel Sambuc   assert(Tok.isObjCAtKeyword(tok::objc_end) &&
1557f4a2713aSLionel Sambuc          "ParseObjCAtEndDeclaration(): Expected @end");
1558f4a2713aSLionel Sambuc   ConsumeToken(); // the "end" identifier
1559f4a2713aSLionel Sambuc   if (CurParsedObjCImpl)
1560f4a2713aSLionel Sambuc     CurParsedObjCImpl->finish(atEnd);
1561f4a2713aSLionel Sambuc   else
1562f4a2713aSLionel Sambuc     // missing @implementation
1563f4a2713aSLionel Sambuc     Diag(atEnd.getBegin(), diag::err_expected_objc_container);
1564f4a2713aSLionel Sambuc   return DeclGroupPtrTy();
1565f4a2713aSLionel Sambuc }
1566f4a2713aSLionel Sambuc 
~ObjCImplParsingDataRAII()1567f4a2713aSLionel Sambuc Parser::ObjCImplParsingDataRAII::~ObjCImplParsingDataRAII() {
1568f4a2713aSLionel Sambuc   if (!Finished) {
1569f4a2713aSLionel Sambuc     finish(P.Tok.getLocation());
1570*0a6a1f1dSLionel Sambuc     if (P.isEofOrEom()) {
1571f4a2713aSLionel Sambuc       P.Diag(P.Tok, diag::err_objc_missing_end)
1572f4a2713aSLionel Sambuc           << FixItHint::CreateInsertion(P.Tok.getLocation(), "\n@end\n");
1573f4a2713aSLionel Sambuc       P.Diag(Dcl->getLocStart(), diag::note_objc_container_start)
1574f4a2713aSLionel Sambuc           << Sema::OCK_Implementation;
1575f4a2713aSLionel Sambuc     }
1576f4a2713aSLionel Sambuc   }
1577*0a6a1f1dSLionel Sambuc   P.CurParsedObjCImpl = nullptr;
1578f4a2713aSLionel Sambuc   assert(LateParsedObjCMethods.empty());
1579f4a2713aSLionel Sambuc }
1580f4a2713aSLionel Sambuc 
finish(SourceRange AtEnd)1581f4a2713aSLionel Sambuc void Parser::ObjCImplParsingDataRAII::finish(SourceRange AtEnd) {
1582f4a2713aSLionel Sambuc   assert(!Finished);
1583f4a2713aSLionel Sambuc   P.Actions.DefaultSynthesizeProperties(P.getCurScope(), Dcl);
1584f4a2713aSLionel Sambuc   for (size_t i = 0; i < LateParsedObjCMethods.size(); ++i)
1585f4a2713aSLionel Sambuc     P.ParseLexedObjCMethodDefs(*LateParsedObjCMethods[i],
1586f4a2713aSLionel Sambuc                                true/*Methods*/);
1587f4a2713aSLionel Sambuc 
1588f4a2713aSLionel Sambuc   P.Actions.ActOnAtEnd(P.getCurScope(), AtEnd);
1589f4a2713aSLionel Sambuc 
1590f4a2713aSLionel Sambuc   if (HasCFunction)
1591f4a2713aSLionel Sambuc     for (size_t i = 0; i < LateParsedObjCMethods.size(); ++i)
1592f4a2713aSLionel Sambuc       P.ParseLexedObjCMethodDefs(*LateParsedObjCMethods[i],
1593f4a2713aSLionel Sambuc                                  false/*c-functions*/);
1594f4a2713aSLionel Sambuc 
1595f4a2713aSLionel Sambuc   /// \brief Clear and free the cached objc methods.
1596f4a2713aSLionel Sambuc   for (LateParsedObjCMethodContainer::iterator
1597f4a2713aSLionel Sambuc          I = LateParsedObjCMethods.begin(),
1598f4a2713aSLionel Sambuc          E = LateParsedObjCMethods.end(); I != E; ++I)
1599f4a2713aSLionel Sambuc     delete *I;
1600f4a2713aSLionel Sambuc   LateParsedObjCMethods.clear();
1601f4a2713aSLionel Sambuc 
1602f4a2713aSLionel Sambuc   Finished = true;
1603f4a2713aSLionel Sambuc }
1604f4a2713aSLionel Sambuc 
1605f4a2713aSLionel Sambuc ///   compatibility-alias-decl:
1606f4a2713aSLionel Sambuc ///     @compatibility_alias alias-name  class-name ';'
1607f4a2713aSLionel Sambuc ///
ParseObjCAtAliasDeclaration(SourceLocation atLoc)1608f4a2713aSLionel Sambuc Decl *Parser::ParseObjCAtAliasDeclaration(SourceLocation atLoc) {
1609f4a2713aSLionel Sambuc   assert(Tok.isObjCAtKeyword(tok::objc_compatibility_alias) &&
1610f4a2713aSLionel Sambuc          "ParseObjCAtAliasDeclaration(): Expected @compatibility_alias");
1611f4a2713aSLionel Sambuc   ConsumeToken(); // consume compatibility_alias
1612f4a2713aSLionel Sambuc   if (Tok.isNot(tok::identifier)) {
1613*0a6a1f1dSLionel Sambuc     Diag(Tok, diag::err_expected) << tok::identifier;
1614*0a6a1f1dSLionel Sambuc     return nullptr;
1615f4a2713aSLionel Sambuc   }
1616f4a2713aSLionel Sambuc   IdentifierInfo *aliasId = Tok.getIdentifierInfo();
1617f4a2713aSLionel Sambuc   SourceLocation aliasLoc = ConsumeToken(); // consume alias-name
1618f4a2713aSLionel Sambuc   if (Tok.isNot(tok::identifier)) {
1619*0a6a1f1dSLionel Sambuc     Diag(Tok, diag::err_expected) << tok::identifier;
1620*0a6a1f1dSLionel Sambuc     return nullptr;
1621f4a2713aSLionel Sambuc   }
1622f4a2713aSLionel Sambuc   IdentifierInfo *classId = Tok.getIdentifierInfo();
1623f4a2713aSLionel Sambuc   SourceLocation classLoc = ConsumeToken(); // consume class-name;
1624*0a6a1f1dSLionel Sambuc   ExpectAndConsume(tok::semi, diag::err_expected_after, "@compatibility_alias");
1625f4a2713aSLionel Sambuc   return Actions.ActOnCompatibilityAlias(atLoc, aliasId, aliasLoc,
1626f4a2713aSLionel Sambuc                                          classId, classLoc);
1627f4a2713aSLionel Sambuc }
1628f4a2713aSLionel Sambuc 
1629f4a2713aSLionel Sambuc ///   property-synthesis:
1630f4a2713aSLionel Sambuc ///     @synthesize property-ivar-list ';'
1631f4a2713aSLionel Sambuc ///
1632f4a2713aSLionel Sambuc ///   property-ivar-list:
1633f4a2713aSLionel Sambuc ///     property-ivar
1634f4a2713aSLionel Sambuc ///     property-ivar-list ',' property-ivar
1635f4a2713aSLionel Sambuc ///
1636f4a2713aSLionel Sambuc ///   property-ivar:
1637f4a2713aSLionel Sambuc ///     identifier
1638f4a2713aSLionel Sambuc ///     identifier '=' identifier
1639f4a2713aSLionel Sambuc ///
ParseObjCPropertySynthesize(SourceLocation atLoc)1640f4a2713aSLionel Sambuc Decl *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
1641f4a2713aSLionel Sambuc   assert(Tok.isObjCAtKeyword(tok::objc_synthesize) &&
1642f4a2713aSLionel Sambuc          "ParseObjCPropertySynthesize(): Expected '@synthesize'");
1643f4a2713aSLionel Sambuc   ConsumeToken(); // consume synthesize
1644f4a2713aSLionel Sambuc 
1645f4a2713aSLionel Sambuc   while (true) {
1646f4a2713aSLionel Sambuc     if (Tok.is(tok::code_completion)) {
1647f4a2713aSLionel Sambuc       Actions.CodeCompleteObjCPropertyDefinition(getCurScope());
1648f4a2713aSLionel Sambuc       cutOffParsing();
1649*0a6a1f1dSLionel Sambuc       return nullptr;
1650f4a2713aSLionel Sambuc     }
1651f4a2713aSLionel Sambuc 
1652f4a2713aSLionel Sambuc     if (Tok.isNot(tok::identifier)) {
1653f4a2713aSLionel Sambuc       Diag(Tok, diag::err_synthesized_property_name);
1654f4a2713aSLionel Sambuc       SkipUntil(tok::semi);
1655*0a6a1f1dSLionel Sambuc       return nullptr;
1656f4a2713aSLionel Sambuc     }
1657f4a2713aSLionel Sambuc 
1658*0a6a1f1dSLionel Sambuc     IdentifierInfo *propertyIvar = nullptr;
1659f4a2713aSLionel Sambuc     IdentifierInfo *propertyId = Tok.getIdentifierInfo();
1660f4a2713aSLionel Sambuc     SourceLocation propertyLoc = ConsumeToken(); // consume property name
1661f4a2713aSLionel Sambuc     SourceLocation propertyIvarLoc;
1662*0a6a1f1dSLionel Sambuc     if (TryConsumeToken(tok::equal)) {
1663f4a2713aSLionel Sambuc       // property '=' ivar-name
1664f4a2713aSLionel Sambuc       if (Tok.is(tok::code_completion)) {
1665f4a2713aSLionel Sambuc         Actions.CodeCompleteObjCPropertySynthesizeIvar(getCurScope(), propertyId);
1666f4a2713aSLionel Sambuc         cutOffParsing();
1667*0a6a1f1dSLionel Sambuc         return nullptr;
1668f4a2713aSLionel Sambuc       }
1669f4a2713aSLionel Sambuc 
1670f4a2713aSLionel Sambuc       if (Tok.isNot(tok::identifier)) {
1671*0a6a1f1dSLionel Sambuc         Diag(Tok, diag::err_expected) << tok::identifier;
1672f4a2713aSLionel Sambuc         break;
1673f4a2713aSLionel Sambuc       }
1674f4a2713aSLionel Sambuc       propertyIvar = Tok.getIdentifierInfo();
1675f4a2713aSLionel Sambuc       propertyIvarLoc = ConsumeToken(); // consume ivar-name
1676f4a2713aSLionel Sambuc     }
1677f4a2713aSLionel Sambuc     Actions.ActOnPropertyImplDecl(getCurScope(), atLoc, propertyLoc, true,
1678f4a2713aSLionel Sambuc                                   propertyId, propertyIvar, propertyIvarLoc);
1679f4a2713aSLionel Sambuc     if (Tok.isNot(tok::comma))
1680f4a2713aSLionel Sambuc       break;
1681f4a2713aSLionel Sambuc     ConsumeToken(); // consume ','
1682f4a2713aSLionel Sambuc   }
1683*0a6a1f1dSLionel Sambuc   ExpectAndConsume(tok::semi, diag::err_expected_after, "@synthesize");
1684*0a6a1f1dSLionel Sambuc   return nullptr;
1685f4a2713aSLionel Sambuc }
1686f4a2713aSLionel Sambuc 
1687f4a2713aSLionel Sambuc ///   property-dynamic:
1688f4a2713aSLionel Sambuc ///     @dynamic  property-list
1689f4a2713aSLionel Sambuc ///
1690f4a2713aSLionel Sambuc ///   property-list:
1691f4a2713aSLionel Sambuc ///     identifier
1692f4a2713aSLionel Sambuc ///     property-list ',' identifier
1693f4a2713aSLionel Sambuc ///
ParseObjCPropertyDynamic(SourceLocation atLoc)1694f4a2713aSLionel Sambuc Decl *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) {
1695f4a2713aSLionel Sambuc   assert(Tok.isObjCAtKeyword(tok::objc_dynamic) &&
1696f4a2713aSLionel Sambuc          "ParseObjCPropertyDynamic(): Expected '@dynamic'");
1697f4a2713aSLionel Sambuc   ConsumeToken(); // consume dynamic
1698f4a2713aSLionel Sambuc   while (true) {
1699f4a2713aSLionel Sambuc     if (Tok.is(tok::code_completion)) {
1700f4a2713aSLionel Sambuc       Actions.CodeCompleteObjCPropertyDefinition(getCurScope());
1701f4a2713aSLionel Sambuc       cutOffParsing();
1702*0a6a1f1dSLionel Sambuc       return nullptr;
1703f4a2713aSLionel Sambuc     }
1704f4a2713aSLionel Sambuc 
1705f4a2713aSLionel Sambuc     if (Tok.isNot(tok::identifier)) {
1706*0a6a1f1dSLionel Sambuc       Diag(Tok, diag::err_expected) << tok::identifier;
1707f4a2713aSLionel Sambuc       SkipUntil(tok::semi);
1708*0a6a1f1dSLionel Sambuc       return nullptr;
1709f4a2713aSLionel Sambuc     }
1710f4a2713aSLionel Sambuc 
1711f4a2713aSLionel Sambuc     IdentifierInfo *propertyId = Tok.getIdentifierInfo();
1712f4a2713aSLionel Sambuc     SourceLocation propertyLoc = ConsumeToken(); // consume property name
1713f4a2713aSLionel Sambuc     Actions.ActOnPropertyImplDecl(getCurScope(), atLoc, propertyLoc, false,
1714*0a6a1f1dSLionel Sambuc                                   propertyId, nullptr, SourceLocation());
1715f4a2713aSLionel Sambuc 
1716f4a2713aSLionel Sambuc     if (Tok.isNot(tok::comma))
1717f4a2713aSLionel Sambuc       break;
1718f4a2713aSLionel Sambuc     ConsumeToken(); // consume ','
1719f4a2713aSLionel Sambuc   }
1720*0a6a1f1dSLionel Sambuc   ExpectAndConsume(tok::semi, diag::err_expected_after, "@dynamic");
1721*0a6a1f1dSLionel Sambuc   return nullptr;
1722f4a2713aSLionel Sambuc }
1723f4a2713aSLionel Sambuc 
1724f4a2713aSLionel Sambuc ///  objc-throw-statement:
1725f4a2713aSLionel Sambuc ///    throw expression[opt];
1726f4a2713aSLionel Sambuc ///
ParseObjCThrowStmt(SourceLocation atLoc)1727f4a2713aSLionel Sambuc StmtResult Parser::ParseObjCThrowStmt(SourceLocation atLoc) {
1728f4a2713aSLionel Sambuc   ExprResult Res;
1729f4a2713aSLionel Sambuc   ConsumeToken(); // consume throw
1730f4a2713aSLionel Sambuc   if (Tok.isNot(tok::semi)) {
1731f4a2713aSLionel Sambuc     Res = ParseExpression();
1732f4a2713aSLionel Sambuc     if (Res.isInvalid()) {
1733f4a2713aSLionel Sambuc       SkipUntil(tok::semi);
1734f4a2713aSLionel Sambuc       return StmtError();
1735f4a2713aSLionel Sambuc     }
1736f4a2713aSLionel Sambuc   }
1737f4a2713aSLionel Sambuc   // consume ';'
1738*0a6a1f1dSLionel Sambuc   ExpectAndConsume(tok::semi, diag::err_expected_after, "@throw");
1739*0a6a1f1dSLionel Sambuc   return Actions.ActOnObjCAtThrowStmt(atLoc, Res.get(), getCurScope());
1740f4a2713aSLionel Sambuc }
1741f4a2713aSLionel Sambuc 
1742f4a2713aSLionel Sambuc /// objc-synchronized-statement:
1743f4a2713aSLionel Sambuc ///   @synchronized '(' expression ')' compound-statement
1744f4a2713aSLionel Sambuc ///
1745f4a2713aSLionel Sambuc StmtResult
ParseObjCSynchronizedStmt(SourceLocation atLoc)1746f4a2713aSLionel Sambuc Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) {
1747f4a2713aSLionel Sambuc   ConsumeToken(); // consume synchronized
1748f4a2713aSLionel Sambuc   if (Tok.isNot(tok::l_paren)) {
1749f4a2713aSLionel Sambuc     Diag(Tok, diag::err_expected_lparen_after) << "@synchronized";
1750f4a2713aSLionel Sambuc     return StmtError();
1751f4a2713aSLionel Sambuc   }
1752f4a2713aSLionel Sambuc 
1753f4a2713aSLionel Sambuc   // The operand is surrounded with parentheses.
1754f4a2713aSLionel Sambuc   ConsumeParen();  // '('
1755f4a2713aSLionel Sambuc   ExprResult operand(ParseExpression());
1756f4a2713aSLionel Sambuc 
1757f4a2713aSLionel Sambuc   if (Tok.is(tok::r_paren)) {
1758f4a2713aSLionel Sambuc     ConsumeParen();  // ')'
1759f4a2713aSLionel Sambuc   } else {
1760f4a2713aSLionel Sambuc     if (!operand.isInvalid())
1761*0a6a1f1dSLionel Sambuc       Diag(Tok, diag::err_expected) << tok::r_paren;
1762f4a2713aSLionel Sambuc 
1763f4a2713aSLionel Sambuc     // Skip forward until we see a left brace, but don't consume it.
1764f4a2713aSLionel Sambuc     SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch);
1765f4a2713aSLionel Sambuc   }
1766f4a2713aSLionel Sambuc 
1767f4a2713aSLionel Sambuc   // Require a compound statement.
1768f4a2713aSLionel Sambuc   if (Tok.isNot(tok::l_brace)) {
1769f4a2713aSLionel Sambuc     if (!operand.isInvalid())
1770*0a6a1f1dSLionel Sambuc       Diag(Tok, diag::err_expected) << tok::l_brace;
1771f4a2713aSLionel Sambuc     return StmtError();
1772f4a2713aSLionel Sambuc   }
1773f4a2713aSLionel Sambuc 
1774f4a2713aSLionel Sambuc   // Check the @synchronized operand now.
1775f4a2713aSLionel Sambuc   if (!operand.isInvalid())
1776*0a6a1f1dSLionel Sambuc     operand = Actions.ActOnObjCAtSynchronizedOperand(atLoc, operand.get());
1777f4a2713aSLionel Sambuc 
1778f4a2713aSLionel Sambuc   // Parse the compound statement within a new scope.
1779f4a2713aSLionel Sambuc   ParseScope bodyScope(this, Scope::DeclScope);
1780f4a2713aSLionel Sambuc   StmtResult body(ParseCompoundStatementBody());
1781f4a2713aSLionel Sambuc   bodyScope.Exit();
1782f4a2713aSLionel Sambuc 
1783f4a2713aSLionel Sambuc   // If there was a semantic or parse error earlier with the
1784f4a2713aSLionel Sambuc   // operand, fail now.
1785f4a2713aSLionel Sambuc   if (operand.isInvalid())
1786f4a2713aSLionel Sambuc     return StmtError();
1787f4a2713aSLionel Sambuc 
1788f4a2713aSLionel Sambuc   if (body.isInvalid())
1789f4a2713aSLionel Sambuc     body = Actions.ActOnNullStmt(Tok.getLocation());
1790f4a2713aSLionel Sambuc 
1791f4a2713aSLionel Sambuc   return Actions.ActOnObjCAtSynchronizedStmt(atLoc, operand.get(), body.get());
1792f4a2713aSLionel Sambuc }
1793f4a2713aSLionel Sambuc 
1794f4a2713aSLionel Sambuc ///  objc-try-catch-statement:
1795f4a2713aSLionel Sambuc ///    @try compound-statement objc-catch-list[opt]
1796f4a2713aSLionel Sambuc ///    @try compound-statement objc-catch-list[opt] @finally compound-statement
1797f4a2713aSLionel Sambuc ///
1798f4a2713aSLionel Sambuc ///  objc-catch-list:
1799f4a2713aSLionel Sambuc ///    @catch ( parameter-declaration ) compound-statement
1800f4a2713aSLionel Sambuc ///    objc-catch-list @catch ( catch-parameter-declaration ) compound-statement
1801f4a2713aSLionel Sambuc ///  catch-parameter-declaration:
1802f4a2713aSLionel Sambuc ///     parameter-declaration
1803f4a2713aSLionel Sambuc ///     '...' [OBJC2]
1804f4a2713aSLionel Sambuc ///
ParseObjCTryStmt(SourceLocation atLoc)1805f4a2713aSLionel Sambuc StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
1806f4a2713aSLionel Sambuc   bool catch_or_finally_seen = false;
1807f4a2713aSLionel Sambuc 
1808f4a2713aSLionel Sambuc   ConsumeToken(); // consume try
1809f4a2713aSLionel Sambuc   if (Tok.isNot(tok::l_brace)) {
1810*0a6a1f1dSLionel Sambuc     Diag(Tok, diag::err_expected) << tok::l_brace;
1811f4a2713aSLionel Sambuc     return StmtError();
1812f4a2713aSLionel Sambuc   }
1813f4a2713aSLionel Sambuc   StmtVector CatchStmts;
1814f4a2713aSLionel Sambuc   StmtResult FinallyStmt;
1815f4a2713aSLionel Sambuc   ParseScope TryScope(this, Scope::DeclScope);
1816f4a2713aSLionel Sambuc   StmtResult TryBody(ParseCompoundStatementBody());
1817f4a2713aSLionel Sambuc   TryScope.Exit();
1818f4a2713aSLionel Sambuc   if (TryBody.isInvalid())
1819f4a2713aSLionel Sambuc     TryBody = Actions.ActOnNullStmt(Tok.getLocation());
1820f4a2713aSLionel Sambuc 
1821f4a2713aSLionel Sambuc   while (Tok.is(tok::at)) {
1822f4a2713aSLionel Sambuc     // At this point, we need to lookahead to determine if this @ is the start
1823f4a2713aSLionel Sambuc     // of an @catch or @finally.  We don't want to consume the @ token if this
1824f4a2713aSLionel Sambuc     // is an @try or @encode or something else.
1825f4a2713aSLionel Sambuc     Token AfterAt = GetLookAheadToken(1);
1826f4a2713aSLionel Sambuc     if (!AfterAt.isObjCAtKeyword(tok::objc_catch) &&
1827f4a2713aSLionel Sambuc         !AfterAt.isObjCAtKeyword(tok::objc_finally))
1828f4a2713aSLionel Sambuc       break;
1829f4a2713aSLionel Sambuc 
1830f4a2713aSLionel Sambuc     SourceLocation AtCatchFinallyLoc = ConsumeToken();
1831f4a2713aSLionel Sambuc     if (Tok.isObjCAtKeyword(tok::objc_catch)) {
1832*0a6a1f1dSLionel Sambuc       Decl *FirstPart = nullptr;
1833f4a2713aSLionel Sambuc       ConsumeToken(); // consume catch
1834f4a2713aSLionel Sambuc       if (Tok.is(tok::l_paren)) {
1835f4a2713aSLionel Sambuc         ConsumeParen();
1836f4a2713aSLionel Sambuc         ParseScope CatchScope(this, Scope::DeclScope|Scope::AtCatchScope);
1837f4a2713aSLionel Sambuc         if (Tok.isNot(tok::ellipsis)) {
1838f4a2713aSLionel Sambuc           DeclSpec DS(AttrFactory);
1839f4a2713aSLionel Sambuc           ParseDeclarationSpecifiers(DS);
1840f4a2713aSLionel Sambuc           Declarator ParmDecl(DS, Declarator::ObjCCatchContext);
1841f4a2713aSLionel Sambuc           ParseDeclarator(ParmDecl);
1842f4a2713aSLionel Sambuc 
1843f4a2713aSLionel Sambuc           // Inform the actions module about the declarator, so it
1844f4a2713aSLionel Sambuc           // gets added to the current scope.
1845f4a2713aSLionel Sambuc           FirstPart = Actions.ActOnObjCExceptionDecl(getCurScope(), ParmDecl);
1846f4a2713aSLionel Sambuc         } else
1847f4a2713aSLionel Sambuc           ConsumeToken(); // consume '...'
1848f4a2713aSLionel Sambuc 
1849f4a2713aSLionel Sambuc         SourceLocation RParenLoc;
1850f4a2713aSLionel Sambuc 
1851f4a2713aSLionel Sambuc         if (Tok.is(tok::r_paren))
1852f4a2713aSLionel Sambuc           RParenLoc = ConsumeParen();
1853f4a2713aSLionel Sambuc         else // Skip over garbage, until we get to ')'.  Eat the ')'.
1854f4a2713aSLionel Sambuc           SkipUntil(tok::r_paren, StopAtSemi);
1855f4a2713aSLionel Sambuc 
1856f4a2713aSLionel Sambuc         StmtResult CatchBody(true);
1857f4a2713aSLionel Sambuc         if (Tok.is(tok::l_brace))
1858f4a2713aSLionel Sambuc           CatchBody = ParseCompoundStatementBody();
1859f4a2713aSLionel Sambuc         else
1860*0a6a1f1dSLionel Sambuc           Diag(Tok, diag::err_expected) << tok::l_brace;
1861f4a2713aSLionel Sambuc         if (CatchBody.isInvalid())
1862f4a2713aSLionel Sambuc           CatchBody = Actions.ActOnNullStmt(Tok.getLocation());
1863f4a2713aSLionel Sambuc 
1864f4a2713aSLionel Sambuc         StmtResult Catch = Actions.ActOnObjCAtCatchStmt(AtCatchFinallyLoc,
1865f4a2713aSLionel Sambuc                                                               RParenLoc,
1866f4a2713aSLionel Sambuc                                                               FirstPart,
1867*0a6a1f1dSLionel Sambuc                                                               CatchBody.get());
1868f4a2713aSLionel Sambuc         if (!Catch.isInvalid())
1869*0a6a1f1dSLionel Sambuc           CatchStmts.push_back(Catch.get());
1870f4a2713aSLionel Sambuc 
1871f4a2713aSLionel Sambuc       } else {
1872f4a2713aSLionel Sambuc         Diag(AtCatchFinallyLoc, diag::err_expected_lparen_after)
1873f4a2713aSLionel Sambuc           << "@catch clause";
1874f4a2713aSLionel Sambuc         return StmtError();
1875f4a2713aSLionel Sambuc       }
1876f4a2713aSLionel Sambuc       catch_or_finally_seen = true;
1877f4a2713aSLionel Sambuc     } else {
1878f4a2713aSLionel Sambuc       assert(Tok.isObjCAtKeyword(tok::objc_finally) && "Lookahead confused?");
1879f4a2713aSLionel Sambuc       ConsumeToken(); // consume finally
1880f4a2713aSLionel Sambuc       ParseScope FinallyScope(this, Scope::DeclScope);
1881f4a2713aSLionel Sambuc 
1882f4a2713aSLionel Sambuc       StmtResult FinallyBody(true);
1883f4a2713aSLionel Sambuc       if (Tok.is(tok::l_brace))
1884f4a2713aSLionel Sambuc         FinallyBody = ParseCompoundStatementBody();
1885f4a2713aSLionel Sambuc       else
1886*0a6a1f1dSLionel Sambuc         Diag(Tok, diag::err_expected) << tok::l_brace;
1887f4a2713aSLionel Sambuc       if (FinallyBody.isInvalid())
1888f4a2713aSLionel Sambuc         FinallyBody = Actions.ActOnNullStmt(Tok.getLocation());
1889f4a2713aSLionel Sambuc       FinallyStmt = Actions.ActOnObjCAtFinallyStmt(AtCatchFinallyLoc,
1890*0a6a1f1dSLionel Sambuc                                                    FinallyBody.get());
1891f4a2713aSLionel Sambuc       catch_or_finally_seen = true;
1892f4a2713aSLionel Sambuc       break;
1893f4a2713aSLionel Sambuc     }
1894f4a2713aSLionel Sambuc   }
1895f4a2713aSLionel Sambuc   if (!catch_or_finally_seen) {
1896f4a2713aSLionel Sambuc     Diag(atLoc, diag::err_missing_catch_finally);
1897f4a2713aSLionel Sambuc     return StmtError();
1898f4a2713aSLionel Sambuc   }
1899f4a2713aSLionel Sambuc 
1900*0a6a1f1dSLionel Sambuc   return Actions.ActOnObjCAtTryStmt(atLoc, TryBody.get(),
1901f4a2713aSLionel Sambuc                                     CatchStmts,
1902*0a6a1f1dSLionel Sambuc                                     FinallyStmt.get());
1903f4a2713aSLionel Sambuc }
1904f4a2713aSLionel Sambuc 
1905f4a2713aSLionel Sambuc /// objc-autoreleasepool-statement:
1906f4a2713aSLionel Sambuc ///   @autoreleasepool compound-statement
1907f4a2713aSLionel Sambuc ///
1908f4a2713aSLionel Sambuc StmtResult
ParseObjCAutoreleasePoolStmt(SourceLocation atLoc)1909f4a2713aSLionel Sambuc Parser::ParseObjCAutoreleasePoolStmt(SourceLocation atLoc) {
1910f4a2713aSLionel Sambuc   ConsumeToken(); // consume autoreleasepool
1911f4a2713aSLionel Sambuc   if (Tok.isNot(tok::l_brace)) {
1912*0a6a1f1dSLionel Sambuc     Diag(Tok, diag::err_expected) << tok::l_brace;
1913f4a2713aSLionel Sambuc     return StmtError();
1914f4a2713aSLionel Sambuc   }
1915f4a2713aSLionel Sambuc   // Enter a scope to hold everything within the compound stmt.  Compound
1916f4a2713aSLionel Sambuc   // statements can always hold declarations.
1917f4a2713aSLionel Sambuc   ParseScope BodyScope(this, Scope::DeclScope);
1918f4a2713aSLionel Sambuc 
1919f4a2713aSLionel Sambuc   StmtResult AutoreleasePoolBody(ParseCompoundStatementBody());
1920f4a2713aSLionel Sambuc 
1921f4a2713aSLionel Sambuc   BodyScope.Exit();
1922f4a2713aSLionel Sambuc   if (AutoreleasePoolBody.isInvalid())
1923f4a2713aSLionel Sambuc     AutoreleasePoolBody = Actions.ActOnNullStmt(Tok.getLocation());
1924f4a2713aSLionel Sambuc   return Actions.ActOnObjCAutoreleasePoolStmt(atLoc,
1925*0a6a1f1dSLionel Sambuc                                                 AutoreleasePoolBody.get());
1926f4a2713aSLionel Sambuc }
1927f4a2713aSLionel Sambuc 
1928f4a2713aSLionel Sambuc /// StashAwayMethodOrFunctionBodyTokens -  Consume the tokens and store them
1929f4a2713aSLionel Sambuc /// for later parsing.
StashAwayMethodOrFunctionBodyTokens(Decl * MDecl)1930f4a2713aSLionel Sambuc void Parser::StashAwayMethodOrFunctionBodyTokens(Decl *MDecl) {
1931f4a2713aSLionel Sambuc   LexedMethod* LM = new LexedMethod(this, MDecl);
1932f4a2713aSLionel Sambuc   CurParsedObjCImpl->LateParsedObjCMethods.push_back(LM);
1933f4a2713aSLionel Sambuc   CachedTokens &Toks = LM->Toks;
1934f4a2713aSLionel Sambuc   // Begin by storing the '{' or 'try' or ':' token.
1935f4a2713aSLionel Sambuc   Toks.push_back(Tok);
1936f4a2713aSLionel Sambuc   if (Tok.is(tok::kw_try)) {
1937f4a2713aSLionel Sambuc     ConsumeToken();
1938f4a2713aSLionel Sambuc     if (Tok.is(tok::colon)) {
1939f4a2713aSLionel Sambuc       Toks.push_back(Tok);
1940f4a2713aSLionel Sambuc       ConsumeToken();
1941f4a2713aSLionel Sambuc       while (Tok.isNot(tok::l_brace)) {
1942f4a2713aSLionel Sambuc         ConsumeAndStoreUntil(tok::l_paren, Toks, /*StopAtSemi=*/false);
1943f4a2713aSLionel Sambuc         ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/false);
1944f4a2713aSLionel Sambuc       }
1945f4a2713aSLionel Sambuc     }
1946f4a2713aSLionel Sambuc     Toks.push_back(Tok); // also store '{'
1947f4a2713aSLionel Sambuc   }
1948f4a2713aSLionel Sambuc   else if (Tok.is(tok::colon)) {
1949f4a2713aSLionel Sambuc     ConsumeToken();
1950f4a2713aSLionel Sambuc     while (Tok.isNot(tok::l_brace)) {
1951f4a2713aSLionel Sambuc       ConsumeAndStoreUntil(tok::l_paren, Toks, /*StopAtSemi=*/false);
1952f4a2713aSLionel Sambuc       ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/false);
1953f4a2713aSLionel Sambuc     }
1954f4a2713aSLionel Sambuc     Toks.push_back(Tok); // also store '{'
1955f4a2713aSLionel Sambuc   }
1956f4a2713aSLionel Sambuc   ConsumeBrace();
1957f4a2713aSLionel Sambuc   // Consume everything up to (and including) the matching right brace.
1958f4a2713aSLionel Sambuc   ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false);
1959f4a2713aSLionel Sambuc   while (Tok.is(tok::kw_catch)) {
1960f4a2713aSLionel Sambuc     ConsumeAndStoreUntil(tok::l_brace, Toks, /*StopAtSemi=*/false);
1961f4a2713aSLionel Sambuc     ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false);
1962f4a2713aSLionel Sambuc   }
1963f4a2713aSLionel Sambuc }
1964f4a2713aSLionel Sambuc 
1965f4a2713aSLionel Sambuc ///   objc-method-def: objc-method-proto ';'[opt] '{' body '}'
1966f4a2713aSLionel Sambuc ///
ParseObjCMethodDefinition()1967f4a2713aSLionel Sambuc Decl *Parser::ParseObjCMethodDefinition() {
1968f4a2713aSLionel Sambuc   Decl *MDecl = ParseObjCMethodPrototype();
1969f4a2713aSLionel Sambuc 
1970f4a2713aSLionel Sambuc   PrettyDeclStackTraceEntry CrashInfo(Actions, MDecl, Tok.getLocation(),
1971f4a2713aSLionel Sambuc                                       "parsing Objective-C method");
1972f4a2713aSLionel Sambuc 
1973f4a2713aSLionel Sambuc   // parse optional ';'
1974f4a2713aSLionel Sambuc   if (Tok.is(tok::semi)) {
1975f4a2713aSLionel Sambuc     if (CurParsedObjCImpl) {
1976f4a2713aSLionel Sambuc       Diag(Tok, diag::warn_semicolon_before_method_body)
1977f4a2713aSLionel Sambuc         << FixItHint::CreateRemoval(Tok.getLocation());
1978f4a2713aSLionel Sambuc     }
1979f4a2713aSLionel Sambuc     ConsumeToken();
1980f4a2713aSLionel Sambuc   }
1981f4a2713aSLionel Sambuc 
1982f4a2713aSLionel Sambuc   // We should have an opening brace now.
1983f4a2713aSLionel Sambuc   if (Tok.isNot(tok::l_brace)) {
1984f4a2713aSLionel Sambuc     Diag(Tok, diag::err_expected_method_body);
1985f4a2713aSLionel Sambuc 
1986f4a2713aSLionel Sambuc     // Skip over garbage, until we get to '{'.  Don't eat the '{'.
1987f4a2713aSLionel Sambuc     SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch);
1988f4a2713aSLionel Sambuc 
1989f4a2713aSLionel Sambuc     // If we didn't find the '{', bail out.
1990f4a2713aSLionel Sambuc     if (Tok.isNot(tok::l_brace))
1991*0a6a1f1dSLionel Sambuc       return nullptr;
1992f4a2713aSLionel Sambuc   }
1993f4a2713aSLionel Sambuc 
1994f4a2713aSLionel Sambuc   if (!MDecl) {
1995f4a2713aSLionel Sambuc     ConsumeBrace();
1996f4a2713aSLionel Sambuc     SkipUntil(tok::r_brace);
1997*0a6a1f1dSLionel Sambuc     return nullptr;
1998f4a2713aSLionel Sambuc   }
1999f4a2713aSLionel Sambuc 
2000f4a2713aSLionel Sambuc   // Allow the rest of sema to find private method decl implementations.
2001f4a2713aSLionel Sambuc   Actions.AddAnyMethodToGlobalPool(MDecl);
2002f4a2713aSLionel Sambuc   assert (CurParsedObjCImpl
2003f4a2713aSLionel Sambuc           && "ParseObjCMethodDefinition - Method out of @implementation");
2004f4a2713aSLionel Sambuc   // Consume the tokens and store them for later parsing.
2005f4a2713aSLionel Sambuc   StashAwayMethodOrFunctionBodyTokens(MDecl);
2006f4a2713aSLionel Sambuc   return MDecl;
2007f4a2713aSLionel Sambuc }
2008f4a2713aSLionel Sambuc 
ParseObjCAtStatement(SourceLocation AtLoc)2009f4a2713aSLionel Sambuc StmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc) {
2010f4a2713aSLionel Sambuc   if (Tok.is(tok::code_completion)) {
2011f4a2713aSLionel Sambuc     Actions.CodeCompleteObjCAtStatement(getCurScope());
2012f4a2713aSLionel Sambuc     cutOffParsing();
2013f4a2713aSLionel Sambuc     return StmtError();
2014f4a2713aSLionel Sambuc   }
2015f4a2713aSLionel Sambuc 
2016f4a2713aSLionel Sambuc   if (Tok.isObjCAtKeyword(tok::objc_try))
2017f4a2713aSLionel Sambuc     return ParseObjCTryStmt(AtLoc);
2018f4a2713aSLionel Sambuc 
2019f4a2713aSLionel Sambuc   if (Tok.isObjCAtKeyword(tok::objc_throw))
2020f4a2713aSLionel Sambuc     return ParseObjCThrowStmt(AtLoc);
2021f4a2713aSLionel Sambuc 
2022f4a2713aSLionel Sambuc   if (Tok.isObjCAtKeyword(tok::objc_synchronized))
2023f4a2713aSLionel Sambuc     return ParseObjCSynchronizedStmt(AtLoc);
2024f4a2713aSLionel Sambuc 
2025f4a2713aSLionel Sambuc   if (Tok.isObjCAtKeyword(tok::objc_autoreleasepool))
2026f4a2713aSLionel Sambuc     return ParseObjCAutoreleasePoolStmt(AtLoc);
2027f4a2713aSLionel Sambuc 
2028*0a6a1f1dSLionel Sambuc   if (Tok.isObjCAtKeyword(tok::objc_import) &&
2029*0a6a1f1dSLionel Sambuc       getLangOpts().DebuggerSupport) {
2030*0a6a1f1dSLionel Sambuc     SkipUntil(tok::semi);
2031*0a6a1f1dSLionel Sambuc     return Actions.ActOnNullStmt(Tok.getLocation());
2032*0a6a1f1dSLionel Sambuc   }
2033*0a6a1f1dSLionel Sambuc 
2034f4a2713aSLionel Sambuc   ExprResult Res(ParseExpressionWithLeadingAt(AtLoc));
2035f4a2713aSLionel Sambuc   if (Res.isInvalid()) {
2036f4a2713aSLionel Sambuc     // If the expression is invalid, skip ahead to the next semicolon. Not
2037f4a2713aSLionel Sambuc     // doing this opens us up to the possibility of infinite loops if
2038f4a2713aSLionel Sambuc     // ParseExpression does not consume any tokens.
2039f4a2713aSLionel Sambuc     SkipUntil(tok::semi);
2040f4a2713aSLionel Sambuc     return StmtError();
2041f4a2713aSLionel Sambuc   }
2042f4a2713aSLionel Sambuc 
2043f4a2713aSLionel Sambuc   // Otherwise, eat the semicolon.
2044f4a2713aSLionel Sambuc   ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
2045f4a2713aSLionel Sambuc   return Actions.ActOnExprStmt(Res);
2046f4a2713aSLionel Sambuc }
2047f4a2713aSLionel Sambuc 
ParseObjCAtExpression(SourceLocation AtLoc)2048f4a2713aSLionel Sambuc ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
2049f4a2713aSLionel Sambuc   switch (Tok.getKind()) {
2050f4a2713aSLionel Sambuc   case tok::code_completion:
2051f4a2713aSLionel Sambuc     Actions.CodeCompleteObjCAtExpression(getCurScope());
2052f4a2713aSLionel Sambuc     cutOffParsing();
2053f4a2713aSLionel Sambuc     return ExprError();
2054f4a2713aSLionel Sambuc 
2055f4a2713aSLionel Sambuc   case tok::minus:
2056f4a2713aSLionel Sambuc   case tok::plus: {
2057f4a2713aSLionel Sambuc     tok::TokenKind Kind = Tok.getKind();
2058f4a2713aSLionel Sambuc     SourceLocation OpLoc = ConsumeToken();
2059f4a2713aSLionel Sambuc 
2060f4a2713aSLionel Sambuc     if (!Tok.is(tok::numeric_constant)) {
2061*0a6a1f1dSLionel Sambuc       const char *Symbol = nullptr;
2062f4a2713aSLionel Sambuc       switch (Kind) {
2063f4a2713aSLionel Sambuc       case tok::minus: Symbol = "-"; break;
2064f4a2713aSLionel Sambuc       case tok::plus: Symbol = "+"; break;
2065f4a2713aSLionel Sambuc       default: llvm_unreachable("missing unary operator case");
2066f4a2713aSLionel Sambuc       }
2067f4a2713aSLionel Sambuc       Diag(Tok, diag::err_nsnumber_nonliteral_unary)
2068f4a2713aSLionel Sambuc         << Symbol;
2069f4a2713aSLionel Sambuc       return ExprError();
2070f4a2713aSLionel Sambuc     }
2071f4a2713aSLionel Sambuc 
2072f4a2713aSLionel Sambuc     ExprResult Lit(Actions.ActOnNumericConstant(Tok));
2073f4a2713aSLionel Sambuc     if (Lit.isInvalid()) {
2074f4a2713aSLionel Sambuc       return Lit;
2075f4a2713aSLionel Sambuc     }
2076f4a2713aSLionel Sambuc     ConsumeToken(); // Consume the literal token.
2077f4a2713aSLionel Sambuc 
2078*0a6a1f1dSLionel Sambuc     Lit = Actions.ActOnUnaryOp(getCurScope(), OpLoc, Kind, Lit.get());
2079f4a2713aSLionel Sambuc     if (Lit.isInvalid())
2080f4a2713aSLionel Sambuc       return Lit;
2081f4a2713aSLionel Sambuc 
2082f4a2713aSLionel Sambuc     return ParsePostfixExpressionSuffix(
2083*0a6a1f1dSLionel Sambuc              Actions.BuildObjCNumericLiteral(AtLoc, Lit.get()));
2084f4a2713aSLionel Sambuc   }
2085f4a2713aSLionel Sambuc 
2086f4a2713aSLionel Sambuc   case tok::string_literal:    // primary-expression: string-literal
2087f4a2713aSLionel Sambuc   case tok::wide_string_literal:
2088f4a2713aSLionel Sambuc     return ParsePostfixExpressionSuffix(ParseObjCStringLiteral(AtLoc));
2089f4a2713aSLionel Sambuc 
2090f4a2713aSLionel Sambuc   case tok::char_constant:
2091f4a2713aSLionel Sambuc     return ParsePostfixExpressionSuffix(ParseObjCCharacterLiteral(AtLoc));
2092f4a2713aSLionel Sambuc 
2093f4a2713aSLionel Sambuc   case tok::numeric_constant:
2094f4a2713aSLionel Sambuc     return ParsePostfixExpressionSuffix(ParseObjCNumericLiteral(AtLoc));
2095f4a2713aSLionel Sambuc 
2096f4a2713aSLionel Sambuc   case tok::kw_true:  // Objective-C++, etc.
2097f4a2713aSLionel Sambuc   case tok::kw___objc_yes: // c/c++/objc/objc++ __objc_yes
2098f4a2713aSLionel Sambuc     return ParsePostfixExpressionSuffix(ParseObjCBooleanLiteral(AtLoc, true));
2099f4a2713aSLionel Sambuc   case tok::kw_false: // Objective-C++, etc.
2100f4a2713aSLionel Sambuc   case tok::kw___objc_no: // c/c++/objc/objc++ __objc_no
2101f4a2713aSLionel Sambuc     return ParsePostfixExpressionSuffix(ParseObjCBooleanLiteral(AtLoc, false));
2102f4a2713aSLionel Sambuc 
2103f4a2713aSLionel Sambuc   case tok::l_square:
2104f4a2713aSLionel Sambuc     // Objective-C array literal
2105f4a2713aSLionel Sambuc     return ParsePostfixExpressionSuffix(ParseObjCArrayLiteral(AtLoc));
2106f4a2713aSLionel Sambuc 
2107f4a2713aSLionel Sambuc   case tok::l_brace:
2108f4a2713aSLionel Sambuc     // Objective-C dictionary literal
2109f4a2713aSLionel Sambuc     return ParsePostfixExpressionSuffix(ParseObjCDictionaryLiteral(AtLoc));
2110f4a2713aSLionel Sambuc 
2111f4a2713aSLionel Sambuc   case tok::l_paren:
2112f4a2713aSLionel Sambuc     // Objective-C boxed expression
2113f4a2713aSLionel Sambuc     return ParsePostfixExpressionSuffix(ParseObjCBoxedExpr(AtLoc));
2114f4a2713aSLionel Sambuc 
2115f4a2713aSLionel Sambuc   default:
2116*0a6a1f1dSLionel Sambuc     if (Tok.getIdentifierInfo() == nullptr)
2117f4a2713aSLionel Sambuc       return ExprError(Diag(AtLoc, diag::err_unexpected_at));
2118f4a2713aSLionel Sambuc 
2119f4a2713aSLionel Sambuc     switch (Tok.getIdentifierInfo()->getObjCKeywordID()) {
2120f4a2713aSLionel Sambuc     case tok::objc_encode:
2121f4a2713aSLionel Sambuc       return ParsePostfixExpressionSuffix(ParseObjCEncodeExpression(AtLoc));
2122f4a2713aSLionel Sambuc     case tok::objc_protocol:
2123f4a2713aSLionel Sambuc       return ParsePostfixExpressionSuffix(ParseObjCProtocolExpression(AtLoc));
2124f4a2713aSLionel Sambuc     case tok::objc_selector:
2125f4a2713aSLionel Sambuc       return ParsePostfixExpressionSuffix(ParseObjCSelectorExpression(AtLoc));
2126f4a2713aSLionel Sambuc       default: {
2127*0a6a1f1dSLionel Sambuc         const char *str = nullptr;
2128f4a2713aSLionel Sambuc         if (GetLookAheadToken(1).is(tok::l_brace)) {
2129f4a2713aSLionel Sambuc           char ch = Tok.getIdentifierInfo()->getNameStart()[0];
2130f4a2713aSLionel Sambuc           str =
2131f4a2713aSLionel Sambuc             ch == 't' ? "try"
2132f4a2713aSLionel Sambuc                       : (ch == 'f' ? "finally"
2133*0a6a1f1dSLionel Sambuc                                    : (ch == 'a' ? "autoreleasepool" : nullptr));
2134f4a2713aSLionel Sambuc         }
2135f4a2713aSLionel Sambuc         if (str) {
2136f4a2713aSLionel Sambuc           SourceLocation kwLoc = Tok.getLocation();
2137f4a2713aSLionel Sambuc           return ExprError(Diag(AtLoc, diag::err_unexpected_at) <<
2138f4a2713aSLionel Sambuc                              FixItHint::CreateReplacement(kwLoc, str));
2139f4a2713aSLionel Sambuc         }
2140f4a2713aSLionel Sambuc         else
2141f4a2713aSLionel Sambuc           return ExprError(Diag(AtLoc, diag::err_unexpected_at));
2142f4a2713aSLionel Sambuc       }
2143f4a2713aSLionel Sambuc     }
2144f4a2713aSLionel Sambuc   }
2145f4a2713aSLionel Sambuc }
2146f4a2713aSLionel Sambuc 
2147f4a2713aSLionel Sambuc /// \brief Parse the receiver of an Objective-C++ message send.
2148f4a2713aSLionel Sambuc ///
2149f4a2713aSLionel Sambuc /// This routine parses the receiver of a message send in
2150f4a2713aSLionel Sambuc /// Objective-C++ either as a type or as an expression. Note that this
2151f4a2713aSLionel Sambuc /// routine must not be called to parse a send to 'super', since it
2152f4a2713aSLionel Sambuc /// has no way to return such a result.
2153f4a2713aSLionel Sambuc ///
2154f4a2713aSLionel Sambuc /// \param IsExpr Whether the receiver was parsed as an expression.
2155f4a2713aSLionel Sambuc ///
2156f4a2713aSLionel Sambuc /// \param TypeOrExpr If the receiver was parsed as an expression (\c
2157f4a2713aSLionel Sambuc /// IsExpr is true), the parsed expression. If the receiver was parsed
2158f4a2713aSLionel Sambuc /// as a type (\c IsExpr is false), the parsed type.
2159f4a2713aSLionel Sambuc ///
2160f4a2713aSLionel Sambuc /// \returns True if an error occurred during parsing or semantic
2161f4a2713aSLionel Sambuc /// analysis, in which case the arguments do not have valid
2162f4a2713aSLionel Sambuc /// values. Otherwise, returns false for a successful parse.
2163f4a2713aSLionel Sambuc ///
2164f4a2713aSLionel Sambuc ///   objc-receiver: [C++]
2165f4a2713aSLionel Sambuc ///     'super' [not parsed here]
2166f4a2713aSLionel Sambuc ///     expression
2167f4a2713aSLionel Sambuc ///     simple-type-specifier
2168f4a2713aSLionel Sambuc ///     typename-specifier
ParseObjCXXMessageReceiver(bool & IsExpr,void * & TypeOrExpr)2169f4a2713aSLionel Sambuc bool Parser::ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr) {
2170f4a2713aSLionel Sambuc   InMessageExpressionRAIIObject InMessage(*this, true);
2171f4a2713aSLionel Sambuc 
2172f4a2713aSLionel Sambuc   if (Tok.is(tok::identifier) || Tok.is(tok::coloncolon) ||
2173f4a2713aSLionel Sambuc       Tok.is(tok::kw_typename) || Tok.is(tok::annot_cxxscope))
2174f4a2713aSLionel Sambuc     TryAnnotateTypeOrScopeToken();
2175f4a2713aSLionel Sambuc 
2176f4a2713aSLionel Sambuc   if (!Actions.isSimpleTypeSpecifier(Tok.getKind())) {
2177f4a2713aSLionel Sambuc     //   objc-receiver:
2178f4a2713aSLionel Sambuc     //     expression
2179*0a6a1f1dSLionel Sambuc     // Make sure any typos in the receiver are corrected or diagnosed, so that
2180*0a6a1f1dSLionel Sambuc     // proper recovery can happen. FIXME: Perhaps filter the corrected expr to
2181*0a6a1f1dSLionel Sambuc     // only the things that are valid ObjC receivers?
2182*0a6a1f1dSLionel Sambuc     ExprResult Receiver = Actions.CorrectDelayedTyposInExpr(ParseExpression());
2183f4a2713aSLionel Sambuc     if (Receiver.isInvalid())
2184f4a2713aSLionel Sambuc       return true;
2185f4a2713aSLionel Sambuc 
2186f4a2713aSLionel Sambuc     IsExpr = true;
2187*0a6a1f1dSLionel Sambuc     TypeOrExpr = Receiver.get();
2188f4a2713aSLionel Sambuc     return false;
2189f4a2713aSLionel Sambuc   }
2190f4a2713aSLionel Sambuc 
2191f4a2713aSLionel Sambuc   // objc-receiver:
2192f4a2713aSLionel Sambuc   //   typename-specifier
2193f4a2713aSLionel Sambuc   //   simple-type-specifier
2194f4a2713aSLionel Sambuc   //   expression (that starts with one of the above)
2195f4a2713aSLionel Sambuc   DeclSpec DS(AttrFactory);
2196f4a2713aSLionel Sambuc   ParseCXXSimpleTypeSpecifier(DS);
2197f4a2713aSLionel Sambuc 
2198f4a2713aSLionel Sambuc   if (Tok.is(tok::l_paren)) {
2199f4a2713aSLionel Sambuc     // If we see an opening parentheses at this point, we are
2200f4a2713aSLionel Sambuc     // actually parsing an expression that starts with a
2201f4a2713aSLionel Sambuc     // function-style cast, e.g.,
2202f4a2713aSLionel Sambuc     //
2203f4a2713aSLionel Sambuc     //   postfix-expression:
2204f4a2713aSLionel Sambuc     //     simple-type-specifier ( expression-list [opt] )
2205f4a2713aSLionel Sambuc     //     typename-specifier ( expression-list [opt] )
2206f4a2713aSLionel Sambuc     //
2207f4a2713aSLionel Sambuc     // Parse the remainder of this case, then the (optional)
2208f4a2713aSLionel Sambuc     // postfix-expression suffix, followed by the (optional)
2209f4a2713aSLionel Sambuc     // right-hand side of the binary expression. We have an
2210f4a2713aSLionel Sambuc     // instance method.
2211f4a2713aSLionel Sambuc     ExprResult Receiver = ParseCXXTypeConstructExpression(DS);
2212f4a2713aSLionel Sambuc     if (!Receiver.isInvalid())
2213*0a6a1f1dSLionel Sambuc       Receiver = ParsePostfixExpressionSuffix(Receiver.get());
2214f4a2713aSLionel Sambuc     if (!Receiver.isInvalid())
2215*0a6a1f1dSLionel Sambuc       Receiver = ParseRHSOfBinaryExpression(Receiver.get(), prec::Comma);
2216f4a2713aSLionel Sambuc     if (Receiver.isInvalid())
2217f4a2713aSLionel Sambuc       return true;
2218f4a2713aSLionel Sambuc 
2219f4a2713aSLionel Sambuc     IsExpr = true;
2220*0a6a1f1dSLionel Sambuc     TypeOrExpr = Receiver.get();
2221f4a2713aSLionel Sambuc     return false;
2222f4a2713aSLionel Sambuc   }
2223f4a2713aSLionel Sambuc 
2224f4a2713aSLionel Sambuc   // We have a class message. Turn the simple-type-specifier or
2225f4a2713aSLionel Sambuc   // typename-specifier we parsed into a type and parse the
2226f4a2713aSLionel Sambuc   // remainder of the class message.
2227f4a2713aSLionel Sambuc   Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
2228f4a2713aSLionel Sambuc   TypeResult Type = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
2229f4a2713aSLionel Sambuc   if (Type.isInvalid())
2230f4a2713aSLionel Sambuc     return true;
2231f4a2713aSLionel Sambuc 
2232f4a2713aSLionel Sambuc   IsExpr = false;
2233f4a2713aSLionel Sambuc   TypeOrExpr = Type.get().getAsOpaquePtr();
2234f4a2713aSLionel Sambuc   return false;
2235f4a2713aSLionel Sambuc }
2236f4a2713aSLionel Sambuc 
2237f4a2713aSLionel Sambuc /// \brief Determine whether the parser is currently referring to a an
2238f4a2713aSLionel Sambuc /// Objective-C message send, using a simplified heuristic to avoid overhead.
2239f4a2713aSLionel Sambuc ///
2240f4a2713aSLionel Sambuc /// This routine will only return true for a subset of valid message-send
2241f4a2713aSLionel Sambuc /// expressions.
isSimpleObjCMessageExpression()2242f4a2713aSLionel Sambuc bool Parser::isSimpleObjCMessageExpression() {
2243f4a2713aSLionel Sambuc   assert(Tok.is(tok::l_square) && getLangOpts().ObjC1 &&
2244f4a2713aSLionel Sambuc          "Incorrect start for isSimpleObjCMessageExpression");
2245f4a2713aSLionel Sambuc   return GetLookAheadToken(1).is(tok::identifier) &&
2246f4a2713aSLionel Sambuc          GetLookAheadToken(2).is(tok::identifier);
2247f4a2713aSLionel Sambuc }
2248f4a2713aSLionel Sambuc 
isStartOfObjCClassMessageMissingOpenBracket()2249f4a2713aSLionel Sambuc bool Parser::isStartOfObjCClassMessageMissingOpenBracket() {
2250f4a2713aSLionel Sambuc   if (!getLangOpts().ObjC1 || !NextToken().is(tok::identifier) ||
2251f4a2713aSLionel Sambuc       InMessageExpression)
2252f4a2713aSLionel Sambuc     return false;
2253f4a2713aSLionel Sambuc 
2254f4a2713aSLionel Sambuc 
2255f4a2713aSLionel Sambuc   ParsedType Type;
2256f4a2713aSLionel Sambuc 
2257f4a2713aSLionel Sambuc   if (Tok.is(tok::annot_typename))
2258f4a2713aSLionel Sambuc     Type = getTypeAnnotation(Tok);
2259f4a2713aSLionel Sambuc   else if (Tok.is(tok::identifier))
2260f4a2713aSLionel Sambuc     Type = Actions.getTypeName(*Tok.getIdentifierInfo(), Tok.getLocation(),
2261f4a2713aSLionel Sambuc                                getCurScope());
2262f4a2713aSLionel Sambuc   else
2263f4a2713aSLionel Sambuc     return false;
2264f4a2713aSLionel Sambuc 
2265f4a2713aSLionel Sambuc   if (!Type.get().isNull() && Type.get()->isObjCObjectOrInterfaceType()) {
2266f4a2713aSLionel Sambuc     const Token &AfterNext = GetLookAheadToken(2);
2267f4a2713aSLionel Sambuc     if (AfterNext.is(tok::colon) || AfterNext.is(tok::r_square)) {
2268f4a2713aSLionel Sambuc       if (Tok.is(tok::identifier))
2269f4a2713aSLionel Sambuc         TryAnnotateTypeOrScopeToken();
2270f4a2713aSLionel Sambuc 
2271f4a2713aSLionel Sambuc       return Tok.is(tok::annot_typename);
2272f4a2713aSLionel Sambuc     }
2273f4a2713aSLionel Sambuc   }
2274f4a2713aSLionel Sambuc 
2275f4a2713aSLionel Sambuc   return false;
2276f4a2713aSLionel Sambuc }
2277f4a2713aSLionel Sambuc 
2278f4a2713aSLionel Sambuc ///   objc-message-expr:
2279f4a2713aSLionel Sambuc ///     '[' objc-receiver objc-message-args ']'
2280f4a2713aSLionel Sambuc ///
2281f4a2713aSLionel Sambuc ///   objc-receiver: [C]
2282f4a2713aSLionel Sambuc ///     'super'
2283f4a2713aSLionel Sambuc ///     expression
2284f4a2713aSLionel Sambuc ///     class-name
2285f4a2713aSLionel Sambuc ///     type-name
2286f4a2713aSLionel Sambuc ///
ParseObjCMessageExpression()2287f4a2713aSLionel Sambuc ExprResult Parser::ParseObjCMessageExpression() {
2288f4a2713aSLionel Sambuc   assert(Tok.is(tok::l_square) && "'[' expected");
2289f4a2713aSLionel Sambuc   SourceLocation LBracLoc = ConsumeBracket(); // consume '['
2290f4a2713aSLionel Sambuc 
2291f4a2713aSLionel Sambuc   if (Tok.is(tok::code_completion)) {
2292f4a2713aSLionel Sambuc     Actions.CodeCompleteObjCMessageReceiver(getCurScope());
2293f4a2713aSLionel Sambuc     cutOffParsing();
2294f4a2713aSLionel Sambuc     return ExprError();
2295f4a2713aSLionel Sambuc   }
2296f4a2713aSLionel Sambuc 
2297f4a2713aSLionel Sambuc   InMessageExpressionRAIIObject InMessage(*this, true);
2298f4a2713aSLionel Sambuc 
2299f4a2713aSLionel Sambuc   if (getLangOpts().CPlusPlus) {
2300f4a2713aSLionel Sambuc     // We completely separate the C and C++ cases because C++ requires
2301f4a2713aSLionel Sambuc     // more complicated (read: slower) parsing.
2302f4a2713aSLionel Sambuc 
2303f4a2713aSLionel Sambuc     // Handle send to super.
2304f4a2713aSLionel Sambuc     // FIXME: This doesn't benefit from the same typo-correction we
2305f4a2713aSLionel Sambuc     // get in Objective-C.
2306f4a2713aSLionel Sambuc     if (Tok.is(tok::identifier) && Tok.getIdentifierInfo() == Ident_super &&
2307f4a2713aSLionel Sambuc         NextToken().isNot(tok::period) && getCurScope()->isInObjcMethodScope())
2308f4a2713aSLionel Sambuc       return ParseObjCMessageExpressionBody(LBracLoc, ConsumeToken(),
2309*0a6a1f1dSLionel Sambuc                                             ParsedType(), nullptr);
2310f4a2713aSLionel Sambuc 
2311f4a2713aSLionel Sambuc     // Parse the receiver, which is either a type or an expression.
2312f4a2713aSLionel Sambuc     bool IsExpr;
2313*0a6a1f1dSLionel Sambuc     void *TypeOrExpr = nullptr;
2314f4a2713aSLionel Sambuc     if (ParseObjCXXMessageReceiver(IsExpr, TypeOrExpr)) {
2315f4a2713aSLionel Sambuc       SkipUntil(tok::r_square, StopAtSemi);
2316f4a2713aSLionel Sambuc       return ExprError();
2317f4a2713aSLionel Sambuc     }
2318f4a2713aSLionel Sambuc 
2319f4a2713aSLionel Sambuc     if (IsExpr)
2320f4a2713aSLionel Sambuc       return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(),
2321f4a2713aSLionel Sambuc                                             ParsedType(),
2322f4a2713aSLionel Sambuc                                             static_cast<Expr*>(TypeOrExpr));
2323f4a2713aSLionel Sambuc 
2324f4a2713aSLionel Sambuc     return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(),
2325f4a2713aSLionel Sambuc                               ParsedType::getFromOpaquePtr(TypeOrExpr),
2326*0a6a1f1dSLionel Sambuc                                           nullptr);
2327f4a2713aSLionel Sambuc   }
2328f4a2713aSLionel Sambuc 
2329f4a2713aSLionel Sambuc   if (Tok.is(tok::identifier)) {
2330f4a2713aSLionel Sambuc     IdentifierInfo *Name = Tok.getIdentifierInfo();
2331f4a2713aSLionel Sambuc     SourceLocation NameLoc = Tok.getLocation();
2332f4a2713aSLionel Sambuc     ParsedType ReceiverType;
2333f4a2713aSLionel Sambuc     switch (Actions.getObjCMessageKind(getCurScope(), Name, NameLoc,
2334f4a2713aSLionel Sambuc                                        Name == Ident_super,
2335f4a2713aSLionel Sambuc                                        NextToken().is(tok::period),
2336f4a2713aSLionel Sambuc                                        ReceiverType)) {
2337f4a2713aSLionel Sambuc     case Sema::ObjCSuperMessage:
2338f4a2713aSLionel Sambuc       return ParseObjCMessageExpressionBody(LBracLoc, ConsumeToken(),
2339*0a6a1f1dSLionel Sambuc                                             ParsedType(), nullptr);
2340f4a2713aSLionel Sambuc 
2341f4a2713aSLionel Sambuc     case Sema::ObjCClassMessage:
2342f4a2713aSLionel Sambuc       if (!ReceiverType) {
2343f4a2713aSLionel Sambuc         SkipUntil(tok::r_square, StopAtSemi);
2344f4a2713aSLionel Sambuc         return ExprError();
2345f4a2713aSLionel Sambuc       }
2346f4a2713aSLionel Sambuc 
2347f4a2713aSLionel Sambuc       ConsumeToken(); // the type name
2348f4a2713aSLionel Sambuc 
2349f4a2713aSLionel Sambuc       return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(),
2350*0a6a1f1dSLionel Sambuc                                             ReceiverType, nullptr);
2351f4a2713aSLionel Sambuc 
2352f4a2713aSLionel Sambuc     case Sema::ObjCInstanceMessage:
2353f4a2713aSLionel Sambuc       // Fall through to parse an expression.
2354f4a2713aSLionel Sambuc       break;
2355f4a2713aSLionel Sambuc     }
2356f4a2713aSLionel Sambuc   }
2357f4a2713aSLionel Sambuc 
2358f4a2713aSLionel Sambuc   // Otherwise, an arbitrary expression can be the receiver of a send.
2359*0a6a1f1dSLionel Sambuc   ExprResult Res = Actions.CorrectDelayedTyposInExpr(ParseExpression());
2360f4a2713aSLionel Sambuc   if (Res.isInvalid()) {
2361f4a2713aSLionel Sambuc     SkipUntil(tok::r_square, StopAtSemi);
2362f4a2713aSLionel Sambuc     return Res;
2363f4a2713aSLionel Sambuc   }
2364f4a2713aSLionel Sambuc 
2365f4a2713aSLionel Sambuc   return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(),
2366*0a6a1f1dSLionel Sambuc                                         ParsedType(), Res.get());
2367f4a2713aSLionel Sambuc }
2368f4a2713aSLionel Sambuc 
2369f4a2713aSLionel Sambuc /// \brief Parse the remainder of an Objective-C message following the
2370f4a2713aSLionel Sambuc /// '[' objc-receiver.
2371f4a2713aSLionel Sambuc ///
2372f4a2713aSLionel Sambuc /// This routine handles sends to super, class messages (sent to a
2373f4a2713aSLionel Sambuc /// class name), and instance messages (sent to an object), and the
2374f4a2713aSLionel Sambuc /// target is represented by \p SuperLoc, \p ReceiverType, or \p
2375f4a2713aSLionel Sambuc /// ReceiverExpr, respectively. Only one of these parameters may have
2376f4a2713aSLionel Sambuc /// a valid value.
2377f4a2713aSLionel Sambuc ///
2378f4a2713aSLionel Sambuc /// \param LBracLoc The location of the opening '['.
2379f4a2713aSLionel Sambuc ///
2380f4a2713aSLionel Sambuc /// \param SuperLoc If this is a send to 'super', the location of the
2381f4a2713aSLionel Sambuc /// 'super' keyword that indicates a send to the superclass.
2382f4a2713aSLionel Sambuc ///
2383f4a2713aSLionel Sambuc /// \param ReceiverType If this is a class message, the type of the
2384f4a2713aSLionel Sambuc /// class we are sending a message to.
2385f4a2713aSLionel Sambuc ///
2386f4a2713aSLionel Sambuc /// \param ReceiverExpr If this is an instance message, the expression
2387f4a2713aSLionel Sambuc /// used to compute the receiver object.
2388f4a2713aSLionel Sambuc ///
2389f4a2713aSLionel Sambuc ///   objc-message-args:
2390f4a2713aSLionel Sambuc ///     objc-selector
2391f4a2713aSLionel Sambuc ///     objc-keywordarg-list
2392f4a2713aSLionel Sambuc ///
2393f4a2713aSLionel Sambuc ///   objc-keywordarg-list:
2394f4a2713aSLionel Sambuc ///     objc-keywordarg
2395f4a2713aSLionel Sambuc ///     objc-keywordarg-list objc-keywordarg
2396f4a2713aSLionel Sambuc ///
2397f4a2713aSLionel Sambuc ///   objc-keywordarg:
2398f4a2713aSLionel Sambuc ///     selector-name[opt] ':' objc-keywordexpr
2399f4a2713aSLionel Sambuc ///
2400f4a2713aSLionel Sambuc ///   objc-keywordexpr:
2401f4a2713aSLionel Sambuc ///     nonempty-expr-list
2402f4a2713aSLionel Sambuc ///
2403f4a2713aSLionel Sambuc ///   nonempty-expr-list:
2404f4a2713aSLionel Sambuc ///     assignment-expression
2405f4a2713aSLionel Sambuc ///     nonempty-expr-list , assignment-expression
2406f4a2713aSLionel Sambuc ///
2407f4a2713aSLionel Sambuc ExprResult
ParseObjCMessageExpressionBody(SourceLocation LBracLoc,SourceLocation SuperLoc,ParsedType ReceiverType,Expr * ReceiverExpr)2408f4a2713aSLionel Sambuc Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
2409f4a2713aSLionel Sambuc                                        SourceLocation SuperLoc,
2410f4a2713aSLionel Sambuc                                        ParsedType ReceiverType,
2411*0a6a1f1dSLionel Sambuc                                        Expr *ReceiverExpr) {
2412f4a2713aSLionel Sambuc   InMessageExpressionRAIIObject InMessage(*this, true);
2413f4a2713aSLionel Sambuc 
2414f4a2713aSLionel Sambuc   if (Tok.is(tok::code_completion)) {
2415f4a2713aSLionel Sambuc     if (SuperLoc.isValid())
2416f4a2713aSLionel Sambuc       Actions.CodeCompleteObjCSuperMessage(getCurScope(), SuperLoc, None,
2417f4a2713aSLionel Sambuc                                            false);
2418f4a2713aSLionel Sambuc     else if (ReceiverType)
2419f4a2713aSLionel Sambuc       Actions.CodeCompleteObjCClassMessage(getCurScope(), ReceiverType, None,
2420f4a2713aSLionel Sambuc                                            false);
2421f4a2713aSLionel Sambuc     else
2422f4a2713aSLionel Sambuc       Actions.CodeCompleteObjCInstanceMessage(getCurScope(), ReceiverExpr,
2423f4a2713aSLionel Sambuc                                               None, false);
2424f4a2713aSLionel Sambuc     cutOffParsing();
2425f4a2713aSLionel Sambuc     return ExprError();
2426f4a2713aSLionel Sambuc   }
2427f4a2713aSLionel Sambuc 
2428f4a2713aSLionel Sambuc   // Parse objc-selector
2429f4a2713aSLionel Sambuc   SourceLocation Loc;
2430f4a2713aSLionel Sambuc   IdentifierInfo *selIdent = ParseObjCSelectorPiece(Loc);
2431f4a2713aSLionel Sambuc 
2432f4a2713aSLionel Sambuc   SmallVector<IdentifierInfo *, 12> KeyIdents;
2433f4a2713aSLionel Sambuc   SmallVector<SourceLocation, 12> KeyLocs;
2434f4a2713aSLionel Sambuc   ExprVector KeyExprs;
2435f4a2713aSLionel Sambuc 
2436f4a2713aSLionel Sambuc   if (Tok.is(tok::colon)) {
2437f4a2713aSLionel Sambuc     while (1) {
2438f4a2713aSLionel Sambuc       // Each iteration parses a single keyword argument.
2439f4a2713aSLionel Sambuc       KeyIdents.push_back(selIdent);
2440f4a2713aSLionel Sambuc       KeyLocs.push_back(Loc);
2441f4a2713aSLionel Sambuc 
2442*0a6a1f1dSLionel Sambuc       if (ExpectAndConsume(tok::colon)) {
2443f4a2713aSLionel Sambuc         // We must manually skip to a ']', otherwise the expression skipper will
2444f4a2713aSLionel Sambuc         // stop at the ']' when it skips to the ';'.  We want it to skip beyond
2445f4a2713aSLionel Sambuc         // the enclosing expression.
2446f4a2713aSLionel Sambuc         SkipUntil(tok::r_square, StopAtSemi);
2447f4a2713aSLionel Sambuc         return ExprError();
2448f4a2713aSLionel Sambuc       }
2449f4a2713aSLionel Sambuc 
2450f4a2713aSLionel Sambuc       ///  Parse the expression after ':'
2451f4a2713aSLionel Sambuc 
2452f4a2713aSLionel Sambuc       if (Tok.is(tok::code_completion)) {
2453f4a2713aSLionel Sambuc         if (SuperLoc.isValid())
2454f4a2713aSLionel Sambuc           Actions.CodeCompleteObjCSuperMessage(getCurScope(), SuperLoc,
2455f4a2713aSLionel Sambuc                                                KeyIdents,
2456f4a2713aSLionel Sambuc                                                /*AtArgumentEpression=*/true);
2457f4a2713aSLionel Sambuc         else if (ReceiverType)
2458f4a2713aSLionel Sambuc           Actions.CodeCompleteObjCClassMessage(getCurScope(), ReceiverType,
2459f4a2713aSLionel Sambuc                                                KeyIdents,
2460f4a2713aSLionel Sambuc                                                /*AtArgumentEpression=*/true);
2461f4a2713aSLionel Sambuc         else
2462f4a2713aSLionel Sambuc           Actions.CodeCompleteObjCInstanceMessage(getCurScope(), ReceiverExpr,
2463f4a2713aSLionel Sambuc                                                   KeyIdents,
2464f4a2713aSLionel Sambuc                                                   /*AtArgumentEpression=*/true);
2465f4a2713aSLionel Sambuc 
2466f4a2713aSLionel Sambuc         cutOffParsing();
2467f4a2713aSLionel Sambuc         return ExprError();
2468f4a2713aSLionel Sambuc       }
2469f4a2713aSLionel Sambuc 
2470f4a2713aSLionel Sambuc       ExprResult Expr;
2471f4a2713aSLionel Sambuc       if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
2472f4a2713aSLionel Sambuc         Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
2473f4a2713aSLionel Sambuc         Expr = ParseBraceInitializer();
2474f4a2713aSLionel Sambuc       } else
2475f4a2713aSLionel Sambuc         Expr = ParseAssignmentExpression();
2476f4a2713aSLionel Sambuc 
2477f4a2713aSLionel Sambuc       ExprResult Res(Expr);
2478f4a2713aSLionel Sambuc       if (Res.isInvalid()) {
2479f4a2713aSLionel Sambuc         // We must manually skip to a ']', otherwise the expression skipper will
2480f4a2713aSLionel Sambuc         // stop at the ']' when it skips to the ';'.  We want it to skip beyond
2481f4a2713aSLionel Sambuc         // the enclosing expression.
2482f4a2713aSLionel Sambuc         SkipUntil(tok::r_square, StopAtSemi);
2483f4a2713aSLionel Sambuc         return Res;
2484f4a2713aSLionel Sambuc       }
2485f4a2713aSLionel Sambuc 
2486f4a2713aSLionel Sambuc       // We have a valid expression.
2487*0a6a1f1dSLionel Sambuc       KeyExprs.push_back(Res.get());
2488f4a2713aSLionel Sambuc 
2489f4a2713aSLionel Sambuc       // Code completion after each argument.
2490f4a2713aSLionel Sambuc       if (Tok.is(tok::code_completion)) {
2491f4a2713aSLionel Sambuc         if (SuperLoc.isValid())
2492f4a2713aSLionel Sambuc           Actions.CodeCompleteObjCSuperMessage(getCurScope(), SuperLoc,
2493f4a2713aSLionel Sambuc                                                KeyIdents,
2494f4a2713aSLionel Sambuc                                                /*AtArgumentEpression=*/false);
2495f4a2713aSLionel Sambuc         else if (ReceiverType)
2496f4a2713aSLionel Sambuc           Actions.CodeCompleteObjCClassMessage(getCurScope(), ReceiverType,
2497f4a2713aSLionel Sambuc                                                KeyIdents,
2498f4a2713aSLionel Sambuc                                                /*AtArgumentEpression=*/false);
2499f4a2713aSLionel Sambuc         else
2500f4a2713aSLionel Sambuc           Actions.CodeCompleteObjCInstanceMessage(getCurScope(), ReceiverExpr,
2501f4a2713aSLionel Sambuc                                                   KeyIdents,
2502f4a2713aSLionel Sambuc                                                 /*AtArgumentEpression=*/false);
2503f4a2713aSLionel Sambuc         cutOffParsing();
2504f4a2713aSLionel Sambuc         return ExprError();
2505f4a2713aSLionel Sambuc       }
2506f4a2713aSLionel Sambuc 
2507f4a2713aSLionel Sambuc       // Check for another keyword selector.
2508f4a2713aSLionel Sambuc       selIdent = ParseObjCSelectorPiece(Loc);
2509f4a2713aSLionel Sambuc       if (!selIdent && Tok.isNot(tok::colon))
2510f4a2713aSLionel Sambuc         break;
2511f4a2713aSLionel Sambuc       // We have a selector or a colon, continue parsing.
2512f4a2713aSLionel Sambuc     }
2513f4a2713aSLionel Sambuc     // Parse the, optional, argument list, comma separated.
2514f4a2713aSLionel Sambuc     while (Tok.is(tok::comma)) {
2515f4a2713aSLionel Sambuc       SourceLocation commaLoc = ConsumeToken(); // Eat the ','.
2516f4a2713aSLionel Sambuc       ///  Parse the expression after ','
2517f4a2713aSLionel Sambuc       ExprResult Res(ParseAssignmentExpression());
2518*0a6a1f1dSLionel Sambuc       if (Tok.is(tok::colon))
2519*0a6a1f1dSLionel Sambuc         Res = Actions.CorrectDelayedTyposInExpr(Res);
2520f4a2713aSLionel Sambuc       if (Res.isInvalid()) {
2521f4a2713aSLionel Sambuc         if (Tok.is(tok::colon)) {
2522f4a2713aSLionel Sambuc           Diag(commaLoc, diag::note_extra_comma_message_arg) <<
2523f4a2713aSLionel Sambuc             FixItHint::CreateRemoval(commaLoc);
2524f4a2713aSLionel Sambuc         }
2525f4a2713aSLionel Sambuc         // We must manually skip to a ']', otherwise the expression skipper will
2526f4a2713aSLionel Sambuc         // stop at the ']' when it skips to the ';'.  We want it to skip beyond
2527f4a2713aSLionel Sambuc         // the enclosing expression.
2528f4a2713aSLionel Sambuc         SkipUntil(tok::r_square, StopAtSemi);
2529f4a2713aSLionel Sambuc         return Res;
2530f4a2713aSLionel Sambuc       }
2531f4a2713aSLionel Sambuc 
2532f4a2713aSLionel Sambuc       // We have a valid expression.
2533*0a6a1f1dSLionel Sambuc       KeyExprs.push_back(Res.get());
2534f4a2713aSLionel Sambuc     }
2535f4a2713aSLionel Sambuc   } else if (!selIdent) {
2536*0a6a1f1dSLionel Sambuc     Diag(Tok, diag::err_expected) << tok::identifier; // missing selector name.
2537f4a2713aSLionel Sambuc 
2538f4a2713aSLionel Sambuc     // We must manually skip to a ']', otherwise the expression skipper will
2539f4a2713aSLionel Sambuc     // stop at the ']' when it skips to the ';'.  We want it to skip beyond
2540f4a2713aSLionel Sambuc     // the enclosing expression.
2541f4a2713aSLionel Sambuc     SkipUntil(tok::r_square, StopAtSemi);
2542f4a2713aSLionel Sambuc     return ExprError();
2543f4a2713aSLionel Sambuc   }
2544f4a2713aSLionel Sambuc 
2545f4a2713aSLionel Sambuc   if (Tok.isNot(tok::r_square)) {
2546*0a6a1f1dSLionel Sambuc     Diag(Tok, diag::err_expected)
2547*0a6a1f1dSLionel Sambuc         << (Tok.is(tok::identifier) ? tok::colon : tok::r_square);
2548f4a2713aSLionel Sambuc     // We must manually skip to a ']', otherwise the expression skipper will
2549f4a2713aSLionel Sambuc     // stop at the ']' when it skips to the ';'.  We want it to skip beyond
2550f4a2713aSLionel Sambuc     // the enclosing expression.
2551f4a2713aSLionel Sambuc     SkipUntil(tok::r_square, StopAtSemi);
2552f4a2713aSLionel Sambuc     return ExprError();
2553f4a2713aSLionel Sambuc   }
2554f4a2713aSLionel Sambuc 
2555f4a2713aSLionel Sambuc   SourceLocation RBracLoc = ConsumeBracket(); // consume ']'
2556f4a2713aSLionel Sambuc 
2557f4a2713aSLionel Sambuc   unsigned nKeys = KeyIdents.size();
2558f4a2713aSLionel Sambuc   if (nKeys == 0) {
2559f4a2713aSLionel Sambuc     KeyIdents.push_back(selIdent);
2560f4a2713aSLionel Sambuc     KeyLocs.push_back(Loc);
2561f4a2713aSLionel Sambuc   }
2562f4a2713aSLionel Sambuc   Selector Sel = PP.getSelectorTable().getSelector(nKeys, &KeyIdents[0]);
2563f4a2713aSLionel Sambuc 
2564f4a2713aSLionel Sambuc   if (SuperLoc.isValid())
2565f4a2713aSLionel Sambuc     return Actions.ActOnSuperMessage(getCurScope(), SuperLoc, Sel,
2566f4a2713aSLionel Sambuc                                      LBracLoc, KeyLocs, RBracLoc, KeyExprs);
2567f4a2713aSLionel Sambuc   else if (ReceiverType)
2568f4a2713aSLionel Sambuc     return Actions.ActOnClassMessage(getCurScope(), ReceiverType, Sel,
2569f4a2713aSLionel Sambuc                                      LBracLoc, KeyLocs, RBracLoc, KeyExprs);
2570f4a2713aSLionel Sambuc   return Actions.ActOnInstanceMessage(getCurScope(), ReceiverExpr, Sel,
2571f4a2713aSLionel Sambuc                                       LBracLoc, KeyLocs, RBracLoc, KeyExprs);
2572f4a2713aSLionel Sambuc }
2573f4a2713aSLionel Sambuc 
ParseObjCStringLiteral(SourceLocation AtLoc)2574f4a2713aSLionel Sambuc ExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) {
2575f4a2713aSLionel Sambuc   ExprResult Res(ParseStringLiteralExpression());
2576f4a2713aSLionel Sambuc   if (Res.isInvalid()) return Res;
2577f4a2713aSLionel Sambuc 
2578f4a2713aSLionel Sambuc   // @"foo" @"bar" is a valid concatenated string.  Eat any subsequent string
2579f4a2713aSLionel Sambuc   // expressions.  At this point, we know that the only valid thing that starts
2580f4a2713aSLionel Sambuc   // with '@' is an @"".
2581f4a2713aSLionel Sambuc   SmallVector<SourceLocation, 4> AtLocs;
2582f4a2713aSLionel Sambuc   ExprVector AtStrings;
2583f4a2713aSLionel Sambuc   AtLocs.push_back(AtLoc);
2584*0a6a1f1dSLionel Sambuc   AtStrings.push_back(Res.get());
2585f4a2713aSLionel Sambuc 
2586f4a2713aSLionel Sambuc   while (Tok.is(tok::at)) {
2587f4a2713aSLionel Sambuc     AtLocs.push_back(ConsumeToken()); // eat the @.
2588f4a2713aSLionel Sambuc 
2589f4a2713aSLionel Sambuc     // Invalid unless there is a string literal.
2590f4a2713aSLionel Sambuc     if (!isTokenStringLiteral())
2591f4a2713aSLionel Sambuc       return ExprError(Diag(Tok, diag::err_objc_concat_string));
2592f4a2713aSLionel Sambuc 
2593f4a2713aSLionel Sambuc     ExprResult Lit(ParseStringLiteralExpression());
2594f4a2713aSLionel Sambuc     if (Lit.isInvalid())
2595f4a2713aSLionel Sambuc       return Lit;
2596f4a2713aSLionel Sambuc 
2597*0a6a1f1dSLionel Sambuc     AtStrings.push_back(Lit.get());
2598f4a2713aSLionel Sambuc   }
2599f4a2713aSLionel Sambuc 
2600f4a2713aSLionel Sambuc   return Actions.ParseObjCStringLiteral(&AtLocs[0], AtStrings.data(),
2601f4a2713aSLionel Sambuc                                         AtStrings.size());
2602f4a2713aSLionel Sambuc }
2603f4a2713aSLionel Sambuc 
2604f4a2713aSLionel Sambuc /// ParseObjCBooleanLiteral -
2605f4a2713aSLionel Sambuc /// objc-scalar-literal : '@' boolean-keyword
2606f4a2713aSLionel Sambuc ///                        ;
2607f4a2713aSLionel Sambuc /// boolean-keyword: 'true' | 'false' | '__objc_yes' | '__objc_no'
2608f4a2713aSLionel Sambuc ///                        ;
ParseObjCBooleanLiteral(SourceLocation AtLoc,bool ArgValue)2609f4a2713aSLionel Sambuc ExprResult Parser::ParseObjCBooleanLiteral(SourceLocation AtLoc,
2610f4a2713aSLionel Sambuc                                            bool ArgValue) {
2611f4a2713aSLionel Sambuc   SourceLocation EndLoc = ConsumeToken();             // consume the keyword.
2612f4a2713aSLionel Sambuc   return Actions.ActOnObjCBoolLiteral(AtLoc, EndLoc, ArgValue);
2613f4a2713aSLionel Sambuc }
2614f4a2713aSLionel Sambuc 
2615f4a2713aSLionel Sambuc /// ParseObjCCharacterLiteral -
2616f4a2713aSLionel Sambuc /// objc-scalar-literal : '@' character-literal
2617f4a2713aSLionel Sambuc ///                        ;
ParseObjCCharacterLiteral(SourceLocation AtLoc)2618f4a2713aSLionel Sambuc ExprResult Parser::ParseObjCCharacterLiteral(SourceLocation AtLoc) {
2619f4a2713aSLionel Sambuc   ExprResult Lit(Actions.ActOnCharacterConstant(Tok));
2620f4a2713aSLionel Sambuc   if (Lit.isInvalid()) {
2621f4a2713aSLionel Sambuc     return Lit;
2622f4a2713aSLionel Sambuc   }
2623f4a2713aSLionel Sambuc   ConsumeToken(); // Consume the literal token.
2624*0a6a1f1dSLionel Sambuc   return Actions.BuildObjCNumericLiteral(AtLoc, Lit.get());
2625f4a2713aSLionel Sambuc }
2626f4a2713aSLionel Sambuc 
2627f4a2713aSLionel Sambuc /// ParseObjCNumericLiteral -
2628f4a2713aSLionel Sambuc /// objc-scalar-literal : '@' scalar-literal
2629f4a2713aSLionel Sambuc ///                        ;
2630f4a2713aSLionel Sambuc /// scalar-literal : | numeric-constant			/* any numeric constant. */
2631f4a2713aSLionel Sambuc ///                    ;
ParseObjCNumericLiteral(SourceLocation AtLoc)2632f4a2713aSLionel Sambuc ExprResult Parser::ParseObjCNumericLiteral(SourceLocation AtLoc) {
2633f4a2713aSLionel Sambuc   ExprResult Lit(Actions.ActOnNumericConstant(Tok));
2634f4a2713aSLionel Sambuc   if (Lit.isInvalid()) {
2635f4a2713aSLionel Sambuc     return Lit;
2636f4a2713aSLionel Sambuc   }
2637f4a2713aSLionel Sambuc   ConsumeToken(); // Consume the literal token.
2638*0a6a1f1dSLionel Sambuc   return Actions.BuildObjCNumericLiteral(AtLoc, Lit.get());
2639f4a2713aSLionel Sambuc }
2640f4a2713aSLionel Sambuc 
2641f4a2713aSLionel Sambuc /// ParseObjCBoxedExpr -
2642f4a2713aSLionel Sambuc /// objc-box-expression:
2643f4a2713aSLionel Sambuc ///       @( assignment-expression )
2644f4a2713aSLionel Sambuc ExprResult
ParseObjCBoxedExpr(SourceLocation AtLoc)2645f4a2713aSLionel Sambuc Parser::ParseObjCBoxedExpr(SourceLocation AtLoc) {
2646f4a2713aSLionel Sambuc   if (Tok.isNot(tok::l_paren))
2647f4a2713aSLionel Sambuc     return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@");
2648f4a2713aSLionel Sambuc 
2649f4a2713aSLionel Sambuc   BalancedDelimiterTracker T(*this, tok::l_paren);
2650f4a2713aSLionel Sambuc   T.consumeOpen();
2651f4a2713aSLionel Sambuc   ExprResult ValueExpr(ParseAssignmentExpression());
2652f4a2713aSLionel Sambuc   if (T.consumeClose())
2653f4a2713aSLionel Sambuc     return ExprError();
2654f4a2713aSLionel Sambuc 
2655f4a2713aSLionel Sambuc   if (ValueExpr.isInvalid())
2656f4a2713aSLionel Sambuc     return ExprError();
2657f4a2713aSLionel Sambuc 
2658f4a2713aSLionel Sambuc   // Wrap the sub-expression in a parenthesized expression, to distinguish
2659f4a2713aSLionel Sambuc   // a boxed expression from a literal.
2660f4a2713aSLionel Sambuc   SourceLocation LPLoc = T.getOpenLocation(), RPLoc = T.getCloseLocation();
2661*0a6a1f1dSLionel Sambuc   ValueExpr = Actions.ActOnParenExpr(LPLoc, RPLoc, ValueExpr.get());
2662f4a2713aSLionel Sambuc   return Actions.BuildObjCBoxedExpr(SourceRange(AtLoc, RPLoc),
2663*0a6a1f1dSLionel Sambuc                                     ValueExpr.get());
2664f4a2713aSLionel Sambuc }
2665f4a2713aSLionel Sambuc 
ParseObjCArrayLiteral(SourceLocation AtLoc)2666f4a2713aSLionel Sambuc ExprResult Parser::ParseObjCArrayLiteral(SourceLocation AtLoc) {
2667f4a2713aSLionel Sambuc   ExprVector ElementExprs;                   // array elements.
2668f4a2713aSLionel Sambuc   ConsumeBracket(); // consume the l_square.
2669f4a2713aSLionel Sambuc 
2670f4a2713aSLionel Sambuc   while (Tok.isNot(tok::r_square)) {
2671f4a2713aSLionel Sambuc     // Parse list of array element expressions (all must be id types).
2672f4a2713aSLionel Sambuc     ExprResult Res(ParseAssignmentExpression());
2673f4a2713aSLionel Sambuc     if (Res.isInvalid()) {
2674f4a2713aSLionel Sambuc       // We must manually skip to a ']', otherwise the expression skipper will
2675f4a2713aSLionel Sambuc       // stop at the ']' when it skips to the ';'.  We want it to skip beyond
2676f4a2713aSLionel Sambuc       // the enclosing expression.
2677f4a2713aSLionel Sambuc       SkipUntil(tok::r_square, StopAtSemi);
2678f4a2713aSLionel Sambuc       return Res;
2679f4a2713aSLionel Sambuc     }
2680f4a2713aSLionel Sambuc 
2681f4a2713aSLionel Sambuc     // Parse the ellipsis that indicates a pack expansion.
2682f4a2713aSLionel Sambuc     if (Tok.is(tok::ellipsis))
2683f4a2713aSLionel Sambuc       Res = Actions.ActOnPackExpansion(Res.get(), ConsumeToken());
2684f4a2713aSLionel Sambuc     if (Res.isInvalid())
2685f4a2713aSLionel Sambuc       return true;
2686f4a2713aSLionel Sambuc 
2687*0a6a1f1dSLionel Sambuc     ElementExprs.push_back(Res.get());
2688f4a2713aSLionel Sambuc 
2689f4a2713aSLionel Sambuc     if (Tok.is(tok::comma))
2690f4a2713aSLionel Sambuc       ConsumeToken(); // Eat the ','.
2691f4a2713aSLionel Sambuc     else if (Tok.isNot(tok::r_square))
2692*0a6a1f1dSLionel Sambuc       return ExprError(Diag(Tok, diag::err_expected_either) << tok::r_square
2693*0a6a1f1dSLionel Sambuc                                                             << tok::comma);
2694f4a2713aSLionel Sambuc   }
2695f4a2713aSLionel Sambuc   SourceLocation EndLoc = ConsumeBracket(); // location of ']'
2696f4a2713aSLionel Sambuc   MultiExprArg Args(ElementExprs);
2697f4a2713aSLionel Sambuc   return Actions.BuildObjCArrayLiteral(SourceRange(AtLoc, EndLoc), Args);
2698f4a2713aSLionel Sambuc }
2699f4a2713aSLionel Sambuc 
ParseObjCDictionaryLiteral(SourceLocation AtLoc)2700f4a2713aSLionel Sambuc ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) {
2701f4a2713aSLionel Sambuc   SmallVector<ObjCDictionaryElement, 4> Elements; // dictionary elements.
2702f4a2713aSLionel Sambuc   ConsumeBrace(); // consume the l_square.
2703f4a2713aSLionel Sambuc   while (Tok.isNot(tok::r_brace)) {
2704f4a2713aSLionel Sambuc     // Parse the comma separated key : value expressions.
2705f4a2713aSLionel Sambuc     ExprResult KeyExpr;
2706f4a2713aSLionel Sambuc     {
2707f4a2713aSLionel Sambuc       ColonProtectionRAIIObject X(*this);
2708f4a2713aSLionel Sambuc       KeyExpr = ParseAssignmentExpression();
2709f4a2713aSLionel Sambuc       if (KeyExpr.isInvalid()) {
2710f4a2713aSLionel Sambuc         // We must manually skip to a '}', otherwise the expression skipper will
2711f4a2713aSLionel Sambuc         // stop at the '}' when it skips to the ';'.  We want it to skip beyond
2712f4a2713aSLionel Sambuc         // the enclosing expression.
2713f4a2713aSLionel Sambuc         SkipUntil(tok::r_brace, StopAtSemi);
2714f4a2713aSLionel Sambuc         return KeyExpr;
2715f4a2713aSLionel Sambuc       }
2716f4a2713aSLionel Sambuc     }
2717f4a2713aSLionel Sambuc 
2718*0a6a1f1dSLionel Sambuc     if (ExpectAndConsume(tok::colon)) {
2719f4a2713aSLionel Sambuc       SkipUntil(tok::r_brace, StopAtSemi);
2720f4a2713aSLionel Sambuc       return ExprError();
2721f4a2713aSLionel Sambuc     }
2722f4a2713aSLionel Sambuc 
2723f4a2713aSLionel Sambuc     ExprResult ValueExpr(ParseAssignmentExpression());
2724f4a2713aSLionel Sambuc     if (ValueExpr.isInvalid()) {
2725f4a2713aSLionel Sambuc       // We must manually skip to a '}', otherwise the expression skipper will
2726f4a2713aSLionel Sambuc       // stop at the '}' when it skips to the ';'.  We want it to skip beyond
2727f4a2713aSLionel Sambuc       // the enclosing expression.
2728f4a2713aSLionel Sambuc       SkipUntil(tok::r_brace, StopAtSemi);
2729f4a2713aSLionel Sambuc       return ValueExpr;
2730f4a2713aSLionel Sambuc     }
2731f4a2713aSLionel Sambuc 
2732f4a2713aSLionel Sambuc     // Parse the ellipsis that designates this as a pack expansion.
2733f4a2713aSLionel Sambuc     SourceLocation EllipsisLoc;
2734*0a6a1f1dSLionel Sambuc     if (getLangOpts().CPlusPlus)
2735*0a6a1f1dSLionel Sambuc       TryConsumeToken(tok::ellipsis, EllipsisLoc);
2736f4a2713aSLionel Sambuc 
2737f4a2713aSLionel Sambuc     // We have a valid expression. Collect it in a vector so we can
2738f4a2713aSLionel Sambuc     // build the argument list.
2739f4a2713aSLionel Sambuc     ObjCDictionaryElement Element = {
2740f4a2713aSLionel Sambuc       KeyExpr.get(), ValueExpr.get(), EllipsisLoc, None
2741f4a2713aSLionel Sambuc     };
2742f4a2713aSLionel Sambuc     Elements.push_back(Element);
2743f4a2713aSLionel Sambuc 
2744*0a6a1f1dSLionel Sambuc     if (!TryConsumeToken(tok::comma) && Tok.isNot(tok::r_brace))
2745*0a6a1f1dSLionel Sambuc       return ExprError(Diag(Tok, diag::err_expected_either) << tok::r_brace
2746*0a6a1f1dSLionel Sambuc                                                             << tok::comma);
2747f4a2713aSLionel Sambuc   }
2748f4a2713aSLionel Sambuc   SourceLocation EndLoc = ConsumeBrace();
2749f4a2713aSLionel Sambuc 
2750f4a2713aSLionel Sambuc   // Create the ObjCDictionaryLiteral.
2751f4a2713aSLionel Sambuc   return Actions.BuildObjCDictionaryLiteral(SourceRange(AtLoc, EndLoc),
2752f4a2713aSLionel Sambuc                                             Elements.data(), Elements.size());
2753f4a2713aSLionel Sambuc }
2754f4a2713aSLionel Sambuc 
2755f4a2713aSLionel Sambuc ///    objc-encode-expression:
2756f4a2713aSLionel Sambuc ///      \@encode ( type-name )
2757f4a2713aSLionel Sambuc ExprResult
ParseObjCEncodeExpression(SourceLocation AtLoc)2758f4a2713aSLionel Sambuc Parser::ParseObjCEncodeExpression(SourceLocation AtLoc) {
2759f4a2713aSLionel Sambuc   assert(Tok.isObjCAtKeyword(tok::objc_encode) && "Not an @encode expression!");
2760f4a2713aSLionel Sambuc 
2761f4a2713aSLionel Sambuc   SourceLocation EncLoc = ConsumeToken();
2762f4a2713aSLionel Sambuc 
2763f4a2713aSLionel Sambuc   if (Tok.isNot(tok::l_paren))
2764f4a2713aSLionel Sambuc     return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@encode");
2765f4a2713aSLionel Sambuc 
2766f4a2713aSLionel Sambuc   BalancedDelimiterTracker T(*this, tok::l_paren);
2767f4a2713aSLionel Sambuc   T.consumeOpen();
2768f4a2713aSLionel Sambuc 
2769f4a2713aSLionel Sambuc   TypeResult Ty = ParseTypeName();
2770f4a2713aSLionel Sambuc 
2771f4a2713aSLionel Sambuc   T.consumeClose();
2772f4a2713aSLionel Sambuc 
2773f4a2713aSLionel Sambuc   if (Ty.isInvalid())
2774f4a2713aSLionel Sambuc     return ExprError();
2775f4a2713aSLionel Sambuc 
2776f4a2713aSLionel Sambuc   return Actions.ParseObjCEncodeExpression(AtLoc, EncLoc, T.getOpenLocation(),
2777f4a2713aSLionel Sambuc                                            Ty.get(), T.getCloseLocation());
2778f4a2713aSLionel Sambuc }
2779f4a2713aSLionel Sambuc 
2780f4a2713aSLionel Sambuc ///     objc-protocol-expression
2781f4a2713aSLionel Sambuc ///       \@protocol ( protocol-name )
2782f4a2713aSLionel Sambuc ExprResult
ParseObjCProtocolExpression(SourceLocation AtLoc)2783f4a2713aSLionel Sambuc Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) {
2784f4a2713aSLionel Sambuc   SourceLocation ProtoLoc = ConsumeToken();
2785f4a2713aSLionel Sambuc 
2786f4a2713aSLionel Sambuc   if (Tok.isNot(tok::l_paren))
2787f4a2713aSLionel Sambuc     return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@protocol");
2788f4a2713aSLionel Sambuc 
2789f4a2713aSLionel Sambuc   BalancedDelimiterTracker T(*this, tok::l_paren);
2790f4a2713aSLionel Sambuc   T.consumeOpen();
2791f4a2713aSLionel Sambuc 
2792f4a2713aSLionel Sambuc   if (Tok.isNot(tok::identifier))
2793*0a6a1f1dSLionel Sambuc     return ExprError(Diag(Tok, diag::err_expected) << tok::identifier);
2794f4a2713aSLionel Sambuc 
2795f4a2713aSLionel Sambuc   IdentifierInfo *protocolId = Tok.getIdentifierInfo();
2796f4a2713aSLionel Sambuc   SourceLocation ProtoIdLoc = ConsumeToken();
2797f4a2713aSLionel Sambuc 
2798f4a2713aSLionel Sambuc   T.consumeClose();
2799f4a2713aSLionel Sambuc 
2800f4a2713aSLionel Sambuc   return Actions.ParseObjCProtocolExpression(protocolId, AtLoc, ProtoLoc,
2801f4a2713aSLionel Sambuc                                              T.getOpenLocation(), ProtoIdLoc,
2802f4a2713aSLionel Sambuc                                              T.getCloseLocation());
2803f4a2713aSLionel Sambuc }
2804f4a2713aSLionel Sambuc 
2805f4a2713aSLionel Sambuc ///     objc-selector-expression
2806*0a6a1f1dSLionel Sambuc ///       @selector '(' '('[opt] objc-keyword-selector ')'[opt] ')'
ParseObjCSelectorExpression(SourceLocation AtLoc)2807f4a2713aSLionel Sambuc ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) {
2808f4a2713aSLionel Sambuc   SourceLocation SelectorLoc = ConsumeToken();
2809f4a2713aSLionel Sambuc 
2810f4a2713aSLionel Sambuc   if (Tok.isNot(tok::l_paren))
2811f4a2713aSLionel Sambuc     return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@selector");
2812f4a2713aSLionel Sambuc 
2813f4a2713aSLionel Sambuc   SmallVector<IdentifierInfo *, 12> KeyIdents;
2814f4a2713aSLionel Sambuc   SourceLocation sLoc;
2815f4a2713aSLionel Sambuc 
2816f4a2713aSLionel Sambuc   BalancedDelimiterTracker T(*this, tok::l_paren);
2817f4a2713aSLionel Sambuc   T.consumeOpen();
2818*0a6a1f1dSLionel Sambuc   bool HasOptionalParen = Tok.is(tok::l_paren);
2819*0a6a1f1dSLionel Sambuc   if (HasOptionalParen)
2820*0a6a1f1dSLionel Sambuc     ConsumeParen();
2821f4a2713aSLionel Sambuc 
2822f4a2713aSLionel Sambuc   if (Tok.is(tok::code_completion)) {
2823f4a2713aSLionel Sambuc     Actions.CodeCompleteObjCSelector(getCurScope(), KeyIdents);
2824f4a2713aSLionel Sambuc     cutOffParsing();
2825f4a2713aSLionel Sambuc     return ExprError();
2826f4a2713aSLionel Sambuc   }
2827f4a2713aSLionel Sambuc 
2828f4a2713aSLionel Sambuc   IdentifierInfo *SelIdent = ParseObjCSelectorPiece(sLoc);
2829f4a2713aSLionel Sambuc   if (!SelIdent &&  // missing selector name.
2830f4a2713aSLionel Sambuc       Tok.isNot(tok::colon) && Tok.isNot(tok::coloncolon))
2831*0a6a1f1dSLionel Sambuc     return ExprError(Diag(Tok, diag::err_expected) << tok::identifier);
2832f4a2713aSLionel Sambuc 
2833f4a2713aSLionel Sambuc   KeyIdents.push_back(SelIdent);
2834*0a6a1f1dSLionel Sambuc 
2835f4a2713aSLionel Sambuc   unsigned nColons = 0;
2836f4a2713aSLionel Sambuc   if (Tok.isNot(tok::r_paren)) {
2837f4a2713aSLionel Sambuc     while (1) {
2838*0a6a1f1dSLionel Sambuc       if (TryConsumeToken(tok::coloncolon)) { // Handle :: in C++.
2839f4a2713aSLionel Sambuc         ++nColons;
2840*0a6a1f1dSLionel Sambuc         KeyIdents.push_back(nullptr);
2841*0a6a1f1dSLionel Sambuc       } else if (ExpectAndConsume(tok::colon)) // Otherwise expect ':'.
2842*0a6a1f1dSLionel Sambuc         return ExprError();
2843*0a6a1f1dSLionel Sambuc       ++nColons;
2844f4a2713aSLionel Sambuc 
2845f4a2713aSLionel Sambuc       if (Tok.is(tok::r_paren))
2846f4a2713aSLionel Sambuc         break;
2847f4a2713aSLionel Sambuc 
2848f4a2713aSLionel Sambuc       if (Tok.is(tok::code_completion)) {
2849f4a2713aSLionel Sambuc         Actions.CodeCompleteObjCSelector(getCurScope(), KeyIdents);
2850f4a2713aSLionel Sambuc         cutOffParsing();
2851f4a2713aSLionel Sambuc         return ExprError();
2852f4a2713aSLionel Sambuc       }
2853f4a2713aSLionel Sambuc 
2854f4a2713aSLionel Sambuc       // Check for another keyword selector.
2855f4a2713aSLionel Sambuc       SourceLocation Loc;
2856f4a2713aSLionel Sambuc       SelIdent = ParseObjCSelectorPiece(Loc);
2857f4a2713aSLionel Sambuc       KeyIdents.push_back(SelIdent);
2858f4a2713aSLionel Sambuc       if (!SelIdent && Tok.isNot(tok::colon) && Tok.isNot(tok::coloncolon))
2859f4a2713aSLionel Sambuc         break;
2860f4a2713aSLionel Sambuc     }
2861f4a2713aSLionel Sambuc   }
2862*0a6a1f1dSLionel Sambuc   if (HasOptionalParen && Tok.is(tok::r_paren))
2863*0a6a1f1dSLionel Sambuc     ConsumeParen(); // ')'
2864f4a2713aSLionel Sambuc   T.consumeClose();
2865f4a2713aSLionel Sambuc   Selector Sel = PP.getSelectorTable().getSelector(nColons, &KeyIdents[0]);
2866f4a2713aSLionel Sambuc   return Actions.ParseObjCSelectorExpression(Sel, AtLoc, SelectorLoc,
2867f4a2713aSLionel Sambuc                                              T.getOpenLocation(),
2868*0a6a1f1dSLionel Sambuc                                              T.getCloseLocation(),
2869*0a6a1f1dSLionel Sambuc                                              !HasOptionalParen);
2870f4a2713aSLionel Sambuc  }
2871f4a2713aSLionel Sambuc 
ParseLexedObjCMethodDefs(LexedMethod & LM,bool parseMethod)2872f4a2713aSLionel Sambuc void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) {
2873f4a2713aSLionel Sambuc   // MCDecl might be null due to error in method or c-function  prototype, etc.
2874f4a2713aSLionel Sambuc   Decl *MCDecl = LM.D;
2875f4a2713aSLionel Sambuc   bool skip = MCDecl &&
2876f4a2713aSLionel Sambuc               ((parseMethod && !Actions.isObjCMethodDecl(MCDecl)) ||
2877f4a2713aSLionel Sambuc               (!parseMethod && Actions.isObjCMethodDecl(MCDecl)));
2878f4a2713aSLionel Sambuc   if (skip)
2879f4a2713aSLionel Sambuc     return;
2880f4a2713aSLionel Sambuc 
2881f4a2713aSLionel Sambuc   // Save the current token position.
2882f4a2713aSLionel Sambuc   SourceLocation OrigLoc = Tok.getLocation();
2883f4a2713aSLionel Sambuc 
2884f4a2713aSLionel Sambuc   assert(!LM.Toks.empty() && "ParseLexedObjCMethodDef - Empty body!");
2885f4a2713aSLionel Sambuc   // Append the current token at the end of the new token stream so that it
2886f4a2713aSLionel Sambuc   // doesn't get lost.
2887f4a2713aSLionel Sambuc   LM.Toks.push_back(Tok);
2888f4a2713aSLionel Sambuc   PP.EnterTokenStream(LM.Toks.data(), LM.Toks.size(), true, false);
2889f4a2713aSLionel Sambuc 
2890f4a2713aSLionel Sambuc   // Consume the previously pushed token.
2891f4a2713aSLionel Sambuc   ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
2892f4a2713aSLionel Sambuc 
2893f4a2713aSLionel Sambuc   assert((Tok.is(tok::l_brace) || Tok.is(tok::kw_try) ||
2894f4a2713aSLionel Sambuc           Tok.is(tok::colon)) &&
2895f4a2713aSLionel Sambuc           "Inline objective-c method not starting with '{' or 'try' or ':'");
2896*0a6a1f1dSLionel Sambuc   // Enter a scope for the method or c-function body.
2897f4a2713aSLionel Sambuc   ParseScope BodyScope(this,
2898f4a2713aSLionel Sambuc                        parseMethod
2899f4a2713aSLionel Sambuc                        ? Scope::ObjCMethodScope|Scope::FnScope|Scope::DeclScope
2900f4a2713aSLionel Sambuc                        : Scope::FnScope|Scope::DeclScope);
2901f4a2713aSLionel Sambuc 
2902f4a2713aSLionel Sambuc   // Tell the actions module that we have entered a method or c-function definition
2903f4a2713aSLionel Sambuc   // with the specified Declarator for the method/function.
2904f4a2713aSLionel Sambuc   if (parseMethod)
2905f4a2713aSLionel Sambuc     Actions.ActOnStartOfObjCMethodDef(getCurScope(), MCDecl);
2906f4a2713aSLionel Sambuc   else
2907f4a2713aSLionel Sambuc     Actions.ActOnStartOfFunctionDef(getCurScope(), MCDecl);
2908f4a2713aSLionel Sambuc   if (Tok.is(tok::kw_try))
2909*0a6a1f1dSLionel Sambuc     ParseFunctionTryBlock(MCDecl, BodyScope);
2910f4a2713aSLionel Sambuc   else {
2911f4a2713aSLionel Sambuc     if (Tok.is(tok::colon))
2912f4a2713aSLionel Sambuc       ParseConstructorInitializer(MCDecl);
2913*0a6a1f1dSLionel Sambuc     ParseFunctionStatementBody(MCDecl, BodyScope);
2914f4a2713aSLionel Sambuc   }
2915f4a2713aSLionel Sambuc 
2916f4a2713aSLionel Sambuc   if (Tok.getLocation() != OrigLoc) {
2917f4a2713aSLionel Sambuc     // Due to parsing error, we either went over the cached tokens or
2918f4a2713aSLionel Sambuc     // there are still cached tokens left. If it's the latter case skip the
2919f4a2713aSLionel Sambuc     // leftover tokens.
2920f4a2713aSLionel Sambuc     // Since this is an uncommon situation that should be avoided, use the
2921f4a2713aSLionel Sambuc     // expensive isBeforeInTranslationUnit call.
2922f4a2713aSLionel Sambuc     if (PP.getSourceManager().isBeforeInTranslationUnit(Tok.getLocation(),
2923f4a2713aSLionel Sambuc                                                      OrigLoc))
2924f4a2713aSLionel Sambuc       while (Tok.getLocation() != OrigLoc && Tok.isNot(tok::eof))
2925f4a2713aSLionel Sambuc         ConsumeAnyToken();
2926f4a2713aSLionel Sambuc   }
2927f4a2713aSLionel Sambuc 
2928f4a2713aSLionel Sambuc   return;
2929f4a2713aSLionel Sambuc }
2930