clang: lib/AST/CommentSema.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

18#include "llvm/ADT/StringSwitch.h"

19

21namespace comments {

22

23namespace {

24#include "clang/AST/CommentHTMLTagsProperties.inc"

25}

26

27Sema::Sema(llvm::BumpPtrAllocator &Allocator, const SourceManager &SourceMgr,

30 Allocator(Allocator), SourceMgr(SourceMgr), Diags(Diags), Traits(Traits),

31 PP(PP), ThisDeclInfo(nullptr), BriefCommand(nullptr),

32 HeaderfileCommand(nullptr) {

33}

34

36 if (D)

37 return;

38

39 ThisDeclInfo = new (Allocator) DeclInfo;

41 ThisDeclInfo->IsFilled = false;

42}

43

47}

48

52 unsigned CommandID,

55 CommandID,

56 CommandMarker);

57 checkContainerDecl(BC);

58 return BC;

59}

60

64}

65

69 checkBlockCommandEmptyParagraph(Command);

70 checkBlockCommandDuplicate(Command);

71 if (ThisDeclInfo) {

72

73

74 checkReturnsCommand(Command);

75 checkDeprecatedCommand(Command);

76 }

77}

78

82 unsigned CommandID,

86 CommandMarker);

87

88 if (!involvesFunctionType())

90 diag::warn_doc_param_not_attached_to_a_function_decl)

91 << CommandMarker

93

94 return Command;

95}

96

100 return;

101

102 unsigned DiagSelect;

103 switch (Comment->getCommandID()) {

104 case CommandTraits::KCI_function:

105 DiagSelect = (!isAnyFunctionDecl() && !isFunctionTemplateDecl())? 1 : 0;

106 break;

107 case CommandTraits::KCI_functiongroup:

108 DiagSelect = (!isAnyFunctionDecl() && !isFunctionTemplateDecl())? 2 : 0;

109 break;

110 case CommandTraits::KCI_method:

111 DiagSelect = !isObjCMethodDecl() ? 3 : 0;

112 break;

113 case CommandTraits::KCI_methodgroup:

114 DiagSelect = !isObjCMethodDecl() ? 4 : 0;

115 break;

116 case CommandTraits::KCI_callback:

117 DiagSelect = !isFunctionPointerVarDecl() ? 5 : 0;

118 break;

119 default:

120 DiagSelect = 0;

121 break;

122 }

123 if (DiagSelect)

124 Diag(Comment->getLocation(), diag::warn_doc_function_method_decl_mismatch)

126 << (DiagSelect-1) << (DiagSelect-1)

128}

129

130void Sema::checkContainerDeclVerbatimLine(const BlockCommandComment *Comment) {

131 const CommandInfo *Info = Traits.getCommandInfo(Comment->getCommandID());

132 if (!Info->IsRecordLikeDeclarationCommand)

133 return;

134 unsigned DiagSelect;

135 switch (Comment->getCommandID()) {

136 case CommandTraits::KCI_class:

137 DiagSelect =

138 (!isClassOrStructOrTagTypedefDecl() && !isClassTemplateDecl()) ? 1

139 : 0;

140

141

142

143 if (DiagSelect && Comment->getCommandMarker() && isObjCInterfaceDecl())

144 DiagSelect = 0;

145 break;

146 case CommandTraits::KCI_interface:

147 DiagSelect = !isObjCInterfaceDecl() ? 2 : 0;

148 break;

149 case CommandTraits::KCI_protocol:

150 DiagSelect = !isObjCProtocolDecl() ? 3 : 0;

151 break;

152 case CommandTraits::KCI_struct:

153 DiagSelect = !isClassOrStructOrTagTypedefDecl() ? 4 : 0;

154 break;

155 case CommandTraits::KCI_union:

156 DiagSelect = !isUnionDecl() ? 5 : 0;

157 break;

158 default:

159 DiagSelect = 0;

160 break;

161 }

162 if (DiagSelect)

163 Diag(Comment->getLocation(), diag::warn_doc_api_container_decl_mismatch)

164 << Comment->getCommandMarker()

165 << (DiagSelect-1) << (DiagSelect-1)

166 << Comment->getSourceRange();

167}

168

