clang: lib/Lex/PPMacroExpansion.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

34#include "llvm/ADT/ArrayRef.h"

35#include "llvm/ADT/DenseMap.h"

36#include "llvm/ADT/DenseSet.h"

37#include "llvm/ADT/FoldingSet.h"

38#include "llvm/ADT/STLExtras.h"

39#include "llvm/ADT/SmallVector.h"

40#include "llvm/ADT/StringRef.h"

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

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

43#include "llvm/Support/Format.h"

44#include "llvm/Support/Path.h"

45#include "llvm/Support/raw_ostream.h"

46#include

47#include

48#include

49#include

50#include

51#include

52#include

53#include

54#include

55#include

56#include

57

58using namespace clang;

59

63 return nullptr;

64 auto Pos = CurSubmoduleState->Macros.find(II);

65 return Pos == CurSubmoduleState->Macros.end() ? nullptr

66 : Pos->second.getLatest();

67}

68

70 assert(MD && "MacroDirective should be non-zero!");

71 assert(!MD->getPrevious() && "Already attached to a MacroDirective history.");

72

73 MacroState &StoredMD = CurSubmoduleState->Macros[II];

74 auto *OldMD = StoredMD.getLatest();

76 StoredMD.setLatest(MD);

77 StoredMD.overrideActiveModuleMacros(*this, II);

78

79 if (needModuleMacros()) {

80

81

82

83 PendingModuleMacroNames.push_back(II);

84 }

85

86

88 if (!MD->isDefined() && !LeafModuleMacros.contains(II))

92}

93

97

98

99

100

101

102

103

104

105

106 assert(II && MD);

107 MacroState &StoredMD = CurSubmoduleState->Macros[II];

108

109 if (auto *OldMD = StoredMD.getLatest()) {

110

111

112

113

114

115 assert(OldMD->getMacroInfo()->isBuiltinMacro() &&

116 "only built-ins should have an entry here");

117 assert(!OldMD->getPrevious() && "builtin should only have a single entry");

119 StoredMD.setLatest(MD);

120 } else {

121 StoredMD = MD;

122 }

123

124

126 if (!MD->isDefined() && !LeafModuleMacros.contains(II))

128}

129

133 bool &New) {

134 llvm::FoldingSetNodeID ID;

136

137 void *InsertPos;

138 if (auto *MM = ModuleMacros.FindNodeOrInsertPos(ID, InsertPos)) {

139 New = false;

140 return MM;

141 }

142

144 ModuleMacros.InsertNode(MM, InsertPos);

145

146

147 bool HidAny = false;

148 for (auto *O : Overrides) {

149 HidAny |= (O->NumOverriddenBy == 0);

150 ++O->NumOverriddenBy;

151 }

152

153

154 auto &LeafMacros = LeafModuleMacros[II];

155 if (HidAny) {

156 llvm::erase_if(LeafMacros,

157 [](ModuleMacro *MM) { return MM->NumOverriddenBy != 0; });

158 }

159

160

161 LeafMacros.push_back(MM);

162

164

165 New = true;

166 return MM;

167}

168

171 llvm::FoldingSetNodeID ID;

173

174 void *InsertPos;

175 return ModuleMacros.FindNodeOrInsertPos(ID, InsertPos);

176}

177

178void Preprocessor::updateModuleMacroInfo(const IdentifierInfo *II,

179 ModuleMacroInfo &Info) {

180 assert(Info.ActiveModuleMacrosGeneration !=

181 CurSubmoduleState->VisibleModules.getGeneration() &&

182 "don't need to update this macro name info");

183 Info.ActiveModuleMacrosGeneration =

184 CurSubmoduleState->VisibleModules.getGeneration();

185

186 auto Leaf = LeafModuleMacros.find(II);

187 if (Leaf == LeafModuleMacros.end()) {

188

189 return;

190 }

191

192 Info.ActiveModuleMacros.clear();

193

194

195 llvm::DenseMap<ModuleMacro *, int> NumHiddenOverrides;

196 for (auto *O : Info.OverriddenMacros)

197 NumHiddenOverrides[O] = -1;

198

199

201 for (auto *LeafMM : Leaf->second) {

202 assert(LeafMM->getNumOverridingMacros() == 0 && "leaf macro overridden");

203 if (NumHiddenOverrides.lookup(LeafMM) == 0)

204 Worklist.push_back(LeafMM);

205 }

206 while (!Worklist.empty()) {

207 auto *MM = Worklist.pop_back_val();

208 if (CurSubmoduleState->VisibleModules.isVisible(MM->getOwningModule())) {

209

210

211 if (MM->getMacroInfo())

212 Info.ActiveModuleMacros.push_back(MM);

213 } else {

214 for (auto *O : MM->overrides())

215 if ((unsigned)++NumHiddenOverrides[O] == O->getNumOverridingMacros())

216 Worklist.push_back(O);

217 }

218 }

219

220 std::reverse(Info.ActiveModuleMacros.begin(), Info.ActiveModuleMacros.end());

221

222

224 bool IsSystemMacro = true;

225 bool IsAmbiguous = false;

226 if (auto *MD = Info.MD) {

227 while (isa_and_nonnull(MD))

228 MD = MD->getPrevious();

229 if (auto *DMD = dyn_cast_or_null(MD)) {

230 MI = DMD->getInfo();

231 IsSystemMacro &= SourceMgr.isInSystemHeader(DMD->getLocation());

232 }

233 }

234 for (auto *Active : Info.ActiveModuleMacros) {

235 auto *NewMI = Active->getMacroInfo();

236

237

238

239

240

241

242

243

244

245

246 if (MI && NewMI != MI &&

247 !MI->isIdenticalTo(*NewMI, *this, true))

248 IsAmbiguous = true;

249 IsSystemMacro &= Active->getOwningModule()->IsSystem ||

251 MI = NewMI;

252 }

253 Info.IsAmbiguous = IsAmbiguous && !IsSystemMacro;

254}

255

258 auto LeafIt = LeafModuleMacros.find(II);

259 if (LeafIt != LeafModuleMacros.end())

260 Leaf = LeafIt->second;

261 const MacroState *State = nullptr;

262 auto Pos = CurSubmoduleState->Macros.find(II);

263 if (Pos != CurSubmoduleState->Macros.end())

264 State = &Pos->second;

265

266 llvm::errs() << "MacroState " << State << " " << II->getNameStart();

267 if (State && State->isAmbiguous(*this, II))

268 llvm::errs() << " ambiguous";

269 if (State && !State->getOverriddenMacros().empty()) {

270 llvm::errs() << " overrides";

271 for (auto *O : State->getOverriddenMacros())

272 llvm::errs() << " " << O->getOwningModule()->getFullModuleName();

273 }

274 llvm::errs() << "\n";

275

276

277 for (auto *MD = State ? State->getLatest() : nullptr; MD;

278 MD = MD->getPrevious()) {

279 llvm::errs() << " ";

280 MD->dump();

281 }

282

283

284 llvm::DenseSet<ModuleMacro*> Active;

285 for (auto *MM : State ? State->getActiveModuleMacros(*this, II)

287 Active.insert(MM);

288 llvm::DenseSet<ModuleMacro*> Visited;

290 while (!Worklist.empty()) {

291 auto *MM = Worklist.pop_back_val();

292 llvm::errs() << " ModuleMacro " << MM << " "

293 << MM->getOwningModule()->getFullModuleName();

294 if (!MM->getMacroInfo())

295 llvm::errs() << " undef";

296

297 if (Active.count(MM))

298 llvm::errs() << " active";

299 else if (!CurSubmoduleState->VisibleModules.isVisible(

300 MM->getOwningModule()))

301 llvm::errs() << " hidden";

302 else if (MM->getMacroInfo())

303 llvm::errs() << " overridden";

304

305 if (!MM->overrides().empty()) {

306 llvm::errs() << " overrides";

307 for (auto *O : MM->overrides()) {

308 llvm::errs() << " " << O->getOwningModule()->getFullModuleName();

309 if (Visited.insert(O).second)

310 Worklist.push_back(O);

311 }

312 }

313 llvm::errs() << "\n";

314 if (auto *MI = MM->getMacroInfo()) {

315 llvm::errs() << " ";

317 llvm::errs() << "\n";

318 }

319 }

320}

321

322

323

