ParseCXXInlineMethods.cpp revision 218893
1252602Spjd//===--- ParseCXXInlineMethods.cpp - C++ class inline methods parsing------===// 2252602Spjd// 3252603Spjd// The LLVM Compiler Infrastructure 4252602Spjd// 51553Srgrimes// This file is distributed under the University of Illinois Open Source 61553Srgrimes// License. See LICENSE.TXT for details. 71553Srgrimes// 81553Srgrimes//===----------------------------------------------------------------------===// 91553Srgrimes// 101553Srgrimes// This file implements parsing for C++ class inline methods. 111553Srgrimes// 121553Srgrimes//===----------------------------------------------------------------------===// 131553Srgrimes 141553Srgrimes#include "clang/Parse/ParseDiagnostic.h" 151553Srgrimes#include "clang/Parse/Parser.h" 161553Srgrimes#include "clang/Sema/DeclSpec.h" 171553Srgrimes#include "clang/Sema/Scope.h" 181553Srgrimesusing namespace clang; 191553Srgrimes 201553Srgrimes/// ParseCXXInlineMethodDef - We parsed and verified that the specified 211553Srgrimes/// Declarator is a well formed C++ inline method definition. Now lex its body 221553Srgrimes/// and store its tokens for parsing after the C++ class is complete. 231553SrgrimesDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, ParsingDeclarator &D, 241553Srgrimes const ParsedTemplateInfo &TemplateInfo, 251553Srgrimes const VirtSpecifiers& VS) { 261553Srgrimes assert(D.isFunctionDeclarator() && "This isn't a function declarator!"); 271553Srgrimes assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) && 281553Srgrimes "Current token not a '{', ':' or 'try'!"); 291553Srgrimes 301553Srgrimes MultiTemplateParamsArg TemplateParams(Actions, 311553Srgrimes TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->data() : 0, 3230380Scharnier TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->size() : 0); 331553Srgrimes 341553Srgrimes Decl *FnD; 351553Srgrimes if (D.getDeclSpec().isFriendSpecified()) 361553Srgrimes // FIXME: Friend templates 37117278Scharnier FnD = Actions.ActOnFriendFunctionDecl(getCurScope(), D, true, 381553Srgrimes move(TemplateParams)); 391553Srgrimes else { // FIXME: pass template information through 40117278Scharnier if (VS.isOverrideSpecified()) 4130380Scharnier Diag(VS.getOverrideLoc(), diag::ext_override_inline) << "override"; 421553Srgrimes if (VS.isFinalSpecified()) 43117278Scharnier Diag(VS.getFinalLoc(), diag::ext_override_inline) << "final"; 44117278Scharnier if (VS.isNewSpecified()) 45117278Scharnier Diag(VS.getNewLoc(), diag::ext_override_inline) << "new"; 46312034Sngie 47280250Srwatson FnD = Actions.ActOnCXXMemberDeclarator(getCurScope(), AS, D, 48312034Sngie move(TemplateParams), 0, 49312034Sngie VS, 0, /*IsDefinition*/true); 501553Srgrimes } 511553Srgrimes 521553Srgrimes HandleMemberFunctionDefaultArgs(D, FnD); 531553Srgrimes 54252603Spjd D.complete(FnD); 551553Srgrimes 561553Srgrimes // Consume the tokens and store them for later parsing. 571553Srgrimes 581553Srgrimes LexedMethod* LM = new LexedMethod(this, FnD); 591553Srgrimes getCurrentClass().LateParsedDeclarations.push_back(LM); 6070284Siedowse LM->TemplateScope = getCurScope()->isTemplateParamScope(); 611553Srgrimes CachedTokens &Toks = LM->Toks; 621553Srgrimes 631553Srgrimes tok::TokenKind kind = Tok.getKind(); 6430380Scharnier // We may have a constructor initializer or function-try-block here. 651553Srgrimes if (kind == tok::colon || kind == tok::kw_try) { 661553Srgrimes // Consume everything up to (and including) the left brace. 67252602Spjd if (!ConsumeAndStoreUntil(tok::l_brace, Toks)) { 681553Srgrimes // We didn't find the left-brace we expected after the 691553Srgrimes // constructor initializer. 70252602Spjd if (Tok.is(tok::semi)) { 711553Srgrimes // We found a semicolon; complain, consume the semicolon, and 721553Srgrimes // don't try to parse this method later. 731553Srgrimes Diag(Tok.getLocation(), diag::err_expected_lbrace); 741553Srgrimes ConsumeAnyToken(); 7599825Salfred delete getCurrentClass().LateParsedDeclarations.back(); 76252602Spjd getCurrentClass().LateParsedDeclarations.pop_back(); 771553Srgrimes return FnD; 781553Srgrimes } 7917832Spst } 8017829Spst 8117829Spst } else { 8210087Sjkh // Begin by storing the '{' token. 8310087Sjkh Toks.push_back(Tok); 8410087Sjkh ConsumeBrace(); 8510087Sjkh } 8610087Sjkh // Consume everything up to (and including) the matching right brace. 8710087Sjkh ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false); 8810087Sjkh 89252602Spjd // If we're in a function-try-block, we need to store all the catch blocks. 9010087Sjkh if (kind == tok::kw_try) { 91252602Spjd while (Tok.is(tok::kw_catch)) { 92252602Spjd ConsumeAndStoreUntil(tok::l_brace, Toks, /*StopAtSemi=*/false); 93252602Spjd ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false); 94252602Spjd } 95252602Spjd } 96252602Spjd 97252602Spjd return FnD; 9810087Sjkh} 9910087Sjkh 100252603SpjdParser::LateParsedDeclaration::~LateParsedDeclaration() {} 1011553Srgrimesvoid Parser::LateParsedDeclaration::ParseLexedMethodDeclarations() {} 1021553Srgrimesvoid Parser::LateParsedDeclaration::ParseLexedMethodDefs() {} 103252603Spjd 1041553SrgrimesParser::LateParsedClass::LateParsedClass(Parser *P, ParsingClass *C) 1051553Srgrimes : Self(P), Class(C) {} 1061553Srgrimes 1071553SrgrimesParser::LateParsedClass::~LateParsedClass() { 1081553Srgrimes Self->DeallocateParsedClasses(Class); 1091553Srgrimes} 1101553Srgrimes 1111553Srgrimesvoid Parser::LateParsedClass::ParseLexedMethodDeclarations() { 1121553Srgrimes Self->ParseLexedMethodDeclarations(*Class); 1131553Srgrimes} 114252602Spjd 1151553Srgrimesvoid Parser::LateParsedClass::ParseLexedMethodDefs() { 116252602Spjd Self->ParseLexedMethodDefs(*Class); 117252602Spjd} 1181553Srgrimes 1191553Srgrimesvoid Parser::LateParsedMethodDeclaration::ParseLexedMethodDeclarations() { 1201553Srgrimes Self->ParseLexedMethodDeclaration(*this); 1211553Srgrimes} 122252602Spjd 123201060Sedvoid Parser::LexedMethod::ParseLexedMethodDefs() { 124252603Spjd Self->ParseLexedMethodDef(*this); 125252603Spjd} 1261553Srgrimes 12799825Salfred/// ParseLexedMethodDeclarations - We finished parsing the member 1281553Srgrimes/// specification of a top (non-nested) C++ class. Now go over the 129252602Spjd/// stack of method declarations with some parts for which parsing was 130252602Spjd/// delayed (such as default arguments) and parse them. 131252603Spjdvoid Parser::ParseLexedMethodDeclarations(ParsingClass &Class) { 132252602Spjd bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope; 133252602Spjd ParseScope ClassTemplateScope(this, Scope::TemplateParamScope, HasTemplateScope); 134252602Spjd if (HasTemplateScope) 135252603Spjd Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate); 136252602Spjd 13799825Salfred // The current scope is still active if we're the top-level class. 138252602Spjd // Otherwise we'll need to push and enter a new scope. 1391553Srgrimes bool HasClassScope = !Class.TopLevelClass; 140252602Spjd ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope, 141252602Spjd HasClassScope); 142252602Spjd if (HasClassScope) 1431553Srgrimes Actions.ActOnStartDelayedMemberDeclarations(getCurScope(), Class.TagOrTemplate); 1441553Srgrimes 1451553Srgrimes for (size_t i = 0; i < Class.LateParsedDeclarations.size(); ++i) { 146252602Spjd Class.LateParsedDeclarations[i]->ParseLexedMethodDeclarations(); 147252602Spjd } 148252602Spjd 149252602Spjd if (HasClassScope) 150252602Spjd Actions.ActOnFinishDelayedMemberDeclarations(getCurScope(), Class.TagOrTemplate); 151252602Spjd} 152252602Spjd 153252602Spjdvoid Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { 154252602Spjd // If this is a member template, introduce the template parameter scope. 155252602Spjd ParseScope TemplateScope(this, Scope::TemplateParamScope, LM.TemplateScope); 156252602Spjd if (LM.TemplateScope) 157252602Spjd Actions.ActOnReenterTemplateScope(getCurScope(), LM.Method); 158252602Spjd 159252602Spjd // Start the delayed C++ method declaration 160252602Spjd Actions.ActOnStartDelayedCXXMethodDeclaration(getCurScope(), LM.Method); 161252602Spjd 162252602Spjd // Introduce the parameters into scope and parse their default 163252602Spjd // arguments. 164252602Spjd ParseScope PrototypeScope(this, 165252602Spjd Scope::FunctionPrototypeScope|Scope::DeclScope); 166252602Spjd for (unsigned I = 0, N = LM.DefaultArgs.size(); I != N; ++I) { 167252602Spjd // Introduce the parameter into scope. 168252602Spjd Actions.ActOnDelayedCXXMethodParameter(getCurScope(), LM.DefaultArgs[I].Param); 169252602Spjd 170252602Spjd if (CachedTokens *Toks = LM.DefaultArgs[I].Toks) { 171252602Spjd // Save the current token position. 172252602Spjd SourceLocation origLoc = Tok.getLocation(); 173252602Spjd 174252602Spjd // Parse the default argument from its saved token stream. 1751553Srgrimes Toks->push_back(Tok); // So that the current token doesn't get lost 17699825Salfred PP.EnterTokenStream(&Toks->front(), Toks->size(), true, false); 1771553Srgrimes 178252602Spjd // Consume the previously-pushed token. 1791553Srgrimes ConsumeAnyToken(); 18099825Salfred 18117829Spst // Consume the '='. 18217829Spst assert(Tok.is(tok::equal) && "Default argument not starting with '='"); 1831553Srgrimes SourceLocation EqualLoc = ConsumeToken(); 184252602Spjd 18530380Scharnier // The argument isn't actually potentially evaluated unless it is 18630380Scharnier // used. 18717829Spst EnterExpressionEvaluationContext Eval(Actions, 18817829Spst Sema::PotentiallyEvaluatedIfUsed); 18917829Spst 190252602Spjd ExprResult DefArgResult(ParseAssignmentExpression()); 191252602Spjd if (DefArgResult.isInvalid()) 19210087Sjkh Actions.ActOnParamDefaultArgumentError(LM.DefaultArgs[I].Param); 19310087Sjkh else { 19410087Sjkh if (Tok.is(tok::cxx_defaultarg_end)) 195252602Spjd ConsumeToken(); 196252602Spjd else 19710087Sjkh Diag(Tok.getLocation(), diag::err_default_arg_unparsed); 19810087Sjkh Actions.ActOnParamDefaultArgument(LM.DefaultArgs[I].Param, EqualLoc, 199252602Spjd DefArgResult.take()); 20030380Scharnier } 201252602Spjd 202252602Spjd assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc, 203252602Spjd Tok.getLocation()) && 204252602Spjd "ParseAssignmentExpression went over the default arg tokens!"); 20510087Sjkh // There could be leftover tokens (e.g. because of an error). 206252602Spjd // Skip through until we reach the original token position. 20742508Ssteve while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof)) 208252602Spjd ConsumeAnyToken(); 20942508Ssteve 210252602Spjd delete Toks; 21147963Sbrian LM.DefaultArgs[I].Toks = 0; 212252602Spjd } 21330380Scharnier } 214252602Spjd PrototypeScope.Exit(); 215252602Spjd 216252602Spjd // Finish the delayed C++ method declaration. 21710087Sjkh Actions.ActOnFinishDelayedCXXMethodDeclaration(getCurScope(), LM.Method); 21830380Scharnier} 21930380Scharnier 2201553Srgrimes/// ParseLexedMethodDefs - We finished parsing the member specification of a top 2211553Srgrimes/// (non-nested) C++ class. Now go over the stack of lexed methods that were 2221553Srgrimes/// collected during its parsing and parse them all. 22310087Sjkhvoid Parser::ParseLexedMethodDefs(ParsingClass &Class) { 224252605Spjd bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope; 22510087Sjkh ParseScope ClassTemplateScope(this, Scope::TemplateParamScope, HasTemplateScope); 22610087Sjkh if (HasTemplateScope) 227117278Scharnier Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate); 22810087Sjkh 22910087Sjkh bool HasClassScope = !Class.TopLevelClass; 2301553Srgrimes ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope, 23153770Scharnier HasClassScope); 2321553Srgrimes 2331553Srgrimes for (size_t i = 0; i < Class.LateParsedDeclarations.size(); ++i) { 2341553Srgrimes Class.LateParsedDeclarations[i]->ParseLexedMethodDefs(); 2351553Srgrimes } 2361553Srgrimes} 2371553Srgrimes 2381553Srgrimesvoid Parser::ParseLexedMethodDef(LexedMethod &LM) { 2391553Srgrimes // If this is a member template, introduce the template parameter scope. 2401553Srgrimes ParseScope TemplateScope(this, Scope::TemplateParamScope, LM.TemplateScope); 241229403Sed if (LM.TemplateScope) 2421553Srgrimes Actions.ActOnReenterTemplateScope(getCurScope(), LM.D); 243252602Spjd 2441553Srgrimes // Save the current token position. 2451553Srgrimes SourceLocation origLoc = Tok.getLocation(); 2461553Srgrimes 2471553Srgrimes assert(!LM.Toks.empty() && "Empty body!"); 2481553Srgrimes // Append the current token at the end of the new token stream so that it 2491553Srgrimes // doesn't get lost. 2501553Srgrimes LM.Toks.push_back(Tok); 2511553Srgrimes PP.EnterTokenStream(LM.Toks.data(), LM.Toks.size(), true, false); 2521553Srgrimes 25399825Salfred // Consume the previously pushed token. 25499825Salfred ConsumeAnyToken(); 25599825Salfred assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) 25699825Salfred && "Inline method not starting with '{', ':' or 'try'"); 25799825Salfred 2581553Srgrimes // Parse the method body. Function body parsing code is similar enough 2591553Srgrimes // to be re-used for method bodies as well. 2601553Srgrimes ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope); 261220969Ssimon Actions.ActOnStartOfFunctionDef(getCurScope(), LM.D); 262220969Ssimon 263220969Ssimon if (Tok.is(tok::kw_try)) { 264220969Ssimon ParseFunctionTryBlock(LM.D); 265252602Spjd assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc, 266220969Ssimon Tok.getLocation()) && 267220969Ssimon "ParseFunctionTryBlock went over the cached tokens!"); 268220969Ssimon // There could be leftover tokens (e.g. because of an error). 269220969Ssimon // Skip through until we reach the original token position. 270220969Ssimon while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof)) 271220969Ssimon ConsumeAnyToken(); 272220969Ssimon return; 2731553Srgrimes } 2741553Srgrimes if (Tok.is(tok::colon)) { 27542508Ssteve ParseConstructorInitializer(LM.D); 276252603Spjd 277252603Spjd // Error recovery. 278252603Spjd if (!Tok.is(tok::l_brace)) { 279252603Spjd Actions.ActOnFinishFunctionBody(LM.D, 0); 280252603Spjd return; 281252603Spjd } 282255227Spjd } else 283255227Spjd Actions.ActOnDefaultCtorInitializers(LM.D); 284255227Spjd 285255227Spjd ParseFunctionStatementBody(LM.D); 286255227Spjd 287255227Spjd if (Tok.getLocation() != origLoc) { 288252603Spjd // Due to parsing error, we either went over the cached tokens or 289252603Spjd // there are still cached tokens left. If it's the latter case skip the 290252603Spjd // leftover tokens. 291252603Spjd // Since this is an uncommon situation that should be avoided, use the 29242508Ssteve // expensive isBeforeInTranslationUnit call. 293252603Spjd if (PP.getSourceManager().isBeforeInTranslationUnit(Tok.getLocation(), 294252603Spjd origLoc)) 295252603Spjd while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof)) 296252603Spjd ConsumeAnyToken(); 297252603Spjd 298252603Spjd } 299252603Spjd} 300252603Spjd 301252603Spjd/// ConsumeAndStoreUntil - Consume and store the token at the passed token 302252603Spjd/// container until the token 'T' is reached (which gets 303252603Spjd/// consumed/stored too, if ConsumeFinalToken). 304252603Spjd/// If StopAtSemi is true, then we will stop early at a ';' character. 305252603Spjd/// Returns true if token 'T1' or 'T2' was found. 306252603Spjd/// NOTE: This is a specialized version of Parser::SkipUntil. 307252603Spjdbool Parser::ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2, 308252603Spjd CachedTokens &Toks, 309252603Spjd bool StopAtSemi, bool ConsumeFinalToken) { 310252603Spjd // We always want this function to consume at least one token if the first 311252603Spjd // token isn't T and if not at EOF. 312252603Spjd bool isFirstTokenConsumed = true; 313252603Spjd while (1) { 314252603Spjd // If we found one of the tokens, stop and return true. 315252603Spjd if (Tok.is(T1) || Tok.is(T2)) { 316252603Spjd if (ConsumeFinalToken) { 317252603Spjd Toks.push_back(Tok); 318252603Spjd ConsumeAnyToken(); 319252603Spjd } 320252603Spjd return true; 321252603Spjd } 322252603Spjd 323252603Spjd switch (Tok.getKind()) { 324252603Spjd case tok::eof: 325252603Spjd // Ran out of tokens. 326252603Spjd return false; 327252603Spjd 328252603Spjd case tok::l_paren: 329252603Spjd // Recursively consume properly-nested parens. 330252603Spjd Toks.push_back(Tok); 331252603Spjd ConsumeParen(); 332252603Spjd ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/false); 333252603Spjd break; 334252603Spjd case tok::l_square: 335252603Spjd // Recursively consume properly-nested square brackets. 336254486Spjd Toks.push_back(Tok); 337254486Spjd ConsumeBracket(); 338254486Spjd ConsumeAndStoreUntil(tok::r_square, Toks, /*StopAtSemi=*/false); 339252603Spjd break; 340254486Spjd case tok::l_brace: 341252603Spjd // Recursively consume properly-nested braces. 342252603Spjd Toks.push_back(Tok); 343252603Spjd ConsumeBrace(); 344252603Spjd ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false); 345252603Spjd break; 346252603Spjd 347252603Spjd // Okay, we found a ']' or '}' or ')', which we think should be balanced. 348252603Spjd // Since the user wasn't looking for this token (if they were, it would 349252603Spjd // already be handled), this isn't balanced. If there is a LHS token at a 350252603Spjd // higher level, we will assume that this matches the unbalanced token 351252603Spjd // and return it. Otherwise, this is a spurious RHS token, which we skip. 352252603Spjd case tok::r_paren: 353255219Spjd if (ParenCount && !isFirstTokenConsumed) 354252603Spjd return false; // Matches something. 355252605Spjd Toks.push_back(Tok); 356252603Spjd ConsumeParen(); 357252603Spjd break; 358252603Spjd case tok::r_square: 359252603Spjd if (BracketCount && !isFirstTokenConsumed) 360252603Spjd return false; // Matches something. 361252603Spjd Toks.push_back(Tok); 362252605Spjd ConsumeBracket(); 363252605Spjd break; 364252605Spjd case tok::r_brace: 365252605Spjd if (BraceCount && !isFirstTokenConsumed) 366252605Spjd return false; // Matches something. 367255219Spjd Toks.push_back(Tok); 368255219Spjd ConsumeBrace(); 369255219Spjd break; 370252605Spjd 371252605Spjd case tok::string_literal: 372252605Spjd case tok::wide_string_literal: 373252605Spjd Toks.push_back(Tok); 374252605Spjd ConsumeStringToken(); 375252605Spjd break; 376252605Spjd case tok::semi: 3771553Srgrimes if (StopAtSemi) 378252602Spjd return false; 379252602Spjd // FALL THROUGH. 3801553Srgrimes default: 3811553Srgrimes // consume this token. 3821553Srgrimes Toks.push_back(Tok); 3831553Srgrimes ConsumeToken(); 3841553Srgrimes break; 38541895Sdes } 38670284Siedowse isFirstTokenConsumed = false; 38770284Siedowse } 3881553Srgrimes} 3891553Srgrimes