169void Sema::checkContainerDecl(const BlockCommandComment *Comment) {

170 const CommandInfo *Info = Traits.getCommandInfo(Comment->getCommandID());

171 if (!Info->IsRecordLikeDetailCommand || isRecordLikeDecl())

172 return;

173 unsigned DiagSelect;

174 switch (Comment->getCommandID()) {

175 case CommandTraits::KCI_classdesign:

176 DiagSelect = 1;

177 break;

178 case CommandTraits::KCI_coclass:

179 DiagSelect = 2;

180 break;

181 case CommandTraits::KCI_dependency:

182 DiagSelect = 3;

183 break;

184 case CommandTraits::KCI_helper:

185 DiagSelect = 4;

186 break;

187 case CommandTraits::KCI_helperclass:

188 DiagSelect = 5;

189 break;

190 case CommandTraits::KCI_helps:

191 DiagSelect = 6;

192 break;

193 case CommandTraits::KCI_instancesize:

194 DiagSelect = 7;

195 break;

196 case CommandTraits::KCI_ownership:

197 DiagSelect = 8;

198 break;

199 case CommandTraits::KCI_performance:

200 DiagSelect = 9;

201 break;

202 case CommandTraits::KCI_security:

203 DiagSelect = 10;

204 break;

205 case CommandTraits::KCI_superclass:

206 DiagSelect = 11;

207 break;

208 default:

209 DiagSelect = 0;

210 break;

211 }

212 if (DiagSelect)

213 Diag(Comment->getLocation(), diag::warn_doc_container_decl_mismatch)

214 << Comment->getCommandMarker()

215 << (DiagSelect-1)

216 << Comment->getSourceRange();

217}

218

219

220

222 return llvm::StringSwitch(Arg)

227}

228

232 StringRef Arg) {

233 std::string ArgLower = Arg.lower();

235

237

240

241 SourceRange ArgRange(ArgLocBegin, ArgLocEnd);

243 const char *FixedName =

245 Diag(ArgLocBegin, diag::warn_doc_param_spaces_in_direction)

247 } else {

248 Diag(ArgLocBegin, diag::warn_doc_param_invalid_direction) << ArgRange;

250 }

251 }

253 true);

254}

255

259 StringRef Arg) {

260

262

264

266 false);

267 }

268 auto *A = new (Allocator)

271}

272

276 checkBlockCommandEmptyParagraph(Command);

277}

278

282 unsigned CommandID,

286 CommandMarker);

287

288 if (!isTemplateOrSpecialization())

290 diag::warn_doc_tparam_not_attached_to_a_template_decl)

291 << CommandMarker

293

294 return Command;

295}

296

300 StringRef Arg) {

301

303

304 auto *A = new (Allocator)

307

308 if (!isTemplateOrSpecialization()) {

309

310 return;

311 }

312

316 if (resolveTParamReference(Arg, TemplateParameters, &Position)) {

319 if (PrevCommand) {

320 SourceRange ArgRange(ArgLocBegin, ArgLocEnd);

321 Diag(ArgLocBegin, diag::warn_doc_tparam_duplicate)

322 << Arg << ArgRange;

323 Diag(PrevCommand->getLocation(), diag::note_doc_tparam_previous)

325 }

326 PrevCommand = Command;

327 return;

328 }

329

330 SourceRange ArgRange(ArgLocBegin, ArgLocEnd);

331 Diag(ArgLocBegin, diag::warn_doc_tparam_not_found)

332 << Arg << ArgRange;

333

334 if (!TemplateParameters || TemplateParameters->size() == 0)

335 return;

336

337 StringRef CorrectedName;

338 if (TemplateParameters->size() == 1) {

341 if (II)

342 CorrectedName = II->getName();

343 } else {

344 CorrectedName = correctTypoInTParamReference(Arg, TemplateParameters);

345 }

346

347 if (!CorrectedName.empty()) {

348 Diag(ArgLocBegin, diag::note_doc_tparam_name_suggestion)

349 << CorrectedName

351 }

352}

353

357 checkBlockCommandEmptyParagraph(Command);

358}

359

365

366 return new (Allocator)

368 getInlineCommandRenderKind(CommandName), Args);

369}

370

373 StringRef CommandName) {

376}

377

380 unsigned CommandID) {

384}

385

388 StringRef Text) {

389 return new (Allocator) TextComment(LocBegin, LocEnd, Text);

390}

391

393 unsigned CommandID) {

397 Loc.getLocWithOffset(1 + CommandName.size()),

398 CommandID);

399}

400

402 StringRef Text) {

404}

405

409 StringRef CloseName,

411 Block->setCloseName(CloseName, CloseNameLocBegin);