324void Preprocessor::RegisterBuiltinMacros() {

325 Ident__LINE__ = RegisterBuiltinMacro("__LINE__");

326 Ident__FILE__ = RegisterBuiltinMacro("__FILE__");

327 Ident__DATE__ = RegisterBuiltinMacro("__DATE__");

328 Ident__TIME__ = RegisterBuiltinMacro("__TIME__");

329 Ident__COUNTER__ = RegisterBuiltinMacro("__COUNTER__");

330 Ident_Pragma = RegisterBuiltinMacro("_Pragma");

331 Ident__FLT_EVAL_METHOD__ = RegisterBuiltinMacro("__FLT_EVAL_METHOD__");

332

333

335 Ident__has_cpp_attribute = RegisterBuiltinMacro("__has_cpp_attribute");

336 else

337 Ident__has_cpp_attribute = nullptr;

338

339

340 Ident__BASE_FILE__ = RegisterBuiltinMacro("__BASE_FILE__");

341 Ident__INCLUDE_LEVEL__ = RegisterBuiltinMacro("__INCLUDE_LEVEL__");

342 Ident__TIMESTAMP__ = RegisterBuiltinMacro("__TIMESTAMP__");

343

344

346 Ident__identifier = RegisterBuiltinMacro("__identifier");

347 Ident__pragma = RegisterBuiltinMacro("__pragma");

348 } else {

349 Ident__identifier = nullptr;

350 Ident__pragma = nullptr;

351 }

352

353

354 Ident__FILE_NAME__ = RegisterBuiltinMacro("__FILE_NAME__");

355 Ident__has_feature = RegisterBuiltinMacro("__has_feature");

356 Ident__has_extension = RegisterBuiltinMacro("__has_extension");

357 Ident__has_builtin = RegisterBuiltinMacro("__has_builtin");

358 Ident__has_constexpr_builtin =

359 RegisterBuiltinMacro("__has_constexpr_builtin");

360 Ident__has_attribute = RegisterBuiltinMacro("__has_attribute");

362 Ident__has_c_attribute = RegisterBuiltinMacro("__has_c_attribute");

363 else

364 Ident__has_c_attribute = nullptr;

365

366 Ident__has_declspec = RegisterBuiltinMacro("__has_declspec_attribute");

367 Ident__has_embed = RegisterBuiltinMacro("__has_embed");

368 Ident__has_include = RegisterBuiltinMacro("__has_include");

369 Ident__has_include_next = RegisterBuiltinMacro("__has_include_next");

370 Ident__has_warning = RegisterBuiltinMacro("__has_warning");

371 Ident__is_identifier = RegisterBuiltinMacro("__is_identifier");

372 Ident__is_target_arch = RegisterBuiltinMacro("__is_target_arch");

373 Ident__is_target_vendor = RegisterBuiltinMacro("__is_target_vendor");

374 Ident__is_target_os = RegisterBuiltinMacro("__is_target_os");

375 Ident__is_target_environment =

376 RegisterBuiltinMacro("__is_target_environment");

377 Ident__is_target_variant_os = RegisterBuiltinMacro("__is_target_variant_os");

378 Ident__is_target_variant_environment =

379 RegisterBuiltinMacro("__is_target_variant_environment");

380

381

382 Ident__building_module = RegisterBuiltinMacro("__building_module");

383 if (getLangOpts().CurrentModule.empty())

384 Ident__MODULE__ = RegisterBuiltinMacro("__MODULE__");

385 else

386 Ident__MODULE__ = nullptr;

387}

388

389

390

395

396

397 if (!II) return true;

398

399

400

403

404

405

407 if (ExpansionMI->isEnabled() &&

408

409 II != MacroIdent)

410 return false;

411

412

413

415

416

417

418 return !llvm::is_contained(MI->params(), II);

419}

420

421

422

423

424bool Preprocessor::isNextPPTokenLParen() {

425

426 unsigned Val;

427 if (CurLexer)

428 Val = CurLexer->isNextPPTokenLParen();

429 else

430 Val = CurTokenLexer->isNextTokenLParen();

431

432 if (Val == 2) {

433

434

435

436 if (CurPPLexer)

437 return false;

438 for (const IncludeStackInfo &Entry : llvm::reverse(IncludeMacroStack)) {

439 if (Entry.TheLexer)

440 Val = Entry.TheLexer->isNextPPTokenLParen();

441 else

442 Val = Entry.TheTokenLexer->isNextTokenLParen();

443

444 if (Val != 2)

445 break;

446

447

448 if (Entry.ThePPLexer)

449 return false;

450 }

451 }

452

453

454

455

456 return Val == 1;

457}

458

459

460

461bool Preprocessor::HandleMacroExpandedIdentifier(Token &Identifier,

464

466

467

468

469

471

472

474 if (Callbacks)

476 nullptr);

478 return true;

479 }

480

481

482

483

485

486

487

489

490

492

493

494

495 InMacroArgs = true;

497

498 Args = ReadMacroCallArgumentList(Identifier, MI, ExpansionEnd);

499

500

501 InMacroArgs = false;

502 ArgMacro = nullptr;

503

504

505 if (!Args) return true;

506

507 ++NumFnMacroExpanded;

508 } else {

509 ++NumMacroExpanded;

510 }

511

512

514

515

517 SourceRange ExpansionRange(ExpandLoc, ExpansionEnd);

518

519 if (Callbacks) {

520 if (InMacroArgs) {

521

522

523

524

525 DelayedMacroExpandsCallbacks.push_back(

526 MacroExpandsInfo(Identifier, M, ExpansionRange));

527 } else {

528 Callbacks->MacroExpands(Identifier, M, ExpansionRange, Args);

529 if (!DelayedMacroExpandsCallbacks.empty()) {

530 for (const MacroExpandsInfo &Info : DelayedMacroExpandsCallbacks) {

531

532 Callbacks->MacroExpands(Info.Tok, Info.MD, Info.Range,

533 nullptr);

534 }

535 DelayedMacroExpandsCallbacks.clear();

536 }

537 }

538 }

539

540

547 if (OtherMI != MI)

550 });

551 }

552

553

554

555

556

558

559 if (Args) Args->destroy(*this);

560

561

562

564 PropagateLineStartLeadingSpaceInfo(Identifier);

565 ++NumFastMacroExpanded;

566 return false;

569 *this)) {

570

571

572

573

574

575 if (Args) Args->destroy(*this);

576

577

578

579 bool isAtStartOfLine = Identifier.isAtStartOfLine();

580 bool hasLeadingSpace = Identifier.hasLeadingSpace();

581

582

584

585

588

589

590

593 ExpansionEnd,Identifier.getLength());

595

596

597

600 if (!NewMI->isEnabled() || NewMI == MI) {

602

603

606 }

607 }

608

609

610

611 ++NumFastMacroExpanded;

612 return true;

613 }

614

615

617 return false;

618}

619

624

625

626

630 E = Tokens.end();

631 I != E; ++I) {

632 if (I->is(tok::l_paren)) {

633 Brackets.push_back(Paren);

634 } else if (I->is(tok::r_paren)) {

635 if (Brackets.empty() || Brackets.back() == Brace)

636 return false;

637 Brackets.pop_back();

638 } else if (I->is(tok::l_brace)) {

639 Brackets.push_back(Brace);

640 } else if (I->is(tok::r_brace)) {

641 if (Brackets.empty() || Brackets.back() == Paren)

642 return false;

643 Brackets.pop_back();

644 }

645 }

646 return Brackets.empty();

647}

648

649

650

651

652

653

654

655

659 unsigned &NumArgs,

663 return false;

664

665

666

668

669

671

672

673

675 NumArgs = 0;

677

678

679

680 bool FoundSeparatorToken = false;

682 E = OldTokens.end();

