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