412 Block->setLines(Lines);

413}

414

416 unsigned CommandID,

418 StringRef Text) {

420 LocBegin,

422 CommandID,

423 TextBegin,

425 checkFunctionDeclVerbatimLine(VL);

426 checkContainerDeclVerbatimLine(VL);

427 return VL;

428}

429

431 StringRef TagName) {

433}

434

439 bool IsSelfClosing) {

440 Tag->setAttrs(Attrs);

441 Tag->setGreaterLoc(GreaterLoc);

442 if (IsSelfClosing)

443 Tag->setSelfClosing();

444 else if (!isHTMLEndTagForbidden(Tag->getTagName()))

445 HTMLOpenTags.push_back(Tag);

446}

447

450 StringRef TagName) {

453 if (isHTMLEndTagForbidden(TagName)) {

454 Diag(HET->getLocation(), diag::warn_doc_html_end_forbidden)

457 return HET;

458 }

459

460 bool FoundOpen = false;

462 I = HTMLOpenTags.rbegin(), E = HTMLOpenTags.rend();

463 I != E; ++I) {

464 if ((*I)->getTagName() == TagName) {

465 FoundOpen = true;

466 break;

467 }

468 }

469 if (!FoundOpen) {

470 Diag(HET->getLocation(), diag::warn_doc_html_end_unbalanced)

473 return HET;

474 }

475

476 while (!HTMLOpenTags.empty()) {

478 StringRef LastNotClosedTagName = HST->getTagName();

479 if (LastNotClosedTagName == TagName) {

480

483 break;

484 }

485

486 if (isHTMLEndTagOptional(LastNotClosedTagName))

487 continue;

488

489 bool OpenLineInvalid;

492 &OpenLineInvalid);

493 bool CloseLineInvalid;

496 &CloseLineInvalid);

497

498 if (OpenLineInvalid || CloseLineInvalid || OpenLine == CloseLine) {

499 Diag(HST->getLocation(), diag::warn_doc_html_start_end_mismatch)

503 } else {

504 Diag(HST->getLocation(), diag::warn_doc_html_start_end_mismatch)

507 Diag(HET->getLocation(), diag::note_doc_html_end_tag)

510 }

511 }

512

513 return HET;

514}

515

519 resolveParamCommandIndexes(FC);

520

521

522 while (!HTMLOpenTags.empty()) {

524 if (isHTMLEndTagOptional(HST->getTagName()))

525 continue;

526

527 Diag(HST->getLocation(), diag::warn_doc_html_missing_end_tag)

530 }

531

532 return FC;

533}

534

535void Sema::checkBlockCommandEmptyParagraph(BlockCommandComment *Command) {

537 return;

538

546 Diag(DiagLoc, diag::warn_doc_block_command_empty_paragraph)

550 }

551}

552

553void Sema::checkReturnsCommand(const BlockCommandComment *Command) {

555 return;

556

557 assert(ThisDeclInfo && "should not call this check on a bare comment");

558

559

560

561 if (isObjCPropertyDecl())

562 return;

563 if (involvesFunctionType()) {

565 "should have a valid return type");

567 unsigned DiagKind;

569 default:

571 DiagKind = 3;

572 else

573 DiagKind = 0;

574 break;

575 case Decl::CXXConstructor:

576 DiagKind = 1;

577 break;

578 case Decl::CXXDestructor:

579 DiagKind = 2;

580 break;

581 }

582 Diag(Command->getLocation(),

583 diag::warn_doc_returns_attached_to_a_void_function)

584 << Command->getCommandMarker()

585 << Command->getCommandName(Traits)

586 << DiagKind

587 << Command->getSourceRange();

588 }

589 return;

590 }

591

592 Diag(Command->getLocation(),

593 diag::warn_doc_returns_not_attached_to_a_function_decl)

594 << Command->getCommandMarker()

595 << Command->getCommandName(Traits)

596 << Command->getSourceRange();

597}

598