683 I != E; ++I) {

684 if (I->is(tok::l_brace)) {

686 } else if (I->is(tok::r_brace)) {

688 if (Braces == 0 && ClosingBrace == E && FoundSeparatorToken)

689 ClosingBrace = I;

690 } else if (I->is(tok::eof)) {

691

693

694

695 FoundSeparatorToken = true;

696 I->setKind(tok::comma);

697 I->setLength(1);

698 } else {

699

700 ++NumArgs;

701

702

703

704 if (FoundSeparatorToken && ArgStartIterator->is(tok::l_brace)) {

705 InitLists.push_back(

706 SourceRange(ArgStartIterator->getLocation(),

708 ClosingBrace = E;

709 }

710

711

712 if (FoundSeparatorToken) {

714 TempToken.setKind(tok::l_paren);

715 TempToken.setLocation(ArgStartIterator->getLocation());

717 NewTokens.push_back(TempToken);

718 }

719

720

721 NewTokens.insert(NewTokens.end(), ArgStartIterator, I);

722

723

724 if (FoundSeparatorToken) {

727 TempToken.setKind(tok::r_paren);

730 NewTokens.push_back(TempToken);

731 ParenHints.push_back(SourceRange(ArgStartIterator->getLocation(),

733 }

734

735

736 NewTokens.push_back(*I);

737

738

739 ArgStartIterator = I + 1;

740 FoundSeparatorToken = false;

741 }

742 }

743 }

744

745 return !ParenHints.empty() && InitLists.empty();

746}

747

748

749

750

751

752MacroArgs *Preprocessor::ReadMacroCallArgumentList(Token &MacroName,

755

756 unsigned NumFixedArgsLeft = MI->getNumParams();

758

759

761

762

763

765 assert(Tok.is(tok::l_paren) && "Error computing l-paren-ness?");

766

767

768

769

771 bool ContainsCodeCompletionTok = false;

772 bool FoundElidedComma = false;

773

775

776 unsigned NumActuals = 0;

777 while (Tok.isNot(tok::r_paren)) {

778 if (ContainsCodeCompletionTok && Tok.isOneOf(tok::eof, tok::eod))

779 break;

780

781 assert(Tok.isOneOf(tok::l_paren, tok::comma) &&

782 "only expect argument separators here");

783

784 size_t ArgTokenStart = ArgTokens.size();

786

787

788

789 unsigned NumParens = 0;

790

791 while (true) {

792

793

795

796 if (Tok.isOneOf(tok::eof, tok::eod)) {

797 if (!ContainsCodeCompletionTok) {

798 Diag(MacroName, diag::err_unterm_macro_invoc);

801

802 MacroName = Tok;

803 return nullptr;

804 }

805

806 auto Toks = std::make_unique<Token[]>(1);

807 Toks[0] = Tok;

808 EnterTokenStream(std::move(Toks), 1, true, false);

809 break;

810 } else if (Tok.is(tok::r_paren)) {

811

812 if (NumParens-- == 0) {

814 if (!ArgTokens.empty() &&

815 ArgTokens.back().commaAfterElided()) {

816 FoundElidedComma = true;

817 }

818 break;

819 }

820 } else if (Tok.is(tok::l_paren)) {

821 ++NumParens;

822 } else if (Tok.is(tok::comma)) {

823

824

825

827

828

829

830

831

833 } else if (NumParens == 0) {

834

835

836

837 if (!isVariadic)

838 break;

839 if (NumFixedArgsLeft > 1)

840 break;

841 }

842 } else if (Tok.is(tok::comment) && !KeepMacroComments) {

843

844

845 continue;

847

848

849

850

851

852

856 } else if (Tok.is(tok::code_completion)) {

857 ContainsCodeCompletionTok = true;

858 if (CodeComplete)

860 MI, NumActuals);

861

862

863

864 }

865

866 ArgTokens.push_back(Tok);

867 }

868

869

870

871 if (ArgTokens.empty() && Tok.getKind() == tok::r_paren)

872 break;

873

874

875

876 if (!isVariadic && NumFixedArgsLeft == 0 && TooManyArgsLoc.isInvalid()) {

877 if (ArgTokens.size() != ArgTokenStart)

878 TooManyArgsLoc = ArgTokens[ArgTokenStart].getLocation();

879 else

880 TooManyArgsLoc = ArgStartLoc;

881 }

882

883

884

885 if (ArgTokens.size() == ArgTokenStart && getLangOpts().C99)

887 ? diag::warn_cxx98_compat_empty_fnmacro_arg

888 : diag::ext_empty_fnmacro_arg);

889

890

893 EOFTok.setKind(tok::eof);

896 ArgTokens.push_back(EOFTok);

897 ++NumActuals;

898 if (!ContainsCodeCompletionTok && NumFixedArgsLeft != 0)

899 --NumFixedArgsLeft;

900 }

901

902

903

904 unsigned MinArgsExpected = MI->getNumParams();

905

906

907

908 if (!isVariadic && NumActuals > MinArgsExpected &&

909 !ContainsCodeCompletionTok) {

910

911

912 Diag(TooManyArgsLoc, diag::err_too_many_args_in_macro_invoc);

915

916

917

918

919

920

922 unsigned FixedNumArgs = 0;

925 ParenHints, InitLists)) {

926 if (!InitLists.empty()) {

928 Diag(MacroName,

929 diag::note_init_list_at_beginning_of_macro_argument);

932 }

933 return nullptr;

934 }

935 if (FixedNumArgs != MinArgsExpected)

936 return nullptr;

937

939 for (SourceRange ParenLocation : ParenHints) {

942 }

943 ArgTokens.swap(FixedArgTokens);

944 NumActuals = FixedNumArgs;

945 }

946

947

948 bool isVarargsElided = false;

949

950 if (ContainsCodeCompletionTok) {

951

954 EOFTok.setKind(tok::eof);

957 for (; NumActuals < MinArgsExpected; ++NumActuals)

958 ArgTokens.push_back(EOFTok);

959 }

960

961 if (NumActuals < MinArgsExpected) {

962

963 if (NumActuals == 0 && MinArgsExpected == 1) {

964

965

966

967

968

970 } else if ((FoundElidedComma || MI->isVariadic()) &&

971 (NumActuals+1 == MinArgsExpected ||

972 (NumActuals == 0 && MinArgsExpected == 2))) {

973

974

975

976

977

978

980

981

982

983

984 unsigned ID;

986 ID = diag::warn_cxx17_compat_missing_varargs_arg;

988 ID = diag::ext_cxx_missing_varargs_arg;

990 ID = diag::warn_c17_compat_missing_varargs_arg;

991 else

992 ID = diag::ext_c_missing_varargs_arg;

993 Diag(Tok, ID);

996 }

997

998

999

1000

1001

1002

1003

1004 isVarargsElided = true;

1005 } else if (!ContainsCodeCompletionTok) {

1006

1007 Diag(Tok, diag::err_too_few_args_in_macro_invoc);

1010 return nullptr;

1011 }

1012

1013

1019 ArgTokens.push_back(Tok);

1020

1021

1022 if (NumActuals == 0 && MinArgsExpected == 2)

1023 ArgTokens.push_back(Tok);

1024

1025 } else if (NumActuals > MinArgsExpected && !MI->isVariadic() &&

1026 !ContainsCodeCompletionTok) {

1027

1028

1029 Diag(MacroName, diag::err_too_many_args_in_macro_invoc);

1032 return nullptr;

1033 }

1034

1035 return MacroArgs::create(MI, ArgTokens, isVarargsElided, *this);

1036}

1037

1038

1039

1040

1041

1042

1043Token *Preprocessor::cacheMacroExpandedTokens(TokenLexer *tokLexer,

1045 assert(tokLexer);

1046 if (tokens.empty())

1047 return nullptr;

1048

1049 size_t newIndex = MacroExpandedTokens.size();

1050 bool cacheNeedsToGrow = tokens.size() >

1051 MacroExpandedTokens.capacity()-MacroExpandedTokens.size();

1052 MacroExpandedTokens.append(tokens.begin(), tokens.end());

1053

1054 if (cacheNeedsToGrow) {

1055

1056

1057 for (const auto &Lexer : MacroExpandingLexersStack) {

1059 size_t tokIndex;

1060 std::tie(prevLexer, tokIndex) = Lexer;

1061 prevLexer->Tokens = MacroExpandedTokens.data() + tokIndex;

1062 }

1063 }

1064

1065 MacroExpandingLexersStack.push_back(std::make_pair(tokLexer, newIndex));

1066 return MacroExpandedTokens.data() + newIndex;

1067}

1068

1069void Preprocessor::removeCachedMacroExpandedTokensOfLastLexer() {

1070 assert(!MacroExpandingLexersStack.empty());

1071 size_t tokIndex = MacroExpandingLexersStack.back().second;

1072 assert(tokIndex < MacroExpandedTokens.size());

1073

1074 MacroExpandedTokens.resize(tokIndex);

1075 MacroExpandingLexersStack.pop_back();

1076}

