summaryrefslogtreecommitdiffstats
path: root/clang/lib/Parse/ParseCXXInlineMethods.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Parse/ParseCXXInlineMethods.cpp')
-rw-r--r--clang/lib/Parse/ParseCXXInlineMethods.cpp88
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.
OpenPOWER on IntegriCloud