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

1

2

3

4

5

6

7

8

13#include "llvm/ADT/StringExtras.h"

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

15#include "llvm/Support/ConvertUTF.h"

16#include "llvm/Support/ErrorHandling.h"

17

19namespace comments {

20

22 llvm::errs() << "comments::Token Kind=" << Kind << " ";

23 Loc.print(llvm::errs(), SM);

24 llvm::errs() << " " << Length << " \"" << L.getSpelling(*this, SM) << "\"\n";

25}

26

29}

30

33}

34

37}

38

40 llvm::BumpPtrAllocator &Allocator,

41 unsigned CodePoint) {

42 char *Resolved = Allocator.Allocate<char>(UNI_MAX_UTF8_BYTES_PER_CODE_POINT);

43 char *ResolvedPtr = Resolved;

44 if (llvm::ConvertCodePointToUTF8(CodePoint, ResolvedPtr))

45 return StringRef(Resolved, ResolvedPtr - Resolved);

46 else

47 return StringRef();

48}

49

50namespace {

51

52#include "clang/AST/CommentHTMLTags.inc"

53#include "clang/AST/CommentHTMLNamedCharacterReferences.inc"

54

55}

56

57StringRef Lexer::resolveHTMLNamedCharacterReference(StringRef Name) const {

58

59 return llvm::StringSwitch(Name)

60 .Case("amp", "&")

61 .Case("lt", "<")

62 .Case("gt", ">")

63 .Case("quot", "\"")

64 .Case("apos", "\'")

65

66 .Default(translateHTMLNamedCharacterReferenceToUTF8(Name));

67}

68

69StringRef Lexer::resolveHTMLDecimalCharacterReference(StringRef Name) const {

70 unsigned CodePoint = 0;

71 for (unsigned i = 0, e = Name.size(); i != e; ++i) {

73 CodePoint *= 10;

74 CodePoint += Name[i] - '0';

75 }

77}

78

79StringRef Lexer::resolveHTMLHexCharacterReference(StringRef Name) const {

80 unsigned CodePoint = 0;

81 for (unsigned i = 0, e = Name.size(); i != e; ++i) {

82 CodePoint *= 16;

83 const char C = Name[i];

85 CodePoint += llvm::hexDigitValue(C);

86 }

88}

89

90void Lexer::skipLineStartingDecorations() {

91

92 assert(CommentState == LCS_InsideCComment);

93

94 if (BufferPtr == CommentEnd)

95 return;

96

97 const char *NewBufferPtr = BufferPtr;

99 if (++NewBufferPtr == CommentEnd)

100 return;

101 if (*NewBufferPtr == '*')

102 BufferPtr = NewBufferPtr + 1;

103}

104

