1 //===--- ParseCXXInlineMethods.cpp - C++ class inline methods parsing------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements parsing for C++ class inline methods.
12 //===----------------------------------------------------------------------===//
14 #include "clang/Parse/ParseDiagnostic.h"
15 #include "clang/Parse/Parser.h"
16 #include "clang/Sema/DeclSpec.h"
17 #include "clang/Sema/Scope.h"
18 using namespace clang
;
20 /// ParseCXXInlineMethodDef - We parsed and verified that the specified
21 /// Declarator is a well formed C++ inline method definition. Now lex its body
22 /// and store its tokens for parsing after the C++ class is complete.
23 Decl
*Parser::ParseCXXInlineMethodDef(AccessSpecifier AS
, Declarator
&D
,
24 const ParsedTemplateInfo
&TemplateInfo
) {
25 assert(D
.getTypeObject(0).Kind
== DeclaratorChunk::Function
&&
26 "This isn't a function declarator!");
27 assert((Tok
.is(tok::l_brace
) || Tok
.is(tok::colon
) || Tok
.is(tok::kw_try
)) &&
28 "Current token not a '{', ':' or 'try'!");
30 MultiTemplateParamsArg
TemplateParams(Actions
,
31 TemplateInfo
.TemplateParams
? TemplateInfo
.TemplateParams
->data() : 0,
32 TemplateInfo
.TemplateParams
? TemplateInfo
.TemplateParams
->size() : 0);
35 if (D
.getDeclSpec().isFriendSpecified())
36 // FIXME: Friend templates
37 FnD
= Actions
.ActOnFriendFunctionDecl(getCurScope(), D
, true,
38 move(TemplateParams
));
39 else // FIXME: pass template information through
40 FnD
= Actions
.ActOnCXXMemberDeclarator(getCurScope(), AS
, D
,
41 move(TemplateParams
), 0, 0,
42 /*IsDefinition*/true);
44 HandleMemberFunctionDefaultArgs(D
, FnD
);
46 // Consume the tokens and store them for later parsing.
48 getCurrentClass().MethodDefs
.push_back(LexedMethod(FnD
));
49 getCurrentClass().MethodDefs
.back().TemplateScope
50 = getCurScope()->isTemplateParamScope();
51 CachedTokens
&Toks
= getCurrentClass().MethodDefs
.back().Toks
;
53 tok::TokenKind kind
= Tok
.getKind();
54 // We may have a constructor initializer or function-try-block here.
55 if (kind
== tok::colon
|| kind
== tok::kw_try
) {
56 // Consume everything up to (and including) the left brace.
57 if (!ConsumeAndStoreUntil(tok::l_brace
, Toks
)) {
58 // We didn't find the left-brace we expected after the
59 // constructor initializer.
60 if (Tok
.is(tok::semi
)) {
61 // We found a semicolon; complain, consume the semicolon, and
62 // don't try to parse this method later.
63 Diag(Tok
.getLocation(), diag::err_expected_lbrace
);
65 getCurrentClass().MethodDefs
.pop_back();
71 // Begin by storing the '{' token.
75 // Consume everything up to (and including) the matching right brace.
76 ConsumeAndStoreUntil(tok::r_brace
, Toks
, /*StopAtSemi=*/false);
78 // If we're in a function-try-block, we need to store all the catch blocks.
79 if (kind
== tok::kw_try
) {
80 while (Tok
.is(tok::kw_catch
)) {
81 ConsumeAndStoreUntil(tok::l_brace
, Toks
, /*StopAtSemi=*/false);
82 ConsumeAndStoreUntil(tok::r_brace
, Toks
, /*StopAtSemi=*/false);
89 /// ParseLexedMethodDeclarations - We finished parsing the member
90 /// specification of a top (non-nested) C++ class. Now go over the
91 /// stack of method declarations with some parts for which parsing was
92 /// delayed (such as default arguments) and parse them.
93 void Parser::ParseLexedMethodDeclarations(ParsingClass
&Class
) {
94 bool HasTemplateScope
= !Class
.TopLevelClass
&& Class
.TemplateScope
;
95 ParseScope
TemplateScope(this, Scope::TemplateParamScope
, HasTemplateScope
);
97 Actions
.ActOnReenterTemplateScope(getCurScope(), Class
.TagOrTemplate
);
99 // The current scope is still active if we're the top-level class.
100 // Otherwise we'll need to push and enter a new scope.
101 bool HasClassScope
= !Class
.TopLevelClass
;
102 ParseScope
ClassScope(this, Scope::ClassScope
|Scope::DeclScope
,
105 Actions
.ActOnStartDelayedMemberDeclarations(getCurScope(), Class
.TagOrTemplate
);
107 for (; !Class
.MethodDecls
.empty(); Class
.MethodDecls
.pop_front()) {
108 LateParsedMethodDeclaration
&LM
= Class
.MethodDecls
.front();
110 // If this is a member template, introduce the template parameter scope.
111 ParseScope
TemplateScope(this, Scope::TemplateParamScope
, LM
.TemplateScope
);
112 if (LM
.TemplateScope
)
113 Actions
.ActOnReenterTemplateScope(getCurScope(), LM
.Method
);
115 // Start the delayed C++ method declaration
116 Actions
.ActOnStartDelayedCXXMethodDeclaration(getCurScope(), LM
.Method
);
118 // Introduce the parameters into scope and parse their default
120 ParseScope
PrototypeScope(this,
121 Scope::FunctionPrototypeScope
|Scope::DeclScope
);
122 for (unsigned I
= 0, N
= LM
.DefaultArgs
.size(); I
!= N
; ++I
) {
123 // Introduce the parameter into scope.
124 Actions
.ActOnDelayedCXXMethodParameter(getCurScope(), LM
.DefaultArgs
[I
].Param
);
126 if (CachedTokens
*Toks
= LM
.DefaultArgs
[I
].Toks
) {
127 // Save the current token position.
128 SourceLocation origLoc
= Tok
.getLocation();
130 // Parse the default argument from its saved token stream.
131 Toks
->push_back(Tok
); // So that the current token doesn't get lost
132 PP
.EnterTokenStream(&Toks
->front(), Toks
->size(), true, false);
134 // Consume the previously-pushed token.
138 assert(Tok
.is(tok::equal
) && "Default argument not starting with '='");
139 SourceLocation EqualLoc
= ConsumeToken();
141 // The argument isn't actually potentially evaluated unless it is
143 EnterExpressionEvaluationContext
Eval(Actions
,
144 Sema::PotentiallyEvaluatedIfUsed
);
146 ExprResult
DefArgResult(ParseAssignmentExpression());
147 if (DefArgResult
.isInvalid())
148 Actions
.ActOnParamDefaultArgumentError(LM
.DefaultArgs
[I
].Param
);
150 if (Tok
.is(tok::cxx_defaultarg_end
))
153 Diag(Tok
.getLocation(), diag::err_default_arg_unparsed
);
154 Actions
.ActOnParamDefaultArgument(LM
.DefaultArgs
[I
].Param
, EqualLoc
,
155 DefArgResult
.take());
158 assert(!PP
.getSourceManager().isBeforeInTranslationUnit(origLoc
,
159 Tok
.getLocation()) &&
160 "ParseAssignmentExpression went over the default arg tokens!");
161 // There could be leftover tokens (e.g. because of an error).
162 // Skip through until we reach the original token position.
163 while (Tok
.getLocation() != origLoc
&& Tok
.isNot(tok::eof
))
167 LM
.DefaultArgs
[I
].Toks
= 0;
170 PrototypeScope
.Exit();
172 // Finish the delayed C++ method declaration.
173 Actions
.ActOnFinishDelayedCXXMethodDeclaration(getCurScope(), LM
.Method
);
176 for (unsigned I
= 0, N
= Class
.NestedClasses
.size(); I
!= N
; ++I
)
177 ParseLexedMethodDeclarations(*Class
.NestedClasses
[I
]);
180 Actions
.ActOnFinishDelayedMemberDeclarations(getCurScope(), Class
.TagOrTemplate
);
183 /// ParseLexedMethodDefs - We finished parsing the member specification of a top
184 /// (non-nested) C++ class. Now go over the stack of lexed methods that were
185 /// collected during its parsing and parse them all.
186 void Parser::ParseLexedMethodDefs(ParsingClass
&Class
) {
187 bool HasTemplateScope
= !Class
.TopLevelClass
&& Class
.TemplateScope
;
188 ParseScope
TemplateScope(this, Scope::TemplateParamScope
, HasTemplateScope
);
189 if (HasTemplateScope
)
190 Actions
.ActOnReenterTemplateScope(getCurScope(), Class
.TagOrTemplate
);
192 bool HasClassScope
= !Class
.TopLevelClass
;
193 ParseScope
ClassScope(this, Scope::ClassScope
|Scope::DeclScope
,
196 for (; !Class
.MethodDefs
.empty(); Class
.MethodDefs
.pop_front()) {
197 LexedMethod
&LM
= Class
.MethodDefs
.front();
199 // If this is a member template, introduce the template parameter scope.
200 ParseScope
TemplateScope(this, Scope::TemplateParamScope
, LM
.TemplateScope
);
201 if (LM
.TemplateScope
)
202 Actions
.ActOnReenterTemplateScope(getCurScope(), LM
.D
);
204 // Save the current token position.
205 SourceLocation origLoc
= Tok
.getLocation();
207 assert(!LM
.Toks
.empty() && "Empty body!");
208 // Append the current token at the end of the new token stream so that it
210 LM
.Toks
.push_back(Tok
);
211 PP
.EnterTokenStream(LM
.Toks
.data(), LM
.Toks
.size(), true, false);
213 // Consume the previously pushed token.
215 assert((Tok
.is(tok::l_brace
) || Tok
.is(tok::colon
) || Tok
.is(tok::kw_try
))
216 && "Inline method not starting with '{', ':' or 'try'");
218 // Parse the method body. Function body parsing code is similar enough
219 // to be re-used for method bodies as well.
220 ParseScope
FnScope(this, Scope::FnScope
|Scope::DeclScope
);
221 Actions
.ActOnStartOfFunctionDef(getCurScope(), LM
.D
);
223 if (Tok
.is(tok::kw_try
)) {
224 ParseFunctionTryBlock(LM
.D
);
225 assert(!PP
.getSourceManager().isBeforeInTranslationUnit(origLoc
,
226 Tok
.getLocation()) &&
227 "ParseFunctionTryBlock went over the cached tokens!");
228 // There could be leftover tokens (e.g. because of an error).
229 // Skip through until we reach the original token position.
230 while (Tok
.getLocation() != origLoc
&& Tok
.isNot(tok::eof
))
234 if (Tok
.is(tok::colon
)) {
235 ParseConstructorInitializer(LM
.D
);
238 if (!Tok
.is(tok::l_brace
)) {
239 Actions
.ActOnFinishFunctionBody(LM
.D
, 0);
243 Actions
.ActOnDefaultCtorInitializers(LM
.D
);
245 ParseFunctionStatementBody(LM
.D
);
247 if (Tok
.getLocation() != origLoc
) {
248 // Due to parsing error, we either went over the cached tokens or
249 // there are still cached tokens left. If it's the latter case skip the
251 // Since this is an uncommon situation that should be avoided, use the
252 // expensive isBeforeInTranslationUnit call.
253 if (PP
.getSourceManager().isBeforeInTranslationUnit(Tok
.getLocation(),
255 while (Tok
.getLocation() != origLoc
&& Tok
.isNot(tok::eof
))
261 for (unsigned I
= 0, N
= Class
.NestedClasses
.size(); I
!= N
; ++I
)
262 ParseLexedMethodDefs(*Class
.NestedClasses
[I
]);
265 /// ConsumeAndStoreUntil - Consume and store the token at the passed token
266 /// container until the token 'T' is reached (which gets
267 /// consumed/stored too, if ConsumeFinalToken).
268 /// If StopAtSemi is true, then we will stop early at a ';' character.
269 /// Returns true if token 'T1' or 'T2' was found.
270 /// NOTE: This is a specialized version of Parser::SkipUntil.
271 bool Parser::ConsumeAndStoreUntil(tok::TokenKind T1
, tok::TokenKind T2
,
273 bool StopAtSemi
, bool ConsumeFinalToken
) {
274 // We always want this function to consume at least one token if the first
275 // token isn't T and if not at EOF.
276 bool isFirstTokenConsumed
= true;
278 // If we found one of the tokens, stop and return true.
279 if (Tok
.is(T1
) || Tok
.is(T2
)) {
280 if (ConsumeFinalToken
) {
287 switch (Tok
.getKind()) {
289 // Ran out of tokens.
293 // Recursively consume properly-nested parens.
296 ConsumeAndStoreUntil(tok::r_paren
, Toks
, /*StopAtSemi=*/false);
299 // Recursively consume properly-nested square brackets.
302 ConsumeAndStoreUntil(tok::r_square
, Toks
, /*StopAtSemi=*/false);
305 // Recursively consume properly-nested braces.
308 ConsumeAndStoreUntil(tok::r_brace
, Toks
, /*StopAtSemi=*/false);
311 // Okay, we found a ']' or '}' or ')', which we think should be balanced.
312 // Since the user wasn't looking for this token (if they were, it would
313 // already be handled), this isn't balanced. If there is a LHS token at a
314 // higher level, we will assume that this matches the unbalanced token
315 // and return it. Otherwise, this is a spurious RHS token, which we skip.
317 if (ParenCount
&& !isFirstTokenConsumed
)
318 return false; // Matches something.
323 if (BracketCount
&& !isFirstTokenConsumed
)
324 return false; // Matches something.
329 if (BraceCount
&& !isFirstTokenConsumed
)
330 return false; // Matches something.
335 case tok::string_literal
:
336 case tok::wide_string_literal
:
338 ConsumeStringToken();
345 // consume this token.
350 isFirstTokenConsumed
= false;