clang: lib/Lex/PPDirectives.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
39#include "llvm/ADT/ArrayRef.h"
40#include "llvm/ADT/STLExtras.h"
41#include "llvm/ADT/ScopeExit.h"
42#include "llvm/ADT/SmallVector.h"
43#include "llvm/ADT/StringExtras.h"
44#include "llvm/ADT/StringRef.h"
45#include "llvm/ADT/StringSwitch.h"
46#include "llvm/Support/ErrorHandling.h"
47#include "llvm/Support/Path.h"
48#include "llvm/Support/SaveAndRestore.h"
49#include
50#include
51#include
52#include
53#include
54#include
55
56using namespace clang;
57
58
59
60
61
63 static_assert(std::is_trivially_destructible_v, "");
65}
66
70}
71
73Preprocessor::AllocateUndefMacroDirective(SourceLocation UndefLoc) {
75}
76
78Preprocessor::AllocateVisibilityMacroDirective(SourceLocation Loc,
79 bool isPublic) {
80 return new (BP) VisibilityMacroDirective(Loc, isPublic);
81}
82
83
84
87
90 while (Tmp.isNot(tok::eod)) {
91 assert(Tmp.isNot(tok::eof) && "EOF seen while discarding directive tokens");
93 }
95 return Res;
96}
97
98
105
106
107
113
115
116
117
118
119
120 static constexpr StringRef ReservedMacro[] = {
121 "_ATFILE_SOURCE",
122 "_BSD_SOURCE",
123 "_CRT_NONSTDC_NO_WARNINGS",
124 "_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES",
125 "_CRT_SECURE_NO_WARNINGS",
126 "_FILE_OFFSET_BITS",
127 "_FORTIFY_SOURCE",
128 "_GLIBCXX_ASSERTIONS",
129 "_GLIBCXX_CONCEPT_CHECKS",
130 "_GLIBCXX_DEBUG",
131 "_GLIBCXX_DEBUG_PEDANTIC",
132 "_GLIBCXX_PARALLEL",
133 "_GLIBCXX_PARALLEL_ASSERTIONS",
134 "_GLIBCXX_SANITIZE_VECTOR",
135 "_GLIBCXX_USE_CXX11_ABI",
136 "_GLIBCXX_USE_DEPRECATED",
137 "_GNU_SOURCE",
138 "_ISOC11_SOURCE",
139 "_ISOC95_SOURCE",
140 "_ISOC99_SOURCE",
141 "_LARGEFILE64_SOURCE",
142 "_POSIX_C_SOURCE",
143 "_REENTRANT",
144 "_SVID_SOURCE",
145 "_THREAD_SAFE",
146 "_XOPEN_SOURCE",
147 "_XOPEN_SOURCE_EXTENDED",
148 "__STDCPP_WANT_MATH_SPEC_FUNCS__",
149 "__STDC_FORMAT_MACROS",
150 };
151 return llvm::binary_search(ReservedMacro, MacroName);
152}
153
156 const StringRef MacroName) {
157
158
160 return true;
161
162 if (!SourceMgr.isWrittenInBuiltinFile(MI->getDefinitionLoc()))
163 return false;
164
165
166 if (MacroName.starts_with("__STDC"))
167 return true;
168
169 if (MacroName == "__cplusplus")
170 return true;
171
172 if (MacroName.starts_with("__cpp"))
173 return true;
174
175 return false;
176}
177
180 if (Lang.CPlusPlus &&
182 PP.getTargetInfo(), Lang, false) > 0) {
187
190 }
191 return false;
192}
193
201 if (Lang.CPlusPlus11 && (Text == "override" || Text == "final"))
206}
207
217
218
219
220
221
222
224
225
226 if (::llvm::sys::path::begin(Include)->equals_insensitive("boost"))
227 return true;
228
229
230
231 static const size_t MaxStdHeaderNameLen = 18u;
232 if (Include.size() > MaxStdHeaderNameLen)
233 return false;
234
235
237 for (char &Ch : LowerInclude) {
238
239 if (static_cast<unsigned char>(Ch) > 0x7f)
240 return false;
241
242 if (Ch >= 'A' && Ch <= 'Z')
243 Ch += 'a' - 'A';
244
245 else if (::llvm::sys::path::is_separator(Ch))
246 Ch = '/';
247 }
248
249
250 return llvm::StringSwitch(LowerInclude)
251
252 .Cases({"assert.h", "complex.h", "ctype.h", "errno.h", "fenv.h"}, true)
253 .Cases({"float.h", "inttypes.h", "iso646.h", "limits.h", "locale.h"},
254 true)
255 .Cases({"math.h", "setjmp.h", "signal.h", "stdalign.h", "stdarg.h"}, true)
256 .Cases({"stdatomic.h", "stdbool.h", "stdckdint.h", "stdcountof.h"}, true)
257 .Cases({"stddef.h", "stdint.h", "stdio.h", "stdlib.h", "stdnoreturn.h"},
258 true)
259 .Cases({"string.h", "tgmath.h", "threads.h", "time.h", "uchar.h"}, true)
260 .Cases({"wchar.h", "wctype.h"}, true)
261
262
263 .Cases({"cassert", "ccomplex", "cctype", "cerrno", "cfenv"}, true)
264 .Cases({"cfloat", "cinttypes", "ciso646", "climits", "clocale"}, true)
265 .Cases({"cmath", "csetjmp", "csignal", "cstdalign", "cstdarg"}, true)
266 .Cases({"cstdbool", "cstddef", "cstdint", "cstdio", "cstdlib"}, true)
267 .Cases({"cstring", "ctgmath", "ctime", "cuchar", "cwchar"}, true)
268 .Case("cwctype", true)
269
270
271 .Cases({"algorithm", "fstream", "list", "regex", "thread"}, true)
272 .Cases({"array", "functional", "locale", "scoped_allocator", "tuple"},
273 true)
274 .Cases({"atomic", "future", "map", "set", "type_traits"}, true)
275 .Cases(
276 {"bitset", "initializer_list", "memory", "shared_mutex", "typeindex"},
277 true)
278 .Cases({"chrono", "iomanip", "mutex", "sstream", "typeinfo"}, true)
279 .Cases({"codecvt", "ios", "new", "stack", "unordered_map"}, true)
280 .Cases({"complex", "iosfwd", "numeric", "stdexcept", "unordered_set"},
281 true)
282 .Cases(
283 {"condition_variable", "iostream", "ostream", "streambuf", "utility"},
284 true)
285 .Cases({"deque", "istream", "queue", "string", "valarray"}, true)
286 .Cases({"exception", "iterator", "random", "strstream", "vector"}, true)
287 .Cases({"forward_list", "limits", "ratio", "system_error"}, true)
288
289
290 .Cases({"aio.h", "arpa/inet.h", "cpio.h", "dirent.h", "dlfcn.h"}, true)
291 .Cases({"fcntl.h", "fmtmsg.h", "fnmatch.h", "ftw.h", "glob.h"}, true)
292 .Cases({"grp.h", "iconv.h", "langinfo.h", "libgen.h", "monetary.h"}, true)
293 .Cases({"mqueue.h", "ndbm.h", "net/if.h", "netdb.h", "netinet/in.h"},
294 true)
295 .Cases({"netinet/tcp.h", "nl_types.h", "poll.h", "pthread.h", "pwd.h"},
296 true)
297 .Cases({"regex.h", "sched.h", "search.h", "semaphore.h", "spawn.h"}, true)
298 .Cases({"strings.h", "stropts.h", "sys/ipc.h", "sys/mman.h", "sys/msg.h"},
299 true)
300 .Cases({"sys/resource.h", "sys/select.h", "sys/sem.h", "sys/shm.h",
301 "sys/socket.h"},
302 true)
303 .Cases({"sys/stat.h", "sys/statvfs.h", "sys/time.h", "sys/times.h",
304 "sys/types.h"},
305 true)
306 .Cases(
307 {"sys/uio.h", "sys/un.h", "sys/utsname.h", "sys/wait.h", "syslog.h"},
308 true)
309 .Cases({"tar.h", "termios.h", "trace.h", "ulimit.h"}, true)
310 .Cases({"unistd.h", "utime.h", "utmpx.h", "wordexp.h"}, true)
312}
313
314
315
316
317
318
319
320
321
322static std::optional
323findSimilarStr(StringRef LHS, const std::vector &Candidates) {
324
325
326 for (StringRef C : Candidates) {
327 if (LHS.equals_insensitive(C)) {
328 return C;
329 }
330 }
331
332
333
334
335 size_t Length = LHS.size();
336 size_t MaxDist = Length < 3 ? Length - 1 : Length / 3;
337
338 std::optional<std::pair<StringRef, size_t>> SimilarStr;
339 for (StringRef C : Candidates) {
340 size_t CurDist = LHS.edit_distance(C, true);
341 if (CurDist <= MaxDist) {
342 if (!SimilarStr) {
343
344 SimilarStr = {C, CurDist};
345 } else if (CurDist < SimilarStr->second) {
346
347 SimilarStr = {C, CurDist};
348 }
349 }
350 }
351
352 if (SimilarStr) {
353 return SimilarStr->first;
354 } else {
355 return std::nullopt;
356 }
357}
358
360 bool *ShadowFlag) {
361
362 if (MacroNameTok.is(tok::eod))
363 return Diag(MacroNameTok, diag::err_pp_missing_macro_name);
364
366 if (!II)
367 return Diag(MacroNameTok, diag::err_pp_macro_not_identifier);
368
370
371
373 ? diag::ext_pp_operator_used_as_macro_name
374 : diag::err_pp_operator_used_as_macro_name)
375 << II << MacroNameTok.getKind();
376
377
378 }
379
381
382 return Diag(MacroNameTok, diag::err_defined_macro_name);
383 }
384
385
386
388 if (ShadowFlag)
389 *ShadowFlag = false;
390
391
392
393
394
395 if (!SourceMgr.isInSystemHeader(MacroNameLoc) &&
396 !SourceMgr.isInPredefinedFile(MacroNameLoc)) {
398 if (isDefineUndef == MU_Define) {
400 }
401 else if (isDefineUndef == MU_Undef)
404
405
406
407 if (ShadowFlag)
408 *ShadowFlag = true;
409 }
411 Diag(MacroNameTok, diag::warn_pp_macro_is_reserved_id);
413 Diag(MacroNameTok, diag::warn_pp_macro_is_reserved_attribute_id)
415 }
416
417
418 return false;
419}
420
421
422
423
424
425
426
427
428
429
430void Preprocessor::ReadMacroName(Token &MacroNameTok, MacroUse isDefineUndef,
431 bool *ShadowFlag) {
432
434
435 if (MacroNameTok.is(tok::code_completion)) {
436 if (CodeComplete)
440 }
441
442 if ((MacroNameTok, isDefineUndef, ShadowFlag))
443 return;
444
445
446
447 if (MacroNameTok.isNot(tok::eod)) {
448 MacroNameTok.setKind(tok::eod);
450 }
451}
452
453
454
455
456
457
458
460 bool EnableMacros) {
462
463
464
465 if (EnableMacros)
466 Lex(Tmp);
467 else
469
470
471
472 while (Tmp.is(tok::comment))
474
475 if (Tmp.is(tok::eod))
477
478
479
480
481
483 if ((LangOpts.GNUMode || LangOpts.C99 || LangOpts.CPlusPlus) &&
484 !CurTokenLexer)
486 Diag(Tmp, diag::ext_pp_extra_tokens_at_eol) << DirType << Hint;
488}
489
490void Preprocessor::SuggestTypoedDirective(const Token &Tok,
491 StringRef Directive) const {
492
493
494 if (getLangOpts().AsmPreprocessor) return;
495
496 std::vector Candidates = {
497 "if", "ifdef", "ifndef", "elif", "else", "endif"
498 };
499 if (LangOpts.C23 || LangOpts.CPlusPlus23)
500 Candidates.insert(Candidates.end(), {"elifdef", "elifndef"});
501
503
504 assert(Tok.getLocation().isFileID());
506 Tok.getLocation(),
507 Tok.getLocation().getLocWithOffset(Directive.size()));
508 StringRef SuggValue = *Sugg;
509
511 Diag(Tok, diag::warn_pp_invalid_directive) << 1 << SuggValue << Hint;
512 }
513}
514
515
516
517
518
519
520
521
522
523void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc,
525 bool FoundNonSkipPortion,
526 bool FoundElse,
528
529
530
531
532
533
534
535
536 assert(!SkippingExcludedConditionalBlock &&
537 "calling SkipExcludedConditionalBlock recursively");
538 llvm::SaveAndRestore SARSkipping(SkippingExcludedConditionalBlock, true);
539
540 ++NumSkipped;
541 assert(!CurTokenLexer && "Conditional PP block cannot appear in a macro!");
542 assert(CurPPLexer && "Conditional PP block must be in a file!");
543 assert(CurLexer && "Conditional PP block but no current lexer set!");
544
545 if (PreambleConditionalStack.reachedEOFWhileSkipping())
546 PreambleConditionalStack.clearSkipInfo();
547 else
548 CurPPLexer->pushConditionalLevel(IfTokenLoc, false,
549 FoundNonSkipPortion, FoundElse);
550
551
552
553 CurPPLexer->LexingRawMode = true;
554 Token Tok;
555 SourceLocation endLoc;
556
557
558
559 struct SkippingRangeStateTy {
560 Preprocessor &PP;
561
562 const char *BeginPtr = nullptr;
563 unsigned *SkipRangePtr = nullptr;
564
565 SkippingRangeStateTy(Preprocessor &PP) : PP(PP) {}
566
567 void beginLexPass() {
568 if (BeginPtr)
569 return;
570
571
572
573 BeginPtr = PP.CurLexer->getBufferLocation();
574 SkipRangePtr = &PP.RecordedSkippedRanges[BeginPtr];
575 if (*SkipRangePtr) {
576 PP.CurLexer->seek(PP.CurLexer->getCurrentBufferOffset() + *SkipRangePtr,
577 true);
578 }
579 }
580
581 void endLexPass(const char *Hashptr) {
582 if (!BeginPtr) {
583
584 assert(PP.CurLexer->isDependencyDirectivesLexer());
585 return;
586 }
587
588
589 if (!*SkipRangePtr) {
590 *SkipRangePtr = Hashptr - BeginPtr;
591 }
592 assert(*SkipRangePtr == unsigned(Hashptr - BeginPtr));
593 BeginPtr = nullptr;
594 SkipRangePtr = nullptr;
595 }
596 } SkippingRangeState(*this);
597
598 while (true) {
599 if (CurLexer->isDependencyDirectivesLexer()) {
600 CurLexer->LexDependencyDirectiveTokenWhileSkipping(Tok);
601 } else {
602 SkippingRangeState.beginLexPass();
603 while (true) {
604 CurLexer->Lex(Tok);
605
606 if (Tok.is(tok::code_completion)) {
608 if (CodeComplete)
609 CodeComplete->CodeCompleteInConditionalExclusion();
610 continue;
611 }
612
613
615
616
617
618 if (PreambleConditionalStack.isRecording())
619 PreambleConditionalStack.SkipInfo.emplace(HashTokenLoc, IfTokenLoc,
620 FoundNonSkipPortion,
621 FoundElse, ElseLoc);
622 break;
623 }
624
625
627 continue;
628
629 break;
630 }
631 }
633 break;
634
635
636
637
638 CurPPLexer->ParsingPreprocessorDirective = true;
639 if (CurLexer) CurLexer->SetKeepWhitespaceMode(false);
640
641 assert(Tok.is(tok::hash));
642 const char *Hashptr = CurLexer->getBufferLocation() - Tok.getLength();
643 assert(CurLexer->getSourceLocation(Hashptr) == Tok.getLocation());
644
645
647
648
649
650 if (Tok.isNot(tok::raw_identifier)) {
651 CurPPLexer->ParsingPreprocessorDirective = false;
652
653 if (CurLexer) CurLexer->resetExtendedTokenMode();
654 continue;
655 }
656
657
658
659
660
661
663
664 char FirstChar = RI[0];
665 if (FirstChar >= 'a' && FirstChar <= 'z' &&
666 FirstChar != 'i' && FirstChar != 'e') {
667 CurPPLexer->ParsingPreprocessorDirective = false;
668
669 if (CurLexer) CurLexer->resetExtendedTokenMode();
670 continue;
671 }
672
673
674
675
676 char DirectiveBuf[20];
680 } else {
682 size_t IdLen = DirectiveStr.size();
683 if (IdLen >= 20) {
684 CurPPLexer->ParsingPreprocessorDirective = false;
685
686 if (CurLexer) CurLexer->resetExtendedTokenMode();
687 continue;
688 }
689 memcpy(DirectiveBuf, &DirectiveStr[0], IdLen);
690 Directive = StringRef(DirectiveBuf, IdLen);
691 }
692
693 if (Directive.starts_with("if")) {
695 if (Sub.empty() ||
696 Sub == "def" ||
697 Sub == "ndef") {
698
699
701 CurPPLexer->pushConditionalLevel(Tok.getLocation(), true,
702 false,
703 false);
704 } else {
706 }
707 } else if (Directive[0] == 'e') {
709 if (Sub == "ndif") {
710 PPConditionalInfo CondInfo;
711 CondInfo.WasSkipping = true;
712 bool InCond = CurPPLexer->popConditionalLevel(CondInfo);
713 (void)InCond;
714 assert(!InCond && "Can't be skipping if not in a conditional!");
715
716
718 SkippingRangeState.endLexPass(Hashptr);
719
720
721 CurPPLexer->LexingRawMode = false;
723 CurPPLexer->LexingRawMode = true;
724 if (Callbacks)
726 break;
727 } else {
729 }
730 } else if (Sub == "lse") {
731
732
733
734 PPConditionalInfo &CondInfo = CurPPLexer->peekConditionalLevel();
735
737 SkippingRangeState.endLexPass(Hashptr);
738
739
741 Diag(Tok, diag::pp_err_else_after_else);
742
743
745
746
747
750
751
752 CurPPLexer->LexingRawMode = false;
754 CurPPLexer->LexingRawMode = true;
755 if (Callbacks)
757 break;
758 } else {
760 }
761 } else if (Sub == "lif") {
762 PPConditionalInfo &CondInfo = CurPPLexer->peekConditionalLevel();
763
765 SkippingRangeState.endLexPass(Hashptr);
766
767
770
771
772
774
775
776
777
779 } else {
780
781
782 assert(CurPPLexer->LexingRawMode && "We have to be skipping here!");
783 CurPPLexer->LexingRawMode = false;
784 IdentifierInfo *IfNDefMacro = nullptr;
785 DirectiveEvalResult DER = EvaluateDirectiveExpression(IfNDefMacro);
786
787 if (!CurPPLexer)
788 return;
789 const bool CondValue = DER.Conditional;
790 CurPPLexer->LexingRawMode = true;
791 if (Callbacks) {
792 Callbacks->Elif(
796 }
797
798 if (CondValue) {
800 break;
801 }
802 }
803 } else if (Sub == "lifdef" ||
804 Sub == "lifndef") {
805 bool IsElifDef = Sub == "lifdef";
806 PPConditionalInfo &CondInfo = CurPPLexer->peekConditionalLevel();
807 Token DirectiveToken = Tok;
808
810 SkippingRangeState.endLexPass(Hashptr);
811
812
813
814 unsigned DiagID;
815 if (LangOpts.CPlusPlus)
816 DiagID = LangOpts.CPlusPlus23 ? diag::warn_cxx23_compat_pp_directive
817 : diag::ext_cxx23_pp_directive;
818 else
819 DiagID = LangOpts.C23 ? diag::warn_c23_compat_pp_directive
820 : diag::ext_c23_pp_directive;
822
823
825 Diag(Tok, diag::pp_err_elif_after_else)
827
828
829
831
832
833
834
836 } else {
837
838
839 assert(CurPPLexer->LexingRawMode && "We have to be skipping here!");
840 CurPPLexer->LexingRawMode = false;
841 Token MacroNameTok;
842 ReadMacroName(MacroNameTok);
843 CurPPLexer->LexingRawMode = true;
844
845
846
847 if (MacroNameTok.is(tok::eod)) {
848
849
850 continue;
851 }
852
854
856
859 MacroInfo *MI = MD.getMacroInfo();
860
861 if (Callbacks) {
862 if (IsElifDef) {
863 Callbacks->Elifdef(DirectiveToken.getLocation(), MacroNameTok,
864 MD);
865 } else {
866 Callbacks->Elifndef(DirectiveToken.getLocation(), MacroNameTok,
867 MD);
868 }
869 }
870
871 if (static_cast<bool>(MI) == IsElifDef) {
873 break;
874 }
875 }
876 } else {
878 }
879 } else {
881 }
882
883 CurPPLexer->ParsingPreprocessorDirective = false;
884
885 if (CurLexer) CurLexer->resetExtendedTokenMode();
886 }
887
888
889
890
891 CurPPLexer->LexingRawMode = false;
892
893
894
896 Callbacks->SourceRangeSkipped(
897 SourceRange(HashTokenLoc, endLoc.isValid()
898 ? endLoc
899 : CurPPLexer->getSourceLocation()),
901}
902
904 bool AllowTextual) {
905 if (!SourceMgr.isInMainFile(Loc)) {
906
907
908 FileID IDOfIncl = SourceMgr.getFileID(SourceMgr.getExpansionLoc(Loc));
909 if (auto EntryOfIncl = SourceMgr.getFileEntryRefForID(IDOfIncl)) {
910
911 return HeaderInfo.getModuleMap()
912 .findModuleForHeader(*EntryOfIncl, AllowTextual)
913 .getModule();
914 }
915 }
916
917
918
921 : HeaderInfo.lookupModule(getLangOpts().CurrentModule, Loc);
922}
923
928 IncLoc, LangOpts.ModulesValidateTextualHeaderIncludes);
929
930
931
932
933
935 while (!Loc.isInvalid() && .isInMainFile(Loc)) {
936 auto ID = SM.getFileID(SM.getExpansionLoc(Loc));
937 auto FE = SM.getFileEntryRefForID(ID);
938 if (!FE)
939 break;
940
941
942
943 HeaderInfo.hasModuleMap(FE->getName(), nullptr,
944 SourceMgr.isInSystemHeader(Loc));
945
946 bool InPrivateHeader = false;
947 for (auto Header : HeaderInfo.findAllModulesForHeader(*FE)) {
948 if (!Header.isAccessibleFrom(IncM)) {
949
950
951
952
953 InPrivateHeader = true;
954 continue;
955 }
956
957
959 continue;
960
961
962
964 continue;
965
966
967
968
970 return std::nullopt;
971
972
973
974
975 return *FE;
976 }
977
978
979
980 if (InPrivateHeader)
981 return std::nullopt;
982
983
984
985
987 return *FE;
988
989 Loc = SM.getIncludeLoc(ID);
990 }
991
992 return std::nullopt;
993}
994
996 SourceLocation FilenameLoc, StringRef Filename, bool isAngled,
1001 bool *IsFrameworkFound, bool SkipCache, bool OpenFile, bool CacheFailures) {
1004
1006 FilenameLoc, LangOpts.ModulesValidateTextualHeaderIncludes);
1007
1008
1009
1011 bool BuildSystemModule = false;
1012 if (!FromDir && !FromFile) {
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028 if (!FileEnt) {
1029 if (FID == SourceMgr.getMainFileID() && MainFileDir) {
1030 auto IncludeDir =
1031 HeaderInfo.getModuleMap().shouldImportRelativeToBuiltinIncludeDir(
1033 ? HeaderInfo.getModuleMap().getBuiltinDir()
1034 : MainFileDir;
1035 Includers.push_back(std::make_pair(std::nullopt, *IncludeDir));
1037 } else if ((FileEnt = SourceMgr.getFileEntryRefForID(
1038 SourceMgr.getMainFileID()))) {
1039 auto CWD = FileMgr.getOptionalDirectoryRef(".");
1040 Includers.push_back(std::make_pair(*FileEnt, *CWD));
1041 }
1042 } else {
1043 Includers.push_back(std::make_pair(*FileEnt, FileEnt->getDir()));
1044 }
1045
1046
1047
1048
1049 if (LangOpts.MSVCCompat && !isAngled) {
1050 for (IncludeStackInfo &ISEntry : llvm::reverse(IncludeMacroStack)) {
1051 if (IsFileLexer(ISEntry))
1052 if ((FileEnt = ISEntry.ThePPLexer->getFileEntry()))
1053 Includers.push_back(std::make_pair(*FileEnt, FileEnt->getDir()));
1054 }
1055 }
1056 }
1057
1058 CurDir = CurDirLookup;
1059
1060 if (FromFile) {
1061
1062
1066 Filename, FilenameLoc, isAngled, TmpFromDir, &TmpCurDir,
1067 Includers, SearchPath, RelativePath, RequestingModule,
1068 SuggestedModule, nullptr,
1069 nullptr, SkipCache)) {
1070
1071 TmpFromDir = TmpCurDir;
1072 ++TmpFromDir;
1073 if (&FE->getFileEntry() == FromFile) {
1074
1075 FromDir = TmpFromDir;
1076 CurDir = TmpCurDir;
1077 break;
1078 }
1079 }
1080 }
1081
1082
1084 Filename, FilenameLoc, isAngled, FromDir, &CurDir, Includers, SearchPath,
1085 RelativePath, RequestingModule, SuggestedModule, IsMapped,
1086 IsFrameworkFound, SkipCache, BuildSystemModule, OpenFile, CacheFailures);
1087 if (FE)
1088 return FE;
1089
1091
1092
1093
1094 if (IsFileLexer()) {
1095 if ((CurFileEnt = CurPPLexer->getFileEntry())) {
1097 Filename, *CurFileEnt, SearchPath, RelativePath, RequestingModule,
1098 SuggestedModule)) {
1099 return FE;
1100 }
1101 }
1102 }
1103
1104 for (IncludeStackInfo &ISEntry : llvm::reverse(IncludeMacroStack)) {
1105 if (IsFileLexer(ISEntry)) {
1106 if ((CurFileEnt = ISEntry.ThePPLexer->getFileEntry())) {
1108 Filename, *CurFileEnt, SearchPath, RelativePath,
1109 RequestingModule, SuggestedModule)) {
1110 return FE;
1111 }
1112 }
1113 }
1114 }
1115
1116
1117 return std::nullopt;
1118}
1119
1122 const FileEntry *LookupFromFile) {
1124 if (llvm::sys::path::is_absolute(Filename)) {
1125
1127 Filename, OpenFile, true, false);
1128 return llvm::expectedToOptional(std::move(ShouldBeEntry));
1129 }
1130
1132 StringRef StartingFrom, StringRef FileName,
1133 bool RemoveInitialFileComponentFromLookupPath) {
1134 llvm::sys::path::native(StartingFrom, LookupPath);
1135 if (RemoveInitialFileComponentFromLookupPath)
1136 llvm::sys::path::remove_filename(LookupPath);
1137 if (!LookupPath.empty() &&
1138 !llvm::sys::path::is_separator(LookupPath.back())) {
1139 LookupPath.push_back(llvm::sys::path::get_separator().front());
1140 }
1142 };
1143
1144
1146
1147 if (!isAngled) {
1148 if (LookupFromFile) {
1149
1151 if (!FullFileDir.empty()) {
1152 SeparateComponents(LookupPath, FullFileDir, Filename, true);
1154 LookupPath, OpenFile, true, false);
1155 if (ShouldBeEntry)
1156 return llvm::expectedToOptional(std::move(ShouldBeEntry));
1157 llvm::consumeError(ShouldBeEntry.takeError());
1158 }
1159 }
1160
1161
1162 LookupPath.clear();
1164 if (MaybeWorkingDirEntry) {
1166 StringRef WorkingDir = WorkingDirEntry.getName();
1167 if (!WorkingDir.empty()) {
1168 SeparateComponents(LookupPath, WorkingDir, Filename, false);
1170 LookupPath, OpenFile, true, false);
1171 if (ShouldBeEntry)
1172 return llvm::expectedToOptional(std::move(ShouldBeEntry));
1173 llvm::consumeError(ShouldBeEntry.takeError());
1174 }
1175 }
1176 }
1177
1178 for (const auto &Entry : PPOpts.EmbedEntries) {
1179 LookupPath.clear();
1180 SeparateComponents(LookupPath, Entry, Filename, false);
1182 LookupPath, OpenFile, true, false);
1183 if (ShouldBeEntry)
1184 return llvm::expectedToOptional(std::move(ShouldBeEntry));
1185 llvm::consumeError(ShouldBeEntry.takeError());
1186 }
1187 return std::nullopt;
1188}
1189
1190
1191
1192
1193
1195public:
1197 : PP(pp), save(pp->DisableMacroExpansion) {
1198 if (pp->MacroExpansionInDirectivesOverride)
1199 pp->DisableMacroExpansion = false;
1200 }
1201
1203 PP->DisableMacroExpansion = save;
1204 }
1205
1206private:
1208 bool save;
1209};
1210
1211
1212
1213
1214
1215
1216
1220 if (II->getPPKeywordID() == tok::pp_define) {
1221 return HandleDefineDirective(Result,
1222 false);
1223 }
1224 if (SkippingUntilPCHThroughHeader &&
1225 II->getPPKeywordID() == tok::pp_include) {
1226 return HandleIncludeDirective(HashLoc, Result);
1227 }
1228 if (SkippingUntilPragmaHdrStop && II->getPPKeywordID() == tok::pp_pragma) {
1230 auto *II = Result.getIdentifierInfo();
1231 if (II && II->getName() == "hdrstop")
1233 }
1234 }
1236}
1237
1238
1239
1240
1241
1243
1244
1245
1246
1247
1248 CurPPLexer->ParsingPreprocessorDirective = true;
1249 if (CurLexer) CurLexer->SetKeepWhitespaceMode(false);
1250
1251 bool ImmediatelyAfterTopLevelIfndef =
1252 CurPPLexer->MIOpt.getImmediatelyAfterTopLevelIfndef();
1253 CurPPLexer->MIOpt.resetImmediatelyAfterTopLevelIfndef();
1254
1255 ++NumDirectives;
1256
1257
1258
1259
1260 bool ReadAnyTokensBeforeDirective =CurPPLexer->MIOpt.getHasReadAnyTokensVal();
1261
1262
1264
1265
1266
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277 if (InMacroArgs) {
1279 switch (II->getPPKeywordID()) {
1280 case tok::pp_include:
1281 case tok::pp_import:
1282 case tok::pp_include_next:
1283 case tok::pp___include_macros:
1284 case tok::pp_pragma:
1285 case tok::pp_embed:
1286 Diag(Result, diag::err_embedded_directive) << II->getName();
1287 Diag(*ArgMacro, diag::note_macro_expansion_here)
1288 << ArgMacro->getIdentifierInfo();
1290 return;
1291 default:
1292 break;
1293 }
1294 }
1295 Diag(Result, diag::ext_embedded_directive);
1296 }
1297
1298
1299
1301
1302 if (SkippingUntilPCHThroughHeader || SkippingUntilPragmaHdrStop)
1304
1305 switch (Result.getKind()) {
1306 case tok::eod:
1307
1308
1309
1310 CurPPLexer->MIOpt.SetReadToken(ReadAnyTokensBeforeDirective);
1311 return;
1312 case tok::code_completion:
1314 if (CodeComplete)
1315 CodeComplete->CodeCompleteDirective(
1316 CurPPLexer->getConditionalStackDepth() > 0);
1317 return;
1318 case tok::numeric_constant:
1319
1320
1321
1324 break;
1325 return HandleDigitDirective(Result);
1326 default:
1328 if (!II) break;
1329
1330
1332 default: break;
1333
1334 case tok::pp_if:
1335 return HandleIfDirective(Result, SavedHash, ReadAnyTokensBeforeDirective);
1336 case tok::pp_ifdef:
1337 return HandleIfdefDirective(Result, SavedHash, false,
1338 true );
1339 case tok::pp_ifndef:
1340 return HandleIfdefDirective(Result, SavedHash, true,
1341 ReadAnyTokensBeforeDirective);
1342 case tok::pp_elif:
1343 case tok::pp_elifdef:
1344 case tok::pp_elifndef:
1346
1347 case tok::pp_else:
1348 return HandleElseDirective(Result, SavedHash);
1349 case tok::pp_endif:
1350 return HandleEndifDirective(Result);
1351
1352
1353 case tok::pp_include:
1354
1356 case tok::pp___include_macros:
1357
1358 return HandleIncludeMacrosDirective(SavedHash.getLocation(), Result);
1359
1360
1361 case tok::pp_define:
1362 return HandleDefineDirective(Result, ImmediatelyAfterTopLevelIfndef);
1363 case tok::pp_undef:
1364 return HandleUndefDirective();
1365
1366
1367 case tok::pp_line:
1368 return HandleLineDirective();
1369
1370
1371 case tok::pp_error:
1372 return HandleUserDiagnosticDirective(Result, false);
1373
1374
1375 case tok::pp_pragma:
1377
1378
1379 case tok::pp_import:
1381 case tok::pp_include_next:
1382 return HandleIncludeNextDirective(SavedHash.getLocation(), Result);
1383
1384 case tok::pp_warning:
1385 if (LangOpts.CPlusPlus)
1387 ? diag::warn_cxx23_compat_warning_directive
1388 : diag::ext_pp_warning_directive)
1389 << 1;
1390 else
1391 Diag(Result, LangOpts.C23 ? diag::warn_c23_compat_warning_directive
1392 : diag::ext_pp_warning_directive)
1393 << 0;
1394
1395 return HandleUserDiagnosticDirective(Result, true);
1396 case tok::pp_ident:
1397 return HandleIdentSCCSDirective(Result);
1398 case tok::pp_sccs:
1399 return HandleIdentSCCSDirective(Result);
1400 case tok::pp_embed: {
1403 return HandleEmbedDirective(SavedHash.getLocation(), Result, *FERef);
1404 return HandleEmbedDirective(SavedHash.getLocation(), Result, nullptr);
1405 }
1406 case tok::pp_assert:
1407
1408 break;
1409 case tok::pp_unassert:
1410
1411 break;
1412
1413 case tok::pp___public_macro:
1415 return HandleMacroPublicDirective(Result);
1416 break;
1417
1418 case tok::pp___private_macro:
1420 return HandleMacroPrivateDirective();
1421 break;
1422 }
1423 break;
1424 }
1425
1426
1427
1428
1429
1431 auto Toks = std::make_unique<Token[]>(2);
1432
1433 Toks[0] = SavedHash;
1435
1436
1437
1438 if (Result.is(tok::hashhash))
1439 Toks[1].setKind(tok::unknown);
1440
1441
1442
1443
1444 EnterTokenStream(std::move(Toks), 2, false, false);
1445 return;
1446 }
1447
1448
1449
1450 Diag(Result, diag::err_pp_invalid_directive) << 0;
1451
1452
1454
1455
1456}
1457
1458
1459
1462 bool IsGNULineDirective=false) {
1463 if (DigitTok.isNot(tok::numeric_constant)) {
1464 PP.Diag(DigitTok, DiagID);
1465
1466 if (DigitTok.isNot(tok::eod))
1468 return true;
1469 }
1470
1472 IntegerBuffer.resize(DigitTok.getLength());
1473 const char *DigitTokBegin = &IntegerBuffer[0];
1475 unsigned ActualLength = PP.getSpelling(DigitTok, DigitTokBegin, &Invalid);
1477 return true;
1478
1479
1480
1481
1482 Val = 0;
1483 for (unsigned i = 0; i != ActualLength; ++i) {
1484
1485
1486 if (DigitTokBegin[i] == '\'')
1487 continue;
1488
1489 if ((DigitTokBegin[i])) {
1491 diag::err_pp_line_digit_sequence) << IsGNULineDirective;
1493 return true;
1494 }
1495
1496 unsigned NextVal = Val*10+(DigitTokBegin[i]-'0');
1497 if (NextVal < Val) {
1498 PP.Diag(DigitTok, DiagID);
1500 return true;
1501 }
1502 Val = NextVal;
1503 }
1504
1505 if (DigitTokBegin[0] == '0' && Val)
1506 PP.Diag(DigitTok.getLocation(), diag::warn_pp_line_decimal)
1507 << IsGNULineDirective;
1508
1509 return false;
1510}
1511
1512
1513
1514
1515
1516
1517
1518
1519void Preprocessor::HandleLineDirective() {
1520
1521
1522 Token DigitTok;
1523 Lex(DigitTok);
1524
1525
1526 unsigned LineNo;
1527 if (GetLineValue(DigitTok, LineNo, diag::err_pp_line_requires_integer,*this))
1528 return;
1529
1530 if (LineNo == 0)
1531 Diag(DigitTok, diag::ext_pp_line_zero);
1532
1533
1534
1535 unsigned LineLimit = 32768U;
1536 if (LangOpts.C99 || LangOpts.CPlusPlus11)
1537 LineLimit = 2147483648U;
1538 if (LineNo >= LineLimit)
1539 Diag(DigitTok, diag::ext_pp_line_too_big) << LineLimit;
1540 else if (LangOpts.CPlusPlus11 && LineNo >= 32768U)
1541 Diag(DigitTok, diag::warn_cxx98_compat_pp_line_too_big);
1542
1543 int FilenameID = -1;
1544 Token StrTok;
1545 Lex(StrTok);
1546
1547
1548
1549 if (StrTok.is(tok::eod))
1550 ;
1551 else if (StrTok.isNot(tok::string_literal)) {
1552 Diag(StrTok, diag::err_pp_line_invalid_filename);
1554 return;
1556 Diag(StrTok, diag::err_invalid_string_udl);
1558 return;
1559 } else {
1560
1561 StringLiteralParser Literal(StrTok, *this);
1562 assert(Literal.isOrdinary() && "Didn't allow wide strings in");
1565 return;
1566 }
1568 Diag(StrTok, diag::err_pp_linemarker_invalid_filename);
1570 return;
1571 }
1572 FilenameID = SourceMgr.getLineTableFilenameID(Literal.GetString());
1573
1574
1575
1577 }
1578
1579
1580
1581
1582
1583
1585 SourceMgr.getFileCharacteristic(DigitTok.getLocation());
1586
1587 SourceMgr.AddLineNote(DigitTok.getLocation(), LineNo, FilenameID, false,
1588 false, FileKind);
1589
1590 if (Callbacks)
1591 Callbacks->FileChanged(CurPPLexer->getSourceLocation(),
1593}
1594
1595
1596
1600 unsigned FlagVal;
1602 PP.Lex(FlagTok);
1603 if (FlagTok.is(tok::eod)) return false;
1604 if (GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag, PP))
1605 return true;
1606
1607 if (FlagVal == 1) {
1608 IsFileEntry = true;
1609
1610 PP.Lex(FlagTok);
1611 if (FlagTok.is(tok::eod)) return false;
1612 if (GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag,PP))
1613 return true;
1614 } else if (FlagVal == 2) {
1615 IsFileExit = true;
1616
1618
1619
1621 SM.getDecomposedExpansionLoc(FlagTok.getLocation()).first;
1624 return true;
1625
1626
1627
1630 SM.getDecomposedExpansionLoc(IncLoc).first != CurFileID) {
1631 PP.Diag(FlagTok, diag::err_pp_linemarker_invalid_pop);
1633 return true;
1634 }
1635
1636 PP.Lex(FlagTok);
1637 if (FlagTok.is(tok::eod)) return false;
1638 if (GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag,PP))
1639 return true;
1640 }
1641
1642
1643 if (FlagVal != 3) {
1644 PP.Diag(FlagTok, diag::err_pp_linemarker_invalid_flag);
1646 return true;
1647 }
1648
1650
1651 PP.Lex(FlagTok);
1652 if (FlagTok.is(tok::eod)) return false;
1653 if (GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag, PP))
1654 return true;
1655
1656
1657 if (FlagVal != 4) {
1658 PP.Diag(FlagTok, diag::err_pp_linemarker_invalid_flag);
1660 return true;
1661 }
1662
1664
1665 PP.Lex(FlagTok);
1666 if (FlagTok.is(tok::eod)) return false;
1667
1668
1669 PP.Diag(FlagTok, diag::err_pp_linemarker_invalid_flag);
1671 return true;
1672}
1673
1674
1675
1676
1677
1678
1679
1680
1681void Preprocessor::HandleDigitDirective(Token &DigitTok) {
1682
1683
1684 unsigned LineNo;
1685 if (GetLineValue(DigitTok, LineNo, diag::err_pp_linemarker_requires_integer,
1686 *this, true))
1687 return;
1688
1689 Token StrTok;
1690 Lex(StrTok);
1691
1692 bool IsFileEntry = false, IsFileExit = false;
1693 int FilenameID = -1;
1695
1696
1697
1698 if (StrTok.is(tok::eod)) {
1699 Diag(StrTok, diag::ext_pp_gnu_line_directive);
1700
1701 FileKind = SourceMgr.getFileCharacteristic(DigitTok.getLocation());
1702 } else if (StrTok.isNot(tok::string_literal)) {
1703 Diag(StrTok, diag::err_pp_linemarker_invalid_filename);
1705 return;
1707 Diag(StrTok, diag::err_invalid_string_udl);
1709 return;
1710 } else {
1711
1712 StringLiteralParser Literal(StrTok, *this);
1713 assert(Literal.isOrdinary() && "Didn't allow wide strings in");
1716 return;
1717 }
1719 Diag(StrTok, diag::err_pp_linemarker_invalid_filename);
1721 return;
1722 }
1723
1724
1726 return;
1727 if (!SourceMgr.isInPredefinedFile(DigitTok.getLocation()))
1728 Diag(StrTok, diag::ext_pp_gnu_line_directive);
1729
1730
1731
1732 if (!(IsFileExit && Literal.GetString().empty()))
1733 FilenameID = SourceMgr.getLineTableFilenameID(Literal.GetString());
1734 }
1735
1736
1737 SourceMgr.AddLineNote(DigitTok.getLocation(), LineNo, FilenameID, IsFileEntry,
1738 IsFileExit, FileKind);
1739
1740
1741
1742
1743 if (Callbacks) {
1745 if (IsFileEntry)
1747 else if (IsFileExit)
1749
1750 Callbacks->FileChanged(CurPPLexer->getSourceLocation(), Reason, FileKind);
1751 }
1752}
1753
1754
1755
1756void Preprocessor::HandleUserDiagnosticDirective(Token &Tok,
1757 bool isWarning) {
1758
1759
1760
1761
1762
1763 SmallString<128> Message;
1764 CurLexer->ReadToEndOfLine(&Message);
1765
1766
1767
1768 StringRef Msg = Message.str().ltrim(' ');
1769
1770 if (isWarning)
1771 Diag(Tok, diag::pp_hash_warning) << Msg;
1772 else
1773 Diag(Tok, diag::err_pp_hash_error) << Msg;
1774}
1775
1776
1777
1778void Preprocessor::HandleIdentSCCSDirective(Token &Tok) {
1779
1780 Diag(Tok, diag::ext_pp_ident_directive);
1781
1782
1783 Token StrTok;
1784 Lex(StrTok);
1785
1786
1787 if (StrTok.isNot(tok::string_literal) &&
1788 StrTok.isNot(tok::wide_string_literal)) {
1789 Diag(StrTok, diag::err_pp_malformed_ident);
1790 if (StrTok.isNot(tok::eod))
1792 return;
1793 }
1794
1796 Diag(StrTok, diag::err_invalid_string_udl);
1798 return;
1799 }
1800
1801
1803
1804 if (Callbacks) {
1809 }
1810}
1811
1812
1813void Preprocessor::HandleMacroPublicDirective(Token &Tok) {
1814 Token MacroNameTok;
1815 ReadMacroName(MacroNameTok, MU_Undef);
1816
1817
1818 if (MacroNameTok.is(tok::eod))
1819 return;
1820
1821
1823
1825
1827
1828
1829 if (!MD) {
1830 Diag(MacroNameTok, diag::err_pp_visibility_non_macro) << II;
1831 return;
1832 }
1833
1834
1836 MacroNameTok.getLocation(), true));
1837}
1838
1839
1840void Preprocessor::HandleMacroPrivateDirective() {
1841 Token MacroNameTok;
1842 ReadMacroName(MacroNameTok, MU_Undef);
1843
1844
1845 if (MacroNameTok.is(tok::eod))
1846 return;
1847
1848
1850
1852
1854
1855
1856 if (!MD) {
1857 Diag(MacroNameTok, diag::err_pp_visibility_non_macro) << II;
1858 return;
1859 }
1860
1861
1863 MacroNameTok.getLocation(), false));
1864}
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1877 StringRef &Buffer) {
1878
1879 assert(!Buffer.empty() && "Can't have tokens with empty spellings!");
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890 bool isAngled;
1891 if (Buffer[0] == '<') {
1892 if (Buffer.back() != '>') {
1893 Diag(Loc, diag::err_pp_expects_filename);
1894 Buffer = StringRef();
1895 return true;
1896 }
1897 isAngled = true;
1898 } else if (Buffer[0] == '"') {
1899 if (Buffer.back() != '"') {
1900 Diag(Loc, diag::err_pp_expects_filename);
1901 Buffer = StringRef();
1902 return true;
1903 }
1904 isAngled = false;
1905 } else {
1906 Diag(Loc, diag::err_pp_expects_filename);
1907 Buffer = StringRef();
1908 return true;
1909 }
1910
1911
1912 if (Buffer.size() <= 2) {
1913 Diag(Loc, diag::err_pp_empty_filename);
1914 Buffer = StringRef();
1915 return true;
1916 }
1917
1918
1919 Buffer = Buffer.substr(1, Buffer.size()-2);
1920 return isAngled;
1921}
1922
1923
1926 void *AnnotationVal) {
1927
1928
1929 auto Tok = std::make_unique<Token[]>(1);
1930 Tok[0].startToken();
1931 Tok[0].setKind(Kind);
1932 Tok[0].setLocation(Range.getBegin());
1933 Tok[0].setAnnotationEndLoc(Range.getEnd());
1934 Tok[0].setAnnotationValue(AnnotationVal);
1935 EnterTokenStream(std::move(Tok), 1, true, false);
1936}
1937
1938
1939
1941 Token &IncludeTok,
1945 for (size_t I = 0, N = Path.size(); I != N; ++I) {
1946 if (I)
1947 PathString += '.';
1948 PathString += Path[I].getIdentifierInfo()->getName();
1949 }
1950
1951 int IncludeKind = 0;
1953 case tok::pp_include:
1954 IncludeKind = 0;
1955 break;
1956
1957 case tok::pp_import:
1958 IncludeKind = 1;
1959 break;
1960
1961 case tok::pp_include_next:
1962 IncludeKind = 2;
1963 break;
1964
1965 case tok::pp___include_macros:
1966 IncludeKind = 3;
1967 break;
1968
1969 default:
1970 llvm_unreachable("unknown include directive kind");
1971 }
1972
1973 PP.Diag(HashLoc, diag::remark_pp_include_directive_modular_translation)
1974 << IncludeKind << PathString;
1975}
1976
1977
1978
1979
1981 StringRef RealPathName,
1982 llvm::sys::path::Style Separator) {
1983 auto RealPathComponentIter = llvm::sys::path::rbegin(RealPathName);
1984 auto RealPathComponentEnd = llvm::sys::path::rend(RealPathName);
1985 int Cnt = 0;
1986 bool SuggestReplacement = false;
1987
1988 auto IsSep = [Separator](StringRef Component) {
1989 return Component.size() == 1 &&
1990 llvm::sys::path::is_separator(Component[0], Separator);
1991 };
1992
1993
1994
1995 for (auto &Component : llvm::reverse(Components)) {
1996 if ("." == Component) {
1997 } else if (".." == Component) {
1998 ++Cnt;
1999 } else if (Cnt) {
2000 --Cnt;
2001 } else if (RealPathComponentIter != RealPathComponentEnd) {
2002 if (!IsSep(Component) && !IsSep(*RealPathComponentIter) &&
2003 Component != *RealPathComponentIter) {
2004
2005
2006
2007 SuggestReplacement =
2008 RealPathComponentIter->equals_insensitive(Component);
2009 if (!SuggestReplacement)
2010 break;
2011 Component = *RealPathComponentIter;
2012 }
2013 ++RealPathComponentIter;
2014 }
2015 }
2016 return SuggestReplacement;
2017}
2018
2025 Module *ShadowingModule = nullptr;
2027 ShadowingModule))
2028 return false;
2029
2031 Diags.Report(MissingHeader.FileNameLoc, diag::err_module_header_missing)
2033 } else if (ShadowingModule) {
2034 Diags.Report(M.DefinitionLoc, diag::err_module_shadowed) << M.Name;
2036 diag::note_previous_definition);
2037 } else {
2038
2039
2040 Diags.Report(M.DefinitionLoc, diag::err_module_unavailable)
2043 }
2044 return true;
2045}
2046
2047std::pair<ConstSearchDirIterator, const FileEntry *>
2048Preprocessor::getIncludeNextStart(const Token &IncludeNextTok) const {
2049
2050
2051
2053 const FileEntry *LookupFromFile = nullptr;
2054
2056
2057
2058
2060 Lookup = nullptr;
2061 Diag(IncludeNextTok, diag::pp_include_next_in_primary);
2062 } else if (CurLexerSubmodule) {
2063
2064
2065 assert(CurPPLexer && "#include_next directive in macro?");
2066 if (auto FE = CurPPLexer->getFileEntry())
2067 LookupFromFile = *FE;
2068 Lookup = nullptr;
2069 } else if (!Lookup) {
2070
2071
2072
2073
2074 Diag(IncludeNextTok, diag::pp_include_next_absolute_path);
2075 } else {
2076
2077 ++Lookup;
2078 }
2079
2080 return {Lookup, LookupFromFile};
2081}
2082
2083
2084
2085
2086
2087
2088void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
2089 Token &IncludeTok,
2091 const FileEntry *LookupFromFile) {
2092 Token FilenameTok;
2094 return;
2095
2096 if (FilenameTok.isNot(tok::header_name)) {
2097 if (FilenameTok.is(tok::identifier) && PPOpts.SingleFileParseMode) {
2098
2099
2100
2101
2103 return;
2104 }
2105
2106 Diag(FilenameTok.getLocation(), diag::err_pp_expects_filename);
2107 if (FilenameTok.isNot(tok::eod))
2109 return;
2110 }
2111
2112
2113
2114
2115
2116 SourceLocation EndLoc =
2118
2119 auto Action = HandleHeaderIncludeOrImport(HashLoc, IncludeTok, FilenameTok,
2120 EndLoc, LookupFrom, LookupFromFile);
2121 switch (Action.Kind) {
2122 case ImportAction::None:
2123 case ImportAction::SkippedModuleImport:
2124 break;
2125 case ImportAction::ModuleBegin:
2127 tok::annot_module_begin, Action.ModuleForHeader);
2128 break;
2129 case ImportAction::HeaderUnitImport:
2131 Action.ModuleForHeader);
2132 break;
2133 case ImportAction::ModuleImport:
2135 tok::annot_module_include, Action.ModuleForHeader);
2136 break;
2137 case ImportAction::Failure:
2138 assert(TheModuleLoader.HadFatalFailure &&
2139 "This should be an early exit only to a fatal error");
2140 TheModuleLoader.HadFatalFailure = true;
2141 IncludeTok.setKind(tok::eof);
2142 CurLexer->cutOffLexing();
2143 return;
2144 }
2145}
2146
2150 const Token &FilenameTok, bool &IsFrameworkFound, bool IsImportDecl,
2152 const FileEntry *LookupFromFile, StringRef &LookupFilename,
2155 auto DiagnoseHeaderInclusion = [&](FileEntryRef FE) {
2156 if (LangOpts.AsmPreprocessor)
2157 return;
2158
2160 FilenameLoc, LangOpts.ModulesValidateTextualHeaderIncludes);
2161 bool RequestingModuleIsModuleInterface =
2162 !SourceMgr.isInMainFile(FilenameLoc);
2163
2164 HeaderInfo.getModuleMap().diagnoseHeaderInclusion(
2165 RequestingModule, RequestingModuleIsModuleInterface, FilenameLoc,
2166 Filename, FE);
2167 };
2168
2170 FilenameLoc, LookupFilename, isAngled, LookupFrom, LookupFromFile, CurDir,
2171 Callbacks ? &SearchPath : nullptr, Callbacks ? &RelativePath : nullptr,
2172 &SuggestedModule, &IsMapped, &IsFrameworkFound);
2174 DiagnoseHeaderInclusion(*File);
2175 return File;
2176 }
2177
2178
2179 if (Callbacks && Callbacks->FileNotFound(Filename))
2180 return std::nullopt;
2181
2182 if (SuppressIncludeNotFoundError)
2183 return std::nullopt;
2184
2185
2186
2187
2188 if (isAngled) {
2190 FilenameLoc, LookupFilename, false, LookupFrom, LookupFromFile, CurDir,
2191 Callbacks ? &SearchPath : nullptr, Callbacks ? &RelativePath : nullptr,
2192 &SuggestedModule, &IsMapped,
2193 nullptr);
2195 DiagnoseHeaderInclusion(*File);
2196 Diag(FilenameTok, diag::err_pp_file_not_found_angled_include_not_fatal)
2197 << Filename << IsImportDecl
2199 "\"" + Filename.str() + "\"");
2200 return File;
2201 }
2202 }
2203
2204
2205
2206 StringRef OriginalFilename = Filename;
2207 if (LangOpts.SpellChecking) {
2208
2209
2210 auto CorrectTypoFilename = [](llvm::StringRef Filename) {
2212 while (!Filename.empty() && (Filename.back())) {
2213 Filename = Filename.drop_back();
2214 }
2215 return Filename;
2216 };
2217 StringRef TypoCorrectionName = CorrectTypoFilename(Filename);
2218 StringRef TypoCorrectionLookupName = CorrectTypoFilename(LookupFilename);
2219
2221 FilenameLoc, TypoCorrectionLookupName, isAngled, LookupFrom,
2222 LookupFromFile, CurDir, Callbacks ? &SearchPath : nullptr,
2223 Callbacks ? &RelativePath : nullptr, &SuggestedModule, &IsMapped,
2224 nullptr);
2226 DiagnoseHeaderInclusion(*File);
2227 auto Hint =
2229 FilenameRange, "<" + TypoCorrectionName.str() + ">")
2230 : FixItHint::CreateReplacement(
2231 FilenameRange, "\"" + TypoCorrectionName.str() + "\"");
2232 Diag(FilenameTok, diag::err_pp_file_not_found_typo_not_fatal)
2233 << OriginalFilename << TypoCorrectionName << Hint;
2234
2235
2236 Filename = TypoCorrectionName;
2237 LookupFilename = TypoCorrectionLookupName;
2238 return File;
2239 }
2240 }
2241
2242
2243 assert( && "expected missing file");
2244 Diag(FilenameTok, diag::err_pp_file_not_found)
2245 << OriginalFilename << FilenameRange;
2246 if (IsFrameworkFound) {
2247 size_t SlashPos = OriginalFilename.find('/');
2248 assert(SlashPos != StringRef::npos &&
2249 "Include with framework name should have '/' in the filename");
2250 StringRef FrameworkName = OriginalFilename.substr(0, SlashPos);
2251 FrameworkCacheEntry &CacheEntry =
2252 HeaderInfo.LookupFrameworkCache(FrameworkName);
2253 assert(CacheEntry.Directory && "Found framework should be in cache");
2254 Diag(FilenameTok, diag::note_pp_framework_without_header)
2255 << OriginalFilename.substr(SlashPos + 1) << FrameworkName
2257 }
2258
2259 return std::nullopt;
2260}
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport(
2277 const FileEntry *LookupFromFile) {
2278 SmallString<128> FilenameBuffer;
2279 StringRef Filename = getSpelling(FilenameTok, FilenameBuffer);
2280 SourceLocation CharEnd = FilenameTok.getEndLoc();
2281
2282 CharSourceRange FilenameRange
2284 StringRef OriginalFilename = Filename;
2285 bool isAngled =
2287
2288
2289
2290 if (Filename.empty())
2291 return {ImportAction::None};
2292
2293 bool IsImportDecl = HashLoc.isInvalid();
2294 SourceLocation StartLoc = IsImportDecl ? IncludeTok.getLocation() : HashLoc;
2295
2296
2297 if (PragmaARCCFCodeAuditedInfo.getLoc().isValid()) {
2298 Diag(StartLoc, diag::err_pp_include_in_arc_cf_code_audited) << IsImportDecl;
2299 Diag(PragmaARCCFCodeAuditedInfo.getLoc(), diag::note_pragma_entered_here);
2300
2301
2302 PragmaARCCFCodeAuditedInfo = IdentifierLoc();
2303 }
2304
2305
2306 if (PragmaAssumeNonNullLoc.isValid()) {
2307 Diag(StartLoc, diag::err_pp_include_in_assume_nonnull) << IsImportDecl;
2308 Diag(PragmaAssumeNonNullLoc, diag::note_pragma_entered_here);
2309
2310
2311 PragmaAssumeNonNullLoc = SourceLocation();
2312 }
2313
2314 if (HeaderInfo.HasIncludeAliasMap()) {
2315
2316
2317
2318 StringRef NewName = HeaderInfo.MapHeaderToIncludeAlias(OriginalFilename);
2319 if (!NewName.empty())
2320 Filename = NewName;
2321 }
2322
2323
2324 bool IsMapped = false;
2325 bool IsFrameworkFound = false;
2327 SmallString<1024> SearchPath;
2328 SmallString<1024> RelativePath;
2329
2330
2331 ModuleMap::KnownHeader SuggestedModule;
2332 SourceLocation FilenameLoc = FilenameTok.getLocation();
2333 StringRef LookupFilename = Filename;
2334
2335
2336
2337 SmallString<128> NormalizedPath;
2338 llvm::sys::path::Style BackslashStyle = llvm::sys::path::Style::native;
2339 if (is_style_posix(BackslashStyle) && LangOpts.MicrosoftExt) {
2340 NormalizedPath = Filename.str();
2341 llvm::sys::path::native(NormalizedPath);
2342 LookupFilename = NormalizedPath;
2343 BackslashStyle = llvm::sys::path::Style::windows;
2344 }
2345
2347 &CurDir, Filename, FilenameLoc, FilenameRange, FilenameTok,
2348 IsFrameworkFound, IsImportDecl, IsMapped, LookupFrom, LookupFromFile,
2349 LookupFilename, RelativePath, SearchPath, SuggestedModule, isAngled);
2350
2353 SkippingUntilPCHThroughHeader = false;
2354 return {ImportAction::None};
2355 }
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372 enum { Enter, Import, Skip, IncludeLimitReached } Action = Enter;
2373
2374 if (PPOpts.SingleFileParseMode)
2375 Action = IncludeLimitReached;
2376
2377
2378
2379
2380 if (Action == Enter && HasReachedMaxIncludeDepth && File &&
2382 Action = IncludeLimitReached;
2383
2384
2385
2386
2388
2389 bool MaybeTranslateInclude = Action == Enter && File && ModuleToImport &&
2391
2392
2393 bool UsableHeaderUnit = false;
2394 if (getLangOpts().CPlusPlusModules && ModuleToImport &&
2396 if (TrackGMFState.inGMF() || IsImportDecl)
2397 UsableHeaderUnit = true;
2398 else if (!IsImportDecl) {
2399
2400 ModuleToImport = nullptr;
2401 }
2402 }
2403
2404 bool UsableClangHeaderModule =
2406 ModuleToImport && !ModuleToImport->isHeaderUnit();
2407
2408
2409
2410
2411 if (MaybeTranslateInclude && (UsableHeaderUnit || UsableClangHeaderModule)) {
2412
2413
2414
2415
2419 diag::note_implicit_top_level_module_import_here)
2421 return {ImportAction::None};
2422 }
2423
2424
2425
2426
2427 SmallVector<IdentifierLoc, 2> Path;
2428 for (Module *Mod = ModuleToImport; Mod; Mod = Mod->Parent)
2429 Path.emplace_back(FilenameTok.getLocation(),
2431 std::reverse(Path.begin(), Path.end());
2432
2433
2434 if (!IsImportDecl)
2436
2437
2438
2439
2440
2441 ModuleLoadResult Imported = TheModuleLoader.loadModule(
2443 true);
2444 assert((Imported == nullptr || Imported == ModuleToImport) &&
2445 "the imported module is different than the suggested one");
2446
2447 if (Imported) {
2451 static_cast<Module *>(Imported)->getTopLevelModule());
2452
2453
2454
2455
2456 ModuleToImport = nullptr;
2458
2459
2460 } else {
2461
2463
2464 Token &Result = IncludeTok;
2465 assert(CurLexer && "#include but no current lexer set!");
2466 Result.startToken();
2467 CurLexer->FormTokenWithChars(Result, CurLexer->BufferEnd, tok::eof);
2468 CurLexer->cutOffLexing();
2469 }
2470 return {ImportAction::None};
2471 }
2472 }
2473
2474
2475
2476
2478 SourceMgr.getFileCharacteristic(FilenameTok.getLocation());
2480 FileCharacter = std::max(HeaderInfo.getFileDirFlavor(*File), FileCharacter);
2481
2482
2483
2484
2485
2486
2487 bool EnterOnce =
2488 IsImportDecl ||
2490
2491 bool IsFirstIncludeOfFile = false;
2492
2493
2494
2495 if (Action == Enter && File &&
2496 !HeaderInfo.ShouldEnterIncludeFile(*this, *File, EnterOnce,
2498 IsFirstIncludeOfFile)) {
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509 if (UsableHeaderUnit && ().CompilingPCH)
2510 Action = TrackGMFState.inGMF() ? Import : Skip;
2511 else
2512 Action = (ModuleToImport && ().CompilingPCH) ? Import : Skip;
2513 }
2514
2515
2516
2517
2518
2519
2520 if (Action == Enter && File && PreambleConditionalStack.isRecording() &&
2521 SourceMgr.isMainFile(File->getFileEntry())) {
2523 diag::err_pp_including_mainfile_in_preamble);
2524 return {ImportAction::None};
2525 }
2526
2527 if (Callbacks && !IsImportDecl) {
2528
2529
2530 Callbacks->InclusionDirective(HashLoc, IncludeTok, LookupFilename, isAngled,
2531 FilenameRange, File, SearchPath, RelativePath,
2532 SuggestedModule.getModule(), Action == Import,
2533 FileCharacter);
2535 Callbacks->FileSkipped(*File, FilenameTok, FileCharacter);
2536 }
2537
2539 return {ImportAction::None};
2540
2541
2542
2543 if (IsImportDecl && !ModuleToImport) {
2544 Diag(FilenameTok, diag::err_header_import_not_header_unit)
2545 << OriginalFilename << File->getName();
2546 return {ImportAction::None};
2547 }
2548
2549
2550
2551 const bool CheckIncludePathPortability =
2552 !IsMapped && ->getFileEntry().tryGetRealPathName().empty();
2553
2554 if (CheckIncludePathPortability) {
2555 StringRef Name = LookupFilename;
2556 StringRef NameWithoriginalSlashes = Filename;
2557#if defined(_WIN32)
2558
2559
2560 bool NameWasUNC = Name.consume_front("\\\\?\\");
2561 NameWithoriginalSlashes.consume_front("\\\\?\\");
2562#endif
2563 StringRef RealPathName = File->getFileEntry().tryGetRealPathName();
2564 SmallVector<StringRef, 16> Components(llvm::sys::path::begin(Name),
2565 llvm::sys::path::end(Name));
2566#if defined(_WIN32)
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577 SmallString<128> FixedDriveRealPath;
2578 if (llvm::sys::path::is_absolute(Name) &&
2579 llvm::sys::path::is_absolute(RealPathName) &&
2582 assert(Components.size() >= 3 && "should have drive, backslash, name");
2583 assert(Components[0].size() == 2 && "should start with drive");
2584 assert(Components[0][1] == ':' && "should have colon");
2585 FixedDriveRealPath = (Name.substr(0, 1) + RealPathName.substr(1)).str();
2586 RealPathName = FixedDriveRealPath;
2587 }
2588#endif
2589
2590 if (trySimplifyPath(Components, RealPathName, BackslashStyle)) {
2591 SmallString<128> Path;
2592 Path.reserve(Name.size()+2);
2593 Path.push_back(isAngled ? '<' : '"');
2594
2595 const auto IsSep = [BackslashStyle](char c) {
2596 return llvm::sys::path::is_separator(c, BackslashStyle);
2597 };
2598
2599 for (auto Component : Components) {
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611 if (!(Component.size() == 1 && IsSep(Component[0])))
2612 Path.append(Component);
2613 else if (Path.size() != 1)
2614 continue;
2615
2616
2617 if (Path.size() > NameWithoriginalSlashes.size()) {
2618 Path.push_back(isAngled ? '>' : '"');
2619 continue;
2620 }
2621 assert(IsSep(NameWithoriginalSlashes[Path.size()-1]));
2622 do
2623 Path.push_back(NameWithoriginalSlashes[Path.size()-1]);
2624 while (Path.size() <= NameWithoriginalSlashes.size() &&
2625 IsSep(NameWithoriginalSlashes[Path.size()-1]));
2626 }
2627
2628#if defined(_WIN32)
2629
2630 if (NameWasUNC)
2631 Path = (Path.substr(0, 1) + "\\\\?\\" + Path.substr(1)).str();
2632#endif
2633
2634
2635
2636 auto DiagId =
2638 ? diag::pp_nonportable_path
2639 : diag::pp_nonportable_system_path;
2640 Diag(FilenameTok, DiagId) << Path <<
2642 }
2643 }
2644
2645 switch (Action) {
2647
2648 if (ModuleToImport)
2649 return {ImportAction::SkippedModuleImport, ModuleToImport};
2650 return {ImportAction::None};
2651
2652 case IncludeLimitReached:
2653
2654
2655 return {ImportAction::None};
2656
2658
2659 assert(ModuleToImport && "no module to import");
2660
2662
2664 tok::pp___include_macros)
2665 return {ImportAction::None};
2666
2667 return {ImportAction::ModuleImport, ModuleToImport};
2668 }
2669
2670 case Enter:
2671 break;
2672 }
2673
2674
2675 if (IncludeMacroStack.size() == MaxAllowedIncludeStackDepth-1) {
2676 Diag(FilenameTok, diag::err_pp_include_too_deep);
2677 HasReachedMaxIncludeDepth = true;
2678 return {ImportAction::None};
2679 }
2680
2682 Diag(FilenameTok, diag::warn_pp_include_angled_in_module_purview)
2684
2685
2686 SourceLocation IncludePos = FilenameTok.getLocation();
2687
2688
2690 IncludePos = SourceMgr.getExpansionRange(IncludePos).getEnd();
2691 FileID FID = SourceMgr.createFileID(*File, IncludePos, FileCharacter);
2693 TheModuleLoader.HadFatalFailure = true;
2694 return ImportAction::Failure;
2695 }
2696
2697
2699 IsFirstIncludeOfFile))
2700 return {ImportAction::None};
2701
2702
2703
2704 if (ModuleToImport && !ModuleToImport->isHeaderUnit()) {
2706
2707
2709 diag::err_module_build_shadowed_submodule)
2712 diag::note_previous_definition);
2713 return {ImportAction::None};
2714 }
2715
2716
2717
2718
2719
2720
2721
2722
2725 return {ImportAction::None};
2726
2727 assert(!CurLexerSubmodule && "should not have marked this as a module yet");
2728 CurLexerSubmodule = ModuleToImport;
2729
2730
2731
2732 EnterSubmodule(ModuleToImport, EndLoc, false);
2733
2734
2735
2736
2737
2738 return {ImportAction::ModuleBegin, ModuleToImport};
2739 }
2740
2741 assert(!IsImportDecl && "failed to diagnose missing module for import decl");
2742 return {ImportAction::None};
2743}
2744
2745
2746
2747void Preprocessor::HandleIncludeNextDirective(SourceLocation HashLoc,
2748 Token &IncludeNextTok) {
2749 Diag(IncludeNextTok, diag::ext_pp_include_next_directive);
2750
2752 const FileEntry *LookupFromFile;
2753 std::tie(Lookup, LookupFromFile) = getIncludeNextStart(IncludeNextTok);
2754
2755 return HandleIncludeDirective(HashLoc, IncludeNextTok, Lookup,
2756 LookupFromFile);
2757}
2758
2759
2760void Preprocessor::HandleMicrosoftImportDirective(Token &Tok) {
2761
2762
2763
2764
2765
2766 Diag(Tok, diag::err_pp_import_directive_ms );
2767
2768
2769
2771}
2772
2773
2774
2775void Preprocessor::HandleImportDirective(SourceLocation HashLoc,
2776 Token &ImportTok) {
2777 if (!LangOpts.ObjC) {
2778 if (LangOpts.MSVCCompat)
2779 return HandleMicrosoftImportDirective(ImportTok);
2780 Diag(ImportTok, diag::ext_pp_import_directive);
2781 }
2782 return HandleIncludeDirective(HashLoc, ImportTok);
2783}
2784
2785
2786
2787
2788
2789void Preprocessor::HandleIncludeMacrosDirective(SourceLocation HashLoc,
2790 Token &IncludeMacrosTok) {
2791
2792
2793 SourceLocation Loc = IncludeMacrosTok.getLocation();
2794 if (SourceMgr.getBufferName(Loc) != "") {
2796 diag::pp_include_macros_out_of_predefines);
2798 return;
2799 }
2800
2801
2802
2803 HandleIncludeDirective(HashLoc, IncludeMacrosTok);
2804
2805 Token TmpTok;
2806 do {
2807 Lex(TmpTok);
2808 assert(TmpTok.isNot(tok::eof) && "Didn't find end of -imacros!");
2809 } while (TmpTok.isNot(tok::hashhash));
2810}
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820bool Preprocessor::ReadMacroParameterList(MacroInfo *MI, Token &Tok) {
2821 SmallVector<IdentifierInfo*, 32> Parameters;
2822
2823 while (true) {
2826 case tok::r_paren:
2827
2828 if (Parameters.empty())
2829 return false;
2830
2831 Diag(Tok, diag::err_pp_expected_ident_in_arg_list);
2832 return true;
2833 case tok::ellipsis:
2834 if (!LangOpts.C99)
2835 Diag(Tok, LangOpts.CPlusPlus11 ?
2836 diag::warn_cxx98_compat_variadic_macro :
2837 diag::ext_variadic_macro);
2838
2839
2840 if (LangOpts.OpenCL && !LangOpts.OpenCLCPlusPlus) {
2841 Diag(Tok, diag::ext_pp_opencl_variadic_macros);
2842 }
2843
2844
2846 if (Tok.isNot(tok::r_paren)) {
2847 Diag(Tok, diag::err_pp_missing_rparen_in_macro_def);
2848 return true;
2849 }
2850
2851 Parameters.push_back(Ident__VA_ARGS__);
2854 return false;
2855 case tok::eod:
2856 Diag(Tok, diag::err_pp_missing_rparen_in_macro_def);
2857 return true;
2858 default:
2859
2860
2862 if (!II) {
2863
2864 Diag(Tok, diag::err_pp_invalid_tok_in_arg_list);
2865 return true;
2866 }
2867
2868
2869
2870 if (llvm::is_contained(Parameters, II)) {
2871 Diag(Tok, diag::err_pp_duplicate_name_in_arg_list) << II;
2872 return true;
2873 }
2874
2875
2877
2878
2880
2882 default:
2883 Diag(Tok, diag::err_pp_expected_comma_in_arg_list);
2884 return true;
2885 case tok::r_paren:
2887 return false;
2888 case tok::comma:
2889 break;
2890 case tok::ellipsis:
2891
2892 Diag(Tok, diag::ext_named_variadic_macro);
2893
2894
2896 if (Tok.isNot(tok::r_paren)) {
2897 Diag(Tok, diag::err_pp_missing_rparen_in_macro_def);
2898 return true;
2899 }
2900
2903 return false;
2904 }
2905 }
2906 }
2907}
2908
2913
2914
2916 return true;
2917
2918
2919
2920
2921
2922
2926 return false;
2927 StringRef ValueText = II->getName();
2928 StringRef TrimmedValue = ValueText;
2929 if (!ValueText.starts_with("__")) {
2930 if (ValueText.starts_with("_"))
2931 TrimmedValue = TrimmedValue.drop_front(1);
2932 else
2933 return false;
2934 } else {
2935 TrimmedValue = TrimmedValue.drop_front(2);
2936 if (TrimmedValue.ends_with("__"))
2937 TrimmedValue = TrimmedValue.drop_back(2);
2938 }
2939 return TrimmedValue == MacroText;
2940 } else {
2941 return false;
2942 }
2943 }
2944
2945
2946 return MacroName.isOneOf(tok::kw_extern, tok::kw_inline, tok::kw_static,
2947 tok::kw_const) &&
2949}
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959MacroInfo *Preprocessor::ReadOptionalMacroParameterListAndBody(
2960 const Token &MacroNameTok, const bool ImmediatelyAfterHeaderGuard) {
2961
2962 Token LastTok = MacroNameTok;
2963
2965
2966 Token Tok;
2968
2969
2970 auto _ = llvm::make_scope_exit([&]() {
2971
2972 if (CurLexer->ParsingPreprocessorDirective)
2974 });
2975
2976
2977
2979
2980
2981
2982
2984 if (ImmediatelyAfterHeaderGuard) {
2985
2986 CurPPLexer->MIOpt.SetDefinedMacro(MacroNameTok.getIdentifierInfo(),
2988 }
2989
2991
2992
2994 } else if (Tok.is(tok::l_paren)) {
2995
2997 if (ReadMacroParameterList(MI, LastTok))
2998 return nullptr;
2999
3000
3001
3002
3003
3004
3007 }
3008
3009
3011 } else if (LangOpts.C99 || LangOpts.CPlusPlus11) {
3012
3013
3014 Diag(Tok, diag::ext_c99_whitespace_required_after_macro_name);
3015 } else {
3016
3017
3018
3019
3020
3021
3025 else if (Tok.is(tok::unknown)) {
3026
3027
3028
3030 }
3032 Diag(Tok, diag::ext_missing_whitespace_after_macro_name);
3033 else
3034 Diag(Tok, diag::warn_missing_whitespace_after_macro_name);
3035 }
3036
3037 if (.is(tok::eod))
3038 LastTok = Tok;
3039
3040 SmallVector<Token, 16> Tokens;
3041
3042
3044
3045 while (Tok.isNot(tok::eod)) {
3046 LastTok = Tok;
3047 Tokens.push_back(Tok);
3048
3050 }
3051 } else {
3052
3053
3054
3055
3057
3058 while (Tok.isNot(tok::eod)) {
3059 LastTok = Tok;
3060
3061 if (.isOneOf(tok::hash, tok::hashat, tok::hashhash)) {
3062 Tokens.push_back(Tok);
3063
3064 if (VAOCtx.isVAOptToken(Tok)) {
3065
3066 if (VAOCtx.isInVAOpt()) {
3067 Diag(Tok, diag::err_pp_vaopt_nested_use);
3068 return nullptr;
3069 }
3070
3072 if (Tok.isNot(tok::l_paren)) {
3073 Diag(Tok, diag::err_pp_missing_lparen_in_vaopt_use);
3074 return nullptr;
3075 }
3076 Tokens.push_back(Tok);
3077 VAOCtx.sawVAOptFollowedByOpeningParens(Tok.getLocation());
3079 if (Tok.is(tok::hashhash)) {
3080 Diag(Tok, diag::err_vaopt_paste_at_start);
3081 return nullptr;
3082 }
3083 continue;
3084 } else if (VAOCtx.isInVAOpt()) {
3085 if (Tok.is(tok::r_paren)) {
3086 if (VAOCtx.sawClosingParen()) {
3087 assert(Tokens.size() >= 3 &&
3088 "Must have seen at least __VA_OPT__( "
3089 "and a subsequent tok::r_paren");
3090 if (Tokens[Tokens.size() - 2].is(tok::hashhash)) {
3091 Diag(Tok, diag::err_vaopt_paste_at_end);
3092 return nullptr;
3093 }
3094 }
3095 } else if (Tok.is(tok::l_paren)) {
3097 }
3098 }
3099
3101 continue;
3102 }
3103
3104
3105
3106
3109 Tokens.push_back(Tok);
3110
3111
3113 continue;
3114 }
3115
3116 if (Tok.is(tok::hashhash)) {
3117
3118
3119
3120
3121
3123
3125 Tokens.push_back(LastTok);
3126 break;
3127 }
3128
3130 Tokens[Tokens.size() - 1].is(tok::comma))
3132
3133
3134 Tokens.push_back(LastTok);
3135 continue;
3136 }
3137
3138
3139
3141
3142
3143 if (!VAOCtx.isVAOptToken(Tok) &&
3146
3147
3148
3149
3150
3152 LastTok.setKind(tok::unknown);
3153 Tokens.push_back(LastTok);
3154 continue;
3155 } else {
3156 Diag(Tok, diag::err_pp_stringize_not_parameter)
3157 << LastTok.is(tok::hashat);
3158 return nullptr;
3159 }
3160 }
3161
3162
3163 Tokens.push_back(LastTok);
3164
3165
3166
3167
3168 if (!VAOCtx.isVAOptToken(Tok)) {
3169 Tokens.push_back(Tok);
3170 LastTok = Tok;
3171
3172
3174 }
3175 }
3176 if (VAOCtx.isInVAOpt()) {
3177 assert(Tok.is(tok::eod) && "Must be at End Of preprocessing Directive");
3178 Diag(Tok, diag::err_pp_expected_after)
3179 << LastTok.getKind() << tok::r_paren;
3180 Diag(VAOCtx.getUnmatchedOpeningParenLoc(), diag::note_matching) << tok::l_paren;
3181 return nullptr;
3182 }
3183 }
3185
3187 return MI;
3188}
3189
3191 return II->isStr("__strong") || II->isStr("__weak") ||
3192 II->isStr("__unsafe_unretained") || II->isStr("__autoreleasing");
3193}
3194
3195
3196
3197void Preprocessor::HandleDefineDirective(
3198 Token &DefineTok, const bool ImmediatelyAfterHeaderGuard) {
3199 ++NumDefined;
3200
3201 Token MacroNameTok;
3202 bool MacroShadowsKeyword;
3203 ReadMacroName(MacroNameTok, MU_Define, &MacroShadowsKeyword);
3204
3205
3206 if (MacroNameTok.is(tok::eod))
3207 return;
3208
3210
3211
3213 emitFinalMacroWarning(MacroNameTok, false);
3214
3215
3216
3217 if (CurLexer) CurLexer->SetCommentRetentionState(KeepMacroComments);
3218
3219 MacroInfo *const MI = ReadOptionalMacroParameterListAndBody(
3220 MacroNameTok, ImmediatelyAfterHeaderGuard);
3221
3222 if (!MI) return;
3223
3224 if (MacroShadowsKeyword &&
3226 Diag(MacroNameTok, diag::warn_pp_macro_hides_keyword);
3227 }
3228
3229
3231 if (NumTokens != 0) {
3234 return;
3235 }
3238 return;
3239 }
3240 }
3241
3242
3243 if (SkippingUntilPCHThroughHeader) {
3245 if (!OtherMI || !MI->isIdenticalTo(*OtherMI, *this,
3246 LangOpts.MicrosoftExt))
3249
3250 if (!LangOpts.MicrosoftExt)
3251 return;
3252 }
3253
3254
3255
3257
3258
3259
3261 emitFinalMacroWarning(MacroNameTok, false);
3262
3263
3264
3265
3270
3271 if ((().getSuppressSystemWarnings() ||
3272 !SourceMgr.isInSystemHeader(DefineTok.getLocation())) &&
3274 LangOpts.MicrosoftExt)) {
3276 }
3278 return;
3279 }
3280
3281
3282
3283
3284 if (().getSuppressSystemWarnings() ||
3285 !SourceMgr.isInSystemHeader(DefineTok.getLocation())) {
3286
3289
3290
3291
3293 Diag(MacroNameTok, diag::ext_pp_redef_builtin_macro);
3294
3295
3297 !MI->isIdenticalTo(*OtherMI, *this, LangOpts.MicrosoftExt)) {
3301 }
3302 }
3305 }
3306
3307 DefMacroDirective *MD =
3309
3310 assert(!MI->isUsed());
3311
3312
3314 !Diags->isIgnored(diag::pp_macro_not_used, MI->getDefinitionLoc()) &&
3315 !MacroExpansionInDirectivesOverride &&
3320 }
3321
3322
3323 if (Callbacks)
3324 Callbacks->MacroDefined(MacroNameTok, MD);
3325}
3326
3327
3328
3329void Preprocessor::HandleUndefDirective() {
3330 ++NumUndefined;
3331
3332 Token MacroNameTok;
3333 ReadMacroName(MacroNameTok, MU_Undef);
3334
3335
3336 if (MacroNameTok.is(tok::eod))
3337 return;
3338
3339
3341
3342
3345 UndefMacroDirective *Undef = nullptr;
3346
3348 emitFinalMacroWarning(MacroNameTok, true);
3349
3350
3351 if (const MacroInfo *MI = MD.getMacroInfo()) {
3354
3355
3356
3358 Diag(MacroNameTok, diag::ext_pp_undef_builtin_macro);
3359
3362
3363 Undef = AllocateUndefMacroDirective(MacroNameTok.getLocation());
3364 }
3365
3366
3367
3368 if (Callbacks)
3369 Callbacks->MacroUndefined(MacroNameTok, MD, Undef);
3370
3371 if (Undef)
3373}
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384void Preprocessor::HandleIfdefDirective(Token &Result,
3385 const Token &HashToken,
3386 bool isIfndef,
3387 bool ReadAnyTokensBeforeDirective) {
3388 ++NumIf;
3389 Token DirectiveTok = Result;
3390
3391 Token MacroNameTok;
3392 ReadMacroName(MacroNameTok);
3393
3394
3395 if (MacroNameTok.is(tok::eod)) {
3396
3397
3398 SkipExcludedConditionalBlock(HashToken.getLocation(),
3400 false, false);
3401 return;
3402 }
3403
3405
3406
3408
3412
3413 if (CurPPLexer->getConditionalStackDepth() == 0) {
3414
3415
3416
3417
3418 if (!ReadAnyTokensBeforeDirective && !MI) {
3419 assert(isIfndef && "#ifdef shouldn't reach here");
3420 CurPPLexer->MIOpt.EnterTopLevelIfndef(MII, MacroNameTok.getLocation());
3421 } else
3422 CurPPLexer->MIOpt.EnterTopLevelConditional();
3423 }
3424
3425
3426 if (MI)
3428
3429 if (Callbacks) {
3430 if (isIfndef)
3431 Callbacks->Ifndef(DirectiveTok.getLocation(), MacroNameTok, MD);
3432 else
3433 Callbacks->Ifdef(DirectiveTok.getLocation(), MacroNameTok, MD);
3434 }
3435
3436 bool RetainExcludedCB = PPOpts.RetainExcludedConditionalBlocks &&
3438
3439
3440 if (PPOpts.SingleFileParseMode && !MI) {
3441
3442
3443 CurPPLexer->pushConditionalLevel(DirectiveTok.getLocation(),
3444 false, false,
3445 false);
3446 } else if (!MI == isIfndef || RetainExcludedCB) {
3447
3448 CurPPLexer->pushConditionalLevel(DirectiveTok.getLocation(),
3449 false, true,
3450 false);
3451 } else {
3452
3453 SkipExcludedConditionalBlock(HashToken.getLocation(),
3455 false,
3456 false);
3457 }
3458}
3459
3460
3461
3462void Preprocessor::HandleIfDirective(Token &IfToken,
3463 const Token &HashToken,
3464 bool ReadAnyTokensBeforeDirective) {
3465 ++NumIf;
3466
3467
3468 IdentifierInfo *IfNDefMacro = nullptr;
3469 const DirectiveEvalResult DER = EvaluateDirectiveExpression(IfNDefMacro);
3470 const bool ConditionalTrue = DER.Conditional;
3471
3472
3473 if (!CurPPLexer)
3474 return;
3475
3476
3477
3478 if (CurPPLexer->getConditionalStackDepth() == 0) {
3479 if (!ReadAnyTokensBeforeDirective && IfNDefMacro && ConditionalTrue)
3480
3481 CurPPLexer->MIOpt.EnterTopLevelIfndef(IfNDefMacro, IfToken.getLocation());
3482 else
3483 CurPPLexer->MIOpt.EnterTopLevelConditional();
3484 }
3485
3486 if (Callbacks)
3487 Callbacks->If(
3490
3491 bool RetainExcludedCB = PPOpts.RetainExcludedConditionalBlocks &&
3493
3494
3495 if (PPOpts.SingleFileParseMode && DER.IncludedUndefinedIds) {
3496
3497
3498 CurPPLexer->pushConditionalLevel(IfToken.getLocation(), false,
3499 false, false);
3500 } else if (ConditionalTrue || RetainExcludedCB) {
3501
3502 CurPPLexer->pushConditionalLevel(IfToken.getLocation(), false,
3503 true, false);
3504 } else {
3505
3507 false,
3508 false);
3509 }
3510}
3511
3512
3513
3514void Preprocessor::HandleEndifDirective(Token &EndifToken) {
3515 ++NumEndif;
3516
3517
3519
3520 PPConditionalInfo CondInfo;
3521 if (CurPPLexer->popConditionalLevel(CondInfo)) {
3522
3523 Diag(EndifToken, diag::err_pp_endif_without_if);
3524 return;
3525 }
3526
3527
3528 if (CurPPLexer->getConditionalStackDepth() == 0)
3529 CurPPLexer->MIOpt.ExitTopLevelConditional();
3530
3531 assert(!CondInfo.WasSkipping && !CurPPLexer->LexingRawMode &&
3532 "This code should only be reachable in the non-skipping case!");
3533
3534 if (Callbacks)
3536}
3537
3538
3539
3540void Preprocessor::HandleElseDirective(Token &Result, const Token &HashToken) {
3541 ++NumElse;
3542
3543
3545
3546 PPConditionalInfo CI;
3547 if (CurPPLexer->popConditionalLevel(CI)) {
3548 Diag(Result, diag::pp_err_else_without_if);
3549 return;
3550 }
3551
3552
3553 if (CurPPLexer->getConditionalStackDepth() == 0)
3554 CurPPLexer->MIOpt.EnterTopLevelConditional();
3555
3556
3558
3559 if (Callbacks)
3560 Callbacks->Else(Result.getLocation(), CI.IfLoc);
3561
3562 bool RetainExcludedCB = PPOpts.RetainExcludedConditionalBlocks &&
3564
3565 if ((PPOpts.SingleFileParseMode && !CI.FoundNonSkip) || RetainExcludedCB) {
3566
3567
3568 CurPPLexer->pushConditionalLevel(CI.IfLoc, false,
3569 false, true);
3570 return;
3571 }
3572
3573
3574 SkipExcludedConditionalBlock(HashToken.getLocation(), CI.IfLoc,
3575 true,
3576 true, Result.getLocation());
3577}
3578
3579
3580void Preprocessor::HandleElifFamilyDirective(Token &ElifToken,
3581 const Token &HashToken,
3586 ++NumElse;
3587
3588
3589 switch (DirKind) {
3592 unsigned DiagID;
3593 if (LangOpts.CPlusPlus)
3594 DiagID = LangOpts.CPlusPlus23 ? diag::warn_cxx23_compat_pp_directive
3595 : diag::ext_cxx23_pp_directive;
3596 else
3597 DiagID = LangOpts.C23 ? diag::warn_c23_compat_pp_directive
3598 : diag::ext_c23_pp_directive;
3599 Diag(ElifToken, DiagID) << DirKind;
3600 break;
3601 default:
3602 break;
3603 }
3604
3605
3606
3607
3609
3610 PPConditionalInfo CI;
3611 if (CurPPLexer->popConditionalLevel(CI)) {
3612 Diag(ElifToken, diag::pp_err_elif_without_if) << DirKind;
3613 return;
3614 }
3615
3616
3617 if (CurPPLexer->getConditionalStackDepth() == 0)
3618 CurPPLexer->MIOpt.EnterTopLevelConditional();
3619
3620
3622 Diag(ElifToken, diag::pp_err_elif_after_else) << DirKind;
3623
3624 if (Callbacks) {
3625 switch (Kind) {
3626 case tok::pp_elif:
3627 Callbacks->Elif(ElifToken.getLocation(), ConditionRange,
3629 break;
3630 case tok::pp_elifdef:
3631 Callbacks->Elifdef(ElifToken.getLocation(), ConditionRange, CI.IfLoc);
3632 break;
3633 case tok::pp_elifndef:
3634 Callbacks->Elifndef(ElifToken.getLocation(), ConditionRange, CI.IfLoc);
3635 break;
3636 default:
3637 assert(false && "unexpected directive kind");
3638 break;
3639 }
3640 }
3641
3642 bool RetainExcludedCB = PPOpts.RetainExcludedConditionalBlocks &&
3644
3645 if ((PPOpts.SingleFileParseMode && !CI.FoundNonSkip) || RetainExcludedCB) {
3646
3647
3648 CurPPLexer->pushConditionalLevel(ElifToken.getLocation(), false,
3649 false, false);
3650 return;
3651 }
3652
3653
3654 SkipExcludedConditionalBlock(
3657}
3658
3659std::optional
3662 tok::TokenKind EndTokenKind = ForHasEmbed ? tok::r_paren : tok::eod;
3663
3664 auto DiagMismatchedBracesAndSkipToEOD =
3666 std::pair<tok::TokenKind, SourceLocation> Matches) {
3667 Diag(CurTok, diag::err_expected) << Expected;
3668 Diag(Matches.second, diag::note_matching) << Matches.first;
3669 if (CurTok.isNot(EndTokenKind))
3671 };
3672
3673 auto ExpectOrDiagAndSkipToEOD = [&](tok::TokenKind Kind) {
3674 if (CurTok.isNot(Kind)) {
3675 Diag(CurTok, diag::err_expected) << Kind;
3676 if (CurTok.isNot(EndTokenKind))
3678 return false;
3679 }
3680 return true;
3681 };
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693 auto LexPPParameterName = [&]() -> std::optionalstd::string {
3694
3695
3696 if (!ExpectOrDiagAndSkipToEOD(tok::identifier))
3697 return std::nullopt;
3698
3700
3701
3702
3704 if (CurTok.is(tok::coloncolon)) {
3705
3707 if (!ExpectOrDiagAndSkipToEOD(tok::identifier))
3708 return std::nullopt;
3709
3711
3712
3714 return (llvm::Twine(Prefix->getName()) + "::" + Suffix->getName()).str();
3715 }
3716 return Prefix->getName().str();
3717 };
3718
3719
3720
3721
3722
3723 auto NormalizeParameterName = [](StringRef Name) {
3724 if (Name.size() > 4 && Name.starts_with("__") && Name.ends_with("__"))
3725 return Name.substr(2, Name.size() - 4);
3726 return Name;
3727 };
3728
3729 auto LexParenthesizedIntegerExpr = [&]() -> std::optional<size_t> {
3730
3731
3732 if (!ExpectOrDiagAndSkipToEOD(tok::l_paren))
3733 return std::nullopt;
3734
3735
3736
3738 bool EvaluatedDefined;
3739 DirectiveEvalResult LimitEvalResult = EvaluateDirectiveExpression(
3740 ParameterIfNDef, CurTok, EvaluatedDefined, false);
3741
3742 if (!LimitEvalResult.Value) {
3743
3744
3745 assert(CurTok.is(tok::eod) && "expect to be at the end of directive");
3746 return std::nullopt;
3747 }
3748
3749 if (!ExpectOrDiagAndSkipToEOD(tok::r_paren))
3750 return std::nullopt;
3751
3752
3754
3755
3756
3757 if (EvaluatedDefined) {
3758 Diag(CurTok, diag::err_defined_in_pp_embed);
3759 return std::nullopt;
3760 }
3761
3762 if (LimitEvalResult.Value) {
3763 const llvm::APSInt &Result = *LimitEvalResult.Value;
3764 if (Result.isNegative()) {
3765 Diag(CurTok, diag::err_requires_positive_value)
3767 if (CurTok.isNot(EndTokenKind))
3769 return std::nullopt;
3770 }
3771 return Result.getLimitedValue();
3772 }
3773 return std::nullopt;
3774 };
3775
3776 auto GetMatchingCloseBracket = [](tok::TokenKind Kind) {
3777 switch (Kind) {
3778 case tok::l_paren:
3779 return tok::r_paren;
3780 case tok::l_brace:
3781 return tok::r_brace;
3782 case tok::l_square:
3783 return tok::r_square;
3784 default:
3785 llvm_unreachable("should not get here");
3786 }
3787 };
3788
3789 auto LexParenthesizedBalancedTokenSoup =
3791 std::vector<std::pair<tok::TokenKind, SourceLocation>> BracketStack;
3792
3793
3794 if (!ExpectOrDiagAndSkipToEOD(tok::l_paren))
3795 return false;
3797
3798 bool WaitingForInnerCloseParen = false;
3799 while (CurTok.isNot(tok::eod) &&
3800 (WaitingForInnerCloseParen || CurTok.isNot(tok::r_paren))) {
3801 switch (CurTok.getKind()) {
3802 default:
3803 break;
3804 case tok::l_paren:
3805 WaitingForInnerCloseParen = true;
3806 [[fallthrough]];
3807 case tok::l_brace:
3808 case tok::l_square:
3810 break;
3811 case tok::r_paren:
3812 WaitingForInnerCloseParen = false;
3813 [[fallthrough]];
3814 case tok::r_brace:
3815 case tok::r_square: {
3816 if (BracketStack.empty()) {
3817 ExpectOrDiagAndSkipToEOD(tok::r_paren);
3818 return false;
3819 }
3821 GetMatchingCloseBracket(BracketStack.back().first);
3822 if (CurTok.getKind() != Matching) {
3823 DiagMismatchedBracesAndSkipToEOD(Matching, BracketStack.back());
3824 return false;
3825 }
3826 BracketStack.pop_back();
3827 } break;
3828 }
3829 Tokens.push_back(CurTok);
3831 }
3832
3833
3834 if (!ExpectOrDiagAndSkipToEOD(tok::r_paren))
3835 return false;
3836
3838 return true;
3839 };
3840
3842 while (!CurTok.isOneOf(EndTokenKind, tok::eod)) {
3844 std::optionalstd::string ParamName = LexPPParameterName();
3845 if (!ParamName)
3846 return std::nullopt;
3847 StringRef Parameter = NormalizeParameterName(*ParamName);
3848
3849
3850
3851
3852
3854 if (Result.MaybeLimitParam)
3855 Diag(CurTok, diag::err_pp_embed_dup_params) << Parameter;
3856
3857 std::optional<size_t> Limit = LexParenthesizedIntegerExpr();
3858 if (!Limit)
3859 return std::nullopt;
3860 Result.MaybeLimitParam =
3862 } else if (Parameter == "clang::offset") {
3863 if (Result.MaybeOffsetParam)
3864 Diag(CurTok, diag::err_pp_embed_dup_params) << Parameter;
3865
3866 std::optional<size_t> Offset = LexParenthesizedIntegerExpr();
3867 if (!Offset)
3868 return std::nullopt;
3870 *Offset, {ParamStartLoc, CurTok.getLocation()}};
3871 } else if (Parameter == "prefix") {
3872 if (Result.MaybePrefixParam)
3873 Diag(CurTok, diag::err_pp_embed_dup_params) << Parameter;
3874
3876 if (!LexParenthesizedBalancedTokenSoup(Soup))
3877 return std::nullopt;
3879 std::move(Soup), {ParamStartLoc, CurTok.getLocation()}};
3880 } else if (Parameter == "suffix") {
3881 if (Result.MaybeSuffixParam)
3882 Diag(CurTok, diag::err_pp_embed_dup_params) << Parameter;
3883
3885 if (!LexParenthesizedBalancedTokenSoup(Soup))
3886 return std::nullopt;
3888 std::move(Soup), {ParamStartLoc, CurTok.getLocation()}};
3889 } else if (Parameter == "if_empty") {
3890 if (Result.MaybeIfEmptyParam)
3891 Diag(CurTok, diag::err_pp_embed_dup_params) << Parameter;
3892
3894 if (!LexParenthesizedBalancedTokenSoup(Soup))
3895 return std::nullopt;
3897 std::move(Soup), {ParamStartLoc, CurTok.getLocation()}};
3898 } else {
3899 ++Result.UnrecognizedParams;
3900
3901
3902
3903 if (CurTok.is(tok::l_paren)) {
3905 if (!LexParenthesizedBalancedTokenSoup(Soup))
3906 return std::nullopt;
3907 }
3908 if (!ForHasEmbed) {
3909 Diag(ParamStartLoc, diag::err_pp_unknown_parameter) << 1 << Parameter;
3910 if (CurTok.isNot(EndTokenKind))
3912 return std::nullopt;
3913 }
3914 }
3915 }
3917}
3918
3919void Preprocessor::HandleEmbedDirectiveImpl(
3921 StringRef BinaryContents, StringRef FileName) {
3922 if (BinaryContents.empty()) {
3923
3924
3925
3926
3927
3930 size_t TokCount = Toks.size();
3931 auto NewToks = std::make_unique<Token[]>(TokCount);
3932 llvm::copy(Toks, NewToks.get());
3933 EnterTokenStream(std::move(NewToks), TokCount, true, true);
3934 }
3935 return;
3936 }
3937
3940 size_t TotalNumToks = 1 + NumPrefixToks + NumSuffixToks;
3941 size_t CurIdx = 0;
3942 auto Toks = std::make_unique<Token[]>(TotalNumToks);
3943
3944
3947 CurIdx += NumPrefixToks;
3948 }
3949
3950 EmbedAnnotationData *Data = new (BP) EmbedAnnotationData;
3951 Data->BinaryData = BinaryContents;
3953
3954 Toks[CurIdx].startToken();
3955 Toks[CurIdx].setKind(tok::annot_embed);
3956 Toks[CurIdx].setAnnotationRange(HashLoc);
3957 Toks[CurIdx++].setAnnotationValue(Data);
3958
3959
3962 CurIdx += NumSuffixToks;
3963 }
3964
3965 assert(CurIdx == TotalNumToks && "Calculated the incorrect number of tokens");
3966 EnterTokenStream(std::move(Toks), TotalNumToks, true, true);
3967}
3968
3969void Preprocessor::HandleEmbedDirective(SourceLocation HashLoc, Token &EmbedTok,
3970 const FileEntry *LookupFromFile) {
3971
3972 if (LangOpts.C23)
3973 Diag(EmbedTok, diag::warn_compat_pp_embed_directive);
3974 else
3975 Diag(EmbedTok, diag::ext_pp_embed_directive)
3976 << (LangOpts.CPlusPlus ? 1 : 0);
3977
3978
3979 Token FilenameTok;
3981 return;
3982
3983 if (FilenameTok.isNot(tok::header_name)) {
3984 Diag(FilenameTok.getLocation(), diag::err_pp_expects_filename);
3985 if (FilenameTok.isNot(tok::eod))
3987 return;
3988 }
3989
3990
3991
3992
3993
3994
3995
3996
3997 Token CurTok;
3998 std::optional Params =
4000
4001 assert((Params || CurTok.is(tok::eod)) &&
4002 "expected success or to be at the end of the directive");
4003 if (!Params)
4004 return;
4005
4006
4007 SmallString<128> FilenameBuffer;
4008 StringRef Filename = getSpelling(FilenameTok, FilenameBuffer);
4009 StringRef OriginalFilename = Filename;
4010 bool isAngled =
4012
4013
4014
4015 if (Filename.empty())
4016 return;
4017
4019 this->LookupEmbedFile(Filename, isAngled, true, LookupFromFile);
4020 if (!MaybeFileRef) {
4021
4022 if (Callbacks && Callbacks->EmbedFileNotFound(Filename)) {
4023 return;
4024 }
4025 Diag(FilenameTok, diag::err_pp_file_not_found) << Filename;
4026 return;
4027 }
4028
4030 Diag(FilenameTok, diag::err_pp_embed_device_file) << Filename;
4031 return;
4032 }
4033
4034 std::optionalllvm::MemoryBufferRef MaybeFile =
4036 if (!MaybeFile) {
4037
4038 Diag(FilenameTok, diag::err_cannot_open_file)
4039 << Filename << "a buffer to the contents could not be created";
4040 return;
4041 }
4042 StringRef BinaryContents = MaybeFile->getBuffer();
4043
4044
4045
4046
4047 if (Params->MaybeOffsetParam) {
4048
4049
4050
4051
4052 BinaryContents = BinaryContents.substr(Params->MaybeOffsetParam->Offset);
4053 }
4054
4055 if (Params->MaybeLimitParam) {
4056
4057
4058
4059 BinaryContents = BinaryContents.substr(0, Params->MaybeLimitParam->Limit);
4060 }
4061
4062 if (Callbacks)
4063 Callbacks->EmbedDirective(HashLoc, Filename, isAngled, MaybeFileRef,
4064 *Params);
4065
4066
4067
4068
4069
4070
4071
4072 void *Mem = BP.Allocate(OriginalFilename.size(), alignof(char *));
4073 memcpy(Mem, OriginalFilename.data(), OriginalFilename.size());
4074 StringRef FilenameToGo =
4075 StringRef(static_cast<char *>(Mem), OriginalFilename.size());
4076 HandleEmbedDirectiveImpl(HashLoc, *Params, BinaryContents, FilenameToGo);
4077}
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.
Definition PPDirectives.cpp:1597
static bool isConfigurationPattern(Token &MacroName, MacroInfo *MI, const LangOptions &LOptions)
Definition PPDirectives.cpp:2909
static void diagnoseAutoModuleImport(Preprocessor &PP, SourceLocation HashLoc, Token &IncludeTok, ArrayRef< IdentifierLoc > Path, SourceLocation PathEnd)
Produce a diagnostic informing the user that a include or similar was implicitly treated as a module ...
Definition PPDirectives.cpp:1940
static std::optional< StringRef > findSimilarStr(StringRef LHS, const std::vector< StringRef > &Candidates)
Find a similar string in Candidates.
Definition PPDirectives.cpp:323
static bool isLanguageDefinedBuiltin(const SourceManager &SourceMgr, const MacroInfo *MI, const StringRef MacroName)
Definition PPDirectives.cpp:154
static bool trySimplifyPath(SmallVectorImpl< StringRef > &Components, StringRef RealPathName, llvm::sys::path::Style Separator)
Definition PPDirectives.cpp:1980
static bool warnByDefaultOnWrongCase(StringRef Include)
Definition PPDirectives.cpp:223
MacroDiag
Enumerates possible cases of define/undef a reserved identifier.
Definition PPDirectives.cpp:99
@ MD_ReservedMacro
Definition PPDirectives.cpp:102
@ MD_ReservedAttributeIdentifier
Definition PPDirectives.cpp:103
@ MD_NoWarn
Definition PPDirectives.cpp:100
@ MD_KeywordDef
Definition PPDirectives.cpp:101
static bool isFeatureTestMacro(StringRef MacroName)
Definition PPDirectives.cpp:114
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...
Definition PPDirectives.cpp:1460
PPElifDiag
Enumerates possible select values for the pp_err_elif_after_else and pp_err_elif_without_if diagnosti...
Definition PPDirectives.cpp:108
@ PED_Elifndef
Definition PPDirectives.cpp:111
@ PED_Elifdef
Definition PPDirectives.cpp:110
@ PED_Elif
Definition PPDirectives.cpp:109
static bool isReservedCXXAttributeName(Preprocessor &PP, IdentifierInfo *II)
Definition PPDirectives.cpp:178
static MacroDiag shouldWarnOnMacroUndef(Preprocessor &PP, IdentifierInfo *II)
Definition PPDirectives.cpp:208
static bool isObjCProtectedMacro(const IdentifierInfo *II)
Definition PPDirectives.cpp:3190
static MacroDiag shouldWarnOnMacroDef(Preprocessor &PP, IdentifierInfo *II)
Definition PPDirectives.cpp:194
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.
VerifyDiagnosticConsumer::Directive Directive
__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)
__device__ __2f16 float c
Definition PPDirectives.cpp:1194
ResetMacroExpansionHelper(Preprocessor *pp)
Definition PPDirectives.cpp:1196
~ResetMacroExpansionHelper()
Definition PPDirectives.cpp:1202
static AttrArgsInfo getCXX11AttrArgsInfo(const IdentifierInfo *Name)
Represents a character-granular source range.
static CharSourceRange getCharRange(SourceRange R)
virtual void CodeCompleteMacroName(bool IsDefinition)
Callback invoked when performing code completion in a context where the name of a macro is expected.
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.
A reference to a DirectoryEntry that includes the name of the directory as it was accessed by the Fil...
StringRef getName() const
bool isDeviceFile() const
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).
llvm::Expected< FileEntryRef > getFileRef(StringRef Filename, bool OpenFile=false, bool CacheFailure=true, bool IsText=true)
Lookup, cache, and verify the specified file (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.
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.
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...
@ 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.
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.
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 )
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.
Definition PPDirectives.cpp:1121
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.
Definition PPDirectives.cpp:1217
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 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.
Definition PPDirectives.cpp:459
friend class VAOptDefinitionContext
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)
Definition PPDirectives.cpp:359
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.
Definition PPDirectives.cpp:2019
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...
bool isNextPPTokenOneOf(Ts... Ks)
Check whether the next pp-token is one of the specificed token kind.
Module * getCurrentModule()
Retrieves the module that we're currently building, if any.
void makeModuleVisible(Module *M, SourceLocation Loc, bool IncludeExports=true)
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.
Definition PPDirectives.cpp:62
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.
Definition PPDirectives.cpp:1876
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.
Definition PPDirectives.cpp:1242
void EnterAnnotationToken(SourceRange Range, tok::TokenKind Kind, void *AnnotationVal)
Enter an annotation token into the token stream.
Definition PPDirectives.cpp:1924
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.
Definition PPDirectives.cpp:995
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 ...
Definition PPDirectives.cpp:925
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.
Definition PPDirectives.cpp:3660
Module * getModuleForLocation(SourceLocation Loc, bool AllowTextual)
Find the module that owns the source or header file that Loc points to.
Definition PPDirectives.cpp:903
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) const
Forwarding function for diagnostics.
bool usingPCHWithThroughHeader()
True if using a PCH with a through header.
Preprocessor(const PreprocessorOptions &PPOpts, DiagnosticsEngine &diags, const LangOptions &LangOpts, SourceManager &SM, HeaderSearch &Headers, ModuleLoader &TheModuleLoader, IdentifierInfoLookup *IILookup=nullptr, bool OwnsHeaderSearch=false, TranslationUnitKind TUKind=TU_Complete)
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.
This class handles loading and caching of source files into memory.
bool isInMainFile(SourceLocation Loc) const
Returns whether the PresumedLoc for a given SourceLocation is in the main file.
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
void setEnd(SourceLocation e)
Exposes information about the current target.
Token - This structure provides full information about a lexed token.
IdentifierInfo * getIdentifierInfo() const
SourceLocation getEndLoc() const
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 isOneOf(Ts... Ks) const
bool hasLeadingSpace() const
Return true if this token has whitespace before it.
bool isNot(tok::TokenKind K) const
bool hasUDSuffix() const
Return true if this token is a string or character literal which has a ud-suffix.
bool needsCleaning() const
Return true if this token has trigraphs or escaped newlines in it.
StringRef getRawIdentifier() const
getRawIdentifier - For a raw identifier token (i.e., an identifier lexed in raw mode),...
A directive for an undefined macro.
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.
CustomizableOptional< FileEntryRef > OptionalFileEntryRef
bool isReservedInAllContexts(ReservedIdentifierStatus Status)
Determine whether an identifier is reserved in all contexts.
int hasAttribute(AttributeCommonInfo::Syntax Syntax, llvm::StringRef ScopeName, llvm::StringRef AttrName, const TargetInfo &Target, const LangOptions &LangOpts, bool CheckPlugins)
Return the version number associated with the attribute if we recognize and implement the attribute s...
LLVM_READONLY char toLowercase(char c)
Converts the given ASCII character to its lowercase equivalent.
detail::SearchDirIteratorImpl< true > ConstSearchDirIterator
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
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].
@ Module
Module linkage, which indicates that the entity can be referred to from other translation units withi...
@ 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.
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
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.