clang: lib/Parse/ParseCXXInlineMethods.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

20#include "llvm/ADT/ScopeExit.h"

21

22using namespace clang;

23

24StringLiteral *Parser::ParseCXXDeletedFunctionMessage() {

25 if (!Tok.is(tok::l_paren))

26 return nullptr;

27 StringLiteral *Message = nullptr;

30

31 if (isTokenStringLiteral()) {

36 ? diag::warn_cxx23_delete_with_message

37 : diag::ext_delete_with_message)

38 << Message->getSourceRange();

39 }

40 } else {

41 Diag(Tok.getLocation(), diag::err_expected_string_literal)

42 << 0 << "'delete'";

44 }

45

48}

49

50void Parser::SkipDeletedFunctionBody() {

51 if (!Tok.is(tok::l_paren))

52 return;

53

56

57

59 if (Tok.is(tok::r_paren))

61}

62

63NamedDecl *Parser::ParseCXXInlineMethodDef(

68 assert(Tok.isOneOf(tok::l_brace, tok::colon, tok::kw_try, tok::equal) &&

69 "Current token not a '{', ':', '=', or 'try'!");

70

72 TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->data()

73 : nullptr,

74 TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->size() : 0);

75

76 NamedDecl *FnD;

78 FnD = Actions.ActOnFriendFunctionDecl(getCurScope(), D,

79 TemplateParams);

80 else {

81 FnD = Actions.ActOnCXXMemberDeclarator(getCurScope(), AS, D,

82 TemplateParams, nullptr,

84 if (FnD) {

85 Actions.ProcessDeclAttributeList(getCurScope(), FnD, AccessAttrs);

86 if (PureSpecLoc.isValid())

87 Actions.ActOnPureSpecifier(FnD, PureSpecLoc);

88 }

89 }

90

91 if (FnD)

92 HandleMemberFunctionDeclDelays(D, FnD);

93

95

97 if (!FnD) {

99 return nullptr;

100 }

101

103 SourceLocation KWLoc;

104 SourceLocation KWEndLoc = Tok.getEndLoc().getLocWithOffset(-1);

107 ? diag::warn_cxx98_compat_defaulted_deleted_function

108 : diag::ext_defaulted_deleted_function)

109 << 1 ;

110 StringLiteral *Message = ParseCXXDeletedFunctionMessage();

111 Actions.SetDeclDeleted(FnD, KWLoc, Message);

113 if (auto *DeclAsFunction = dyn_cast(FnD)) {

114 DeclAsFunction->setRangeEnd(KWEndLoc);

115 }

118 ? diag::warn_cxx98_compat_defaulted_deleted_function

119 : diag::ext_defaulted_deleted_function)

120 << 0 ;

121 Actions.SetDeclDefaulted(FnD, KWLoc);

122 if (auto *DeclAsFunction = dyn_cast(FnD)) {

123 DeclAsFunction->setRangeEnd(KWEndLoc);

124 }

125 } else {

126 llvm_unreachable("function definition after = not 'delete' or 'default'");

127 }

128

129 if (Tok.is(tok::comma)) {

130 Diag(KWLoc, diag::err_default_delete_in_multiple_declaration)

133 } else if (ExpectAndConsume(tok::semi, diag::err_expected_after,

134 Delete ? "delete" : "default")) {

136 }

137

138 return FnD;

139 }

140

141 if (SkipFunctionBodies && (!FnD || Actions.canSkipFunctionBody(FnD)) &&

142 trySkippingFunctionBody()) {

143 Actions.ActOnSkippedFunctionBody(FnD);

144 return FnD;

145 }

146

147

148

149

150 if (getLangOpts().DelayedTemplateParsing &&

155 ((Actions.CurContext->isDependentContext() ||

158 !Actions.IsInsideALocalClassWithinATemplateFunction())) {

159

161 LexTemplateFunctionForLateParsing(Toks);

162

163 if (FnD) {

165 Actions.CheckForFunctionRedefinition(FD);

166 Actions.MarkAsLateParsedTemplate(FD, FnD, Toks);

167 }

168

169 return FnD;

170 }

171

172

173

174 LexedMethod* LM = new LexedMethod(this, FnD);

175 getCurrentClass().LateParsedDeclarations.push_back(LM);

177

179

180

181 if (ConsumeAndStoreFunctionPrologue(Toks)) {

182

183

184

185

186

187 if (PP.isCodeCompletionEnabled() &&

188 llvm::any_of(Toks, [](const Token &Tok) {

189 return Tok.is(tok::code_completion);

190 })) {

191

192

193

194 return FnD;

195 }

196

197

198

199

200

202 delete getCurrentClass().LateParsedDeclarations.back();

203 getCurrentClass().LateParsedDeclarations.pop_back();

204 return FnD;

205 } else {

206

207 ConsumeAndStoreUntil(tok::r_brace, Toks, false);

208 }

209

210

211 if (kind == tok::kw_try) {

212 while (Tok.is(tok::kw_catch)) {

213 ConsumeAndStoreUntil(tok::l_brace, Toks, false);

214 ConsumeAndStoreUntil(tok::r_brace, Toks, false);

215 }

216 }

217

218 if (FnD) {

220

221

222 Actions.CheckForFunctionRedefinition(FD);

224 } else {

225

226

227 delete getCurrentClass().LateParsedDeclarations.back();

228 getCurrentClass().LateParsedDeclarations.pop_back();

229 }

230

231 return FnD;

232}