1077

1078

1079

1080

1083 time_t TT;

1084 std::tm *TM;

1087 TM = std::gmtime(&TT);

1088 } else {

1089 TT = std::time(nullptr);

1090 TM = std::localtime(&TT);

1091 }

1092

1093 static const char * const Months[] = {

1094 "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"

1095 };

1096

1097 {

1099 llvm::raw_svector_ostream TmpStream(TmpBuffer);

1100 if (TM)

1101 TmpStream << llvm::format("\"%s %2d %4d\"", Months[TM->tm_mon],

1102 TM->tm_mday, TM->tm_year + 1900);

1103 else

1104 TmpStream << "??? ?? ????";

1109 }

1110

1111 {

1113 llvm::raw_svector_ostream TmpStream(TmpBuffer);

1114 if (TM)

1115 TmpStream << llvm::format("\"%02d:%02d:%02d\"", TM->tm_hour, TM->tm_min,

1116 TM->tm_sec);

1117 else

1118 TmpStream << "??:??:??";

1123 }

1124}

1125

1126

1127

1130

1131

1132 if (Feature.starts_with("__") && Feature.ends_with("__") &&

1133 Feature.size() >= 4)

1134 Feature = Feature.substr(2, Feature.size() - 4);

1135

1136#define FEATURE(Name, Predicate) .Case(#Name, Predicate)

1137 return llvm::StringSwitch(Feature)

1138#include "clang/Basic/Features.def"

1139 .Default(false);

1140#undef FEATURE

1141}

1142

1143

1144

1145

1148 return true;

1149

1150

1151

1154 return false;

1155

1157

1158

1159 if (Extension.starts_with("__") && Extension.ends_with("__") &&

1160 Extension.size() >= 4)

1161 Extension = Extension.substr(2, Extension.size() - 4);

1162

1163

1164

1165#define EXTENSION(Name, Predicate) .Case(#Name, Predicate)

1166 return llvm::StringSwitch(Extension)

1167#include "clang/Basic/Features.def"

1168 .Default(false);

1169#undef EXTENSION

1170}

1171

1172

1173

1174

1178 const FileEntry *LookupFromFile) {

1179

1180

1182

1183

1185 PP.Diag(LParenLoc, diag::err_pp_directive_required) << II;

1186

1187 assert(Tok.is(tok::identifier));

1189 return false;

1190 }

1191

1192

1193 do {

1195 return false;

1196 } while (Tok.getKind() == tok::comment);

1197

1198

1199 if (Tok.isNot(tok::l_paren)) {

1200

1202 PP.Diag(LParenLoc, diag::err_pp_expected_after) << II << tok::l_paren;

1203

1204

1205 if (Tok.isNot(tok::header_name))

1206 return false;

1207 } else {

1208

1211 return false;

1212 }

1213

1214 if (Tok.isNot(tok::header_name)) {

1215 PP.Diag(Tok.getLocation(), diag::err_pp_expects_filename);

1216 return false;

1217 }

1218

1219

1224 return false;

1225

1227

1228

1230

1231

1232 if (Tok.isNot(tok::r_paren)) {

1234 << II << tok::r_paren;

1235 PP.Diag(LParenLoc, diag::note_matching) << tok::l_paren;

1236 return false;

1237 }

1238

1240

1241

1243 return false;

1244

1245

1246

1247

1249

1250

1252 PP.LookupFile(FilenameLoc, Filename, isAngled, LookupFrom, LookupFromFile,

1253 nullptr, nullptr, nullptr, &KH, nullptr, nullptr);

1254

1260 }

1261

1262

1263 return File.has_value();

1264}

1265

1266

1267

1269

1271 Diag(Tok, diag::err_pp_directive_required) << II;

1272

1273 assert(Tok.is(tok::identifier));

1276 }

1277

1278

1280 if (Tok.isNot(tok::l_paren)) {

1281 Diag(Tok, diag::err_pp_expected_after) << II << tok::l_paren;

1282

1283

1285 }

1286

1287

1288

1292

1293 if (Tok.isNot(tok::header_name)) {

1296 }

1297

1299 Token FilenameTok = Tok;

1300

1301 std::optional Params =

1303 assert((Params || Tok.is(tok::eod)) &&

1304 "expected success or to be at the end of the directive");

1305

1306 if (!Params)

1308

1309 if (Params->UnrecognizedParams > 0)

1311

1312 if (!Tok.is(tok::r_paren)) {

1314 << II << tok::r_paren;

1315 Diag(LParenLoc, diag::note_matching) << tok::l_paren;

1316 if (Tok.isNot(tok::eod))

1319 }

1320

1323 bool isAngled =

1325

1326

1328 const FileEntry *LookupFromFile =

1330 : static_cast<FileEntry *>(nullptr);

1332 this->LookupEmbedFile(Filename, isAngled, false, LookupFromFile);

1333 if (Callbacks) {

1334 Callbacks->HasEmbed(LParenLoc, Filename, isAngled, MaybeFileEntry);

1335 }

1336 if (!MaybeFileEntry)

1338

1339 size_t FileSize = MaybeFileEntry->getSize();

1340

1341

1342 if (Params->MaybeOffsetParam) {

1343 if (Params->MaybeOffsetParam->Offset > FileSize)

1344 FileSize = 0;

1345 else

1346 FileSize -= Params->MaybeOffsetParam->Offset;

1347 }

1348

1349

1350

1351 if (Params->MaybeLimitParam) {

1352 if (Params->MaybeLimitParam->Limit > FileSize)

1353 FileSize = 0;

1354 else

1355 FileSize = Params->MaybeLimitParam->Limit;

1356 }

1357

1358

1359

1360 if (FileSize == 0)

1363}

1364

1367}

1368

1369bool Preprocessor::EvaluateHasIncludeNext(Token &Tok, IdentifierInfo *II) {

1371 const FileEntry *LookupFromFile;

1372 std::tie(Lookup, LookupFromFile) = getIncludeNextStart(Tok);

1373

1375}

1376

1377

1378

1382 llvm::function_ref<

1384 bool &HasLexedNextTok)> Op) {

1385

1387 if (Tok.isNot(tok::l_paren)) {

1388 PP.Diag(Tok.getLocation(), diag::err_pp_expected_after) << II

1389 << tok::l_paren;

1390

1391

1392 if (!Tok.isOneOf(tok::eof, tok::eod)) {

1393 OS << 0;

1394 Tok.setKind(tok::numeric_constant);

1395 }

1396 return;

1397 }

1398

1399 unsigned ParenDepth = 1;

1401 std::optional Result;

1402

1403 Token ResultTok;

1404 bool SuppressDiagnostic = false;

1405 while (true) {

1406

1407 if (ExpandArgs)

1408 PP.Lex(Tok);

1409 else

1411

1412already_lexed:

1413 switch (Tok.getKind()) {

1414 case tok::eof:

1415 case tok::eod:

1416

1417

1418 PP.Diag(Tok.getLocation(), diag::err_unterm_macro_invoc);

1419 return;

1420

1421 case tok::comma:

1422 if (!SuppressDiagnostic) {

1423 PP.Diag(Tok.getLocation(), diag::err_too_many_args_in_macro_invoc);

1424 SuppressDiagnostic = true;

1425 }

1426 continue;

1427

1428 case tok::l_paren:

1429 ++ParenDepth;

1431 break;

1432 if (!SuppressDiagnostic) {

1433 PP.Diag(Tok.getLocation(), diag::err_pp_nested_paren) << II;

1434 SuppressDiagnostic = true;

1435 }

1436 continue;

1437

1438 case tok::r_paren:

1439 if (--ParenDepth > 0)

1440 continue;

1441

1442

1443

1446

1447

1449 OS << 'L';

1450 } else {

1451 OS << 0;

1452 if (!SuppressDiagnostic)

1453 PP.Diag(Tok.getLocation(), diag::err_too_few_args_in_macro_invoc);

1454 }

1455 Tok.setKind(tok::numeric_constant);

1456 return;

1457

1458 default: {

1459

1461 break;

1462

1463 bool HasLexedNextToken = false;

1464 Result = Op(Tok, HasLexedNextToken);

1465 ResultTok = Tok;

1466 if (HasLexedNextToken)

1467 goto already_lexed;

1468 continue;

1469 }

1470 }

1471

1472

1473 if (!SuppressDiagnostic) {

1474 if (auto Diag = PP.Diag(Tok.getLocation(), diag::err_pp_expected_after)) {

1476 Diag << LastII;

1477 else

1480 }

1481 PP.Diag(LParenLoc, diag::note_matching) << tok::l_paren;

1482 SuppressDiagnostic = true;

1483 }

1484 }

