ParseCXXInlineMethods.cpp revision 72b505b7904b3c9320a1312998800ba76e4f5841
14cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis//===--- ParseCXXInlineMethods.cpp - C++ class inline methods parsing------===//
24cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis//
34cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis//                     The LLVM Compiler Infrastructure
44cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis//
54cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis// This file is distributed under the University of Illinois Open Source
64cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis// License. See LICENSE.TXT for details.
74cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis//
84cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis//===----------------------------------------------------------------------===//
94cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis//
104cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis//  This file implements parsing for C++ class inline methods.
114cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis//
124cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis//===----------------------------------------------------------------------===//
134cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis
143f08d181f620e6bf4971c436fc9878f98a02bbe3Douglas Gregor#include "clang/Basic/Diagnostic.h"
154cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis#include "clang/Parse/Parser.h"
164cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis#include "clang/Parse/DeclSpec.h"
174cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis#include "clang/Parse/Scope.h"
184cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidisusing namespace clang;
194cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis
204cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis/// ParseInlineCXXMethodDef - We parsed and verified that the specified
214cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis/// Declarator is a well formed C++ inline method definition. Now lex its body
224cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis/// and store its tokens for parsing after the C++ class is complete.
234cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios KyrtzidisParser::DeclTy *
244cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios KyrtzidisParser::ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D) {
254cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis  assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function &&
264cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis         "This isn't a function declarator!");
277ad8390f7992ab7f19b1460c5f0b9d96f165c4e9Douglas Gregor  assert((Tok.is(tok::l_brace) || Tok.is(tok::colon)) &&
287ad8390f7992ab7f19b1460c5f0b9d96f165c4e9Douglas Gregor         "Current token not a '{' or ':'!");
294cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis
304cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis  DeclTy *FnD = Actions.ActOnCXXMemberDeclarator(CurScope, AS, D, 0, 0, 0);
314cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis
324cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis  // Consume the tokens and store them for later parsing.
334cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis
3472b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor  getCurTopClassStack().MethodDefs.push_back(LexedMethod(FnD));
3572b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor  CachedTokens &Toks = getCurTopClassStack().MethodDefs.back().Toks;
364cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis
377ad8390f7992ab7f19b1460c5f0b9d96f165c4e9Douglas Gregor  // We may have a constructor initializer here.
387ad8390f7992ab7f19b1460c5f0b9d96f165c4e9Douglas Gregor  if (Tok.is(tok::colon)) {
397ad8390f7992ab7f19b1460c5f0b9d96f165c4e9Douglas Gregor    // Consume everything up to (and including) the left brace.
4072b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor    if (!ConsumeAndStoreUntil(tok::l_brace, tok::unknown, Toks, tok::semi)) {
413f08d181f620e6bf4971c436fc9878f98a02bbe3Douglas Gregor      // We didn't find the left-brace we expected after the
423f08d181f620e6bf4971c436fc9878f98a02bbe3Douglas Gregor      // constructor initializer.
433f08d181f620e6bf4971c436fc9878f98a02bbe3Douglas Gregor      if (Tok.is(tok::semi)) {
443f08d181f620e6bf4971c436fc9878f98a02bbe3Douglas Gregor        // We found a semicolon; complain, consume the semicolon, and
453f08d181f620e6bf4971c436fc9878f98a02bbe3Douglas Gregor        // don't try to parse this method later.
463f08d181f620e6bf4971c436fc9878f98a02bbe3Douglas Gregor        Diag(Tok.getLocation(), diag::err_expected_lbrace);
473f08d181f620e6bf4971c436fc9878f98a02bbe3Douglas Gregor        ConsumeAnyToken();
4872b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor        getCurTopClassStack().MethodDefs.pop_back();
493f08d181f620e6bf4971c436fc9878f98a02bbe3Douglas Gregor        return FnD;
503f08d181f620e6bf4971c436fc9878f98a02bbe3Douglas Gregor      }
513f08d181f620e6bf4971c436fc9878f98a02bbe3Douglas Gregor    }
523f08d181f620e6bf4971c436fc9878f98a02bbe3Douglas Gregor
537ad8390f7992ab7f19b1460c5f0b9d96f165c4e9Douglas Gregor  } else {
547ad8390f7992ab7f19b1460c5f0b9d96f165c4e9Douglas Gregor    // Begin by storing the '{' token.
557ad8390f7992ab7f19b1460c5f0b9d96f165c4e9Douglas Gregor    Toks.push_back(Tok);
567ad8390f7992ab7f19b1460c5f0b9d96f165c4e9Douglas Gregor    ConsumeBrace();
577ad8390f7992ab7f19b1460c5f0b9d96f165c4e9Douglas Gregor  }
587ad8390f7992ab7f19b1460c5f0b9d96f165c4e9Douglas Gregor  // Consume everything up to (and including) the matching right brace.
5972b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor  ConsumeAndStoreUntil(tok::r_brace, tok::unknown, Toks);
604cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis
614cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis  return FnD;
624cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis}
634cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis
6472b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor/// ParseLexedMethodDeclarations - We finished parsing the member
6572b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor/// specification of a top (non-nested) C++ class. Now go over the
6672b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor/// stack of method declarations with some parts for which parsing was
6772b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor/// delayed (such as default arguments) and parse them.
6872b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregorvoid Parser::ParseLexedMethodDeclarations() {
6972b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor  for (; !getCurTopClassStack().MethodDecls.empty();
7072b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor       getCurTopClassStack().MethodDecls.pop_front()) {
7172b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor    LateParsedMethodDeclaration &LM = getCurTopClassStack().MethodDecls.front();
7272b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor
7372b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor    // Start the delayed C++ method declaration
7472b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor    Actions.ActOnStartDelayedCXXMethodDeclaration(CurScope, LM.Method);
7572b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor
7672b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor    // Introduce the parameters into scope and parse their default
7772b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor    // arguments.
7872b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor    ParseScope PrototypeScope(this, Scope::FnScope|Scope::DeclScope);
7972b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor    for (unsigned I = 0, N = LM.DefaultArgs.size(); I != N; ++I) {
8072b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor      // Introduce the parameter into scope.
8172b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor      Actions.ActOnDelayedCXXMethodParameter(CurScope, LM.DefaultArgs[I].Param);
8272b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor
8372b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor      if (CachedTokens *Toks = LM.DefaultArgs[I].Toks) {
8472b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor        // Parse the default argument from its saved token stream.
8572b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor        Toks->push_back(Tok); // So that the current token doesn't get lost
8672b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor        PP.EnterTokenStream(&Toks->front(), Toks->size(), true, false);
8772b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor
8872b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor        // Consume the previously-pushed token.
8972b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor        ConsumeAnyToken();
9072b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor
9172b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor        // Consume the '='.
9272b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor        assert(Tok.is(tok::equal) && "Default argument not starting with '='");
9372b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor        SourceLocation EqualLoc = ConsumeToken();
9472b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor
9572b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor        OwningExprResult DefArgResult(ParseAssignmentExpression());
9672b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor        if (DefArgResult.isInvalid())
9772b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor          Actions.ActOnParamDefaultArgumentError(LM.DefaultArgs[I].Param);
9872b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor        else
9972b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor          Actions.ActOnParamDefaultArgument(LM.DefaultArgs[I].Param, EqualLoc,
10072b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor                                            DefArgResult.release());
10172b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor        delete Toks;
10272b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor        LM.DefaultArgs[I].Toks = 0;
10372b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor      }
10472b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor    }
10572b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor    PrototypeScope.Exit();
10672b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor
10772b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor    // Finish the delayed C++ method declaration.
10872b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor    Actions.ActOnFinishDelayedCXXMethodDeclaration(CurScope, LM.Method);
10972b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor  }
11072b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor}
11172b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor
1124cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis/// ParseLexedMethodDefs - We finished parsing the member specification of a top
1134cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis/// (non-nested) C++ class. Now go over the stack of lexed methods that were
1144cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis/// collected during its parsing and parse them all.
1154cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidisvoid Parser::ParseLexedMethodDefs() {
11672b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor  for (; !getCurTopClassStack().MethodDefs.empty();
11772b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor       getCurTopClassStack().MethodDefs.pop_front()) {
11872b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor    LexedMethod &LM = getCurTopClassStack().MethodDefs.front();
1194cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis
1204cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis    assert(!LM.Toks.empty() && "Empty body!");
1214cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis    // Append the current token at the end of the new token stream so that it
1224cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis    // doesn't get lost.
1234cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis    LM.Toks.push_back(Tok);
1244cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis    PP.EnterTokenStream(&LM.Toks.front(), LM.Toks.size(), true, false);
1254cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis
1264cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis    // Consume the previously pushed token.
1274cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis    ConsumeAnyToken();
1287ad8390f7992ab7f19b1460c5f0b9d96f165c4e9Douglas Gregor    assert((Tok.is(tok::l_brace) || Tok.is(tok::colon)) &&
1297ad8390f7992ab7f19b1460c5f0b9d96f165c4e9Douglas Gregor           "Inline method not starting with '{' or ':'");
1304cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis
1314cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis    // Parse the method body. Function body parsing code is similar enough
1324cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis    // to be re-used for method bodies as well.
1338935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor    ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope);
1344cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis    Actions.ActOnStartOfFunctionDef(CurScope, LM.D);
1354cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis
1367ad8390f7992ab7f19b1460c5f0b9d96f165c4e9Douglas Gregor    if (Tok.is(tok::colon))
1377ad8390f7992ab7f19b1460c5f0b9d96f165c4e9Douglas Gregor      ParseConstructorInitializer(LM.D);
1387ad8390f7992ab7f19b1460c5f0b9d96f165c4e9Douglas Gregor
1394cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis    ParseFunctionStatementBody(LM.D, Tok.getLocation(), Tok.getLocation());
1404cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis  }
1414cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis}
1424cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis
1434cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis/// ConsumeAndStoreUntil - Consume and store the token at the passed token
14472b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor/// container until the token 'T' is reached (which gets
14572b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor/// consumed/stored too, if ConsumeFinalToken).
1463f08d181f620e6bf4971c436fc9878f98a02bbe3Douglas Gregor/// If EarlyAbortIf is specified, then we will stop early if we find that
1473f08d181f620e6bf4971c436fc9878f98a02bbe3Douglas Gregor/// token at the top level.
14872b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor/// Returns true if token 'T1' or 'T2' was found.
1494cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis/// NOTE: This is a specialized version of Parser::SkipUntil.
15072b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregorbool Parser::ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2,
15172b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor                                  CachedTokens &Toks,
15272b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor                                  tok::TokenKind EarlyAbortIf,
15372b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor                                  bool ConsumeFinalToken) {
1544cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis  // We always want this function to consume at least one token if the first
1554cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis  // token isn't T and if not at EOF.
1564cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis  bool isFirstTokenConsumed = true;
1574cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis  while (1) {
1584cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis    // If we found one of the tokens, stop and return true.
15972b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor    if (Tok.is(T1) || Tok.is(T2)) {
16072b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor      if (ConsumeFinalToken) {
16172b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor        Toks.push_back(Tok);
16272b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor        ConsumeAnyToken();
16372b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor      }
1644cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis      return true;
1654cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis    }
1664cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis
1673f08d181f620e6bf4971c436fc9878f98a02bbe3Douglas Gregor    // If we found the early-abort token, return.
1683f08d181f620e6bf4971c436fc9878f98a02bbe3Douglas Gregor    if (Tok.is(EarlyAbortIf))
1693f08d181f620e6bf4971c436fc9878f98a02bbe3Douglas Gregor      return false;
1703f08d181f620e6bf4971c436fc9878f98a02bbe3Douglas Gregor
1714cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis    switch (Tok.getKind()) {
1724cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis    case tok::eof:
1734cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis      // Ran out of tokens.
1744cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis      return false;
1754cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis
1764cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis    case tok::l_paren:
1774cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis      // Recursively consume properly-nested parens.
1784cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis      Toks.push_back(Tok);
1794cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis      ConsumeParen();
18072b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor      ConsumeAndStoreUntil(tok::r_paren, tok::unknown, Toks);
1814cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis      break;
1824cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis    case tok::l_square:
1834cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis      // Recursively consume properly-nested square brackets.
1844cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis      Toks.push_back(Tok);
1854cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis      ConsumeBracket();
18672b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor      ConsumeAndStoreUntil(tok::r_square, tok::unknown, Toks);
1874cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis      break;
1884cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis    case tok::l_brace:
1894cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis      // Recursively consume properly-nested braces.
1904cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis      Toks.push_back(Tok);
1914cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis      ConsumeBrace();
19272b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor      ConsumeAndStoreUntil(tok::r_brace, tok::unknown, Toks);
1934cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis      break;
1944cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis
1954cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis    // Okay, we found a ']' or '}' or ')', which we think should be balanced.
1964cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis    // Since the user wasn't looking for this token (if they were, it would
1974cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis    // already be handled), this isn't balanced.  If there is a LHS token at a
1984cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis    // higher level, we will assume that this matches the unbalanced token
1994cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis    // and return it.  Otherwise, this is a spurious RHS token, which we skip.
2004cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis    case tok::r_paren:
2014cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis      if (ParenCount && !isFirstTokenConsumed)
2024cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis        return false;  // Matches something.
2034cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis      Toks.push_back(Tok);
2044cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis      ConsumeParen();
2054cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis      break;
2064cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis    case tok::r_square:
2074cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis      if (BracketCount && !isFirstTokenConsumed)
2084cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis        return false;  // Matches something.
2094cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis      Toks.push_back(Tok);
2104cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis      ConsumeBracket();
2114cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis      break;
2124cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis    case tok::r_brace:
2134cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis      if (BraceCount && !isFirstTokenConsumed)
2144cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis        return false;  // Matches something.
2154cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis      Toks.push_back(Tok);
2164cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis      ConsumeBrace();
2174cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis      break;
2184cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis
2194cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis    case tok::string_literal:
2204cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis    case tok::wide_string_literal:
2214cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis      Toks.push_back(Tok);
2224cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis      ConsumeStringToken();
2234cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis      break;
2244cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis    default:
2254cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis      // consume this token.
2264cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis      Toks.push_back(Tok);
2274cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis      ConsumeToken();
2284cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis      break;
2294cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis    }
2304cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis    isFirstTokenConsumed = false;
2314cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis  }
2324cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis}
233