ParseCXXInlineMethods.cpp revision d226f65006733ed7f709c3174f22ce33391cb58f
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 14500d3297d2a21edeac4d46cbcbe21bc2352c2a28Chris Lattner#include "clang/Parse/ParseDiagnostic.h" 154cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis#include "clang/Parse/Parser.h" 1619510856727e0e14a3696b2a72c35163bff2a71fJohn McCall#include "clang/Sema/DeclSpec.h" 1719510856727e0e14a3696b2a72c35163bff2a71fJohn McCall#include "clang/Sema/Scope.h" 184cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidisusing namespace clang; 194cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis 20d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl/// ParseCXXInlineMethodDef - 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. 23d226f65006733ed7f709c3174f22ce33391cb58fJohn McCallDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D, 2437b372b76a3fafe77186d7e6079e5642e2017478Douglas Gregor const ParsedTemplateInfo &TemplateInfo) { 254cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function && 264cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis "This isn't a function declarator!"); 27d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) && 28d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl "Current token not a '{', ':' or 'try'!"); 294cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis 3037b372b76a3fafe77186d7e6079e5642e2017478Douglas Gregor Action::MultiTemplateParamsArg TemplateParams(Actions, 314cd8494d9a2f99cbf38147bca80be18cdff83734Sean Hunt TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->data() : 0, 324cd8494d9a2f99cbf38147bca80be18cdff83734Sean Hunt TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->size() : 0); 334cd8494d9a2f99cbf38147bca80be18cdff83734Sean Hunt 34d226f65006733ed7f709c3174f22ce33391cb58fJohn McCall Decl *FnD; 3567d1a67f3db2f1aa69083c5c94164d6e0ee05b32John McCall if (D.getDeclSpec().isFriendSpecified()) 3637b372b76a3fafe77186d7e6079e5642e2017478Douglas Gregor // FIXME: Friend templates 3723c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor FnD = Actions.ActOnFriendFunctionDecl(getCurScope(), D, true, 384cd8494d9a2f99cbf38147bca80be18cdff83734Sean Hunt move(TemplateParams)); 3937b372b76a3fafe77186d7e6079e5642e2017478Douglas Gregor else // FIXME: pass template information through 4023c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor FnD = Actions.ActOnCXXMemberDeclarator(getCurScope(), AS, D, 41d1a7846699a82f85ff3ce6b2e383409537c3f5c5Sebastian Redl move(TemplateParams), 0, 0, 42d1a7846699a82f85ff3ce6b2e383409537c3f5c5Sebastian Redl /*IsDefinition*/true); 434cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis 44d33133cdc1af466f9c276249b2621be03867888bEli Friedman HandleMemberFunctionDefaultArgs(D, FnD); 45d33133cdc1af466f9c276249b2621be03867888bEli Friedman 464cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis // Consume the tokens and store them for later parsing. 474cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis 486569d68745c8213709740337d2be52b031384f58Douglas Gregor getCurrentClass().MethodDefs.push_back(LexedMethod(FnD)); 491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump getCurrentClass().MethodDefs.back().TemplateScope 5023c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor = getCurScope()->isTemplateParamScope(); 516569d68745c8213709740337d2be52b031384f58Douglas Gregor CachedTokens &Toks = getCurrentClass().MethodDefs.back().Toks; 524cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis 53d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl tok::TokenKind kind = Tok.getKind(); 54d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl // We may have a constructor initializer or function-try-block here. 55d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl if (kind == tok::colon || kind == tok::kw_try) { 567ad8390f7992ab7f19b1460c5f0b9d96f165c4e9Douglas Gregor // Consume everything up to (and including) the left brace. 5714b91628961ab50cc6e724bbcd408fdee100662dArgyrios Kyrtzidis if (!ConsumeAndStoreUntil(tok::l_brace, Toks)) { 583f08d181f620e6bf4971c436fc9878f98a02bbe3Douglas Gregor // We didn't find the left-brace we expected after the 591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // constructor initializer. 603f08d181f620e6bf4971c436fc9878f98a02bbe3Douglas Gregor if (Tok.is(tok::semi)) { 613f08d181f620e6bf4971c436fc9878f98a02bbe3Douglas Gregor // We found a semicolon; complain, consume the semicolon, and 623f08d181f620e6bf4971c436fc9878f98a02bbe3Douglas Gregor // don't try to parse this method later. 633f08d181f620e6bf4971c436fc9878f98a02bbe3Douglas Gregor Diag(Tok.getLocation(), diag::err_expected_lbrace); 643f08d181f620e6bf4971c436fc9878f98a02bbe3Douglas Gregor ConsumeAnyToken(); 656569d68745c8213709740337d2be52b031384f58Douglas Gregor getCurrentClass().MethodDefs.pop_back(); 663f08d181f620e6bf4971c436fc9878f98a02bbe3Douglas Gregor return FnD; 673f08d181f620e6bf4971c436fc9878f98a02bbe3Douglas Gregor } 683f08d181f620e6bf4971c436fc9878f98a02bbe3Douglas Gregor } 693f08d181f620e6bf4971c436fc9878f98a02bbe3Douglas Gregor 707ad8390f7992ab7f19b1460c5f0b9d96f165c4e9Douglas Gregor } else { 711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Begin by storing the '{' token. 727ad8390f7992ab7f19b1460c5f0b9d96f165c4e9Douglas Gregor Toks.push_back(Tok); 737ad8390f7992ab7f19b1460c5f0b9d96f165c4e9Douglas Gregor ConsumeBrace(); 747ad8390f7992ab7f19b1460c5f0b9d96f165c4e9Douglas Gregor } 757ad8390f7992ab7f19b1460c5f0b9d96f165c4e9Douglas Gregor // Consume everything up to (and including) the matching right brace. 7614b91628961ab50cc6e724bbcd408fdee100662dArgyrios Kyrtzidis ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false); 774cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis 78d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl // If we're in a function-try-block, we need to store all the catch blocks. 79d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl if (kind == tok::kw_try) { 80d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl while (Tok.is(tok::kw_catch)) { 8114b91628961ab50cc6e724bbcd408fdee100662dArgyrios Kyrtzidis ConsumeAndStoreUntil(tok::l_brace, Toks, /*StopAtSemi=*/false); 8214b91628961ab50cc6e724bbcd408fdee100662dArgyrios Kyrtzidis ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false); 83d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl } 84d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl } 85d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl 864cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis return FnD; 874cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis} 884cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis 8972b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor/// ParseLexedMethodDeclarations - We finished parsing the member 9072b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor/// specification of a top (non-nested) C++ class. Now go over the 9172b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor/// stack of method declarations with some parts for which parsing was 9272b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor/// delayed (such as default arguments) and parse them. 936569d68745c8213709740337d2be52b031384f58Douglas Gregorvoid Parser::ParseLexedMethodDeclarations(ParsingClass &Class) { 946569d68745c8213709740337d2be52b031384f58Douglas Gregor bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope; 956569d68745c8213709740337d2be52b031384f58Douglas Gregor ParseScope TemplateScope(this, Scope::TemplateParamScope, HasTemplateScope); 966569d68745c8213709740337d2be52b031384f58Douglas Gregor if (HasTemplateScope) 9723c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate); 986569d68745c8213709740337d2be52b031384f58Douglas Gregor 997a1dc562d4ad59237ed9fe7e8cef56f9eaa7a26cJohn McCall // The current scope is still active if we're the top-level class. 1007a1dc562d4ad59237ed9fe7e8cef56f9eaa7a26cJohn McCall // Otherwise we'll need to push and enter a new scope. 1016569d68745c8213709740337d2be52b031384f58Douglas Gregor bool HasClassScope = !Class.TopLevelClass; 1024cd8494d9a2f99cbf38147bca80be18cdff83734Sean Hunt ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope, 1034cd8494d9a2f99cbf38147bca80be18cdff83734Sean Hunt HasClassScope); 1047a1dc562d4ad59237ed9fe7e8cef56f9eaa7a26cJohn McCall if (HasClassScope) 10523c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor Actions.ActOnStartDelayedMemberDeclarations(getCurScope(), Class.TagOrTemplate); 1066569d68745c8213709740337d2be52b031384f58Douglas Gregor 1076569d68745c8213709740337d2be52b031384f58Douglas Gregor for (; !Class.MethodDecls.empty(); Class.MethodDecls.pop_front()) { 1086569d68745c8213709740337d2be52b031384f58Douglas Gregor LateParsedMethodDeclaration &LM = Class.MethodDecls.front(); 1091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 110d83d04041f64a2c89123d227fa8003b482391279Douglas Gregor // If this is a member template, introduce the template parameter scope. 111d83d04041f64a2c89123d227fa8003b482391279Douglas Gregor ParseScope TemplateScope(this, Scope::TemplateParamScope, LM.TemplateScope); 112d83d04041f64a2c89123d227fa8003b482391279Douglas Gregor if (LM.TemplateScope) 11323c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor Actions.ActOnReenterTemplateScope(getCurScope(), LM.Method); 1141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11572b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor // Start the delayed C++ method declaration 11623c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor Actions.ActOnStartDelayedCXXMethodDeclaration(getCurScope(), LM.Method); 11772b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor 11872b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor // Introduce the parameters into scope and parse their default 11972b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor // arguments. 1201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump ParseScope PrototypeScope(this, 1213218c4bb3b5d7250f12420de6db7ef3e3f805a75Douglas Gregor Scope::FunctionPrototypeScope|Scope::DeclScope); 12272b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor for (unsigned I = 0, N = LM.DefaultArgs.size(); I != N; ++I) { 12372b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor // Introduce the parameter into scope. 12423c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor Actions.ActOnDelayedCXXMethodParameter(getCurScope(), LM.DefaultArgs[I].Param); 12572b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor 12672b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor if (CachedTokens *Toks = LM.DefaultArgs[I].Toks) { 1277fd3a6456a88cdd225b92ae1606144f24c7f51d4Argyrios Kyrtzidis // Save the current token position. 1287fd3a6456a88cdd225b92ae1606144f24c7f51d4Argyrios Kyrtzidis SourceLocation origLoc = Tok.getLocation(); 1297fd3a6456a88cdd225b92ae1606144f24c7f51d4Argyrios Kyrtzidis 13072b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor // Parse the default argument from its saved token stream. 13172b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor Toks->push_back(Tok); // So that the current token doesn't get lost 13272b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor PP.EnterTokenStream(&Toks->front(), Toks->size(), true, false); 13372b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor 13472b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor // Consume the previously-pushed token. 13572b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor ConsumeAnyToken(); 13672b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor 13772b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor // Consume the '='. 13872b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor assert(Tok.is(tok::equal) && "Default argument not starting with '='"); 13972b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor SourceLocation EqualLoc = ConsumeToken(); 14072b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor 14172b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor OwningExprResult DefArgResult(ParseAssignmentExpression()); 14272b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor if (DefArgResult.isInvalid()) 14372b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor Actions.ActOnParamDefaultArgumentError(LM.DefaultArgs[I].Param); 1442b602adf9798eaf13850efaf8ed41c69d3cf7da6Argyrios Kyrtzidis else { 145f315fd6ebb9dbc47619315284c9af1ce5ec5f834Argyrios Kyrtzidis if (Tok.is(tok::cxx_defaultarg_end)) 146f315fd6ebb9dbc47619315284c9af1ce5ec5f834Argyrios Kyrtzidis ConsumeToken(); 147219cffcad343aef5939ca34d5abb59fbc7da1c36Argyrios Kyrtzidis else 148219cffcad343aef5939ca34d5abb59fbc7da1c36Argyrios Kyrtzidis Diag(Tok.getLocation(), diag::err_default_arg_unparsed); 14972b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor Actions.ActOnParamDefaultArgument(LM.DefaultArgs[I].Param, EqualLoc, 150f53597fb16142bdb4a66901f8c0b768db4f2a548Sebastian Redl move(DefArgResult)); 1512b602adf9798eaf13850efaf8ed41c69d3cf7da6Argyrios Kyrtzidis } 1527fd3a6456a88cdd225b92ae1606144f24c7f51d4Argyrios Kyrtzidis 1537fd3a6456a88cdd225b92ae1606144f24c7f51d4Argyrios Kyrtzidis assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc, 1547fd3a6456a88cdd225b92ae1606144f24c7f51d4Argyrios Kyrtzidis Tok.getLocation()) && 1557fd3a6456a88cdd225b92ae1606144f24c7f51d4Argyrios Kyrtzidis "ParseAssignmentExpression went over the default arg tokens!"); 1567fd3a6456a88cdd225b92ae1606144f24c7f51d4Argyrios Kyrtzidis // There could be leftover tokens (e.g. because of an error). 1577fd3a6456a88cdd225b92ae1606144f24c7f51d4Argyrios Kyrtzidis // Skip through until we reach the original token position. 1588f9359f5ae1227f3b489d1d261225d8180b64ed3Argyrios Kyrtzidis while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof)) 1597fd3a6456a88cdd225b92ae1606144f24c7f51d4Argyrios Kyrtzidis ConsumeAnyToken(); 1607fd3a6456a88cdd225b92ae1606144f24c7f51d4Argyrios Kyrtzidis 16172b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor delete Toks; 16272b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor LM.DefaultArgs[I].Toks = 0; 16372b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor } 16472b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor } 16572b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor PrototypeScope.Exit(); 16672b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor 16772b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor // Finish the delayed C++ method declaration. 16823c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor Actions.ActOnFinishDelayedCXXMethodDeclaration(getCurScope(), LM.Method); 16972b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor } 1706569d68745c8213709740337d2be52b031384f58Douglas Gregor 1716569d68745c8213709740337d2be52b031384f58Douglas Gregor for (unsigned I = 0, N = Class.NestedClasses.size(); I != N; ++I) 1726569d68745c8213709740337d2be52b031384f58Douglas Gregor ParseLexedMethodDeclarations(*Class.NestedClasses[I]); 1737a1dc562d4ad59237ed9fe7e8cef56f9eaa7a26cJohn McCall 1747a1dc562d4ad59237ed9fe7e8cef56f9eaa7a26cJohn McCall if (HasClassScope) 17523c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor Actions.ActOnFinishDelayedMemberDeclarations(getCurScope(), Class.TagOrTemplate); 17672b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor} 17772b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor 1784cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis/// ParseLexedMethodDefs - We finished parsing the member specification of a top 1794cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis/// (non-nested) C++ class. Now go over the stack of lexed methods that were 1804cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis/// collected during its parsing and parse them all. 1816569d68745c8213709740337d2be52b031384f58Douglas Gregorvoid Parser::ParseLexedMethodDefs(ParsingClass &Class) { 1826569d68745c8213709740337d2be52b031384f58Douglas Gregor bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope; 1836569d68745c8213709740337d2be52b031384f58Douglas Gregor ParseScope TemplateScope(this, Scope::TemplateParamScope, HasTemplateScope); 1846569d68745c8213709740337d2be52b031384f58Douglas Gregor if (HasTemplateScope) 18523c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate); 1866569d68745c8213709740337d2be52b031384f58Douglas Gregor 1876569d68745c8213709740337d2be52b031384f58Douglas Gregor bool HasClassScope = !Class.TopLevelClass; 1886569d68745c8213709740337d2be52b031384f58Douglas Gregor ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope, 1896569d68745c8213709740337d2be52b031384f58Douglas Gregor HasClassScope); 1906569d68745c8213709740337d2be52b031384f58Douglas Gregor 1916569d68745c8213709740337d2be52b031384f58Douglas Gregor for (; !Class.MethodDefs.empty(); Class.MethodDefs.pop_front()) { 1926569d68745c8213709740337d2be52b031384f58Douglas Gregor LexedMethod &LM = Class.MethodDefs.front(); 1934cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis 194d83d04041f64a2c89123d227fa8003b482391279Douglas Gregor // If this is a member template, introduce the template parameter scope. 195d83d04041f64a2c89123d227fa8003b482391279Douglas Gregor ParseScope TemplateScope(this, Scope::TemplateParamScope, LM.TemplateScope); 196d83d04041f64a2c89123d227fa8003b482391279Douglas Gregor if (LM.TemplateScope) 19723c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor Actions.ActOnReenterTemplateScope(getCurScope(), LM.D); 1981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 199c50a5e09c6c49577ecee7fb49ece97dc38ee1219Argyrios Kyrtzidis // Save the current token position. 200c50a5e09c6c49577ecee7fb49ece97dc38ee1219Argyrios Kyrtzidis SourceLocation origLoc = Tok.getLocation(); 201c50a5e09c6c49577ecee7fb49ece97dc38ee1219Argyrios Kyrtzidis 2024cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis assert(!LM.Toks.empty() && "Empty body!"); 2034cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis // Append the current token at the end of the new token stream so that it 2044cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis // doesn't get lost. 2054cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis LM.Toks.push_back(Tok); 206efd5bdad3c2b746db46452c6b13bd3c462dd761dDouglas Gregor PP.EnterTokenStream(LM.Toks.data(), LM.Toks.size(), true, false); 2074cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis 2084cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis // Consume the previously pushed token. 2094cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis ConsumeAnyToken(); 210d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) 211d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl && "Inline method not starting with '{', ':' or 'try'"); 2124cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis 2134cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis // Parse the method body. Function body parsing code is similar enough 2144cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis // to be re-used for method bodies as well. 2158935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope); 21623c94dbb6631fecdb55ba401aa93722803d980c6Douglas Gregor Actions.ActOnStartOfFunctionDef(getCurScope(), LM.D); 2174cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis 218d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl if (Tok.is(tok::kw_try)) { 219d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl ParseFunctionTryBlock(LM.D); 220c50a5e09c6c49577ecee7fb49ece97dc38ee1219Argyrios Kyrtzidis assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc, 221c50a5e09c6c49577ecee7fb49ece97dc38ee1219Argyrios Kyrtzidis Tok.getLocation()) && 222c50a5e09c6c49577ecee7fb49ece97dc38ee1219Argyrios Kyrtzidis "ParseFunctionTryBlock went over the cached tokens!"); 2237558cd00a5ac620990174f3cba86aea4bd9a000aArgyrios Kyrtzidis // There could be leftover tokens (e.g. because of an error). 2247558cd00a5ac620990174f3cba86aea4bd9a000aArgyrios Kyrtzidis // Skip through until we reach the original token position. 2258f9359f5ae1227f3b489d1d261225d8180b64ed3Argyrios Kyrtzidis while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof)) 2267558cd00a5ac620990174f3cba86aea4bd9a000aArgyrios Kyrtzidis ConsumeAnyToken(); 227de1b60a9868f80f0872ed05d78df3b40a10ba5caSebastian Redl continue; 228d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl } 229d6ca8da0f5a4115813055729faaa5128e994806dJohn McCall if (Tok.is(tok::colon)) { 2307ad8390f7992ab7f19b1460c5f0b9d96f165c4e9Douglas Gregor ParseConstructorInitializer(LM.D); 231d6ca8da0f5a4115813055729faaa5128e994806dJohn McCall 232d6ca8da0f5a4115813055729faaa5128e994806dJohn McCall // Error recovery. 233d6ca8da0f5a4115813055729faaa5128e994806dJohn McCall if (!Tok.is(tok::l_brace)) { 234d6ca8da0f5a4115813055729faaa5128e994806dJohn McCall Actions.ActOnFinishFunctionBody(LM.D, Action::StmtArg(Actions)); 235d6ca8da0f5a4115813055729faaa5128e994806dJohn McCall continue; 236d6ca8da0f5a4115813055729faaa5128e994806dJohn McCall } 237d6ca8da0f5a4115813055729faaa5128e994806dJohn McCall } else 238393612e6c7727f1fee50039254d9f434364cc0b2Fariborz Jahanian Actions.ActOnDefaultCtorInitializers(LM.D); 239d01c915dda27bb0045687f0a08bbcab1dd40e652Fariborz Jahanian 24040e9bc84a2ab49fc33c2b1a95c6674ab2b820e9eChris Lattner ParseFunctionStatementBody(LM.D); 241252485e6bf88064e8cce5b47da2481e6c795c21dTed Kremenek 2427558cd00a5ac620990174f3cba86aea4bd9a000aArgyrios Kyrtzidis if (Tok.getLocation() != origLoc) { 2437558cd00a5ac620990174f3cba86aea4bd9a000aArgyrios Kyrtzidis // Due to parsing error, we either went over the cached tokens or 2447558cd00a5ac620990174f3cba86aea4bd9a000aArgyrios Kyrtzidis // there are still cached tokens left. If it's the latter case skip the 2457558cd00a5ac620990174f3cba86aea4bd9a000aArgyrios Kyrtzidis // leftover tokens. 2467558cd00a5ac620990174f3cba86aea4bd9a000aArgyrios Kyrtzidis // Since this is an uncommon situation that should be avoided, use the 2477558cd00a5ac620990174f3cba86aea4bd9a000aArgyrios Kyrtzidis // expensive isBeforeInTranslationUnit call. 2487558cd00a5ac620990174f3cba86aea4bd9a000aArgyrios Kyrtzidis if (PP.getSourceManager().isBeforeInTranslationUnit(Tok.getLocation(), 2497558cd00a5ac620990174f3cba86aea4bd9a000aArgyrios Kyrtzidis origLoc)) 2508f9359f5ae1227f3b489d1d261225d8180b64ed3Argyrios Kyrtzidis while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof)) 2517558cd00a5ac620990174f3cba86aea4bd9a000aArgyrios Kyrtzidis ConsumeAnyToken(); 2527558cd00a5ac620990174f3cba86aea4bd9a000aArgyrios Kyrtzidis 2537558cd00a5ac620990174f3cba86aea4bd9a000aArgyrios Kyrtzidis } 2544cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis } 2556569d68745c8213709740337d2be52b031384f58Douglas Gregor 2566569d68745c8213709740337d2be52b031384f58Douglas Gregor for (unsigned I = 0, N = Class.NestedClasses.size(); I != N; ++I) 2576569d68745c8213709740337d2be52b031384f58Douglas Gregor ParseLexedMethodDefs(*Class.NestedClasses[I]); 2584cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis} 2594cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis 2604cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis/// ConsumeAndStoreUntil - Consume and store the token at the passed token 26172b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor/// container until the token 'T' is reached (which gets 2621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// consumed/stored too, if ConsumeFinalToken). 26314b91628961ab50cc6e724bbcd408fdee100662dArgyrios Kyrtzidis/// If StopAtSemi is true, then we will stop early at a ';' character. 26472b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor/// Returns true if token 'T1' or 'T2' was found. 2654cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis/// NOTE: This is a specialized version of Parser::SkipUntil. 26672b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregorbool Parser::ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2, 26772b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor CachedTokens &Toks, 26814b91628961ab50cc6e724bbcd408fdee100662dArgyrios Kyrtzidis bool StopAtSemi, bool ConsumeFinalToken) { 2694cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis // We always want this function to consume at least one token if the first 2704cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis // token isn't T and if not at EOF. 2714cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis bool isFirstTokenConsumed = true; 2724cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis while (1) { 2734cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis // If we found one of the tokens, stop and return true. 27472b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor if (Tok.is(T1) || Tok.is(T2)) { 27572b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor if (ConsumeFinalToken) { 27672b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor Toks.push_back(Tok); 27772b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor ConsumeAnyToken(); 27872b505b7904b3c9320a1312998800ba76e4f5841Douglas Gregor } 2794cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis return true; 2804cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis } 2814cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis 2824cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis switch (Tok.getKind()) { 2834cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis case tok::eof: 2844cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis // Ran out of tokens. 2854cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis return false; 2864cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis 2874cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis case tok::l_paren: 2884cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis // Recursively consume properly-nested parens. 2894cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis Toks.push_back(Tok); 2904cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis ConsumeParen(); 29114b91628961ab50cc6e724bbcd408fdee100662dArgyrios Kyrtzidis ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/false); 2924cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis break; 2934cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis case tok::l_square: 2944cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis // Recursively consume properly-nested square brackets. 2954cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis Toks.push_back(Tok); 2964cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis ConsumeBracket(); 29714b91628961ab50cc6e724bbcd408fdee100662dArgyrios Kyrtzidis ConsumeAndStoreUntil(tok::r_square, Toks, /*StopAtSemi=*/false); 2984cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis break; 2994cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis case tok::l_brace: 3004cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis // Recursively consume properly-nested braces. 3014cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis Toks.push_back(Tok); 3024cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis ConsumeBrace(); 30314b91628961ab50cc6e724bbcd408fdee100662dArgyrios Kyrtzidis ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false); 3044cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis break; 3054cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis 3064cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis // Okay, we found a ']' or '}' or ')', which we think should be balanced. 3074cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis // Since the user wasn't looking for this token (if they were, it would 3084cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis // already be handled), this isn't balanced. If there is a LHS token at a 3094cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis // higher level, we will assume that this matches the unbalanced token 3104cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis // and return it. Otherwise, this is a spurious RHS token, which we skip. 3114cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis case tok::r_paren: 3124cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis if (ParenCount && !isFirstTokenConsumed) 3134cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis return false; // Matches something. 3144cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis Toks.push_back(Tok); 3154cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis ConsumeParen(); 3164cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis break; 3174cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis case tok::r_square: 3184cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis if (BracketCount && !isFirstTokenConsumed) 3194cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis return false; // Matches something. 3204cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis Toks.push_back(Tok); 3214cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis ConsumeBracket(); 3224cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis break; 3234cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis case tok::r_brace: 3244cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis if (BraceCount && !isFirstTokenConsumed) 3254cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis return false; // Matches something. 3264cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis Toks.push_back(Tok); 3274cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis ConsumeBrace(); 3284cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis break; 3294cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis 3304cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis case tok::string_literal: 3314cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis case tok::wide_string_literal: 3324cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis Toks.push_back(Tok); 3334cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis ConsumeStringToken(); 3344cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis break; 33514b91628961ab50cc6e724bbcd408fdee100662dArgyrios Kyrtzidis case tok::semi: 33614b91628961ab50cc6e724bbcd408fdee100662dArgyrios Kyrtzidis if (StopAtSemi) 33714b91628961ab50cc6e724bbcd408fdee100662dArgyrios Kyrtzidis return false; 33814b91628961ab50cc6e724bbcd408fdee100662dArgyrios Kyrtzidis // FALL THROUGH. 3394cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis default: 3404cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis // consume this token. 3414cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis Toks.push_back(Tok); 3424cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis ConsumeToken(); 3434cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis break; 3444cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis } 3454cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis isFirstTokenConsumed = false; 3464cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis } 3474cc18a4d5222e04bd568b1e3e4d86127dbbcdf3fArgyrios Kyrtzidis} 348