1485}

1486

1487

1488

1491 signed DiagID) {

1494 return II;

1495

1497 return nullptr;

1498}

1499

1500

1502 std::string ArchName = II->getName().lower() + "--";

1503 llvm::Triple Arch(ArchName);

1504 const llvm::Triple &TT = TI.getTriple();

1505 if (TT.isThumb()) {

1506

1507 if ((Arch.getSubArch() == llvm::Triple::NoSubArch ||

1508 Arch.getSubArch() == TT.getSubArch()) &&

1509 ((TT.getArch() == llvm::Triple::thumb &&

1510 Arch.getArch() == llvm::Triple::arm) ||

1511 (TT.getArch() == llvm::Triple::thumbeb &&

1512 Arch.getArch() == llvm::Triple::armeb)))

1513 return true;

1514 }

1515

1516

1517 return (Arch.getSubArch() == llvm::Triple::NoSubArch ||

1518 Arch.getSubArch() == TT.getSubArch()) &&

1519 Arch.getArch() == TT.getArch();

1520}

1521

1522

1524 StringRef VendorName = TI.getTriple().getVendorName();

1525 if (VendorName.empty())

1526 VendorName = "unknown";

1527 return VendorName.equals_insensitive(II->getName());

1528}

1529

1530

1532 std::string OSName =

1533 (llvm::Twine("unknown-unknown-") + II->getName().lower()).str();

1534 llvm::Triple OS(OSName);

1535 if (OS.getOS() == llvm::Triple::Darwin) {

1536

1537 return TI.getTriple().isOSDarwin();

1538 }

1539 return TI.getTriple().getOS() == OS.getOS();

1540}

1541

1542

1545 std::string EnvName = (llvm::Twine("---") + II->getName().lower()).str();

1546 llvm::Triple Env(EnvName);

1547

1548

1549 if (Env.getEnvironment() == llvm::Triple::UnknownEnvironment &&

1550 EnvName != "---unknown")

1551 return false;

1552 return TI.getTriple().getEnvironment() == Env.getEnvironment();

1553}

1554

1555

1557 if (TI.getTriple().isOSDarwin()) {

1559 if (!VariantTriple)

1560 return false;

1561

1562 std::string OSName =

1563 (llvm::Twine("unknown-unknown-") + II->getName().lower()).str();

1564 llvm::Triple OS(OSName);

1565 if (OS.getOS() == llvm::Triple::Darwin) {

1566

1567 return VariantTriple->isOSDarwin();

1568 }

1569 return VariantTriple->getOS() == OS.getOS();

1570 }

1571 return false;

1572}

1573

1574

1577 if (TI.getTriple().isOSDarwin()) {

1579 if (!VariantTriple)

1580 return false;

1581 std::string EnvName = (llvm::Twine("---") + II->getName().lower()).str();

1582 llvm::Triple Env(EnvName);

1583 return VariantTriple->getEnvironment() == Env.getEnvironment();

1584 }

1585 return false;

1586}

1587

1588#if defined(__sun__) && defined(__svr4__) && defined(__clang__) && \

1589 __clang__ < 20

1590

1591

1592

1593

1594asm("_ZNKSt8time_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE3putES3_"

1595 "RSt8ios_basecPKSt2tmPKcSB_ = "

1596 "_ZNKSt8time_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE3putES3_"

1597 "RSt8ios_basecPK2tmPKcSB_");

1598#endif

1599

1601

1602#define TYPE_TRAIT_1(Spelling, Name, Key) \

1603 case tok::kw_##Spelling: \

1604 return true;

1605#define TYPE_TRAIT_2(Spelling, Name, Key) \

1606 case tok::kw_##Spelling: \

1607 return true;

1608#define TYPE_TRAIT_N(Spelling, Name, Key) \

1609 case tok::kw_##Spelling: \

1610 return true;

1611#define ARRAY_TYPE_TRAIT(Spelling, Name, Key) \

1612 case tok::kw_##Spelling: \

1613 return true;

1614#define EXPRESSION_TRAIT(Spelling, Name, Key) \

1615 case tok::kw_##Spelling: \

1616 return true;

1617#define TRANSFORM_TYPE_TRAIT_DEF(K, Spelling) \

1618 case tok::kw___##Spelling: \

1619 return true;

1620

1621 switch (Tok.getKind()) {

1622 default:

1623 return false;

1624#include "clang/Basic/TokenKinds.def"

1625 }

1626}

1627

1628

1629

1630void Preprocessor::ExpandBuiltinMacro(Token &Tok) {

1631

1633 assert(II && "Can't be a macro without id info!");

1634

1635

1636

1637 if (II == Ident_Pragma)

1638 return Handle_Pragma(Tok);

1639 else if (II == Ident__pragma)

1640 return HandleMicrosoft__pragma(Tok);

1641

1642 ++NumBuiltinMacroExpanded;

1643

1645 llvm::raw_svector_ostream OS(TmpBuffer);

1646

1647

1652

1653 if (II == Ident__LINE__) {

1654

1655

1656

1658

1659

1660

1662

1663

1664

1665

1666

1667

1670

1671

1673 Tok.setKind(tok::numeric_constant);

1674 } else if (II == Ident__FILE__ || II == Ident__BASE_FILE__ ||

1675 II == Ident__FILE_NAME__) {

1676

1677

1679

1680

1681

1682 if (II == Ident__BASE_FILE__ && PLoc.isValid()) {

1684 while (NextLoc.isValid()) {

1687 break;

1688

1690 }

1691 }

1692

1693

1696

1697

1698 if (II == Ident__FILE_NAME__) {

1700 } else {

1703 }

1705 OS << '"' << FN << '"';

1706 }

1707 Tok.setKind(tok::string_literal);

1708 } else if (II == Ident__DATE__) {

1712 Tok.setKind(tok::string_literal);

1713 Tok.setLength(strlen("\"Mmm dd yyyy\""));

1717 return;

1718 } else if (II == Ident__TIME__) {

1722 Tok.setKind(tok::string_literal);

1723 Tok.setLength(strlen("\"hh:mm:ss\""));

1727 return;

1728 } else if (II == Ident__INCLUDE_LEVEL__) {

1729

1730

1731 unsigned Depth = 0;

1732

1736 for (; PLoc.isValid(); ++Depth)

1738 }

1739

1740

1741 OS << Depth;

1742 Tok.setKind(tok::numeric_constant);

1743 } else if (II == Ident__TIMESTAMP__) {

1745

1746

1748 std::stringstream TmpStream;

1749 TmpStream.imbue(std::locale("C"));

1752 std::tm *TM = std::gmtime(&TT);

1753 TmpStream << std::put_time(TM, "%a %b %e %T %Y");

1754 } else {

1755

1756

1757 const FileEntry *CurFile = nullptr;

1760 if (CurFile) {

1762 struct tm *TM = localtime(&TT);

1763 TmpStream << std::put_time(TM, "%a %b %e %T %Y");

1764 }

1765 }

1766 Result = TmpStream.str();

1768 Result = "??? ??? ?? ??:??:?? ????";

1769 OS << '"' << Result << '"';

1770 Tok.setKind(tok::string_literal);

1771 } else if (II == Ident__FLT_EVAL_METHOD__) {

1772

1774

1775 Tok.setKind(tok::numeric_constant);

1777

1778

1779 Diag(Tok, diag::err_illegal_use_of_flt_eval_macro);

1781 }

1782 } else if (II == Ident__COUNTER__) {

1783

1784 OS << CounterValue++;

1785 Tok.setKind(tok::numeric_constant);

1786 } else if (II == Ident__has_feature) {

1788 [this](Token &Tok, bool &HasLexedNextToken) -> int {

1790 diag::err_feature_check_malformed);

1792 });