105namespace {

106

107const char *findNewline(const char *BufferPtr, const char *BufferEnd) {

108 for ( ; BufferPtr != BufferEnd; ++BufferPtr) {

110 return BufferPtr;

111 }

112 return BufferEnd;

113}

114

115const char *skipNewline(const char *BufferPtr, const char *BufferEnd) {

116 if (BufferPtr == BufferEnd)

117 return BufferPtr;

118

119 if (*BufferPtr == '\n')

120 BufferPtr++;

121 else {

122 assert(*BufferPtr == '\r');

123 BufferPtr++;

124 if (BufferPtr != BufferEnd && *BufferPtr == '\n')

125 BufferPtr++;

126 }

127 return BufferPtr;

128}

129

130const char *skipNamedCharacterReference(const char *BufferPtr,

131 const char *BufferEnd) {

132 for ( ; BufferPtr != BufferEnd; ++BufferPtr) {

134 return BufferPtr;

135 }

136 return BufferEnd;

137}

138

139const char *skipDecimalCharacterReference(const char *BufferPtr,

140 const char *BufferEnd) {

141 for ( ; BufferPtr != BufferEnd; ++BufferPtr) {

143 return BufferPtr;

144 }

145 return BufferEnd;

146}

147

148const char *skipHexCharacterReference(const char *BufferPtr,

149 const char *BufferEnd) {

150 for ( ; BufferPtr != BufferEnd; ++BufferPtr) {

152 return BufferPtr;

153 }

154 return BufferEnd;

155}

156

157bool isHTMLIdentifierStartingCharacter(char C) {

159}

160

161bool isHTMLIdentifierCharacter(char C) {

163}

164

165const char *skipHTMLIdentifier(const char *BufferPtr, const char *BufferEnd) {

166 for ( ; BufferPtr != BufferEnd; ++BufferPtr) {

167 if (!isHTMLIdentifierCharacter(*BufferPtr))

168 return BufferPtr;

169 }

170 return BufferEnd;

171}

172

173

174

175

176

177const char *skipHTMLQuotedString(const char *BufferPtr, const char *BufferEnd)

178{

179 const char Quote = *BufferPtr;

180 assert(Quote == '\"' || Quote == '\'');

181

182 BufferPtr++;

183 for ( ; BufferPtr != BufferEnd; ++BufferPtr) {

184 const char C = *BufferPtr;

185 if (C == Quote && BufferPtr[-1] != '\\')

186 return BufferPtr;

187 }

188 return BufferEnd;

189}

190

191const char *skipWhitespace(const char *BufferPtr, const char *BufferEnd) {

192 for ( ; BufferPtr != BufferEnd; ++BufferPtr) {

194 return BufferPtr;

195 }

196 return BufferEnd;

197}

198

199bool isWhitespace(const char *BufferPtr, const char *BufferEnd) {

200 return skipWhitespace(BufferPtr, BufferEnd) == BufferEnd;

201}

202

203bool isCommandNameStartCharacter(char C) {

205}

206

207bool isCommandNameCharacter(char C) {

209}

210

211const char *skipCommandName(const char *BufferPtr, const char *BufferEnd) {

212 for ( ; BufferPtr != BufferEnd; ++BufferPtr) {

213 if (!isCommandNameCharacter(*BufferPtr))

214 return BufferPtr;

215 }

216 return BufferEnd;

217}

218

219

220

221const char *findBCPLCommentEnd(const char *BufferPtr, const char *BufferEnd) {

222 const char *CurPtr = BufferPtr;

223 while (CurPtr != BufferEnd) {

225 CurPtr++;

226 if (CurPtr == BufferEnd)

227 return BufferEnd;

228 }

229

230 const char *EscapePtr = CurPtr - 1;

232 EscapePtr--;

233

234 if (*EscapePtr == '\\' ||

235 (EscapePtr - 2 >= BufferPtr && EscapePtr[0] == '/' &&

236 EscapePtr[-1] == '?' && EscapePtr[-2] == '?')) {

237

239 } else

240 return CurPtr;

241 }

242 return BufferEnd;

243}

244

245

246

247const char *findCCommentEnd(const char *BufferPtr, const char *BufferEnd) {

248 for ( ; BufferPtr != BufferEnd; ++BufferPtr) {

249 if (*BufferPtr == '*') {

250 assert(BufferPtr + 1 != BufferEnd);

251 if (*(BufferPtr + 1) == '/')

252 return BufferPtr;

253 }

254 }

255 llvm_unreachable("buffer end hit before '*/' was seen");

256}

257

258}

259

260void Lexer::formTokenWithChars(Token &Result, const char *TokEnd,

262 const unsigned TokLen = TokEnd - BufferPtr;

263 Result.setLocation(getSourceLocation(BufferPtr));

265 Result.setLength(TokLen);

266#ifndef NDEBUG

267 Result.TextPtr = "";

269#endif

270 BufferPtr = TokEnd;

271}

272

