Do not warn with -Wuninitialized when the member is used in a sizeof or address-of...
[clang.git] / lib / Parse / ParseCXXInlineMethods.cpp
blob8b2fb55d9dc00c2b8f0d65168ae8b11d8c5eb585
1 //===--- 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.
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);
34 Decl *FnD;
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);
64 ConsumeAnyToken();
65 getCurrentClass().MethodDefs.pop_back();
66 return FnD;
70 } else {
71 // Begin by storing the '{' token.
72 Toks.push_back(Tok);
73 ConsumeBrace();
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);
86 return FnD;
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);
96 if (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,
103 HasClassScope);
104 if (HasClassScope)
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
119 // arguments.
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.
135 ConsumeAnyToken();
137 // Consume the '='.
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
142 // used.
143 EnterExpressionEvaluationContext Eval(Actions,
144 Sema::PotentiallyEvaluatedIfUsed);
146 ExprResult DefArgResult(ParseAssignmentExpression());
147 if (DefArgResult.isInvalid())
148 Actions.ActOnParamDefaultArgumentError(LM.DefaultArgs[I].Param);
149 else {
150 if (Tok.is(tok::cxx_defaultarg_end))
151 ConsumeToken();
152 else
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))
164 ConsumeAnyToken();
166 delete Toks;
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]);
179 if (HasClassScope)
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,
194 HasClassScope);
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
209 // doesn't get lost.
210 LM.Toks.push_back(Tok);
211 PP.EnterTokenStream(LM.Toks.data(), LM.Toks.size(), true, false);
213 // Consume the previously pushed token.
214 ConsumeAnyToken();
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))
231 ConsumeAnyToken();
232 continue;
234 if (Tok.is(tok::colon)) {
235 ParseConstructorInitializer(LM.D);
237 // Error recovery.
238 if (!Tok.is(tok::l_brace)) {
239 Actions.ActOnFinishFunctionBody(LM.D, 0);
240 continue;
242 } else
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
250 // leftover tokens.
251 // Since this is an uncommon situation that should be avoided, use the
252 // expensive isBeforeInTranslationUnit call.
253 if (PP.getSourceManager().isBeforeInTranslationUnit(Tok.getLocation(),
254 origLoc))
255 while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof))
256 ConsumeAnyToken();
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,
272 CachedTokens &Toks,
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;
277 while (1) {
278 // If we found one of the tokens, stop and return true.
279 if (Tok.is(T1) || Tok.is(T2)) {
280 if (ConsumeFinalToken) {
281 Toks.push_back(Tok);
282 ConsumeAnyToken();
284 return true;
287 switch (Tok.getKind()) {
288 case tok::eof:
289 // Ran out of tokens.
290 return false;
292 case tok::l_paren:
293 // Recursively consume properly-nested parens.
294 Toks.push_back(Tok);
295 ConsumeParen();
296 ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/false);
297 break;
298 case tok::l_square:
299 // Recursively consume properly-nested square brackets.
300 Toks.push_back(Tok);
301 ConsumeBracket();
302 ConsumeAndStoreUntil(tok::r_square, Toks, /*StopAtSemi=*/false);
303 break;
304 case tok::l_brace:
305 // Recursively consume properly-nested braces.
306 Toks.push_back(Tok);
307 ConsumeBrace();
308 ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false);
309 break;
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.
316 case tok::r_paren:
317 if (ParenCount && !isFirstTokenConsumed)
318 return false; // Matches something.
319 Toks.push_back(Tok);
320 ConsumeParen();
321 break;
322 case tok::r_square:
323 if (BracketCount && !isFirstTokenConsumed)
324 return false; // Matches something.
325 Toks.push_back(Tok);
326 ConsumeBracket();
327 break;
328 case tok::r_brace:
329 if (BraceCount && !isFirstTokenConsumed)
330 return false; // Matches something.
331 Toks.push_back(Tok);
332 ConsumeBrace();
333 break;
335 case tok::string_literal:
336 case tok::wide_string_literal:
337 Toks.push_back(Tok);
338 ConsumeStringToken();
339 break;
340 case tok::semi:
341 if (StopAtSemi)
342 return false;
343 // FALL THROUGH.
344 default:
345 // consume this token.
346 Toks.push_back(Tok);
347 ConsumeToken();
348 break;
350 isFirstTokenConsumed = false;