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 14249423Sdim#include "clang/Parse/Parser.h" 15249423Sdim#include "RAIIObjectsForParser.h" 16249423Sdim#include "clang/AST/DeclTemplate.h" 17193326Sed#include "clang/Parse/ParseDiagnostic.h" 18212904Sdim#include "clang/Sema/DeclSpec.h" 19212904Sdim#include "clang/Sema/Scope.h" 20193326Sedusing namespace clang; 21193326Sed 22249423Sdim/// Get the FunctionDecl for a function or function template decl. 23249423Sdimstatic FunctionDecl *getFunctionDecl(Decl *D) { 24249423Sdim if (FunctionDecl *fn = dyn_cast<FunctionDecl>(D)) 25249423Sdim return fn; 26249423Sdim return cast<FunctionTemplateDecl>(D)->getTemplatedDecl(); 27249423Sdim} 28249423Sdim 29193326Sed/// ParseCXXInlineMethodDef - We parsed and verified that the specified 30193326Sed/// Declarator is a well formed C++ inline method definition. Now lex its body 31193326Sed/// and store its tokens for parsing after the C++ class is complete. 32249423SdimNamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, 33226633Sdim AttributeList *AccessAttrs, 34226633Sdim ParsingDeclarator &D, 35234353Sdim const ParsedTemplateInfo &TemplateInfo, 36234353Sdim const VirtSpecifiers& VS, 37234353Sdim FunctionDefinitionKind DefinitionKind, 38234353Sdim ExprResult& Init) { 39218893Sdim assert(D.isFunctionDeclarator() && "This isn't a function declarator!"); 40223017Sdim assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try) || 41223017Sdim Tok.is(tok::equal)) && 42223017Sdim "Current token not a '{', ':', '=', or 'try'!"); 43193326Sed 44243830Sdim MultiTemplateParamsArg TemplateParams( 45207619Srdivacky TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->data() : 0, 46207619Srdivacky TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->size() : 0); 47207619Srdivacky 48249423Sdim NamedDecl *FnD; 49234353Sdim D.setFunctionDefinitionKind(DefinitionKind); 50198092Srdivacky if (D.getDeclSpec().isFriendSpecified()) 51226633Sdim FnD = Actions.ActOnFriendFunctionDecl(getCurScope(), D, 52243830Sdim TemplateParams); 53226633Sdim else { 54210299Sed FnD = Actions.ActOnCXXMemberDeclarator(getCurScope(), AS, D, 55243830Sdim TemplateParams, 0, 56239462Sdim VS, ICIS_NoInit); 57226633Sdim if (FnD) { 58263508Sdim Actions.ProcessDeclAttributeList(getCurScope(), FnD, AccessAttrs); 59251662Sdim bool TypeSpecContainsAuto = D.getDeclSpec().containsPlaceholderType(); 60234353Sdim if (Init.isUsable()) 61263508Sdim Actions.AddInitializerToDecl(FnD, Init.get(), false, 62226633Sdim TypeSpecContainsAuto); 63226633Sdim else 64226633Sdim Actions.ActOnUninitializedDecl(FnD, TypeSpecContainsAuto); 65226633Sdim } 66218893Sdim } 67193326Sed 68234982Sdim HandleMemberFunctionDeclDelays(D, FnD); 69198092Srdivacky 70218893Sdim D.complete(FnD); 71218893Sdim 72223017Sdim if (Tok.is(tok::equal)) { 73223017Sdim ConsumeToken(); 74223017Sdim 75234353Sdim if (!FnD) { 76234353Sdim SkipUntil(tok::semi); 77234353Sdim return 0; 78234353Sdim } 79234353Sdim 80223017Sdim bool Delete = false; 81223017Sdim SourceLocation KWLoc; 82223017Sdim if (Tok.is(tok::kw_delete)) { 83249423Sdim Diag(Tok, getLangOpts().CPlusPlus11 ? 84234353Sdim diag::warn_cxx98_compat_deleted_function : 85234353Sdim diag::ext_deleted_function); 86223017Sdim 87223017Sdim KWLoc = ConsumeToken(); 88223017Sdim Actions.SetDeclDeleted(FnD, KWLoc); 89223017Sdim Delete = true; 90223017Sdim } else if (Tok.is(tok::kw_default)) { 91249423Sdim Diag(Tok, getLangOpts().CPlusPlus11 ? 92234353Sdim diag::warn_cxx98_compat_defaulted_function : 93234353Sdim diag::ext_defaulted_function); 94223017Sdim 95223017Sdim KWLoc = ConsumeToken(); 96223017Sdim Actions.SetDeclDefaulted(FnD, KWLoc); 97223017Sdim } else { 98223017Sdim llvm_unreachable("function definition after = not 'delete' or 'default'"); 99223017Sdim } 100223017Sdim 101223017Sdim if (Tok.is(tok::comma)) { 102223017Sdim Diag(KWLoc, diag::err_default_delete_in_multiple_declaration) 103223017Sdim << Delete; 104223017Sdim SkipUntil(tok::semi); 105223017Sdim } else { 106223017Sdim ExpectAndConsume(tok::semi, diag::err_expected_semi_after, 107223017Sdim Delete ? "delete" : "default", tok::semi); 108223017Sdim } 109223017Sdim 110223017Sdim return FnD; 111223017Sdim } 112263508Sdim 113221345Sdim // In delayed template parsing mode, if we are within a class template 114221345Sdim // or if we are about to parse function member template then consume 115221345Sdim // the tokens and store them for parsing at the end of the translation unit. 116263508Sdim if (getLangOpts().DelayedTemplateParsing && 117263508Sdim DefinitionKind == FDK_Definition && 118263508Sdim !D.getDeclSpec().isConstexprSpecified() && 119263508Sdim !(FnD && getFunctionDecl(FnD) && 120263508Sdim getFunctionDecl(FnD)->getResultType()->getContainedAutoType()) && 121221345Sdim ((Actions.CurContext->isDependentContext() || 122263508Sdim (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate && 123263508Sdim TemplateInfo.Kind != ParsedTemplateInfo::ExplicitSpecialization)) && 124263508Sdim !Actions.IsInsideALocalClassWithinATemplateFunction())) { 125221345Sdim 126263508Sdim CachedTokens Toks; 127263508Sdim LexTemplateFunctionForLateParsing(Toks); 128263508Sdim 129221345Sdim if (FnD) { 130249423Sdim FunctionDecl *FD = getFunctionDecl(FnD); 131221345Sdim Actions.CheckForFunctionRedefinition(FD); 132263508Sdim Actions.MarkAsLateParsedTemplate(FD, FnD, 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. 152263508Sdim // Skip over the rest of the decl and back to somewhere that looks 153263508Sdim // reasonable. 154263508Sdim SkipMalformedDecl(); 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 171263508Sdim if (FnD) { 172263508Sdim // If this is a friend function, mark that it's late-parsed so that 173263508Sdim // it's still known to be a definition even before we attach the 174263508Sdim // parsed body. Sema needs to treat friend function definitions 175263508Sdim // differently during template instantiation, and it's possible for 176263508Sdim // the containing class to be instantiated before all its member 177263508Sdim // function definitions are parsed. 178263508Sdim // 179263508Sdim // If you remove this, you can remove the code that clears the flag 180263508Sdim // after parsing the member. 181263508Sdim if (D.getDeclSpec().isFriendSpecified()) { 182263508Sdim FunctionDecl *FD = getFunctionDecl(FnD); 183263508Sdim Actions.CheckForFunctionRedefinition(FD); 184263508Sdim FD->setLateTemplateParsed(true); 185263508Sdim } 186263508Sdim } else { 187221345Sdim // If semantic analysis could not build a function declaration, 188221345Sdim // just throw away the late-parsed declaration. 189221345Sdim delete getCurrentClass().LateParsedDeclarations.back(); 190221345Sdim getCurrentClass().LateParsedDeclarations.pop_back(); 191221345Sdim } 192221345Sdim 193193326Sed return FnD; 194193326Sed} 195193326Sed 196223017Sdim/// ParseCXXNonStaticMemberInitializer - We parsed and verified that the 197223017Sdim/// specified Declarator is a well formed C++ non-static data member 198223017Sdim/// declaration. Now lex its initializer and store its tokens for parsing 199223017Sdim/// after the class is complete. 200223017Sdimvoid Parser::ParseCXXNonStaticMemberInitializer(Decl *VarD) { 201223017Sdim assert((Tok.is(tok::l_brace) || Tok.is(tok::equal)) && 202223017Sdim "Current token not a '{' or '='!"); 203223017Sdim 204223017Sdim LateParsedMemberInitializer *MI = 205223017Sdim new LateParsedMemberInitializer(this, VarD); 206223017Sdim getCurrentClass().LateParsedDeclarations.push_back(MI); 207223017Sdim CachedTokens &Toks = MI->Toks; 208223017Sdim 209223017Sdim tok::TokenKind kind = Tok.getKind(); 210223017Sdim if (kind == tok::equal) { 211223017Sdim Toks.push_back(Tok); 212234353Sdim ConsumeToken(); 213223017Sdim } 214223017Sdim 215223017Sdim if (kind == tok::l_brace) { 216223017Sdim // Begin by storing the '{' token. 217223017Sdim Toks.push_back(Tok); 218223017Sdim ConsumeBrace(); 219223017Sdim 220223017Sdim // Consume everything up to (and including) the matching right brace. 221223017Sdim ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/true); 222223017Sdim } else { 223223017Sdim // Consume everything up to (but excluding) the comma or semicolon. 224263508Sdim ConsumeAndStoreInitializer(Toks, CIK_DefaultInitializer); 225223017Sdim } 226223017Sdim 227223017Sdim // Store an artificial EOF token to ensure that we don't run off the end of 228223017Sdim // the initializer when we come to parse it. 229223017Sdim Token Eof; 230223017Sdim Eof.startToken(); 231223017Sdim Eof.setKind(tok::eof); 232223017Sdim Eof.setLocation(Tok.getLocation()); 233223017Sdim Toks.push_back(Eof); 234223017Sdim} 235223017Sdim 236218893SdimParser::LateParsedDeclaration::~LateParsedDeclaration() {} 237218893Sdimvoid Parser::LateParsedDeclaration::ParseLexedMethodDeclarations() {} 238223017Sdimvoid Parser::LateParsedDeclaration::ParseLexedMemberInitializers() {} 239218893Sdimvoid Parser::LateParsedDeclaration::ParseLexedMethodDefs() {} 240218893Sdim 241218893SdimParser::LateParsedClass::LateParsedClass(Parser *P, ParsingClass *C) 242218893Sdim : Self(P), Class(C) {} 243218893Sdim 244218893SdimParser::LateParsedClass::~LateParsedClass() { 245218893Sdim Self->DeallocateParsedClasses(Class); 246218893Sdim} 247218893Sdim 248218893Sdimvoid Parser::LateParsedClass::ParseLexedMethodDeclarations() { 249218893Sdim Self->ParseLexedMethodDeclarations(*Class); 250218893Sdim} 251218893Sdim 252223017Sdimvoid Parser::LateParsedClass::ParseLexedMemberInitializers() { 253223017Sdim Self->ParseLexedMemberInitializers(*Class); 254223017Sdim} 255223017Sdim 256218893Sdimvoid Parser::LateParsedClass::ParseLexedMethodDefs() { 257218893Sdim Self->ParseLexedMethodDefs(*Class); 258218893Sdim} 259218893Sdim 260218893Sdimvoid Parser::LateParsedMethodDeclaration::ParseLexedMethodDeclarations() { 261218893Sdim Self->ParseLexedMethodDeclaration(*this); 262218893Sdim} 263218893Sdim 264218893Sdimvoid Parser::LexedMethod::ParseLexedMethodDefs() { 265218893Sdim Self->ParseLexedMethodDef(*this); 266218893Sdim} 267218893Sdim 268223017Sdimvoid Parser::LateParsedMemberInitializer::ParseLexedMemberInitializers() { 269223017Sdim Self->ParseLexedMemberInitializer(*this); 270223017Sdim} 271223017Sdim 272193326Sed/// ParseLexedMethodDeclarations - We finished parsing the member 273193326Sed/// specification of a top (non-nested) C++ class. Now go over the 274193326Sed/// stack of method declarations with some parts for which parsing was 275193326Sed/// delayed (such as default arguments) and parse them. 276193326Sedvoid Parser::ParseLexedMethodDeclarations(ParsingClass &Class) { 277193326Sed bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope; 278218893Sdim ParseScope ClassTemplateScope(this, Scope::TemplateParamScope, HasTemplateScope); 279251662Sdim TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth); 280251662Sdim if (HasTemplateScope) { 281210299Sed Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate); 282251662Sdim ++CurTemplateDepthTracker; 283251662Sdim } 284193326Sed 285201361Srdivacky // The current scope is still active if we're the top-level class. 286201361Srdivacky // Otherwise we'll need to push and enter a new scope. 287193326Sed bool HasClassScope = !Class.TopLevelClass; 288207619Srdivacky ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope, 289207619Srdivacky HasClassScope); 290201361Srdivacky if (HasClassScope) 291210299Sed Actions.ActOnStartDelayedMemberDeclarations(getCurScope(), Class.TagOrTemplate); 292193326Sed 293218893Sdim for (size_t i = 0; i < Class.LateParsedDeclarations.size(); ++i) { 294218893Sdim Class.LateParsedDeclarations[i]->ParseLexedMethodDeclarations(); 295218893Sdim } 296193326Sed 297218893Sdim if (HasClassScope) 298218893Sdim Actions.ActOnFinishDelayedMemberDeclarations(getCurScope(), Class.TagOrTemplate); 299218893Sdim} 300198092Srdivacky 301218893Sdimvoid Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { 302218893Sdim // If this is a member template, introduce the template parameter scope. 303218893Sdim ParseScope TemplateScope(this, Scope::TemplateParamScope, LM.TemplateScope); 304251662Sdim TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth); 305251662Sdim if (LM.TemplateScope) { 306218893Sdim Actions.ActOnReenterTemplateScope(getCurScope(), LM.Method); 307251662Sdim ++CurTemplateDepthTracker; 308251662Sdim } 309218893Sdim // Start the delayed C++ method declaration 310218893Sdim Actions.ActOnStartDelayedCXXMethodDeclaration(getCurScope(), LM.Method); 311193326Sed 312218893Sdim // Introduce the parameters into scope and parse their default 313218893Sdim // arguments. 314249423Sdim ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope | 315249423Sdim Scope::FunctionDeclarationScope | Scope::DeclScope); 316218893Sdim for (unsigned I = 0, N = LM.DefaultArgs.size(); I != N; ++I) { 317218893Sdim // Introduce the parameter into scope. 318234353Sdim Actions.ActOnDelayedCXXMethodParameter(getCurScope(), 319234353Sdim LM.DefaultArgs[I].Param); 320206084Srdivacky 321218893Sdim if (CachedTokens *Toks = LM.DefaultArgs[I].Toks) { 322218893Sdim // Save the current token position. 323218893Sdim SourceLocation origLoc = Tok.getLocation(); 324193326Sed 325218893Sdim // Parse the default argument from its saved token stream. 326218893Sdim Toks->push_back(Tok); // So that the current token doesn't get lost 327218893Sdim PP.EnterTokenStream(&Toks->front(), Toks->size(), true, false); 328193326Sed 329218893Sdim // Consume the previously-pushed token. 330218893Sdim ConsumeAnyToken(); 331193326Sed 332218893Sdim // Consume the '='. 333218893Sdim assert(Tok.is(tok::equal) && "Default argument not starting with '='"); 334218893Sdim SourceLocation EqualLoc = ConsumeToken(); 335206084Srdivacky 336218893Sdim // The argument isn't actually potentially evaluated unless it is 337218893Sdim // used. 338218893Sdim EnterExpressionEvaluationContext Eval(Actions, 339234353Sdim Sema::PotentiallyEvaluatedIfUsed, 340234353Sdim LM.DefaultArgs[I].Param); 341206084Srdivacky 342234353Sdim ExprResult DefArgResult; 343249423Sdim if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { 344234353Sdim Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists); 345234353Sdim DefArgResult = ParseBraceInitializer(); 346234353Sdim } else 347234353Sdim DefArgResult = ParseAssignmentExpression(); 348218893Sdim if (DefArgResult.isInvalid()) 349218893Sdim Actions.ActOnParamDefaultArgumentError(LM.DefaultArgs[I].Param); 350218893Sdim else { 351218893Sdim if (Tok.is(tok::cxx_defaultarg_end)) 352218893Sdim ConsumeToken(); 353263508Sdim else { 354263508Sdim // The last two tokens are the terminator and the saved value of 355263508Sdim // Tok; the last token in the default argument is the one before 356263508Sdim // those. 357263508Sdim assert(Toks->size() >= 3 && "expected a token in default arg"); 358263508Sdim Diag(Tok.getLocation(), diag::err_default_arg_unparsed) 359263508Sdim << SourceRange(Tok.getLocation(), 360263508Sdim (*Toks)[Toks->size() - 3].getLocation()); 361263508Sdim } 362218893Sdim Actions.ActOnParamDefaultArgument(LM.DefaultArgs[I].Param, EqualLoc, 363218893Sdim DefArgResult.take()); 364193326Sed } 365218893Sdim 366218893Sdim assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc, 367218893Sdim Tok.getLocation()) && 368218893Sdim "ParseAssignmentExpression went over the default arg tokens!"); 369218893Sdim // There could be leftover tokens (e.g. because of an error). 370218893Sdim // Skip through until we reach the original token position. 371218893Sdim while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof)) 372218893Sdim ConsumeAnyToken(); 373218893Sdim 374218893Sdim delete Toks; 375218893Sdim LM.DefaultArgs[I].Toks = 0; 376193326Sed } 377193326Sed } 378234982Sdim 379218893Sdim PrototypeScope.Exit(); 380193326Sed 381218893Sdim // Finish the delayed C++ method declaration. 382218893Sdim Actions.ActOnFinishDelayedCXXMethodDeclaration(getCurScope(), LM.Method); 383193326Sed} 384193326Sed 385193326Sed/// ParseLexedMethodDefs - We finished parsing the member specification of a top 386193326Sed/// (non-nested) C++ class. Now go over the stack of lexed methods that were 387193326Sed/// collected during its parsing and parse them all. 388193326Sedvoid Parser::ParseLexedMethodDefs(ParsingClass &Class) { 389193326Sed bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope; 390218893Sdim ParseScope ClassTemplateScope(this, Scope::TemplateParamScope, HasTemplateScope); 391251662Sdim TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth); 392251662Sdim if (HasTemplateScope) { 393210299Sed Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate); 394251662Sdim ++CurTemplateDepthTracker; 395251662Sdim } 396193326Sed bool HasClassScope = !Class.TopLevelClass; 397193326Sed ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope, 398193326Sed HasClassScope); 399193326Sed 400218893Sdim for (size_t i = 0; i < Class.LateParsedDeclarations.size(); ++i) { 401218893Sdim Class.LateParsedDeclarations[i]->ParseLexedMethodDefs(); 402218893Sdim } 403218893Sdim} 404193326Sed 405218893Sdimvoid Parser::ParseLexedMethodDef(LexedMethod &LM) { 406218893Sdim // If this is a member template, introduce the template parameter scope. 407218893Sdim ParseScope TemplateScope(this, Scope::TemplateParamScope, LM.TemplateScope); 408251662Sdim TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth); 409251662Sdim if (LM.TemplateScope) { 410218893Sdim Actions.ActOnReenterTemplateScope(getCurScope(), LM.D); 411251662Sdim ++CurTemplateDepthTracker; 412251662Sdim } 413218893Sdim // Save the current token position. 414218893Sdim SourceLocation origLoc = Tok.getLocation(); 415206084Srdivacky 416218893Sdim assert(!LM.Toks.empty() && "Empty body!"); 417218893Sdim // Append the current token at the end of the new token stream so that it 418218893Sdim // doesn't get lost. 419218893Sdim LM.Toks.push_back(Tok); 420218893Sdim PP.EnterTokenStream(LM.Toks.data(), LM.Toks.size(), true, false); 421193326Sed 422218893Sdim // Consume the previously pushed token. 423249423Sdim ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); 424218893Sdim assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) 425218893Sdim && "Inline method not starting with '{', ':' or 'try'"); 426193326Sed 427218893Sdim // Parse the method body. Function body parsing code is similar enough 428218893Sdim // to be re-used for method bodies as well. 429218893Sdim ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope); 430218893Sdim Actions.ActOnStartOfFunctionDef(getCurScope(), LM.D); 431193326Sed 432218893Sdim if (Tok.is(tok::kw_try)) { 433221345Sdim ParseFunctionTryBlock(LM.D, FnScope); 434218893Sdim assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc, 435218893Sdim Tok.getLocation()) && 436218893Sdim "ParseFunctionTryBlock went over the cached tokens!"); 437218893Sdim // There could be leftover tokens (e.g. because of an error). 438218893Sdim // Skip through until we reach the original token position. 439218893Sdim while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof)) 440218893Sdim ConsumeAnyToken(); 441218893Sdim return; 442218893Sdim } 443218893Sdim if (Tok.is(tok::colon)) { 444218893Sdim ParseConstructorInitializer(LM.D); 445218893Sdim 446218893Sdim // Error recovery. 447218893Sdim if (!Tok.is(tok::l_brace)) { 448221345Sdim FnScope.Exit(); 449218893Sdim Actions.ActOnFinishFunctionBody(LM.D, 0); 450226633Sdim while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof)) 451226633Sdim ConsumeAnyToken(); 452218893Sdim return; 453193326Sed } 454218893Sdim } else 455218893Sdim Actions.ActOnDefaultCtorInitializers(LM.D); 456207619Srdivacky 457251662Sdim assert((Actions.getDiagnostics().hasErrorOccurred() || 458251662Sdim !isa<FunctionTemplateDecl>(LM.D) || 459251662Sdim cast<FunctionTemplateDecl>(LM.D)->getTemplateParameters()->getDepth() 460251662Sdim < TemplateParameterDepth) && 461251662Sdim "TemplateParameterDepth should be greater than the depth of " 462251662Sdim "current template being instantiated!"); 463251662Sdim 464221345Sdim ParseFunctionStatementBody(LM.D, FnScope); 465198092Srdivacky 466249423Sdim // Clear the late-template-parsed bit if we set it before. 467249423Sdim if (LM.D) getFunctionDecl(LM.D)->setLateTemplateParsed(false); 468249423Sdim 469218893Sdim if (Tok.getLocation() != origLoc) { 470218893Sdim // Due to parsing error, we either went over the cached tokens or 471218893Sdim // there are still cached tokens left. If it's the latter case skip the 472218893Sdim // leftover tokens. 473218893Sdim // Since this is an uncommon situation that should be avoided, use the 474218893Sdim // expensive isBeforeInTranslationUnit call. 475218893Sdim if (PP.getSourceManager().isBeforeInTranslationUnit(Tok.getLocation(), 476218893Sdim origLoc)) 477218893Sdim while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof)) 478218893Sdim ConsumeAnyToken(); 479223017Sdim } 480223017Sdim} 481210299Sed 482223017Sdim/// ParseLexedMemberInitializers - We finished parsing the member specification 483223017Sdim/// of a top (non-nested) C++ class. Now go over the stack of lexed data member 484223017Sdim/// initializers that were collected during its parsing and parse them all. 485223017Sdimvoid Parser::ParseLexedMemberInitializers(ParsingClass &Class) { 486223017Sdim bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope; 487223017Sdim ParseScope ClassTemplateScope(this, Scope::TemplateParamScope, 488223017Sdim HasTemplateScope); 489251662Sdim TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth); 490251662Sdim if (HasTemplateScope) { 491223017Sdim Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate); 492251662Sdim ++CurTemplateDepthTracker; 493251662Sdim } 494234982Sdim // Set or update the scope flags. 495223017Sdim bool AlreadyHasClassScope = Class.TopLevelClass; 496234982Sdim unsigned ScopeFlags = Scope::ClassScope|Scope::DeclScope; 497223017Sdim ParseScope ClassScope(this, ScopeFlags, !AlreadyHasClassScope); 498223017Sdim ParseScopeFlags ClassScopeFlags(this, ScopeFlags, AlreadyHasClassScope); 499223017Sdim 500223017Sdim if (!AlreadyHasClassScope) 501223017Sdim Actions.ActOnStartDelayedMemberDeclarations(getCurScope(), 502223017Sdim Class.TagOrTemplate); 503223017Sdim 504239462Sdim if (!Class.LateParsedDeclarations.empty()) { 505234982Sdim // C++11 [expr.prim.general]p4: 506234982Sdim // Otherwise, if a member-declarator declares a non-static data member 507234982Sdim // (9.2) of a class X, the expression this is a prvalue of type "pointer 508234982Sdim // to X" within the optional brace-or-equal-initializer. It shall not 509234982Sdim // appear elsewhere in the member-declarator. 510234982Sdim Sema::CXXThisScopeRAII ThisScope(Actions, Class.TagOrTemplate, 511234982Sdim /*TypeQuals=*/(unsigned)0); 512234982Sdim 513234982Sdim for (size_t i = 0; i < Class.LateParsedDeclarations.size(); ++i) { 514234982Sdim Class.LateParsedDeclarations[i]->ParseLexedMemberInitializers(); 515234982Sdim } 516193326Sed } 517234982Sdim 518223017Sdim if (!AlreadyHasClassScope) 519223017Sdim Actions.ActOnFinishDelayedMemberDeclarations(getCurScope(), 520223017Sdim Class.TagOrTemplate); 521223017Sdim 522223017Sdim Actions.ActOnFinishDelayedMemberInitializers(Class.TagOrTemplate); 523193326Sed} 524193326Sed 525223017Sdimvoid Parser::ParseLexedMemberInitializer(LateParsedMemberInitializer &MI) { 526226633Sdim if (!MI.Field || MI.Field->isInvalidDecl()) 527223017Sdim return; 528223017Sdim 529223017Sdim // Append the current token at the end of the new token stream so that it 530223017Sdim // doesn't get lost. 531223017Sdim MI.Toks.push_back(Tok); 532223017Sdim PP.EnterTokenStream(MI.Toks.data(), MI.Toks.size(), true, false); 533223017Sdim 534223017Sdim // Consume the previously pushed token. 535249423Sdim ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); 536223017Sdim 537223017Sdim SourceLocation EqualLoc; 538239462Sdim 539234353Sdim ExprResult Init = ParseCXXMemberInitializer(MI.Field, /*IsFunction=*/false, 540234353Sdim EqualLoc); 541223017Sdim 542223017Sdim Actions.ActOnCXXInClassMemberInitializer(MI.Field, EqualLoc, Init.release()); 543223017Sdim 544223017Sdim // The next token should be our artificial terminating EOF token. 545223017Sdim if (Tok.isNot(tok::eof)) { 546223017Sdim SourceLocation EndLoc = PP.getLocForEndOfToken(PrevTokLocation); 547223017Sdim if (!EndLoc.isValid()) 548223017Sdim EndLoc = Tok.getLocation(); 549223017Sdim // No fixit; we can't recover as if there were a semicolon here. 550223017Sdim Diag(EndLoc, diag::err_expected_semi_decl_list); 551223017Sdim 552223017Sdim // Consume tokens until we hit the artificial EOF. 553223017Sdim while (Tok.isNot(tok::eof)) 554223017Sdim ConsumeAnyToken(); 555223017Sdim } 556223017Sdim ConsumeAnyToken(); 557223017Sdim} 558223017Sdim 559193326Sed/// ConsumeAndStoreUntil - Consume and store the token at the passed token 560193326Sed/// container until the token 'T' is reached (which gets 561198092Srdivacky/// consumed/stored too, if ConsumeFinalToken). 562207619Srdivacky/// If StopAtSemi is true, then we will stop early at a ';' character. 563193326Sed/// Returns true if token 'T1' or 'T2' was found. 564193326Sed/// NOTE: This is a specialized version of Parser::SkipUntil. 565193326Sedbool Parser::ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2, 566193326Sed CachedTokens &Toks, 567207619Srdivacky bool StopAtSemi, bool ConsumeFinalToken) { 568193326Sed // We always want this function to consume at least one token if the first 569193326Sed // token isn't T and if not at EOF. 570193326Sed bool isFirstTokenConsumed = true; 571193326Sed while (1) { 572193326Sed // If we found one of the tokens, stop and return true. 573193326Sed if (Tok.is(T1) || Tok.is(T2)) { 574193326Sed if (ConsumeFinalToken) { 575193326Sed Toks.push_back(Tok); 576193326Sed ConsumeAnyToken(); 577193326Sed } 578193326Sed return true; 579193326Sed } 580193326Sed 581193326Sed switch (Tok.getKind()) { 582193326Sed case tok::eof: 583193326Sed // Ran out of tokens. 584193326Sed return false; 585193326Sed 586193326Sed case tok::l_paren: 587193326Sed // Recursively consume properly-nested parens. 588193326Sed Toks.push_back(Tok); 589193326Sed ConsumeParen(); 590207619Srdivacky ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/false); 591193326Sed break; 592193326Sed case tok::l_square: 593193326Sed // Recursively consume properly-nested square brackets. 594193326Sed Toks.push_back(Tok); 595193326Sed ConsumeBracket(); 596207619Srdivacky ConsumeAndStoreUntil(tok::r_square, Toks, /*StopAtSemi=*/false); 597193326Sed break; 598193326Sed case tok::l_brace: 599193326Sed // Recursively consume properly-nested braces. 600193326Sed Toks.push_back(Tok); 601193326Sed ConsumeBrace(); 602207619Srdivacky ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false); 603193326Sed break; 604193326Sed 605193326Sed // Okay, we found a ']' or '}' or ')', which we think should be balanced. 606193326Sed // Since the user wasn't looking for this token (if they were, it would 607193326Sed // already be handled), this isn't balanced. If there is a LHS token at a 608193326Sed // higher level, we will assume that this matches the unbalanced token 609193326Sed // and return it. Otherwise, this is a spurious RHS token, which we skip. 610193326Sed case tok::r_paren: 611193326Sed if (ParenCount && !isFirstTokenConsumed) 612193326Sed return false; // Matches something. 613193326Sed Toks.push_back(Tok); 614193326Sed ConsumeParen(); 615193326Sed break; 616193326Sed case tok::r_square: 617193326Sed if (BracketCount && !isFirstTokenConsumed) 618193326Sed return false; // Matches something. 619193326Sed Toks.push_back(Tok); 620193326Sed ConsumeBracket(); 621193326Sed break; 622193326Sed case tok::r_brace: 623193326Sed if (BraceCount && !isFirstTokenConsumed) 624193326Sed return false; // Matches something. 625193326Sed Toks.push_back(Tok); 626193326Sed ConsumeBrace(); 627193326Sed break; 628193326Sed 629226633Sdim case tok::code_completion: 630226633Sdim Toks.push_back(Tok); 631226633Sdim ConsumeCodeCompletionToken(); 632226633Sdim break; 633226633Sdim 634193326Sed case tok::string_literal: 635193326Sed case tok::wide_string_literal: 636226633Sdim case tok::utf8_string_literal: 637226633Sdim case tok::utf16_string_literal: 638226633Sdim case tok::utf32_string_literal: 639193326Sed Toks.push_back(Tok); 640193326Sed ConsumeStringToken(); 641193326Sed break; 642207619Srdivacky case tok::semi: 643207619Srdivacky if (StopAtSemi) 644207619Srdivacky return false; 645207619Srdivacky // FALL THROUGH. 646193326Sed default: 647193326Sed // consume this token. 648193326Sed Toks.push_back(Tok); 649193326Sed ConsumeToken(); 650193326Sed break; 651193326Sed } 652193326Sed isFirstTokenConsumed = false; 653193326Sed } 654193326Sed} 655226633Sdim 656226633Sdim/// \brief Consume tokens and store them in the passed token container until 657226633Sdim/// we've passed the try keyword and constructor initializers and have consumed 658226633Sdim/// the opening brace of the function body. The opening brace will be consumed 659226633Sdim/// if and only if there was no error. 660226633Sdim/// 661263508Sdim/// \return True on error. 662226633Sdimbool Parser::ConsumeAndStoreFunctionPrologue(CachedTokens &Toks) { 663226633Sdim if (Tok.is(tok::kw_try)) { 664226633Sdim Toks.push_back(Tok); 665226633Sdim ConsumeToken(); 666226633Sdim } 667263508Sdim 668263508Sdim if (Tok.isNot(tok::colon)) { 669263508Sdim // Easy case, just a function body. 670263508Sdim 671263508Sdim // Grab any remaining garbage to be diagnosed later. We stop when we reach a 672263508Sdim // brace: an opening one is the function body, while a closing one probably 673263508Sdim // means we've reached the end of the class. 674263508Sdim ConsumeAndStoreUntil(tok::l_brace, tok::r_brace, Toks, 675263508Sdim /*StopAtSemi=*/true, 676263508Sdim /*ConsumeFinalToken=*/false); 677263508Sdim if (Tok.isNot(tok::l_brace)) 678263508Sdim return Diag(Tok.getLocation(), diag::err_expected_lbrace); 679263508Sdim 680226633Sdim Toks.push_back(Tok); 681263508Sdim ConsumeBrace(); 682263508Sdim return false; 683263508Sdim } 684226633Sdim 685263508Sdim Toks.push_back(Tok); 686263508Sdim ConsumeToken(); 687226633Sdim 688263508Sdim // We can't reliably skip over a mem-initializer-id, because it could be 689263508Sdim // a template-id involving not-yet-declared names. Given: 690263508Sdim // 691263508Sdim // S ( ) : a < b < c > ( e ) 692263508Sdim // 693263508Sdim // 'e' might be an initializer or part of a template argument, depending 694263508Sdim // on whether 'b' is a template. 695226633Sdim 696263508Sdim // Track whether we might be inside a template argument. We can give 697263508Sdim // significantly better diagnostics if we know that we're not. 698263508Sdim bool MightBeTemplateArgument = false; 699263508Sdim 700263508Sdim while (true) { 701263508Sdim // Skip over the mem-initializer-id, if possible. 702263508Sdim if (Tok.is(tok::kw_decltype)) { 703226633Sdim Toks.push_back(Tok); 704263508Sdim SourceLocation OpenLoc = ConsumeToken(); 705263508Sdim if (Tok.isNot(tok::l_paren)) 706263508Sdim return Diag(Tok.getLocation(), diag::err_expected_lparen_after) 707263508Sdim << "decltype"; 708263508Sdim Toks.push_back(Tok); 709263508Sdim ConsumeParen(); 710263508Sdim if (!ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/true)) { 711263508Sdim Diag(Tok.getLocation(), diag::err_expected_rparen); 712263508Sdim Diag(OpenLoc, diag::note_matching) << "("; 713263508Sdim return true; 714263508Sdim } 715263508Sdim } 716263508Sdim do { 717263508Sdim // Walk over a component of a nested-name-specifier. 718263508Sdim if (Tok.is(tok::coloncolon)) { 719263508Sdim Toks.push_back(Tok); 720263508Sdim ConsumeToken(); 721234353Sdim 722263508Sdim if (Tok.is(tok::kw_template)) { 723263508Sdim Toks.push_back(Tok); 724263508Sdim ConsumeToken(); 725263508Sdim } 726263508Sdim } 727263508Sdim 728263508Sdim if (Tok.is(tok::identifier) || Tok.is(tok::kw_template)) { 729263508Sdim Toks.push_back(Tok); 730263508Sdim ConsumeToken(); 731263508Sdim } else if (Tok.is(tok::code_completion)) { 732263508Sdim Toks.push_back(Tok); 733263508Sdim ConsumeCodeCompletionToken(); 734263508Sdim // Consume the rest of the initializers permissively. 735263508Sdim // FIXME: We should be able to perform code-completion here even if 736263508Sdim // there isn't a subsequent '{' token. 737263508Sdim MightBeTemplateArgument = true; 738263508Sdim break; 739234353Sdim } else { 740263508Sdim break; 741226633Sdim } 742263508Sdim } while (Tok.is(tok::coloncolon)); 743226633Sdim 744263508Sdim if (Tok.is(tok::less)) 745263508Sdim MightBeTemplateArgument = true; 746263508Sdim 747263508Sdim if (MightBeTemplateArgument) { 748263508Sdim // We may be inside a template argument list. Grab up to the start of the 749263508Sdim // next parenthesized initializer or braced-init-list. This *might* be the 750263508Sdim // initializer, or it might be a subexpression in the template argument 751263508Sdim // list. 752263508Sdim // FIXME: Count angle brackets, and clear MightBeTemplateArgument 753263508Sdim // if all angles are closed. 754263508Sdim if (!ConsumeAndStoreUntil(tok::l_paren, tok::l_brace, Toks, 755263508Sdim /*StopAtSemi=*/true, 756263508Sdim /*ConsumeFinalToken=*/false)) { 757263508Sdim // We're not just missing the initializer, we're also missing the 758263508Sdim // function body! 759263508Sdim return Diag(Tok.getLocation(), diag::err_expected_lbrace); 760263508Sdim } 761263508Sdim } else if (Tok.isNot(tok::l_paren) && Tok.isNot(tok::l_brace)) { 762263508Sdim // We found something weird in a mem-initializer-id. 763263508Sdim return Diag(Tok.getLocation(), getLangOpts().CPlusPlus11 764263508Sdim ? diag::err_expected_lparen_or_lbrace 765263508Sdim : diag::err_expected_lparen); 766263508Sdim } 767263508Sdim 768263508Sdim tok::TokenKind kind = Tok.getKind(); 769263508Sdim Toks.push_back(Tok); 770263508Sdim bool IsLParen = (kind == tok::l_paren); 771263508Sdim SourceLocation OpenLoc = Tok.getLocation(); 772263508Sdim 773263508Sdim if (IsLParen) { 774263508Sdim ConsumeParen(); 775263508Sdim } else { 776263508Sdim assert(kind == tok::l_brace && "Must be left paren or brace here."); 777263508Sdim ConsumeBrace(); 778263508Sdim // In C++03, this has to be the start of the function body, which 779263508Sdim // means the initializer is malformed; we'll diagnose it later. 780263508Sdim if (!getLangOpts().CPlusPlus11) 781263508Sdim return false; 782263508Sdim } 783263508Sdim 784263508Sdim // Grab the initializer (or the subexpression of the template argument). 785263508Sdim // FIXME: If we support lambdas here, we'll need to set StopAtSemi to false 786263508Sdim // if we might be inside the braces of a lambda-expression. 787263508Sdim if (!ConsumeAndStoreUntil(IsLParen ? tok::r_paren : tok::r_brace, 788263508Sdim Toks, /*StopAtSemi=*/true)) { 789263508Sdim Diag(Tok, IsLParen ? diag::err_expected_rparen : 790263508Sdim diag::err_expected_rbrace); 791263508Sdim Diag(OpenLoc, diag::note_matching) << (IsLParen ? "(" : "{"); 792263508Sdim return true; 793263508Sdim } 794263508Sdim 795263508Sdim // Grab pack ellipsis, if present. 796263508Sdim if (Tok.is(tok::ellipsis)) { 797263508Sdim Toks.push_back(Tok); 798263508Sdim ConsumeToken(); 799263508Sdim } 800263508Sdim 801263508Sdim // If we know we just consumed a mem-initializer, we must have ',' or '{' 802263508Sdim // next. 803263508Sdim if (Tok.is(tok::comma)) { 804263508Sdim Toks.push_back(Tok); 805263508Sdim ConsumeToken(); 806263508Sdim } else if (Tok.is(tok::l_brace)) { 807263508Sdim // This is the function body if the ')' or '}' is immediately followed by 808263508Sdim // a '{'. That cannot happen within a template argument, apart from the 809263508Sdim // case where a template argument contains a compound literal: 810263508Sdim // 811263508Sdim // S ( ) : a < b < c > ( d ) { } 812263508Sdim // // End of declaration, or still inside the template argument? 813263508Sdim // 814263508Sdim // ... and the case where the template argument contains a lambda: 815263508Sdim // 816263508Sdim // S ( ) : a < 0 && b < c > ( d ) + [ ] ( ) { return 0; } 817263508Sdim // ( ) > ( ) { } 818263508Sdim // 819263508Sdim // FIXME: Disambiguate these cases. Note that the latter case is probably 820263508Sdim // going to be made ill-formed by core issue 1607. 821263508Sdim Toks.push_back(Tok); 822263508Sdim ConsumeBrace(); 823263508Sdim return false; 824263508Sdim } else if (!MightBeTemplateArgument) { 825263508Sdim return Diag(Tok.getLocation(), diag::err_expected_lbrace_or_comma); 826263508Sdim } 827263508Sdim } 828263508Sdim} 829263508Sdim 830263508Sdim/// \brief Consume and store tokens from the '?' to the ':' in a conditional 831263508Sdim/// expression. 832263508Sdimbool Parser::ConsumeAndStoreConditional(CachedTokens &Toks) { 833263508Sdim // Consume '?'. 834263508Sdim assert(Tok.is(tok::question)); 835263508Sdim Toks.push_back(Tok); 836263508Sdim ConsumeToken(); 837263508Sdim 838263508Sdim while (Tok.isNot(tok::colon)) { 839263508Sdim if (!ConsumeAndStoreUntil(tok::question, tok::colon, Toks, /*StopAtSemi*/true, 840263508Sdim /*ConsumeFinalToken*/false)) 841263508Sdim return false; 842263508Sdim 843263508Sdim // If we found a nested conditional, consume it. 844263508Sdim if (Tok.is(tok::question) && !ConsumeAndStoreConditional(Toks)) 845263508Sdim return false; 846263508Sdim } 847263508Sdim 848263508Sdim // Consume ':'. 849263508Sdim Toks.push_back(Tok); 850263508Sdim ConsumeToken(); 851263508Sdim return true; 852263508Sdim} 853263508Sdim 854263508Sdim/// \brief A tentative parsing action that can also revert token annotations. 855263508Sdimclass Parser::UnannotatedTentativeParsingAction : public TentativeParsingAction { 856263508Sdimpublic: 857263508Sdim explicit UnannotatedTentativeParsingAction(Parser &Self, 858263508Sdim tok::TokenKind EndKind) 859263508Sdim : TentativeParsingAction(Self), Self(Self), EndKind(EndKind) { 860263508Sdim // Stash away the old token stream, so we can restore it once the 861263508Sdim // tentative parse is complete. 862263508Sdim TentativeParsingAction Inner(Self); 863263508Sdim Self.ConsumeAndStoreUntil(EndKind, Toks, true, /*ConsumeFinalToken*/false); 864263508Sdim Inner.Revert(); 865263508Sdim } 866263508Sdim 867263508Sdim void RevertAnnotations() { 868263508Sdim Revert(); 869263508Sdim 870263508Sdim // Put back the original tokens. 871263508Sdim Self.SkipUntil(EndKind, StopAtSemi | StopBeforeMatch); 872263508Sdim if (Toks.size()) { 873263508Sdim Token *Buffer = new Token[Toks.size()]; 874263508Sdim std::copy(Toks.begin() + 1, Toks.end(), Buffer); 875263508Sdim Buffer[Toks.size() - 1] = Self.Tok; 876263508Sdim Self.PP.EnterTokenStream(Buffer, Toks.size(), true, /*Owned*/true); 877263508Sdim 878263508Sdim Self.Tok = Toks.front(); 879263508Sdim } 880263508Sdim } 881263508Sdim 882263508Sdimprivate: 883263508Sdim Parser &Self; 884263508Sdim CachedTokens Toks; 885263508Sdim tok::TokenKind EndKind; 886263508Sdim}; 887263508Sdim 888263508Sdim/// ConsumeAndStoreInitializer - Consume and store the token at the passed token 889263508Sdim/// container until the end of the current initializer expression (either a 890263508Sdim/// default argument or an in-class initializer for a non-static data member). 891263508Sdim/// The final token is not consumed. 892263508Sdimbool Parser::ConsumeAndStoreInitializer(CachedTokens &Toks, 893263508Sdim CachedInitKind CIK) { 894263508Sdim // We always want this function to consume at least one token if not at EOF. 895263508Sdim bool IsFirstTokenConsumed = true; 896263508Sdim 897263508Sdim // Number of possible unclosed <s we've seen so far. These might be templates, 898263508Sdim // and might not, but if there were none of them (or we know for sure that 899263508Sdim // we're within a template), we can avoid a tentative parse. 900263508Sdim unsigned AngleCount = 0; 901263508Sdim unsigned KnownTemplateCount = 0; 902263508Sdim 903263508Sdim while (1) { 904263508Sdim switch (Tok.getKind()) { 905263508Sdim case tok::comma: 906263508Sdim // If we might be in a template, perform a tentative parse to check. 907263508Sdim if (!AngleCount) 908263508Sdim // Not a template argument: this is the end of the initializer. 909226633Sdim return true; 910263508Sdim if (KnownTemplateCount) 911263508Sdim goto consume_token; 912263508Sdim 913263508Sdim // We hit a comma inside angle brackets. This is the hard case. The 914263508Sdim // rule we follow is: 915263508Sdim // * For a default argument, if the tokens after the comma form a 916263508Sdim // syntactically-valid parameter-declaration-clause, in which each 917263508Sdim // parameter has an initializer, then this comma ends the default 918263508Sdim // argument. 919263508Sdim // * For a default initializer, if the tokens after the comma form a 920263508Sdim // syntactically-valid init-declarator-list, then this comma ends 921263508Sdim // the default initializer. 922263508Sdim { 923263508Sdim UnannotatedTentativeParsingAction PA(*this, 924263508Sdim CIK == CIK_DefaultInitializer 925263508Sdim ? tok::semi : tok::r_paren); 926263508Sdim Sema::TentativeAnalysisScope Scope(Actions); 927263508Sdim 928263508Sdim TPResult Result = TPResult::Error(); 929263508Sdim ConsumeToken(); 930263508Sdim switch (CIK) { 931263508Sdim case CIK_DefaultInitializer: 932263508Sdim Result = TryParseInitDeclaratorList(); 933263508Sdim // If we parsed a complete, ambiguous init-declarator-list, this 934263508Sdim // is only syntactically-valid if it's followed by a semicolon. 935263508Sdim if (Result == TPResult::Ambiguous() && Tok.isNot(tok::semi)) 936263508Sdim Result = TPResult::False(); 937263508Sdim break; 938263508Sdim 939263508Sdim case CIK_DefaultArgument: 940263508Sdim bool InvalidAsDeclaration = false; 941263508Sdim Result = TryParseParameterDeclarationClause( 942263508Sdim &InvalidAsDeclaration, /*VersusTemplateArgument*/true); 943263508Sdim // If this is an expression or a declaration with a missing 944263508Sdim // 'typename', assume it's not a declaration. 945263508Sdim if (Result == TPResult::Ambiguous() && InvalidAsDeclaration) 946263508Sdim Result = TPResult::False(); 947263508Sdim break; 948263508Sdim } 949263508Sdim 950263508Sdim // If what follows could be a declaration, it is a declaration. 951263508Sdim if (Result != TPResult::False() && Result != TPResult::Error()) { 952263508Sdim PA.Revert(); 953263508Sdim return true; 954263508Sdim } 955263508Sdim 956263508Sdim // In the uncommon case that we decide the following tokens are part 957263508Sdim // of a template argument, revert any annotations we've performed in 958263508Sdim // those tokens. We're not going to look them up until we've parsed 959263508Sdim // the rest of the class, and that might add more declarations. 960263508Sdim PA.RevertAnnotations(); 961234353Sdim } 962226633Sdim 963263508Sdim // Keep going. We know we're inside a template argument list now. 964263508Sdim ++KnownTemplateCount; 965263508Sdim goto consume_token; 966263508Sdim 967263508Sdim case tok::eof: 968263508Sdim // Ran out of tokens. 969263508Sdim return false; 970263508Sdim 971263508Sdim case tok::less: 972263508Sdim // FIXME: A '<' can only start a template-id if it's preceded by an 973263508Sdim // identifier, an operator-function-id, or a literal-operator-id. 974263508Sdim ++AngleCount; 975263508Sdim goto consume_token; 976263508Sdim 977263508Sdim case tok::question: 978263508Sdim // In 'a ? b : c', 'b' can contain an unparenthesized comma. If it does, 979263508Sdim // that is *never* the end of the initializer. Skip to the ':'. 980263508Sdim if (!ConsumeAndStoreConditional(Toks)) 981263508Sdim return false; 982263508Sdim break; 983263508Sdim 984263508Sdim case tok::greatergreatergreater: 985263508Sdim if (!getLangOpts().CPlusPlus11) 986263508Sdim goto consume_token; 987263508Sdim if (AngleCount) --AngleCount; 988263508Sdim if (KnownTemplateCount) --KnownTemplateCount; 989263508Sdim // Fall through. 990263508Sdim case tok::greatergreater: 991263508Sdim if (!getLangOpts().CPlusPlus11) 992263508Sdim goto consume_token; 993263508Sdim if (AngleCount) --AngleCount; 994263508Sdim if (KnownTemplateCount) --KnownTemplateCount; 995263508Sdim // Fall through. 996263508Sdim case tok::greater: 997263508Sdim if (AngleCount) --AngleCount; 998263508Sdim if (KnownTemplateCount) --KnownTemplateCount; 999263508Sdim goto consume_token; 1000263508Sdim 1001263508Sdim case tok::kw_template: 1002263508Sdim // 'template' identifier '<' is known to start a template argument list, 1003263508Sdim // and can be used to disambiguate the parse. 1004263508Sdim // FIXME: Support all forms of 'template' unqualified-id '<'. 1005263508Sdim Toks.push_back(Tok); 1006263508Sdim ConsumeToken(); 1007263508Sdim if (Tok.is(tok::identifier)) { 1008234353Sdim Toks.push_back(Tok); 1009234353Sdim ConsumeToken(); 1010263508Sdim if (Tok.is(tok::less)) { 1011263508Sdim ++KnownTemplateCount; 1012263508Sdim Toks.push_back(Tok); 1013263508Sdim ConsumeToken(); 1014263508Sdim } 1015234353Sdim } 1016263508Sdim break; 1017234353Sdim 1018263508Sdim case tok::kw_operator: 1019263508Sdim // If 'operator' precedes other punctuation, that punctuation loses 1020263508Sdim // its special behavior. 1021263508Sdim Toks.push_back(Tok); 1022263508Sdim ConsumeToken(); 1023263508Sdim switch (Tok.getKind()) { 1024263508Sdim case tok::comma: 1025263508Sdim case tok::greatergreatergreater: 1026263508Sdim case tok::greatergreater: 1027263508Sdim case tok::greater: 1028263508Sdim case tok::less: 1029226633Sdim Toks.push_back(Tok); 1030226633Sdim ConsumeToken(); 1031234353Sdim break; 1032263508Sdim default: 1033263508Sdim break; 1034226633Sdim } 1035263508Sdim break; 1036263508Sdim 1037263508Sdim case tok::l_paren: 1038263508Sdim // Recursively consume properly-nested parens. 1039263508Sdim Toks.push_back(Tok); 1040263508Sdim ConsumeParen(); 1041263508Sdim ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/false); 1042263508Sdim break; 1043263508Sdim case tok::l_square: 1044263508Sdim // Recursively consume properly-nested square brackets. 1045263508Sdim Toks.push_back(Tok); 1046263508Sdim ConsumeBracket(); 1047263508Sdim ConsumeAndStoreUntil(tok::r_square, Toks, /*StopAtSemi=*/false); 1048263508Sdim break; 1049263508Sdim case tok::l_brace: 1050263508Sdim // Recursively consume properly-nested braces. 1051263508Sdim Toks.push_back(Tok); 1052263508Sdim ConsumeBrace(); 1053263508Sdim ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false); 1054263508Sdim break; 1055263508Sdim 1056263508Sdim // Okay, we found a ']' or '}' or ')', which we think should be balanced. 1057263508Sdim // Since the user wasn't looking for this token (if they were, it would 1058263508Sdim // already be handled), this isn't balanced. If there is a LHS token at a 1059263508Sdim // higher level, we will assume that this matches the unbalanced token 1060263508Sdim // and return it. Otherwise, this is a spurious RHS token, which we skip. 1061263508Sdim case tok::r_paren: 1062263508Sdim if (CIK == CIK_DefaultArgument) 1063263508Sdim return true; // End of the default argument. 1064263508Sdim if (ParenCount && !IsFirstTokenConsumed) 1065263508Sdim return false; // Matches something. 1066263508Sdim goto consume_token; 1067263508Sdim case tok::r_square: 1068263508Sdim if (BracketCount && !IsFirstTokenConsumed) 1069263508Sdim return false; // Matches something. 1070263508Sdim goto consume_token; 1071263508Sdim case tok::r_brace: 1072263508Sdim if (BraceCount && !IsFirstTokenConsumed) 1073263508Sdim return false; // Matches something. 1074263508Sdim goto consume_token; 1075263508Sdim 1076263508Sdim case tok::code_completion: 1077263508Sdim Toks.push_back(Tok); 1078263508Sdim ConsumeCodeCompletionToken(); 1079263508Sdim break; 1080263508Sdim 1081263508Sdim case tok::string_literal: 1082263508Sdim case tok::wide_string_literal: 1083263508Sdim case tok::utf8_string_literal: 1084263508Sdim case tok::utf16_string_literal: 1085263508Sdim case tok::utf32_string_literal: 1086263508Sdim Toks.push_back(Tok); 1087263508Sdim ConsumeStringToken(); 1088263508Sdim break; 1089263508Sdim case tok::semi: 1090263508Sdim if (CIK == CIK_DefaultInitializer) 1091263508Sdim return true; // End of the default initializer. 1092263508Sdim // FALL THROUGH. 1093263508Sdim default: 1094263508Sdim consume_token: 1095263508Sdim Toks.push_back(Tok); 1096263508Sdim ConsumeToken(); 1097263508Sdim break; 1098226633Sdim } 1099263508Sdim IsFirstTokenConsumed = false; 1100226633Sdim } 1101226633Sdim} 1102