273const char *Lexer::skipTextToken() {

274 const char *TokenPtr = BufferPtr;

275 assert(TokenPtr < CommentEnd);

276 StringRef TokStartSymbols = ParseCommands ? "\n\r\\@\"&<" : "\n\r";

277

278again:

279 size_t End =

280 StringRef(TokenPtr, CommentEnd - TokenPtr).find_first_of(TokStartSymbols);

281 if (End == StringRef::npos)

282 return CommentEnd;

283

284

285

286 if (*(TokenPtr + End) == '\"') {

287 TokenPtr += End + 1;

288 End = StringRef(TokenPtr, CommentEnd - TokenPtr).find_first_of("\n\r\"");

289 if (End != StringRef::npos && *(TokenPtr + End) == '\"')

290 TokenPtr += End + 1;

291 goto again;

292 }

293 return TokenPtr + End;

294}

295

296void Lexer::lexCommentText(Token &T) {

297 assert(CommentState == LCS_InsideBCPLComment ||

298 CommentState == LCS_InsideCComment);

299

300

301 auto HandleNonCommandToken = [&]() -> void {

302 assert(State == LS_Normal);

303

304 const char *TokenPtr = BufferPtr;

305 assert(TokenPtr < CommentEnd);

306 switch (*TokenPtr) {

307 case '\n':

308 case '\r':

309 TokenPtr = skipNewline(TokenPtr, CommentEnd);

311

312 if (CommentState == LCS_InsideCComment)

313 skipLineStartingDecorations();

314 return;

315

316 default:

317 return formTextToken(T, skipTextToken());

318 }

319 };

320

321 if (!ParseCommands)

322 return HandleNonCommandToken();

323

324 switch (State) {

325 case LS_Normal:

326 break;

327 case LS_VerbatimBlockFirstLine:

328 lexVerbatimBlockFirstLine(T);

329 return;

330 case LS_VerbatimBlockBody:

331 lexVerbatimBlockBody(T);

332 return;

333 case LS_VerbatimLineText:

334 lexVerbatimLineText(T);

335 return;

336 case LS_HTMLStartTag:

337 lexHTMLStartTag(T);

338 return;

339 case LS_HTMLEndTag:

340 lexHTMLEndTag(T);

341 return;

342 }

343

344 assert(State == LS_Normal);

345 const char *TokenPtr = BufferPtr;

346 assert(TokenPtr < CommentEnd);

347 switch(*TokenPtr) {

348 case '\\':

349 case '@': {

350

351

352

355 TokenPtr++;

356 if (TokenPtr == CommentEnd) {

357 formTextToken(T, TokenPtr);

358 return;

359 }

360 char C = *TokenPtr;

361 switch (C) {

362 default:

363 break;

364

365 case '\\': case '@': case '&': case '$':

366 case '#': case '<': case '>': case '%':

367 case '\"': case '.': case ':':

368

369 TokenPtr++;

370 if (C == ':' && TokenPtr != CommentEnd && *TokenPtr == ':') {

371

372 TokenPtr++;

373 }

374 StringRef UnescapedText(BufferPtr + 1, TokenPtr - (BufferPtr + 1));

375 formTokenWithChars(T, TokenPtr, tok::text);

376 T.setText(UnescapedText);

377 return;

378 }

379

380

381 if (!isCommandNameStartCharacter(*TokenPtr)) {

382 formTextToken(T, TokenPtr);

383 return;

384 }

385

386 TokenPtr = skipCommandName(TokenPtr, CommentEnd);

387 unsigned Length = TokenPtr - (BufferPtr + 1);

388

389

390

391 if (Length == 1 && TokenPtr[-1] == 'f' && TokenPtr != CommentEnd) {

392 C = *TokenPtr;

393 if (C == '$' || C == '(' || C == ')' || C == '[' || C == ']' ||

394 C == '{' || C == '}') {

395 TokenPtr++;

396 Length++;

397 }

398 }

399

400 StringRef CommandName(BufferPtr + 1, Length);

401

403 if (!Info) {

405 StringRef CorrectedName = Info->Name;

406 SourceLocation Loc = getSourceLocation(BufferPtr);

407 SourceLocation EndLoc = getSourceLocation(TokenPtr);

408 SourceRange FullRange = SourceRange(Loc, EndLoc);

409 SourceRange CommandRange(Loc.getLocWithOffset(1), EndLoc);

410 Diag(Loc, diag::warn_correct_comment_command_name)

411 << FullRange << CommandName << CorrectedName

413 } else {

415 T.setUnknownCommandName(CommandName);

416 Diag(T.getLocation(), diag::warn_unknown_comment_command_name)

417 << SourceRange(T.getLocation(), T.getEndLocation());

418 return;

419 }

420 }

421 if (Info->IsVerbatimBlockCommand) {

422 setupAndLexVerbatimBlock(T, TokenPtr, *BufferPtr, Info);

423 return;

424 }

425 if (Info->IsVerbatimLineCommand) {

426 setupAndLexVerbatimLine(T, TokenPtr, Info);

427 return;

428 }

429 formTokenWithChars(T, TokenPtr, CommandKind);

430 T.setCommandID(Info->getID());

431 return;

432 }

433

434 case '&':

435 lexHTMLCharacterReference(T);

436 return;

437

438 case '<': {

439 TokenPtr++;

440 if (TokenPtr == CommentEnd) {

441 formTextToken(T, TokenPtr);

442 return;

443 }

444 const char C = *TokenPtr;

445 if (isHTMLIdentifierStartingCharacter(C))

446 setupAndLexHTMLStartTag(T);

447 else if (C == '/')

448 setupAndLexHTMLEndTag(T);

449 else

450 formTextToken(T, TokenPtr);

451 return;

452 }

453

454 default:

455 return HandleNonCommandToken();

456 }

