ParseCXXInlineMethods.cpp revision 198092
1193326Sed//===--- ParseCXXInlineMethods.cpp - C++ class inline methods parsing------===//
2193326Sed//
3193326Sed//                     The LLVM Compiler Infrastructure
4193326Sed//
5193326Sed// This file is distributed under the University of Illinois Open Source
6193326Sed// License. See LICENSE.TXT for details.
7193326Sed//
8193326Sed//===----------------------------------------------------------------------===//
9193326Sed//
10193326Sed//  This file implements parsing for C++ class inline methods.
11193326Sed//
12193326Sed//===----------------------------------------------------------------------===//
13193326Sed
14193326Sed#include "clang/Parse/ParseDiagnostic.h"
15193326Sed#include "clang/Parse/Parser.h"
16193326Sed#include "clang/Parse/DeclSpec.h"
17193326Sed#include "clang/Parse/Scope.h"
18193326Sedusing namespace clang;
19193326Sed
20193326Sed/// ParseCXXInlineMethodDef - We parsed and verified that the specified
21193326Sed/// Declarator is a well formed C++ inline method definition. Now lex its body
22193326Sed/// and store its tokens for parsing after the C++ class is complete.
23193326SedParser::DeclPtrTy
24198092SrdivackyParser::ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D,
25198092Srdivacky                                const ParsedTemplateInfo &TemplateInfo) {
26193326Sed  assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function &&
27193326Sed         "This isn't a function declarator!");
28193326Sed  assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) &&
29193326Sed         "Current token not a '{', ':' or 'try'!");
30193326Sed
31198092Srdivacky  Action::MultiTemplateParamsArg TemplateParams(Actions,
32198092Srdivacky                                                TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->data() : 0,
33198092Srdivacky                                                TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->size() : 0);
34198092Srdivacky  DeclPtrTy FnD;
35198092Srdivacky  if (D.getDeclSpec().isFriendSpecified())
36198092Srdivacky    // FIXME: Friend templates
37198092Srdivacky    FnD = Actions.ActOnFriendFunctionDecl(CurScope, D, true, move(TemplateParams));
38198092Srdivacky  else // FIXME: pass template information through
39198092Srdivacky    FnD = Actions.ActOnCXXMemberDeclarator(CurScope, AS, D,
40198092Srdivacky                                           move(TemplateParams), 0, 0);
41193326Sed
42198092Srdivacky  HandleMemberFunctionDefaultArgs(D, FnD);
43198092Srdivacky
44193326Sed  // Consume the tokens and store them for later parsing.
45193326Sed
46193326Sed  getCurrentClass().MethodDefs.push_back(LexedMethod(FnD));
47198092Srdivacky  getCurrentClass().MethodDefs.back().TemplateScope
48198092Srdivacky    = CurScope->isTemplateParamScope();
49193326Sed  CachedTokens &Toks = getCurrentClass().MethodDefs.back().Toks;
50193326Sed
51193326Sed  tok::TokenKind kind = Tok.getKind();
52193326Sed  // We may have a constructor initializer or function-try-block here.
53193326Sed  if (kind == tok::colon || kind == tok::kw_try) {
54193326Sed    // Consume everything up to (and including) the left brace.
55193326Sed    if (!ConsumeAndStoreUntil(tok::l_brace, tok::unknown, Toks, tok::semi)) {
56193326Sed      // We didn't find the left-brace we expected after the
57198092Srdivacky      // constructor initializer.
58193326Sed      if (Tok.is(tok::semi)) {
59193326Sed        // We found a semicolon; complain, consume the semicolon, and
60193326Sed        // don't try to parse this method later.
61193326Sed        Diag(Tok.getLocation(), diag::err_expected_lbrace);
62193326Sed        ConsumeAnyToken();
63193326Sed        getCurrentClass().MethodDefs.pop_back();
64193326Sed        return FnD;
65193326Sed      }
66193326Sed    }
67193326Sed
68193326Sed  } else {
69198092Srdivacky    // Begin by storing the '{' token.
70193326Sed    Toks.push_back(Tok);
71193326Sed    ConsumeBrace();
72193326Sed  }
73193326Sed  // Consume everything up to (and including) the matching right brace.
74193326Sed  ConsumeAndStoreUntil(tok::r_brace, tok::unknown, Toks);
75193326Sed
76193326Sed  // If we're in a function-try-block, we need to store all the catch blocks.
77193326Sed  if (kind == tok::kw_try) {
78193326Sed    while (Tok.is(tok::kw_catch)) {
79193326Sed      ConsumeAndStoreUntil(tok::l_brace, tok::unknown, Toks);
80193326Sed      ConsumeAndStoreUntil(tok::r_brace, tok::unknown, Toks);
81193326Sed    }
82193326Sed  }
83193326Sed
84193326Sed  return FnD;
85193326Sed}
86193326Sed
87193326Sed/// ParseLexedMethodDeclarations - We finished parsing the member
88193326Sed/// specification of a top (non-nested) C++ class. Now go over the
89193326Sed/// stack of method declarations with some parts for which parsing was
90193326Sed/// delayed (such as default arguments) and parse them.
91193326Sedvoid Parser::ParseLexedMethodDeclarations(ParsingClass &Class) {
92193326Sed  bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope;
93193326Sed  ParseScope TemplateScope(this, Scope::TemplateParamScope, HasTemplateScope);
94193326Sed  if (HasTemplateScope)
95193326Sed    Actions.ActOnReenterTemplateScope(CurScope, Class.TagOrTemplate);
96193326Sed
97193326Sed  bool HasClassScope = !Class.TopLevelClass;
98193326Sed  ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope,
99193326Sed                        HasClassScope);
100193326Sed
101193326Sed  for (; !Class.MethodDecls.empty(); Class.MethodDecls.pop_front()) {
102193326Sed    LateParsedMethodDeclaration &LM = Class.MethodDecls.front();
103193326Sed
104198092Srdivacky    // If this is a member template, introduce the template parameter scope.
105198092Srdivacky    ParseScope TemplateScope(this, Scope::TemplateParamScope, LM.TemplateScope);
106198092Srdivacky    if (LM.TemplateScope)
107198092Srdivacky      Actions.ActOnReenterTemplateScope(CurScope, LM.Method);
108198092Srdivacky
109193326Sed    // Start the delayed C++ method declaration
110193326Sed    Actions.ActOnStartDelayedCXXMethodDeclaration(CurScope, LM.Method);
111193326Sed
112193326Sed    // Introduce the parameters into scope and parse their default
113193326Sed    // arguments.
114198092Srdivacky    ParseScope PrototypeScope(this,
115193326Sed                              Scope::FunctionPrototypeScope|Scope::DeclScope);
116193326Sed    for (unsigned I = 0, N = LM.DefaultArgs.size(); I != N; ++I) {
117193326Sed      // Introduce the parameter into scope.
118193326Sed      Actions.ActOnDelayedCXXMethodParameter(CurScope, LM.DefaultArgs[I].Param);
119193326Sed
120193326Sed      if (CachedTokens *Toks = LM.DefaultArgs[I].Toks) {
121193326Sed        // Parse the default argument from its saved token stream.
122193326Sed        Toks->push_back(Tok); // So that the current token doesn't get lost
123193326Sed        PP.EnterTokenStream(&Toks->front(), Toks->size(), true, false);
124193326Sed
125193326Sed        // Consume the previously-pushed token.
126193326Sed        ConsumeAnyToken();
127193326Sed
128193326Sed        // Consume the '='.
129193326Sed        assert(Tok.is(tok::equal) && "Default argument not starting with '='");
130193326Sed        SourceLocation EqualLoc = ConsumeToken();
131193326Sed
132193326Sed        OwningExprResult DefArgResult(ParseAssignmentExpression());
133193326Sed        if (DefArgResult.isInvalid())
134193326Sed          Actions.ActOnParamDefaultArgumentError(LM.DefaultArgs[I].Param);
135193326Sed        else
136193326Sed          Actions.ActOnParamDefaultArgument(LM.DefaultArgs[I].Param, EqualLoc,
137193326Sed                                            move(DefArgResult));
138193326Sed        delete Toks;
139193326Sed        LM.DefaultArgs[I].Toks = 0;
140193326Sed      }
141193326Sed    }
142193326Sed    PrototypeScope.Exit();
143193326Sed
144193326Sed    // Finish the delayed C++ method declaration.
145193326Sed    Actions.ActOnFinishDelayedCXXMethodDeclaration(CurScope, LM.Method);
146193326Sed  }
147193326Sed
148193326Sed  for (unsigned I = 0, N = Class.NestedClasses.size(); I != N; ++I)
149193326Sed    ParseLexedMethodDeclarations(*Class.NestedClasses[I]);
150193326Sed}
151193326Sed
152193326Sed/// ParseLexedMethodDefs - We finished parsing the member specification of a top
153193326Sed/// (non-nested) C++ class. Now go over the stack of lexed methods that were
154193326Sed/// collected during its parsing and parse them all.
155193326Sedvoid Parser::ParseLexedMethodDefs(ParsingClass &Class) {
156193326Sed  bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope;
157193326Sed  ParseScope TemplateScope(this, Scope::TemplateParamScope, HasTemplateScope);
158193326Sed  if (HasTemplateScope)
159193326Sed    Actions.ActOnReenterTemplateScope(CurScope, Class.TagOrTemplate);
160193326Sed
161193326Sed  bool HasClassScope = !Class.TopLevelClass;
162193326Sed  ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope,
163193326Sed                        HasClassScope);
164193326Sed
165193326Sed  for (; !Class.MethodDefs.empty(); Class.MethodDefs.pop_front()) {
166193326Sed    LexedMethod &LM = Class.MethodDefs.front();
167193326Sed
168198092Srdivacky    // If this is a member template, introduce the template parameter scope.
169198092Srdivacky    ParseScope TemplateScope(this, Scope::TemplateParamScope, LM.TemplateScope);
170198092Srdivacky    if (LM.TemplateScope)
171198092Srdivacky      Actions.ActOnReenterTemplateScope(CurScope, LM.D);
172198092Srdivacky
173193326Sed    assert(!LM.Toks.empty() && "Empty body!");
174193326Sed    // Append the current token at the end of the new token stream so that it
175193326Sed    // doesn't get lost.
176193326Sed    LM.Toks.push_back(Tok);
177198092Srdivacky    PP.EnterTokenStream(LM.Toks.data(), LM.Toks.size(), true, false);
178193326Sed
179193326Sed    // Consume the previously pushed token.
180193326Sed    ConsumeAnyToken();
181193326Sed    assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try))
182193326Sed           && "Inline method not starting with '{', ':' or 'try'");
183193326Sed
184193326Sed    // Parse the method body. Function body parsing code is similar enough
185193326Sed    // to be re-used for method bodies as well.
186193326Sed    ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope);
187193326Sed    Actions.ActOnStartOfFunctionDef(CurScope, LM.D);
188193326Sed
189193326Sed    if (Tok.is(tok::kw_try)) {
190193326Sed      ParseFunctionTryBlock(LM.D);
191193326Sed      continue;
192193326Sed    }
193193326Sed    if (Tok.is(tok::colon))
194193326Sed      ParseConstructorInitializer(LM.D);
195198092Srdivacky    else
196198092Srdivacky      Actions.ActOnDefaultCtorInitializers(LM.D);
197198092Srdivacky
198193326Sed    // FIXME: What if ParseConstructorInitializer doesn't leave us with a '{'??
199193326Sed    ParseFunctionStatementBody(LM.D);
200193326Sed  }
201193326Sed
202193326Sed  for (unsigned I = 0, N = Class.NestedClasses.size(); I != N; ++I)
203193326Sed    ParseLexedMethodDefs(*Class.NestedClasses[I]);
204193326Sed}
205193326Sed
206193326Sed/// ConsumeAndStoreUntil - Consume and store the token at the passed token
207193326Sed/// container until the token 'T' is reached (which gets
208198092Srdivacky/// consumed/stored too, if ConsumeFinalToken).
209193326Sed/// If EarlyAbortIf is specified, then we will stop early if we find that
210193326Sed/// token at the top level.
211193326Sed/// Returns true if token 'T1' or 'T2' was found.
212193326Sed/// NOTE: This is a specialized version of Parser::SkipUntil.
213193326Sedbool Parser::ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2,
214193326Sed                                  CachedTokens &Toks,
215193326Sed                                  tok::TokenKind EarlyAbortIf,
216193326Sed                                  bool ConsumeFinalToken) {
217193326Sed  // We always want this function to consume at least one token if the first
218193326Sed  // token isn't T and if not at EOF.
219193326Sed  bool isFirstTokenConsumed = true;
220193326Sed  while (1) {
221193326Sed    // If we found one of the tokens, stop and return true.
222193326Sed    if (Tok.is(T1) || Tok.is(T2)) {
223193326Sed      if (ConsumeFinalToken) {
224193326Sed        Toks.push_back(Tok);
225193326Sed        ConsumeAnyToken();
226193326Sed      }
227193326Sed      return true;
228193326Sed    }
229193326Sed
230193326Sed    // If we found the early-abort token, return.
231193326Sed    if (Tok.is(EarlyAbortIf))
232193326Sed      return false;
233193326Sed
234193326Sed    switch (Tok.getKind()) {
235193326Sed    case tok::eof:
236193326Sed      // Ran out of tokens.
237193326Sed      return false;
238193326Sed
239193326Sed    case tok::l_paren:
240193326Sed      // Recursively consume properly-nested parens.
241193326Sed      Toks.push_back(Tok);
242193326Sed      ConsumeParen();
243193326Sed      ConsumeAndStoreUntil(tok::r_paren, tok::unknown, Toks);
244193326Sed      break;
245193326Sed    case tok::l_square:
246193326Sed      // Recursively consume properly-nested square brackets.
247193326Sed      Toks.push_back(Tok);
248193326Sed      ConsumeBracket();
249193326Sed      ConsumeAndStoreUntil(tok::r_square, tok::unknown, Toks);
250193326Sed      break;
251193326Sed    case tok::l_brace:
252193326Sed      // Recursively consume properly-nested braces.
253193326Sed      Toks.push_back(Tok);
254193326Sed      ConsumeBrace();
255193326Sed      ConsumeAndStoreUntil(tok::r_brace, tok::unknown, Toks);
256193326Sed      break;
257193326Sed
258193326Sed    // Okay, we found a ']' or '}' or ')', which we think should be balanced.
259193326Sed    // Since the user wasn't looking for this token (if they were, it would
260193326Sed    // already be handled), this isn't balanced.  If there is a LHS token at a
261193326Sed    // higher level, we will assume that this matches the unbalanced token
262193326Sed    // and return it.  Otherwise, this is a spurious RHS token, which we skip.
263193326Sed    case tok::r_paren:
264193326Sed      if (ParenCount && !isFirstTokenConsumed)
265193326Sed        return false;  // Matches something.
266193326Sed      Toks.push_back(Tok);
267193326Sed      ConsumeParen();
268193326Sed      break;
269193326Sed    case tok::r_square:
270193326Sed      if (BracketCount && !isFirstTokenConsumed)
271193326Sed        return false;  // Matches something.
272193326Sed      Toks.push_back(Tok);
273193326Sed      ConsumeBracket();
274193326Sed      break;
275193326Sed    case tok::r_brace:
276193326Sed      if (BraceCount && !isFirstTokenConsumed)
277193326Sed        return false;  // Matches something.
278193326Sed      Toks.push_back(Tok);
279193326Sed      ConsumeBrace();
280193326Sed      break;
281193326Sed
282193326Sed    case tok::string_literal:
283193326Sed    case tok::wide_string_literal:
284193326Sed      Toks.push_back(Tok);
285193326Sed      ConsumeStringToken();
286193326Sed      break;
287193326Sed    default:
288193326Sed      // consume this token.
289193326Sed      Toks.push_back(Tok);
290193326Sed      ConsumeToken();
291193326Sed      break;
292193326Sed    }
293193326Sed    isFirstTokenConsumed = false;
294193326Sed  }
295193326Sed}
296