diff options
Diffstat (limited to 'clang/lib/Parse/ParseCXXInlineMethods.cpp')
-rw-r--r-- | clang/lib/Parse/ParseCXXInlineMethods.cpp | 88 |
1 files changed, 71 insertions, 17 deletions
diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp index 824847af63b..a9712fe9ed4 100644 --- a/clang/lib/Parse/ParseCXXInlineMethods.cpp +++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp @@ -31,13 +31,13 @@ Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D) { // Consume the tokens and store them for later parsing. - getCurTopClassStack().push(LexedMethod(FnD)); - TokensTy &Toks = getCurTopClassStack().top().Toks; + getCurTopClassStack().MethodDefs.push_back(LexedMethod(FnD)); + CachedTokens &Toks = getCurTopClassStack().MethodDefs.back().Toks; // We may have a constructor initializer here. if (Tok.is(tok::colon)) { // Consume everything up to (and including) the left brace. - if (!ConsumeAndStoreUntil(tok::l_brace, Toks, tok::semi)) { + if (!ConsumeAndStoreUntil(tok::l_brace, tok::unknown, Toks, tok::semi)) { // We didn't find the left-brace we expected after the // constructor initializer. if (Tok.is(tok::semi)) { @@ -45,7 +45,7 @@ Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D) { // don't try to parse this method later. Diag(Tok.getLocation(), diag::err_expected_lbrace); ConsumeAnyToken(); - getCurTopClassStack().pop(); + getCurTopClassStack().MethodDefs.pop_back(); return FnD; } } @@ -56,17 +56,66 @@ Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D) { ConsumeBrace(); } // Consume everything up to (and including) the matching right brace. - ConsumeAndStoreUntil(tok::r_brace, Toks); + ConsumeAndStoreUntil(tok::r_brace, tok::unknown, Toks); return FnD; } +/// ParseLexedMethodDeclarations - We finished parsing the member +/// specification of a top (non-nested) C++ class. Now go over the +/// stack of method declarations with some parts for which parsing was +/// delayed (such as default arguments) and parse them. +void Parser::ParseLexedMethodDeclarations() { + for (; !getCurTopClassStack().MethodDecls.empty(); + getCurTopClassStack().MethodDecls.pop_front()) { + LateParsedMethodDeclaration &LM = getCurTopClassStack().MethodDecls.front(); + + // Start the delayed C++ method declaration + Actions.ActOnStartDelayedCXXMethodDeclaration(CurScope, LM.Method); + + // Introduce the parameters into scope and parse their default + // arguments. + ParseScope PrototypeScope(this, Scope::FnScope|Scope::DeclScope); + for (unsigned I = 0, N = LM.DefaultArgs.size(); I != N; ++I) { + // Introduce the parameter into scope. + Actions.ActOnDelayedCXXMethodParameter(CurScope, LM.DefaultArgs[I].Param); + + if (CachedTokens *Toks = LM.DefaultArgs[I].Toks) { + // Parse the default argument from its saved token stream. + Toks->push_back(Tok); // So that the current token doesn't get lost + PP.EnterTokenStream(&Toks->front(), Toks->size(), true, false); + + // Consume the previously-pushed token. + ConsumeAnyToken(); + + // Consume the '='. + assert(Tok.is(tok::equal) && "Default argument not starting with '='"); + SourceLocation EqualLoc = ConsumeToken(); + + OwningExprResult DefArgResult(ParseAssignmentExpression()); + if (DefArgResult.isInvalid()) + Actions.ActOnParamDefaultArgumentError(LM.DefaultArgs[I].Param); + else + Actions.ActOnParamDefaultArgument(LM.DefaultArgs[I].Param, EqualLoc, + DefArgResult.release()); + delete Toks; + LM.DefaultArgs[I].Toks = 0; + } + } + PrototypeScope.Exit(); + + // Finish the delayed C++ method declaration. + Actions.ActOnFinishDelayedCXXMethodDeclaration(CurScope, LM.Method); + } +} + /// ParseLexedMethodDefs - We finished parsing the member specification of a top /// (non-nested) C++ class. Now go over the stack of lexed methods that were /// collected during its parsing and parse them all. void Parser::ParseLexedMethodDefs() { - for (; !getCurTopClassStack().empty(); getCurTopClassStack().pop()) { - LexedMethod &LM = getCurTopClassStack().top(); + for (; !getCurTopClassStack().MethodDefs.empty(); + getCurTopClassStack().MethodDefs.pop_front()) { + LexedMethod &LM = getCurTopClassStack().MethodDefs.front(); assert(!LM.Toks.empty() && "Empty body!"); // Append the current token at the end of the new token stream so that it @@ -92,21 +141,26 @@ void Parser::ParseLexedMethodDefs() { } /// ConsumeAndStoreUntil - Consume and store the token at the passed token -/// container until the token 'T' is reached (which gets consumed/stored too). +/// container until the token 'T' is reached (which gets +/// consumed/stored too, if ConsumeFinalToken). /// If EarlyAbortIf is specified, then we will stop early if we find that /// token at the top level. -/// Returns true if token 'T' was found. +/// Returns true if token 'T1' or 'T2' was found. /// NOTE: This is a specialized version of Parser::SkipUntil. -bool Parser::ConsumeAndStoreUntil(tok::TokenKind T, TokensTy &Toks, - tok::TokenKind EarlyAbortIf) { +bool Parser::ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2, + CachedTokens &Toks, + tok::TokenKind EarlyAbortIf, + bool ConsumeFinalToken) { // We always want this function to consume at least one token if the first // token isn't T and if not at EOF. bool isFirstTokenConsumed = true; while (1) { // If we found one of the tokens, stop and return true. - if (Tok.is(T)) { - Toks.push_back(Tok); - ConsumeAnyToken(); + if (Tok.is(T1) || Tok.is(T2)) { + if (ConsumeFinalToken) { + Toks.push_back(Tok); + ConsumeAnyToken(); + } return true; } @@ -123,19 +177,19 @@ bool Parser::ConsumeAndStoreUntil(tok::TokenKind T, TokensTy &Toks, // Recursively consume properly-nested parens. Toks.push_back(Tok); ConsumeParen(); - ConsumeAndStoreUntil(tok::r_paren, Toks); + ConsumeAndStoreUntil(tok::r_paren, tok::unknown, Toks); break; case tok::l_square: // Recursively consume properly-nested square brackets. Toks.push_back(Tok); ConsumeBracket(); - ConsumeAndStoreUntil(tok::r_square, Toks); + ConsumeAndStoreUntil(tok::r_square, tok::unknown, Toks); break; case tok::l_brace: // Recursively consume properly-nested braces. Toks.push_back(Tok); ConsumeBrace(); - ConsumeAndStoreUntil(tok::r_brace, Toks); + ConsumeAndStoreUntil(tok::r_brace, tok::unknown, Toks); break; // Okay, we found a ']' or '}' or ')', which we think should be balanced. |