599void Sema::checkBlockCommandDuplicate(const BlockCommandComment *Command) {

600 const CommandInfo *Info = Traits.getCommandInfo(Command->getCommandID());

601 const BlockCommandComment *PrevCommand = nullptr;

602 if (Info->IsBriefCommand) {

603 if (!BriefCommand) {

604 BriefCommand = Command;

605 return;

606 }

607 PrevCommand = BriefCommand;

608 } else if (Info->IsHeaderfileCommand) {

609 if (!HeaderfileCommand) {

610 HeaderfileCommand = Command;

611 return;

612 }

613 PrevCommand = HeaderfileCommand;

614 } else {

615

616 return;

617 }

618 StringRef CommandName = Command->getCommandName(Traits);

619 StringRef PrevCommandName = PrevCommand->getCommandName(Traits);

620 Diag(Command->getLocation(), diag::warn_doc_block_command_duplicate)

621 << Command->getCommandMarker()

622 << CommandName

623 << Command->getSourceRange();

624 if (CommandName == PrevCommandName)

625 Diag(PrevCommand->getLocation(), diag::note_doc_block_command_previous)

626 << PrevCommand->getCommandMarker()

627 << PrevCommandName

628 << PrevCommand->getSourceRange();

629 else

630 Diag(PrevCommand->getLocation(),

631 diag::note_doc_block_command_previous_alias)

632 << PrevCommand->getCommandMarker()

633 << PrevCommandName

634 << CommandName;

635}

636

637void Sema::checkDeprecatedCommand(const BlockCommandComment *Command) {

639 return;

640

641 assert(ThisDeclInfo && "should not call this check on a bare comment");

642

644 if (D)

645 return;

646

647 if (D->hasAttr() ||

648 D->hasAttr() ||

649 D->hasAttr())

650 return;

651

652 Diag(Command->getLocation(), diag::warn_doc_deprecated_not_sync)

653 << Command->getSourceRange() << Command->getCommandMarker();

654

655

656 if (const FunctionDecl *FD = dyn_cast(D)) {

657

658

659 const DeclContext *Ctx = FD->getDeclContext();

660 if ((!Ctx || !Ctx->isRecord()) &&

661 FD->doesThisDeclarationHaveABody())

662 return;

663

664 const LangOptions &LO = FD->getLangOpts();

665 const bool DoubleSquareBracket = LO.CPlusPlus14 || LO.C23;

666 StringRef AttributeSpelling =

667 DoubleSquareBracket ? "[[deprecated]]" : "__attribute__((deprecated))";

668 if (PP) {

669

670

671

672 StringRef MacroName;

673 if (DoubleSquareBracket) {

674 TokenValue Tokens[] = {tok::l_square, tok::l_square,

676 tok::r_square, tok::r_square};

678 if (!MacroName.empty())

679 AttributeSpelling = MacroName;

680 }

681

682 if (MacroName.empty()) {

683 TokenValue Tokens[] = {

684 tok::kw___attribute, tok::l_paren,

686 tok::r_paren, tok::r_paren};

687 StringRef MacroName =

689 if (!MacroName.empty())

690 AttributeSpelling = MacroName;

691 }

692 }

693

694 SmallString<64> TextToInsert = AttributeSpelling;

695 TextToInsert += " ";

696 SourceLocation Loc = FD->getSourceRange().getBegin();

697 Diag(Loc, diag::note_add_deprecation_attr)

699 }

700}

701

702void Sema::resolveParamCommandIndexes(const FullComment *FC) {

703 if (!involvesFunctionType()) {

704

705

706 return;

707 }

708

709 SmallVector<ParamCommandComment *, 8> UnresolvedParamCommands;

710

711

712

713 SmallVector<ParamCommandComment *, 8> ParamVarDocs;

714

715 ArrayRef<const ParmVarDecl *> ParamVars = getParamVars();

716 ParamVarDocs.resize(ParamVars.size(), nullptr);

717

718

720 I != E; ++I) {

721 ParamCommandComment *PCC = dyn_cast(*I);

722 if (!PCC || !PCC->hasParamName())

723 continue;

724 StringRef ParamName = PCC->getParamNameAsWritten();

725

726

727 const unsigned ResolvedParamIndex = resolveParmVarReference(ParamName,

728 ParamVars);

730 PCC->setIsVarArgParam();

731 continue;

732 }

734 UnresolvedParamCommands.push_back(PCC);

735 continue;

736 }

737 PCC->setParamIndex(ResolvedParamIndex);

738 if (ParamVarDocs[ResolvedParamIndex]) {

739 SourceRange ArgRange = PCC->getParamNameRange();

740 Diag(ArgRange.getBegin(), diag::warn_doc_param_duplicate)

741 << ParamName << ArgRange;

742 ParamCommandComment *PrevCommand = ParamVarDocs[ResolvedParamIndex];

743 Diag(PrevCommand->getLocation(), diag::note_doc_param_previous)

744 << PrevCommand->getParamNameRange();

745 }

