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