457}

458

459void Lexer::setupAndLexVerbatimBlock(Token &T,

460 const char *TextBegin,

461 char Marker, const CommandInfo *Info) {

462 assert(Info->IsVerbatimBlockCommand);

463

464 VerbatimBlockEndCommandName.clear();

465 VerbatimBlockEndCommandName.append(Marker == '\\' ? "\\" : "@");

466 VerbatimBlockEndCommandName.append(Info->EndCommandName);

467

469 T.setVerbatimBlockID(Info->getID());

470

471

472

473

474 if (BufferPtr != CommentEnd &&

476 BufferPtr = skipNewline(BufferPtr, CommentEnd);

477 State = LS_VerbatimBlockBody;

478 return;

479 }

480

481 State = LS_VerbatimBlockFirstLine;

482}

483

484void Lexer::lexVerbatimBlockFirstLine(Token &T) {

485again:

486 assert(BufferPtr < CommentEnd);

487

488

489

490

491

492 const char *Newline = findNewline(BufferPtr, CommentEnd);

493 StringRef Line(BufferPtr, Newline - BufferPtr);

494

495

496 size_t Pos = Line.find(VerbatimBlockEndCommandName);

497 const char *TextEnd;

498 const char *NextLine;

499 if (Pos == StringRef::npos) {

500

501 TextEnd = Newline;

502 NextLine = skipNewline(Newline, CommentEnd);

503 } else if (Pos == 0) {

504

505 const char *End = BufferPtr + VerbatimBlockEndCommandName.size();

506 StringRef Name(BufferPtr + 1, End - (BufferPtr + 1));

509 State = LS_Normal;

510 return;

511 } else {

512

513 TextEnd = BufferPtr + Pos;

514 NextLine = TextEnd;

515

517 BufferPtr = TextEnd;

518 goto again;

519 }

520 }

521

522 StringRef Text(BufferPtr, TextEnd - BufferPtr);

524 T.setVerbatimBlockText(Text);

525

526 State = LS_VerbatimBlockBody;

527}

528