1793 } else if (II == Ident__has_extension) {

1795 [this](Token &Tok, bool &HasLexedNextToken) -> int {

1797 diag::err_feature_check_malformed);

1799 });

1800 } else if (II == Ident__has_builtin) {

1802 [this](Token &Tok, bool &HasLexedNextToken) -> int {

1804 diag::err_feature_check_malformed);

1805 if (!II)

1806 return false;

1809 case Builtin::BI__builtin_cpu_is:

1811 case Builtin::BI__builtin_cpu_init:

1813 case Builtin::BI__builtin_cpu_supports:

1815 case Builtin::BI__builtin_operator_new:

1816 case Builtin::BI__builtin_operator_delete:

1817

1818

1819 return 201802;

1820 default:

1824 }

1825 return true;

1827 return true;

1828 } else if (II->getTokenID() != tok::identifier &&

1829 II->getName().starts_with("__builtin_")) {

1830 return true;

1831 } else {

1832 return llvm::StringSwitch(II->getName())

1833

1837

1838

1839

1840 .Case("__is_target_arch", true)

1841 .Case("__is_target_vendor", true)

1842 .Case("__is_target_os", true)

1843 .Case("__is_target_environment", true)

1844 .Case("__is_target_variant_os", true)

1845 .Case("__is_target_variant_environment", true)

1846 .Default(false);

1847 }

1848 });

1849 } else if (II == Ident__has_constexpr_builtin) {

1851 OS, Tok, II, *this, false,

1852 [this](Token &Tok, bool &HasLexedNextToken) -> int {

1854 Tok, *this, diag::err_feature_check_malformed);

1855 if (!II)

1856 return false;

1858 return BuiltinOp != 0 &&

1860 });

1861 } else if (II == Ident__is_identifier) {

1863 [](Token &Tok, bool &HasLexedNextToken) -> int {

1864 return Tok.is(tok::identifier);

1865 });

1866 } else if (II == Ident__has_attribute) {

1868 [this](Token &Tok, bool &HasLexedNextToken) -> int {

1870 diag::err_feature_check_malformed);

1873 : 0;

1874 });

1875 } else if (II == Ident__has_declspec) {

1877 [this](Token &Tok, bool &HasLexedNextToken) -> int {

1879 diag::err_feature_check_malformed);

1880 if (II) {

1882 return LangOpts.DeclSpecKeyword &&

1885 }

1886

1887 return false;

1888 });

1889 } else if (II == Ident__has_cpp_attribute ||

1890 II == Ident__has_c_attribute) {

1891 bool IsCXX = II == Ident__has_cpp_attribute;

1893 [&](Token &Tok, bool &HasLexedNextToken) -> int {

1896 Tok, *this, diag::err_feature_check_malformed);

1897 if (!II)

1898 return false;

1899

1900

1901

1903 if (Tok.isNot(tok::coloncolon))

1904 HasLexedNextToken = true;

1905 else {

1906 ScopeII = II;

1907

1908 Lex(Tok);

1910 diag::err_feature_check_malformed);

1911 }

1912

1918 : 0;

1919 });

1920 } else if (II == Ident__has_include ||

1921 II == Ident__has_include_next) {

1922

1923

1924

1926 if (II == Ident__has_include)

1927 Value = EvaluateHasInclude(Tok, II);

1928 else

1929 Value = EvaluateHasIncludeNext(Tok, II);

1930

1931 if (Tok.isNot(tok::r_paren))

1932 return;

1934 Tok.setKind(tok::numeric_constant);

1935 } else if (II == Ident__has_embed) {

1936

1937

1938

1939

1942 return;

1943

1944 Tok.setKind(tok::numeric_constant);

1945 OS << static_cast(Value);

1946 } else if (II == Ident__has_warning) {

1947

1949 [this](Token &Tok, bool &HasLexedNextToken) -> int {

1950 std::string WarningName;

1952

1953 HasLexedNextToken = Tok.is(tok::string_literal);

1955 false))

1956 return false;

1957

1958

1959

1960 if (WarningName.size() < 3 || WarningName[0] != '-' ||

1961 WarningName[1] != 'W') {

1962 Diag(StrStartLoc, diag::warn_has_warning_invalid_option);

1963 return false;

1964 }

1965

1966

1967

1968

1969

1973 WarningName.substr(2), Diags);

1974 });

1975 } else if (II == Ident__building_module) {

1976

1977

1978

1980 [this](Token &Tok, bool &HasLexedNextToken) -> int {

1982 diag::err_expected_id_building_module);

1985 });

1986 } else if (II == Ident__MODULE__) {

1987

1992 } else if (II == Ident__identifier) {

1994

1995

1996

1998 if (Tok.isNot(tok::l_paren)) {

1999

2001 << II << tok::l_paren;

2002

2004 Tok.setKind(tok::identifier);

2005 return;

2006 }

2007

2010

2012 Tok.setKind(tok::identifier);

2013 else if (Tok.is(tok::string_literal) && !Tok.hasUDSuffix()) {

2017 return;

2018

2020 Tok.setKind(tok::identifier);

2021 } else {

2022 Diag(Tok.getLocation(), diag::err_pp_identifier_arg_not_identifier)

2024

2026 return;

2027 }

2028

2029

2032 if (RParen.isNot(tok::r_paren)) {

2034 << Tok.getKind() << tok::r_paren;

2035 Diag(LParenLoc, diag::note_matching) << tok::l_paren;

2036 }

2037 return;

2038 } else if (II == Ident__is_target_arch) {

2040 OS, Tok, II, *this, false,

2041 [this](Token &Tok, bool &HasLexedNextToken) -> int {

2043 Tok, *this, diag::err_feature_check_malformed);

2045 });

2046 } else if (II == Ident__is_target_vendor) {

2048 OS, Tok, II, *this, false,

2049 [this](Token &Tok, bool &HasLexedNextToken) -> int {

2051 Tok, *this, diag::err_feature_check_malformed);

2053 });

2054 } else if (II == Ident__is_target_os) {

2056 OS, Tok, II, *this, false,

2057 [this](Token &Tok, bool &HasLexedNextToken) -> int {

2059 Tok, *this, diag::err_feature_check_malformed);

2061 });

2062 } else if (II == Ident__is_target_environment) {

2064 OS, Tok, II, *this, false,

2065 [this](Token &Tok, bool &HasLexedNextToken) -> int {

2067 Tok, *this, diag::err_feature_check_malformed);

2069 });

2070 } else if (II == Ident__is_target_variant_os) {

2072 OS, Tok, II, *this, false,

2073 [this](Token &Tok, bool &HasLexedNextToken) -> int {

2075 Tok, *this, diag::err_feature_check_malformed);

2077 });

2078 } else if (II == Ident__is_target_variant_environment) {

2080 OS, Tok, II, *this, false,

2081 [this](Token &Tok, bool &HasLexedNextToken) -> int {

2083 Tok, *this, diag::err_feature_check_malformed);

2085 });

2086 } else {

2087 llvm_unreachable("Unknown identifier!");

2088 }

2092}

2093

2095

2096

2100}

2101

2107 if (TI.getTriple().isOSWindows())

2108 llvm::sys::path::remove_dots(Path, false,

2109 llvm::sys::path::Style::windows_backslash);

2110 else

2111 llvm::sys::path::remove_dots(Path, false, llvm::sys::path::Style::posix);

2112 }

2113}

2114

2119

2120

2121 StringRef PLFileName = llvm::sys::path::filename(PLoc.getFilename());

2122 if (PLFileName.empty())

2124 FileName.append(PLFileName.begin(), PLFileName.end());

2126}

Defines enum values for all the target-independent builtin functions.

static bool getDiagnosticsInGroup(diag::Flavor Flavor, const WarningOption *Group, SmallVectorImpl< diag::kind > &Diags)

Return true if any diagnostics were found in this group, even if they were filtered out due to having...

llvm::DenseSet< const void * > Visited

Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.

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

Defines the clang::LangOptions interface.

static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)

Produce a diagnostic highlighting some portion of a literal.

llvm::MachO::FileType FileType

Defines the clang::MacroInfo and clang::MacroDirective classes.

static bool HasExtension(const Preprocessor &PP, StringRef Extension)

HasExtension - Return true if we recognize and implement the feature specified by the identifier,...

static bool CheckMatchedBrackets(const SmallVectorImpl< Token > &Tokens)