233

234void Parser::ParseCXXNonStaticMemberInitializer(Decl *VarD) {

235 assert(Tok.isOneOf(tok::l_brace, tok::equal) &&

236 "Current token not a '{' or '='!");

237

238 LateParsedMemberInitializer *MI =

239 new LateParsedMemberInitializer(this, VarD);

240 getCurrentClass().LateParsedDeclarations.push_back(MI);

242

244 if (kind == tok::equal) {

245 Toks.push_back(Tok);

247 }

248

249 if (kind == tok::l_brace) {

250

251 Toks.push_back(Tok);

252 ConsumeBrace();

253

254

255 ConsumeAndStoreUntil(tok::r_brace, Toks, true);

256 } else {

257

259 }

260

261

262

263 Token Eof;

268 Toks.push_back(Eof);

269}

270

271Parser::LateParsedDeclaration::~LateParsedDeclaration() {}

272void Parser::LateParsedDeclaration::ParseLexedMethodDeclarations() {}

273void Parser::LateParsedDeclaration::ParseLexedMemberInitializers() {}

274void Parser::LateParsedDeclaration::ParseLexedMethodDefs() {}

275void Parser::LateParsedDeclaration::ParseLexedAttributes() {}

276void Parser::LateParsedDeclaration::ParseLexedPragmas() {}

277

278Parser::LateParsedClass::LateParsedClass(Parser *P, ParsingClass *C)

280

281Parser::LateParsedClass::~LateParsedClass() {

282 Self->DeallocateParsedClasses(Class);

283}

284

285void Parser::LateParsedClass::ParseLexedMethodDeclarations() {

286 Self->ParseLexedMethodDeclarations(*Class);

287}

288

289void Parser::LateParsedClass::ParseLexedMemberInitializers() {

290 Self->ParseLexedMemberInitializers(*Class);

291}

292

293void Parser::LateParsedClass::ParseLexedMethodDefs() {

294 Self->ParseLexedMethodDefs(*Class);

295}

296

297void Parser::LateParsedClass::ParseLexedAttributes() {

298 Self->ParseLexedAttributes(*Class);

299}

300

301void Parser::LateParsedClass::ParseLexedPragmas() {

303}

304

305void Parser::LateParsedMethodDeclaration::ParseLexedMethodDeclarations() {

306 Self->ParseLexedMethodDeclaration(*this);

307}

308

309void Parser::LexedMethod::ParseLexedMethodDefs() {

310 Self->ParseLexedMethodDef(*this);

311}

312

313void Parser::LateParsedMemberInitializer::ParseLexedMemberInitializers() {

314 Self->ParseLexedMemberInitializer(*this);

315}

316

317void Parser::LateParsedAttribute::ParseLexedAttributes() {

318 Self->ParseLexedAttribute(*this, true, false);

319}

320

321void Parser::LateParsedPragma::ParseLexedPragmas() {

322 Self->ParseLexedPragma(*this);

323}

324

329

332 if (Enter) {

334 P.ReenterTemplateScopes(Scopes, MaybeTemplated));

335 }

336 }

337};

338

341

344 Class.TopLevelClass),

346

347 if (Class.TopLevelClass)

348 return;

349

350

352 P.Actions.ActOnStartDelayedMemberDeclarations(P.getCurScope(),

353 Class.TagOrTemplate);

354 }

356 if (Class.TopLevelClass)

357 return;

358

359 P.Actions.ActOnFinishDelayedMemberDeclarations(P.getCurScope(),

360 Class.TagOrTemplate);

361 }

362};

363

364void Parser::ParseLexedMethodDeclarations(ParsingClass &Class) {

365 ReenterClassScopeRAII InClassScope(*this, Class);

366

367 for (LateParsedDeclaration *LateD : Class.LateParsedDeclarations)

368 LateD->ParseLexedMethodDeclarations();

369}

370

371void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {

372

373 ReenterTemplateScopeRAII InFunctionTemplateScope(*this, LM.Method);

374

375

377

378

379

383 for (unsigned I = 0, N = LM.DefaultArgs.size(); I != N; ++I) {

385

386 bool HasUnparsed = Param->hasUnparsedDefaultArg();

388 std::unique_ptr Toks = std::move(LM.DefaultArgs[I].Toks);

389 if (Toks) {

391

392

393

394 Token LastDefaultArgToken = Toks->back();

397 DefArgEnd.setKind(tok::eof);

400 Toks->push_back(DefArgEnd);

401

402

403 Toks->push_back(Tok);

404 PP.EnterTokenStream(*Toks, true, true);

405

406

408

409

410 assert(Tok.is(tok::equal) && "Default argument not starting with '='");

412

413

414

416 Actions,

418

421 Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);

422 DefArgResult = ParseBraceInitializer();

423 } else

426 Actions.ActOnParamDefaultArgumentError(Param, EqualLoc,

427 nullptr);

428 } else {

429 if (Tok.isNot(tok::eof) || Tok.getEofData() != Param) {

430

431

432

433 assert(Toks->size() >= 3 && "expected a token in default arg");

434 Diag(Tok.getLocation(), diag::err_default_arg_unparsed)

435 << SourceRange(Tok.getLocation(),

436 (*Toks)[Toks->size() - 3].getLocation());

437 }

438 Actions.ActOnParamDefaultArgument(Param, EqualLoc,

439 DefArgResult.get());

440 }

