/// ParseCXXInlineMethodDef - We parsed and verified that the specified /// Declarator is a well formed C++ inline method definition. Now lex its body /// and store its tokens for parsing after the C++ class is complete. NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, AttributeList *AccessAttrs, ParsingDeclarator &D, const ParsedTemplateInfo &TemplateInfo, const VirtSpecifiers& VS, FunctionDefinitionKind DefinitionKind, ExprResult& Init) { assert(D.isFunctionDeclarator() && "This isn't a function declarator!"); assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try) || Tok.is(tok::equal)) && "Current token not a '{', ':', '=', or 'try'!"); MultiTemplateParamsArg TemplateParams( TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->data() : nullptr, TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->size() : 0); NamedDecl *FnD; D.setFunctionDefinitionKind(DefinitionKind); if (D.getDeclSpec().isFriendSpecified()) FnD = Actions.ActOnFriendFunctionDecl(getCurScope(), D, TemplateParams); else { FnD = Actions.ActOnCXXMemberDeclarator(getCurScope(), AS, D, TemplateParams, nullptr, VS, ICIS_NoInit); if (FnD) { Actions.ProcessDeclAttributeList(getCurScope(), FnD, AccessAttrs); Actions.ProcessAPINotes(FnD); bool TypeSpecContainsAuto = D.getDeclSpec().containsPlaceholderType(); if (Init.isUsable()) Actions.AddInitializerToDecl(FnD, Init.get(), false, TypeSpecContainsAuto); else Actions.ActOnUninitializedDecl(FnD, TypeSpecContainsAuto); } } HandleMemberFunctionDeclDelays(D, FnD); D.complete(FnD); if (TryConsumeToken(tok::equal)) { if (!FnD) { SkipUntil(tok::semi); return nullptr; } bool Delete = false; SourceLocation KWLoc; if (TryConsumeToken(tok::kw_delete, KWLoc)) { Diag(KWLoc, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_deleted_function : diag::ext_deleted_function); Actions.SetDeclDeleted(FnD, KWLoc); Delete = true; } else if (TryConsumeToken(tok::kw_default, KWLoc)) { Diag(KWLoc, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_defaulted_function : diag::ext_defaulted_function); Actions.SetDeclDefaulted(FnD, KWLoc); } else { llvm_unreachable("function definition after = not 'delete' or 'default'"); } if (Tok.is(tok::comma)) { Diag(KWLoc, diag::err_default_delete_in_multiple_declaration) << Delete; SkipUntil(tok::semi); } else if (ExpectAndConsume(tok::semi, diag::err_expected_after, Delete ? "delete" : "default")) { SkipUntil(tok::semi); } return FnD; } // In delayed template parsing mode, if we are within a class template // or if we are about to parse function member template then consume // the tokens and store them for parsing at the end of the translation unit. if (getLangOpts().DelayedTemplateParsing && DefinitionKind == FDK_Definition && !D.getDeclSpec().isConstexprSpecified() && !(FnD && FnD->getAsFunction() && FnD->getAsFunction()->getReturnType()->getContainedAutoType()) && ((Actions.CurContext->isDependentContext() || (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate && TemplateInfo.Kind != ParsedTemplateInfo::ExplicitSpecialization)) && !Actions.IsInsideALocalClassWithinATemplateFunction())) { CachedTokens Toks; LexTemplateFunctionForLateParsing(Toks); if (FnD) { FunctionDecl *FD = FnD->getAsFunction(); Actions.CheckForFunctionRedefinition(FD); Actions.MarkAsLateParsedTemplate(FD, FnD, Toks); } return FnD; } // Consume the tokens and store them for later parsing. LexedMethod* LM = new LexedMethod(this, FnD); getCurrentClass().LateParsedDeclarations.push_back(LM); LM->TemplateScope = getCurScope()->isTemplateParamScope(); CachedTokens &Toks = LM->Toks; tok::TokenKind kind = Tok.getKind(); // Consume everything up to (and including) the left brace of the // function body. if (ConsumeAndStoreFunctionPrologue(Toks)) { // We didn't find the left-brace we expected after the // constructor initializer; we already printed an error, and it's likely // impossible to recover, so don't try to parse this method later. // Skip over the rest of the decl and back to somewhere that looks // reasonable. SkipMalformedDecl(); delete getCurrentClass().LateParsedDeclarations.back(); getCurrentClass().LateParsedDeclarations.pop_back(); return FnD; } else { // Consume everything up to (and including) the matching right brace. ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false); } // If we're in a function-try-block, we need to store all the catch blocks. if (kind == tok::kw_try) { while (Tok.is(tok::kw_catch)) { ConsumeAndStoreUntil(tok::l_brace, Toks, /*StopAtSemi=*/false); ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false); } } if (FnD) { // If this is a friend function, mark that it's late-parsed so that // it's still known to be a definition even before we attach the // parsed body. Sema needs to treat friend function definitions // differently during template instantiation, and it's possible for // the containing class to be instantiated before all its member // function definitions are parsed. // // If you remove this, you can remove the code that clears the flag // after parsing the member. if (D.getDeclSpec().isFriendSpecified()) { FunctionDecl *FD = FnD->getAsFunction(); Actions.CheckForFunctionRedefinition(FD); FD->setLateTemplateParsed(true); } } else { // If semantic analysis could not build a function declaration, // just throw away the late-parsed declaration. delete getCurrentClass().LateParsedDeclarations.back(); getCurrentClass().LateParsedDeclarations.pop_back(); } return FnD; }