CheckMatchedBrackets - Returns true if the braces and parentheses in the token vector are properly ne...

static bool EvaluateHasIncludeCommon(Token &Tok, IdentifierInfo *II, Preprocessor &PP, ConstSearchDirIterator LookupFrom, const FileEntry *LookupFromFile)

EvaluateHasIncludeCommon - Process a '__has_include("path")' or '__has_include_next("path")' expressi...

static bool GenerateNewArgTokens(Preprocessor &PP, SmallVectorImpl< Token > &OldTokens, SmallVectorImpl< Token > &NewTokens, unsigned &NumArgs, SmallVectorImpl< SourceRange > &ParenHints, SmallVectorImpl< SourceRange > &InitLists)

GenerateNewArgTokens - Returns true if OldTokens can be converted to a new vector of tokens in NewTok...

static bool isTargetVariantOS(const TargetInfo &TI, const IdentifierInfo *II)

Implements the __is_target_variant_os builtin macro.

static bool isTrivialSingleTokenExpansion(const MacroInfo *MI, const IdentifierInfo *MacroIdent, Preprocessor &PP)

isTrivialSingleTokenExpansion - Return true if MI, which has a single token in its expansion,...

static bool isTargetArch(const TargetInfo &TI, const IdentifierInfo *II)

Implements the __is_target_arch builtin macro.

static void ComputeDATE_TIME(SourceLocation &DATELoc, SourceLocation &TIMELoc, Preprocessor &PP)

ComputeDATE_TIME - Compute the current time, enter it into the specified scratch buffer,...

static bool isTargetVariantEnvironment(const TargetInfo &TI, const IdentifierInfo *II)

Implements the __is_target_variant_environment builtin macro.

static bool isTargetEnvironment(const TargetInfo &TI, const IdentifierInfo *II)

Implements the __is_target_environment builtin macro.

static bool IsBuiltinTrait(Token &Tok)

static bool isTargetOS(const TargetInfo &TI, const IdentifierInfo *II)

Implements the __is_target_os builtin macro.

static bool isTargetVendor(const TargetInfo &TI, const IdentifierInfo *II)

Implements the __is_target_vendor builtin macro.

static void EvaluateFeatureLikeBuiltinMacro(llvm::raw_svector_ostream &OS, Token &Tok, IdentifierInfo *II, Preprocessor &PP, bool ExpandArgs, llvm::function_ref< int(Token &Tok, bool &HasLexedNextTok)> Op)

Process single-argument builtin feature-like macros that return integer values.

static bool HasFeature(const Preprocessor &PP, StringRef Feature)

HasFeature - Return true if we recognize and implement the feature specified by the identifier as a s...

static IdentifierInfo * ExpectFeatureIdentifierInfo(Token &Tok, Preprocessor &PP, signed DiagID)

Helper function to return the IdentifierInfo structure of a Token or generate a diagnostic if none av...

Defines the PreprocessorLexer interface.

Defines the clang::Preprocessor interface.

Defines the clang::SourceLocation class and associated facilities.

Syntax

The style used to specify an attribute.

@ AS_Declspec

__declspec(...)

bool isConstantEvaluated(unsigned ID) const

Return true if this function can be constant evaluated by Clang frontend.

SourceLocation getEnd() const

virtual void CodeCompleteMacroArgument(IdentifierInfo *Macro, MacroInfo *MacroInfo, unsigned ArgumentIndex)

Callback invoked when performing code completion inside a function-like macro argument.

A little helper class used to produce diagnostics.

diag::Severity getExtensionHandlingBehavior() const

virtual void updateOutOfDateIdentifier(const IdentifierInfo &II)=0

Update an out-of-date identifier.

Cached information about one file (either on disk or in the virtual file system).

time_t getModificationTime() const

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.

unsigned getBuiltinID() const

Return a value indicating whether this is a builtin function.

tok::TokenKind getTokenID() const

If this is a source-language token (e.g.

bool hadMacroDefinition() const

Returns true if this identifier was #defined to some value at any moment.

bool isFromAST() const

Return true if the identifier in its current state was loaded from an AST file.

const char * getNameStart() const

Return the beginning of the actual null-terminated string for this identifier.

void setHasMacroDefinition(bool Val)

bool isOutOfDate() const

Determine whether the information for this identifier is out of date with respect to the external sou...

void setChangedSinceDeserialization()

Note that this identifier has changed since it was loaded from an AST file.

StringRef getName() const

Return the actual identifier string.

Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...

bool UseTargetPathSeparator

Indicates whether to use target's platform-specific file separator when FILE macro is used and when c...

void remapPathPrefix(SmallVectorImpl< char > &Path) const

Remap path prefix according to -fmacro-prefix-path option.

bool isCompilingModule() const

Are we compiling a module?

std::string CurrentModule

The name of the current module, of which the main source file is a part.

Lexer - This provides a simple interface that turns a text buffer into a stream of tokens.

static std::string Stringify(StringRef Str, bool Charify=false)

Stringify - Convert the specified string into a C string by i) escaping '\' and " characters and ii) ...

MacroArgs - An instance of this class captures information about the formal arguments specified to a ...

static MacroArgs * create(const MacroInfo *MI, ArrayRef< Token > UnexpArgTokens, bool VarargsElided, Preprocessor &PP)

MacroArgs ctor function - Create a new MacroArgs object with the specified macro and argument info.

void destroy(Preprocessor &PP)

destroy - Destroy and deallocate the memory for this object.

A description of the current definition of a macro.

MacroInfo * getMacroInfo() const

Get the MacroInfo that should be used for this definition.

bool isAmbiguous() const

true if the definition is ambiguous, false otherwise.

void forAllDefinitions(Fn F) const