441

442

443

444 while (Tok.isNot(tok::eof))

446

447 if (Tok.is(tok::eof) && Tok.getEofData() == Param)

449 } else if (HasUnparsed) {

450 assert(Param->hasInheritedDefaultArg());

451 FunctionDecl *Old;

452 if (const auto *FunTmpl = dyn_cast(LM.Method))

453 Old =

455 else

457 if (Old) {

458 ParmVarDecl *OldParam = Old->getParamDecl(I);

461 Param->setUninstantiatedDefaultArg(

463 else

464 Param->setDefaultArg(OldParam->getInit());

465 }

466 }

467 }

468

469

470 if (CachedTokens *Toks = LM.ExceptionSpecTokens) {

472

473

474 Token LastExceptionSpecToken = Toks->back();

475 Token ExceptionSpecEnd;

477 ExceptionSpecEnd.setKind(tok::eof);

479 ExceptionSpecEnd.setEofData(LM.Method);

480 Toks->push_back(ExceptionSpecEnd);

481

482

483 Toks->push_back(Tok);

484 PP.EnterTokenStream(*Toks, true, true);

485

486

488

489

490

491

492

493

494

495 CXXMethodDecl *Method;

496 FunctionDecl *FunctionToPush;

497 if (FunctionTemplateDecl *FunTmpl

498 = dyn_cast(LM.Method))

499 FunctionToPush = FunTmpl->getTemplatedDecl();

500 else

502 Method = dyn_cast(FunctionToPush);

503

504

505

506

507

508

509

510

511

512

514 Sema::ContextRAII FnContext(Actions, FunctionToPush,

515 false);

516 Sema::FunctionScopeRAII PopFnContext(Actions);

517 Actions.PushFunctionScope();

518

519 Sema::CXXThisScopeRAII ThisScope(

520 Actions, Method ? Method->getParent() : nullptr,

521 Method ? Method->getMethodQualifiers() : Qualifiers{},

523

524

525 SourceRange SpecificationRange;

526 SmallVector<ParsedType, 4> DynamicExceptions;

527 SmallVector<SourceRange, 4> DynamicExceptionRanges;

530

532 = tryParseExceptionSpecification(false, SpecificationRange,

533 DynamicExceptions,

534 DynamicExceptionRanges, NoexceptExpr,

535 ExceptionSpecTokens);

536

537 if (Tok.isNot(tok::eof) || Tok.getEofData() != LM.Method)

538 Diag(Tok.getLocation(), diag::err_except_spec_unparsed);

539

540

541 Actions.actOnDelayedExceptionSpecification(LM.Method, EST,

542 SpecificationRange,

543 DynamicExceptions,

544 DynamicExceptionRanges,

546 NoexceptExpr.get() : nullptr);

547

548

549

550 while (Tok.isNot(tok::eof))

552

553

554 if (Tok.is(tok::eof) && Tok.getEofData() == LM.Method)

556

557 delete Toks;

558 LM.ExceptionSpecTokens = nullptr;

559 }

560

561 InFunctionTemplateScope.Scopes.Exit();

562

563

564 Actions.ActOnFinishDelayedCXXMethodDeclaration(getCurScope(), LM.Method);

565}

566

567void Parser::ParseLexedMethodDefs(ParsingClass &Class) {

569

570 for (LateParsedDeclaration *D : Class.LateParsedDeclarations)

571 D->ParseLexedMethodDefs();

572}

573

574void Parser::ParseLexedMethodDef(LexedMethod &LM) {

575

577

579

580 assert(!LM.Toks.empty() && "Empty body!");

581 Token LastBodyToken = LM.Toks.back();

582 Token BodyEnd;

584 BodyEnd.setKind(tok::eof);

587 LM.Toks.push_back(BodyEnd);

588

589

590 LM.Toks.push_back(Tok);

591 PP.EnterTokenStream(LM.Toks, true, true);

592

593

595 assert(Tok.isOneOf(tok::l_brace, tok::colon, tok::kw_try)

596 && "Inline method not starting with '{', ':' or 'try'");

597

598

599

602 Sema::FPFeaturesStateRAII SaveFPFeatures(Actions);

603

604 Actions.ActOnStartOfFunctionDef(getCurScope(), LM.D);

605

606 auto _ = llvm::make_scope_exit([&]() {

607 while (Tok.isNot(tok::eof))

609

610 if (Tok.is(tok::eof) && Tok.getEofData() == LM.D)

612

613 if (auto *FD = dyn_cast_or_null(LM.D))

616 Actions.ActOnFinishInlineFunctionDef(FD);

617 });

618

619 if (Tok.is(tok::kw_try)) {

620 ParseFunctionTryBlock(LM.D, FnScope);

621 return;

622 }

623 if (Tok.is(tok::colon)) {

624 ParseConstructorInitializer(LM.D);

625

626

627 if (!Tok.is(tok::l_brace)) {

628 FnScope.Exit();

629 Actions.ActOnFinishFunctionBody(LM.D, nullptr);

630 return;

631 }

632 } else

633 Actions.ActOnDefaultCtorInitializers(LM.D);

634

635 assert((Actions.getDiagnostics().hasErrorOccurred() ||

638 < TemplateParameterDepth) &&

639 "TemplateParameterDepth should be greater than the depth of "

640 "current template being instantiated!");

641

642 ParseFunctionStatementBody(LM.D, FnScope);

643}

