ParseCXXInlineMethods.cpp revision 218893
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" 18193326Sedusing namespace clang; 19193326Sed 20193326Sed/// ParseCXXInlineMethodDef - We parsed and verified that the specified 21193326Sed/// Declarator is a well formed C++ inline method definition. Now lex its body 22193326Sed/// and store its tokens for parsing after the C++ class is complete. 23218893SdimDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, ParsingDeclarator &D, 24218893Sdim const ParsedTemplateInfo &TemplateInfo, 25218893Sdim const VirtSpecifiers& VS) { 26218893Sdim assert(D.isFunctionDeclarator() && "This isn't a function declarator!"); 27193326Sed assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) && 28193326Sed "Current token not a '{', ':' or 'try'!"); 29193326Sed 30212904Sdim MultiTemplateParamsArg TemplateParams(Actions, 31207619Srdivacky TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->data() : 0, 32207619Srdivacky TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->size() : 0); 33207619Srdivacky 34212904Sdim Decl *FnD; 35198092Srdivacky if (D.getDeclSpec().isFriendSpecified()) 36198092Srdivacky // FIXME: Friend templates 37210299Sed FnD = Actions.ActOnFriendFunctionDecl(getCurScope(), D, true, 38207619Srdivacky move(TemplateParams)); 39218893Sdim else { // FIXME: pass template information through 40218893Sdim if (VS.isOverrideSpecified()) 41218893Sdim Diag(VS.getOverrideLoc(), diag::ext_override_inline) << "override"; 42218893Sdim if (VS.isFinalSpecified()) 43218893Sdim Diag(VS.getFinalLoc(), diag::ext_override_inline) << "final"; 44218893Sdim if (VS.isNewSpecified()) 45218893Sdim Diag(VS.getNewLoc(), diag::ext_override_inline) << "new"; 46218893Sdim 47210299Sed FnD = Actions.ActOnCXXMemberDeclarator(getCurScope(), AS, D, 48218893Sdim move(TemplateParams), 0, 49218893Sdim VS, 0, /*IsDefinition*/true); 50218893Sdim } 51193326Sed 52198092Srdivacky HandleMemberFunctionDefaultArgs(D, FnD); 53198092Srdivacky 54218893Sdim D.complete(FnD); 55218893Sdim 56193326Sed // Consume the tokens and store them for later parsing. 57193326Sed 58218893Sdim LexedMethod* LM = new LexedMethod(this, FnD); 59218893Sdim getCurrentClass().LateParsedDeclarations.push_back(LM); 60218893Sdim LM->TemplateScope = getCurScope()->isTemplateParamScope(); 61218893Sdim CachedTokens &Toks = LM->Toks; 62193326Sed 63193326Sed tok::TokenKind kind = Tok.getKind(); 64193326Sed // We may have a constructor initializer or function-try-block here. 65193326Sed if (kind == tok::colon || kind == tok::kw_try) { 66193326Sed // Consume everything up to (and including) the left brace. 67207619Srdivacky if (!ConsumeAndStoreUntil(tok::l_brace, Toks)) { 68193326Sed // We didn't find the left-brace we expected after the 69198092Srdivacky // constructor initializer. 70193326Sed if (Tok.is(tok::semi)) { 71193326Sed // We found a semicolon; complain, consume the semicolon, and 72193326Sed // don't try to parse this method later. 73193326Sed Diag(Tok.getLocation(), diag::err_expected_lbrace); 74193326Sed ConsumeAnyToken(); 75218893Sdim delete getCurrentClass().LateParsedDeclarations.back(); 76218893Sdim getCurrentClass().LateParsedDeclarations.pop_back(); 77193326Sed return FnD; 78193326Sed } 79193326Sed } 80193326Sed 81193326Sed } else { 82198092Srdivacky // Begin by storing the '{' token. 83193326Sed Toks.push_back(Tok); 84193326Sed ConsumeBrace(); 85193326Sed } 86193326Sed // Consume everything up to (and including) the matching right brace. 87207619Srdivacky ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false); 88193326Sed 89193326Sed // If we're in a function-try-block, we need to store all the catch blocks. 90193326Sed if (kind == tok::kw_try) { 91193326Sed while (Tok.is(tok::kw_catch)) { 92207619Srdivacky ConsumeAndStoreUntil(tok::l_brace, Toks, /*StopAtSemi=*/false); 93207619Srdivacky ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false); 94193326Sed } 95193326Sed } 96193326Sed 97193326Sed return FnD; 98193326Sed} 99193326Sed 100218893SdimParser::LateParsedDeclaration::~LateParsedDeclaration() {} 101218893Sdimvoid Parser::LateParsedDeclaration::ParseLexedMethodDeclarations() {} 102218893Sdimvoid Parser::LateParsedDeclaration::ParseLexedMethodDefs() {} 103218893Sdim 104218893SdimParser::LateParsedClass::LateParsedClass(Parser *P, ParsingClass *C) 105218893Sdim : Self(P), Class(C) {} 106218893Sdim 107218893SdimParser::LateParsedClass::~LateParsedClass() { 108218893Sdim Self->DeallocateParsedClasses(Class); 109218893Sdim} 110218893Sdim 111218893Sdimvoid Parser::LateParsedClass::ParseLexedMethodDeclarations() { 112218893Sdim Self->ParseLexedMethodDeclarations(*Class); 113218893Sdim} 114218893Sdim 115218893Sdimvoid Parser::LateParsedClass::ParseLexedMethodDefs() { 116218893Sdim Self->ParseLexedMethodDefs(*Class); 117218893Sdim} 118218893Sdim 119218893Sdimvoid Parser::LateParsedMethodDeclaration::ParseLexedMethodDeclarations() { 120218893Sdim Self->ParseLexedMethodDeclaration(*this); 121218893Sdim} 122218893Sdim 123218893Sdimvoid Parser::LexedMethod::ParseLexedMethodDefs() { 124218893Sdim Self->ParseLexedMethodDef(*this); 125218893Sdim} 126218893Sdim 127193326Sed/// ParseLexedMethodDeclarations - We finished parsing the member 128193326Sed/// specification of a top (non-nested) C++ class. Now go over the 129193326Sed/// stack of method declarations with some parts for which parsing was 130193326Sed/// delayed (such as default arguments) and parse them. 131193326Sedvoid Parser::ParseLexedMethodDeclarations(ParsingClass &Class) { 132193326Sed bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope; 133218893Sdim ParseScope ClassTemplateScope(this, Scope::TemplateParamScope, HasTemplateScope); 134193326Sed if (HasTemplateScope) 135210299Sed Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate); 136193326Sed 137201361Srdivacky // The current scope is still active if we're the top-level class. 138201361Srdivacky // Otherwise we'll need to push and enter a new scope. 139193326Sed bool HasClassScope = !Class.TopLevelClass; 140207619Srdivacky ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope, 141207619Srdivacky HasClassScope); 142201361Srdivacky if (HasClassScope) 143210299Sed Actions.ActOnStartDelayedMemberDeclarations(getCurScope(), Class.TagOrTemplate); 144193326Sed 145218893Sdim for (size_t i = 0; i < Class.LateParsedDeclarations.size(); ++i) { 146218893Sdim Class.LateParsedDeclarations[i]->ParseLexedMethodDeclarations(); 147218893Sdim } 148193326Sed 149218893Sdim if (HasClassScope) 150218893Sdim Actions.ActOnFinishDelayedMemberDeclarations(getCurScope(), Class.TagOrTemplate); 151218893Sdim} 152198092Srdivacky 153218893Sdimvoid Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { 154218893Sdim // If this is a member template, introduce the template parameter scope. 155218893Sdim ParseScope TemplateScope(this, Scope::TemplateParamScope, LM.TemplateScope); 156218893Sdim if (LM.TemplateScope) 157218893Sdim Actions.ActOnReenterTemplateScope(getCurScope(), LM.Method); 158193326Sed 159218893Sdim // Start the delayed C++ method declaration 160218893Sdim Actions.ActOnStartDelayedCXXMethodDeclaration(getCurScope(), LM.Method); 161193326Sed 162218893Sdim // Introduce the parameters into scope and parse their default 163218893Sdim // arguments. 164218893Sdim ParseScope PrototypeScope(this, 165218893Sdim Scope::FunctionPrototypeScope|Scope::DeclScope); 166218893Sdim for (unsigned I = 0, N = LM.DefaultArgs.size(); I != N; ++I) { 167218893Sdim // Introduce the parameter into scope. 168218893Sdim Actions.ActOnDelayedCXXMethodParameter(getCurScope(), LM.DefaultArgs[I].Param); 169206084Srdivacky 170218893Sdim if (CachedTokens *Toks = LM.DefaultArgs[I].Toks) { 171218893Sdim // Save the current token position. 172218893Sdim SourceLocation origLoc = Tok.getLocation(); 173193326Sed 174218893Sdim // Parse the default argument from its saved token stream. 175218893Sdim Toks->push_back(Tok); // So that the current token doesn't get lost 176218893Sdim PP.EnterTokenStream(&Toks->front(), Toks->size(), true, false); 177193326Sed 178218893Sdim // Consume the previously-pushed token. 179218893Sdim ConsumeAnyToken(); 180193326Sed 181218893Sdim // Consume the '='. 182218893Sdim assert(Tok.is(tok::equal) && "Default argument not starting with '='"); 183218893Sdim SourceLocation EqualLoc = ConsumeToken(); 184206084Srdivacky 185218893Sdim // The argument isn't actually potentially evaluated unless it is 186218893Sdim // used. 187218893Sdim EnterExpressionEvaluationContext Eval(Actions, 188218893Sdim Sema::PotentiallyEvaluatedIfUsed); 189206084Srdivacky 190218893Sdim ExprResult DefArgResult(ParseAssignmentExpression()); 191218893Sdim if (DefArgResult.isInvalid()) 192218893Sdim Actions.ActOnParamDefaultArgumentError(LM.DefaultArgs[I].Param); 193218893Sdim else { 194218893Sdim if (Tok.is(tok::cxx_defaultarg_end)) 195218893Sdim ConsumeToken(); 196218893Sdim else 197218893Sdim Diag(Tok.getLocation(), diag::err_default_arg_unparsed); 198218893Sdim Actions.ActOnParamDefaultArgument(LM.DefaultArgs[I].Param, EqualLoc, 199218893Sdim DefArgResult.take()); 200193326Sed } 201218893Sdim 202218893Sdim assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc, 203218893Sdim Tok.getLocation()) && 204218893Sdim "ParseAssignmentExpression went over the default arg tokens!"); 205218893Sdim // There could be leftover tokens (e.g. because of an error). 206218893Sdim // Skip through until we reach the original token position. 207218893Sdim while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof)) 208218893Sdim ConsumeAnyToken(); 209218893Sdim 210218893Sdim delete Toks; 211218893Sdim LM.DefaultArgs[I].Toks = 0; 212193326Sed } 213193326Sed } 214218893Sdim PrototypeScope.Exit(); 215193326Sed 216218893Sdim // Finish the delayed C++ method declaration. 217218893Sdim Actions.ActOnFinishDelayedCXXMethodDeclaration(getCurScope(), LM.Method); 218193326Sed} 219193326Sed 220193326Sed/// ParseLexedMethodDefs - We finished parsing the member specification of a top 221193326Sed/// (non-nested) C++ class. Now go over the stack of lexed methods that were 222193326Sed/// collected during its parsing and parse them all. 223193326Sedvoid Parser::ParseLexedMethodDefs(ParsingClass &Class) { 224193326Sed bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope; 225218893Sdim ParseScope ClassTemplateScope(this, Scope::TemplateParamScope, HasTemplateScope); 226193326Sed if (HasTemplateScope) 227210299Sed Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate); 228193326Sed 229193326Sed bool HasClassScope = !Class.TopLevelClass; 230193326Sed ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope, 231193326Sed HasClassScope); 232193326Sed 233218893Sdim for (size_t i = 0; i < Class.LateParsedDeclarations.size(); ++i) { 234218893Sdim Class.LateParsedDeclarations[i]->ParseLexedMethodDefs(); 235218893Sdim } 236218893Sdim} 237193326Sed 238218893Sdimvoid Parser::ParseLexedMethodDef(LexedMethod &LM) { 239218893Sdim // If this is a member template, introduce the template parameter scope. 240218893Sdim ParseScope TemplateScope(this, Scope::TemplateParamScope, LM.TemplateScope); 241218893Sdim if (LM.TemplateScope) 242218893Sdim Actions.ActOnReenterTemplateScope(getCurScope(), LM.D); 243198092Srdivacky 244218893Sdim // Save the current token position. 245218893Sdim SourceLocation origLoc = Tok.getLocation(); 246206084Srdivacky 247218893Sdim assert(!LM.Toks.empty() && "Empty body!"); 248218893Sdim // Append the current token at the end of the new token stream so that it 249218893Sdim // doesn't get lost. 250218893Sdim LM.Toks.push_back(Tok); 251218893Sdim PP.EnterTokenStream(LM.Toks.data(), LM.Toks.size(), true, false); 252193326Sed 253218893Sdim // Consume the previously pushed token. 254218893Sdim ConsumeAnyToken(); 255218893Sdim assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) 256218893Sdim && "Inline method not starting with '{', ':' or 'try'"); 257193326Sed 258218893Sdim // Parse the method body. Function body parsing code is similar enough 259218893Sdim // to be re-used for method bodies as well. 260218893Sdim ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope); 261218893Sdim Actions.ActOnStartOfFunctionDef(getCurScope(), LM.D); 262193326Sed 263218893Sdim if (Tok.is(tok::kw_try)) { 264218893Sdim ParseFunctionTryBlock(LM.D); 265218893Sdim assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc, 266218893Sdim Tok.getLocation()) && 267218893Sdim "ParseFunctionTryBlock went over the cached tokens!"); 268218893Sdim // There could be leftover tokens (e.g. because of an error). 269218893Sdim // Skip through until we reach the original token position. 270218893Sdim while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof)) 271218893Sdim ConsumeAnyToken(); 272218893Sdim return; 273218893Sdim } 274218893Sdim if (Tok.is(tok::colon)) { 275218893Sdim ParseConstructorInitializer(LM.D); 276218893Sdim 277218893Sdim // Error recovery. 278218893Sdim if (!Tok.is(tok::l_brace)) { 279218893Sdim Actions.ActOnFinishFunctionBody(LM.D, 0); 280218893Sdim return; 281193326Sed } 282218893Sdim } else 283218893Sdim Actions.ActOnDefaultCtorInitializers(LM.D); 284207619Srdivacky 285218893Sdim ParseFunctionStatementBody(LM.D); 286198092Srdivacky 287218893Sdim if (Tok.getLocation() != origLoc) { 288218893Sdim // Due to parsing error, we either went over the cached tokens or 289218893Sdim // there are still cached tokens left. If it's the latter case skip the 290218893Sdim // leftover tokens. 291218893Sdim // Since this is an uncommon situation that should be avoided, use the 292218893Sdim // expensive isBeforeInTranslationUnit call. 293218893Sdim if (PP.getSourceManager().isBeforeInTranslationUnit(Tok.getLocation(), 294218893Sdim origLoc)) 295218893Sdim while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof)) 296218893Sdim ConsumeAnyToken(); 297210299Sed 298193326Sed } 299193326Sed} 300193326Sed 301193326Sed/// ConsumeAndStoreUntil - Consume and store the token at the passed token 302193326Sed/// container until the token 'T' is reached (which gets 303198092Srdivacky/// consumed/stored too, if ConsumeFinalToken). 304207619Srdivacky/// If StopAtSemi is true, then we will stop early at a ';' character. 305193326Sed/// Returns true if token 'T1' or 'T2' was found. 306193326Sed/// NOTE: This is a specialized version of Parser::SkipUntil. 307193326Sedbool Parser::ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2, 308193326Sed CachedTokens &Toks, 309207619Srdivacky bool StopAtSemi, bool ConsumeFinalToken) { 310193326Sed // We always want this function to consume at least one token if the first 311193326Sed // token isn't T and if not at EOF. 312193326Sed bool isFirstTokenConsumed = true; 313193326Sed while (1) { 314193326Sed // If we found one of the tokens, stop and return true. 315193326Sed if (Tok.is(T1) || Tok.is(T2)) { 316193326Sed if (ConsumeFinalToken) { 317193326Sed Toks.push_back(Tok); 318193326Sed ConsumeAnyToken(); 319193326Sed } 320193326Sed return true; 321193326Sed } 322193326Sed 323193326Sed switch (Tok.getKind()) { 324193326Sed case tok::eof: 325193326Sed // Ran out of tokens. 326193326Sed return false; 327193326Sed 328193326Sed case tok::l_paren: 329193326Sed // Recursively consume properly-nested parens. 330193326Sed Toks.push_back(Tok); 331193326Sed ConsumeParen(); 332207619Srdivacky ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/false); 333193326Sed break; 334193326Sed case tok::l_square: 335193326Sed // Recursively consume properly-nested square brackets. 336193326Sed Toks.push_back(Tok); 337193326Sed ConsumeBracket(); 338207619Srdivacky ConsumeAndStoreUntil(tok::r_square, Toks, /*StopAtSemi=*/false); 339193326Sed break; 340193326Sed case tok::l_brace: 341193326Sed // Recursively consume properly-nested braces. 342193326Sed Toks.push_back(Tok); 343193326Sed ConsumeBrace(); 344207619Srdivacky ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false); 345193326Sed break; 346193326Sed 347193326Sed // Okay, we found a ']' or '}' or ')', which we think should be balanced. 348193326Sed // Since the user wasn't looking for this token (if they were, it would 349193326Sed // already be handled), this isn't balanced. If there is a LHS token at a 350193326Sed // higher level, we will assume that this matches the unbalanced token 351193326Sed // and return it. Otherwise, this is a spurious RHS token, which we skip. 352193326Sed case tok::r_paren: 353193326Sed if (ParenCount && !isFirstTokenConsumed) 354193326Sed return false; // Matches something. 355193326Sed Toks.push_back(Tok); 356193326Sed ConsumeParen(); 357193326Sed break; 358193326Sed case tok::r_square: 359193326Sed if (BracketCount && !isFirstTokenConsumed) 360193326Sed return false; // Matches something. 361193326Sed Toks.push_back(Tok); 362193326Sed ConsumeBracket(); 363193326Sed break; 364193326Sed case tok::r_brace: 365193326Sed if (BraceCount && !isFirstTokenConsumed) 366193326Sed return false; // Matches something. 367193326Sed Toks.push_back(Tok); 368193326Sed ConsumeBrace(); 369193326Sed break; 370193326Sed 371193326Sed case tok::string_literal: 372193326Sed case tok::wide_string_literal: 373193326Sed Toks.push_back(Tok); 374193326Sed ConsumeStringToken(); 375193326Sed break; 376207619Srdivacky case tok::semi: 377207619Srdivacky if (StopAtSemi) 378207619Srdivacky return false; 379207619Srdivacky // FALL THROUGH. 380193326Sed default: 381193326Sed // consume this token. 382193326Sed Toks.push_back(Tok); 383193326Sed ConsumeToken(); 384193326Sed break; 385193326Sed } 386193326Sed isFirstTokenConsumed = false; 387193326Sed } 388193326Sed} 389