diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp | 257 |
1 files changed, 129 insertions, 128 deletions
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp index 076edb9..fa6401f 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp @@ -101,17 +101,13 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context, do { // Consume the 'export', if any. SourceLocation ExportLoc; - if (Tok.is(tok::kw_export)) { - ExportLoc = ConsumeToken(); - } + TryConsumeToken(tok::kw_export, ExportLoc); // Consume the 'template', which should be here. SourceLocation TemplateLoc; - if (Tok.is(tok::kw_template)) { - TemplateLoc = ConsumeToken(); - } else { + if (!TryConsumeToken(tok::kw_template, TemplateLoc)) { Diag(Tok.getLocation(), diag::err_expected_template); - return 0; + return nullptr; } // Parse the '<' template-parameter-list '>' @@ -121,9 +117,8 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context, TemplateParams, LAngleLoc, RAngleLoc)) { // Skip until the semi-colon or a }. SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch); - if (Tok.is(tok::semi)) - ConsumeToken(); - return 0; + TryConsumeToken(tok::semi); + return nullptr; } ParamLists.push_back( @@ -175,7 +170,7 @@ Parser::ParseSingleDeclarationAfterTemplate( // We are parsing a member template. ParseCXXClassMemberDeclaration(AS, AccessAttrs, TemplateInfo, &DiagsFromTParams); - return 0; + return nullptr; } ParsedAttributesWithRange prefixAttrs(AttrFactory); @@ -219,7 +214,7 @@ Parser::ParseSingleDeclarationAfterTemplate( SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch); if (Tok.is(tok::semi)) ConsumeToken(); - return 0; + return nullptr; } LateParsedAttrList LateParsedAttrs(true); @@ -255,8 +250,8 @@ Parser::ParseSingleDeclarationAfterTemplate( // Recover as if it were an explicit specialization. TemplateParameterLists FakedParamLists; FakedParamLists.push_back(Actions.ActOnTemplateParameterList( - 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, 0, 0, - LAngleLoc)); + 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, nullptr, + 0, LAngleLoc)); return ParseFunctionDefinition( DeclaratorInfo, ParsedTemplateInfo(&FakedParamLists, @@ -302,11 +297,10 @@ bool Parser::ParseTemplateParameters(unsigned Depth, SourceLocation &LAngleLoc, SourceLocation &RAngleLoc) { // Get the template parameter list. - if (!Tok.is(tok::less)) { + if (!TryConsumeToken(tok::less, LAngleLoc)) { Diag(Tok.getLocation(), diag::err_expected_less_after) << "template"; return true; } - LAngleLoc = ConsumeToken(); // Try to parse the template parameter list. bool Failed = false; @@ -322,10 +316,8 @@ bool Parser::ParseTemplateParameters(unsigned Depth, Tok.setKind(tok::greater); RAngleLoc = Tok.getLocation(); Tok.setLocation(Tok.getLocation().getLocWithOffset(1)); - } else if (Tok.is(tok::greater)) - RAngleLoc = ConsumeToken(); - else if (Failed) { - Diag(Tok.getLocation(), diag::err_expected_greater); + } else if (!TryConsumeToken(tok::greater, RAngleLoc) && Failed) { + Diag(Tok.getLocation(), diag::err_expected) << tok::greater; return true; } return false; @@ -481,12 +473,8 @@ Decl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) { SourceLocation KeyLoc = ConsumeToken(); // Grab the ellipsis (if given). - bool Ellipsis = false; SourceLocation EllipsisLoc; - if (Tok.is(tok::ellipsis)) { - Ellipsis = true; - EllipsisLoc = ConsumeToken(); - + if (TryConsumeToken(tok::ellipsis, EllipsisLoc)) { Diag(EllipsisLoc, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_variadic_templates @@ -495,7 +483,7 @@ Decl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) { // Grab the template parameter name (if given) SourceLocation NameLoc; - IdentifierInfo* ParamName = 0; + IdentifierInfo *ParamName = nullptr; if (Tok.is(tok::identifier)) { ParamName = Tok.getIdentifierInfo(); NameLoc = ConsumeToken(); @@ -504,34 +492,40 @@ Decl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) { // Unnamed template parameter. Don't have to do anything here, just // don't consume this token. } else { - Diag(Tok.getLocation(), diag::err_expected_ident); - return 0; + Diag(Tok.getLocation(), diag::err_expected) << tok::identifier; + return nullptr; } + // Recover from misplaced ellipsis. + bool AlreadyHasEllipsis = EllipsisLoc.isValid(); + if (TryConsumeToken(tok::ellipsis, EllipsisLoc)) + DiagnoseMisplacedEllipsis(EllipsisLoc, NameLoc, AlreadyHasEllipsis, true); + // Grab a default argument (if available). // Per C++0x [basic.scope.pdecl]p9, we parse the default argument before // we introduce the type parameter into the local scope. SourceLocation EqualLoc; ParsedType DefaultArg; - if (Tok.is(tok::equal)) { - EqualLoc = ConsumeToken(); - DefaultArg = ParseTypeName(/*Range=*/0, + if (TryConsumeToken(tok::equal, EqualLoc)) + DefaultArg = ParseTypeName(/*Range=*/nullptr, Declarator::TemplateTypeArgContext).get(); - } - return Actions.ActOnTypeParameter(getCurScope(), TypenameKeyword, Ellipsis, - EllipsisLoc, KeyLoc, ParamName, NameLoc, - Depth, Position, EqualLoc, DefaultArg); + return Actions.ActOnTypeParameter(getCurScope(), TypenameKeyword, EllipsisLoc, + KeyLoc, ParamName, NameLoc, Depth, Position, + EqualLoc, DefaultArg); } /// ParseTemplateTemplateParameter - Handle the parsing of template /// template parameters. /// /// type-parameter: [C++ temp.param] -/// 'template' '<' template-parameter-list '>' 'class' +/// 'template' '<' template-parameter-list '>' type-parameter-key /// ...[opt] identifier[opt] -/// 'template' '<' template-parameter-list '>' 'class' identifier[opt] -/// = id-expression +/// 'template' '<' template-parameter-list '>' type-parameter-key +/// identifier[opt] = id-expression +/// type-parameter-key: +/// 'class' +/// 'typename' [C++1z] Decl * Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) { assert(Tok.is(tok::kw_template) && "Expected 'template' keyword"); @@ -544,45 +538,50 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) { ParseScope TemplateParmScope(this, Scope::TemplateParamScope); if (ParseTemplateParameters(Depth + 1, TemplateParams, LAngleLoc, RAngleLoc)) { - return 0; + return nullptr; } } + // Provide an ExtWarn if the C++1z feature of using 'typename' here is used. // Generate a meaningful error if the user forgot to put class before the // identifier, comma, or greater. Provide a fixit if the identifier, comma, - // or greater appear immediately or after 'typename' or 'struct'. In the - // latter case, replace the keyword with 'class'. - if (!Tok.is(tok::kw_class)) { + // or greater appear immediately or after 'struct'. In the latter case, + // replace the keyword with 'class'. + if (!TryConsumeToken(tok::kw_class)) { bool Replace = Tok.is(tok::kw_typename) || Tok.is(tok::kw_struct); - const Token& Next = Replace ? NextToken() : Tok; - if (Next.is(tok::identifier) || Next.is(tok::comma) || - Next.is(tok::greater) || Next.is(tok::greatergreater) || - Next.is(tok::ellipsis)) + const Token &Next = Tok.is(tok::kw_struct) ? NextToken() : Tok; + if (Tok.is(tok::kw_typename)) { + Diag(Tok.getLocation(), + getLangOpts().CPlusPlus1z + ? diag::warn_cxx1y_compat_template_template_param_typename + : diag::ext_template_template_param_typename) + << (!getLangOpts().CPlusPlus1z + ? FixItHint::CreateReplacement(Tok.getLocation(), "class") + : FixItHint()); + } else if (Next.is(tok::identifier) || Next.is(tok::comma) || + Next.is(tok::greater) || Next.is(tok::greatergreater) || + Next.is(tok::ellipsis)) { Diag(Tok.getLocation(), diag::err_class_on_template_template_param) << (Replace ? FixItHint::CreateReplacement(Tok.getLocation(), "class") : FixItHint::CreateInsertion(Tok.getLocation(), "class ")); - else + } else Diag(Tok.getLocation(), diag::err_class_on_template_template_param); if (Replace) ConsumeToken(); - } else - ConsumeToken(); + } // Parse the ellipsis, if given. SourceLocation EllipsisLoc; - if (Tok.is(tok::ellipsis)) { - EllipsisLoc = ConsumeToken(); - + if (TryConsumeToken(tok::ellipsis, EllipsisLoc)) Diag(EllipsisLoc, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_variadic_templates : diag::ext_variadic_templates); - } // Get the identifier, if given. SourceLocation NameLoc; - IdentifierInfo* ParamName = 0; + IdentifierInfo *ParamName = nullptr; if (Tok.is(tok::identifier)) { ParamName = Tok.getIdentifierInfo(); NameLoc = ConsumeToken(); @@ -591,10 +590,15 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) { // Unnamed template parameter. Don't have to do anything here, just // don't consume this token. } else { - Diag(Tok.getLocation(), diag::err_expected_ident); - return 0; + Diag(Tok.getLocation(), diag::err_expected) << tok::identifier; + return nullptr; } + // Recover from misplaced ellipsis. + bool AlreadyHasEllipsis = EllipsisLoc.isValid(); + if (TryConsumeToken(tok::ellipsis, EllipsisLoc)) + DiagnoseMisplacedEllipsis(EllipsisLoc, NameLoc, AlreadyHasEllipsis, true); + TemplateParameterList *ParamList = Actions.ActOnTemplateParameterList(Depth, SourceLocation(), TemplateLoc, LAngleLoc, @@ -607,8 +611,7 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) { // we introduce the template parameter into the local scope. SourceLocation EqualLoc; ParsedTemplateArgument DefaultArg; - if (Tok.is(tok::equal)) { - EqualLoc = ConsumeToken(); + if (TryConsumeToken(tok::equal, EqualLoc)) { DefaultArg = ParseTemplateTemplateArgument(); if (DefaultArg.isInvalid()) { Diag(Tok.getLocation(), @@ -643,17 +646,20 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) { ParseDeclarator(ParamDecl); if (DS.getTypeSpecType() == DeclSpec::TST_unspecified) { Diag(Tok.getLocation(), diag::err_expected_template_parameter); - return 0; + return nullptr; } + // Recover from misplaced ellipsis. + SourceLocation EllipsisLoc; + if (TryConsumeToken(tok::ellipsis, EllipsisLoc)) + DiagnoseMisplacedEllipsisInDeclarator(EllipsisLoc, ParamDecl); + // If there is a default value, parse it. // Per C++0x [basic.scope.pdecl]p9, we parse the default argument before // we introduce the template parameter into the local scope. SourceLocation EqualLoc; ExprResult DefaultArg; - if (Tok.is(tok::equal)) { - EqualLoc = ConsumeToken(); - + if (TryConsumeToken(tok::equal, EqualLoc)) { // C++ [temp.param]p15: // When parsing a default template-argument for a non-type // template-parameter, the first non-nested > is taken as the @@ -670,7 +676,29 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) { // Create the parameter. return Actions.ActOnNonTypeTemplateParameter(getCurScope(), ParamDecl, Depth, Position, EqualLoc, - DefaultArg.take()); + DefaultArg.get()); +} + +void Parser::DiagnoseMisplacedEllipsis(SourceLocation EllipsisLoc, + SourceLocation CorrectLoc, + bool AlreadyHasEllipsis, + bool IdentifierHasName) { + FixItHint Insertion; + if (!AlreadyHasEllipsis) + Insertion = FixItHint::CreateInsertion(CorrectLoc, "..."); + Diag(EllipsisLoc, diag::err_misplaced_ellipsis_in_declaration) + << FixItHint::CreateRemoval(EllipsisLoc) << Insertion + << !IdentifierHasName; +} + +void Parser::DiagnoseMisplacedEllipsisInDeclarator(SourceLocation EllipsisLoc, + Declarator &D) { + assert(EllipsisLoc.isValid()); + bool AlreadyHasEllipsis = D.getEllipsisLoc().isValid(); + if (!AlreadyHasEllipsis) + D.setEllipsisLoc(EllipsisLoc); + DiagnoseMisplacedEllipsis(EllipsisLoc, D.getIdentifierLoc(), + AlreadyHasEllipsis, D.hasName()); } /// \brief Parses a '>' at the end of a template list. @@ -692,7 +720,7 @@ bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc, switch (Tok.getKind()) { default: - Diag(Tok.getLocation(), diag::err_expected_greater); + Diag(Tok.getLocation(), diag::err_expected) << tok::greater; return true; case tok::greater: @@ -723,7 +751,9 @@ bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc, // This template-id is terminated by a token which starts with a '>'. Outside // C++11, this is now error recovery, and in C++11, this is error recovery if - // the token isn't '>>'. + // the token isn't '>>' or '>>>'. + // '>>>' is for CUDA, where this sequence of characters is parsed into + // tok::greatergreatergreater, rather than two separate tokens. RAngleLoc = Tok.getLocation(); @@ -753,7 +783,8 @@ bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc, Hint2 = FixItHint::CreateInsertion(Next.getLocation(), " "); unsigned DiagId = diag::err_two_right_angle_brackets_need_space; - if (getLangOpts().CPlusPlus11 && Tok.is(tok::greatergreater)) + if (getLangOpts().CPlusPlus11 && + (Tok.is(tok::greatergreater) || Tok.is(tok::greatergreatergreater))) DiagId = diag::warn_cxx98_compat_two_right_angle_brackets; else if (Tok.is(tok::greaterequal)) DiagId = diag::err_right_angle_bracket_equal_needs_space; @@ -900,8 +931,7 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, if (Invalid) { // If we failed to parse the template ID but skipped ahead to a >, we're not // going to be able to form a token annotation. Eat the '>' if present. - if (Tok.is(tok::greater)) - ConsumeToken(); + TryConsumeToken(tok::greater); return true; } @@ -916,8 +946,7 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, if (Type.isInvalid()) { // If we failed to parse the template ID but skipped ahead to a >, we're not // going to be able to form a token annotation. Eat the '>' if present. - if (Tok.is(tok::greater)) - ConsumeToken(); + TryConsumeToken(tok::greater); return true; } @@ -940,7 +969,7 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, TemplateId->Name = TemplateName.Identifier; TemplateId->Operator = OO_None; } else { - TemplateId->Name = 0; + TemplateId->Name = nullptr; TemplateId->Operator = TemplateName.OperatorFunctionId.Operator; } TemplateId->SS = SS; @@ -1044,11 +1073,9 @@ ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() { UnqualifiedId Name; Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation()); ConsumeToken(); // the identifier - - // Parse the ellipsis. - if (Tok.is(tok::ellipsis)) - EllipsisLoc = ConsumeToken(); - + + TryConsumeToken(tok::ellipsis, EllipsisLoc); + // If the next token signals the end of a template argument, // then we have a dependent template name that could be a template // template argument. @@ -1067,10 +1094,8 @@ ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() { UnqualifiedId Name; Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation()); ConsumeToken(); // the identifier - - // Parse the ellipsis. - if (Tok.is(tok::ellipsis)) - EllipsisLoc = ConsumeToken(); + + TryConsumeToken(tok::ellipsis, EllipsisLoc); if (isEndOfTemplateArgument(Tok)) { bool MemberOfUnknownSpecialization; @@ -1111,7 +1136,7 @@ ParsedTemplateArgument Parser::ParseTemplateArgument() { // Therefore, we initially try to parse a type-id. if (isCXXTypeId(TypeIdAsTemplateArgument)) { SourceLocation Loc = Tok.getLocation(); - TypeResult TypeArg = ParseTypeName(/*Range=*/0, + TypeResult TypeArg = ParseTypeName(/*Range=*/nullptr, Declarator::TemplateTypeArgContext); if (TypeArg.isInvalid()) return ParsedTemplateArgument(); @@ -1143,7 +1168,7 @@ ParsedTemplateArgument Parser::ParseTemplateArgument() { return ParsedTemplateArgument(); return ParsedTemplateArgument(ParsedTemplateArgument::NonType, - ExprArg.release(), Loc); + ExprArg.get(), Loc); } /// \brief Determine whether the current tokens can only be parsed as a @@ -1161,16 +1186,15 @@ bool Parser::IsTemplateArgumentList(unsigned Skip) { } // '<' - if (!Tok.is(tok::less)) + if (!TryConsumeToken(tok::less)) return false; - ConsumeToken(); // An empty template argument list. if (Tok.is(tok::greater)) return true; // See whether we have declaration specifiers, which indicate a type. - while (isCXXDeclarationSpecifier() == TPResult::True()) + while (isCXXDeclarationSpecifier() == TPResult::True) ConsumeToken(); // If we have a '>' or a ',' then this is a template argument list. @@ -1187,13 +1211,13 @@ bool Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) { // Template argument lists are constant-evaluation contexts. EnterExpressionEvaluationContext EvalContext(Actions,Sema::ConstantEvaluated); + ColonProtectionRAIIObject ColonProtection(*this, false); - while (true) { + do { ParsedTemplateArgument Arg = ParseTemplateArgument(); - if (Tok.is(tok::ellipsis)) { - SourceLocation EllipsisLoc = ConsumeToken(); + SourceLocation EllipsisLoc; + if (TryConsumeToken(tok::ellipsis, EllipsisLoc)) Arg = Actions.ActOnPackExpansion(Arg, EllipsisLoc); - } if (Arg.isInvalid()) { SkipUntil(tok::comma, tok::greater, StopAtSemi | StopBeforeMatch); @@ -1205,11 +1229,7 @@ Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) { // If the next token is a comma, consume it and keep reading // arguments. - if (Tok.isNot(tok::comma)) break; - - // Consume the comma. - ConsumeToken(); - } + } while (TryConsumeToken(tok::comma)); return false; } @@ -1258,9 +1278,7 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) { return; // Get the FunctionDecl. - FunctionTemplateDecl *FunTmplD = dyn_cast<FunctionTemplateDecl>(LPT.D); - FunctionDecl *FunD = - FunTmplD ? FunTmplD->getTemplatedDecl() : cast<FunctionDecl>(LPT.D); + FunctionDecl *FunD = LPT.D->getAsFunction(); // Track template parameter depth. TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth); @@ -1271,7 +1289,7 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) { // Get the list of DeclContexts to reenter. SmallVector<DeclContext*, 4> DeclContextsToReenter; - DeclContext *DD = FunD->getLexicalParent(); + DeclContext *DD = FunD; while (DD && !DD->isTranslationUnit()) { DeclContextsToReenter.push_back(DD); DD = DD->getLexicalParent(); @@ -1281,35 +1299,16 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) { SmallVectorImpl<DeclContext *>::reverse_iterator II = DeclContextsToReenter.rbegin(); for (; II != DeclContextsToReenter.rend(); ++II) { - if (ClassTemplatePartialSpecializationDecl *MD = - dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(*II)) { - TemplateParamScopeStack.push_back( - new ParseScope(this, Scope::TemplateParamScope)); - Actions.ActOnReenterTemplateScope(getCurScope(), MD); - ++CurTemplateDepthTracker; - } else if (CXXRecordDecl *MD = dyn_cast_or_null<CXXRecordDecl>(*II)) { - bool IsClassTemplate = MD->getDescribedClassTemplate() != 0; - TemplateParamScopeStack.push_back( - new ParseScope(this, Scope::TemplateParamScope, - /*ManageScope*/IsClassTemplate)); - Actions.ActOnReenterTemplateScope(getCurScope(), - MD->getDescribedClassTemplate()); - if (IsClassTemplate) - ++CurTemplateDepthTracker; + TemplateParamScopeStack.push_back(new ParseScope(this, + Scope::TemplateParamScope)); + unsigned NumParamLists = + Actions.ActOnReenterTemplateScope(getCurScope(), cast<Decl>(*II)); + CurTemplateDepthTracker.addDepth(NumParamLists); + if (*II != FunD) { + TemplateParamScopeStack.push_back(new ParseScope(this, Scope::DeclScope)); + Actions.PushDeclContext(Actions.getCurScope(), *II); } - TemplateParamScopeStack.push_back(new ParseScope(this, Scope::DeclScope)); - Actions.PushDeclContext(Actions.getCurScope(), *II); - } - TemplateParamScopeStack.push_back( - new ParseScope(this, Scope::TemplateParamScope)); - - DeclaratorDecl *Declarator = dyn_cast<DeclaratorDecl>(FunD); - if (Declarator && Declarator->getNumTemplateParameterLists() != 0) { - Actions.ActOnReenterDeclaratorTemplateScope(getCurScope(), Declarator); - ++CurTemplateDepthTracker; } - Actions.ActOnReenterTemplateScope(getCurScope(), LPT.D); - ++CurTemplateDepthTracker; assert(!LPT.Toks.empty() && "Empty body!"); @@ -1341,14 +1340,16 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) { Actions.ActOnDefaultCtorInitializers(LPT.D); if (Tok.is(tok::l_brace)) { - assert((!FunTmplD || FunTmplD->getTemplateParameters()->getDepth() < - TemplateParameterDepth) && + assert((!isa<FunctionTemplateDecl>(LPT.D) || + cast<FunctionTemplateDecl>(LPT.D) + ->getTemplateParameters() + ->getDepth() == TemplateParameterDepth - 1) && "TemplateParameterDepth should be greater than the depth of " "current template being instantiated!"); ParseFunctionStatementBody(LPT.D, FnScope); Actions.UnmarkAsLateParsedTemplate(FunD); } else - Actions.ActOnFinishFunctionBody(LPT.D, 0); + Actions.ActOnFinishFunctionBody(LPT.D, nullptr); } // Exit scopes. |