36#include "llvm/ADT/ArrayRef.h"
37#include "llvm/ADT/DenseMap.h"
38#include "llvm/ADT/DenseSet.h"
39#include "llvm/ADT/FoldingSet.h"
40#include "llvm/ADT/STLExtras.h"
41#include "llvm/ADT/SmallString.h"
42#include "llvm/ADT/SmallVector.h"
43#include "llvm/ADT/StringRef.h"
44#include "llvm/ADT/StringSwitch.h"
45#include "llvm/Support/Casting.h"
46#include "llvm/Support/ErrorHandling.h"
47#include "llvm/Support/Format.h"
48#include "llvm/Support/Path.h"
49#include "llvm/Support/raw_ostream.h"
66 auto Pos = CurSubmoduleState->Macros.find(II);
67 return Pos == CurSubmoduleState->Macros.end() ? nullptr
68 : Pos->second.getLatest();
72 assert(MD &&
"MacroDirective should be non-zero!");
73 assert(!MD->
getPrevious() &&
"Already attached to a MacroDirective history.");
75 MacroState &StoredMD = CurSubmoduleState->Macros[II];
76 auto *OldMD = StoredMD.getLatest();
78 StoredMD.setLatest(MD);
79 StoredMD.overrideActiveModuleMacros(*
this, II);
81 if (needModuleMacros()) {
85 PendingModuleMacroNames.push_back(II);
90 if (!MD->
isDefined() && !LeafModuleMacros.contains(II))
109 MacroState &StoredMD = CurSubmoduleState->Macros[II];
111 if (
auto *OldMD = StoredMD.getLatest()) {
117 assert(OldMD->getMacroInfo()->isBuiltinMacro() &&
118 "only built-ins should have an entry here");
119 assert(!OldMD->getPrevious() &&
"builtin should only have a single entry");
121 StoredMD.setLatest(MD);
128 if (!MD->
isDefined() && !LeafModuleMacros.contains(II))
136 llvm::FoldingSetNodeID ID;
140 if (
auto *MM = ModuleMacros.FindNodeOrInsertPos(ID, InsertPos)) {
146 ModuleMacros.InsertNode(MM, InsertPos);
150 for (
auto *O : Overrides) {
151 HidAny |= (O->NumOverriddenBy == 0);
152 ++O->NumOverriddenBy;
156 auto &LeafMacros = LeafModuleMacros[II];
158 llvm::erase_if(LeafMacros,
159 [](
ModuleMacro *MM) {
return MM->NumOverriddenBy != 0; });
163 LeafMacros.push_back(MM);
173 llvm::FoldingSetNodeID ID;
177 return ModuleMacros.FindNodeOrInsertPos(ID, InsertPos);
181 ModuleMacroInfo &Info) {
182 assert(Info.ActiveModuleMacrosGeneration !=
183 CurSubmoduleState->VisibleModules.getGeneration() &&
184 "don't need to update this macro name info");
185 Info.ActiveModuleMacrosGeneration =
186 CurSubmoduleState->VisibleModules.getGeneration();
188 auto Leaf = LeafModuleMacros.find(II);
189 if (Leaf == LeafModuleMacros.end()) {
194 Info.ActiveModuleMacros.clear();
197 llvm::DenseMap<ModuleMacro *, int> NumHiddenOverrides;
198 for (
auto *O : Info.OverriddenMacros)
199 NumHiddenOverrides[O] = -1;
203 for (
auto *LeafMM : Leaf->second) {
204 assert(LeafMM->getNumOverridingMacros() == 0 &&
"leaf macro overridden");
205 if (NumHiddenOverrides.lookup(LeafMM) == 0)
206 Worklist.push_back(LeafMM);
208 while (!Worklist.empty()) {
209 auto *MM = Worklist.pop_back_val();
210 if (CurSubmoduleState->VisibleModules.isVisible(MM->getOwningModule())) {
213 if (MM->getMacroInfo())
214 Info.ActiveModuleMacros.push_back(MM);
216 for (
auto *O : MM->overrides())
217 if ((
unsigned)++NumHiddenOverrides[O] == O->getNumOverridingMacros())
218 Worklist.push_back(O);
222 std::reverse(Info.ActiveModuleMacros.begin(), Info.ActiveModuleMacros.end());
226 bool IsSystemMacro =
true;
227 bool IsAmbiguous =
false;
228 if (
auto *MD = Info.MD) {
229 while (MD && isa<VisibilityMacroDirective>(MD))
230 MD = MD->getPrevious();
231 if (
auto *DMD = dyn_cast_or_null<DefMacroDirective>(MD)) {
236 for (
auto *Active : Info.ActiveModuleMacros) {
237 auto *NewMI = Active->getMacroInfo();
248 if (MI && NewMI != MI &&
251 IsSystemMacro &= Active->getOwningModule()->IsSystem ||
255 Info.IsAmbiguous = IsAmbiguous && !IsSystemMacro;
260 auto LeafIt = LeafModuleMacros.find(II);
261 if (LeafIt != LeafModuleMacros.end())
262 Leaf = LeafIt->second;
263 const MacroState *State =
nullptr;
264 auto Pos = CurSubmoduleState->Macros.find(II);
265 if (Pos != CurSubmoduleState->Macros.end())
266 State = &Pos->second;
268 llvm::errs() <<
"MacroState " << State <<
" " << II->
getNameStart();
269 if (State && State->isAmbiguous(*
this, II))
270 llvm::errs() <<
" ambiguous";
271 if (State && !State->getOverriddenMacros().empty()) {
272 llvm::errs() <<
" overrides";
273 for (
auto *O : State->getOverriddenMacros())
274 llvm::errs() <<
" " << O->getOwningModule()->getFullModuleName();
276 llvm::errs() <<
"\n";
279 for (
auto *MD = State ? State->getLatest() :
nullptr; MD;
280 MD = MD->getPrevious()) {
288 State ? State->getActiveModuleMacros(*
this, II) : std::nullopt)
292 while (!Worklist.empty()) {
293 auto *MM = Worklist.pop_back_val();
294 llvm::errs() <<
" ModuleMacro " << MM <<
" "
295 << MM->getOwningModule()->getFullModuleName();
296 if (!MM->getMacroInfo())
297 llvm::errs() <<
" undef";
299 if (Active.count(MM))
300 llvm::errs() <<
" active";
301 else if (!CurSubmoduleState->VisibleModules.isVisible(
302 MM->getOwningModule()))
303 llvm::errs() <<
" hidden";
304 else if (MM->getMacroInfo())
305 llvm::errs() <<
" overridden";
307 if (!MM->overrides().empty()) {
308 llvm::errs() <<
" overrides";
309 for (
auto *O : MM->overrides()) {
310 llvm::errs() <<
" " << O->getOwningModule()->getFullModuleName();
312 Worklist.push_back(O);
315 llvm::errs() <<
"\n";
316 if (
auto *MI = MM->getMacroInfo()) {
319 llvm::errs() <<
"\n";
339void Preprocessor::RegisterBuiltinMacros() {
350 Ident__has_cpp_attribute =
353 Ident__has_cpp_attribute =
nullptr;
365 Ident__identifier =
nullptr;
366 Ident__pragma =
nullptr;
374 Ident__has_constexpr_builtin =
380 Ident__has_c_attribute =
nullptr;
390 Ident__is_target_environment =
392 Ident__is_target_variant_os =
394 Ident__is_target_variant_environment =
402 Ident__MODULE__ =
nullptr;
413 if (!II)
return true;
423 if (ExpansionMI->isEnabled() &&
434 return !llvm::is_contained(MI->
params(), II);
440bool Preprocessor::isNextPPTokenLParen() {
444 Val = CurLexer->isNextPPTokenLParen();
446 Val = CurTokenLexer->isNextTokenLParen();
454 for (
const IncludeStackInfo &Entry : llvm::reverse(IncludeMacroStack)) {
456 Val = Entry.TheLexer->isNextPPTokenLParen();
458 Val = Entry.TheTokenLexer->isNextTokenLParen();
464 if (Entry.ThePPLexer)
514 Args = ReadMacroCallArgumentList(
Identifier, MI, ExpansionEnd);
521 if (!Args)
return true;
523 ++NumFnMacroExpanded;
533 SourceRange ExpansionRange(ExpandLoc, ExpansionEnd);
541 DelayedMacroExpandsCallbacks.push_back(
542 MacroExpandsInfo(
Identifier, M, ExpansionRange));
544 Callbacks->MacroExpands(
Identifier, M, ExpansionRange, Args);
545 if (!DelayedMacroExpandsCallbacks.empty()) {
546 for (
const MacroExpandsInfo &Info : DelayedMacroExpandsCallbacks) {
548 Callbacks->MacroExpands(Info.Tok, Info.MD, Info.Range,
551 DelayedMacroExpandsCallbacks.clear();
575 if (Args) Args->
destroy(*
this);
580 PropagateLineStartLeadingSpaceInfo(
Identifier);
581 ++NumFastMacroExpanded;
591 if (Args) Args->
destroy(*
this);
595 bool isAtStartOfLine =
Identifier.isAtStartOfLine();
596 bool hasLeadingSpace =
Identifier.hasLeadingSpace();
616 if (!NewMI->isEnabled() || NewMI == MI) {
627 ++NumFastMacroExpanded;
648 if (I->is(tok::l_paren)) {
649 Brackets.push_back(
Paren);
650 }
else if (I->is(tok::r_paren)) {
651 if (Brackets.empty() || Brackets.back() ==
Brace)
654 }
else if (I->is(tok::l_brace)) {
655 Brackets.push_back(
Brace);
656 }
else if (I->is(tok::r_brace)) {
657 if (Brackets.empty() || Brackets.back() ==
Paren)
662 return Brackets.empty();
696 bool FoundSeparatorToken =
false;
700 if (I->is(tok::l_brace)) {
702 }
else if (I->is(tok::r_brace)) {
704 if (
Braces == 0 && ClosingBrace == E && FoundSeparatorToken)
706 }
else if (I->is(tok::eof)) {
711 FoundSeparatorToken =
true;
712 I->setKind(tok::comma);
720 if (FoundSeparatorToken && ArgStartIterator->is(tok::l_brace)) {
728 if (FoundSeparatorToken) {
730 TempToken.
setKind(tok::l_paren);
731 TempToken.
setLocation(ArgStartIterator->getLocation());
733 NewTokens.push_back(TempToken);
737 NewTokens.insert(NewTokens.end(), ArgStartIterator, I);
740 if (FoundSeparatorToken) {
743 TempToken.
setKind(tok::r_paren);
746 NewTokens.push_back(TempToken);
747 ParenHints.push_back(
SourceRange(ArgStartIterator->getLocation(),
752 NewTokens.push_back(*I);
755 ArgStartIterator = I + 1;
756 FoundSeparatorToken =
false;
761 return !ParenHints.empty() && InitLists.empty();
768MacroArgs *Preprocessor::ReadMacroCallArgumentList(
Token &MacroName,
781 assert(Tok.
is(tok::l_paren) &&
"Error computing l-paren-ness?");
787 bool ContainsCodeCompletionTok =
false;
788 bool FoundElidedComma =
false;
792 unsigned NumActuals = 0;
793 while (Tok.
isNot(tok::r_paren)) {
794 if (ContainsCodeCompletionTok && Tok.
isOneOf(tok::eof, tok::eod))
797 assert(Tok.
isOneOf(tok::l_paren, tok::comma) &&
798 "only expect argument separators here");
800 size_t ArgTokenStart = ArgTokens.size();
805 unsigned NumParens = 0;
812 if (Tok.
isOneOf(tok::eof, tok::eod)) {
813 if (!ContainsCodeCompletionTok) {
814 Diag(MacroName, diag::err_unterm_macro_invoc);
822 auto Toks = std::make_unique<Token[]>(1);
824 EnterTokenStream(std::move(Toks), 1,
true,
false);
826 }
else if (Tok.
is(tok::r_paren)) {
828 if (NumParens-- == 0) {
830 if (!ArgTokens.empty() &&
831 ArgTokens.back().commaAfterElided()) {
832 FoundElidedComma =
true;
836 }
else if (Tok.
is(tok::l_paren)) {
838 }
else if (Tok.
is(tok::comma)) {
849 }
else if (NumParens == 0) {
855 if (NumFixedArgsLeft > 1)
858 }
else if (Tok.
is(tok::comment) && !KeepMacroComments) {
872 }
else if (Tok.
is(tok::code_completion)) {
873 ContainsCodeCompletionTok =
true;
882 ArgTokens.push_back(Tok);
887 if (ArgTokens.empty() && Tok.
getKind() == tok::r_paren)
892 if (!isVariadic && NumFixedArgsLeft == 0 && TooManyArgsLoc.
isInvalid()) {
893 if (ArgTokens.size() != ArgTokenStart)
894 TooManyArgsLoc = ArgTokens[ArgTokenStart].getLocation();
896 TooManyArgsLoc = ArgStartLoc;
903 ? diag::warn_cxx98_compat_empty_fnmacro_arg
904 : diag::ext_empty_fnmacro_arg);
912 ArgTokens.push_back(EOFTok);
914 if (!ContainsCodeCompletionTok && NumFixedArgsLeft != 0)
924 if (!isVariadic && NumActuals > MinArgsExpected &&
925 !ContainsCodeCompletionTok) {
928 Diag(TooManyArgsLoc, diag::err_too_many_args_in_macro_invoc);
938 unsigned FixedNumArgs = 0;
941 ParenHints, InitLists)) {
942 if (!InitLists.empty()) {
945 diag::note_init_list_at_beginning_of_macro_argument);
951 if (FixedNumArgs != MinArgsExpected)
959 ArgTokens.swap(FixedArgTokens);
960 NumActuals = FixedNumArgs;
964 bool isVarargsElided =
false;
966 if (ContainsCodeCompletionTok) {
973 for (; NumActuals < MinArgsExpected; ++NumActuals)
974 ArgTokens.push_back(EOFTok);
977 if (NumActuals < MinArgsExpected) {
979 if (NumActuals == 0 && MinArgsExpected == 1) {
986 }
else if ((FoundElidedComma || MI->
isVariadic()) &&
987 (NumActuals+1 == MinArgsExpected ||
988 (NumActuals == 0 && MinArgsExpected == 2))) {
1002 ID = diag::warn_cxx17_compat_missing_varargs_arg;
1004 ID = diag::ext_cxx_missing_varargs_arg;
1006 ID = diag::warn_c17_compat_missing_varargs_arg;
1008 ID = diag::ext_c_missing_varargs_arg;
1020 isVarargsElided =
true;
1021 }
else if (!ContainsCodeCompletionTok) {
1023 Diag(Tok, diag::err_too_few_args_in_macro_invoc);
1035 ArgTokens.push_back(Tok);
1038 if (NumActuals == 0 && MinArgsExpected == 2)
1039 ArgTokens.push_back(Tok);
1041 }
else if (NumActuals > MinArgsExpected && !MI->
isVariadic() &&
1042 !ContainsCodeCompletionTok) {
1045 Diag(MacroName, diag::err_too_many_args_in_macro_invoc);
1065 size_t newIndex = MacroExpandedTokens.size();
1066 bool cacheNeedsToGrow = tokens.size() >
1067 MacroExpandedTokens.capacity()-MacroExpandedTokens.size();
1068 MacroExpandedTokens.append(tokens.begin(), tokens.end());
1070 if (cacheNeedsToGrow) {
1073 for (
const auto &
Lexer : MacroExpandingLexersStack) {
1076 std::tie(prevLexer, tokIndex) =
Lexer;
1077 prevLexer->Tokens = MacroExpandedTokens.data() + tokIndex;
1081 MacroExpandingLexersStack.push_back(std::make_pair(tokLexer, newIndex));
1082 return MacroExpandedTokens.data() + newIndex;
1085void Preprocessor::removeCachedMacroExpandedTokensOfLastLexer() {
1086 assert(!MacroExpandingLexersStack.empty());
1087 size_t tokIndex = MacroExpandingLexersStack.back().second;
1088 assert(tokIndex < MacroExpandedTokens.size());
1090 MacroExpandedTokens.resize(tokIndex);
1091 MacroExpandingLexersStack.pop_back();
1103 TM = std::gmtime(&TT);
1105 TT = std::time(
nullptr);
1106 TM = std::localtime(&TT);
1109 static const char *
const Months[] = {
1110 "Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"
1115 llvm::raw_svector_ostream TmpStream(TmpBuffer);
1117 TmpStream << llvm::format(
"\"%s %2d %4d\"", Months[TM->tm_mon],
1118 TM->tm_mday, TM->tm_year + 1900);
1120 TmpStream <<
"??? ?? ????";
1129 llvm::raw_svector_ostream TmpStream(TmpBuffer);
1131 TmpStream << llvm::format(
"\"%02d:%02d:%02d\"", TM->tm_hour, TM->tm_min,
1134 TmpStream <<
"??:??:??";
1148 if (Feature.starts_with(
"__") && Feature.ends_with(
"__") &&
1149 Feature.size() >= 4)
1150 Feature = Feature.substr(2, Feature.size() - 4);
1152#define FEATURE(Name, Predicate) .Case(#Name, Predicate)
1153 return llvm::StringSwitch<bool>(Feature)
1154#include "clang/Basic/Features.def"
1175 if (Extension.starts_with(
"__") && Extension.ends_with(
"__") &&
1176 Extension.size() >= 4)
1177 Extension = Extension.substr(2, Extension.size() - 4);
1181#define EXTENSION(Name, Predicate) .Case(#Name, Predicate)
1182 return llvm::StringSwitch<bool>(Extension)
1183#include "clang/Basic/Features.def"
1201 PP.
Diag(LParenLoc, diag::err_pp_directive_required) << II;
1203 assert(Tok.
is(tok::identifier));
1212 }
while (Tok.
getKind() == tok::comment);
1215 if (Tok.
isNot(tok::l_paren)) {
1218 PP.
Diag(LParenLoc, diag::err_pp_expected_after) << II << tok::l_paren;
1221 if (Tok.
isNot(tok::header_name))
1230 if (Tok.
isNot(tok::header_name)) {
1248 if (Tok.
isNot(tok::r_paren)) {
1250 << II << tok::r_paren;
1251 PP.
Diag(LParenLoc, diag::note_matching) << tok::l_paren;
1269 nullptr,
nullptr,
nullptr, &KH,
nullptr,
nullptr);
1279 return File.has_value();
1289 std::tie(Lookup, LookupFromFile) = getIncludeNextStart(Tok);
1301 bool &HasLexedNextTok)> Op) {
1304 if (Tok.
isNot(tok::l_paren)) {
1309 if (!Tok.
isOneOf(tok::eof, tok::eod)) {
1311 Tok.
setKind(tok::numeric_constant);
1316 unsigned ParenDepth = 1;
1318 std::optional<int>
Result;
1321 bool SuppressDiagnostic =
false;
1339 if (!SuppressDiagnostic) {
1341 SuppressDiagnostic =
true;
1349 if (!SuppressDiagnostic) {
1351 SuppressDiagnostic =
true;
1356 if (--ParenDepth > 0)
1369 if (!SuppressDiagnostic)
1372 Tok.
setKind(tok::numeric_constant);
1380 bool HasLexedNextToken =
false;
1381 Result = Op(Tok, HasLexedNextToken);
1383 if (HasLexedNextToken)
1390 if (!SuppressDiagnostic) {
1398 PP.
Diag(LParenLoc, diag::note_matching) << tok::l_paren;
1399 SuppressDiagnostic =
true;
1419 std::string ArchName = II->
getName().lower() +
"--";
1420 llvm::Triple Arch(ArchName);
1421 const llvm::Triple &TT = TI.
getTriple();
1424 if ((Arch.getSubArch() == llvm::Triple::NoSubArch ||
1425 Arch.getSubArch() == TT.getSubArch()) &&
1426 ((TT.getArch() == llvm::Triple::thumb &&
1427 Arch.getArch() == llvm::Triple::arm) ||
1428 (TT.getArch() == llvm::Triple::thumbeb &&
1429 Arch.getArch() == llvm::Triple::armeb)))
1434 return (Arch.getSubArch() == llvm::Triple::NoSubArch ||
1435 Arch.getSubArch() == TT.getSubArch()) &&
1436 Arch.getArch() == TT.getArch();
1441 StringRef VendorName = TI.
getTriple().getVendorName();
1442 if (VendorName.empty())
1443 VendorName =
"unknown";
1444 return VendorName.equals_insensitive(II->
getName());
1449 std::string OSName =
1450 (llvm::Twine(
"unknown-unknown-") + II->
getName().lower()).str();
1451 llvm::Triple OS(OSName);
1452 if (OS.getOS() == llvm::Triple::Darwin) {
1456 return TI.
getTriple().getOS() == OS.getOS();
1462 std::string EnvName = (llvm::Twine(
"---") + II->
getName().lower()).str();
1463 llvm::Triple
Env(EnvName);
1466 if (
Env.getEnvironment() == llvm::Triple::UnknownEnvironment &&
1467 EnvName !=
"---unknown")
1469 return TI.
getTriple().getEnvironment() ==
Env.getEnvironment();
1479 std::string OSName =
1480 (llvm::Twine(
"unknown-unknown-") + II->
getName().lower()).str();
1481 llvm::Triple OS(OSName);
1482 if (OS.getOS() == llvm::Triple::Darwin) {
1484 return VariantTriple->isOSDarwin();
1486 return VariantTriple->getOS() == OS.getOS();
1498 std::string EnvName = (llvm::Twine(
"---") + II->
getName().lower()).str();
1499 llvm::Triple
Env(EnvName);
1500 return VariantTriple->getEnvironment() ==
Env.getEnvironment();
1507void Preprocessor::ExpandBuiltinMacro(
Token &Tok) {
1510 assert(II &&
"Can't be a macro without id info!");
1514 if (II == Ident_Pragma)
1515 return Handle_Pragma(Tok);
1516 else if (II == Ident__pragma)
1517 return HandleMicrosoft__pragma(Tok);
1519 ++NumBuiltinMacroExpanded;
1522 llvm::raw_svector_ostream OS(TmpBuffer);
1530 if (II == Ident__LINE__) {
1550 Tok.
setKind(tok::numeric_constant);
1551 }
else if (II == Ident__FILE__ || II == Ident__BASE_FILE__ ||
1552 II == Ident__FILE_NAME__) {
1559 if (II == Ident__BASE_FILE__ && PLoc.
isValid()) {
1575 if (II == Ident__FILE_NAME__) {
1582 OS <<
'"' << FN <<
'"';
1584 Tok.
setKind(tok::string_literal);
1585 }
else if (II == Ident__DATE__) {
1589 Tok.
setKind(tok::string_literal);
1590 Tok.
setLength(strlen(
"\"Mmm dd yyyy\""));
1595 }
else if (II == Ident__TIME__) {
1599 Tok.
setKind(tok::string_literal);
1605 }
else if (II == Ident__INCLUDE_LEVEL__) {
1613 for (; PLoc.
isValid(); ++Depth)
1619 Tok.
setKind(tok::numeric_constant);
1620 }
else if (II == Ident__TIMESTAMP__) {
1627 std::tm *TM = std::gmtime(&TT);
1637 struct tm *TM = localtime(&TT);
1640 Result =
"??? ??? ?? ??:??:?? ????\n";
1644 OS <<
'"' << StringRef(
Result).drop_back() <<
'"';
1645 Tok.
setKind(tok::string_literal);
1646 }
else if (II == Ident__FLT_EVAL_METHOD__) {
1650 Tok.
setKind(tok::numeric_constant);
1654 Diag(Tok, diag::err_illegal_use_of_flt_eval_macro);
1657 }
else if (II == Ident__COUNTER__) {
1659 OS << CounterValue++;
1660 Tok.
setKind(tok::numeric_constant);
1661 }
else if (II == Ident__has_feature) {
1663 [
this](
Token &Tok,
bool &HasLexedNextToken) ->
int {
1665 diag::err_feature_check_malformed);
1668 }
else if (II == Ident__has_extension) {
1670 [
this](
Token &Tok,
bool &HasLexedNextToken) ->
int {
1672 diag::err_feature_check_malformed);
1675 }
else if (II == Ident__has_builtin) {
1677 [
this](
Token &Tok,
bool &HasLexedNextToken) ->
int {
1679 diag::err_feature_check_malformed);
1684 case Builtin::BI__builtin_cpu_is:
1686 case Builtin::BI__builtin_cpu_init:
1688 case Builtin::BI__builtin_cpu_supports:
1690 case Builtin::BI__builtin_operator_new:
1691 case Builtin::BI__builtin_operator_delete:
1701 }
else if (II->
getTokenID() != tok::identifier ||
1710 if (II->
getName().starts_with(
"__builtin_") ||
1711 II->
getName().starts_with(
"__is_") ||
1712 II->
getName().starts_with(
"__has_"))
1714 return llvm::StringSwitch<bool>(II->
getName())
1715 .Case(
"__array_rank",
true)
1716 .Case(
"__array_extent",
true)
1717 .Case(
"__reference_binds_to_temporary",
true)
1718 .Case(
"__reference_constructs_from_temporary",
true)
1719#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) .Case("__" #Trait, true)
1720#include "clang/Basic/TransformTypeTraits.def"
1723 return llvm::StringSwitch<bool>(II->
getName())
1730 .Case(
"__is_target_arch",
true)
1731 .Case(
"__is_target_vendor",
true)
1732 .Case(
"__is_target_os",
true)
1733 .Case(
"__is_target_environment",
true)
1734 .Case(
"__is_target_variant_os",
true)
1735 .Case(
"__is_target_variant_environment",
true)
1739 }
else if (II == Ident__has_constexpr_builtin) {
1741 OS, Tok, II, *
this,
false,
1742 [
this](
Token &Tok,
bool &HasLexedNextToken) ->
int {
1744 Tok, *
this, diag::err_feature_check_malformed);
1748 return BuiltinOp != 0 &&
1751 }
else if (II == Ident__is_identifier) {
1753 [](
Token &Tok,
bool &HasLexedNextToken) ->
int {
1754 return Tok.
is(tok::identifier);
1756 }
else if (II == Ident__has_attribute) {
1758 [
this](
Token &Tok,
bool &HasLexedNextToken) ->
int {
1760 diag::err_feature_check_malformed);
1765 }
else if (II == Ident__has_declspec) {
1767 [
this](
Token &Tok,
bool &HasLexedNextToken) ->
int {
1769 diag::err_feature_check_malformed);
1772 return LangOpts.DeclSpecKeyword &&
1779 }
else if (II == Ident__has_cpp_attribute ||
1780 II == Ident__has_c_attribute) {
1781 bool IsCXX = II == Ident__has_cpp_attribute;
1783 [&](
Token &Tok,
bool &HasLexedNextToken) ->
int {
1786 Tok, *
this, diag::err_feature_check_malformed);
1793 if (Tok.
isNot(tok::coloncolon))
1794 HasLexedNextToken =
true;
1800 diag::err_feature_check_malformed);
1810 }
else if (II == Ident__has_include ||
1811 II == Ident__has_include_next) {
1816 if (II == Ident__has_include)
1817 Value = EvaluateHasInclude(Tok, II);
1819 Value = EvaluateHasIncludeNext(Tok, II);
1821 if (Tok.
isNot(tok::r_paren))
1824 Tok.
setKind(tok::numeric_constant);
1825 }
else if (II == Ident__has_warning) {
1828 [
this](
Token &Tok,
bool &HasLexedNextToken) ->
int {
1829 std::string WarningName;
1832 HasLexedNextToken = Tok.
is(tok::string_literal);
1839 if (WarningName.size() < 3 || WarningName[0] !=
'-' ||
1840 WarningName[1] !=
'W') {
1841 Diag(StrStartLoc, diag::warn_has_warning_invalid_option);
1852 WarningName.substr(2), Diags);
1854 }
else if (II == Ident__building_module) {
1859 [
this](
Token &Tok,
bool &HasLexedNextToken) ->
int {
1861 diag::err_expected_id_building_module);
1865 }
else if (II == Ident__MODULE__) {
1871 }
else if (II == Ident__identifier) {
1877 if (Tok.
isNot(tok::l_paren)) {
1880 << II << tok::l_paren;
1892 else if (Tok.
is(tok::string_literal) && !Tok.
hasUDSuffix()) {
1911 if (RParen.
isNot(tok::r_paren)) {
1913 << Tok.
getKind() << tok::r_paren;
1914 Diag(LParenLoc, diag::note_matching) << tok::l_paren;
1917 }
else if (II == Ident__is_target_arch) {
1919 OS, Tok, II, *
this,
false,
1920 [
this](
Token &Tok,
bool &HasLexedNextToken) ->
int {
1922 Tok, *
this, diag::err_feature_check_malformed);
1925 }
else if (II == Ident__is_target_vendor) {
1927 OS, Tok, II, *
this,
false,
1928 [
this](
Token &Tok,
bool &HasLexedNextToken) ->
int {
1930 Tok, *
this, diag::err_feature_check_malformed);
1933 }
else if (II == Ident__is_target_os) {
1935 OS, Tok, II, *
this,
false,
1936 [
this](
Token &Tok,
bool &HasLexedNextToken) ->
int {
1938 Tok, *
this, diag::err_feature_check_malformed);
1941 }
else if (II == Ident__is_target_environment) {
1943 OS, Tok, II, *
this,
false,
1944 [
this](
Token &Tok,
bool &HasLexedNextToken) ->
int {
1946 Tok, *
this, diag::err_feature_check_malformed);
1949 }
else if (II == Ident__is_target_variant_os) {
1951 OS, Tok, II, *
this,
false,
1952 [
this](
Token &Tok,
bool &HasLexedNextToken) ->
int {
1954 Tok, *
this, diag::err_feature_check_malformed);
1957 }
else if (II == Ident__is_target_variant_environment) {
1959 OS, Tok, II, *
this,
false,
1960 [
this](
Token &Tok,
bool &HasLexedNextToken) ->
int {
1962 Tok, *
this, diag::err_feature_check_malformed);
1966 llvm_unreachable(
"Unknown identifier!");
1987 llvm::sys::path::remove_dots(Path,
false,
1988 llvm::sys::path::Style::windows_backslash);
1990 llvm::sys::path::remove_dots(Path,
false, llvm::sys::path::Style::posix);
2000 StringRef PLFileName = llvm::sys::path::filename(PLoc.
getFilename());
2001 if (PLFileName.empty())
2003 FileName.append(PLFileName.begin(), PLFileName.end());
Defines enum values for all the target-independent builtin functions.
static bool getDiagnosticsInGroup(diag::Flavor Flavor, const WarningOption *Group, SmallVectorImpl< diag::kind > &Diags)
Return true if any diagnostics were found in this group, even if they were filtered out due to having...
Defines the clang::FileManager interface and associated types.
llvm::DenseSet< const void * > Visited
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
Defines the clang::LangOptions interface.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
llvm::MachO::FileType FileType
Defines the clang::MacroInfo and clang::MacroDirective classes.
Defines types useful for describing an Objective-C runtime.
static bool HasExtension(const Preprocessor &PP, StringRef Extension)
HasExtension - Return true if we recognize and implement the feature specified by the identifier,...
static bool CheckMatchedBrackets(const SmallVectorImpl< Token > &Tokens)
CheckMatchedBrackets - Returns true if the braces and parentheses in the token vector are properly ne...
static bool EvaluateHasIncludeCommon(Token &Tok, IdentifierInfo *II, Preprocessor &PP, ConstSearchDirIterator LookupFrom, const FileEntry *LookupFromFile)
EvaluateHasIncludeCommon - Process a '__has_include("path")' or '__has_include_next("path")' expressi...
static IdentifierInfo * RegisterBuiltinMacro(Preprocessor &PP, const char *Name)
RegisterBuiltinMacro - Register the specified identifier in the identifier table and mark it as a bui...
static bool GenerateNewArgTokens(Preprocessor &PP, SmallVectorImpl< Token > &OldTokens, SmallVectorImpl< Token > &NewTokens, unsigned &NumArgs, SmallVectorImpl< SourceRange > &ParenHints, SmallVectorImpl< SourceRange > &InitLists)
GenerateNewArgTokens - Returns true if OldTokens can be converted to a new vector of tokens in NewTok...
static bool isTargetVariantOS(const TargetInfo &TI, const IdentifierInfo *II)
Implements the __is_target_variant_os builtin macro.
static bool isTrivialSingleTokenExpansion(const MacroInfo *MI, const IdentifierInfo *MacroIdent, Preprocessor &PP)
isTrivialSingleTokenExpansion - Return true if MI, which has a single token in its expansion,...
static bool isTargetArch(const TargetInfo &TI, const IdentifierInfo *II)
Implements the __is_target_arch builtin macro.
static void ComputeDATE_TIME(SourceLocation &DATELoc, SourceLocation &TIMELoc, Preprocessor &PP)
ComputeDATE_TIME - Compute the current time, enter it into the specified scratch buffer,...
static bool isTargetVariantEnvironment(const TargetInfo &TI, const IdentifierInfo *II)
Implements the __is_target_variant_environment builtin macro.
static bool isTargetEnvironment(const TargetInfo &TI, const IdentifierInfo *II)
Implements the __is_target_environment builtin macro.
static bool isTargetOS(const TargetInfo &TI, const IdentifierInfo *II)
Implements the __is_target_os builtin macro.
static bool isTargetVendor(const TargetInfo &TI, const IdentifierInfo *II)
Implements the __is_target_vendor builtin macro.
static void EvaluateFeatureLikeBuiltinMacro(llvm::raw_svector_ostream &OS, Token &Tok, IdentifierInfo *II, Preprocessor &PP, bool ExpandArgs, llvm::function_ref< int(Token &Tok, bool &HasLexedNextTok)> Op)
Process single-argument builtin feature-like macros that return integer values.
static bool HasFeature(const Preprocessor &PP, StringRef Feature)
HasFeature - Return true if we recognize and implement the feature specified by the identifier as a s...
static IdentifierInfo * ExpectFeatureIdentifierInfo(Token &Tok, Preprocessor &PP, signed DiagID)
Helper function to return the IdentifierInfo structure of a Token or generate a diagnostic if none av...
Defines the PreprocessorLexer interface.
Defines the clang::Preprocessor interface.
Defines the clang::SourceLocation class and associated facilities.
Syntax
The style used to specify an attribute.
@ AS_Declspec
__declspec(...)
bool isConstantEvaluated(unsigned ID) const
Return true if this function can be constant evaluated by Clang frontend.
SourceLocation getEnd() const
virtual void CodeCompleteMacroArgument(IdentifierInfo *Macro, MacroInfo *MacroInfo, unsigned ArgumentIndex)
Callback invoked when performing code completion inside a function-like macro argument.
A little helper class used to produce diagnostics.
diag::Severity getExtensionHandlingBehavior() const
virtual void updateOutOfDateIdentifier(const IdentifierInfo &II)=0
Update an out-of-date identifier.
Cached information about one file (either on disk or in the virtual file system).
time_t getModificationTime() const
static FixItHint CreateInsertion(SourceLocation InsertionLoc, StringRef Code, bool BeforePreviousInsertions=false)
Create a code modification hint that inserts the given code string at a specific location.
One of these records is kept for each identifier that is lexed.
unsigned getBuiltinID() const
Return a value indicating whether this is a builtin function.
tok::TokenKind getTokenID() const
If this is a source-language token (e.g.
bool hadMacroDefinition() const
Returns true if this identifier was #defined to some value at any moment.
bool isFromAST() const
Return true if the identifier in its current state was loaded from an AST file.
bool hasRevertedTokenIDToIdentifier() const
True if revertTokenIDToIdentifier() was called.
const char * getNameStart() const
Return the beginning of the actual null-terminated string for this identifier.
void setHasMacroDefinition(bool Val)
bool isOutOfDate() const
Determine whether the information for this identifier is out of date with respect to the external sou...
void setChangedSinceDeserialization()
Note that this identifier has changed since it was loaded from an AST file.
StringRef getName() const
Return the actual identifier string.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
bool UseTargetPathSeparator
Indicates whether to use target's platform-specific file separator when FILE macro is used and when c...
void remapPathPrefix(SmallVectorImpl< char > &Path) const
Remap path prefix according to -fmacro-prefix-path option.
bool isCompilingModule() const
Are we compiling a module?
std::string CurrentModule
The name of the current module, of which the main source file is a part.
Lexer - This provides a simple interface that turns a text buffer into a stream of tokens.
static std::string Stringify(StringRef Str, bool Charify=false)
Stringify - Convert the specified string into a C string by i) escaping '\' and " characters and ii) ...
MacroArgs - An instance of this class captures information about the formal arguments specified to a ...
static MacroArgs * create(const MacroInfo *MI, ArrayRef< Token > UnexpArgTokens, bool VarargsElided, Preprocessor &PP)
MacroArgs ctor function - Create a new MacroArgs object with the specified macro and argument info.
void destroy(Preprocessor &PP)
destroy - Destroy and deallocate the memory for this object.
A description of the current definition of a macro.
MacroInfo * getMacroInfo() const
Get the MacroInfo that should be used for this definition.
bool isAmbiguous() const
true if the definition is ambiguous, false otherwise.
void forAllDefinitions(Fn F) const
Encapsulates changes to the "macros namespace" (the location where the macro name became active,...
const MacroDirective * getPrevious() const
Get previous definition of the macro with the same name.
void setPrevious(MacroDirective *Prev)
Set previous definition of the macro with the same name.
Encapsulates the data about a macro definition (e.g.
bool isIdenticalTo(const MacroInfo &Other, Preprocessor &PP, bool Syntactically) const
Return true if the specified macro definition is equal to this macro in spelling, arguments,...
bool isUsed() const
Return false if this macro is defined in the main file and has not yet been used.
bool isFunctionLike() const
ArrayRef< const IdentifierInfo * > params() const
unsigned getNumTokens() const
Return the number of tokens that this macro expands to.
unsigned getNumParams() const
const Token & getReplacementToken(unsigned Tok) const
bool isBuiltinMacro() const
Return true if this macro requires processing before expansion.
SourceLocation getDefinitionLoc() const
Return the location that the macro was defined at.
bool hasCommaPasting() const
bool isObjectLike() const
bool isWarnIfUnused() const
Return true if we should emit a warning if the macro is unused.
bool isEnabled() const
Return true if this macro is enabled.
void setIsUsed(bool Val)
Set the value of the IsUsed flag.
void setIsBuiltinMacro(bool Val=true)
Set or clear the isBuiltinMacro flag.
Represents a macro directive exported by a module.
static ModuleMacro * create(Preprocessor &PP, Module *OwningModule, const IdentifierInfo *II, MacroInfo *Macro, ArrayRef< ModuleMacro * > Overrides)
void Profile(llvm::FoldingSetNodeID &ID) const
Describes a module or submodule.
void ExpandedMacro()
ExpandedMacro - When a macro is expanded with this lexer as the current buffer, this method is called...
This interface provides a way to observe the actions of the preprocessor as it does its thing.
MultipleIncludeOpt MIOpt
A state machine that detects the #ifndef-wrapping a file idiom for the multiple-include optimization.
std::optional< uint64_t > SourceDateEpoch
If set, the UNIX timestamp specified by SOURCE_DATE_EPOCH.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
SourceLocation getLastFPEvalPragmaLocation() const
bool FinishLexStringLiteral(Token &Result, std::string &String, const char *DiagnosticTag, bool AllowMacroExpansion)
Complete the lexing of a string literal where the first token has already been lexed (see LexStringLi...
void dumpMacroInfo(const IdentifierInfo *II)
void setLoadedMacroDirective(IdentifierInfo *II, MacroDirective *ED, MacroDirective *MD)
Set a MacroDirective that was loaded from a PCH file.
PPCallbacks * getPPCallbacks() const
const MacroInfo * getMacroInfo(const IdentifierInfo *II) const
void CreateString(StringRef Str, Token &Tok, SourceLocation ExpansionLocStart=SourceLocation(), SourceLocation ExpansionLocEnd=SourceLocation())
Plop the specified string into a scratch buffer and set the specified token's location and length to ...
void markMacroAsUsed(MacroInfo *MI)
A macro is used, update information about macros that need unused warnings.
MacroDirective * getLocalMacroDirectiveHistory(const IdentifierInfo *II) const
Given an identifier, return the latest non-imported macro directive for that identifier.
void Lex(Token &Result)
Lex the next token for this preprocessor.
bool isParsingIfOrElifDirective() const
True if we are currently preprocessing a if or #elif directive.
void LexNonComment(Token &Result)
Lex a token.
ModuleMacro * addModuleMacro(Module *Mod, const IdentifierInfo *II, MacroInfo *Macro, ArrayRef< ModuleMacro * > Overrides, bool &IsNew)
Register an exported macro for a module and identifier.
IdentifierInfo * getIdentifierInfo(StringRef Name) const
Return information about the specified preprocessor identifier token.
SourceLocation AdvanceToTokenCharacter(SourceLocation TokStart, unsigned Char) const
Given a location that specifies the start of a token, return a new location that specifies a characte...
static void processPathToFileName(SmallVectorImpl< char > &FileName, const PresumedLoc &PLoc, const LangOptions &LangOpts, const TargetInfo &TI)
const TargetInfo & getTargetInfo() const
bool LexHeaderName(Token &Result, bool AllowMacroExpansion=true)
Lex a token, forming a header-name token if possible.
PreprocessorOptions & getPreprocessorOpts() const
Retrieve the preprocessor options used to initialize this preprocessor.
MacroInfo * AllocateMacroInfo(SourceLocation L)
Allocate a new MacroInfo object with the provided SourceLocation.
void LexUnexpandedToken(Token &Result)
Just like Lex, but disables macro expansion of identifier tokens.
ModuleMacro * getModuleMacro(Module *Mod, const IdentifierInfo *II)
StringRef getSpelling(SourceLocation loc, SmallVectorImpl< char > &buffer, bool *invalid=nullptr) const
Return the 'spelling' of the token at the given location; does not go up to the spelling location or ...
bool GetIncludeFilenameSpelling(SourceLocation Loc, StringRef &Buffer)
Turn the specified lexer token into a fully checked and spelled filename, e.g.
PreprocessorLexer * getCurrentFileLexer() const
Return the current file lexer being lexed from.
HeaderSearch & getHeaderSearchInfo() const
void emitMacroExpansionWarnings(const Token &Identifier, bool IsIfnDef=false) const
ExternalPreprocessorSource * getExternalSource() const
OptionalFileEntryRef LookupFile(SourceLocation FilenameLoc, StringRef Filename, bool isAngled, ConstSearchDirIterator FromDir, const FileEntry *FromFile, ConstSearchDirIterator *CurDir, SmallVectorImpl< char > *SearchPath, SmallVectorImpl< char > *RelativePath, ModuleMap::KnownHeader *SuggestedModule, bool *IsMapped, bool *IsFrameworkFound, bool SkipCache=false, bool OpenFile=true, bool CacheFailures=true)
Given a "foo" or <foo> reference, look up the indicated file.
Builtin::Context & getBuiltinInfo()
LangOptions::FPEvalMethodKind getTUFPEvalMethod() const
const LangOptions & getLangOpts() const
static void processPathForFileMacro(SmallVectorImpl< char > &Path, const LangOptions &LangOpts, const TargetInfo &TI)
DefMacroDirective * appendDefMacroDirective(IdentifierInfo *II, MacroInfo *MI, SourceLocation Loc)
DiagnosticsEngine & getDiagnostics() const
SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset=0)
Computes the source location just past the end of the token at this source location.
void EnterMacro(Token &Tok, SourceLocation ILEnd, MacroInfo *Macro, MacroArgs *Args)
Add a Macro to the top of the include stack and start lexing tokens from it instead of the current bu...
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) const
Forwarding function for diagnostics.
void appendMacroDirective(IdentifierInfo *II, MacroDirective *MD)
Add a directive to the macro directive history for this identifier.
Represents an unpacked "presumed" location which can be presented to the user.
const char * getFilename() const
Return the presumed filename of this location.
unsigned getLine() const
Return the presumed line number of this location.
bool isInvalid() const
Return true if this object is invalid or uninitialized.
SourceLocation getIncludeLoc() const
Return the presumed include location of this location.
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.
CharSourceRange getExpansionRange(SourceLocation Loc) const
Given a SourceLocation object, return the range of tokens covered by the expansion in the ultimate fi...
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
SourceLocation createExpansionLoc(SourceLocation SpellingLoc, SourceLocation ExpansionLocStart, SourceLocation ExpansionLocEnd, unsigned Length, bool ExpansionIsTokenRange=true, int LoadedID=0, SourceLocation::UIntTy LoadedOffset=0)
Creates an expansion SLocEntry for a macro use.
A trivial tuple used to represent a source range.
StringLiteralParser - This decodes string escape characters and performs wide string analysis and Tra...
Exposes information about the current target.
virtual bool supportsCpuSupports() const
virtual bool supportsCpuInit() const
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
const llvm::Triple * getDarwinTargetVariantTriple() const
Returns the darwin target variant triple, the variant of the deployment target for which the code is ...
virtual bool supportsCpuIs() const
TokenLexer - This implements a lexer that returns tokens from a macro body or token stream instead of...
Token - This structure provides full information about a lexed token.
IdentifierInfo * getIdentifierInfo() const
unsigned getFlags() const
Return the internal represtation of the flags.
void clearFlag(TokenFlags Flag)
Unset the specified flag.
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file.
unsigned getLength() const
void setLength(unsigned Len)
void setKind(tok::TokenKind K)
bool is(tok::TokenKind K) const
is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {....
tok::TokenKind getKind() const
bool isAtStartOfLine() const
isAtStartOfLine - Return true if this token is at the start of a line.
bool hasLeadingSpace() const
Return true if this token has whitespace before it.
void setLocation(SourceLocation L)
bool isOneOf(tok::TokenKind K1, tok::TokenKind K2) const
bool isNot(tok::TokenKind K) const
bool isAnnotation() const
Return true if this is any of tok::annot_* kind tokens.
bool hasUDSuffix() const
Return true if this token is a string or character literal which has a ud-suffix.
void startToken()
Reset all flags to cleared.
void setIdentifierInfo(IdentifierInfo *II)
void setFlagValue(TokenFlags Flag, bool Val)
Set a flag to either true or false.
void setFlag(TokenFlags Flag)
Set the specified flag.
Defines the clang::TargetInfo interface.
bool evaluateRequiredTargetFeatures(llvm::StringRef RequiredFatures, const llvm::StringMap< bool > &TargetFetureMap)
Returns true if the required target features of a builtin function are enabled.
CharacteristicKind
Indicates whether a file or directory holds normal user code, system code, or system code which is im...
uint32_t Literal
Literals are represented as positive integers.
@ Error
Present this diagnostic as an error.
@ WarningOrError
A diagnostic that indicates a problem or potential problem.
The JSON file list parser is used to communicate input to InstallAPI.
@ Result
The result type of a method or function.
int hasAttribute(AttributeCommonInfo::Syntax Syntax, const IdentifierInfo *Scope, const IdentifierInfo *Attr, const TargetInfo &Target, const LangOptions &LangOpts)
Return the version number associated with the attribute if we recognize and implement the attribute s...
@ Braces
New-expression has a C++11 list-initializer.