ParseCXXInlineMethods.cpp revision 198092
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" 16193326Sed#include "clang/Parse/DeclSpec.h" 17193326Sed#include "clang/Parse/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. 23193326SedParser::DeclPtrTy 24198092SrdivackyParser::ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D, 25198092Srdivacky const ParsedTemplateInfo &TemplateInfo) { 26193326Sed assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function && 27193326Sed "This isn't a function declarator!"); 28193326Sed assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) && 29193326Sed "Current token not a '{', ':' or 'try'!"); 30193326Sed 31198092Srdivacky Action::MultiTemplateParamsArg TemplateParams(Actions, 32198092Srdivacky TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->data() : 0, 33198092Srdivacky TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->size() : 0); 34198092Srdivacky DeclPtrTy FnD; 35198092Srdivacky if (D.getDeclSpec().isFriendSpecified()) 36198092Srdivacky // FIXME: Friend templates 37198092Srdivacky FnD = Actions.ActOnFriendFunctionDecl(CurScope, D, true, move(TemplateParams)); 38198092Srdivacky else // FIXME: pass template information through 39198092Srdivacky FnD = Actions.ActOnCXXMemberDeclarator(CurScope, AS, D, 40198092Srdivacky move(TemplateParams), 0, 0); 41193326Sed 42198092Srdivacky HandleMemberFunctionDefaultArgs(D, FnD); 43198092Srdivacky 44193326Sed // Consume the tokens and store them for later parsing. 45193326Sed 46193326Sed getCurrentClass().MethodDefs.push_back(LexedMethod(FnD)); 47198092Srdivacky getCurrentClass().MethodDefs.back().TemplateScope 48198092Srdivacky = CurScope->isTemplateParamScope(); 49193326Sed CachedTokens &Toks = getCurrentClass().MethodDefs.back().Toks; 50193326Sed 51193326Sed tok::TokenKind kind = Tok.getKind(); 52193326Sed // We may have a constructor initializer or function-try-block here. 53193326Sed if (kind == tok::colon || kind == tok::kw_try) { 54193326Sed // Consume everything up to (and including) the left brace. 55193326Sed if (!ConsumeAndStoreUntil(tok::l_brace, tok::unknown, Toks, tok::semi)) { 56193326Sed // We didn't find the left-brace we expected after the 57198092Srdivacky // constructor initializer. 58193326Sed if (Tok.is(tok::semi)) { 59193326Sed // We found a semicolon; complain, consume the semicolon, and 60193326Sed // don't try to parse this method later. 61193326Sed Diag(Tok.getLocation(), diag::err_expected_lbrace); 62193326Sed ConsumeAnyToken(); 63193326Sed getCurrentClass().MethodDefs.pop_back(); 64193326Sed return FnD; 65193326Sed } 66193326Sed } 67193326Sed 68193326Sed } else { 69198092Srdivacky // Begin by storing the '{' token. 70193326Sed Toks.push_back(Tok); 71193326Sed ConsumeBrace(); 72193326Sed } 73193326Sed // Consume everything up to (and including) the matching right brace. 74193326Sed ConsumeAndStoreUntil(tok::r_brace, tok::unknown, Toks); 75193326Sed 76193326Sed // If we're in a function-try-block, we need to store all the catch blocks. 77193326Sed if (kind == tok::kw_try) { 78193326Sed while (Tok.is(tok::kw_catch)) { 79193326Sed ConsumeAndStoreUntil(tok::l_brace, tok::unknown, Toks); 80193326Sed ConsumeAndStoreUntil(tok::r_brace, tok::unknown, Toks); 81193326Sed } 82193326Sed } 83193326Sed 84193326Sed return FnD; 85193326Sed} 86193326Sed 87193326Sed/// ParseLexedMethodDeclarations - We finished parsing the member 88193326Sed/// specification of a top (non-nested) C++ class. Now go over the 89193326Sed/// stack of method declarations with some parts for which parsing was 90193326Sed/// delayed (such as default arguments) and parse them. 91193326Sedvoid Parser::ParseLexedMethodDeclarations(ParsingClass &Class) { 92193326Sed bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope; 93193326Sed ParseScope TemplateScope(this, Scope::TemplateParamScope, HasTemplateScope); 94193326Sed if (HasTemplateScope) 95193326Sed Actions.ActOnReenterTemplateScope(CurScope, Class.TagOrTemplate); 96193326Sed 97193326Sed bool HasClassScope = !Class.TopLevelClass; 98193326Sed ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope, 99193326Sed HasClassScope); 100193326Sed 101193326Sed for (; !Class.MethodDecls.empty(); Class.MethodDecls.pop_front()) { 102193326Sed LateParsedMethodDeclaration &LM = Class.MethodDecls.front(); 103193326Sed 104198092Srdivacky // If this is a member template, introduce the template parameter scope. 105198092Srdivacky ParseScope TemplateScope(this, Scope::TemplateParamScope, LM.TemplateScope); 106198092Srdivacky if (LM.TemplateScope) 107198092Srdivacky Actions.ActOnReenterTemplateScope(CurScope, LM.Method); 108198092Srdivacky 109193326Sed // Start the delayed C++ method declaration 110193326Sed Actions.ActOnStartDelayedCXXMethodDeclaration(CurScope, LM.Method); 111193326Sed 112193326Sed // Introduce the parameters into scope and parse their default 113193326Sed // arguments. 114198092Srdivacky ParseScope PrototypeScope(this, 115193326Sed Scope::FunctionPrototypeScope|Scope::DeclScope); 116193326Sed for (unsigned I = 0, N = LM.DefaultArgs.size(); I != N; ++I) { 117193326Sed // Introduce the parameter into scope. 118193326Sed Actions.ActOnDelayedCXXMethodParameter(CurScope, LM.DefaultArgs[I].Param); 119193326Sed 120193326Sed if (CachedTokens *Toks = LM.DefaultArgs[I].Toks) { 121193326Sed // Parse the default argument from its saved token stream. 122193326Sed Toks->push_back(Tok); // So that the current token doesn't get lost 123193326Sed PP.EnterTokenStream(&Toks->front(), Toks->size(), true, false); 124193326Sed 125193326Sed // Consume the previously-pushed token. 126193326Sed ConsumeAnyToken(); 127193326Sed 128193326Sed // Consume the '='. 129193326Sed assert(Tok.is(tok::equal) && "Default argument not starting with '='"); 130193326Sed SourceLocation EqualLoc = ConsumeToken(); 131193326Sed 132193326Sed OwningExprResult DefArgResult(ParseAssignmentExpression()); 133193326Sed if (DefArgResult.isInvalid()) 134193326Sed Actions.ActOnParamDefaultArgumentError(LM.DefaultArgs[I].Param); 135193326Sed else 136193326Sed Actions.ActOnParamDefaultArgument(LM.DefaultArgs[I].Param, EqualLoc, 137193326Sed move(DefArgResult)); 138193326Sed delete Toks; 139193326Sed LM.DefaultArgs[I].Toks = 0; 140193326Sed } 141193326Sed } 142193326Sed PrototypeScope.Exit(); 143193326Sed 144193326Sed // Finish the delayed C++ method declaration. 145193326Sed Actions.ActOnFinishDelayedCXXMethodDeclaration(CurScope, LM.Method); 146193326Sed } 147193326Sed 148193326Sed for (unsigned I = 0, N = Class.NestedClasses.size(); I != N; ++I) 149193326Sed ParseLexedMethodDeclarations(*Class.NestedClasses[I]); 150193326Sed} 151193326Sed 152193326Sed/// ParseLexedMethodDefs - We finished parsing the member specification of a top 153193326Sed/// (non-nested) C++ class. Now go over the stack of lexed methods that were 154193326Sed/// collected during its parsing and parse them all. 155193326Sedvoid Parser::ParseLexedMethodDefs(ParsingClass &Class) { 156193326Sed bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope; 157193326Sed ParseScope TemplateScope(this, Scope::TemplateParamScope, HasTemplateScope); 158193326Sed if (HasTemplateScope) 159193326Sed Actions.ActOnReenterTemplateScope(CurScope, Class.TagOrTemplate); 160193326Sed 161193326Sed bool HasClassScope = !Class.TopLevelClass; 162193326Sed ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope, 163193326Sed HasClassScope); 164193326Sed 165193326Sed for (; !Class.MethodDefs.empty(); Class.MethodDefs.pop_front()) { 166193326Sed LexedMethod &LM = Class.MethodDefs.front(); 167193326Sed 168198092Srdivacky // If this is a member template, introduce the template parameter scope. 169198092Srdivacky ParseScope TemplateScope(this, Scope::TemplateParamScope, LM.TemplateScope); 170198092Srdivacky if (LM.TemplateScope) 171198092Srdivacky Actions.ActOnReenterTemplateScope(CurScope, LM.D); 172198092Srdivacky 173193326Sed assert(!LM.Toks.empty() && "Empty body!"); 174193326Sed // Append the current token at the end of the new token stream so that it 175193326Sed // doesn't get lost. 176193326Sed LM.Toks.push_back(Tok); 177198092Srdivacky PP.EnterTokenStream(LM.Toks.data(), LM.Toks.size(), true, false); 178193326Sed 179193326Sed // Consume the previously pushed token. 180193326Sed ConsumeAnyToken(); 181193326Sed assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) 182193326Sed && "Inline method not starting with '{', ':' or 'try'"); 183193326Sed 184193326Sed // Parse the method body. Function body parsing code is similar enough 185193326Sed // to be re-used for method bodies as well. 186193326Sed ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope); 187193326Sed Actions.ActOnStartOfFunctionDef(CurScope, LM.D); 188193326Sed 189193326Sed if (Tok.is(tok::kw_try)) { 190193326Sed ParseFunctionTryBlock(LM.D); 191193326Sed continue; 192193326Sed } 193193326Sed if (Tok.is(tok::colon)) 194193326Sed ParseConstructorInitializer(LM.D); 195198092Srdivacky else 196198092Srdivacky Actions.ActOnDefaultCtorInitializers(LM.D); 197198092Srdivacky 198193326Sed // FIXME: What if ParseConstructorInitializer doesn't leave us with a '{'?? 199193326Sed ParseFunctionStatementBody(LM.D); 200193326Sed } 201193326Sed 202193326Sed for (unsigned I = 0, N = Class.NestedClasses.size(); I != N; ++I) 203193326Sed ParseLexedMethodDefs(*Class.NestedClasses[I]); 204193326Sed} 205193326Sed 206193326Sed/// ConsumeAndStoreUntil - Consume and store the token at the passed token 207193326Sed/// container until the token 'T' is reached (which gets 208198092Srdivacky/// consumed/stored too, if ConsumeFinalToken). 209193326Sed/// If EarlyAbortIf is specified, then we will stop early if we find that 210193326Sed/// token at the top level. 211193326Sed/// Returns true if token 'T1' or 'T2' was found. 212193326Sed/// NOTE: This is a specialized version of Parser::SkipUntil. 213193326Sedbool Parser::ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2, 214193326Sed CachedTokens &Toks, 215193326Sed tok::TokenKind EarlyAbortIf, 216193326Sed bool ConsumeFinalToken) { 217193326Sed // We always want this function to consume at least one token if the first 218193326Sed // token isn't T and if not at EOF. 219193326Sed bool isFirstTokenConsumed = true; 220193326Sed while (1) { 221193326Sed // If we found one of the tokens, stop and return true. 222193326Sed if (Tok.is(T1) || Tok.is(T2)) { 223193326Sed if (ConsumeFinalToken) { 224193326Sed Toks.push_back(Tok); 225193326Sed ConsumeAnyToken(); 226193326Sed } 227193326Sed return true; 228193326Sed } 229193326Sed 230193326Sed // If we found the early-abort token, return. 231193326Sed if (Tok.is(EarlyAbortIf)) 232193326Sed return false; 233193326Sed 234193326Sed switch (Tok.getKind()) { 235193326Sed case tok::eof: 236193326Sed // Ran out of tokens. 237193326Sed return false; 238193326Sed 239193326Sed case tok::l_paren: 240193326Sed // Recursively consume properly-nested parens. 241193326Sed Toks.push_back(Tok); 242193326Sed ConsumeParen(); 243193326Sed ConsumeAndStoreUntil(tok::r_paren, tok::unknown, Toks); 244193326Sed break; 245193326Sed case tok::l_square: 246193326Sed // Recursively consume properly-nested square brackets. 247193326Sed Toks.push_back(Tok); 248193326Sed ConsumeBracket(); 249193326Sed ConsumeAndStoreUntil(tok::r_square, tok::unknown, Toks); 250193326Sed break; 251193326Sed case tok::l_brace: 252193326Sed // Recursively consume properly-nested braces. 253193326Sed Toks.push_back(Tok); 254193326Sed ConsumeBrace(); 255193326Sed ConsumeAndStoreUntil(tok::r_brace, tok::unknown, Toks); 256193326Sed break; 257193326Sed 258193326Sed // Okay, we found a ']' or '}' or ')', which we think should be balanced. 259193326Sed // Since the user wasn't looking for this token (if they were, it would 260193326Sed // already be handled), this isn't balanced. If there is a LHS token at a 261193326Sed // higher level, we will assume that this matches the unbalanced token 262193326Sed // and return it. Otherwise, this is a spurious RHS token, which we skip. 263193326Sed case tok::r_paren: 264193326Sed if (ParenCount && !isFirstTokenConsumed) 265193326Sed return false; // Matches something. 266193326Sed Toks.push_back(Tok); 267193326Sed ConsumeParen(); 268193326Sed break; 269193326Sed case tok::r_square: 270193326Sed if (BracketCount && !isFirstTokenConsumed) 271193326Sed return false; // Matches something. 272193326Sed Toks.push_back(Tok); 273193326Sed ConsumeBracket(); 274193326Sed break; 275193326Sed case tok::r_brace: 276193326Sed if (BraceCount && !isFirstTokenConsumed) 277193326Sed return false; // Matches something. 278193326Sed Toks.push_back(Tok); 279193326Sed ConsumeBrace(); 280193326Sed break; 281193326Sed 282193326Sed case tok::string_literal: 283193326Sed case tok::wide_string_literal: 284193326Sed Toks.push_back(Tok); 285193326Sed ConsumeStringToken(); 286193326Sed break; 287193326Sed default: 288193326Sed // consume this token. 289193326Sed Toks.push_back(Tok); 290193326Sed ConsumeToken(); 291193326Sed break; 292193326Sed } 293193326Sed isFirstTokenConsumed = false; 294193326Sed } 295193326Sed} 296