529void Lexer::lexVerbatimBlockBody(Token &T) {

530 assert(State == LS_VerbatimBlockBody);

531

532 if (CommentState == LCS_InsideCComment)

533 skipLineStartingDecorations();

534

535 if (BufferPtr == CommentEnd) {

537 T.setVerbatimBlockText("");

538 return;

539 }

540

541 lexVerbatimBlockFirstLine(T);

542}

543

544void Lexer::setupAndLexVerbatimLine(Token &T, const char *TextBegin,

545 const CommandInfo *Info) {

546 assert(Info->IsVerbatimLineCommand);

548 T.setVerbatimLineID(Info->getID());

549

550 State = LS_VerbatimLineText;

551}

552

553void Lexer::lexVerbatimLineText(Token &T) {

554 assert(State == LS_VerbatimLineText);

555

556

557 const char *Newline = findNewline(BufferPtr, CommentEnd);

558 StringRef Text(BufferPtr, Newline - BufferPtr);

560 T.setVerbatimLineText(Text);

561

562 State = LS_Normal;

563}

564

565void Lexer::lexHTMLCharacterReference(Token &T) {

566 const char *TokenPtr = BufferPtr;

567 assert(*TokenPtr == '&');

568 TokenPtr++;

569 if (TokenPtr == CommentEnd) {

570 formTextToken(T, TokenPtr);

571 return;

572 }

573 const char *NamePtr;

575 bool isDecimal = false;

576 char C = *TokenPtr;

578 NamePtr = TokenPtr;

579 TokenPtr = skipNamedCharacterReference(TokenPtr, CommentEnd);

581 } else if (C == '#') {

582 TokenPtr++;

583 if (TokenPtr == CommentEnd) {

584 formTextToken(T, TokenPtr);

585 return;

586 }

587 C = *TokenPtr;

589 NamePtr = TokenPtr;

590 TokenPtr = skipDecimalCharacterReference(TokenPtr, CommentEnd);

591 isDecimal = true;

592 } else if (C == 'x' || C == 'X') {

593 TokenPtr++;

594 NamePtr = TokenPtr;

595 TokenPtr = skipHexCharacterReference(TokenPtr, CommentEnd);

596 } else {

597 formTextToken(T, TokenPtr);

598 return;

599 }

600 } else {

601 formTextToken(T, TokenPtr);

602 return;

603 }

604 if (NamePtr == TokenPtr || TokenPtr == CommentEnd ||

605 *TokenPtr != ';') {

606 formTextToken(T, TokenPtr);

607 return;

608 }

609 StringRef Name(NamePtr, TokenPtr - NamePtr);

610 TokenPtr++;

611 StringRef Resolved;

613 Resolved = resolveHTMLNamedCharacterReference(Name);

614 else if (isDecimal)

615 Resolved = resolveHTMLDecimalCharacterReference(Name);

616 else

617 Resolved = resolveHTMLHexCharacterReference(Name);

618

619 if (Resolved.empty()) {

620 formTextToken(T, TokenPtr);

621 return;

622 }

623 formTokenWithChars(T, TokenPtr, tok::text);

624 T.setText(Resolved);

625}

626

627void Lexer::setupAndLexHTMLStartTag(Token &T) {

628 assert(BufferPtr[0] == '<' &&

629 isHTMLIdentifierStartingCharacter(BufferPtr[1]));

630 const char *TagNameEnd = skipHTMLIdentifier(BufferPtr + 2, CommentEnd);

631 StringRef Name(BufferPtr + 1, TagNameEnd - (BufferPtr + 1));

632 if (!isHTMLTagName(Name)) {

633 formTextToken(T, TagNameEnd);

634 return;

635 }

636

638 T.setHTMLTagStartName(Name);

639

641

642 const char C = *BufferPtr;

643 if (BufferPtr != CommentEnd &&

644 (C == '>' || C == '/' || isHTMLIdentifierStartingCharacter(C)))

645 State = LS_HTMLStartTag;

646}

647

