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/Parse/DeclSpec.h"
17 #include "clang/Parse/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.
24 Parser::ParseCXXInlineMethodDef(AccessSpecifier AS
, Declarator
&D
) {
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 DeclPtrTy FnD
= Actions
.ActOnCXXMemberDeclarator(CurScope
, AS
, D
, 0, 0);
32 // Consume the tokens and store them for later parsing.
34 getCurrentClass().MethodDefs
.push_back(LexedMethod(FnD
));
35 CachedTokens
&Toks
= getCurrentClass().MethodDefs
.back().Toks
;
37 tok::TokenKind kind
= Tok
.getKind();
38 // We may have a constructor initializer or function-try-block here.
39 if (kind
== tok::colon
|| kind
== tok::kw_try
) {
40 // Consume everything up to (and including) the left brace.
41 if (!ConsumeAndStoreUntil(tok::l_brace
, tok::unknown
, Toks
, tok::semi
)) {
42 // We didn't find the left-brace we expected after the
43 // constructor initializer.
44 if (Tok
.is(tok::semi
)) {
45 // We found a semicolon; complain, consume the semicolon, and
46 // don't try to parse this method later.
47 Diag(Tok
.getLocation(), diag::err_expected_lbrace
);
49 getCurrentClass().MethodDefs
.pop_back();
55 // Begin by storing the '{' token.
59 // Consume everything up to (and including) the matching right brace.
60 ConsumeAndStoreUntil(tok::r_brace
, tok::unknown
, Toks
);
62 // If we're in a function-try-block, we need to store all the catch blocks.
63 if (kind
== tok::kw_try
) {
64 while (Tok
.is(tok::kw_catch
)) {
65 ConsumeAndStoreUntil(tok::l_brace
, tok::unknown
, Toks
);
66 ConsumeAndStoreUntil(tok::r_brace
, tok::unknown
, Toks
);
73 /// ParseLexedMethodDeclarations - We finished parsing the member
74 /// specification of a top (non-nested) C++ class. Now go over the
75 /// stack of method declarations with some parts for which parsing was
76 /// delayed (such as default arguments) and parse them.
77 void Parser::ParseLexedMethodDeclarations(ParsingClass
&Class
) {
78 bool HasTemplateScope
= !Class
.TopLevelClass
&& Class
.TemplateScope
;
79 ParseScope
TemplateScope(this, Scope::TemplateParamScope
, HasTemplateScope
);
81 Actions
.ActOnReenterTemplateScope(CurScope
, Class
.TagOrTemplate
);
83 bool HasClassScope
= !Class
.TopLevelClass
;
84 ParseScope
ClassScope(this, Scope::ClassScope
|Scope::DeclScope
,
87 for (; !Class
.MethodDecls
.empty(); Class
.MethodDecls
.pop_front()) {
88 LateParsedMethodDeclaration
&LM
= Class
.MethodDecls
.front();
90 // FIXME: For member function templates, we'll need to introduce a
91 // scope for the template parameters.
93 // Start the delayed C++ method declaration
94 Actions
.ActOnStartDelayedCXXMethodDeclaration(CurScope
, LM
.Method
);
96 // Introduce the parameters into scope and parse their default
98 ParseScope
PrototypeScope(this,
99 Scope::FunctionPrototypeScope
|Scope::DeclScope
);
100 for (unsigned I
= 0, N
= LM
.DefaultArgs
.size(); I
!= N
; ++I
) {
101 // Introduce the parameter into scope.
102 Actions
.ActOnDelayedCXXMethodParameter(CurScope
, LM
.DefaultArgs
[I
].Param
);
104 if (CachedTokens
*Toks
= LM
.DefaultArgs
[I
].Toks
) {
105 // Parse the default argument from its saved token stream.
106 Toks
->push_back(Tok
); // So that the current token doesn't get lost
107 PP
.EnterTokenStream(&Toks
->front(), Toks
->size(), true, false);
109 // Consume the previously-pushed token.
113 assert(Tok
.is(tok::equal
) && "Default argument not starting with '='");
114 SourceLocation EqualLoc
= ConsumeToken();
116 OwningExprResult
DefArgResult(ParseAssignmentExpression());
117 if (DefArgResult
.isInvalid())
118 Actions
.ActOnParamDefaultArgumentError(LM
.DefaultArgs
[I
].Param
);
120 Actions
.ActOnParamDefaultArgument(LM
.DefaultArgs
[I
].Param
, EqualLoc
,
123 LM
.DefaultArgs
[I
].Toks
= 0;
126 PrototypeScope
.Exit();
128 // Finish the delayed C++ method declaration.
129 Actions
.ActOnFinishDelayedCXXMethodDeclaration(CurScope
, LM
.Method
);
132 for (unsigned I
= 0, N
= Class
.NestedClasses
.size(); I
!= N
; ++I
)
133 ParseLexedMethodDeclarations(*Class
.NestedClasses
[I
]);
136 /// ParseLexedMethodDefs - We finished parsing the member specification of a top
137 /// (non-nested) C++ class. Now go over the stack of lexed methods that were
138 /// collected during its parsing and parse them all.
139 void Parser::ParseLexedMethodDefs(ParsingClass
&Class
) {
140 bool HasTemplateScope
= !Class
.TopLevelClass
&& Class
.TemplateScope
;
141 ParseScope
TemplateScope(this, Scope::TemplateParamScope
, HasTemplateScope
);
142 if (HasTemplateScope
)
143 Actions
.ActOnReenterTemplateScope(CurScope
, Class
.TagOrTemplate
);
145 bool HasClassScope
= !Class
.TopLevelClass
;
146 ParseScope
ClassScope(this, Scope::ClassScope
|Scope::DeclScope
,
149 for (; !Class
.MethodDefs
.empty(); Class
.MethodDefs
.pop_front()) {
150 LexedMethod
&LM
= Class
.MethodDefs
.front();
152 assert(!LM
.Toks
.empty() && "Empty body!");
153 // Append the current token at the end of the new token stream so that it
155 LM
.Toks
.push_back(Tok
);
156 PP
.EnterTokenStream(&LM
.Toks
.front(), LM
.Toks
.size(), true, false);
158 // Consume the previously pushed token.
160 assert((Tok
.is(tok::l_brace
) || Tok
.is(tok::colon
) || Tok
.is(tok::kw_try
))
161 && "Inline method not starting with '{', ':' or 'try'");
163 // Parse the method body. Function body parsing code is similar enough
164 // to be re-used for method bodies as well.
165 ParseScope
FnScope(this, Scope::FnScope
|Scope::DeclScope
);
166 Actions
.ActOnStartOfFunctionDef(CurScope
, LM
.D
);
168 if (Tok
.is(tok::kw_try
)) {
169 ParseFunctionTryBlock(LM
.D
);
172 if (Tok
.is(tok::colon
))
173 ParseConstructorInitializer(LM
.D
);
175 Actions
.ActOnDefaultCDtorInitializers(LM
.D
);
177 // FIXME: What if ParseConstructorInitializer doesn't leave us with a '{'??
178 ParseFunctionStatementBody(LM
.D
);
181 for (unsigned I
= 0, N
= Class
.NestedClasses
.size(); I
!= N
; ++I
)
182 ParseLexedMethodDefs(*Class
.NestedClasses
[I
]);
185 /// ConsumeAndStoreUntil - Consume and store the token at the passed token
186 /// container until the token 'T' is reached (which gets
187 /// consumed/stored too, if ConsumeFinalToken).
188 /// If EarlyAbortIf is specified, then we will stop early if we find that
189 /// token at the top level.
190 /// Returns true if token 'T1' or 'T2' was found.
191 /// NOTE: This is a specialized version of Parser::SkipUntil.
192 bool Parser::ConsumeAndStoreUntil(tok::TokenKind T1
, tok::TokenKind T2
,
194 tok::TokenKind EarlyAbortIf
,
195 bool ConsumeFinalToken
) {
196 // We always want this function to consume at least one token if the first
197 // token isn't T and if not at EOF.
198 bool isFirstTokenConsumed
= true;
200 // If we found one of the tokens, stop and return true.
201 if (Tok
.is(T1
) || Tok
.is(T2
)) {
202 if (ConsumeFinalToken
) {
209 // If we found the early-abort token, return.
210 if (Tok
.is(EarlyAbortIf
))
213 switch (Tok
.getKind()) {
215 // Ran out of tokens.
219 // Recursively consume properly-nested parens.
222 ConsumeAndStoreUntil(tok::r_paren
, tok::unknown
, Toks
);
225 // Recursively consume properly-nested square brackets.
228 ConsumeAndStoreUntil(tok::r_square
, tok::unknown
, Toks
);
231 // Recursively consume properly-nested braces.
234 ConsumeAndStoreUntil(tok::r_brace
, tok::unknown
, Toks
);
237 // Okay, we found a ']' or '}' or ')', which we think should be balanced.
238 // Since the user wasn't looking for this token (if they were, it would
239 // already be handled), this isn't balanced. If there is a LHS token at a
240 // higher level, we will assume that this matches the unbalanced token
241 // and return it. Otherwise, this is a spurious RHS token, which we skip.
243 if (ParenCount
&& !isFirstTokenConsumed
)
244 return false; // Matches something.
249 if (BracketCount
&& !isFirstTokenConsumed
)
250 return false; // Matches something.
255 if (BraceCount
&& !isFirstTokenConsumed
)
256 return false; // Matches something.
261 case tok::string_literal
:
262 case tok::wide_string_literal
:
264 ConsumeStringToken();
267 // consume this token.
272 isFirstTokenConsumed
= false;