644

645void Parser::ParseLexedMemberInitializers(ParsingClass &Class) {

647

648 if (Class.LateParsedDeclarations.empty()) {

649

650

651

652

653

654

655 Sema::CXXThisScopeRAII ThisScope(Actions, Class.TagOrTemplate,

656 Qualifiers());

657

658 for (LateParsedDeclaration *D : Class.LateParsedDeclarations)

659 D->ParseLexedMemberInitializers();

660 }

661

662 Actions.ActOnFinishDelayedMemberInitializers(Class.TagOrTemplate);

663}

664

665void Parser::ParseLexedMemberInitializer(LateParsedMemberInitializer &MI) {

666 if (!MI.Field || MI.Field->isInvalidDecl())

667 return;

668

670

671

672

673 MI.Toks.push_back(Tok);

674 PP.EnterTokenStream(MI.Toks, true, true);

675

676

678

679 SourceLocation EqualLoc;

680

681 Actions.ActOnStartCXXInClassMemberInitializer();

682

683

684

685 EnterExpressionEvaluationContext Eval(

687

688 ExprResult Init = ParseCXXMemberInitializer(MI.Field, false,

689 EqualLoc);

690

691 Actions.ActOnFinishCXXInClassMemberInitializer(MI.Field, EqualLoc, Init);

692

693

694 if (Tok.isNot(tok::eof)) {

695 if (Init.isInvalid()) {

696 SourceLocation EndLoc = PP.getLocForEndOfToken(PrevTokLocation);

698 EndLoc = Tok.getLocation();

699

700 Diag(EndLoc, diag::err_expected_semi_decl_list);

701 }

702

703

704 while (Tok.isNot(tok::eof))

706 }

707

708 if (Tok.getEofData() == MI.Field)

710}

711

712void Parser::ParseLexedAttributes(ParsingClass &Class) {

714

715 for (LateParsedDeclaration *LateD : Class.LateParsedDeclarations)

716 LateD->ParseLexedAttributes();

717}

718

719void Parser::ParseLexedAttributeList(LateParsedAttrList &LAs, Decl *D,

720 bool EnterScope, bool OnDefinition) {

721 assert(LAs.parseSoon() &&

722 "Attribute list should be marked for immediate parsing.");

723 for (unsigned i = 0, ni = LAs.size(); i < ni; ++i) {

724 if (D)

725 LAs[i]->addDecl(D);

726 ParseLexedAttribute(*LAs[i], EnterScope, OnDefinition);

727 delete LAs[i];

728 }

729 LAs.clear();

730}

731

732void Parser::ParseLexedAttribute(LateParsedAttribute &LA,

733 bool EnterScope, bool OnDefinition) {

734

735

736 Token AttrEnd;

737 AttrEnd.startToken();

738 AttrEnd.setKind(tok::eof);

739 AttrEnd.setLocation(Tok.getLocation());

740 AttrEnd.setEofData(LA.Toks.data());

741 LA.Toks.push_back(AttrEnd);

742

743

744

745 LA.Toks.push_back(Tok);

746 PP.EnterTokenStream(LA.Toks, true, true);

747

749

750 ParsedAttributes Attrs(AttrFactory);

751

752 if (LA.Decls.size() > 0) {

753 Decl *D = LA.Decls[0];

754 NamedDecl *ND = dyn_cast(D);

755 RecordDecl *RD = dyn_cast_or_null(D->getDeclContext());

756

757

758 Sema::CXXThisScopeRAII ThisScope(Actions, RD, Qualifiers(),

760

761 if (LA.Decls.size() == 1) {

762

764

765

767 if (HasFunScope) {

770 Actions.ActOnReenterFunctionContext(Actions.CurScope, D);

771 }

772

773 ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, nullptr,

774 nullptr, SourceLocation(), ParsedAttr::Form::GNU(),

775 nullptr);

776

777 if (HasFunScope)

778 Actions.ActOnExitFunctionContext();

779 } else {

780

781

782 ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, nullptr,

783 nullptr, SourceLocation(), ParsedAttr::Form::GNU(),

784 nullptr);

785 }

786 } else {

787 Diag(Tok, diag::warn_attribute_no_decl) << LA.AttrName.getName();

788 }

789

790 if (OnDefinition && !Attrs.empty() && !Attrs.begin()->isCXX11Attribute() &&

791 Attrs.begin()->isKnownToGCC())

792 Diag(Tok, diag::warn_attribute_on_function_definition)

793 << &LA.AttrName;

794

795 for (unsigned i = 0, ni = LA.Decls.size(); i < ni; ++i)

796 Actions.ActOnFinishDelayedAttribute(getCurScope(), LA.Decls[i], Attrs);

797

798

799

800 while (Tok.isNot(tok::eof))

802

803 if (Tok.is(tok::eof) && Tok.getEofData() == AttrEnd.getEofData())

805}