648void Lexer::lexHTMLStartTag(Token &T) {

649 assert(State == LS_HTMLStartTag);

650

651 const char *TokenPtr = BufferPtr;

652 char C = *TokenPtr;

653 if (isHTMLIdentifierCharacter(C)) {

654 TokenPtr = skipHTMLIdentifier(TokenPtr, CommentEnd);

655 StringRef Ident(BufferPtr, TokenPtr - BufferPtr);

657 T.setHTMLIdent(Ident);

658 } else {

659 switch (C) {

660 case '=':

661 TokenPtr++;

663 break;

664 case '\"':

665 case '\'': {

666 const char *OpenQuote = TokenPtr;

667 TokenPtr = skipHTMLQuotedString(TokenPtr, CommentEnd);

668 const char *ClosingQuote = TokenPtr;

669 if (TokenPtr != CommentEnd)

670 TokenPtr++;

672 T.setHTMLQuotedString(StringRef(OpenQuote + 1,

673 ClosingQuote - (OpenQuote + 1)));

674 break;

675 }

676 case '>':

677 TokenPtr++;

679 State = LS_Normal;

680 return;

681 case '/':

682 TokenPtr++;

683 if (TokenPtr != CommentEnd && *TokenPtr == '>') {

684 TokenPtr++;

686 } else

687 formTextToken(T, TokenPtr);

688

689 State = LS_Normal;

690 return;

691 }

692 }

693

694

695

697 if (BufferPtr == CommentEnd) {

698 State = LS_Normal;

699 return;

700 }

701

702 C = *BufferPtr;

703 if (!isHTMLIdentifierStartingCharacter(C) &&

704 C != '=' && C != '\"' && C != '\'' && C != '>' && C != '/') {

705 State = LS_Normal;

706 return;

707 }

708}

709

710void Lexer::setupAndLexHTMLEndTag(Token &T) {

711 assert(BufferPtr[0] == '<' && BufferPtr[1] == '/');

712

713 const char *TagNameBegin = skipWhitespace(BufferPtr + 2, CommentEnd);

714 const char *TagNameEnd = skipHTMLIdentifier(TagNameBegin, CommentEnd);

715 StringRef Name(TagNameBegin, TagNameEnd - TagNameBegin);

716 if (!isHTMLTagName(Name)) {

717 formTextToken(T, TagNameEnd);

718 return;

719 }

720

721 const char *End = skipWhitespace(TagNameEnd, CommentEnd);

722

724 T.setHTMLTagEndName(Name);

725

726 if (BufferPtr != CommentEnd && *BufferPtr == '>')

727 State = LS_HTMLEndTag;

728}

729

730void Lexer::lexHTMLEndTag(Token &T) {

731 assert(BufferPtr != CommentEnd && *BufferPtr == '>');

732

734 State = LS_Normal;

735}

736

739 const char *BufferStart, const char *BufferEnd, bool ParseCommands)

740 : Allocator(Allocator), Diags(Diags), Traits(Traits),

741 BufferStart(BufferStart), BufferEnd(BufferEnd), BufferPtr(BufferStart),

742 FileLoc(FileLoc), ParseCommands(ParseCommands),

743 CommentState(LCS_BeforeComment), State(LS_Normal) {}

744

746again:

