ParseCXXInlineMethods.cpp revision 221345
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. 11// 12//===----------------------------------------------------------------------===// 13 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#include "clang/AST/DeclTemplate.h" 19using namespace clang; 20 21/// ParseCXXInlineMethodDef - We parsed and verified that the specified 22/// Declarator is a well formed C++ inline method definition. Now lex its body 23/// and store its tokens for parsing after the C++ class is complete. 24Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, ParsingDeclarator &D, 25 const ParsedTemplateInfo &TemplateInfo, 26 const VirtSpecifiers& VS) { 27 assert(D.isFunctionDeclarator() && "This isn't a function declarator!"); 28 assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) && 29 "Current token not a '{', ':' or 'try'!"); 30 31 MultiTemplateParamsArg TemplateParams(Actions, 32 TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->data() : 0, 33 TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->size() : 0); 34 35 Decl *FnD; 36 if (D.getDeclSpec().isFriendSpecified()) 37 // FIXME: Friend templates 38 FnD = Actions.ActOnFriendFunctionDecl(getCurScope(), D, true, 39 move(TemplateParams)); 40 else { // FIXME: pass template information through 41 FnD = Actions.ActOnCXXMemberDeclarator(getCurScope(), AS, D, 42 move(TemplateParams), 0, 43 VS, 0, /*IsDefinition*/true); 44 } 45 46 HandleMemberFunctionDefaultArgs(D, FnD); 47 48 D.complete(FnD); 49 50 // In delayed template parsing mode, if we are within a class template 51 // or if we are about to parse function member template then consume 52 // the tokens and store them for parsing at the end of the translation unit. 53 if (getLang().DelayedTemplateParsing && 54 ((Actions.CurContext->isDependentContext() || 55 TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate) && 56 !Actions.IsInsideALocalClassWithinATemplateFunction()) && 57 !D.getDeclSpec().isFriendSpecified()) { 58 59 if (FnD) { 60 LateParsedTemplatedFunction *LPT = 61 new LateParsedTemplatedFunction(this, FnD); 62 63 FunctionDecl *FD = 0; 64 if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(FnD)) 65 FD = FunTmpl->getTemplatedDecl(); 66 else 67 FD = cast<FunctionDecl>(FnD); 68 Actions.CheckForFunctionRedefinition(FD); 69 70 LateParsedTemplateMap[FD] = LPT; 71 Actions.MarkAsLateParsedTemplate(FD); 72 LexTemplateFunctionForLateParsing(LPT->Toks); 73 } else { 74 CachedTokens Toks; 75 LexTemplateFunctionForLateParsing(Toks); 76 } 77 78 return FnD; 79 } 80 81 // Consume the tokens and store them for later parsing. 82 83 LexedMethod* LM = new LexedMethod(this, FnD); 84 getCurrentClass().LateParsedDeclarations.push_back(LM); 85 LM->TemplateScope = getCurScope()->isTemplateParamScope(); 86 CachedTokens &Toks = LM->Toks; 87 88 tok::TokenKind kind = Tok.getKind(); 89 // We may have a constructor initializer or function-try-block here. 90 if (kind == tok::colon || kind == tok::kw_try) { 91 // Consume everything up to (and including) the left brace. 92 if (!ConsumeAndStoreUntil(tok::l_brace, Toks)) { 93 // We didn't find the left-brace we expected after the 94 // constructor initializer. 95 if (Tok.is(tok::semi)) { 96 // We found a semicolon; complain, consume the semicolon, and 97 // don't try to parse this method later. 98 Diag(Tok.getLocation(), diag::err_expected_lbrace); 99 ConsumeAnyToken(); 100 delete getCurrentClass().LateParsedDeclarations.back(); 101 getCurrentClass().LateParsedDeclarations.pop_back(); 102 return FnD; 103 } 104 } 105 106 } else { 107 // Begin by storing the '{' token. 108 Toks.push_back(Tok); 109 ConsumeBrace(); 110 } 111 // Consume everything up to (and including) the matching right brace. 112 ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false); 113 114 // If we're in a function-try-block, we need to store all the catch blocks. 115 if (kind == tok::kw_try) { 116 while (Tok.is(tok::kw_catch)) { 117 ConsumeAndStoreUntil(tok::l_brace, Toks, /*StopAtSemi=*/false); 118 ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false); 119 } 120 } 121 122 123 if (!FnD) { 124 // If semantic analysis could not build a function declaration, 125 // just throw away the late-parsed declaration. 126 delete getCurrentClass().LateParsedDeclarations.back(); 127 getCurrentClass().LateParsedDeclarations.pop_back(); 128 } 129 130 return FnD; 131} 132 133Parser::LateParsedDeclaration::~LateParsedDeclaration() {} 134void Parser::LateParsedDeclaration::ParseLexedMethodDeclarations() {} 135void Parser::LateParsedDeclaration::ParseLexedMethodDefs() {} 136 137Parser::LateParsedClass::LateParsedClass(Parser *P, ParsingClass *C) 138 : Self(P), Class(C) {} 139 140Parser::LateParsedClass::~LateParsedClass() { 141 Self->DeallocateParsedClasses(Class); 142} 143 144void Parser::LateParsedClass::ParseLexedMethodDeclarations() { 145 Self->ParseLexedMethodDeclarations(*Class); 146} 147 148void Parser::LateParsedClass::ParseLexedMethodDefs() { 149 Self->ParseLexedMethodDefs(*Class); 150} 151 152void Parser::LateParsedMethodDeclaration::ParseLexedMethodDeclarations() { 153 Self->ParseLexedMethodDeclaration(*this); 154} 155 156void Parser::LexedMethod::ParseLexedMethodDefs() { 157 Self->ParseLexedMethodDef(*this); 158} 159 160/// ParseLexedMethodDeclarations - We finished parsing the member 161/// specification of a top (non-nested) C++ class. Now go over the 162/// stack of method declarations with some parts for which parsing was 163/// delayed (such as default arguments) and parse them. 164void Parser::ParseLexedMethodDeclarations(ParsingClass &Class) { 165 bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope; 166 ParseScope ClassTemplateScope(this, Scope::TemplateParamScope, HasTemplateScope); 167 if (HasTemplateScope) 168 Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate); 169 170 // The current scope is still active if we're the top-level class. 171 // Otherwise we'll need to push and enter a new scope. 172 bool HasClassScope = !Class.TopLevelClass; 173 ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope, 174 HasClassScope); 175 if (HasClassScope) 176 Actions.ActOnStartDelayedMemberDeclarations(getCurScope(), Class.TagOrTemplate); 177 178 for (size_t i = 0; i < Class.LateParsedDeclarations.size(); ++i) { 179 Class.LateParsedDeclarations[i]->ParseLexedMethodDeclarations(); 180 } 181 182 if (HasClassScope) 183 Actions.ActOnFinishDelayedMemberDeclarations(getCurScope(), Class.TagOrTemplate); 184} 185 186void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { 187 // If this is a member template, introduce the template parameter scope. 188 ParseScope TemplateScope(this, Scope::TemplateParamScope, LM.TemplateScope); 189 if (LM.TemplateScope) 190 Actions.ActOnReenterTemplateScope(getCurScope(), LM.Method); 191 192 // Start the delayed C++ method declaration 193 Actions.ActOnStartDelayedCXXMethodDeclaration(getCurScope(), LM.Method); 194 195 // Introduce the parameters into scope and parse their default 196 // arguments. 197 ParseScope PrototypeScope(this, 198 Scope::FunctionPrototypeScope|Scope::DeclScope); 199 for (unsigned I = 0, N = LM.DefaultArgs.size(); I != N; ++I) { 200 // Introduce the parameter into scope. 201 Actions.ActOnDelayedCXXMethodParameter(getCurScope(), LM.DefaultArgs[I].Param); 202 203 if (CachedTokens *Toks = LM.DefaultArgs[I].Toks) { 204 // Save the current token position. 205 SourceLocation origLoc = Tok.getLocation(); 206 207 // Parse the default argument from its saved token stream. 208 Toks->push_back(Tok); // So that the current token doesn't get lost 209 PP.EnterTokenStream(&Toks->front(), Toks->size(), true, false); 210 211 // Consume the previously-pushed token. 212 ConsumeAnyToken(); 213 214 // Consume the '='. 215 assert(Tok.is(tok::equal) && "Default argument not starting with '='"); 216 SourceLocation EqualLoc = ConsumeToken(); 217 218 // The argument isn't actually potentially evaluated unless it is 219 // used. 220 EnterExpressionEvaluationContext Eval(Actions, 221 Sema::PotentiallyEvaluatedIfUsed); 222 223 ExprResult DefArgResult(ParseAssignmentExpression()); 224 if (DefArgResult.isInvalid()) 225 Actions.ActOnParamDefaultArgumentError(LM.DefaultArgs[I].Param); 226 else { 227 if (Tok.is(tok::cxx_defaultarg_end)) 228 ConsumeToken(); 229 else 230 Diag(Tok.getLocation(), diag::err_default_arg_unparsed); 231 Actions.ActOnParamDefaultArgument(LM.DefaultArgs[I].Param, EqualLoc, 232 DefArgResult.take()); 233 } 234 235 assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc, 236 Tok.getLocation()) && 237 "ParseAssignmentExpression went over the default arg tokens!"); 238 // There could be leftover tokens (e.g. because of an error). 239 // Skip through until we reach the original token position. 240 while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof)) 241 ConsumeAnyToken(); 242 243 delete Toks; 244 LM.DefaultArgs[I].Toks = 0; 245 } 246 } 247 PrototypeScope.Exit(); 248 249 // Finish the delayed C++ method declaration. 250 Actions.ActOnFinishDelayedCXXMethodDeclaration(getCurScope(), LM.Method); 251} 252 253/// ParseLexedMethodDefs - We finished parsing the member specification of a top 254/// (non-nested) C++ class. Now go over the stack of lexed methods that were 255/// collected during its parsing and parse them all. 256void Parser::ParseLexedMethodDefs(ParsingClass &Class) { 257 bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope; 258 ParseScope ClassTemplateScope(this, Scope::TemplateParamScope, HasTemplateScope); 259 if (HasTemplateScope) 260 Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate); 261 262 bool HasClassScope = !Class.TopLevelClass; 263 ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope, 264 HasClassScope); 265 266 for (size_t i = 0; i < Class.LateParsedDeclarations.size(); ++i) { 267 Class.LateParsedDeclarations[i]->ParseLexedMethodDefs(); 268 } 269} 270 271void Parser::ParseLexedMethodDef(LexedMethod &LM) { 272 // If this is a member template, introduce the template parameter scope. 273 ParseScope TemplateScope(this, Scope::TemplateParamScope, LM.TemplateScope); 274 if (LM.TemplateScope) 275 Actions.ActOnReenterTemplateScope(getCurScope(), LM.D); 276 277 // Save the current token position. 278 SourceLocation origLoc = Tok.getLocation(); 279 280 assert(!LM.Toks.empty() && "Empty body!"); 281 // Append the current token at the end of the new token stream so that it 282 // doesn't get lost. 283 LM.Toks.push_back(Tok); 284 PP.EnterTokenStream(LM.Toks.data(), LM.Toks.size(), true, false); 285 286 // Consume the previously pushed token. 287 ConsumeAnyToken(); 288 assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) 289 && "Inline method not starting with '{', ':' or 'try'"); 290 291 // Parse the method body. Function body parsing code is similar enough 292 // to be re-used for method bodies as well. 293 ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope); 294 Actions.ActOnStartOfFunctionDef(getCurScope(), LM.D); 295 296 if (Tok.is(tok::kw_try)) { 297 ParseFunctionTryBlock(LM.D, FnScope); 298 assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc, 299 Tok.getLocation()) && 300 "ParseFunctionTryBlock went over the cached tokens!"); 301 // There could be leftover tokens (e.g. because of an error). 302 // Skip through until we reach the original token position. 303 while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof)) 304 ConsumeAnyToken(); 305 return; 306 } 307 if (Tok.is(tok::colon)) { 308 ParseConstructorInitializer(LM.D); 309 310 // Error recovery. 311 if (!Tok.is(tok::l_brace)) { 312 FnScope.Exit(); 313 Actions.ActOnFinishFunctionBody(LM.D, 0); 314 return; 315 } 316 } else 317 Actions.ActOnDefaultCtorInitializers(LM.D); 318 319 ParseFunctionStatementBody(LM.D, FnScope); 320 321 if (Tok.getLocation() != origLoc) { 322 // Due to parsing error, we either went over the cached tokens or 323 // there are still cached tokens left. If it's the latter case skip the 324 // leftover tokens. 325 // Since this is an uncommon situation that should be avoided, use the 326 // expensive isBeforeInTranslationUnit call. 327 if (PP.getSourceManager().isBeforeInTranslationUnit(Tok.getLocation(), 328 origLoc)) 329 while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof)) 330 ConsumeAnyToken(); 331 332 } 333} 334 335/// ConsumeAndStoreUntil - Consume and store the token at the passed token 336/// container until the token 'T' is reached (which gets 337/// consumed/stored too, if ConsumeFinalToken). 338/// If StopAtSemi is true, then we will stop early at a ';' character. 339/// Returns true if token 'T1' or 'T2' was found. 340/// NOTE: This is a specialized version of Parser::SkipUntil. 341bool Parser::ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2, 342 CachedTokens &Toks, 343 bool StopAtSemi, bool ConsumeFinalToken) { 344 // We always want this function to consume at least one token if the first 345 // token isn't T and if not at EOF. 346 bool isFirstTokenConsumed = true; 347 while (1) { 348 // If we found one of the tokens, stop and return true. 349 if (Tok.is(T1) || Tok.is(T2)) { 350 if (ConsumeFinalToken) { 351 Toks.push_back(Tok); 352 ConsumeAnyToken(); 353 } 354 return true; 355 } 356 357 switch (Tok.getKind()) { 358 case tok::eof: 359 // Ran out of tokens. 360 return false; 361 362 case tok::l_paren: 363 // Recursively consume properly-nested parens. 364 Toks.push_back(Tok); 365 ConsumeParen(); 366 ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/false); 367 break; 368 case tok::l_square: 369 // Recursively consume properly-nested square brackets. 370 Toks.push_back(Tok); 371 ConsumeBracket(); 372 ConsumeAndStoreUntil(tok::r_square, Toks, /*StopAtSemi=*/false); 373 break; 374 case tok::l_brace: 375 // Recursively consume properly-nested braces. 376 Toks.push_back(Tok); 377 ConsumeBrace(); 378 ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false); 379 break; 380 381 // Okay, we found a ']' or '}' or ')', which we think should be balanced. 382 // Since the user wasn't looking for this token (if they were, it would 383 // already be handled), this isn't balanced. If there is a LHS token at a 384 // higher level, we will assume that this matches the unbalanced token 385 // and return it. Otherwise, this is a spurious RHS token, which we skip. 386 case tok::r_paren: 387 if (ParenCount && !isFirstTokenConsumed) 388 return false; // Matches something. 389 Toks.push_back(Tok); 390 ConsumeParen(); 391 break; 392 case tok::r_square: 393 if (BracketCount && !isFirstTokenConsumed) 394 return false; // Matches something. 395 Toks.push_back(Tok); 396 ConsumeBracket(); 397 break; 398 case tok::r_brace: 399 if (BraceCount && !isFirstTokenConsumed) 400 return false; // Matches something. 401 Toks.push_back(Tok); 402 ConsumeBrace(); 403 break; 404 405 case tok::string_literal: 406 case tok::wide_string_literal: 407 Toks.push_back(Tok); 408 ConsumeStringToken(); 409 break; 410 case tok::semi: 411 if (StopAtSemi) 412 return false; 413 // FALL THROUGH. 414 default: 415 // consume this token. 416 Toks.push_back(Tok); 417 ConsumeToken(); 418 break; 419 } 420 isFirstTokenConsumed = false; 421 } 422} 423