806

807void Parser::ParseLexedPragmas(ParsingClass &Class) {

809

810 for (LateParsedDeclaration *D : Class.LateParsedDeclarations)

811 D->ParseLexedPragmas();

812}

813

814void Parser::ParseLexedPragma(LateParsedPragma &LP) {

815 PP.EnterToken(Tok, true);

816 PP.EnterTokenStream(LP.toks(), true,

817 true);

818

819

821 assert(Tok.isAnnotation() && "Expected annotation token.");

822 switch (Tok.getKind()) {

823 case tok::annot_attr_openmp:

824 case tok::annot_pragma_openmp: {

826 ParsedAttributes Attrs(AttrFactory);

827 (void)ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs);

828 break;

829 }

830 default:

831 llvm_unreachable("Unexpected token.");

832 }

833}

834

837 bool StopAtSemi, bool ConsumeFinalToken) {

838

839

840 bool isFirstTokenConsumed = true;

841 while (true) {

842

843 if (Tok.is(T1) || Tok.is(T2)) {

844 if (ConsumeFinalToken) {

845 Toks.push_back(Tok);

847 }

848 return true;

849 }

850

851 switch (Tok.getKind()) {

852 case tok::eof:

853 case tok::annot_module_begin:

854 case tok::annot_module_end:

855 case tok::annot_module_include:

856 case tok::annot_repl_input_end:

857

858 return false;

859

860 case tok::l_paren:

861

862 Toks.push_back(Tok);

863 ConsumeParen();

864 ConsumeAndStoreUntil(tok::r_paren, Toks, false);

865 break;

866 case tok::l_square:

867

868 Toks.push_back(Tok);

869 ConsumeBracket();

870 ConsumeAndStoreUntil(tok::r_square, Toks, false);

871 break;

872 case tok::l_brace:

873

874 Toks.push_back(Tok);

875 ConsumeBrace();

876 ConsumeAndStoreUntil(tok::r_brace, Toks, false);

877 break;

878

879

880

881

882

883

884 case tok::r_paren:

885 if (ParenCount && !isFirstTokenConsumed)

886 return false;

887 Toks.push_back(Tok);

888 ConsumeParen();

889 break;

890 case tok::r_square:

891 if (BracketCount && !isFirstTokenConsumed)

892 return false;

893 Toks.push_back(Tok);

894 ConsumeBracket();

895 break;

896 case tok::r_brace:

897 if (BraceCount && !isFirstTokenConsumed)

898 return false;

899 Toks.push_back(Tok);

900 ConsumeBrace();

901 break;

902

903 case tok:🚛

905 return false;

906 [[fallthrough]];

907 default:

908

909 Toks.push_back(Tok);

911 break;

912 }

913 isFirstTokenConsumed = false;

914 }

915}

916