747 switch (CommentState) {

748 case LCS_BeforeComment:

749 if (BufferPtr == BufferEnd) {

750 formTokenWithChars(T, BufferPtr, tok::eof);

751 return;

752 }

753

754 assert(*BufferPtr == '/');

755 BufferPtr++;

756 switch(*BufferPtr) {

757 case '/': {

758 BufferPtr++;

759

760 if (BufferPtr != BufferEnd) {

761

762

763

764

765 const char C = *BufferPtr;

766 if (C == '/' || C == '!')

767 BufferPtr++;

768 }

769

770

771

772

773 if (BufferPtr != BufferEnd && *BufferPtr == '<')

774 BufferPtr++;

775

776 CommentState = LCS_InsideBCPLComment;

777 if (State != LS_VerbatimBlockBody && State != LS_VerbatimBlockFirstLine)

778 State = LS_Normal;

779 CommentEnd = findBCPLCommentEnd(BufferPtr, BufferEnd);

780 goto again;

781 }

782 case '*': {

783 BufferPtr++;

784

785

786 const char C = *BufferPtr;

787 if ((C == '*' && *(BufferPtr + 1) != '/') || C == '!')

788 BufferPtr++;

789

790

791 if (BufferPtr != BufferEnd && *BufferPtr == '<')

792 BufferPtr++;

793

794 CommentState = LCS_InsideCComment;

795 State = LS_Normal;

796 CommentEnd = findCCommentEnd(BufferPtr, BufferEnd);

797 goto again;

798 }

799 default:

800 llvm_unreachable("second character of comment should be '/' or '*'");

801 }

802

803 case LCS_BetweenComments: {

804

805

806 const char *EndWhitespace = BufferPtr;

807 while(EndWhitespace != BufferEnd && *EndWhitespace != '/')

808 EndWhitespace++;

809

810

811

812

813

814 formTokenWithChars(T, EndWhitespace, tok::newline);

815

816 CommentState = LCS_BeforeComment;

817 break;

818 }

819

820 case LCS_InsideBCPLComment:

821 case LCS_InsideCComment:

822 if (BufferPtr != CommentEnd) {

823 lexCommentText(T);

824 break;

825 } else {

826

827 if (CommentState == LCS_InsideCComment) {

828 assert(BufferPtr[0] == '*' && BufferPtr[1] == '/');

829 BufferPtr += 2;

830 assert(BufferPtr <= BufferEnd);

831

832

833

835

836 CommentState = LCS_BetweenComments;

837 break;

838 } else {

839

840 CommentState = LCS_BetweenComments;

841 goto again;

842 }

843 }

844 }

845}

846

851

852 bool InvalidTemp = false;

853 StringRef File = SourceMgr.getBufferData(LocInfo.first, &InvalidTemp);

854 if (InvalidTemp)

855 return StringRef();

856

857 const char *Begin = File.data() + LocInfo.second;

859}

860

861}

862}

enum clang::sema::@1727::IndirectLocalPathEntry::EntryKind Kind

static bool isNamed(const NamedDecl *ND, const char(&Str)[Len])

static unsigned skipNewline(const char *&First, const char *End)

static unsigned skipWhitespace(unsigned Idx, StringRef Str, unsigned Length)

Skip over whitespace in the string, starting at the given index.

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.

Encodes a location in the source.

void print(raw_ostream &OS, const SourceManager &SM) const

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

StringRef getBufferData(FileID FID, bool *Invalid=nullptr) const

Return a StringRef to the source buffer data for the specified FileID.

std::pair< FileID, unsigned > getDecomposedLoc(SourceLocation Loc) const

Decompose the specified location into a raw FileID + Offset pair.

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

LLVM_READONLY bool isVerticalWhitespace(unsigned char c)

Returns true if this character is vertical ASCII whitespace: '\n', '\r'.

LLVM_READONLY bool isLetter(unsigned char c)

Return true if this character is an ASCII letter: [a-zA-Z].

LLVM_READONLY bool isAlphanumeric(unsigned char c)

Return true if this character is an ASCII letter or digit: [a-zA-Z0-9].

LLVM_READONLY bool isHorizontalWhitespace(unsigned char c)

Returns true if this character is horizontal ASCII whitespace: ' ', '\t', '\f', '\v'.

@ Result

The result type of a method or function.

LLVM_READONLY bool isDigit(unsigned char c)

Return true if this character is an ASCII digit: [0-9].

LLVM_READONLY bool isWhitespace(unsigned char c)

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

LLVM_READONLY bool isHexDigit(unsigned char c)

Return true if this character is an ASCII hex digit: [0-9a-fA-F].

const FunctionProtoType * T