746 ParamVarDocs[ResolvedParamIndex] = PCC;

747 }

748

749

750 SmallVector<const ParmVarDecl *, 8> OrphanedParamDecls;

751 for (unsigned i = 0, e = ParamVarDocs.size(); i != e; ++i) {

752 if (!ParamVarDocs[i])

753 OrphanedParamDecls.push_back(ParamVars[i]);

754 }

755

756

757

758

759 for (unsigned i = 0, e = UnresolvedParamCommands.size(); i != e; ++i) {

760 const ParamCommandComment *PCC = UnresolvedParamCommands[i];

761

762 SourceRange ArgRange = PCC->getParamNameRange();

763 StringRef ParamName = PCC->getParamNameAsWritten();

764 Diag(ArgRange.getBegin(), diag::warn_doc_param_not_found)

765 << ParamName << ArgRange;

766

767

768 if (OrphanedParamDecls.size() == 0)

769 continue;

770

772 if (OrphanedParamDecls.size() == 1) {

773

774

775 CorrectedParamIndex = 0;

776 } else {

777

778 CorrectedParamIndex = correctTypoInParmVarReference(ParamName,

779 OrphanedParamDecls);

780 }

782 const ParmVarDecl *CorrectedPVD = OrphanedParamDecls[CorrectedParamIndex];

783 if (const IdentifierInfo *CorrectedII = CorrectedPVD->getIdentifier())

784 Diag(ArgRange.getBegin(), diag::note_doc_param_name_suggestion)

785 << CorrectedII->getName()

787 }

788 }

789}

790

791bool Sema::involvesFunctionType() {

792 if (!ThisDeclInfo)

793 return false;

795 inspectThisDecl();

797}

798

799bool Sema::isFunctionDecl() {

800 if (!ThisDeclInfo)

801 return false;

803 inspectThisDecl();

805}

806

807bool Sema::isAnyFunctionDecl() {

808 return isFunctionDecl() && ThisDeclInfo->CurrentDecl &&

809 isa(ThisDeclInfo->CurrentDecl);

810}

811

812bool Sema::isFunctionOrMethodVariadic() {

813 if (!ThisDeclInfo)

814 return false;

816 inspectThisDecl();

818}

819

820bool Sema::isObjCMethodDecl() {

821 return isFunctionDecl() && ThisDeclInfo->CurrentDecl &&

822 isa(ThisDeclInfo->CurrentDecl);

823}

824

825bool Sema::isFunctionPointerVarDecl() {

826 if (!ThisDeclInfo)

827 return false;

829 inspectThisDecl();

831 if (const VarDecl *VD = dyn_cast_or_null(ThisDeclInfo->CurrentDecl)) {

832 QualType QT = VD->getType();

833 return QT->isFunctionPointerType();

834 }

835 }

836 return false;

837}

838

839bool Sema::isObjCPropertyDecl() {

840 if (!ThisDeclInfo)

841 return false;

843 inspectThisDecl();

845}

846

847bool Sema::isTemplateOrSpecialization() {

848 if (!ThisDeclInfo)

849 return false;

851 inspectThisDecl();

853}

854

855bool Sema::isRecordLikeDecl() {

856 if (!ThisDeclInfo)

857 return false;

859 inspectThisDecl();

860 return isUnionDecl() || isClassOrStructDecl() || isObjCInterfaceDecl() ||

861 isObjCProtocolDecl();

862}

863

864bool Sema::isUnionDecl() {

865 if (!ThisDeclInfo)

866 return false;

868 inspectThisDecl();

869 if (const RecordDecl *RD =

870 dyn_cast_or_null(ThisDeclInfo->CurrentDecl))

871 return RD->isUnion();

872 return false;

873}

875 if (auto *record = dyn_cast_or_null(D))

876 return !record->isUnion();

877

878 return false;

879}

880

881bool Sema::isClassOrStructDecl() {

882 if (!ThisDeclInfo)

883 return false;

885 inspectThisDecl();

886

888 return false;

889

891}

892