917bool Parser::ConsumeAndStoreFunctionPrologue(CachedTokens &Toks) {

918 if (Tok.is(tok::kw_try)) {

919 Toks.push_back(Tok);

921 }

922

923 if (Tok.isNot(tok::colon)) {

924

925

926

927

928

929 ConsumeAndStoreUntil(tok::l_brace, tok::r_brace, Toks,

930 true,

931 false);

932 if (Tok.isNot(tok::l_brace))

933 return Diag(Tok.getLocation(), diag::err_expected) << tok::l_brace;

934

935 Toks.push_back(Tok);

936 ConsumeBrace();

937 return false;

938 }

939

940 Toks.push_back(Tok);

942

943

944

945

946

947

948

949

950

951

952

953 bool MightBeTemplateArgument = false;

954

955 while (true) {

956

957 if (Tok.is(tok::kw_decltype)) {

958 Toks.push_back(Tok);

960 if (Tok.isNot(tok::l_paren))

961 return Diag(Tok.getLocation(), diag::err_expected_lparen_after)

962 << "decltype";

963 Toks.push_back(Tok);

964 ConsumeParen();

965 if (!ConsumeAndStoreUntil(tok::r_paren, Toks, true)) {

966 Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;

967 Diag(OpenLoc, diag::note_matching) << tok::l_paren;

968 return true;

969 }

970 }

971 do {

972

973 if (Tok.is(tok::coloncolon)) {

974 Toks.push_back(Tok);

976

977 if (Tok.is(tok::kw_template)) {

978 Toks.push_back(Tok);

980 }

981 }

982

983 if (Tok.is(tok::identifier)) {

984 Toks.push_back(Tok);

986 } else {

987 break;

988 }

989

990 if (Tok.is(tok::ellipsis) && NextToken().is(tok::l_square)) {

991 Toks.push_back(Tok);

993 Toks.push_back(Tok);

994 ConsumeBracket();

995 if (!ConsumeAndStoreUntil(tok::r_square, Toks, true)) {

996 Diag(Tok.getLocation(), diag::err_expected) << tok::r_square;

997 Diag(OpenLoc, diag::note_matching) << tok::l_square;

998 return true;

999 }

1000 }

1001

1002 } while (Tok.is(tok::coloncolon));

1003

1004 if (Tok.is(tok::code_completion)) {

1005 Toks.push_back(Tok);

1006 ConsumeCodeCompletionToken();

1007 if (Tok.isOneOf(tok::identifier, tok::coloncolon, tok::kw_decltype)) {

1008

1009

1010 continue;

1011 }

1012 }

1013

1014 if (Tok.is(tok::comma)) {

1015

1016 Toks.push_back(Tok);

1018 continue;

1019 }

1020 if (Tok.is(tok::less))

1021 MightBeTemplateArgument = true;

1022

1023 if (MightBeTemplateArgument) {

1024

1025

1026

1027

1028

1029

1030 if (!ConsumeAndStoreUntil(tok::l_paren, tok::l_brace, Toks,

1031 true,

1032 false)) {

1033

1034

1035 return Diag(Tok.getLocation(), diag::err_expected) << tok::l_brace;

1036 }

1037 } else if (Tok.isNot(tok::l_paren) && Tok.isNot(tok::l_brace)) {

1038

1040 return Diag(Tok.getLocation(), diag::err_expected_either)

1041 << tok::l_paren << tok::l_brace;

1042 else

1043 return Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;

1044 }

1045

1047 Toks.push_back(Tok);

1048 bool IsLParen = (kind == tok::l_paren);

1049 SourceLocation OpenLoc = Tok.getLocation();

1050

1051 if (IsLParen) {

1052 ConsumeParen();

1053 } else {

1054 assert(kind == tok::l_brace && "Must be left paren or brace here.");

1055 ConsumeBrace();

1056

1057

1059 return false;

1060

1061 const Token &PreviousToken = Toks[Toks.size() - 2];

1062 if (!MightBeTemplateArgument &&

1063 !PreviousToken.isOneOf(tok::identifier, tok::greater,

1064 tok::greatergreater)) {

1065

1066

1067

1068

1069

1070 TentativeParsingAction PA(*this);

1072 !Tok.isOneOf(tok::comma, tok::ellipsis, tok::l_brace)) {

1073

1074

1075 PA.Revert();

1076 return false;

1077 }

1078 PA.Revert();

1079 }

1080 }

1081

1082

1083

1084

1085 tok::TokenKind CloseKind = IsLParen ? tok::r_paren : tok::r_brace;

1086 if (!ConsumeAndStoreUntil(CloseKind, Toks, true)) {

1087 Diag(Tok, diag::err_expected) << CloseKind;

1088 Diag(OpenLoc, diag::note_matching) << kind;

1089 return true;

1090 }

1091

1092

1093 if (Tok.is(tok::ellipsis)) {

1094 Toks.push_back(Tok);

1096 }

1097

1098

1099

1100 if (Tok.is(tok::comma)) {

1101 Toks.push_back(Tok);

1103 } else if (Tok.is(tok::l_brace)) {

1104

1105

1106

1107

1108

1109

1110

1111

1112

1113

1114

1115

1116

1117

1118 Toks.push_back(Tok);

1119 ConsumeBrace();

1120 return false;

1121 } else if (!MightBeTemplateArgument) {

1122 return Diag(Tok.getLocation(), diag::err_expected_either) << tok::l_brace

1123 << tok::comma;

1124 }

1125 }

1126}

1127

1128bool Parser::ConsumeAndStoreConditional(CachedTokens &Toks) {

1129

1130 assert(Tok.is(tok::question));

1131 Toks.push_back(Tok);

1133

1134 while (Tok.isNot(tok::colon)) {

1135 if (!ConsumeAndStoreUntil(tok::question, tok::colon, Toks,

1136 true,

1137 false))

1138 return false;

1139

1140

1141 if (Tok.is(tok::question) && !ConsumeAndStoreConditional(Toks))

1142 return false;

1143 }

1144

1145

1146 Toks.push_back(Tok);

1148 return true;

1149}

1150