Encapsulates changes to the "macros namespace" (the location where the macro name became active,...

const MacroDirective * getPrevious() const

Get previous definition of the macro with the same name.

void setPrevious(MacroDirective *Prev)

Set previous definition of the macro with the same name.

Encapsulates the data about a macro definition (e.g.

bool isIdenticalTo(const MacroInfo &Other, Preprocessor &PP, bool Syntactically) const

Return true if the specified macro definition is equal to this macro in spelling, arguments,...

bool isUsed() const

Return false if this macro is defined in the main file and has not yet been used.

bool isFunctionLike() const

ArrayRef< const IdentifierInfo * > params() const

unsigned getNumTokens() const

Return the number of tokens that this macro expands to.

unsigned getNumParams() const

const Token & getReplacementToken(unsigned Tok) const

bool isBuiltinMacro() const

Return true if this macro requires processing before expansion.

SourceLocation getDefinitionLoc() const

Return the location that the macro was defined at.

bool hasCommaPasting() const

bool isObjectLike() const

bool isWarnIfUnused() const

Return true if we should emit a warning if the macro is unused.

bool isEnabled() const

Return true if this macro is enabled.

void setIsUsed(bool Val)

Set the value of the IsUsed flag.

Represents a macro directive exported by a module.

static ModuleMacro * create(Preprocessor &PP, Module *OwningModule, const IdentifierInfo *II, MacroInfo *Macro, ArrayRef< ModuleMacro * > Overrides)

void Profile(llvm::FoldingSetNodeID &ID) const

Describes a module or submodule.

void ExpandedMacro()

ExpandedMacro - When a macro is expanded with this lexer as the current buffer, this method is called...

This interface provides a way to observe the actions of the preprocessor as it does its thing.

MultipleIncludeOpt MIOpt

A state machine that detects the #ifndef-wrapping a file idiom for the multiple-include optimization.

OptionalFileEntryRef getFileEntry() const

getFileEntry - Return the FileEntry corresponding to this FileID.

std::optional< uint64_t > SourceDateEpoch

If set, the UNIX timestamp specified by SOURCE_DATE_EPOCH.

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

SourceLocation getLastFPEvalPragmaLocation() const

bool FinishLexStringLiteral(Token &Result, std::string &String, const char *DiagnosticTag, bool AllowMacroExpansion)

Complete the lexing of a string literal where the first token has already been lexed (see LexStringLi...

void dumpMacroInfo(const IdentifierInfo *II)

ModuleMacro * addModuleMacro(Module *Mod, IdentifierInfo *II, MacroInfo *Macro, ArrayRef< ModuleMacro * > Overrides, bool &IsNew)

Register an exported macro for a module and identifier.

void setLoadedMacroDirective(IdentifierInfo *II, MacroDirective *ED, MacroDirective *MD)

Set a MacroDirective that was loaded from a PCH file.

OptionalFileEntryRef LookupEmbedFile(StringRef Filename, bool isAngled, bool OpenFile, const FileEntry *LookupFromFile=nullptr)

Given a "Filename" or reference, look up the indicated embed resource.

PPCallbacks * getPPCallbacks() const

const MacroInfo * getMacroInfo(const IdentifierInfo *II) const

void CreateString(StringRef Str, Token &Tok, SourceLocation ExpansionLocStart=SourceLocation(), SourceLocation ExpansionLocEnd=SourceLocation())

Plop the specified string into a scratch buffer and set the specified token's location and length to ...

void markMacroAsUsed(MacroInfo *MI)

A macro is used, update information about macros that need unused warnings.

MacroDirective * getLocalMacroDirectiveHistory(const IdentifierInfo *II) const

Given an identifier, return the latest non-imported macro directive for that identifier.

void Lex(Token &Result)

Lex the next token for this preprocessor.

bool isParsingIfOrElifDirective() const

True if we are currently preprocessing a if or #elif directive.

void LexNonComment(Token &Result)

Lex a token.

SourceRange DiscardUntilEndOfDirective()

Read and discard all tokens remaining on the current line until the tok::eod token is found.

IdentifierInfo * getIdentifierInfo(StringRef Name) const

Return information about the specified preprocessor identifier token.

SourceLocation AdvanceToTokenCharacter(SourceLocation TokStart, unsigned Char) const

Given a location that specifies the start of a token, return a new location that specifies a characte...

static void processPathToFileName(SmallVectorImpl< char > &FileName, const PresumedLoc &PLoc, const LangOptions &LangOpts, const TargetInfo &TI)

const TargetInfo & getTargetInfo() const

bool LexHeaderName(Token &Result, bool AllowMacroExpansion=true)

Lex a token, forming a header-name token if possible.

PreprocessorOptions & getPreprocessorOpts() const

Retrieve the preprocessor options used to initialize this preprocessor.

void LexUnexpandedToken(Token &Result)

Just like Lex, but disables macro expansion of identifier tokens.

ModuleMacro * getModuleMacro(Module *Mod, const IdentifierInfo *II)

StringRef getSpelling(SourceLocation loc, SmallVectorImpl< char > &buffer, bool *invalid=nullptr) const

Return the 'spelling' of the token at the given location; does not go up to the spelling location or ...

bool GetIncludeFilenameSpelling(SourceLocation Loc, StringRef &Buffer)

Turn the specified lexer token into a fully checked and spelled filename, e.g.

PreprocessorLexer * getCurrentFileLexer() const

Return the current file lexer being lexed from.

HeaderSearch & getHeaderSearchInfo() const

void emitMacroExpansionWarnings(const Token &Identifier, bool IsIfnDef=false) const

ExternalPreprocessorSource * getExternalSource() const

OptionalFileEntryRef LookupFile(SourceLocation FilenameLoc, StringRef Filename, bool isAngled, ConstSearchDirIterator FromDir, const FileEntry *FromFile, ConstSearchDirIterator *CurDir, SmallVectorImpl< char > *SearchPath, SmallVectorImpl< char > *RelativePath, ModuleMap::KnownHeader *SuggestedModule, bool *IsMapped, bool *IsFrameworkFound, bool SkipCache=false, bool OpenFile=true, bool CacheFailures=true)

Given a "foo" or reference, look up the indicated file.

Builtin::Context & getBuiltinInfo()

LangOptions::FPEvalMethodKind getTUFPEvalMethod() const

const LangOptions & getLangOpts() const

static void processPathForFileMacro(SmallVectorImpl< char > &Path, const LangOptions &LangOpts, const TargetInfo &TI)

DiagnosticsEngine & getDiagnostics() const

SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset=0)

Computes the source location just past the end of the token at this source location.

std::optional< LexEmbedParametersResult > LexEmbedParameters(Token &Current, bool ForHasEmbed)

Lex the parameters for an #embed directive, returns nullopt on error.

void EnterMacro(Token &Tok, SourceLocation ILEnd, MacroInfo *Macro, MacroArgs *Args)

Add a Macro to the top of the include stack and start lexing tokens from it instead of the current bu...

DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) const

Forwarding function for diagnostics.

void appendMacroDirective(IdentifierInfo *II, MacroDirective *MD)

Add a directive to the macro directive history for this identifier.

Represents an unpacked "presumed" location which can be presented to the user.

const char * getFilename() const

Return the presumed filename of this location.

unsigned getLine() const

Return the presumed line number of this location.

bool isInvalid() const

Return true if this object is invalid or uninitialized.

SourceLocation getIncludeLoc() const

Return the presumed include location of this location.

Encodes a location in the source.

bool isValid() const

Return true if this is a valid SourceLocation object.

PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const

Returns the "presumed" location of a SourceLocation specifies.

CharSourceRange getExpansionRange(SourceLocation Loc) const

Given a SourceLocation object, return the range of tokens covered by the expansion in the ultimate fi...

bool isInSystemHeader(SourceLocation Loc) const

Returns if a SourceLocation is in a system header.

const FileEntry * getFileEntryForID(FileID FID) const

Returns the FileEntry record for the provided FileID.

SourceLocation createExpansionLoc(SourceLocation SpellingLoc, SourceLocation ExpansionLocStart, SourceLocation ExpansionLocEnd, unsigned Length, bool ExpansionIsTokenRange=true, int LoadedID=0, SourceLocation::UIntTy LoadedOffset=0)

Creates an expansion SLocEntry for a macro use.

A trivial tuple used to represent a source range.

StringLiteralParser - This decodes string escape characters and performs wide string analysis and Tra...

Exposes information about the current target.

virtual bool supportsCpuSupports() const

virtual bool supportsCpuInit() const

const llvm::Triple & getTriple() const

Returns the target triple of the primary target.

const llvm::Triple * getDarwinTargetVariantTriple() const

Returns the darwin target variant triple, the variant of the deployment target for which the code is ...

virtual bool supportsCpuIs() const

TokenLexer - This implements a lexer that returns tokens from a macro body or token stream instead of...

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

IdentifierInfo * getIdentifierInfo() const

unsigned getFlags() const

Return the internal represtation of the flags.

void clearFlag(TokenFlags Flag)

Unset the specified flag.

SourceLocation getLocation() const

Return a source location identifier for the specified offset in the current file.

unsigned getLength() const

void setLength(unsigned Len)

void setKind(tok::TokenKind K)

bool is(tok::TokenKind K) const

is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {....

tok::TokenKind getKind() const

bool isAtStartOfLine() const

isAtStartOfLine - Return true if this token is at the start of a line.

bool hasLeadingSpace() const

Return true if this token has whitespace before it.

void setLocation(SourceLocation L)

bool isOneOf(tok::TokenKind K1, tok::TokenKind K2) const

bool isNot(tok::TokenKind K) const

bool isAnnotation() const

Return true if this is any of tok::annot_* kind tokens.

bool hasUDSuffix() const

Return true if this token is a string or character literal which has a ud-suffix.

void startToken()

Reset all flags to cleared.

void setIdentifierInfo(IdentifierInfo *II)

void setFlagValue(TokenFlags Flag, bool Val)

Set a flag to either true or false.

void setFlag(TokenFlags Flag)

Set the specified flag.

Defines the clang::TargetInfo interface.

bool evaluateRequiredTargetFeatures(llvm::StringRef RequiredFatures, const llvm::StringMap< bool > &TargetFetureMap)

Returns true if the required target features of a builtin function are enabled.

CharacteristicKind

Indicates whether a file or directory holds normal user code, system code, or system code which is im...

uint32_t Literal

Literals are represented as positive integers.

@ Error

Present this diagnostic as an error.

@ WarningOrError

A diagnostic that indicates a problem or potential problem.

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

@ Result

The result type of a method or function.

int hasAttribute(AttributeCommonInfo::Syntax Syntax, const IdentifierInfo *Scope, const IdentifierInfo *Attr, const TargetInfo &Target, const LangOptions &LangOpts)

Return the version number associated with the attribute if we recognize and implement the attribute s...

@ Braces

New-expression has a C++11 list-initializer.