893bool Sema::isClassOrStructOrTagTypedefDecl() {

894 if (!ThisDeclInfo)

895 return false;

897 inspectThisDecl();

898

900 return false;

901

903 return true;

904

905 if (auto *ThisTypedefDecl = dyn_cast(ThisDeclInfo->CurrentDecl)) {

906 auto UnderlyingType = ThisTypedefDecl->getUnderlyingType();

907 if (auto ThisElaboratedType = dyn_cast(UnderlyingType)) {

908 auto DesugaredType = ThisElaboratedType->desugar();

909 if (auto *DesugaredTypePtr = DesugaredType.getTypePtrOrNull()) {

910 if (auto *ThisRecordType = dyn_cast(DesugaredTypePtr)) {

912 }

913 }

914 }

915 }

916

917 return false;

918}

919

920bool Sema::isClassTemplateDecl() {

921 if (!ThisDeclInfo)

922 return false;

924 inspectThisDecl();

926 (isa(ThisDeclInfo->CurrentDecl));

927}

928

929bool Sema::isFunctionTemplateDecl() {

930 if (!ThisDeclInfo)

931 return false;

933 inspectThisDecl();

935 (isa(ThisDeclInfo->CurrentDecl));

936}

937

938bool Sema::isObjCInterfaceDecl() {

939 if (!ThisDeclInfo)

940 return false;

942 inspectThisDecl();

944 isa(ThisDeclInfo->CurrentDecl);

945}

946

947bool Sema::isObjCProtocolDecl() {

948 if (!ThisDeclInfo)

949 return false;

951 inspectThisDecl();

953 isa(ThisDeclInfo->CurrentDecl);

954}

955

956ArrayRef<const ParmVarDecl *> Sema::getParamVars() {

958 inspectThisDecl();

960}

961

962void Sema::inspectThisDecl() {

963 ThisDeclInfo->fill();

964}

965

966unsigned Sema::resolveParmVarReference(StringRef Name,

967 ArrayRef<const ParmVarDecl *> ParamVars) {

968 for (unsigned i = 0, e = ParamVars.size(); i != e; ++i) {

969 const IdentifierInfo *II = ParamVars[i]->getIdentifier();

970 if (II && II->getName() == Name)

971 return i;

972 }

973 if (Name == "..." && isFunctionOrMethodVariadic())

976}

977

978namespace {

979class SimpleTypoCorrector {

980 const NamedDecl *BestDecl;

981

982 StringRef Typo;

983 const unsigned MaxEditDistance;

984

985 unsigned BestEditDistance;

986 unsigned BestIndex;

987 unsigned NextIndex;

988

989public:

990 explicit SimpleTypoCorrector(StringRef Typo)

991 : BestDecl(nullptr), Typo(Typo), MaxEditDistance((Typo.size() + 2) / 3),

992 BestEditDistance(MaxEditDistance + 1), BestIndex(0), NextIndex(0) {}

993

994 void addDecl(const NamedDecl *ND);

995

996 const NamedDecl *getBestDecl() const {

997 if (BestEditDistance > MaxEditDistance)

998 return nullptr;

999

1000 return BestDecl;

1001 }

1002

1003 unsigned getBestDeclIndex() const {

1004 assert(getBestDecl());

1005 return BestIndex;

1006 }

1007};

1008

1009void SimpleTypoCorrector::addDecl(const NamedDecl *ND) {

1010 unsigned CurrIndex = NextIndex++;

1011

1012 const IdentifierInfo *II = ND->getIdentifier();

1013 if (!II)

1014 return;

1015

1016 StringRef Name = II->getName();

1017 unsigned MinPossibleEditDistance = abs((int)Name.size() - (int)Typo.size());

1018 if (MinPossibleEditDistance > 0 &&

1019 Typo.size() / MinPossibleEditDistance < 3)

1020 return;

1021

1022 unsigned EditDistance = Typo.edit_distance(Name, true, MaxEditDistance);

1023 if (EditDistance < BestEditDistance) {

1024 BestEditDistance = EditDistance;

1025 BestDecl = ND;

1026 BestIndex = CurrIndex;

1027 }

1028}

1029}

1030

1031unsigned Sema::correctTypoInParmVarReference(

1032 StringRef Typo,

1033 ArrayRef<const ParmVarDecl *> ParamVars) {

1034 SimpleTypoCorrector Corrector(Typo);

1035 for (unsigned i = 0, e = ParamVars.size(); i != e; ++i)

1036 Corrector.addDecl(ParamVars[i]);

1037 if (Corrector.getBestDecl())

1038 return Corrector.getBestDeclIndex();

1039 else

1041}

1042