1151bool Parser::ConsumeAndStoreInitializer(CachedTokens &Toks,

1153

1154 bool IsFirstToken = true;

1155

1156

1157

1158

1159 unsigned AngleCount = 0;

1160 unsigned KnownTemplateCount = 0;

1161

1162 while (true) {

1163 switch (Tok.getKind()) {

1164 case tok::ellipsis:

1165

1166

1167 if (ParenCount == 1 && NextToken().is(tok::r_paren))

1168 return true;

1169 goto consume_token;

1170 case tok::comma:

1171

1172 if (!AngleCount)

1173

1174 return true;

1175 if (KnownTemplateCount)

1176 goto consume_token;

1177

1178

1179

1180

1181

1182

1183

1184

1185

1186

1187 {

1188 TentativeParsingAction TPA(*this, true);

1189 Sema::TentativeAnalysisScope Scope(Actions);

1190

1191 TPResult Result = TPResult::Error;

1193 switch (CIK) {

1195 Result = TryParseInitDeclaratorList();

1196

1197

1198 if (Result == TPResult::Ambiguous && Tok.isNot(tok::semi))

1199 Result = TPResult::False;

1200 break;

1201

1203 bool InvalidAsDeclaration = false;

1204 Result = TryParseParameterDeclarationClause(

1205 &InvalidAsDeclaration, true);

1206

1207

1208 if (Result == TPResult::Ambiguous && InvalidAsDeclaration)

1209 Result = TPResult::False;

1210 break;

1211 }

1212

1213

1214

1215

1216 TPA.Revert();

1217

1218

1219 if (Result != TPResult::False && Result != TPResult::Error)

1220 return true;

1221 }

1222

1223

1224 ++KnownTemplateCount;

1225 goto consume_token;

1226

1227 case tok::eof:

1228

1229 return false;

1230

1231 case tok::less:

1232

1233

1234 ++AngleCount;

1235 goto consume_token;

1236

1237 case tok::question:

1238

1239

1240 if (!ConsumeAndStoreConditional(Toks))

1241 return false;

1242 break;

1243

1244 case tok::greatergreatergreater:

1246 goto consume_token;

1247 if (AngleCount) --AngleCount;

1248 if (KnownTemplateCount) --KnownTemplateCount;

1249 [[fallthrough]];

1250 case tok::greatergreater:

1252 goto consume_token;

1253 if (AngleCount) --AngleCount;

1254 if (KnownTemplateCount) --KnownTemplateCount;

1255 [[fallthrough]];

1256 case tok::greater:

1257 if (AngleCount) --AngleCount;

1258 if (KnownTemplateCount) --KnownTemplateCount;

1259 goto consume_token;

1260

1261 case tok::kw_template:

1262

1263

1264

1265 Toks.push_back(Tok);

1267 if (Tok.is(tok::identifier)) {

1268 Toks.push_back(Tok);

1270 if (Tok.is(tok::less)) {

1271 ++AngleCount;

1272 ++KnownTemplateCount;

1273 Toks.push_back(Tok);

1275 }

1276 }

1277 break;

1278

1279 case tok::kw_operator:

1280

1281

1282 Toks.push_back(Tok);

1284 switch (Tok.getKind()) {

1285 case tok::comma:

1286 case tok::greatergreatergreater:

1287 case tok::greatergreater:

1288 case tok::greater:

1289 case tok::less:

1290 Toks.push_back(Tok);

1292 break;

1293 default:

1294 break;

1295 }

1296 break;

1297

1298 case tok::l_paren:

1299

1300 Toks.push_back(Tok);

1301 ConsumeParen();

1302 ConsumeAndStoreUntil(tok::r_paren, Toks, false);

1303 break;

1304 case tok::l_square:

1305

1306 Toks.push_back(Tok);

1307 ConsumeBracket();

1308 ConsumeAndStoreUntil(tok::r_square, Toks, false);

1309 break;

1310 case tok::l_brace:

1311

1312 Toks.push_back(Tok);

1313 ConsumeBrace();

1314 ConsumeAndStoreUntil(tok::r_brace, Toks, false);

1315 break;

1316

1317

1318

1319

1320

1321

1322

1323 case tok::r_paren:

1325 return true;

1326 if (ParenCount && !IsFirstToken)

1327 return false;

1328 Toks.push_back(Tok);

1329 ConsumeParen();

1330 continue;

1331 case tok::r_square:

1332 if (BracketCount && !IsFirstToken)

1333 return false;

1334 Toks.push_back(Tok);

1335 ConsumeBracket();

1336 continue;

1337 case tok::r_brace:

1338 if (BraceCount && !IsFirstToken)

1339 return false;

1340 Toks.push_back(Tok);

1341 ConsumeBrace();

1342 continue;

1343

1344 case tok::code_completion:

1345 Toks.push_back(Tok);

1346 ConsumeCodeCompletionToken();

1347 break;

1348

1349 case tok::string_literal:

1350 case tok::wide_string_literal:

1351 case tok::utf8_string_literal:

1352 case tok::utf16_string_literal:

1353 case tok::utf32_string_literal:

1354 Toks.push_back(Tok);

1355 ConsumeStringToken();

1356 break;

1357 case tok:🚛

1359 return true;

1360 [[fallthrough]];

1361 default:

1362 consume_token:

1363

1364

1365 if (Tok.isAnnotation())

1366 return false;

1367

1368 Toks.push_back(Tok);

1370 break;

1371 }

1372 IsFirstToken = false;

1373 }

1374}

This file defines the classes used to store parsed information about declaration-specifiers and decla...

Defines the C++ template declaration subclasses.

bool is(tok::TokenKind Kind) const

FriendSpecified isFriendSpecified() const

bool hasConstexprSpecifier() const

Decl - This represents one declaration (or definition), e.g.

bool isFunctionOrFunctionTemplate() const

Whether this declaration is a function or function template.

bool isInIdentifierNamespace(unsigned NS) const

FunctionDecl * getAsFunction() LLVM_READONLY

Returns the function itself, or the templated function if this is a function template.

@ IDNS_OrdinaryFriend

This declaration is a friend function.

DeclContext * getDeclContext()

bool isFunctionDeclarator(unsigned &idx) const

isFunctionDeclarator - This method returns true if the declarator is a function declarator (looking t...

FunctionDefinitionKind getFunctionDefinitionKind() const

RAII object that enters a new expression evaluation context.

const ParmVarDecl * getParamDecl(unsigned i) const

QualType getReturnType() const

void setWillHaveBody(bool V=true)

This represents a decl that may have a name.

bool isCXXInstanceMember() const

Determine whether the given declaration is an instance member of a C++ class.

RAII object that makes sure paren/bracket/brace count is correct after declaration/statement parsing,...

bool hasUnparsedDefaultArg() const

Determines whether this parameter has a default argument that has not yet been parsed.

bool hasUninstantiatedDefaultArg() const

Expr * getUninstantiatedDefaultArg()

Introduces zero or more scopes for parsing.

ParseScope - Introduces a new scope for parsing.

DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)

