blob: b593f8966818fa8d2584e9314dddf2a097681e97 [file] [log] [blame]
Argiris Kirtzidis9d784332008-06-24 22:12:16 +00001//===--- ParseCXXInlineMethods.cpp - C++ class inline methods parsing------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements parsing for C++ class inline methods.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Parse/Parser.h"
15#include "clang/Parse/DeclSpec.h"
16#include "clang/Parse/Scope.h"
17using namespace clang;
18
19/// ParseInlineCXXMethodDef - We parsed and verified that the specified
20/// Declarator is a well formed C++ inline method definition. Now lex its body
21/// and store its tokens for parsing after the C++ class is complete.
22Parser::DeclTy *
23Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D) {
24 assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function &&
25 "This isn't a function declarator!");
26
27 DeclTy *FnD = Actions.ActOnCXXMemberDeclarator(CurScope, AS, D, 0, 0, 0);
28
29 // We should have an opening brace now.
30 if (Tok.isNot(tok::l_brace)) {
31 Diag(Tok, diag::err_expected_fn_body);
32
33 // Skip over garbage, until we get to '{'. Don't eat the '{'.
34 SkipUntil(tok::l_brace, true, true);
35
36 // If we didn't find the '{', bail out.
37 if (Tok.isNot(tok::l_brace))
38 return FnD;
39 }
40
41 // Consume the tokens and store them for later parsing.
42
43 getCurTopClassStack().push(LexedMethod(FnD));
44 TokensTy &Toks = getCurTopClassStack().top().Toks;
45
46 // Begin by storing the '{' token.
47 Toks.push_back(Tok);
48 ConsumeBrace();
49 ConsumeAndStoreUntil(tok::r_brace, Toks);
50
51 return FnD;
52}
53
54/// ParseLexedMethodDefs - We finished parsing the member specification of a top
55/// (non-nested) C++ class. Now go over the stack of lexed methods that were
56/// collected during its parsing and parse them all.
57void Parser::ParseLexedMethodDefs() {
58 while (!getCurTopClassStack().empty()) {
59 LexedMethod &LM = getCurTopClassStack().top();
60
61 assert(!LM.Toks.empty() && "Empty body!");
62 // Append the current token at the end of the new token stream so that it
63 // doesn't get lost.
64 LM.Toks.push_back(Tok);
65 PP.EnterTokenStream(&LM.Toks.front(), LM.Toks.size(), true, false);
66
67 // Consume the previously pushed token.
68 ConsumeAnyToken();
69 assert(Tok.is(tok::l_brace) && "Inline method not starting with '{'");
70
71 // Parse the method body. Function body parsing code is similar enough
72 // to be re-used for method bodies as well.
73 EnterScope(Scope::FnScope|Scope::DeclScope);
74 Actions.ActOnStartOfFunctionDef(CurScope, LM.D);
75
76 ParseFunctionStatementBody(LM.D, Tok.getLocation(), Tok.getLocation());
77
78 getCurTopClassStack().pop();
79 }
80}
81
82/// ConsumeAndStoreUntil - Consume and store the token at the passed token
83/// container until the token 'T' is reached (which gets consumed/stored too).
84/// Returns true if token 'T' was found.
85/// NOTE: This is a specialized version of Parser::SkipUntil.
86bool Parser::ConsumeAndStoreUntil(tok::TokenKind T, TokensTy &Toks) {
87 // We always want this function to consume at least one token if the first
88 // token isn't T and if not at EOF.
89 bool isFirstTokenConsumed = true;
90 while (1) {
91 // If we found one of the tokens, stop and return true.
92 if (Tok.is(T)) {
93 Toks.push_back(Tok);
94 ConsumeAnyToken();
95 return true;
96 }
97
98 switch (Tok.getKind()) {
99 case tok::eof:
100 // Ran out of tokens.
101 return false;
102
103 case tok::l_paren:
104 // Recursively consume properly-nested parens.
105 Toks.push_back(Tok);
106 ConsumeParen();
107 ConsumeAndStoreUntil(tok::r_paren, Toks);
108 break;
109 case tok::l_square:
110 // Recursively consume properly-nested square brackets.
111 Toks.push_back(Tok);
112 ConsumeBracket();
113 ConsumeAndStoreUntil(tok::r_square, Toks);
114 break;
115 case tok::l_brace:
116 // Recursively consume properly-nested braces.
117 Toks.push_back(Tok);
118 ConsumeBrace();
119 ConsumeAndStoreUntil(tok::r_brace, Toks);
120 break;
121
122 // Okay, we found a ']' or '}' or ')', which we think should be balanced.
123 // Since the user wasn't looking for this token (if they were, it would
124 // already be handled), this isn't balanced. If there is a LHS token at a
125 // higher level, we will assume that this matches the unbalanced token
126 // and return it. Otherwise, this is a spurious RHS token, which we skip.
127 case tok::r_paren:
128 if (ParenCount && !isFirstTokenConsumed)
129 return false; // Matches something.
130 Toks.push_back(Tok);
131 ConsumeParen();
132 break;
133 case tok::r_square:
134 if (BracketCount && !isFirstTokenConsumed)
135 return false; // Matches something.
136 Toks.push_back(Tok);
137 ConsumeBracket();
138 break;
139 case tok::r_brace:
140 if (BraceCount && !isFirstTokenConsumed)
141 return false; // Matches something.
142 Toks.push_back(Tok);
143 ConsumeBrace();
144 break;
145
146 case tok::string_literal:
147 case tok::wide_string_literal:
148 Toks.push_back(Tok);
149 ConsumeStringToken();
150 break;
151 default:
152 // consume this token.
153 Toks.push_back(Tok);
154 ConsumeToken();
155 break;
156 }
157 isFirstTokenConsumed = false;
158 }
159}