1043namespace {

1044bool ResolveTParamReferenceHelper(

1045 StringRef Name,

1046 const TemplateParameterList *TemplateParameters,

1047 SmallVectorImpl *Position) {

1048 for (unsigned i = 0, e = TemplateParameters->size(); i != e; ++i) {

1049 const NamedDecl *Param = TemplateParameters->getParam(i);

1050 const IdentifierInfo *II = Param->getIdentifier();

1051 if (II && II->getName() == Name) {

1052 Position->push_back(i);

1053 return true;

1054 }

1055

1056 if (const TemplateTemplateParmDecl *TTP =

1057 dyn_cast(Param)) {

1058 Position->push_back(i);

1059 if (ResolveTParamReferenceHelper(Name, TTP->getTemplateParameters(),

1060 Position))

1061 return true;

1062 Position->pop_back();

1063 }

1064 }

1065 return false;

1066}

1067}

1068

1069bool Sema::resolveTParamReference(

1070 StringRef Name,

1071 const TemplateParameterList *TemplateParameters,

1072 SmallVectorImpl *Position) {

1073 Position->clear();

1074 if (!TemplateParameters)

1075 return false;

1076

1077 return ResolveTParamReferenceHelper(Name, TemplateParameters, Position);

1078}

1079

1080namespace {

1081void CorrectTypoInTParamReferenceHelper(

1082 const TemplateParameterList *TemplateParameters,

1083 SimpleTypoCorrector &Corrector) {

1084 for (unsigned i = 0, e = TemplateParameters->size(); i != e; ++i) {

1085 const NamedDecl *Param = TemplateParameters->getParam(i);

1086 Corrector.addDecl(Param);

1087

1088 if (const TemplateTemplateParmDecl *TTP =

1089 dyn_cast(Param))

1090 CorrectTypoInTParamReferenceHelper(TTP->getTemplateParameters(),

1091 Corrector);

1092 }

1093}

1094}

1095

1096StringRef Sema::correctTypoInTParamReference(

1097 StringRef Typo,

1098 const TemplateParameterList *TemplateParameters) {

1099 SimpleTypoCorrector Corrector(Typo);

1100 CorrectTypoInTParamReferenceHelper(TemplateParameters, Corrector);

1101 if (const NamedDecl *ND = Corrector.getBestDecl()) {

1102 const IdentifierInfo *II = ND->getIdentifier();

1103 assert(II && "SimpleTypoCorrector should not return this decl");

1104 return II->getName();

1105 }

1106 return StringRef();

1107}

1108

1111

1112 return llvm::StringSwitch(Name)

1118}

1119

1120}

1121}

Defines the C++ template declaration subclasses.

Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.

Defines the clang::Preprocessor interface.

Defines the SourceManager interface.

__DEVICE__ long long abs(long long __n)

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

Concrete class used by the front-end to report problems and issues.

static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)

Create a code modification hint that replaces the given source range with the given code string.

static FixItHint CreateInsertion(SourceLocation InsertionLoc, StringRef Code, bool BeforePreviousInsertions=false)

Create a code modification hint that inserts the given code string at a specific location.

One of these records is kept for each identifier that is lexed.

StringRef getName() const

Return the actual identifier string.

This represents a decl that may have a name.

IdentifierInfo * getIdentifier() const

Get the identifier that names this declaration, if there is one.

Engages in a tight little dance with the lexer to efficiently preprocess tokens.

IdentifierInfo * getIdentifierInfo(StringRef Name) const

Return information about the specified preprocessor identifier token.

StringRef getLastMacroWithSpelling(SourceLocation Loc, ArrayRef< TokenValue > Tokens) const

Return the name of the macro defined before Loc that has spelling Tokens.

bool isNull() const

Return true if this QualType doesn't point to a type yet.

Encodes a location in the source.

bool isValid() const

Return true if this is a valid SourceLocation object.

SourceLocation getLocWithOffset(IntTy Offset) const

Return a source location with the specified offset from this SourceLocation.

This class handles loading and caching of source files into memory.

unsigned getPresumedLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const

A trivial tuple used to represent a source range.

SourceLocation getEnd() const

Stores a list of template parameters for a TemplateDecl and its derived classes.

NamedDecl * getParam(unsigned Idx)

Inline content (contained within a block).

@ Decl

The l-value was an access to a declared entity or something equivalently strong, like the address of ...

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

LLVM_READONLY bool isWhitespace(unsigned char c)

Return true if this character is horizontal or vertical ASCII whitespace: ' ', '\t',...