ParseCXXInlineMethods.cpp revision 243830
1193326Sed//===--- ParseCXXInlineMethods.cpp - C++ class inline methods parsing------===//
2193326Sed//
3193326Sed//                     The LLVM Compiler Infrastructure
4193326Sed//
5193326Sed// This file is distributed under the University of Illinois Open Source
6193326Sed// License. See LICENSE.TXT for details.
7193326Sed//
8193326Sed//===----------------------------------------------------------------------===//
9193326Sed//
10193326Sed//  This file implements parsing for C++ class inline methods.
11193326Sed//
12193326Sed//===----------------------------------------------------------------------===//
13193326Sed
14193326Sed#include "clang/Parse/ParseDiagnostic.h"
15193326Sed#include "clang/Parse/Parser.h"
16212904Sdim#include "clang/Sema/DeclSpec.h"
17212904Sdim#include "clang/Sema/Scope.h"
18221345Sdim#include "clang/AST/DeclTemplate.h"
19239462Sdim#include "RAIIObjectsForParser.h"
20193326Sedusing namespace clang;
21193326Sed
22193326Sed/// ParseCXXInlineMethodDef - We parsed and verified that the specified
23193326Sed/// Declarator is a well formed C++ inline method definition. Now lex its body
24193326Sed/// and store its tokens for parsing after the C++ class is complete.
25226633SdimDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,
26226633Sdim                                      AttributeList *AccessAttrs,
27226633Sdim                                      ParsingDeclarator &D,
28234353Sdim                                      const ParsedTemplateInfo &TemplateInfo,
29234353Sdim                                      const VirtSpecifiers& VS,
30234353Sdim                                      FunctionDefinitionKind DefinitionKind,
31234353Sdim                                      ExprResult& Init) {
32218893Sdim  assert(D.isFunctionDeclarator() && "This isn't a function declarator!");
33223017Sdim  assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try) ||
34223017Sdim          Tok.is(tok::equal)) &&
35223017Sdim         "Current token not a '{', ':', '=', or 'try'!");
36193326Sed
37243830Sdim  MultiTemplateParamsArg TemplateParams(
38207619Srdivacky          TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->data() : 0,
39207619Srdivacky          TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->size() : 0);
40207619Srdivacky
41212904Sdim  Decl *FnD;
42234353Sdim  D.setFunctionDefinitionKind(DefinitionKind);
43198092Srdivacky  if (D.getDeclSpec().isFriendSpecified())
44226633Sdim    FnD = Actions.ActOnFriendFunctionDecl(getCurScope(), D,
45243830Sdim                                          TemplateParams);
46226633Sdim  else {
47210299Sed    FnD = Actions.ActOnCXXMemberDeclarator(getCurScope(), AS, D,
48243830Sdim                                           TemplateParams, 0,
49239462Sdim                                           VS, ICIS_NoInit);
50226633Sdim    if (FnD) {
51226633Sdim      Actions.ProcessDeclAttributeList(getCurScope(), FnD, AccessAttrs,
52226633Sdim                                       false, true);
53226633Sdim      bool TypeSpecContainsAuto
54226633Sdim        = D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto;
55234353Sdim      if (Init.isUsable())
56226633Sdim        Actions.AddInitializerToDecl(FnD, Init.get(), false,
57226633Sdim                                     TypeSpecContainsAuto);
58226633Sdim      else
59226633Sdim        Actions.ActOnUninitializedDecl(FnD, TypeSpecContainsAuto);
60226633Sdim    }
61218893Sdim  }
62193326Sed
63234982Sdim  HandleMemberFunctionDeclDelays(D, FnD);
64198092Srdivacky
65218893Sdim  D.complete(FnD);
66218893Sdim
67223017Sdim  if (Tok.is(tok::equal)) {
68223017Sdim    ConsumeToken();
69223017Sdim
70234353Sdim    if (!FnD) {
71234353Sdim      SkipUntil(tok::semi);
72234353Sdim      return 0;
73234353Sdim    }
74234353Sdim
75223017Sdim    bool Delete = false;
76223017Sdim    SourceLocation KWLoc;
77223017Sdim    if (Tok.is(tok::kw_delete)) {
78234353Sdim      Diag(Tok, getLangOpts().CPlusPlus0x ?
79234353Sdim           diag::warn_cxx98_compat_deleted_function :
80234353Sdim           diag::ext_deleted_function);
81223017Sdim
82223017Sdim      KWLoc = ConsumeToken();
83223017Sdim      Actions.SetDeclDeleted(FnD, KWLoc);
84223017Sdim      Delete = true;
85223017Sdim    } else if (Tok.is(tok::kw_default)) {
86234353Sdim      Diag(Tok, getLangOpts().CPlusPlus0x ?
87234353Sdim           diag::warn_cxx98_compat_defaulted_function :
88234353Sdim           diag::ext_defaulted_function);
89223017Sdim
90223017Sdim      KWLoc = ConsumeToken();
91223017Sdim      Actions.SetDeclDefaulted(FnD, KWLoc);
92223017Sdim    } else {
93223017Sdim      llvm_unreachable("function definition after = not 'delete' or 'default'");
94223017Sdim    }
95223017Sdim
96223017Sdim    if (Tok.is(tok::comma)) {
97223017Sdim      Diag(KWLoc, diag::err_default_delete_in_multiple_declaration)
98223017Sdim        << Delete;
99223017Sdim      SkipUntil(tok::semi);
100223017Sdim    } else {
101223017Sdim      ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
102223017Sdim                       Delete ? "delete" : "default", tok::semi);
103223017Sdim    }
104223017Sdim
105223017Sdim    return FnD;
106223017Sdim  }
107223017Sdim
108221345Sdim  // In delayed template parsing mode, if we are within a class template
109221345Sdim  // or if we are about to parse function member template then consume
110221345Sdim  // the tokens and store them for parsing at the end of the translation unit.
111234353Sdim  if (getLangOpts().DelayedTemplateParsing &&
112239462Sdim      DefinitionKind == FDK_Definition &&
113221345Sdim      ((Actions.CurContext->isDependentContext() ||
114221345Sdim        TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate) &&
115234353Sdim        !Actions.IsInsideALocalClassWithinATemplateFunction())) {
116221345Sdim
117221345Sdim    if (FnD) {
118234353Sdim      LateParsedTemplatedFunction *LPT = new LateParsedTemplatedFunction(FnD);
119221345Sdim
120221345Sdim      FunctionDecl *FD = 0;
121221345Sdim      if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(FnD))
122221345Sdim        FD = FunTmpl->getTemplatedDecl();
123221345Sdim      else
124221345Sdim        FD = cast<FunctionDecl>(FnD);
125221345Sdim      Actions.CheckForFunctionRedefinition(FD);
126221345Sdim
127221345Sdim      LateParsedTemplateMap[FD] = LPT;
128221345Sdim      Actions.MarkAsLateParsedTemplate(FD);
129221345Sdim      LexTemplateFunctionForLateParsing(LPT->Toks);
130221345Sdim    } else {
131221345Sdim      CachedTokens Toks;
132221345Sdim      LexTemplateFunctionForLateParsing(Toks);
133221345Sdim    }
134221345Sdim
135221345Sdim    return FnD;
136221345Sdim  }
137221345Sdim
138193326Sed  // Consume the tokens and store them for later parsing.
139193326Sed
140218893Sdim  LexedMethod* LM = new LexedMethod(this, FnD);
141218893Sdim  getCurrentClass().LateParsedDeclarations.push_back(LM);
142218893Sdim  LM->TemplateScope = getCurScope()->isTemplateParamScope();
143218893Sdim  CachedTokens &Toks = LM->Toks;
144193326Sed
145193326Sed  tok::TokenKind kind = Tok.getKind();
146226633Sdim  // Consume everything up to (and including) the left brace of the
147226633Sdim  // function body.
148226633Sdim  if (ConsumeAndStoreFunctionPrologue(Toks)) {
149226633Sdim    // We didn't find the left-brace we expected after the
150234353Sdim    // constructor initializer; we already printed an error, and it's likely
151234353Sdim    // impossible to recover, so don't try to parse this method later.
152234353Sdim    // If we stopped at a semicolon, consume it to avoid an extra warning.
153234353Sdim     if (Tok.is(tok::semi))
154234353Sdim      ConsumeToken();
155234353Sdim    delete getCurrentClass().LateParsedDeclarations.back();
156234353Sdim    getCurrentClass().LateParsedDeclarations.pop_back();
157234353Sdim    return FnD;
158193326Sed  } else {
159226633Sdim    // Consume everything up to (and including) the matching right brace.
160226633Sdim    ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false);
161193326Sed  }
162193326Sed
163193326Sed  // If we're in a function-try-block, we need to store all the catch blocks.
164193326Sed  if (kind == tok::kw_try) {
165193326Sed    while (Tok.is(tok::kw_catch)) {
166207619Srdivacky      ConsumeAndStoreUntil(tok::l_brace, Toks, /*StopAtSemi=*/false);
167207619Srdivacky      ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false);
168193326Sed    }
169193326Sed  }
170193326Sed
171221345Sdim
172221345Sdim  if (!FnD) {
173221345Sdim    // If semantic analysis could not build a function declaration,
174221345Sdim    // just throw away the late-parsed declaration.
175221345Sdim    delete getCurrentClass().LateParsedDeclarations.back();
176221345Sdim    getCurrentClass().LateParsedDeclarations.pop_back();
177221345Sdim  }
178221345Sdim
179193326Sed  return FnD;
180193326Sed}
181193326Sed
182223017Sdim/// ParseCXXNonStaticMemberInitializer - We parsed and verified that the
183223017Sdim/// specified Declarator is a well formed C++ non-static data member
184223017Sdim/// declaration. Now lex its initializer and store its tokens for parsing
185223017Sdim/// after the class is complete.
186223017Sdimvoid Parser::ParseCXXNonStaticMemberInitializer(Decl *VarD) {
187223017Sdim  assert((Tok.is(tok::l_brace) || Tok.is(tok::equal)) &&
188223017Sdim         "Current token not a '{' or '='!");
189223017Sdim
190223017Sdim  LateParsedMemberInitializer *MI =
191223017Sdim    new LateParsedMemberInitializer(this, VarD);
192223017Sdim  getCurrentClass().LateParsedDeclarations.push_back(MI);
193223017Sdim  CachedTokens &Toks = MI->Toks;
194223017Sdim
195223017Sdim  tok::TokenKind kind = Tok.getKind();
196223017Sdim  if (kind == tok::equal) {
197223017Sdim    Toks.push_back(Tok);
198234353Sdim    ConsumeToken();
199223017Sdim  }
200223017Sdim
201223017Sdim  if (kind == tok::l_brace) {
202223017Sdim    // Begin by storing the '{' token.
203223017Sdim    Toks.push_back(Tok);
204223017Sdim    ConsumeBrace();
205223017Sdim
206223017Sdim    // Consume everything up to (and including) the matching right brace.
207223017Sdim    ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/true);
208223017Sdim  } else {
209223017Sdim    // Consume everything up to (but excluding) the comma or semicolon.
210223017Sdim    ConsumeAndStoreUntil(tok::comma, Toks, /*StopAtSemi=*/true,
211223017Sdim                         /*ConsumeFinalToken=*/false);
212223017Sdim  }
213223017Sdim
214223017Sdim  // Store an artificial EOF token to ensure that we don't run off the end of
215223017Sdim  // the initializer when we come to parse it.
216223017Sdim  Token Eof;
217223017Sdim  Eof.startToken();
218223017Sdim  Eof.setKind(tok::eof);
219223017Sdim  Eof.setLocation(Tok.getLocation());
220223017Sdim  Toks.push_back(Eof);
221223017Sdim}
222223017Sdim
223218893SdimParser::LateParsedDeclaration::~LateParsedDeclaration() {}
224218893Sdimvoid Parser::LateParsedDeclaration::ParseLexedMethodDeclarations() {}
225223017Sdimvoid Parser::LateParsedDeclaration::ParseLexedMemberInitializers() {}
226218893Sdimvoid Parser::LateParsedDeclaration::ParseLexedMethodDefs() {}
227218893Sdim
228218893SdimParser::LateParsedClass::LateParsedClass(Parser *P, ParsingClass *C)
229218893Sdim  : Self(P), Class(C) {}
230218893Sdim
231218893SdimParser::LateParsedClass::~LateParsedClass() {
232218893Sdim  Self->DeallocateParsedClasses(Class);
233218893Sdim}
234218893Sdim
235218893Sdimvoid Parser::LateParsedClass::ParseLexedMethodDeclarations() {
236218893Sdim  Self->ParseLexedMethodDeclarations(*Class);
237218893Sdim}
238218893Sdim
239223017Sdimvoid Parser::LateParsedClass::ParseLexedMemberInitializers() {
240223017Sdim  Self->ParseLexedMemberInitializers(*Class);
241223017Sdim}
242223017Sdim
243218893Sdimvoid Parser::LateParsedClass::ParseLexedMethodDefs() {
244218893Sdim  Self->ParseLexedMethodDefs(*Class);
245218893Sdim}
246218893Sdim
247218893Sdimvoid Parser::LateParsedMethodDeclaration::ParseLexedMethodDeclarations() {
248218893Sdim  Self->ParseLexedMethodDeclaration(*this);
249218893Sdim}
250218893Sdim
251218893Sdimvoid Parser::LexedMethod::ParseLexedMethodDefs() {
252218893Sdim  Self->ParseLexedMethodDef(*this);
253218893Sdim}
254218893Sdim
255223017Sdimvoid Parser::LateParsedMemberInitializer::ParseLexedMemberInitializers() {
256223017Sdim  Self->ParseLexedMemberInitializer(*this);
257223017Sdim}
258223017Sdim
259193326Sed/// ParseLexedMethodDeclarations - We finished parsing the member
260193326Sed/// specification of a top (non-nested) C++ class. Now go over the
261193326Sed/// stack of method declarations with some parts for which parsing was
262193326Sed/// delayed (such as default arguments) and parse them.
263193326Sedvoid Parser::ParseLexedMethodDeclarations(ParsingClass &Class) {
264193326Sed  bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope;
265218893Sdim  ParseScope ClassTemplateScope(this, Scope::TemplateParamScope, HasTemplateScope);
266193326Sed  if (HasTemplateScope)
267210299Sed    Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate);
268193326Sed
269201361Srdivacky  // The current scope is still active if we're the top-level class.
270201361Srdivacky  // Otherwise we'll need to push and enter a new scope.
271193326Sed  bool HasClassScope = !Class.TopLevelClass;
272207619Srdivacky  ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope,
273207619Srdivacky                        HasClassScope);
274201361Srdivacky  if (HasClassScope)
275210299Sed    Actions.ActOnStartDelayedMemberDeclarations(getCurScope(), Class.TagOrTemplate);
276193326Sed
277218893Sdim  for (size_t i = 0; i < Class.LateParsedDeclarations.size(); ++i) {
278218893Sdim    Class.LateParsedDeclarations[i]->ParseLexedMethodDeclarations();
279218893Sdim  }
280193326Sed
281218893Sdim  if (HasClassScope)
282218893Sdim    Actions.ActOnFinishDelayedMemberDeclarations(getCurScope(), Class.TagOrTemplate);
283218893Sdim}
284198092Srdivacky
285218893Sdimvoid Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
286218893Sdim  // If this is a member template, introduce the template parameter scope.
287218893Sdim  ParseScope TemplateScope(this, Scope::TemplateParamScope, LM.TemplateScope);
288218893Sdim  if (LM.TemplateScope)
289218893Sdim    Actions.ActOnReenterTemplateScope(getCurScope(), LM.Method);
290193326Sed
291218893Sdim  // Start the delayed C++ method declaration
292218893Sdim  Actions.ActOnStartDelayedCXXMethodDeclaration(getCurScope(), LM.Method);
293193326Sed
294218893Sdim  // Introduce the parameters into scope and parse their default
295218893Sdim  // arguments.
296218893Sdim  ParseScope PrototypeScope(this,
297218893Sdim                            Scope::FunctionPrototypeScope|Scope::DeclScope);
298218893Sdim  for (unsigned I = 0, N = LM.DefaultArgs.size(); I != N; ++I) {
299218893Sdim    // Introduce the parameter into scope.
300234353Sdim    Actions.ActOnDelayedCXXMethodParameter(getCurScope(),
301234353Sdim                                           LM.DefaultArgs[I].Param);
302206084Srdivacky
303218893Sdim    if (CachedTokens *Toks = LM.DefaultArgs[I].Toks) {
304218893Sdim      // Save the current token position.
305218893Sdim      SourceLocation origLoc = Tok.getLocation();
306193326Sed
307218893Sdim      // Parse the default argument from its saved token stream.
308218893Sdim      Toks->push_back(Tok); // So that the current token doesn't get lost
309218893Sdim      PP.EnterTokenStream(&Toks->front(), Toks->size(), true, false);
310193326Sed
311218893Sdim      // Consume the previously-pushed token.
312218893Sdim      ConsumeAnyToken();
313193326Sed
314218893Sdim      // Consume the '='.
315218893Sdim      assert(Tok.is(tok::equal) && "Default argument not starting with '='");
316218893Sdim      SourceLocation EqualLoc = ConsumeToken();
317206084Srdivacky
318218893Sdim      // The argument isn't actually potentially evaluated unless it is
319218893Sdim      // used.
320218893Sdim      EnterExpressionEvaluationContext Eval(Actions,
321234353Sdim                                            Sema::PotentiallyEvaluatedIfUsed,
322234353Sdim                                            LM.DefaultArgs[I].Param);
323206084Srdivacky
324234353Sdim      ExprResult DefArgResult;
325234353Sdim      if (getLangOpts().CPlusPlus0x && Tok.is(tok::l_brace)) {
326234353Sdim        Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
327234353Sdim        DefArgResult = ParseBraceInitializer();
328234353Sdim      } else
329234353Sdim        DefArgResult = ParseAssignmentExpression();
330218893Sdim      if (DefArgResult.isInvalid())
331218893Sdim        Actions.ActOnParamDefaultArgumentError(LM.DefaultArgs[I].Param);
332218893Sdim      else {
333218893Sdim        if (Tok.is(tok::cxx_defaultarg_end))
334218893Sdim          ConsumeToken();
335218893Sdim        else
336218893Sdim          Diag(Tok.getLocation(), diag::err_default_arg_unparsed);
337218893Sdim        Actions.ActOnParamDefaultArgument(LM.DefaultArgs[I].Param, EqualLoc,
338218893Sdim                                          DefArgResult.take());
339193326Sed      }
340218893Sdim
341218893Sdim      assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc,
342218893Sdim                                                         Tok.getLocation()) &&
343218893Sdim             "ParseAssignmentExpression went over the default arg tokens!");
344218893Sdim      // There could be leftover tokens (e.g. because of an error).
345218893Sdim      // Skip through until we reach the original token position.
346218893Sdim      while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof))
347218893Sdim        ConsumeAnyToken();
348218893Sdim
349218893Sdim      delete Toks;
350218893Sdim      LM.DefaultArgs[I].Toks = 0;
351193326Sed    }
352193326Sed  }
353234982Sdim
354218893Sdim  PrototypeScope.Exit();
355193326Sed
356218893Sdim  // Finish the delayed C++ method declaration.
357218893Sdim  Actions.ActOnFinishDelayedCXXMethodDeclaration(getCurScope(), LM.Method);
358193326Sed}
359193326Sed
360193326Sed/// ParseLexedMethodDefs - We finished parsing the member specification of a top
361193326Sed/// (non-nested) C++ class. Now go over the stack of lexed methods that were
362193326Sed/// collected during its parsing and parse them all.
363193326Sedvoid Parser::ParseLexedMethodDefs(ParsingClass &Class) {
364193326Sed  bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope;
365218893Sdim  ParseScope ClassTemplateScope(this, Scope::TemplateParamScope, HasTemplateScope);
366193326Sed  if (HasTemplateScope)
367210299Sed    Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate);
368193326Sed
369193326Sed  bool HasClassScope = !Class.TopLevelClass;
370193326Sed  ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope,
371193326Sed                        HasClassScope);
372193326Sed
373218893Sdim  for (size_t i = 0; i < Class.LateParsedDeclarations.size(); ++i) {
374218893Sdim    Class.LateParsedDeclarations[i]->ParseLexedMethodDefs();
375218893Sdim  }
376218893Sdim}
377193326Sed
378218893Sdimvoid Parser::ParseLexedMethodDef(LexedMethod &LM) {
379218893Sdim  // If this is a member template, introduce the template parameter scope.
380218893Sdim  ParseScope TemplateScope(this, Scope::TemplateParamScope, LM.TemplateScope);
381218893Sdim  if (LM.TemplateScope)
382218893Sdim    Actions.ActOnReenterTemplateScope(getCurScope(), LM.D);
383198092Srdivacky
384218893Sdim  // Save the current token position.
385218893Sdim  SourceLocation origLoc = Tok.getLocation();
386206084Srdivacky
387218893Sdim  assert(!LM.Toks.empty() && "Empty body!");
388218893Sdim  // Append the current token at the end of the new token stream so that it
389218893Sdim  // doesn't get lost.
390218893Sdim  LM.Toks.push_back(Tok);
391218893Sdim  PP.EnterTokenStream(LM.Toks.data(), LM.Toks.size(), true, false);
392193326Sed
393218893Sdim  // Consume the previously pushed token.
394218893Sdim  ConsumeAnyToken();
395218893Sdim  assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try))
396218893Sdim         && "Inline method not starting with '{', ':' or 'try'");
397193326Sed
398218893Sdim  // Parse the method body. Function body parsing code is similar enough
399218893Sdim  // to be re-used for method bodies as well.
400218893Sdim  ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope);
401218893Sdim  Actions.ActOnStartOfFunctionDef(getCurScope(), LM.D);
402193326Sed
403218893Sdim  if (Tok.is(tok::kw_try)) {
404221345Sdim    ParseFunctionTryBlock(LM.D, FnScope);
405218893Sdim    assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc,
406218893Sdim                                                         Tok.getLocation()) &&
407218893Sdim           "ParseFunctionTryBlock went over the cached tokens!");
408218893Sdim    // There could be leftover tokens (e.g. because of an error).
409218893Sdim    // Skip through until we reach the original token position.
410218893Sdim    while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof))
411218893Sdim      ConsumeAnyToken();
412218893Sdim    return;
413218893Sdim  }
414218893Sdim  if (Tok.is(tok::colon)) {
415218893Sdim    ParseConstructorInitializer(LM.D);
416218893Sdim
417218893Sdim    // Error recovery.
418218893Sdim    if (!Tok.is(tok::l_brace)) {
419221345Sdim      FnScope.Exit();
420218893Sdim      Actions.ActOnFinishFunctionBody(LM.D, 0);
421226633Sdim      while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof))
422226633Sdim        ConsumeAnyToken();
423218893Sdim      return;
424193326Sed    }
425218893Sdim  } else
426218893Sdim    Actions.ActOnDefaultCtorInitializers(LM.D);
427207619Srdivacky
428221345Sdim  ParseFunctionStatementBody(LM.D, FnScope);
429198092Srdivacky
430218893Sdim  if (Tok.getLocation() != origLoc) {
431218893Sdim    // Due to parsing error, we either went over the cached tokens or
432218893Sdim    // there are still cached tokens left. If it's the latter case skip the
433218893Sdim    // leftover tokens.
434218893Sdim    // Since this is an uncommon situation that should be avoided, use the
435218893Sdim    // expensive isBeforeInTranslationUnit call.
436218893Sdim    if (PP.getSourceManager().isBeforeInTranslationUnit(Tok.getLocation(),
437218893Sdim                                                        origLoc))
438218893Sdim      while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof))
439218893Sdim        ConsumeAnyToken();
440223017Sdim  }
441223017Sdim}
442210299Sed
443223017Sdim/// ParseLexedMemberInitializers - We finished parsing the member specification
444223017Sdim/// of a top (non-nested) C++ class. Now go over the stack of lexed data member
445223017Sdim/// initializers that were collected during its parsing and parse them all.
446223017Sdimvoid Parser::ParseLexedMemberInitializers(ParsingClass &Class) {
447223017Sdim  bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope;
448223017Sdim  ParseScope ClassTemplateScope(this, Scope::TemplateParamScope,
449223017Sdim                                HasTemplateScope);
450223017Sdim  if (HasTemplateScope)
451223017Sdim    Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate);
452223017Sdim
453234982Sdim  // Set or update the scope flags.
454223017Sdim  bool AlreadyHasClassScope = Class.TopLevelClass;
455234982Sdim  unsigned ScopeFlags = Scope::ClassScope|Scope::DeclScope;
456223017Sdim  ParseScope ClassScope(this, ScopeFlags, !AlreadyHasClassScope);
457223017Sdim  ParseScopeFlags ClassScopeFlags(this, ScopeFlags, AlreadyHasClassScope);
458223017Sdim
459223017Sdim  if (!AlreadyHasClassScope)
460223017Sdim    Actions.ActOnStartDelayedMemberDeclarations(getCurScope(),
461223017Sdim                                                Class.TagOrTemplate);
462223017Sdim
463239462Sdim  if (!Class.LateParsedDeclarations.empty()) {
464234982Sdim    // C++11 [expr.prim.general]p4:
465234982Sdim    //   Otherwise, if a member-declarator declares a non-static data member
466234982Sdim    //  (9.2) of a class X, the expression this is a prvalue of type "pointer
467234982Sdim    //  to X" within the optional brace-or-equal-initializer. It shall not
468234982Sdim    //  appear elsewhere in the member-declarator.
469234982Sdim    Sema::CXXThisScopeRAII ThisScope(Actions, Class.TagOrTemplate,
470234982Sdim                                     /*TypeQuals=*/(unsigned)0);
471234982Sdim
472234982Sdim    for (size_t i = 0; i < Class.LateParsedDeclarations.size(); ++i) {
473234982Sdim      Class.LateParsedDeclarations[i]->ParseLexedMemberInitializers();
474234982Sdim    }
475193326Sed  }
476234982Sdim
477223017Sdim  if (!AlreadyHasClassScope)
478223017Sdim    Actions.ActOnFinishDelayedMemberDeclarations(getCurScope(),
479223017Sdim                                                 Class.TagOrTemplate);
480223017Sdim
481223017Sdim  Actions.ActOnFinishDelayedMemberInitializers(Class.TagOrTemplate);
482193326Sed}
483193326Sed
484223017Sdimvoid Parser::ParseLexedMemberInitializer(LateParsedMemberInitializer &MI) {
485226633Sdim  if (!MI.Field || MI.Field->isInvalidDecl())
486223017Sdim    return;
487223017Sdim
488223017Sdim  // Append the current token at the end of the new token stream so that it
489223017Sdim  // doesn't get lost.
490223017Sdim  MI.Toks.push_back(Tok);
491223017Sdim  PP.EnterTokenStream(MI.Toks.data(), MI.Toks.size(), true, false);
492223017Sdim
493223017Sdim  // Consume the previously pushed token.
494223017Sdim  ConsumeAnyToken();
495223017Sdim
496223017Sdim  SourceLocation EqualLoc;
497239462Sdim
498234353Sdim  ExprResult Init = ParseCXXMemberInitializer(MI.Field, /*IsFunction=*/false,
499234353Sdim                                              EqualLoc);
500223017Sdim
501223017Sdim  Actions.ActOnCXXInClassMemberInitializer(MI.Field, EqualLoc, Init.release());
502223017Sdim
503223017Sdim  // The next token should be our artificial terminating EOF token.
504223017Sdim  if (Tok.isNot(tok::eof)) {
505223017Sdim    SourceLocation EndLoc = PP.getLocForEndOfToken(PrevTokLocation);
506223017Sdim    if (!EndLoc.isValid())
507223017Sdim      EndLoc = Tok.getLocation();
508223017Sdim    // No fixit; we can't recover as if there were a semicolon here.
509223017Sdim    Diag(EndLoc, diag::err_expected_semi_decl_list);
510223017Sdim
511223017Sdim    // Consume tokens until we hit the artificial EOF.
512223017Sdim    while (Tok.isNot(tok::eof))
513223017Sdim      ConsumeAnyToken();
514223017Sdim  }
515223017Sdim  ConsumeAnyToken();
516223017Sdim}
517223017Sdim
518193326Sed/// ConsumeAndStoreUntil - Consume and store the token at the passed token
519193326Sed/// container until the token 'T' is reached (which gets
520198092Srdivacky/// consumed/stored too, if ConsumeFinalToken).
521207619Srdivacky/// If StopAtSemi is true, then we will stop early at a ';' character.
522193326Sed/// Returns true if token 'T1' or 'T2' was found.
523193326Sed/// NOTE: This is a specialized version of Parser::SkipUntil.
524193326Sedbool Parser::ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2,
525193326Sed                                  CachedTokens &Toks,
526207619Srdivacky                                  bool StopAtSemi, bool ConsumeFinalToken) {
527193326Sed  // We always want this function to consume at least one token if the first
528193326Sed  // token isn't T and if not at EOF.
529193326Sed  bool isFirstTokenConsumed = true;
530193326Sed  while (1) {
531193326Sed    // If we found one of the tokens, stop and return true.
532193326Sed    if (Tok.is(T1) || Tok.is(T2)) {
533193326Sed      if (ConsumeFinalToken) {
534193326Sed        Toks.push_back(Tok);
535193326Sed        ConsumeAnyToken();
536193326Sed      }
537193326Sed      return true;
538193326Sed    }
539193326Sed
540193326Sed    switch (Tok.getKind()) {
541193326Sed    case tok::eof:
542193326Sed      // Ran out of tokens.
543193326Sed      return false;
544193326Sed
545193326Sed    case tok::l_paren:
546193326Sed      // Recursively consume properly-nested parens.
547193326Sed      Toks.push_back(Tok);
548193326Sed      ConsumeParen();
549207619Srdivacky      ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/false);
550193326Sed      break;
551193326Sed    case tok::l_square:
552193326Sed      // Recursively consume properly-nested square brackets.
553193326Sed      Toks.push_back(Tok);
554193326Sed      ConsumeBracket();
555207619Srdivacky      ConsumeAndStoreUntil(tok::r_square, Toks, /*StopAtSemi=*/false);
556193326Sed      break;
557193326Sed    case tok::l_brace:
558193326Sed      // Recursively consume properly-nested braces.
559193326Sed      Toks.push_back(Tok);
560193326Sed      ConsumeBrace();
561207619Srdivacky      ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false);
562193326Sed      break;
563193326Sed
564193326Sed    // Okay, we found a ']' or '}' or ')', which we think should be balanced.
565193326Sed    // Since the user wasn't looking for this token (if they were, it would
566193326Sed    // already be handled), this isn't balanced.  If there is a LHS token at a
567193326Sed    // higher level, we will assume that this matches the unbalanced token
568193326Sed    // and return it.  Otherwise, this is a spurious RHS token, which we skip.
569193326Sed    case tok::r_paren:
570193326Sed      if (ParenCount && !isFirstTokenConsumed)
571193326Sed        return false;  // Matches something.
572193326Sed      Toks.push_back(Tok);
573193326Sed      ConsumeParen();
574193326Sed      break;
575193326Sed    case tok::r_square:
576193326Sed      if (BracketCount && !isFirstTokenConsumed)
577193326Sed        return false;  // Matches something.
578193326Sed      Toks.push_back(Tok);
579193326Sed      ConsumeBracket();
580193326Sed      break;
581193326Sed    case tok::r_brace:
582193326Sed      if (BraceCount && !isFirstTokenConsumed)
583193326Sed        return false;  // Matches something.
584193326Sed      Toks.push_back(Tok);
585193326Sed      ConsumeBrace();
586193326Sed      break;
587193326Sed
588226633Sdim    case tok::code_completion:
589226633Sdim      Toks.push_back(Tok);
590226633Sdim      ConsumeCodeCompletionToken();
591226633Sdim      break;
592226633Sdim
593193326Sed    case tok::string_literal:
594193326Sed    case tok::wide_string_literal:
595226633Sdim    case tok::utf8_string_literal:
596226633Sdim    case tok::utf16_string_literal:
597226633Sdim    case tok::utf32_string_literal:
598193326Sed      Toks.push_back(Tok);
599193326Sed      ConsumeStringToken();
600193326Sed      break;
601207619Srdivacky    case tok::semi:
602207619Srdivacky      if (StopAtSemi)
603207619Srdivacky        return false;
604207619Srdivacky      // FALL THROUGH.
605193326Sed    default:
606193326Sed      // consume this token.
607193326Sed      Toks.push_back(Tok);
608193326Sed      ConsumeToken();
609193326Sed      break;
610193326Sed    }
611193326Sed    isFirstTokenConsumed = false;
612193326Sed  }
613193326Sed}
614226633Sdim
615226633Sdim/// \brief Consume tokens and store them in the passed token container until
616226633Sdim/// we've passed the try keyword and constructor initializers and have consumed
617226633Sdim/// the opening brace of the function body. The opening brace will be consumed
618226633Sdim/// if and only if there was no error.
619226633Sdim///
620226633Sdim/// \return True on error.
621226633Sdimbool Parser::ConsumeAndStoreFunctionPrologue(CachedTokens &Toks) {
622226633Sdim  if (Tok.is(tok::kw_try)) {
623226633Sdim    Toks.push_back(Tok);
624226633Sdim    ConsumeToken();
625226633Sdim  }
626234353Sdim  bool ReadInitializer = false;
627226633Sdim  if (Tok.is(tok::colon)) {
628226633Sdim    // Initializers can contain braces too.
629226633Sdim    Toks.push_back(Tok);
630226633Sdim    ConsumeToken();
631226633Sdim
632226633Sdim    while (Tok.is(tok::identifier) || Tok.is(tok::coloncolon)) {
633226633Sdim      if (Tok.is(tok::eof) || Tok.is(tok::semi))
634234353Sdim        return Diag(Tok.getLocation(), diag::err_expected_lbrace);
635226633Sdim
636226633Sdim      // Grab the identifier.
637226633Sdim      if (!ConsumeAndStoreUntil(tok::l_paren, tok::l_brace, Toks,
638226633Sdim                                /*StopAtSemi=*/true,
639226633Sdim                                /*ConsumeFinalToken=*/false))
640234353Sdim        return Diag(Tok.getLocation(), diag::err_expected_lparen);
641226633Sdim
642226633Sdim      tok::TokenKind kind = Tok.getKind();
643226633Sdim      Toks.push_back(Tok);
644234353Sdim      bool IsLParen = (kind == tok::l_paren);
645234353Sdim      SourceLocation LOpen = Tok.getLocation();
646234353Sdim
647234353Sdim      if (IsLParen) {
648226633Sdim        ConsumeParen();
649234353Sdim      } else {
650226633Sdim        assert(kind == tok::l_brace && "Must be left paren or brace here.");
651226633Sdim        ConsumeBrace();
652226633Sdim        // In C++03, this has to be the start of the function body, which
653234353Sdim        // means the initializer is malformed; we'll diagnose it later.
654234353Sdim        if (!getLangOpts().CPlusPlus0x)
655226633Sdim          return false;
656226633Sdim      }
657226633Sdim
658226633Sdim      // Grab the initializer
659234353Sdim      if (!ConsumeAndStoreUntil(IsLParen ? tok::r_paren : tok::r_brace,
660234353Sdim                                Toks, /*StopAtSemi=*/true)) {
661234353Sdim        Diag(Tok, IsLParen ? diag::err_expected_rparen :
662234353Sdim                             diag::err_expected_rbrace);
663234353Sdim        Diag(LOpen, diag::note_matching) << (IsLParen ? "(" : "{");
664226633Sdim        return true;
665234353Sdim      }
666226633Sdim
667234353Sdim      // Grab pack ellipsis, if present
668234353Sdim      if (Tok.is(tok::ellipsis)) {
669234353Sdim        Toks.push_back(Tok);
670234353Sdim        ConsumeToken();
671234353Sdim      }
672234353Sdim
673226633Sdim      // Grab the separating comma, if any.
674226633Sdim      if (Tok.is(tok::comma)) {
675226633Sdim        Toks.push_back(Tok);
676226633Sdim        ConsumeToken();
677234353Sdim      } else if (Tok.isNot(tok::l_brace)) {
678234353Sdim        ReadInitializer = true;
679234353Sdim        break;
680226633Sdim      }
681226633Sdim    }
682226633Sdim  }
683226633Sdim
684226633Sdim  // Grab any remaining garbage to be diagnosed later. We stop when we reach a
685226633Sdim  // brace: an opening one is the function body, while a closing one probably
686226633Sdim  // means we've reached the end of the class.
687234353Sdim  ConsumeAndStoreUntil(tok::l_brace, tok::r_brace, Toks,
688234353Sdim                       /*StopAtSemi=*/true,
689234353Sdim                       /*ConsumeFinalToken=*/false);
690234353Sdim  if (Tok.isNot(tok::l_brace)) {
691234353Sdim    if (ReadInitializer)
692234353Sdim      return Diag(Tok.getLocation(), diag::err_expected_lbrace_or_comma);
693234353Sdim    return Diag(Tok.getLocation(), diag::err_expected_lbrace);
694234353Sdim  }
695226633Sdim
696226633Sdim  Toks.push_back(Tok);
697226633Sdim  ConsumeBrace();
698226633Sdim  return false;
699226633Sdim}
700