SourceLocation ConsumeToken()

ConsumeToken - Consume the current 'peek token' and lex the next one.

Parser(Preprocessor &PP, Sema &Actions, bool SkipFunctionBodies)

void EnterScope(unsigned ScopeFlags)

EnterScope - Start a new scope.

SourceLocation ConsumeAnyToken(bool ConsumeCodeCompletionTok=false)

ConsumeAnyToken - Dispatch to the right Consume* method based on the current token type.

bool TryConsumeToken(tok::TokenKind Expected)

Scope * getCurScope() const

bool SkipUntil(tok::TokenKind T, SkipUntilFlags Flags=static_cast< SkipUntilFlags >(0))

SkipUntil - Read tokens until we get to the specified token, then consume it (unless StopBeforeMatch ...

void SkipMalformedDecl()

SkipMalformedDecl - Read tokens until we get to some likely good stopping point for skipping past a s...

const LangOptions & getLangOpts() const

friend class ParenBraceBracketBalancer

@ StopBeforeMatch

Stop skipping at specified token, but don't skip the token itself.

@ StopAtSemi

Stop skipping at semicolon.

ExprResult ParseUnevaluatedStringLiteralExpression()

const Token & NextToken()

NextToken - This peeks ahead one token and returns it without consuming it.

ExprResult ParseAssignmentExpression(TypoCorrectionTypeBehavior CorrectionBehavior=TypoCorrectionTypeBehavior::AllowNonTypes)

Parse an expr that doesn't include (top-level) commas.

friend class BalancedDelimiterTracker

A class for parsing a declarator.

const ParsingDeclSpec & getDeclSpec() const

@ FunctionPrototypeScope

This is a scope that corresponds to the parameters within a function prototype.

@ CompoundStmtScope

This is a compound statement scope.

@ ClassScope

The scope of a struct/union/class definition.

@ FunctionDeclarationScope

This is a scope that corresponds to the parameters within a function prototype for a function declara...

@ FnScope

This indicates that the scope corresponds to a function, which means that labels are set here.

@ DeclScope

This is a scope that can contain a declaration.

@ PotentiallyEvaluatedIfUsed

The current expression is potentially evaluated, but any declarations referenced inside that expressi...

void ActOnStartDelayedCXXMethodDeclaration(Scope *S, Decl *Method)

ActOnStartDelayedCXXMethodDeclaration - We have completed parsing a top-level (non-nested) C++ class,...

void ActOnDelayedCXXMethodParameter(Scope *S, Decl *Param)

ActOnDelayedCXXMethodParameter - We've already started a delayed C++ method declaration.

Encodes a location in the source.

bool isValid() const

Return true if this is a valid SourceLocation object.

StringLiteral - This represents a string literal expression, e.g.

Token - This structure provides full information about a lexed token.

SourceLocation getEndLoc() const

void setKind(tok::TokenKind K)

bool isOneOf(Ts... Ks) const

void setEofData(const void *D)

void setLocation(SourceLocation L)

void startToken()

Reset all flags to cleared.

AutoType * getContainedAutoType() const

Get the AutoType whose type will be deduced for a variable with an initializer of this type.

const Expr * getInit() const

Represents a C++11 virt-specifier-seq.

unsigned kind

All of the diagnostics that can be emitted by the frontend.

std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl

All declarations that can appear in a module declaration.

TokenKind

Provides a simple uniform namespace for tokens from all C languages.

The JSON file list parser is used to communicate input to InstallAPI.

bool isa(CodeGen::Address addr)

MutableArrayRef< TemplateParameterList * > MultiTemplateParamsArg

@ ICIS_NoInit

No in-class initializer.

@ Self

'self' clause, allowed on Compute and Combined Constructs, plus 'update'.

@ Delete

'delete' clause, allowed on the 'exit data' construct.

AccessSpecifier

A C++ access specifier (public, private, protected), plus the special value "none" which means differ...

@ Result

The result type of a method or function.

@ ExplicitSpecialization

We are parsing an explicit specialization.

@ NonTemplate

We are not parsing a template at all.

U cast(CodeGen::Address addr)

SmallVector< Token, 4 > CachedTokens

A set of tokens that has been cached for later parsing.

@ Class

The "class" keyword introduces the elaborated-type-specifier.

ActionResult< Expr * > ExprResult

ExceptionSpecificationType

The various types of exception specifications that exist in C++11.

~ReenterClassScopeRAII()

Definition ParseCXXInlineMethods.cpp:355

ParsingClass & Class

Definition ParseCXXInlineMethods.cpp:340

ReenterClassScopeRAII(Parser &P, ParsingClass &Class)

Definition ParseCXXInlineMethods.cpp:342

Parser & P

Definition ParseCXXInlineMethods.cpp:326

ReenterTemplateScopeRAII(Parser &P, Decl *MaybeTemplated, bool Enter=true)

Definition ParseCXXInlineMethods.cpp:330

MultiParseScope Scopes

Definition ParseCXXInlineMethods.cpp:327

TemplateParameterDepthRAII CurTemplateDepthTracker

Definition ParseCXXInlineMethods.cpp:328