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