clang: lib/Lex/PPDirectives.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
37#include "llvm/ADT/ArrayRef.h"
38#include "llvm/ADT/STLExtras.h"
39#include "llvm/ADT/ScopeExit.h"
40#include "llvm/ADT/SmallVector.h"
41#include "llvm/ADT/StringExtras.h"
42#include "llvm/ADT/StringRef.h"
43#include "llvm/ADT/StringSwitch.h"
44#include "llvm/Support/ErrorHandling.h"
45#include "llvm/Support/Path.h"
46#include "llvm/Support/SaveAndRestore.h"
47#include
48#include
49#include
50#include
51#include
52#include
53
54using namespace clang;
55
56
57
58
59
61 static_assert(std::is_trivially_destructible_v, "");
63}
64
68}
69
71Preprocessor::AllocateUndefMacroDirective(SourceLocation UndefLoc) {
73}
74
77 bool isPublic) {
79}
80
81
82
85
88 while (Tmp.isNot(tok::eod)) {
89 assert(Tmp.isNot(tok::eof) && "EOF seen while discarding directive tokens");
91 }
93 return Res;
94}
95
96
100 MD_ReservedMacro
102
103
104
110
112
113
114
115
116
117 static constexpr StringRef ReservedMacro[] = {
118 "_ATFILE_SOURCE",
119 "_BSD_SOURCE",
120 "_CRT_NONSTDC_NO_WARNINGS",
121 "_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES",
122 "_CRT_SECURE_NO_WARNINGS",
123 "_FILE_OFFSET_BITS",
124 "_FORTIFY_SOURCE",
125 "_GLIBCXX_ASSERTIONS",
126 "_GLIBCXX_CONCEPT_CHECKS",
127 "_GLIBCXX_DEBUG",
128 "_GLIBCXX_DEBUG_PEDANTIC",
129 "_GLIBCXX_PARALLEL",
130 "_GLIBCXX_PARALLEL_ASSERTIONS",
131 "_GLIBCXX_SANITIZE_VECTOR",
132 "_GLIBCXX_USE_CXX11_ABI",
133 "_GLIBCXX_USE_DEPRECATED",
134 "_GNU_SOURCE",
135 "_ISOC11_SOURCE",
136 "_ISOC95_SOURCE",
137 "_ISOC99_SOURCE",
138 "_LARGEFILE64_SOURCE",
139 "_POSIX_C_SOURCE",
140 "_REENTRANT",
141 "_SVID_SOURCE",
142 "_THREAD_SAFE",
143 "_XOPEN_SOURCE",
144 "_XOPEN_SOURCE_EXTENDED",
145 "__STDCPP_WANT_MATH_SPEC_FUNCS__",
146 "__STDC_FORMAT_MACROS",
147 };
148 return std::binary_search(std::begin(ReservedMacro), std::end(ReservedMacro),
149 MacroName);
150}
151
154 const StringRef MacroName) {
155
156
158 return true;
159
161 return false;
162
163
164 if (MacroName.starts_with("__STDC"))
165 return true;
166
167 if (MacroName == "__cplusplus")
168 return true;
169
170 if (MacroName.starts_with("__cpp"))
171 return true;
172
173 return false;
174}
175
183 if (Lang.CPlusPlus11 && (Text == "override" || Text == "final"))
186}
187
190
194}
195
196
197
198
199
200
202
203
204 if (::llvm::sys::path::begin(Include)->equals_insensitive("boost"))
205 return true;
206
207
208
209 static const size_t MaxStdHeaderNameLen = 18u;
210 if (Include.size() > MaxStdHeaderNameLen)
211 return false;
212
213
215 for (char &Ch : LowerInclude) {
216
217 if (static_cast<unsigned char>(Ch) > 0x7f)
218 return false;
219
220 if (Ch >= 'A' && Ch <= 'Z')
221 Ch += 'a' - 'A';
222
223 else if (::llvm::sys::path::is_separator(Ch))
224 Ch = '/';
225 }
226
227
228 return llvm::StringSwitch(LowerInclude)
229
230 .Cases("assert.h", "complex.h", "ctype.h", "errno.h", "fenv.h", true)
231 .Cases("float.h", "inttypes.h", "iso646.h", "limits.h", "locale.h", true)
232 .Cases("math.h", "setjmp.h", "signal.h", "stdalign.h", "stdarg.h", true)
233 .Cases("stdatomic.h", "stdbool.h", "stdckdint.h", "stddef.h", true)
234 .Cases("stdint.h", "stdio.h", "stdlib.h", "stdnoreturn.h", true)
235 .Cases("string.h", "tgmath.h", "threads.h", "time.h", "uchar.h", true)
236 .Cases("wchar.h", "wctype.h", true)
237
238
239 .Cases("cassert", "ccomplex", "cctype", "cerrno", "cfenv", true)
240 .Cases("cfloat", "cinttypes", "ciso646", "climits", "clocale", true)
241 .Cases("cmath", "csetjmp", "csignal", "cstdalign", "cstdarg", true)
242 .Cases("cstdbool", "cstddef", "cstdint", "cstdio", "cstdlib", true)
243 .Cases("cstring", "ctgmath", "ctime", "cuchar", "cwchar", true)
244 .Case("cwctype", true)
245
246
247 .Cases("algorithm", "fstream", "list", "regex", "thread", true)
248 .Cases("array", "functional", "locale", "scoped_allocator", "tuple", true)
249 .Cases("atomic", "future", "map", "set", "type_traits", true)
250 .Cases("bitset", "initializer_list", "memory", "shared_mutex", "typeindex", true)
251 .Cases("chrono", "iomanip", "mutex", "sstream", "typeinfo", true)
252 .Cases("codecvt", "ios", "new", "stack", "unordered_map", true)
253 .Cases("complex", "iosfwd", "numeric", "stdexcept", "unordered_set", true)
254 .Cases("condition_variable", "iostream", "ostream", "streambuf", "utility", true)
255 .Cases("deque", "istream", "queue", "string", "valarray", true)
256 .Cases("exception", "iterator", "random", "strstream", "vector", true)
257 .Cases("forward_list", "limits", "ratio", "system_error", true)
258
259
260 .Cases("aio.h", "arpa/inet.h", "cpio.h", "dirent.h", "dlfcn.h", true)
261 .Cases("fcntl.h", "fmtmsg.h", "fnmatch.h", "ftw.h", "glob.h", true)
262 .Cases("grp.h", "iconv.h", "langinfo.h", "libgen.h", "monetary.h", true)
263 .Cases("mqueue.h", "ndbm.h", "net/if.h", "netdb.h", "netinet/in.h", true)
264 .Cases("netinet/tcp.h", "nl_types.h", "poll.h", "pthread.h", "pwd.h", true)
265 .Cases("regex.h", "sched.h", "search.h", "semaphore.h", "spawn.h", true)
266 .Cases("strings.h", "stropts.h", "sys/ipc.h", "sys/mman.h", "sys/msg.h", true)
267 .Cases("sys/resource.h", "sys/select.h", "sys/sem.h", "sys/shm.h", "sys/socket.h", true)
268 .Cases("sys/stat.h", "sys/statvfs.h", "sys/time.h", "sys/times.h", "sys/types.h", true)
269 .Cases("sys/uio.h", "sys/un.h", "sys/utsname.h", "sys/wait.h", "syslog.h", true)
270 .Cases("tar.h", "termios.h", "trace.h", "ulimit.h", true)
271 .Cases("unistd.h", "utime.h", "utmpx.h", "wordexp.h", true)
272 .Default(false);
273}
274
275
276
277
278
279
280
281
282
283static std::optional
284findSimilarStr(StringRef LHS, const std::vector &Candidates) {
285
286
287 for (StringRef C : Candidates) {
288 if (LHS.equals_insensitive(C)) {
289 return C;
290 }
291 }
292
293
294
295
296 size_t Length = LHS.size();
297 size_t MaxDist = Length < 3 ? Length - 1 : Length / 3;
298
299 std::optional<std::pair<StringRef, size_t>> SimilarStr;
300 for (StringRef C : Candidates) {
301 size_t CurDist = LHS.edit_distance(C, true);
302 if (CurDist <= MaxDist) {
303 if (!SimilarStr) {
304
305 SimilarStr = {C, CurDist};
306 } else if (CurDist < SimilarStr->second) {
307
308 SimilarStr = {C, CurDist};
309 }
310 }
311 }
312
313 if (SimilarStr) {
314 return SimilarStr->first;
315 } else {
316 return std::nullopt;
317 }
318}
319
321 bool *ShadowFlag) {
322
323 if (MacroNameTok.is(tok::eod))
324 return Diag(MacroNameTok, diag::err_pp_missing_macro_name);
325
327 if (!II)
328 return Diag(MacroNameTok, diag::err_pp_macro_not_identifier);
329
331
332
334 ? diag::ext_pp_operator_used_as_macro_name
335 : diag::err_pp_operator_used_as_macro_name)
336 << II << MacroNameTok.getKind();
337
338
339 }
340
342
343 return Diag(MacroNameTok, diag::err_defined_macro_name);
344 }
345
346
347
349 if (ShadowFlag)
350 *ShadowFlag = false;
352 (SourceMgr.getBufferName(MacroNameLoc) != "")) {
354 if (isDefineUndef == MU_Define) {
356 }
357 else if (isDefineUndef == MU_Undef)
360
361
362
363 if (ShadowFlag)
364 *ShadowFlag = true;
365 }
367 Diag(MacroNameTok, diag::warn_pp_macro_is_reserved_id);
368 }
369
370
371 return false;
372}
373
374
375
376
377
378
379
380
381
382
383void Preprocessor::ReadMacroName(Token &MacroNameTok, MacroUse isDefineUndef,
384 bool *ShadowFlag) {
385
387
388 if (MacroNameTok.is(tok::code_completion)) {
389 if (CodeComplete)
393 }
394
395 if ((MacroNameTok, isDefineUndef, ShadowFlag))
396 return;
397
398
399
400 if (MacroNameTok.isNot(tok::eod)) {
401 MacroNameTok.setKind(tok::eod);
403 }
404}
405
406
407
408
409
410
411
413 bool EnableMacros) {
415
416
417
418 if (EnableMacros)
419 Lex(Tmp);
420 else
422
423
424
425 while (Tmp.is(tok::comment))
427
428 if (Tmp.is(tok::eod))
430
431
432
433
434
436 if ((LangOpts.GNUMode || LangOpts.C99 || LangOpts.CPlusPlus) &&
437 !CurTokenLexer)
439 Diag(Tmp, diag::ext_pp_extra_tokens_at_eol) << DirType << Hint;
441}
442
443void Preprocessor::SuggestTypoedDirective(const Token &Tok,
445
446
447 if (getLangOpts().AsmPreprocessor) return;
448
449 std::vector Candidates = {
450 "if", "ifdef", "ifndef", "elif", "else", "endif"
451 };
452 if (LangOpts.C23 || LangOpts.CPlusPlus23)
453 Candidates.insert(Candidates.end(), {"elifdef", "elifndef"});
454
456
461 StringRef SuggValue = *Sugg;
462
464 Diag(Tok, diag::warn_pp_invalid_directive) << 1 << SuggValue << Hint;
465 }
466}
467
468
469
470
471
472
473
474
475
476void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc,
478 bool FoundNonSkipPortion,
479 bool FoundElse,
481
482
483
484
485
486
487
488
489 assert(!SkippingExcludedConditionalBlock &&
490 "calling SkipExcludedConditionalBlock recursively");
492
493 ++NumSkipped;
494 assert(!CurTokenLexer && "Conditional PP block cannot appear in a macro!");
495 assert(CurPPLexer && "Conditional PP block must be in a file!");
496 assert(CurLexer && "Conditional PP block but no current lexer set!");
497
498 if (PreambleConditionalStack.reachedEOFWhileSkipping())
499 PreambleConditionalStack.clearSkipInfo();
500 else
502 FoundNonSkipPortion, FoundElse);
503
504
505
509
510
511
512 struct SkippingRangeStateTy {
514
515 const char *BeginPtr = nullptr;
516 unsigned *SkipRangePtr = nullptr;
517
518 SkippingRangeStateTy(Preprocessor &PP) : PP(PP) {}
519
520 void beginLexPass() {
521 if (BeginPtr)
522 return;
523
524
525
526 BeginPtr = PP.CurLexer->getBufferLocation();
527 SkipRangePtr = &PP.RecordedSkippedRanges[BeginPtr];
528 if (*SkipRangePtr) {
529 PP.CurLexer->seek(PP.CurLexer->getCurrentBufferOffset() + *SkipRangePtr,
530 true);
531 }
532 }
533
534 void endLexPass(const char *Hashptr) {
535 if (!BeginPtr) {
536
537 assert(PP.CurLexer->isDependencyDirectivesLexer());
538 return;
539 }
540
541
542 if (!*SkipRangePtr) {
543 *SkipRangePtr = Hashptr - BeginPtr;
544 }
545 assert(*SkipRangePtr == unsigned(Hashptr - BeginPtr));
546 BeginPtr = nullptr;
547 SkipRangePtr = nullptr;
548 }
549 } SkippingRangeState(*this);
550
551 while (true) {
552 if (CurLexer->isDependencyDirectivesLexer()) {
553 CurLexer->LexDependencyDirectiveTokenWhileSkipping(Tok);
554 } else {
555 SkippingRangeState.beginLexPass();
556 while (true) {
557 CurLexer->Lex(Tok);
558
559 if (Tok.is(tok::code_completion)) {
561 if (CodeComplete)
563 continue;
564 }
565
566
567 if (Tok.is(tok::eof)) {
568
569
570
571 if (PreambleConditionalStack.isRecording())
572 PreambleConditionalStack.SkipInfo.emplace(HashTokenLoc, IfTokenLoc,
573 FoundNonSkipPortion,
574 FoundElse, ElseLoc);
575 break;
576 }
577
578
580 continue;
581
582 break;
583 }
584 }
585 if (Tok.is(tok::eof))
586 break;
587
588
589
590
592 if (CurLexer) CurLexer->SetKeepWhitespaceMode(false);
593
594 assert(Tok.is(tok::hash));
595 const char *Hashptr = CurLexer->getBufferLocation() - Tok.getLength();
596 assert(CurLexer->getSourceLocation(Hashptr) == Tok.getLocation());
597
598
600
601
602
603 if (Tok.isNot(tok::raw_identifier)) {
605
606 if (CurLexer) CurLexer->resetExtendedTokenMode();
607 continue;
608 }
609
610
611
612
613
614
616
617 char FirstChar = RI[0];
618 if (FirstChar >= 'a' && FirstChar <= 'z' &&
619 FirstChar != 'i' && FirstChar != 'e') {
621
622 if (CurLexer) CurLexer->resetExtendedTokenMode();
623 continue;
624 }
625
626
627
628
629 char DirectiveBuf[20];
633 } else {
634 std::string DirectiveStr = getSpelling(Tok);
635 size_t IdLen = DirectiveStr.size();
636 if (IdLen >= 20) {
638
639 if (CurLexer) CurLexer->resetExtendedTokenMode();
640 continue;
641 }
642 memcpy(DirectiveBuf, &DirectiveStr[0], IdLen);
643 Directive = StringRef(DirectiveBuf, IdLen);
644 }
645
646 if (Directive.starts_with("if")) {
648 if (Sub.empty() ||
649 Sub == "def" ||
650 Sub == "ndef") {
651
652
655 false,
656 false);
657 } else {
658 SuggestTypoedDirective(Tok, Directive);
659 }
660 } else if (Directive[0] == 'e') {
662 if (Sub == "ndif") {
664 CondInfo.WasSkipping = true;
666 (void)InCond;
667 assert(!InCond && "Can't be skipping if not in a conditional!");
668
669
671 SkippingRangeState.endLexPass(Hashptr);
672
673
677 if (Callbacks)
679 break;
680 } else {
682 }
683 } else if (Sub == "lse") {
684
685
686
688
690 SkippingRangeState.endLexPass(Hashptr);
691
692
694 Diag(Tok, diag::pp_err_else_after_else);
695
696
698
699
700
703
704
708 if (Callbacks)
710 break;
711 } else {
713 }
714 } else if (Sub == "lif") {
716
718 SkippingRangeState.endLexPass(Hashptr);
719
720
722 Diag(Tok, diag::pp_err_elif_after_else) << PED_Elif;
723
724
725
727
728
729
730
732 } else {
733
734
735 assert(CurPPLexer->LexingRawMode && "We have to be skipping here!");
738 DirectiveEvalResult DER = EvaluateDirectiveExpression(IfNDefMacro);
739
740 if (!CurPPLexer)
741 return;
742 const bool CondValue = DER.Conditional;
744 if (Callbacks) {
745 Callbacks->Elif(
749 }
750
751 if (CondValue) {
753 break;
754 }
755 }
756 } else if (Sub == "lifdef" ||
757 Sub == "lifndef") {
758 bool IsElifDef = Sub == "lifdef";
760 Token DirectiveToken = Tok;
761
763 SkippingRangeState.endLexPass(Hashptr);
764
765
766
767 unsigned DiagID;
768 if (LangOpts.CPlusPlus)
769 DiagID = LangOpts.CPlusPlus23 ? diag::warn_cxx23_compat_pp_directive
770 : diag::ext_cxx23_pp_directive;
771 else
772 DiagID = LangOpts.C23 ? diag::warn_c23_compat_pp_directive
773 : diag::ext_c23_pp_directive;
775
776
778 Diag(Tok, diag::pp_err_elif_after_else)
780
781
782
784
785
786
787
789 } else {
790
791
792 assert(CurPPLexer->LexingRawMode && "We have to be skipping here!");
794 Token MacroNameTok;
795 ReadMacroName(MacroNameTok);
797
798
799
800 if (MacroNameTok.is(tok::eod)) {
801
802
803 continue;
804 }
805
807
809
812 MacroInfo *MI = MD.getMacroInfo();
813
814 if (Callbacks) {
815 if (IsElifDef) {
816 Callbacks->Elifdef(DirectiveToken.getLocation(), MacroNameTok,
817 MD);
818 } else {
819 Callbacks->Elifndef(DirectiveToken.getLocation(), MacroNameTok,
820 MD);
821 }
822 }
823
824 if (static_cast<bool>(MI) == IsElifDef) {
826 break;
827 }
828 }
829 } else {
830 SuggestTypoedDirective(Tok, Directive);
831 }
832 } else {
833 SuggestTypoedDirective(Tok, Directive);
834 }
835
837
838 if (CurLexer) CurLexer->resetExtendedTokenMode();
839 }
840
841
842
843
845
846
847
849 Callbacks->SourceRangeSkipped(
851 ? endLoc
854}
855
857 bool AllowTextual) {
859
860
863
867 }
868 }
869
870
871
873 ? nullptr
875}
876
881 IncLoc, LangOpts.ModulesValidateTextualHeaderIncludes);
882
883
884
885
886
889 auto ID = SM.getFileID(SM.getExpansionLoc(Loc));
890 auto FE = SM.getFileEntryRefForID(ID);
891 if (!FE)
892 break;
893
894
895
896 HeaderInfo.hasModuleMap(FE->getName(), nullptr,
898
899 bool InPrivateHeader = false;
901 if (!Header.isAccessibleFrom(IncM)) {
902
903
904
905
906 InPrivateHeader = true;
907 continue;
908 }
909
910
912 continue;
913
914
915
917 continue;
918
919
920
921
923 return std::nullopt;
924
925
926
927
928 return *FE;
929 }
930
931
932
933 if (InPrivateHeader)
934 return std::nullopt;
935
936
937
938
940 return *FE;
941
942 Loc = SM.getIncludeLoc(ID);
943 }
944
945 return std::nullopt;
946}
947
954 bool *IsFrameworkFound, bool SkipCache, bool OpenFile, bool CacheFailures) {
957
959 FilenameLoc, LangOpts.ModulesValidateTextualHeaderIncludes);
960
961
962
964 bool BuildSystemModule = false;
965 if (!FromDir && !FromFile) {
968
969
970
971
972
973
974
975
976
977
978
979
980
981 if (!FileEnt) {
982 if (FID == SourceMgr.getMainFileID() && MainFileDir) {
983 auto IncludeDir =
987 : MainFileDir;
988 Includers.push_back(std::make_pair(std::nullopt, *IncludeDir));
993 Includers.push_back(std::make_pair(*FileEnt, *CWD));
994 }
995 } else {
996 Includers.push_back(std::make_pair(*FileEnt, FileEnt->getDir()));
997 }
998
999
1000
1001
1002 if (LangOpts.MSVCCompat && !isAngled) {
1003 for (IncludeStackInfo &ISEntry : llvm::reverse(IncludeMacroStack)) {
1004 if (IsFileLexer(ISEntry))
1005 if ((FileEnt = ISEntry.ThePPLexer->getFileEntry()))
1006 Includers.push_back(std::make_pair(*FileEnt, FileEnt->getDir()));
1007 }
1008 }
1009 }
1010
1011 CurDir = CurDirLookup;
1012
1013 if (FromFile) {
1014
1015
1019 Filename, FilenameLoc, isAngled, TmpFromDir, &TmpCurDir,
1020 Includers, SearchPath, RelativePath, RequestingModule,
1021 SuggestedModule, nullptr,
1022 nullptr, SkipCache)) {
1023
1024 TmpFromDir = TmpCurDir;
1025 ++TmpFromDir;
1026 if (&FE->getFileEntry() == FromFile) {
1027
1028 FromDir = TmpFromDir;
1029 CurDir = TmpCurDir;
1030 break;
1031 }
1032 }
1033 }
1034
1035
1037 Filename, FilenameLoc, isAngled, FromDir, &CurDir, Includers, SearchPath,
1038 RelativePath, RequestingModule, SuggestedModule, IsMapped,
1039 IsFrameworkFound, SkipCache, BuildSystemModule, OpenFile, CacheFailures);
1040 if (FE)
1041 return FE;
1042
1044
1045
1046
1047 if (IsFileLexer()) {
1048 if ((CurFileEnt = CurPPLexer->getFileEntry())) {
1050 Filename, *CurFileEnt, SearchPath, RelativePath, RequestingModule,
1051 SuggestedModule)) {
1052 return FE;
1053 }
1054 }
1055 }
1056
1057 for (IncludeStackInfo &ISEntry : llvm::reverse(IncludeMacroStack)) {
1058 if (IsFileLexer(ISEntry)) {
1059 if ((CurFileEnt = ISEntry.ThePPLexer->getFileEntry())) {
1061 Filename, *CurFileEnt, SearchPath, RelativePath,
1062 RequestingModule, SuggestedModule)) {
1063 return FE;
1064 }
1065 }
1066 }
1067 }
1068
1069
1070 return std::nullopt;
1071}
1072
1075 const FileEntry *LookupFromFile) {
1077 if (llvm::sys::path::is_absolute(Filename)) {
1078
1080 Filename, OpenFile, true, false);
1081 return llvm::expectedToOptional(std::move(ShouldBeEntry));
1082 }
1083
1085 StringRef StartingFrom, StringRef FileName,
1086 bool RemoveInitialFileComponentFromLookupPath) {
1087 llvm::sys::path::native(StartingFrom, LookupPath);
1088 if (RemoveInitialFileComponentFromLookupPath)
1089 llvm::sys::path::remove_filename(LookupPath);
1090 if (!LookupPath.empty() &&
1091 !llvm::sys::path::is_separator(LookupPath.back())) {
1092 LookupPath.push_back(llvm::sys::path::get_separator().front());
1093 }
1095 };
1096
1097
1099
1100 if (!isAngled) {
1101 if (LookupFromFile) {
1102
1104 if (!FullFileDir.empty()) {
1105 SeparateComponents(LookupPath, FullFileDir, Filename, true);
1107 LookupPath, OpenFile, true, false);
1108 if (ShouldBeEntry)
1109 return llvm::expectedToOptional(std::move(ShouldBeEntry));
1110 llvm::consumeError(ShouldBeEntry.takeError());
1111 }
1112 }
1113
1114
1115 LookupPath.clear();
1117 if (MaybeWorkingDirEntry) {
1119 StringRef WorkingDir = WorkingDirEntry.getName();
1120 if (!WorkingDir.empty()) {
1121 SeparateComponents(LookupPath, WorkingDir, Filename, false);
1123 LookupPath, OpenFile, true, false);
1124 if (ShouldBeEntry)
1125 return llvm::expectedToOptional(std::move(ShouldBeEntry));
1126 llvm::consumeError(ShouldBeEntry.takeError());
1127 }
1128 }
1129 }
1130
1131 for (const auto &Entry : PPOpts->EmbedEntries) {
1132 LookupPath.clear();
1133 SeparateComponents(LookupPath, Entry, Filename, false);
1135 LookupPath, OpenFile, true, false);
1136 if (ShouldBeEntry)
1137 return llvm::expectedToOptional(std::move(ShouldBeEntry));
1138 llvm::consumeError(ShouldBeEntry.takeError());
1139 }
1140 return std::nullopt;
1141}
1142
1143
1144
1145
1146
1148public:
1150 : PP(pp), save(pp->DisableMacroExpansion) {
1151 if (pp->MacroExpansionInDirectivesOverride)
1152 pp->DisableMacroExpansion = false;
1153 }
1154
1156 PP->DisableMacroExpansion = save;
1157 }
1158
1159private:
1161 bool save;
1162};
1163
1164
1165
1166
1167
1168
1169
1173 if (II->getPPKeywordID() == tok::pp_define) {
1174 return HandleDefineDirective(Result,
1175 false);
1176 }
1177 if (SkippingUntilPCHThroughHeader &&
1178 II->getPPKeywordID() == tok::pp_include) {
1179 return HandleIncludeDirective(HashLoc, Result);
1180 }
1181 if (SkippingUntilPragmaHdrStop && II->getPPKeywordID() == tok::pp_pragma) {
1183 auto *II = Result.getIdentifierInfo();
1184 if (II && II->getName() == "hdrstop")
1186 }
1187 }
1189}
1190
1191
1192
1193
1194
1196
1197
1198
1199
1200
1202 if (CurLexer) CurLexer->SetKeepWhitespaceMode(false);
1203
1204 bool ImmediatelyAfterTopLevelIfndef =
1207
1208 ++NumDirectives;
1209
1210
1211
1212
1214
1215
1217
1218
1219
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230 if (InMacroArgs) {
1232 switch (II->getPPKeywordID()) {
1233 case tok::pp_include:
1234 case tok::pp_import:
1235 case tok::pp_include_next:
1236 case tok::pp___include_macros:
1237 case tok::pp_pragma:
1238 case tok::pp_embed:
1239 Diag(Result, diag::err_embedded_directive) << II->getName();
1240 Diag(*ArgMacro, diag::note_macro_expansion_here)
1243 return;
1244 default:
1245 break;
1246 }
1247 }
1248 Diag(Result, diag::ext_embedded_directive);
1249 }
1250
1251
1252
1254
1255 if (SkippingUntilPCHThroughHeader || SkippingUntilPragmaHdrStop)
1257
1258 switch (Result.getKind()) {
1259 case tok::eod:
1260
1261
1262
1264 return;
1265 case tok::code_completion:
1267 if (CodeComplete)
1270 return;
1271 case tok::numeric_constant:
1272
1273
1274
1277 break;
1278 return HandleDigitDirective(Result);
1279 default:
1281 if (!II) break;
1282
1283
1285 default: break;
1286
1287 case tok::pp_if:
1288 return HandleIfDirective(Result, SavedHash, ReadAnyTokensBeforeDirective);
1289 case tok::pp_ifdef:
1290 return HandleIfdefDirective(Result, SavedHash, false,
1291 true );
1292 case tok::pp_ifndef:
1293 return HandleIfdefDirective(Result, SavedHash, true,
1294 ReadAnyTokensBeforeDirective);
1295 case tok::pp_elif:
1296 case tok::pp_elifdef:
1297 case tok::pp_elifndef:
1299
1300 case tok::pp_else:
1301 return HandleElseDirective(Result, SavedHash);
1302 case tok::pp_endif:
1303 return HandleEndifDirective(Result);
1304
1305
1306 case tok::pp_include:
1307
1309 case tok::pp___include_macros:
1310
1311 return HandleIncludeMacrosDirective(SavedHash.getLocation(), Result);
1312
1313
1314 case tok::pp_define:
1315 return HandleDefineDirective(Result, ImmediatelyAfterTopLevelIfndef);
1316 case tok::pp_undef:
1317 return HandleUndefDirective();
1318
1319
1320 case tok::pp_line:
1321 return HandleLineDirective();
1322
1323
1324 case tok::pp_error:
1325 return HandleUserDiagnosticDirective(Result, false);
1326
1327
1328 case tok::pp_pragma:
1330
1331
1332 case tok::pp_import:
1334 case tok::pp_include_next:
1335 return HandleIncludeNextDirective(SavedHash.getLocation(), Result);
1336
1337 case tok::pp_warning:
1338 if (LangOpts.CPlusPlus)
1340 ? diag::warn_cxx23_compat_warning_directive
1341 : diag::ext_pp_warning_directive)
1342 << 1;
1343 else
1344 Diag(Result, LangOpts.C23 ? diag::warn_c23_compat_warning_directive
1345 : diag::ext_pp_warning_directive)
1346 << 0;
1347
1348 return HandleUserDiagnosticDirective(Result, true);
1349 case tok::pp_ident:
1350 return HandleIdentSCCSDirective(Result);
1351 case tok::pp_sccs:
1352 return HandleIdentSCCSDirective(Result);
1353 case tok::pp_embed:
1357 : static_cast<FileEntry *>(nullptr));
1358 case tok::pp_assert:
1359
1360 break;
1361 case tok::pp_unassert:
1362
1363 break;
1364
1365 case tok::pp___public_macro:
1367 return HandleMacroPublicDirective(Result);
1368 break;
1369
1370 case tok::pp___private_macro:
1372 return HandleMacroPrivateDirective();
1373 break;
1374 }
1375 break;
1376 }
1377
1378
1379
1380
1381
1383 auto Toks = std::make_unique<Token[]>(2);
1384
1385 Toks[0] = SavedHash;
1387
1388
1389
1390 if (Result.is(tok::hashhash))
1391 Toks[1].setKind(tok::unknown);
1392
1393
1394
1395
1396 EnterTokenStream(std::move(Toks), 2, false, false);
1397 return;
1398 }
1399
1400
1401
1402 Diag(Result, diag::err_pp_invalid_directive) << 0;
1403
1404
1406
1407
1408}
1409
1410
1411
1414 bool IsGNULineDirective=false) {
1415 if (DigitTok.isNot(tok::numeric_constant)) {
1416 PP.Diag(DigitTok, DiagID);
1417
1418 if (DigitTok.isNot(tok::eod))
1420 return true;
1421 }
1422
1424 IntegerBuffer.resize(DigitTok.getLength());
1425 const char *DigitTokBegin = &IntegerBuffer[0];
1427 unsigned ActualLength = PP.getSpelling(DigitTok, DigitTokBegin, &Invalid);
1429 return true;
1430
1431
1432
1433
1434 Val = 0;
1435 for (unsigned i = 0; i != ActualLength; ++i) {
1436
1437
1438 if (DigitTokBegin[i] == '\'')
1439 continue;
1440
1441 if ((DigitTokBegin[i])) {
1443 diag::err_pp_line_digit_sequence) << IsGNULineDirective;
1445 return true;
1446 }
1447
1448 unsigned NextVal = Val*10+(DigitTokBegin[i]-'0');
1449 if (NextVal < Val) {
1450 PP.Diag(DigitTok, DiagID);
1452 return true;
1453 }
1454 Val = NextVal;
1455 }
1456
1457 if (DigitTokBegin[0] == '0' && Val)
1458 PP.Diag(DigitTok.getLocation(), diag::warn_pp_line_decimal)
1459 << IsGNULineDirective;
1460
1461 return false;
1462}
1463
1464
1465
1466
1467
1468
1469
1470
1471void Preprocessor::HandleLineDirective() {
1472
1473
1475 Lex(DigitTok);
1476
1477
1478 unsigned LineNo;
1479 if (GetLineValue(DigitTok, LineNo, diag::err_pp_line_requires_integer,*this))
1480 return;
1481
1482 if (LineNo == 0)
1483 Diag(DigitTok, diag::ext_pp_line_zero);
1484
1485
1486
1487 unsigned LineLimit = 32768U;
1488 if (LangOpts.C99 || LangOpts.CPlusPlus11)
1489 LineLimit = 2147483648U;
1490 if (LineNo >= LineLimit)
1491 Diag(DigitTok, diag::ext_pp_line_too_big) << LineLimit;
1492 else if (LangOpts.CPlusPlus11 && LineNo >= 32768U)
1493 Diag(DigitTok, diag::warn_cxx98_compat_pp_line_too_big);
1494
1495 int FilenameID = -1;
1497 Lex(StrTok);
1498
1499
1500
1501 if (StrTok.is(tok::eod))
1502 ;
1503 else if (StrTok.isNot(tok::string_literal)) {
1504 Diag(StrTok, diag::err_pp_line_invalid_filename);
1506 return;
1508 Diag(StrTok, diag::err_invalid_string_udl);
1510 return;
1511 } else {
1512
1514 assert(Literal.isOrdinary() && "Didn't allow wide strings in");
1517 return;
1518 }
1520 Diag(StrTok, diag::err_pp_linemarker_invalid_filename);
1522 return;
1523 }
1525
1526
1527
1529 }
1530
1531
1532
1533
1534
1535
1538
1540 false, FileKind);
1541
1542 if (Callbacks)
1545}
1546
1547
1548
1552 unsigned FlagVal;
1554 PP.Lex(FlagTok);
1555 if (FlagTok.is(tok::eod)) return false;
1556 if (GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag, PP))
1557 return true;
1558
1559 if (FlagVal == 1) {
1560 IsFileEntry = true;
1561
1562 PP.Lex(FlagTok);
1563 if (FlagTok.is(tok::eod)) return false;
1564 if (GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag,PP))
1565 return true;
1566 } else if (FlagVal == 2) {
1567 IsFileExit = true;
1568
1570
1571
1573 SM.getDecomposedExpansionLoc(FlagTok.getLocation()).first;
1576 return true;
1577
1578
1579
1582 SM.getDecomposedExpansionLoc(IncLoc).first != CurFileID) {
1583 PP.Diag(FlagTok, diag::err_pp_linemarker_invalid_pop);
1585 return true;
1586 }
1587
1588 PP.Lex(FlagTok);
1589 if (FlagTok.is(tok::eod)) return false;
1590 if (GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag,PP))
1591 return true;
1592 }
1593
1594
1595 if (FlagVal != 3) {
1596 PP.Diag(FlagTok, diag::err_pp_linemarker_invalid_flag);
1598 return true;
1599 }
1600
1602
1603 PP.Lex(FlagTok);
1604 if (FlagTok.is(tok::eod)) return false;
1605 if (GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag, PP))
1606 return true;
1607
1608
1609 if (FlagVal != 4) {
1610 PP.Diag(FlagTok, diag::err_pp_linemarker_invalid_flag);
1612 return true;
1613 }
1614
1616
1617 PP.Lex(FlagTok);
1618 if (FlagTok.is(tok::eod)) return false;
1619
1620
1621 PP.Diag(FlagTok, diag::err_pp_linemarker_invalid_flag);
1623 return true;
1624}
1625
1626
1627
1628
1629
1630
1631
1632
1633void Preprocessor::HandleDigitDirective(Token &DigitTok) {
1634
1635
1636 unsigned LineNo;
1637 if (GetLineValue(DigitTok, LineNo, diag::err_pp_linemarker_requires_integer,
1638 *this, true))
1639 return;
1640
1642 Lex(StrTok);
1643
1644 bool IsFileEntry = false, IsFileExit = false;
1645 int FilenameID = -1;
1647
1648
1649
1650 if (StrTok.is(tok::eod)) {
1651 Diag(StrTok, diag::ext_pp_gnu_line_directive);
1652
1654 } else if (StrTok.isNot(tok::string_literal)) {
1655 Diag(StrTok, diag::err_pp_linemarker_invalid_filename);
1657 return;
1659 Diag(StrTok, diag::err_invalid_string_udl);
1661 return;
1662 } else {
1663
1665 assert(Literal.isOrdinary() && "Didn't allow wide strings in");
1668 return;
1669 }
1671 Diag(StrTok, diag::err_pp_linemarker_invalid_filename);
1673 return;
1674 }
1675
1676
1678 return;
1681 Diag(StrTok, diag::ext_pp_gnu_line_directive);
1682
1683
1684
1685 if (!(IsFileExit && Literal.GetString().empty()))
1687 }
1688
1689
1691 IsFileExit, FileKind);
1692
1693
1694
1695
1696 if (Callbacks) {
1698 if (IsFileEntry)
1700 else if (IsFileExit)
1702
1703 Callbacks->FileChanged(CurPPLexer->getSourceLocation(), Reason, FileKind);
1704 }
1705}
1706
1707
1708
1709void Preprocessor::HandleUserDiagnosticDirective(Token &Tok,
1710 bool isWarning) {
1711
1712
1713
1714
1715
1717 CurLexer->ReadToEndOfLine(&Message);
1718
1719
1720
1721 StringRef Msg = Message.str().ltrim(' ');
1722
1723 if (isWarning)
1724 Diag(Tok, diag::pp_hash_warning) << Msg;
1725 else
1726 Diag(Tok, diag::err_pp_hash_error) << Msg;
1727}
1728
1729
1730
1731void Preprocessor::HandleIdentSCCSDirective(Token &Tok) {
1732
1733 Diag(Tok, diag::ext_pp_ident_directive);
1734
1735
1737 Lex(StrTok);
1738
1739
1740 if (StrTok.isNot(tok::string_literal) &&
1741 StrTok.isNot(tok::wide_string_literal)) {
1742 Diag(StrTok, diag::err_pp_malformed_ident);
1743 if (StrTok.isNot(tok::eod))
1745 return;
1746 }
1747
1749 Diag(StrTok, diag::err_invalid_string_udl);
1751 return;
1752 }
1753
1754
1756
1757 if (Callbacks) {
1761 Callbacks->Ident(Tok.getLocation(), Str);
1762 }
1763}
1764
1765
1766void Preprocessor::HandleMacroPublicDirective(Token &Tok) {
1767 Token MacroNameTok;
1768 ReadMacroName(MacroNameTok, MU_Undef);
1769
1770
1771 if (MacroNameTok.is(tok::eod))
1772 return;
1773
1774
1776
1778
1780
1781
1782 if (!MD) {
1783 Diag(MacroNameTok, diag::err_pp_visibility_non_macro) << II;
1784 return;
1785 }
1786
1787
1789 MacroNameTok.getLocation(), true));
1790}
1791
1792
1793void Preprocessor::HandleMacroPrivateDirective() {
1794 Token MacroNameTok;
1795 ReadMacroName(MacroNameTok, MU_Undef);
1796
1797
1798 if (MacroNameTok.is(tok::eod))
1799 return;
1800
1801
1803
1805
1807
1808
1809 if (!MD) {
1810 Diag(MacroNameTok, diag::err_pp_visibility_non_macro) << II;
1811 return;
1812 }
1813
1814
1816 MacroNameTok.getLocation(), false));
1817}
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1830 StringRef &Buffer) {
1831
1832 assert(!Buffer.empty() && "Can't have tokens with empty spellings!");
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843 bool isAngled;
1844 if (Buffer[0] == '<') {
1845 if (Buffer.back() != '>') {
1846 Diag(Loc, diag::err_pp_expects_filename);
1847 Buffer = StringRef();
1848 return true;
1849 }
1850 isAngled = true;
1851 } else if (Buffer[0] == '"') {
1852 if (Buffer.back() != '"') {
1853 Diag(Loc, diag::err_pp_expects_filename);
1854 Buffer = StringRef();
1855 return true;
1856 }
1857 isAngled = false;
1858 } else {
1859 Diag(Loc, diag::err_pp_expects_filename);
1860 Buffer = StringRef();
1861 return true;
1862 }
1863
1864
1865 if (Buffer.size() <= 2) {
1866 Diag(Loc, diag::err_pp_empty_filename);
1867 Buffer = StringRef();
1868 return true;
1869 }
1870
1871
1872 Buffer = Buffer.substr(1, Buffer.size()-2);
1873 return isAngled;
1874}
1875
1876
1879 void *AnnotationVal) {
1880
1881
1882 auto Tok = std::make_unique<Token[]>(1);
1888 EnterTokenStream(std::move(Tok), 1, true, false);
1889}
1890
1891
1892
1895 ArrayRef<std::pair<IdentifierInfo *, SourceLocation>> Path,
1898 for (size_t I = 0, N = Path.size(); I != N; ++I) {
1899 if (I)
1900 PathString += '.';
1901 PathString += Path[I].first->getName();
1902 }
1903
1904 int IncludeKind = 0;
1906 case tok::pp_include:
1907 IncludeKind = 0;
1908 break;
1909
1910 case tok::pp_import:
1911 IncludeKind = 1;
1912 break;
1913
1914 case tok::pp_include_next:
1915 IncludeKind = 2;
1916 break;
1917
1918 case tok::pp___include_macros:
1919 IncludeKind = 3;
1920 break;
1921
1922 default:
1923 llvm_unreachable("unknown include directive kind");
1924 }
1925
1926 PP.Diag(HashLoc, diag::remark_pp_include_directive_modular_translation)
1927 << IncludeKind << PathString;
1928}
1929
1930
1931
1932
1934 StringRef RealPathName,
1935 llvm::sys::path::Style Separator) {
1936 auto RealPathComponentIter = llvm::sys::path::rbegin(RealPathName);
1937 auto RealPathComponentEnd = llvm::sys::path::rend(RealPathName);
1938 int Cnt = 0;
1939 bool SuggestReplacement = false;
1940
1941 auto IsSep = [Separator](StringRef Component) {
1942 return Component.size() == 1 &&
1943 llvm::sys::path::is_separator(Component[0], Separator);
1944 };
1945
1946
1947
1948 for (auto &Component : llvm::reverse(Components)) {
1949 if ("." == Component) {
1950 } else if (".." == Component) {
1951 ++Cnt;
1952 } else if (Cnt) {
1953 --Cnt;
1954 } else if (RealPathComponentIter != RealPathComponentEnd) {
1955 if (!IsSep(Component) && !IsSep(*RealPathComponentIter) &&
1956 Component != *RealPathComponentIter) {
1957
1958
1959
1960 SuggestReplacement =
1961 RealPathComponentIter->equals_insensitive(Component);
1962 if (!SuggestReplacement)
1963 break;
1964 Component = *RealPathComponentIter;
1965 }
1966 ++RealPathComponentIter;
1967 }
1968 }
1969 return SuggestReplacement;
1970}
1971
1978 Module *ShadowingModule = nullptr;
1980 ShadowingModule))
1981 return false;
1982
1984 Diags.Report(MissingHeader.FileNameLoc, diag::err_module_header_missing)
1986 } else if (ShadowingModule) {
1989 diag::note_previous_definition);
1990 } else {
1991
1992
1996 }
1997 return true;
1998}
1999
2000std::pair<ConstSearchDirIterator, const FileEntry *>
2001Preprocessor::getIncludeNextStart(const Token &IncludeNextTok) const {
2002
2003
2004
2006 const FileEntry *LookupFromFile = nullptr;
2007
2009
2010
2011
2013 Lookup = nullptr;
2014 Diag(IncludeNextTok, diag::pp_include_next_in_primary);
2015 } else if (CurLexerSubmodule) {
2016
2017
2018 assert(CurPPLexer && "#include_next directive in macro?");
2020 LookupFromFile = *FE;
2021 Lookup = nullptr;
2022 } else if (!Lookup) {
2023
2024
2025
2026
2027 Diag(IncludeNextTok, diag::pp_include_next_absolute_path);
2028 } else {
2029
2030 ++Lookup;
2031 }
2032
2033 return {Lookup, LookupFromFile};
2034}
2035
2036
2037
2038
2039
2040
2041void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
2042 Token &IncludeTok,
2044 const FileEntry *LookupFromFile) {
2045 Token FilenameTok;
2047 return;
2048
2049 if (FilenameTok.isNot(tok::header_name)) {
2050 Diag(FilenameTok.getLocation(), diag::err_pp_expects_filename);
2051 if (FilenameTok.isNot(tok::eod))
2053 return;
2054 }
2055
2056
2057
2058
2059
2062
2063 auto Action = HandleHeaderIncludeOrImport(HashLoc, IncludeTok, FilenameTok,
2064 EndLoc, LookupFrom, LookupFromFile);
2065 switch (Action.Kind) {
2066 case ImportAction::None:
2067 case ImportAction::SkippedModuleImport:
2068 break;
2069 case ImportAction::ModuleBegin:
2071 tok::annot_module_begin, Action.ModuleForHeader);
2072 break;
2073 case ImportAction::HeaderUnitImport:
2075 Action.ModuleForHeader);
2076 break;
2077 case ImportAction::ModuleImport:
2079 tok::annot_module_include, Action.ModuleForHeader);
2080 break;
2081 case ImportAction::Failure:
2083 "This should be an early exit only to a fatal error");
2085 IncludeTok.setKind(tok::eof);
2086 CurLexer->cutOffLexing();
2087 return;
2088 }
2089}
2090
2094 const Token &FilenameTok, bool &IsFrameworkFound, bool IsImportDecl,
2096 const FileEntry *LookupFromFile, StringRef &LookupFilename,
2099 auto DiagnoseHeaderInclusion = [&](FileEntryRef FE) {
2100 if (LangOpts.AsmPreprocessor)
2101 return;
2102
2104 FilenameLoc, LangOpts.ModulesValidateTextualHeaderIncludes);
2105 bool RequestingModuleIsModuleInterface =
2107
2109 RequestingModule, RequestingModuleIsModuleInterface, FilenameLoc,
2111 };
2112
2114 FilenameLoc, LookupFilename, isAngled, LookupFrom, LookupFromFile, CurDir,
2115 Callbacks ? &SearchPath : nullptr, Callbacks ? &RelativePath : nullptr,
2116 &SuggestedModule, &IsMapped, &IsFrameworkFound);
2118 DiagnoseHeaderInclusion(*File);
2119 return File;
2120 }
2121
2122
2123 if (Callbacks && Callbacks->FileNotFound(Filename))
2124 return std::nullopt;
2125
2126 if (SuppressIncludeNotFoundError)
2127 return std::nullopt;
2128
2129
2130
2131
2132 if (isAngled) {
2134 FilenameLoc, LookupFilename, false, LookupFrom, LookupFromFile, CurDir,
2135 Callbacks ? &SearchPath : nullptr, Callbacks ? &RelativePath : nullptr,
2136 &SuggestedModule, &IsMapped,
2137 nullptr);
2139 DiagnoseHeaderInclusion(*File);
2140 Diag(FilenameTok, diag::err_pp_file_not_found_angled_include_not_fatal)
2143 "\"" + Filename.str() + "\"");
2144 return File;
2145 }
2146 }
2147
2148
2149
2150 StringRef OriginalFilename = Filename;
2151 if (LangOpts.SpellChecking) {
2152
2153
2154 auto CorrectTypoFilename = [](llvm::StringRef Filename) {
2158 }
2160 };
2161 StringRef TypoCorrectionName = CorrectTypoFilename(Filename);
2162 StringRef TypoCorrectionLookupName = CorrectTypoFilename(LookupFilename);
2163
2165 FilenameLoc, TypoCorrectionLookupName, isAngled, LookupFrom,
2166 LookupFromFile, CurDir, Callbacks ? &SearchPath : nullptr,
2167 Callbacks ? &RelativePath : nullptr, &SuggestedModule, &IsMapped,
2168 nullptr);
2170 DiagnoseHeaderInclusion(*File);
2171 auto Hint =
2173 FilenameRange, "<" + TypoCorrectionName.str() + ">")
2175 FilenameRange, "\"" + TypoCorrectionName.str() + "\"");
2176 Diag(FilenameTok, diag::err_pp_file_not_found_typo_not_fatal)
2177 << OriginalFilename << TypoCorrectionName << Hint;
2178
2179
2180 Filename = TypoCorrectionName;
2181 LookupFilename = TypoCorrectionLookupName;
2182 return File;
2183 }
2184 }
2185
2186
2187 assert( && "expected missing file");
2188 Diag(FilenameTok, diag::err_pp_file_not_found)
2189 << OriginalFilename << FilenameRange;
2190 if (IsFrameworkFound) {
2191 size_t SlashPos = OriginalFilename.find('/');
2192 assert(SlashPos != StringRef::npos &&
2193 "Include with framework name should have '/' in the filename");
2194 StringRef FrameworkName = OriginalFilename.substr(0, SlashPos);
2197 assert(CacheEntry.Directory && "Found framework should be in cache");
2198 Diag(FilenameTok, diag::note_pp_framework_without_header)
2199 << OriginalFilename.substr(SlashPos + 1) << FrameworkName
2201 }
2202
2203 return std::nullopt;
2204}
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport(
2221 const FileEntry *LookupFromFile) {
2225
2228 StringRef OriginalFilename = Filename;
2229 bool isAngled =
2231
2232
2233
2235 return {ImportAction::None};
2236
2237 bool IsImportDecl = HashLoc.isInvalid();
2239
2240
2241 if (PragmaARCCFCodeAuditedInfo.second.isValid()) {
2242 Diag(StartLoc, diag::err_pp_include_in_arc_cf_code_audited) << IsImportDecl;
2243 Diag(PragmaARCCFCodeAuditedInfo.second, diag::note_pragma_entered_here);
2244
2245
2246 PragmaARCCFCodeAuditedInfo = {nullptr, SourceLocation()};
2247 }
2248
2249
2250 if (PragmaAssumeNonNullLoc.isValid()) {
2251 Diag(StartLoc, diag::err_pp_include_in_assume_nonnull) << IsImportDecl;
2252 Diag(PragmaAssumeNonNullLoc, diag::note_pragma_entered_here);
2253
2254
2256 }
2257
2259
2260
2261
2263 if (!NewName.empty())
2265 }
2266
2267
2268 bool IsMapped = false;
2269 bool IsFrameworkFound = false;
2273
2274
2277 StringRef LookupFilename = Filename;
2278
2279
2280
2282 llvm::sys::path::Style BackslashStyle = llvm::sys::path::Style::native;
2283 if (is_style_posix(BackslashStyle) && LangOpts.MicrosoftExt) {
2284 NormalizedPath = Filename.str();
2285 llvm::sys::path::native(NormalizedPath);
2286 LookupFilename = NormalizedPath;
2287 BackslashStyle = llvm::sys::path::Style::windows;
2288 }
2289
2291 &CurDir, Filename, FilenameLoc, FilenameRange, FilenameTok,
2292 IsFrameworkFound, IsImportDecl, IsMapped, LookupFrom, LookupFromFile,
2293 LookupFilename, RelativePath, SearchPath, SuggestedModule, isAngled);
2294
2297 SkippingUntilPCHThroughHeader = false;
2298 return {ImportAction::None};
2299 }
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316 enum { Enter, Import, Skip, IncludeLimitReached } Action = Enter;
2317
2318 if (PPOpts->SingleFileParseMode)
2319 Action = IncludeLimitReached;
2320
2321
2322
2323
2324 if (Action == Enter && HasReachedMaxIncludeDepth && File &&
2326 Action = IncludeLimitReached;
2327
2328
2329
2330
2332
2333 bool MaybeTranslateInclude = Action == Enter && File && ModuleToImport &&
2335
2336
2337 bool UsableHeaderUnit = false;
2338 if (getLangOpts().CPlusPlusModules && ModuleToImport &&
2340 if (TrackGMFState.inGMF() || IsImportDecl)
2341 UsableHeaderUnit = true;
2342 else if (!IsImportDecl) {
2343
2344 ModuleToImport = nullptr;
2345 }
2346 }
2347
2348 bool UsableClangHeaderModule =
2350 ModuleToImport && !ModuleToImport->isHeaderUnit();
2351
2352
2353
2354
2355 if (MaybeTranslateInclude && (UsableHeaderUnit || UsableClangHeaderModule)) {
2356
2357
2358
2359
2363 diag::note_implicit_top_level_module_import_here)
2365 return {ImportAction::None};
2366 }
2367
2368
2369
2370
2372 for (Module *Mod = ModuleToImport; Mod; Mod = Mod->Parent)
2375 std::reverse(Path.begin(), Path.end());
2376
2377
2378 if (!IsImportDecl)
2380
2381
2382
2383
2384
2387 true);
2388 assert((Imported == nullptr || Imported == ModuleToImport) &&
2389 "the imported module is different than the suggested one");
2390
2391 if (Imported) {
2395 static_cast<Module *>(Imported)->getTopLevelModule());
2396
2397
2398
2399
2400 ModuleToImport = nullptr;
2402
2403
2404 } else {
2405
2407
2409 assert(CurLexer && "#include but no current lexer set!");
2410 Result.startToken();
2411 CurLexer->FormTokenWithChars(Result, CurLexer->BufferEnd, tok::eof);
2412 CurLexer->cutOffLexing();
2413 }
2414 return {ImportAction::None};
2415 }
2416 }
2417
2418
2419
2420
2424 FileCharacter = std::max(HeaderInfo.getFileDirFlavor(*File), FileCharacter);
2425
2426
2427
2428
2429
2430
2431 bool EnterOnce =
2432 IsImportDecl ||
2434
2435 bool IsFirstIncludeOfFile = false;
2436
2437
2438
2439 if (Action == Enter && File &&
2442 IsFirstIncludeOfFile)) {
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453 if (UsableHeaderUnit && ().CompilingPCH)
2454 Action = TrackGMFState.inGMF() ? Import : Skip;
2455 else
2456 Action = (ModuleToImport && ().CompilingPCH) ? Import : Skip;
2457 }
2458
2459
2460
2461
2462
2463
2464 if (Action == Enter && File && PreambleConditionalStack.isRecording() &&
2467 diag::err_pp_including_mainfile_in_preamble);
2468 return {ImportAction::None};
2469 }
2470
2471 if (Callbacks && !IsImportDecl) {
2472
2473
2474 Callbacks->InclusionDirective(HashLoc, IncludeTok, LookupFilename, isAngled,
2475 FilenameRange, File, SearchPath, RelativePath,
2476 SuggestedModule.getModule(), Action == Import,
2477 FileCharacter);
2479 Callbacks->FileSkipped(*File, FilenameTok, FileCharacter);
2480 }
2481
2483 return {ImportAction::None};
2484
2485
2486
2487 if (IsImportDecl && !ModuleToImport) {
2488 Diag(FilenameTok, diag::err_header_import_not_header_unit)
2489 << OriginalFilename << File->getName();
2490 return {ImportAction::None};
2491 }
2492
2493
2494
2495 const bool CheckIncludePathPortability =
2496 !IsMapped && ->getFileEntry().tryGetRealPathName().empty();
2497
2498 if (CheckIncludePathPortability) {
2499 StringRef Name = LookupFilename;
2500 StringRef NameWithoriginalSlashes = Filename;
2501#if defined(_WIN32)
2502
2503
2504 bool NameWasUNC = Name.consume_front("\\\\?\\");
2505 NameWithoriginalSlashes.consume_front("\\\\?\\");
2506#endif
2507 StringRef RealPathName = File->getFileEntry().tryGetRealPathName();
2509 llvm::sys::path::end(Name));
2510#if defined(_WIN32)
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2522 if (llvm::sys::path::is_absolute(Name) &&
2523 llvm::sys::path::is_absolute(RealPathName) &&
2526 assert(Components.size() >= 3 && "should have drive, backslash, name");
2527 assert(Components[0].size() == 2 && "should start with drive");
2528 assert(Components[0][1] == ':' && "should have colon");
2529 FixedDriveRealPath = (Name.substr(0, 1) + RealPathName.substr(1)).str();
2530 RealPathName = FixedDriveRealPath;
2531 }
2532#endif
2533
2534 if (trySimplifyPath(Components, RealPathName, BackslashStyle)) {
2536 Path.reserve(Name.size()+2);
2537 Path.push_back(isAngled ? '<' : '"');
2538
2539 const auto IsSep = [BackslashStyle](char c) {
2540 return llvm::sys::path::is_separator(c, BackslashStyle);
2541 };
2542
2543 for (auto Component : Components) {
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555 if (!(Component.size() == 1 && IsSep(Component[0])))
2556 Path.append(Component);
2557 else if (Path.size() != 1)
2558 continue;
2559
2560
2561 if (Path.size() > NameWithoriginalSlashes.size()) {
2562 Path.push_back(isAngled ? '>' : '"');
2563 continue;
2564 }
2565 assert(IsSep(NameWithoriginalSlashes[Path.size()-1]));
2566 do
2567 Path.push_back(NameWithoriginalSlashes[Path.size()-1]);
2568 while (Path.size() <= NameWithoriginalSlashes.size() &&
2569 IsSep(NameWithoriginalSlashes[Path.size()-1]));
2570 }
2571
2572#if defined(_WIN32)
2573
2574 if (NameWasUNC)
2575 Path = (Path.substr(0, 1) + "\\\\?\\" + Path.substr(1)).str();
2576#endif
2577
2578
2579
2580 auto DiagId =
2582 ? diag::pp_nonportable_path
2583 : diag::pp_nonportable_system_path;
2584 Diag(FilenameTok, DiagId) << Path <<
2586 }
2587 }
2588
2589 switch (Action) {
2591
2592 if (ModuleToImport)
2593 return {ImportAction::SkippedModuleImport, ModuleToImport};
2594 return {ImportAction::None};
2595
2596 case IncludeLimitReached:
2597
2598
2599 return {ImportAction::None};
2600
2602
2603 assert(ModuleToImport && "no module to import");
2604
2606
2608 tok::pp___include_macros)
2609 return {ImportAction::None};
2610
2611 return {ImportAction::ModuleImport, ModuleToImport};
2612 }
2613
2614 case Enter:
2615 break;
2616 }
2617
2618
2619 if (IncludeMacroStack.size() == MaxAllowedIncludeStackDepth-1) {
2620 Diag(FilenameTok, diag::err_pp_include_too_deep);
2621 HasReachedMaxIncludeDepth = true;
2622 return {ImportAction::None};
2623 }
2624
2626 Diag(FilenameTok, diag::warn_pp_include_angled_in_module_purview)
2628
2629
2631
2632
2638 return ImportAction::Failure;
2639 }
2640
2641
2643 IsFirstIncludeOfFile))
2644 return {ImportAction::None};
2645
2646
2647
2648 if (ModuleToImport && !ModuleToImport->isHeaderUnit()) {
2650
2651
2653 diag::err_module_build_shadowed_submodule)
2656 diag::note_previous_definition);
2657 return {ImportAction::None};
2658 }
2659
2660
2661
2662
2663
2664
2665
2666
2669 return {ImportAction::None};
2670
2671 assert(!CurLexerSubmodule && "should not have marked this as a module yet");
2672 CurLexerSubmodule = ModuleToImport;
2673
2674
2675
2676 EnterSubmodule(ModuleToImport, EndLoc, false);
2677
2678
2679
2680
2681
2682 return {ImportAction::ModuleBegin, ModuleToImport};
2683 }
2684
2685 assert(!IsImportDecl && "failed to diagnose missing module for import decl");
2686 return {ImportAction::None};
2687}
2688
2689
2690
2691void Preprocessor::HandleIncludeNextDirective(SourceLocation HashLoc,
2692 Token &IncludeNextTok) {
2693 Diag(IncludeNextTok, diag::ext_pp_include_next_directive);
2694
2696 const FileEntry *LookupFromFile;
2697 std::tie(Lookup, LookupFromFile) = getIncludeNextStart(IncludeNextTok);
2698
2699 return HandleIncludeDirective(HashLoc, IncludeNextTok, Lookup,
2700 LookupFromFile);
2701}
2702
2703
2704void Preprocessor::HandleMicrosoftImportDirective(Token &Tok) {
2705
2706
2707
2708
2709
2710 Diag(Tok, diag::err_pp_import_directive_ms );
2711
2712
2713
2715}
2716
2717
2718
2719void Preprocessor::HandleImportDirective(SourceLocation HashLoc,
2720 Token &ImportTok) {
2721 if (!LangOpts.ObjC) {
2722 if (LangOpts.MSVCCompat)
2723 return HandleMicrosoftImportDirective(ImportTok);
2724 Diag(ImportTok, diag::ext_pp_import_directive);
2725 }
2726 return HandleIncludeDirective(HashLoc, ImportTok);
2727}
2728
2729
2730
2731
2732
2733void Preprocessor::HandleIncludeMacrosDirective(SourceLocation HashLoc,
2734 Token &IncludeMacrosTok) {
2735
2736
2740 diag::pp_include_macros_out_of_predefines);
2742 return;
2743 }
2744
2745
2746
2747 HandleIncludeDirective(HashLoc, IncludeMacrosTok);
2748
2750 do {
2751 Lex(TmpTok);
2752 assert(TmpTok.isNot(tok::eof) && "Didn't find end of -imacros!");
2753 } while (TmpTok.isNot(tok::hashhash));
2754}
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764bool Preprocessor::ReadMacroParameterList(MacroInfo *MI, Token &Tok) {
2766
2767 while (true) {
2769 switch (Tok.getKind()) {
2770 case tok::r_paren:
2771
2772 if (Parameters.empty())
2773 return false;
2774
2775 Diag(Tok, diag::err_pp_expected_ident_in_arg_list);
2776 return true;
2777 case tok::ellipsis:
2778 if (!LangOpts.C99)
2779 Diag(Tok, LangOpts.CPlusPlus11 ?
2780 diag::warn_cxx98_compat_variadic_macro :
2781 diag::ext_variadic_macro);
2782
2783
2784 if (LangOpts.OpenCL && !LangOpts.OpenCLCPlusPlus) {
2785 Diag(Tok, diag::ext_pp_opencl_variadic_macros);
2786 }
2787
2788
2790 if (Tok.isNot(tok::r_paren)) {
2791 Diag(Tok, diag::err_pp_missing_rparen_in_macro_def);
2792 return true;
2793 }
2794
2795 Parameters.push_back(Ident__VA_ARGS__);
2798 return false;
2799 case tok::eod:
2800 Diag(Tok, diag::err_pp_missing_rparen_in_macro_def);
2801 return true;
2802 default:
2803
2804
2806 if (!II) {
2807
2808 Diag(Tok, diag::err_pp_invalid_tok_in_arg_list);
2809 return true;
2810 }
2811
2812
2813
2814 if (llvm::is_contained(Parameters, II)) {
2815 Diag(Tok, diag::err_pp_duplicate_name_in_arg_list) << II;
2816 return true;
2817 }
2818
2819
2821
2822
2824
2825 switch (Tok.getKind()) {
2826 default:
2827 Diag(Tok, diag::err_pp_expected_comma_in_arg_list);
2828 return true;
2829 case tok::r_paren:
2831 return false;
2832 case tok::comma:
2833 break;
2834 case tok::ellipsis:
2835
2836 Diag(Tok, diag::ext_named_variadic_macro);
2837
2838
2840 if (Tok.isNot(tok::r_paren)) {
2841 Diag(Tok, diag::err_pp_missing_rparen_in_macro_def);
2842 return true;
2843 }
2844
2847 return false;
2848 }
2849 }
2850 }
2851}
2852
2857
2858
2860 return true;
2861
2862
2863
2864
2865
2866
2870 return false;
2871 StringRef ValueText = II->getName();
2872 StringRef TrimmedValue = ValueText;
2873 if (!ValueText.starts_with("__")) {
2874 if (ValueText.starts_with("_"))
2875 TrimmedValue = TrimmedValue.drop_front(1);
2876 else
2877 return false;
2878 } else {
2879 TrimmedValue = TrimmedValue.drop_front(2);
2880 if (TrimmedValue.ends_with("__"))
2881 TrimmedValue = TrimmedValue.drop_back(2);
2882 }
2883 return TrimmedValue == MacroText;
2884 } else {
2885 return false;
2886 }
2887 }
2888
2889
2890 return MacroName.isOneOf(tok::kw_extern, tok::kw_inline, tok::kw_static,
2891 tok::kw_const) &&
2893}
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903MacroInfo *Preprocessor::ReadOptionalMacroParameterListAndBody(
2904 const Token &MacroNameTok, const bool ImmediatelyAfterHeaderGuard) {
2905
2906 Token LastTok = MacroNameTok;
2907
2909
2912
2913
2914 auto _ = llvm::make_scope_exit([&]() {
2915
2916 if (CurLexer->ParsingPreprocessorDirective)
2918 });
2919
2920
2921
2923
2924
2925
2926
2927 if (Tok.is(tok::eod)) {
2928 if (ImmediatelyAfterHeaderGuard) {
2929
2932 }
2933
2935
2936
2938 } else if (Tok.is(tok::l_paren)) {
2939
2941 if (ReadMacroParameterList(MI, LastTok))
2942 return nullptr;
2943
2944
2945
2946
2947
2948
2951 }
2952
2953
2955 } else if (LangOpts.C99 || LangOpts.CPlusPlus11) {
2956
2957
2958 Diag(Tok, diag::ext_c99_whitespace_required_after_macro_name);
2959 } else {
2960
2961
2962
2963
2964
2965
2967 if (Tok.is(tok::at))
2969 else if (Tok.is(tok::unknown)) {
2970
2971
2972
2974 }
2976 Diag(Tok, diag::ext_missing_whitespace_after_macro_name);
2977 else
2978 Diag(Tok, diag::warn_missing_whitespace_after_macro_name);
2979 }
2980
2981 if (!Tok.is(tok::eod))
2982 LastTok = Tok;
2983
2985
2986
2988
2989 while (Tok.isNot(tok::eod)) {
2990 LastTok = Tok;
2991 Tokens.push_back(Tok);
2992
2994 }
2995 } else {
2996
2997
2998
2999
3001
3002 while (Tok.isNot(tok::eod)) {
3003 LastTok = Tok;
3004
3005 if (!Tok.isOneOf(tok::hash, tok::hashat, tok::hashhash)) {
3006 Tokens.push_back(Tok);
3007
3008 if (VAOCtx.isVAOptToken(Tok)) {
3009
3010 if (VAOCtx.isInVAOpt()) {
3011 Diag(Tok, diag::err_pp_vaopt_nested_use);
3012 return nullptr;
3013 }
3014
3016 if (Tok.isNot(tok::l_paren)) {
3017 Diag(Tok, diag::err_pp_missing_lparen_in_vaopt_use);
3018 return nullptr;
3019 }
3020 Tokens.push_back(Tok);
3021 VAOCtx.sawVAOptFollowedByOpeningParens(Tok.getLocation());
3023 if (Tok.is(tok::hashhash)) {
3024 Diag(Tok, diag::err_vaopt_paste_at_start);
3025 return nullptr;
3026 }
3027 continue;
3028 } else if (VAOCtx.isInVAOpt()) {
3029 if (Tok.is(tok::r_paren)) {
3030 if (VAOCtx.sawClosingParen()) {
3031 assert(Tokens.size() >= 3 &&
3032 "Must have seen at least __VA_OPT__( "
3033 "and a subsequent tok::r_paren");
3034 if (Tokens[Tokens.size() - 2].is(tok::hashhash)) {
3035 Diag(Tok, diag::err_vaopt_paste_at_end);
3036 return nullptr;
3037 }
3038 }
3039 } else if (Tok.is(tok::l_paren)) {
3040 VAOCtx.sawOpeningParen(Tok.getLocation());
3041 }
3042 }
3043
3045 continue;
3046 }
3047
3048
3049
3050
3052 Tok.setKind(tok::unknown);
3053 Tokens.push_back(Tok);
3054
3055
3057 continue;
3058 }
3059
3060 if (Tok.is(tok::hashhash)) {
3061
3062
3063
3064
3065
3067
3068 if (Tok.is(tok::eod)) {
3069 Tokens.push_back(LastTok);
3070 break;
3071 }
3072
3073 if (!Tokens.empty() && Tok.getIdentifierInfo() == Ident__VA_ARGS__ &&
3074 Tokens[Tokens.size() - 1].is(tok::comma))
3076
3077
3078 Tokens.push_back(LastTok);
3079 continue;
3080 }
3081
3082
3083
3085
3086
3087 if (!VAOCtx.isVAOptToken(Tok) &&
3090
3091
3092
3093
3094
3096 LastTok.setKind(tok::unknown);
3097 Tokens.push_back(LastTok);
3098 continue;
3099 } else {
3100 Diag(Tok, diag::err_pp_stringize_not_parameter)
3101 << LastTok.is(tok::hashat);
3102 return nullptr;
3103 }
3104 }
3105
3106
3107 Tokens.push_back(LastTok);
3108
3109
3110
3111
3112 if (!VAOCtx.isVAOptToken(Tok)) {
3113 Tokens.push_back(Tok);
3114 LastTok = Tok;
3115
3116
3118 }
3119 }
3120 if (VAOCtx.isInVAOpt()) {
3121 assert(Tok.is(tok::eod) && "Must be at End Of preprocessing Directive");
3122 Diag(Tok, diag::err_pp_expected_after)
3123 << LastTok.getKind() << tok::r_paren;
3124 Diag(VAOCtx.getUnmatchedOpeningParenLoc(), diag::note_matching) << tok::l_paren;
3125 return nullptr;
3126 }
3127 }
3129
3131 return MI;
3132}
3133
3135 return II->isStr("__strong") || II->isStr("__weak") ||
3136 II->isStr("__unsafe_unretained") || II->isStr("__autoreleasing");
3137}
3138
3139
3140
3141void Preprocessor::HandleDefineDirective(
3142 Token &DefineTok, const bool ImmediatelyAfterHeaderGuard) {
3143 ++NumDefined;
3144
3145 Token MacroNameTok;
3146 bool MacroShadowsKeyword;
3147 ReadMacroName(MacroNameTok, MU_Define, &MacroShadowsKeyword);
3148
3149
3150 if (MacroNameTok.is(tok::eod))
3151 return;
3152
3154
3155
3157 emitFinalMacroWarning(MacroNameTok, false);
3158
3159
3160
3161 if (CurLexer) CurLexer->SetCommentRetentionState(KeepMacroComments);
3162
3163 MacroInfo *const MI = ReadOptionalMacroParameterListAndBody(
3164 MacroNameTok, ImmediatelyAfterHeaderGuard);
3165
3166 if (!MI) return;
3167
3168 if (MacroShadowsKeyword &&
3170 Diag(MacroNameTok, diag::warn_pp_macro_hides_keyword);
3171 }
3172
3173
3175 if (NumTokens != 0) {
3178 return;
3179 }
3182 return;
3183 }
3184 }
3185
3186
3187 if (SkippingUntilPCHThroughHeader) {
3189 if (!OtherMI || !MI->isIdenticalTo(*OtherMI, *this,
3190 LangOpts.MicrosoftExt))
3193
3194 if (!LangOpts.MicrosoftExt)
3195 return;
3196 }
3197
3198
3199
3201
3202
3203
3205 emitFinalMacroWarning(MacroNameTok, false);
3206
3207
3208
3209
3214
3215 if ((().getSuppressSystemWarnings() ||
3218 LangOpts.MicrosoftExt)) {
3220 }
3222 return;
3223 }
3224
3225
3226
3227
3228 if (().getSuppressSystemWarnings() ||
3230
3233
3234
3235
3237 Diag(MacroNameTok, diag::ext_pp_redef_builtin_macro);
3238
3239
3241 !MI->isIdenticalTo(*OtherMI, *this, LangOpts.MicrosoftExt)) {
3245 }
3246 }
3249 }
3250
3253
3254 assert(!MI->isUsed());
3255
3256
3259 !MacroExpansionInDirectivesOverride &&
3264 }
3265
3266
3267 if (Callbacks)
3268 Callbacks->MacroDefined(MacroNameTok, MD);
3269
3270
3271
3272
3273
3278
3281 Tok.setKind(tok::kw__Static_assert);
3285 }
3286}
3287
3288
3289
3290void Preprocessor::HandleUndefDirective() {
3291 ++NumUndefined;
3292
3293 Token MacroNameTok;
3294 ReadMacroName(MacroNameTok, MU_Undef);
3295
3296
3297 if (MacroNameTok.is(tok::eod))
3298 return;
3299
3300
3302
3303
3307
3309 emitFinalMacroWarning(MacroNameTok, true);
3310
3311
3315
3316
3317
3319 Diag(MacroNameTok, diag::ext_pp_undef_builtin_macro);
3320
3323
3324 Undef = AllocateUndefMacroDirective(MacroNameTok.getLocation());
3325 }
3326
3327
3328
3329 if (Callbacks)
3330 Callbacks->MacroUndefined(MacroNameTok, MD, Undef);
3331
3332 if (Undef)
3334}
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345void Preprocessor::HandleIfdefDirective(Token &Result,
3346 const Token &HashToken,
3347 bool isIfndef,
3348 bool ReadAnyTokensBeforeDirective) {
3349 ++NumIf;
3351
3352 Token MacroNameTok;
3353 ReadMacroName(MacroNameTok);
3354
3355
3356 if (MacroNameTok.is(tok::eod)) {
3357
3358
3359 SkipExcludedConditionalBlock(HashToken.getLocation(),
3361 false, false);
3362 return;
3363 }
3364
3366
3367
3369
3373
3375
3376
3377
3378
3379 if (!ReadAnyTokensBeforeDirective && !MI) {
3380 assert(isIfndef && "#ifdef shouldn't reach here");
3382 } else
3384 }
3385
3386
3387 if (MI)
3389
3390 if (Callbacks) {
3391 if (isIfndef)
3392 Callbacks->Ifndef(DirectiveTok.getLocation(), MacroNameTok, MD);
3393 else
3394 Callbacks->Ifdef(DirectiveTok.getLocation(), MacroNameTok, MD);
3395 }
3396
3397 bool RetainExcludedCB = PPOpts->RetainExcludedConditionalBlocks &&
3399
3400
3401 if (PPOpts->SingleFileParseMode && !MI) {
3402
3403
3405 false, false,
3406 false);
3407 } else if (!MI == isIfndef || RetainExcludedCB) {
3408
3410 false, true,
3411 false);
3412 } else {
3413
3414 SkipExcludedConditionalBlock(HashToken.getLocation(),
3416 false,
3417 false);
3418 }
3419}
3420
3421
3422
3423void Preprocessor::HandleIfDirective(Token &IfToken,
3424 const Token &HashToken,
3425 bool ReadAnyTokensBeforeDirective) {
3426 ++NumIf;
3427
3428
3430 const DirectiveEvalResult DER = EvaluateDirectiveExpression(IfNDefMacro);
3431 const bool ConditionalTrue = DER.Conditional;
3432
3433
3434 if (!CurPPLexer)
3435 return;
3436
3437
3438
3440 if (!ReadAnyTokensBeforeDirective && IfNDefMacro && ConditionalTrue)
3441
3443 else
3445 }
3446
3447 if (Callbacks)
3448 Callbacks->If(
3451
3452 bool RetainExcludedCB = PPOpts->RetainExcludedConditionalBlocks &&
3454
3455
3456 if (PPOpts->SingleFileParseMode && DER.IncludedUndefinedIds) {
3457
3458
3460 false, false);
3461 } else if (ConditionalTrue || RetainExcludedCB) {
3462
3464 true, false);
3465 } else {
3466
3468 false,
3469 false);
3470 }
3471}
3472
3473
3474
3475void Preprocessor::HandleEndifDirective(Token &EndifToken) {
3476 ++NumEndif;
3477
3478
3480
3483
3484 Diag(EndifToken, diag::err_pp_endif_without_if);
3485 return;
3486 }
3487
3488
3491
3493 "This code should only be reachable in the non-skipping case!");
3494
3495 if (Callbacks)
3497}
3498
3499
3500
3501void Preprocessor::HandleElseDirective(Token &Result, const Token &HashToken) {
3502 ++NumElse;
3503
3504
3506
3509 Diag(Result, diag::pp_err_else_without_if);
3510 return;
3511 }
3512
3513
3516
3517
3519
3520 if (Callbacks)
3521 Callbacks->Else(Result.getLocation(), CI.IfLoc);
3522
3523 bool RetainExcludedCB = PPOpts->RetainExcludedConditionalBlocks &&
3525
3526 if ((PPOpts->SingleFileParseMode && !CI.FoundNonSkip) || RetainExcludedCB) {
3527
3528
3530 false, true);
3531 return;
3532 }
3533
3534
3535 SkipExcludedConditionalBlock(HashToken.getLocation(), CI.IfLoc,
3536 true,
3537 true, Result.getLocation());
3538}
3539
3540
3541void Preprocessor::HandleElifFamilyDirective(Token &ElifToken,
3542 const Token &HashToken,
3547 ++NumElse;
3548
3549
3550 switch (DirKind) {
3553 unsigned DiagID;
3554 if (LangOpts.CPlusPlus)
3555 DiagID = LangOpts.CPlusPlus23 ? diag::warn_cxx23_compat_pp_directive
3556 : diag::ext_cxx23_pp_directive;
3557 else
3558 DiagID = LangOpts.C23 ? diag::warn_c23_compat_pp_directive
3559 : diag::ext_c23_pp_directive;
3560 Diag(ElifToken, DiagID) << DirKind;
3561 break;
3562 default:
3563 break;
3564 }
3565
3566
3567
3568
3570
3573 Diag(ElifToken, diag::pp_err_elif_without_if) << DirKind;
3574 return;
3575 }
3576
3577
3580
3581
3583 Diag(ElifToken, diag::pp_err_elif_after_else) << DirKind;
3584
3585 if (Callbacks) {
3586 switch (Kind) {
3587 case tok::pp_elif:
3588 Callbacks->Elif(ElifToken.getLocation(), ConditionRange,
3590 break;
3591 case tok::pp_elifdef:
3592 Callbacks->Elifdef(ElifToken.getLocation(), ConditionRange, CI.IfLoc);
3593 break;
3594 case tok::pp_elifndef:
3595 Callbacks->Elifndef(ElifToken.getLocation(), ConditionRange, CI.IfLoc);
3596 break;
3597 default:
3598 assert(false && "unexpected directive kind");
3599 break;
3600 }
3601 }
3602
3603 bool RetainExcludedCB = PPOpts->RetainExcludedConditionalBlocks &&
3605
3606 if ((PPOpts->SingleFileParseMode && !CI.FoundNonSkip) || RetainExcludedCB) {
3607
3608
3610 false, false);
3611 return;
3612 }
3613
3614
3615 SkipExcludedConditionalBlock(
3618}
3619
3620std::optional
3624 tok::TokenKind EndTokenKind = ForHasEmbed ? tok::r_paren : tok::eod;
3625
3626 auto DiagMismatchedBracesAndSkipToEOD =
3628 std::pair<tok::TokenKind, SourceLocation> Matches) {
3629 Diag(CurTok, diag::err_expected) << Expected;
3630 Diag(Matches.second, diag::note_matching) << Matches.first;
3631 if (CurTok.isNot(tok::eod))
3633 };
3634
3635 auto ExpectOrDiagAndSkipToEOD = [&](tok::TokenKind Kind) {
3636 if (CurTok.isNot(Kind)) {
3637 Diag(CurTok, diag::err_expected) << Kind;
3638 if (CurTok.isNot(tok::eod))
3640 return false;
3641 }
3642 return true;
3643 };
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655 auto LexPPParameterName = [&]() -> std::optionalstd::string {
3656
3657
3658 if (!ExpectOrDiagAndSkipToEOD(tok::identifier))
3659 return std::nullopt;
3660
3662
3663
3664
3666 if (CurTok.is(tok::coloncolon)) {
3667
3669 if (!ExpectOrDiagAndSkipToEOD(tok::identifier))
3670 return std::nullopt;
3671
3673
3674
3676 return (llvm::Twine(Prefix->getName()) + "::" + Suffix->getName()).str();
3677 }
3678 return Prefix->getName().str();
3679 };
3680
3681
3682
3683
3684
3685 auto NormalizeParameterName = [](StringRef Name) {
3686 if (Name.size() > 4 && Name.starts_with("__") && Name.ends_with("__"))
3687 return Name.substr(2, Name.size() - 4);
3688 return Name;
3689 };
3690
3691 auto LexParenthesizedIntegerExpr = [&]() -> std::optional<size_t> {
3692
3693
3694 if (!ExpectOrDiagAndSkipToEOD(tok::l_paren))
3695 return std::nullopt;
3696
3697
3698
3700 bool EvaluatedDefined;
3701 DirectiveEvalResult LimitEvalResult = EvaluateDirectiveExpression(
3702 ParameterIfNDef, CurTok, EvaluatedDefined, false);
3703
3704 if (!LimitEvalResult.Value) {
3705
3706
3707 assert(CurTok.is(tok::eod) && "expect to be at the end of directive");
3708 return std::nullopt;
3709 }
3710
3711 if (!ExpectOrDiagAndSkipToEOD(tok::r_paren))
3712 return std::nullopt;
3713
3714
3716
3717
3718
3719 if (EvaluatedDefined) {
3720 Diag(CurTok, diag::err_defined_in_pp_embed);
3721 return std::nullopt;
3722 }
3723
3724 if (LimitEvalResult.Value) {
3725 const llvm::APSInt &Result = *LimitEvalResult.Value;
3726 if (Result.isNegative()) {
3727 Diag(CurTok, diag::err_requires_positive_value)
3729 return std::nullopt;
3730 }
3731 return Result.getLimitedValue();
3732 }
3733 return std::nullopt;
3734 };
3735
3736 auto GetMatchingCloseBracket = [](tok::TokenKind Kind) {
3737 switch (Kind) {
3738 case tok::l_paren:
3739 return tok::r_paren;
3740 case tok::l_brace:
3741 return tok::r_brace;
3742 case tok::l_square:
3743 return tok::r_square;
3744 default:
3745 llvm_unreachable("should not get here");
3746 }
3747 };
3748
3749 auto LexParenthesizedBalancedTokenSoup =
3751 std::vector<std::pair<tok::TokenKind, SourceLocation>> BracketStack;
3752
3753
3754 if (!ExpectOrDiagAndSkipToEOD(tok::l_paren))
3755 return false;
3757
3758 bool WaitingForInnerCloseParen = false;
3759 while (CurTok.isNot(tok::eod) &&
3760 (WaitingForInnerCloseParen || CurTok.isNot(tok::r_paren))) {
3761 switch (CurTok.getKind()) {
3762 default:
3763 break;
3764 case tok::l_paren:
3765 WaitingForInnerCloseParen = true;
3766 [[fallthrough]];
3767 case tok::l_brace:
3768 case tok::l_square:
3770 break;
3771 case tok::r_paren:
3772 WaitingForInnerCloseParen = false;
3773 [[fallthrough]];
3774 case tok::r_brace:
3775 case tok::r_square: {
3777 GetMatchingCloseBracket(BracketStack.back().first);
3778 if (BracketStack.empty() || CurTok.getKind() != Matching) {
3779 DiagMismatchedBracesAndSkipToEOD(Matching, BracketStack.back());
3780 return false;
3781 }
3782 BracketStack.pop_back();
3783 } break;
3784 }
3785 Tokens.push_back(CurTok);
3787 }
3788
3789
3790 if (!ExpectOrDiagAndSkipToEOD(tok::r_paren))
3791 return false;
3792
3794 return true;
3795 };
3796
3798 while (!CurTok.isOneOf(EndTokenKind, tok::eod)) {
3800 std::optionalstd::string ParamName = LexPPParameterName();
3801 if (!ParamName)
3802 return std::nullopt;
3803 StringRef Parameter = NormalizeParameterName(*ParamName);
3804
3805
3806
3807
3808
3810 if (Result.MaybeLimitParam)
3811 Diag(CurTok, diag::err_pp_embed_dup_params) << Parameter;
3812
3813 std::optional<size_t> Limit = LexParenthesizedIntegerExpr();
3814 if (!Limit)
3815 return std::nullopt;
3816 Result.MaybeLimitParam =
3818 } else if (Parameter == "clang::offset") {
3819 if (Result.MaybeOffsetParam)
3820 Diag(CurTok, diag::err_pp_embed_dup_params) << Parameter;
3821
3822 std::optional<size_t> Offset = LexParenthesizedIntegerExpr();
3823 if (!Offset)
3824 return std::nullopt;
3826 *Offset, {ParamStartLoc, CurTok.getLocation()}};
3827 } else if (Parameter == "prefix") {
3828 if (Result.MaybePrefixParam)
3829 Diag(CurTok, diag::err_pp_embed_dup_params) << Parameter;
3830
3832 if (!LexParenthesizedBalancedTokenSoup(Soup))
3833 return std::nullopt;
3835 std::move(Soup), {ParamStartLoc, CurTok.getLocation()}};
3836 } else if (Parameter == "suffix") {
3837 if (Result.MaybeSuffixParam)
3838 Diag(CurTok, diag::err_pp_embed_dup_params) << Parameter;
3839
3841 if (!LexParenthesizedBalancedTokenSoup(Soup))
3842 return std::nullopt;
3844 std::move(Soup), {ParamStartLoc, CurTok.getLocation()}};
3845 } else if (Parameter == "if_empty") {
3846 if (Result.MaybeIfEmptyParam)
3847 Diag(CurTok, diag::err_pp_embed_dup_params) << Parameter;
3848
3850 if (!LexParenthesizedBalancedTokenSoup(Soup))
3851 return std::nullopt;
3853 std::move(Soup), {ParamStartLoc, CurTok.getLocation()}};
3854 } else {
3855 ++Result.UnrecognizedParams;
3856
3857
3858
3859 if (CurTok.is(tok::l_paren)) {
3861 if (!LexParenthesizedBalancedTokenSoup(Soup))
3862 return std::nullopt;
3863 }
3864 if (!ForHasEmbed) {
3865 Diag(CurTok, diag::err_pp_unknown_parameter) << 1 << Parameter;
3866 return std::nullopt;
3867 }
3868 }
3869 }
3871}
3872
3873void Preprocessor::HandleEmbedDirectiveImpl(
3875 StringRef BinaryContents) {
3876 if (BinaryContents.empty()) {
3877
3878
3879
3880
3881
3884 size_t TokCount = Toks.size();
3885 auto NewToks = std::make_unique<Token[]>(TokCount);
3886 llvm::copy(Toks, NewToks.get());
3887 EnterTokenStream(std::move(NewToks), TokCount, true, true);
3888 }
3889 return;
3890 }
3891
3894 size_t TotalNumToks = 1 + NumPrefixToks + NumSuffixToks;
3895 size_t CurIdx = 0;
3896 auto Toks = std::make_unique<Token[]>(TotalNumToks);
3897
3898
3901 CurIdx += NumPrefixToks;
3902 }
3903
3905 Data->BinaryData = BinaryContents;
3906
3907 Toks[CurIdx].startToken();
3908 Toks[CurIdx].setKind(tok::annot_embed);
3909 Toks[CurIdx].setAnnotationRange(HashLoc);
3910 Toks[CurIdx++].setAnnotationValue(Data);
3911
3912
3915 CurIdx += NumSuffixToks;
3916 }
3917
3918 assert(CurIdx == TotalNumToks && "Calculated the incorrect number of tokens");
3919 EnterTokenStream(std::move(Toks), TotalNumToks, true, true);
3920}
3921
3922void Preprocessor::HandleEmbedDirective(SourceLocation HashLoc, Token &EmbedTok,
3923 const FileEntry *LookupFromFile) {
3924
3925 if (LangOpts.C23)
3926 Diag(EmbedTok, diag::warn_compat_pp_embed_directive);
3927 else
3928 Diag(EmbedTok, diag::ext_pp_embed_directive)
3929 << (LangOpts.CPlusPlus ? 1 : 0);
3930
3931
3932 Token FilenameTok;
3934 return;
3935
3936 if (FilenameTok.isNot(tok::header_name)) {
3937 Diag(FilenameTok.getLocation(), diag::err_pp_expects_filename);
3938 if (FilenameTok.isNot(tok::eod))
3940 return;
3941 }
3942
3943
3944
3945
3946
3947
3948
3949
3951 std::optional Params =
3953
3954 assert((Params || CurTok.is(tok::eod)) &&
3955 "expected success or to be at the end of the directive");
3956 if (!Params)
3957 return;
3958
3959
3962 StringRef OriginalFilename = Filename;
3963 bool isAngled =
3965
3966
3969 this->LookupEmbedFile(Filename, isAngled, true, LookupFromFile);
3970 if (!MaybeFileRef) {
3971
3972 if (Callbacks && Callbacks->EmbedFileNotFound(OriginalFilename)) {
3973 return;
3974 }
3975 Diag(FilenameTok, diag::err_pp_file_not_found) << Filename;
3976 return;
3977 }
3978 std::optionalllvm::MemoryBufferRef MaybeFile =
3980 if (!MaybeFile) {
3981
3982 Diag(FilenameTok, diag::err_cannot_open_file)
3983 << Filename << "a buffer to the contents could not be created";
3984 return;
3985 }
3986 StringRef BinaryContents = MaybeFile->getBuffer();
3987
3988
3989
3990
3991 if (Params->MaybeOffsetParam) {
3992
3993
3994
3995
3996 BinaryContents = BinaryContents.substr(Params->MaybeOffsetParam->Offset);
3997 }
3998
3999 if (Params->MaybeLimitParam) {
4000
4001
4002
4003 BinaryContents = BinaryContents.substr(0, Params->MaybeLimitParam->Limit);
4004 }
4005
4006 if (Callbacks)
4007 Callbacks->EmbedDirective(HashLoc, Filename, isAngled, MaybeFileRef,
4008 *Params);
4009 HandleEmbedDirectiveImpl(HashLoc, *Params, BinaryContents);
4010}
static bool isInMainFile(const clang::Diagnostic &D)
Defines interfaces for clang::DirectoryEntry and clang::DirectoryEntryRef.
Defines the clang::FileManager interface and associated types.
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Defines the clang::LangOptions interface.
Defines the clang::MacroInfo and clang::MacroDirective classes.
Defines the clang::Module class, which describes a module in the source code.
Defines the PPCallbacks interface.
static bool ReadLineMarkerFlags(bool &IsFileEntry, bool &IsFileExit, SrcMgr::CharacteristicKind &FileKind, Preprocessor &PP)
ReadLineMarkerFlags - Parse and validate any flags at the end of a GNU line marker directive.
static bool isConfigurationPattern(Token &MacroName, MacroInfo *MI, const LangOptions &LOptions)
static std::optional< StringRef > findSimilarStr(StringRef LHS, const std::vector< StringRef > &Candidates)
Find a similar string in Candidates.
static bool isLanguageDefinedBuiltin(const SourceManager &SourceMgr, const MacroInfo *MI, const StringRef MacroName)
static bool trySimplifyPath(SmallVectorImpl< StringRef > &Components, StringRef RealPathName, llvm::sys::path::Style Separator)
static void diagnoseAutoModuleImport(Preprocessor &PP, SourceLocation HashLoc, Token &IncludeTok, ArrayRef< std::pair< IdentifierInfo *, SourceLocation > > Path, SourceLocation PathEnd)
Produce a diagnostic informing the user that a #include or similar was implicitly treated as a module...
static bool warnByDefaultOnWrongCase(StringRef Include)
MacroDiag
Enumerates possible cases of #define/#undef a reserved identifier.
static bool isFeatureTestMacro(StringRef MacroName)
static bool GetLineValue(Token &DigitTok, unsigned &Val, unsigned DiagID, Preprocessor &PP, bool IsGNULineDirective=false)
GetLineValue - Convert a numeric token into an unsigned value, emitting Diagnostic DiagID if it is in...
PPElifDiag
Enumerates possible select values for the pp_err_elif_after_else and pp_err_elif_without_if diagnosti...
static MacroDiag shouldWarnOnMacroUndef(Preprocessor &PP, IdentifierInfo *II)
static bool isObjCProtectedMacro(const IdentifierInfo *II)
static MacroDiag shouldWarnOnMacroDef(Preprocessor &PP, IdentifierInfo *II)
Defines the clang::Preprocessor interface.
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
Defines the clang::SourceLocation class and associated facilities.
static bool isInvalid(LocType Loc, bool *Invalid)
Defines the SourceManager interface.
Defines the clang::TokenKind enum and support functions.
__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)
__device__ __2f16 float c
ResetMacroExpansionHelper(Preprocessor *pp)
~ResetMacroExpansionHelper()
Represents a character-granular source range.
static CharSourceRange getCharRange(SourceRange R)
SourceLocation getEnd() const
virtual void CodeCompleteMacroName(bool IsDefinition)
Callback invoked when performing code completion in a context where the name of a macro is expected.
virtual void CodeCompleteInConditionalExclusion()
Callback invoked when performing code completion within a block of code that was excluded due to prep...
virtual void CodeCompleteDirective(bool InConditional)
Callback invoked when performing code completion for a preprocessor directive.
A directive for a defined macro or a macro imported from a module.
Concrete class used by the front-end to report problems and issues.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
bool isIgnored(unsigned DiagID, SourceLocation Loc) const
Determine whether the diagnostic is known to be ignored.
A reference to a DirectoryEntry that includes the name of the directory as it was accessed by the Fil...
StringRef getName() const
A reference to a FileEntry that includes the name of the file as it was accessed by the FileManager's...
const FileEntry & getFileEntry() const
DirectoryEntryRef getDir() const
Cached information about one file (either on disk or in the virtual file system).
StringRef tryGetRealPathName() const
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
Implements support for file system lookup, file system caching, and directory search management.
llvm::Expected< DirectoryEntryRef > getDirectoryRef(StringRef DirName, bool CacheFailure=true)
Lookup, cache, and verify the specified directory (real or virtual).
OptionalDirectoryEntryRef getOptionalDirectoryRef(StringRef DirName, bool CacheFailure=true)
Get a DirectoryEntryRef if it exists, without doing anything on error.
LLVM_DEPRECATED("Functions returning DirectoryEntry are deprecated.", "getOptionalDirectoryRef()") llvm LLVM_DEPRECATED("Functions returning FileEntry are deprecated.", "getOptionalFileRef()") llvm llvm::Expected< FileEntryRef > getFileRef(StringRef Filename, bool OpenFile=false, bool CacheFailure=true, bool IsText=true)
Lookup, cache, and verify the specified directory (real or virtual).
Annotates a diagnostic with some code that should be inserted, removed, or replaced to fix the proble...
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.
tok::PPKeywordKind getPPKeywordID() const
Return the preprocessor keyword ID for this identifier.
bool isCPlusPlusOperatorKeyword() const
bool hadMacroDefinition() const
Returns true if this identifier was #defined to some value at any moment.
bool hasMacroDefinition() const
Return true if this identifier is #defined to some other value.
const char * getNameStart() const
Return the beginning of the actual null-terminated string for this identifier.
bool isKeyword(const LangOptions &LangOpts) const
Return true if this token is a keyword in the specified language.
ReservedIdentifierStatus isReserved(const LangOptions &LangOpts) const
Determine whether this is a name reserved for the implementation (C99 7.1.3, C++ [lib....
bool isStr(const char(&Str)[StrLen]) const
Return true if this is the identifier for the specified string.
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 IsHeaderFile
Indicates whether the front-end is explicitly told that the input is a header file (i....
std::string CurrentModule
The name of the current module, of which the main source file is a part.
Encapsulates changes to the "macros namespace" (the location where the macro name became active,...
const MacroInfo * getMacroInfo() const
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 isC99Varargs() const
bool isAllowRedefinitionsWithoutWarning() const
Return true if this macro can be redefined without warning.
void setHasCommaPasting()
unsigned getNumTokens() const
Return the number of tokens that this macro expands to.
const Token & getReplacementToken(unsigned Tok) const
void setDefinitionEndLoc(SourceLocation EndLoc)
Set the location of the last token in the macro.
bool isBuiltinMacro() const
Return true if this macro requires processing before expansion.
void setTokens(ArrayRef< Token > Tokens, llvm::BumpPtrAllocator &PPAllocator)
void setParameterList(ArrayRef< IdentifierInfo * > List, llvm::BumpPtrAllocator &PPAllocator)
Set the specified list of identifiers as the parameter list for this macro.
SourceLocation getDefinitionLoc() const
Return the location that the macro was defined at.
void setIsFunctionLike()
Function/Object-likeness.
bool isObjectLike() const
void setIsWarnIfUnused(bool val)
Set the value of the IsWarnIfUnused flag.
int getParameterNum(const IdentifierInfo *Arg) const
Return the parameter number of the specified identifier, or -1 if the identifier is not a formal para...
bool isWarnIfUnused() const
Return true if we should emit a warning if the macro is unused.
void setIsC99Varargs()
Varargs querying methods. This can only be set for function-like macros.
Describes the result of attempting to load a module.
bool isMissingExpected() const
Determines whether the module, which failed to load, was actually a submodule that we expected to see...
bool isConfigMismatch() const
Determines whether the module failed to load due to a configuration mismatch with an explicitly-named...
virtual ModuleLoadResult loadModule(SourceLocation ImportLoc, ModuleIdPath Path, Module::NameVisibilityKind Visibility, bool IsInclusionDirective)=0
Attempt to load the given module.
void diagnoseHeaderInclusion(Module *RequestingModule, bool RequestingModuleIsModuleInterface, SourceLocation FilenameLoc, StringRef Filename, FileEntryRef File)
Reports errors if a module must not include a specific file.
KnownHeader findModuleForHeader(FileEntryRef File, bool AllowTextual=false, bool AllowExcluded=false)
Retrieve the module that owns the given header file, if any.
bool shouldImportRelativeToBuiltinIncludeDir(StringRef FileName, Module *Module) const
OptionalDirectoryEntryRef getBuiltinDir() const
Get the directory that contains Clang-supplied include files.
@ ExcludedHeader
This header is explicitly excluded from the module.
@ TextualHeader
This header is part of the module (for layering purposes) but should be textually included.
Describes a module or submodule.
StringRef getTopLevelModuleName() const
Retrieve the name of the top-level module.
bool isForBuilding(const LangOptions &LangOpts) const
Determine whether this module can be built in this compilation.
@ Hidden
All of the names in this module are hidden.
SourceLocation DefinitionLoc
The location of the module definition.
Module * Parent
The parent of this module.
unsigned IsSystem
Whether this is a "system" module (which assumes that all headers in it are system headers).
std::string Name
The name of this module.
bool isAvailable() const
Determine whether this module is available for use within the current translation unit.
bool isHeaderUnit() const
Is this module a header unit.
Module * ShadowingModule
A module with the same name that shadows this module.
std::string getFullModuleName(bool AllowStringLiterals=false) const
Retrieve the full name of this module, including the path from its top-level module.
Module * getTopLevelModule()
Retrieve the top-level module for this (sub)module, which may be this module.
bool getHasReadAnyTokensVal() const
getHasReadAnyTokensVal - This is used for the #ifndef handshake at the top of the file when reading p...
void ExitTopLevelConditional()
Called when the lexer exits the top-level conditional.
void SetDefinedMacro(IdentifierInfo *M, SourceLocation Loc)
void SetReadToken(bool Value)
SetReadToken - Set whether the value of 'ReadAnyTokens'.
bool getImmediatelyAfterTopLevelIfndef() const
getImmediatelyAfterTopLevelIfndef - returns true if the last directive was an #ifndef at the beginnin...
void EnterTopLevelConditional()
Invoked when a top level conditional (except #ifndef) is found.
void resetImmediatelyAfterTopLevelIfndef()
void EnterTopLevelIfndef(const IdentifierInfo *M, SourceLocation Loc)
Called when entering a top-level #ifndef directive (or the "\#if !defined" equivalent) without any pr...
Preprocessor standard embed parameter "if_empty" if_empty( balanced-token-seq )
Preprocessor standard embed parameter "limit" limit( constant-expression )
Preprocessor extension embed parameter "clang::offset" clang::offset( constant-expression )
Preprocessor standard embed parameter "prefix" prefix( balanced-token-seq )
Preprocessor standard embed parameter "suffix" suffix( balanced-token-seq )
void pushConditionalLevel(SourceLocation DirectiveStart, bool WasSkipping, bool FoundNonSkip, bool FoundElse)
pushConditionalLevel - When we enter a #if directive, this keeps track of what we are currently in fo...
unsigned getConditionalStackDepth() const
bool LexingRawMode
True if in raw mode.
bool ParsingPreprocessorDirective
True when parsing #XXX; turns '\n' into a tok::eod token.
MultipleIncludeOpt MIOpt
A state machine that detects the #ifndef-wrapping a file idiom for the multiple-include optimization.
bool popConditionalLevel(PPConditionalInfo &CI)
popConditionalLevel - Remove an entry off the top of the conditional stack, returning information abo...
OptionalFileEntryRef getFileEntry() const
getFileEntry - Return the FileEntry corresponding to this FileID.
PPConditionalInfo & peekConditionalLevel()
Return the top of the conditional stack.
virtual SourceLocation getSourceLocation()=0
Return the source location for the next observable location.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
MacroDirective * getLocalMacroDirective(const IdentifierInfo *II) const
Given an identifier, return its latest non-imported MacroDirective if it is #define'd and not #undef'...
void markClangModuleAsAffecting(Module *M)
Mark the given clang module as affecting the current clang module or translation unit.
OptionalFileEntryRef LookupEmbedFile(StringRef Filename, bool isAngled, bool OpenFile, const FileEntry *LookupFromFile=nullptr)
Given a "Filename" or reference, look up the indicated embed resource.
const MacroInfo * getMacroInfo(const IdentifierInfo *II) const
bool isRecordingPreamble() const
void HandleSkippedDirectiveWhileUsingPCH(Token &Result, SourceLocation HashLoc)
Process directives while skipping until the through header or #pragma hdrstop is found.
bool isInPrimaryFile() const
Return true if we're in the top-level file, not in a #include.
void markMacroAsUsed(MacroInfo *MI)
A macro is used, update information about macros that need unused warnings.
void EnterSubmodule(Module *M, SourceLocation ImportLoc, bool ForPragma)
void setCodeCompletionReached()
Note that we hit the code-completion point.
StringRef getNamedModuleName() const
Get the named module name we're preprocessing.
void makeModuleVisible(Module *M, SourceLocation Loc)
void Lex(Token &Result)
Lex the next token for this preprocessor.
bool EnterSourceFile(FileID FID, ConstSearchDirIterator Dir, SourceLocation Loc, bool IsFirstIncludeOfFile=true)
Add a source file to the top of the include stack and start lexing tokens from it instead of the curr...
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.
SourceLocation CheckEndOfDirective(const char *DirType, bool EnableMacros=false)
Ensure that the next token is a tok::eod token.
IdentifierInfo * getIdentifierInfo(StringRef Name) const
Return information about the specified preprocessor identifier token.
SourceManager & getSourceManager() const
MacroDefinition getMacroDefinition(const IdentifierInfo *II)
bool CheckMacroName(Token &MacroNameTok, MacroUse isDefineUndef, bool *ShadowFlag=nullptr)
bool isMacroDefined(StringRef Id)
static bool checkModuleIsAvailable(const LangOptions &LangOpts, const TargetInfo &TargetInfo, const Module &M, DiagnosticsEngine &Diags)
Check that the given module is available, producing a diagnostic if not.
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...
Module * getCurrentModule()
Retrieves the module that we're currently building, if any.
bool hadModuleLoaderFatalFailure() const
const TargetInfo & getTargetInfo() const
FileManager & getFileManager() const
bool LexHeaderName(Token &Result, bool AllowMacroExpansion=true)
Lex a token, forming a header-name token if possible.
bool isPCHThroughHeader(const FileEntry *FE)
Returns true if the FileEntry is the PCH through header.
friend class VariadicMacroScopeGuard
MacroInfo * AllocateMacroInfo(SourceLocation L)
Allocate a new MacroInfo object with the provided SourceLocation.
void LexUnexpandedToken(Token &Result)
Just like Lex, but disables macro expansion of identifier tokens.
bool alreadyIncluded(FileEntryRef File) const
Return true if this header has already been included.
FileID getPredefinesFileID() const
Returns the FileID for the preprocessor predefines.
void LexUnexpandedNonComment(Token &Result)
Like LexNonComment, but this disables macro expansion of identifier tokens.
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
void HandleDirective(Token &Result)
Callback invoked when the lexer sees a # token at the start of a line.
void EnterAnnotationToken(SourceRange Range, tok::TokenKind Kind, void *AnnotationVal)
Enter an annotation token into the token stream.
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.
const LangOptions & getLangOpts() const
bool isInNamedModule() const
If we are preprocessing a named module.
OptionalFileEntryRef getHeaderToIncludeForDiagnostics(SourceLocation IncLoc, SourceLocation MLoc)
We want to produce a diagnostic at location IncLoc concerning an unreachable effect at location MLoc ...
DefMacroDirective * appendDefMacroDirective(IdentifierInfo *II, MacroInfo *MI, SourceLocation Loc)
void HandlePragmaHdrstop(Token &Tok)
DiagnosticsEngine & getDiagnostics() const
std::optional< LexEmbedParametersResult > LexEmbedParameters(Token &Current, bool ForHasEmbed)
Lex the parameters for an #embed directive, returns nullopt on error.
Module * getModuleForLocation(SourceLocation Loc, bool AllowTextual)
Find the module that owns the source or header file that Loc points to.
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) const
Forwarding function for diagnostics.
bool usingPCHWithThroughHeader()
True if using a PCH with a through header.
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.
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.
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.
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
bool isWrittenInBuiltinFile(SourceLocation Loc) const
Returns whether Loc is located in a file.
bool isInMainFile(SourceLocation Loc) const
Returns whether the PresumedLoc for a given SourceLocation is in the main file.
void AddLineNote(SourceLocation Loc, unsigned LineNo, int FilenameID, bool IsFileEntry, bool IsFileExit, SrcMgr::CharacteristicKind FileKind)
Add a line note to the line table for the FileID and offset specified by Loc.
bool isWrittenInCommandLineFile(SourceLocation Loc) const
Returns whether Loc is located in a file.
OptionalFileEntryRef getFileEntryRefForID(FileID FID) const
Returns the FileEntryRef for the provided FileID.
StringRef getBufferName(SourceLocation Loc, bool *Invalid=nullptr) const
Return the filename or buffer identifier of the buffer the location is in.
FileID createFileID(FileEntryRef SourceFile, SourceLocation IncludePos, SrcMgr::CharacteristicKind FileCharacter, int LoadedID=0, SourceLocation::UIntTy LoadedOffset=0)
Create a new FileID that represents the specified file being #included from the specified IncludePosi...
bool isMainFile(const FileEntry &SourceFile)
Returns true when the given FileEntry corresponds to the main file.
FileID getMainFileID() const
Returns the FileID of the main source file.
CharSourceRange getExpansionRange(SourceLocation Loc) const
Given a SourceLocation object, return the range of tokens covered by the expansion in the ultimate fi...
unsigned getLineTableFilenameID(StringRef Str)
Return the uniqued ID for the specified filename.
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
SrcMgr::CharacteristicKind getFileCharacteristic(SourceLocation Loc) const
Return the file characteristic of the specified source location, indicating whether this is a normal ...
SourceLocation getExpansionLoc(SourceLocation Loc) const
Given a SourceLocation object Loc, return the expansion location referenced by the ID.
std::optional< llvm::MemoryBufferRef > getMemoryBufferForFileOrNone(FileEntryRef File)
Retrieve the memory buffer associated with the given file.
A trivial tuple used to represent a source range.
void setBegin(SourceLocation b)
SourceLocation getEnd() const
SourceLocation getBegin() const
void setEnd(SourceLocation e)
StringLiteralParser - This decodes string escape characters and performs wide string analysis and Tra...
Exposes information about the current target.
Token - This structure provides full information about a lexed token.
IdentifierInfo * getIdentifierInfo() const
SourceLocation getEndLoc() const
void setAnnotationEndLoc(SourceLocation L)
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 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
void setAnnotationValue(void *val)
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.
bool needsCleaning() const
Return true if this token has trigraphs or escaped newlines in it.
void setIdentifierInfo(IdentifierInfo *II)
StringRef getRawIdentifier() const
getRawIdentifier - For a raw identifier token (i.e., an identifier lexed in raw mode),...
A directive for an undefined macro.
A class for tracking whether we're inside a VA_OPT during a traversal of the tokens of a variadic mac...
An RAII class that tracks when the Preprocessor starts and stops lexing the definition of a (ISO C/C+...
void enterScope()
Client code should call this function just before the Preprocessor is about to Lex tokens from the de...
Directive - Abstract class representing a parsed verify directive.
A directive for setting the module visibility of a macro.
Defines the clang::TargetInfo interface.
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.
bool Sub(InterpState &S, CodePtr OpPC)
TokenKind
Provides a simple uniform namespace for tokens from all C languages.
PPKeywordKind
Provides a namespace for preprocessor keywords which start with a '#' at the beginning of the line.
The JSON file list parser is used to communicate input to InstallAPI.
bool isReservedInAllContexts(ReservedIdentifierStatus Status)
Determine whether an identifier is reserved in all contexts.
LLVM_READONLY char toLowercase(char c)
Converts the given ASCII character to its lowercase equivalent.
MacroUse
Context in which macro name is used.
LLVM_READONLY bool isAlphanumeric(unsigned char c)
Return true if this character is an ASCII letter or digit: [a-zA-Z0-9].
@ Parameter
The parameter type of a method or function.
@ 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 isLowercase(unsigned char c)
Return true if this character is a lowercase ASCII letter: [a-z].
@ PIK_HashPragma
The pragma was introduced via #pragma.
Helper class to shuttle information about #embed directives from the preprocessor to the parser throu...
This structure is used to record entries in our framework cache.
OptionalDirectoryEntryRef Directory
The directory entry which should be used for the cached framework.
std::optional< PPEmbedParameterIfEmpty > MaybeIfEmptyParam
size_t SuffixTokenCount() const
std::optional< PPEmbedParameterSuffix > MaybeSuffixParam
std::optional< PPEmbedParameterPrefix > MaybePrefixParam
size_t PrefixTokenCount() const
Information about the conditional stack (#if directives) currently active.
bool FoundNonSkip
True if we have emitted tokens already, and now we're in an #else block or something.
SourceLocation IfLoc
Location where the conditional started.
bool WasSkipping
True if this was contained in a skipping directive, e.g., in a "\#if 0" block.
bool FoundElse
True if we've seen a #else in this block.