34 #include "llvm/ADT/ArrayRef.h" 35 #include "llvm/ADT/DenseMap.h" 36 #include "llvm/ADT/DenseSet.h" 37 #include "llvm/ADT/FoldingSet.h" 38 #include "llvm/ADT/None.h" 39 #include "llvm/ADT/Optional.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" 59 using namespace clang;
65 auto Pos = CurSubmoduleState->Macros.find(II);
66 return Pos == CurSubmoduleState->Macros.end() ? nullptr
67 : Pos->second.getLatest();
71 assert(MD &&
"MacroDirective should be non-zero!");
72 assert(!MD->
getPrevious() &&
"Already attached to a MacroDirective history.");
74 MacroState &StoredMD = CurSubmoduleState->Macros[II];
75 auto *OldMD = StoredMD.getLatest();
77 StoredMD.setLatest(MD);
78 StoredMD.overrideActiveModuleMacros(*
this, II);
80 if (needModuleMacros()) {
84 PendingModuleMacroNames.push_back(II);
89 if (!MD->
isDefined() && LeafModuleMacros.find(II) == LeafModuleMacros.end())
108 MacroState &StoredMD = CurSubmoduleState->Macros[II];
110 if (
auto *OldMD = StoredMD.getLatest()) {
116 assert(OldMD->getMacroInfo()->isBuiltinMacro() &&
117 "only built-ins should have an entry here");
118 assert(!OldMD->getPrevious() &&
"builtin should only have a single entry");
120 StoredMD.setLatest(MD);
127 if (!MD->
isDefined() && LeafModuleMacros.find(II) == LeafModuleMacros.end())
135 llvm::FoldingSetNodeID
ID;
139 if (
auto *MM = ModuleMacros.FindNodeOrInsertPos(
ID, InsertPos)) {
145 ModuleMacros.InsertNode(MM, InsertPos);
149 for (
auto *O : Overrides) {
150 HidAny |= (O->NumOverriddenBy == 0);
151 ++O->NumOverriddenBy;
155 auto &LeafMacros = LeafModuleMacros[II];
157 LeafMacros.erase(std::remove_if(LeafMacros.begin(), LeafMacros.end(),
159 return MM->NumOverriddenBy != 0;
165 LeafMacros.push_back(MM);
174 llvm::FoldingSetNodeID
ID;
178 return ModuleMacros.FindNodeOrInsertPos(
ID, InsertPos);
181 void Preprocessor::updateModuleMacroInfo(
const IdentifierInfo *II,
182 ModuleMacroInfo &Info) {
183 assert(Info.ActiveModuleMacrosGeneration !=
184 CurSubmoduleState->VisibleModules.getGeneration() &&
185 "don't need to update this macro name info");
186 Info.ActiveModuleMacrosGeneration =
187 CurSubmoduleState->VisibleModules.getGeneration();
189 auto Leaf = LeafModuleMacros.find(II);
190 if (Leaf == LeafModuleMacros.end()) {
195 Info.ActiveModuleMacros.clear();
198 llvm::DenseMap<ModuleMacro *, int> NumHiddenOverrides;
199 for (
auto *O : Info.OverriddenMacros)
200 NumHiddenOverrides[O] = -1;
204 for (
auto *LeafMM : Leaf->second) {
205 assert(LeafMM->getNumOverridingMacros() == 0 &&
"leaf macro overridden");
206 if (NumHiddenOverrides.lookup(LeafMM) == 0)
207 Worklist.push_back(LeafMM);
209 while (!Worklist.empty()) {
210 auto *MM = Worklist.pop_back_val();
211 if (CurSubmoduleState->VisibleModules.isVisible(MM->getOwningModule())) {
214 if (MM->getMacroInfo())
215 Info.ActiveModuleMacros.push_back(MM);
217 for (
auto *O : MM->overrides())
218 if ((
unsigned)++NumHiddenOverrides[O] == O->getNumOverridingMacros())
219 Worklist.push_back(O);
223 std::reverse(Info.ActiveModuleMacros.begin(), Info.ActiveModuleMacros.end());
227 bool IsSystemMacro =
true;
228 bool IsAmbiguous =
false;
229 if (
auto *MD = Info.MD) {
230 while (MD && isa<VisibilityMacroDirective>(MD))
231 MD = MD->getPrevious();
232 if (
auto *DMD = dyn_cast_or_null<DefMacroDirective>(MD)) {
237 for (
auto *Active : Info.ActiveModuleMacros) {
238 auto *NewMI = Active->getMacroInfo();
249 if (MI && NewMI != MI &&
250 !MI->isIdenticalTo(*NewMI, *
this,
true))
252 IsSystemMacro &= Active->getOwningModule()->IsSystem ||
256 Info.IsAmbiguous = IsAmbiguous && !IsSystemMacro;
261 auto LeafIt = LeafModuleMacros.find(II);
262 if (LeafIt != LeafModuleMacros.end())
263 Leaf = LeafIt->second;
264 const MacroState *
State =
nullptr;
265 auto Pos = CurSubmoduleState->Macros.find(II);
266 if (Pos != CurSubmoduleState->Macros.end())
267 State = &Pos->second;
271 llvm::errs() <<
" ambiguous";
272 if (
State && !
State->getOverriddenMacros().empty()) {
273 llvm::errs() <<
" overrides";
274 for (
auto *O :
State->getOverriddenMacros())
275 llvm::errs() <<
" " << O->getOwningModule()->getFullModuleName();
277 llvm::errs() <<
"\n";
280 for (
auto *MD =
State ?
State->getLatest() :
nullptr; MD;
281 MD = MD->getPrevious()) {
288 for (
auto *MM :
State ?
State->getActiveModuleMacros(*
this, II) :
None)
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();
311 if (Visited.insert(O).second)
312 Worklist.push_back(O);
315 llvm::errs() <<
"\n";
316 if (
auto *MI = MM->getMacroInfo()) {
319 llvm::errs() <<
"\n";
339 void Preprocessor::RegisterBuiltinMacros() {
349 Ident__has_cpp_attribute =
352 Ident__has_cpp_attribute =
nullptr;
364 Ident__identifier =
nullptr;
365 Ident__pragma =
nullptr;
377 Ident__has_c_attribute =
nullptr;
387 Ident__is_target_environment =
395 Ident__MODULE__ =
nullptr;
406 if (!II)
return true;
416 if (ExpansionMI->isEnabled() &&
433 bool Preprocessor::isNextPPTokenLParen() {
437 Val = CurLexer->isNextPPTokenLParen();
439 Val = CurTokenLexer->isNextTokenLParen();
447 for (
const IncludeStackInfo &Entry : llvm::reverse(IncludeMacroStack)) {
449 Val = Entry.TheLexer->isNextPPTokenLParen();
451 Val = Entry.TheTokenLexer->isNextTokenLParen();
457 if (Entry.ThePPLexer)
505 Args = ReadMacroCallArgumentList(
Identifier, MI, ExpansionEnd);
512 if (!Args)
return true;
514 ++NumFnMacroExpanded;
524 SourceRange ExpansionRange(ExpandLoc, ExpansionEnd);
532 DelayedMacroExpandsCallbacks.push_back(
533 MacroExpandsInfo(
Identifier, M, ExpansionRange));
535 Callbacks->MacroExpands(
Identifier, M, ExpansionRange, Args);
536 if (!DelayedMacroExpandsCallbacks.empty()) {
537 for (
const MacroExpandsInfo &Info : DelayedMacroExpandsCallbacks) {
539 Callbacks->MacroExpands(Info.Tok, Info.MD, Info.Range,
542 DelayedMacroExpandsCallbacks.clear();
566 if (Args) Args->
destroy(*
this);
571 PropagateLineStartLeadingSpaceInfo(
Identifier);
572 ++NumFastMacroExpanded;
582 if (Args) Args->
destroy(*
this);
586 bool isAtStartOfLine =
Identifier.isAtStartOfLine();
587 bool hasLeadingSpace =
Identifier.hasLeadingSpace();
607 if (!NewMI->isEnabled() || NewMI == MI) {
618 ++NumFastMacroExpanded;
639 if (I->is(tok::l_paren)) {
640 Brackets.push_back(
Paren);
641 }
else if (I->is(tok::r_paren)) {
642 if (Brackets.empty() || Brackets.back() ==
Brace)
645 }
else if (I->is(tok::l_brace)) {
646 Brackets.push_back(
Brace);
647 }
else if (I->is(tok::r_brace)) {
648 if (Brackets.empty() || Brackets.back() ==
Paren)
653 return Brackets.empty();
687 bool FoundSeparatorToken =
false;
691 if (I->is(tok::l_brace)) {
693 }
else if (I->is(tok::r_brace)) {
695 if (Braces == 0 && ClosingBrace == E && FoundSeparatorToken)
702 FoundSeparatorToken =
true;
703 I->setKind(tok::comma);
711 if (FoundSeparatorToken && ArgStartIterator->is(tok::l_brace)) {
719 if (FoundSeparatorToken) {
721 TempToken.
setKind(tok::l_paren);
722 TempToken.
setLocation(ArgStartIterator->getLocation());
724 NewTokens.push_back(TempToken);
728 NewTokens.insert(NewTokens.end(), ArgStartIterator, I);
731 if (FoundSeparatorToken) {
734 TempToken.
setKind(tok::r_paren);
737 NewTokens.push_back(TempToken);
738 ParenHints.push_back(
SourceRange(ArgStartIterator->getLocation(),
743 NewTokens.push_back(*I);
746 ArgStartIterator = I + 1;
747 FoundSeparatorToken =
false;
752 return !ParenHints.empty() && InitLists.empty();
759 MacroArgs *Preprocessor::ReadMacroCallArgumentList(
Token &MacroName,
772 assert(
Tok.
is(tok::l_paren) &&
"Error computing l-paren-ness?");
778 bool ContainsCodeCompletionTok =
false;
779 bool FoundElidedComma =
false;
783 unsigned NumActuals = 0;
788 assert(
Tok.
isOneOf(tok::l_paren, tok::comma) &&
789 "only expect argument separators here");
791 size_t ArgTokenStart = ArgTokens.size();
796 unsigned NumParens = 0;
804 if (!ContainsCodeCompletionTok) {
805 Diag(MacroName, diag::err_unterm_macro_invoc);
813 auto Toks = std::make_unique<Token[]>(1);
815 EnterTokenStream(std::move(Toks), 1,
true,
false);
817 }
else if (
Tok.
is(tok::r_paren)) {
819 if (NumParens-- == 0) {
820 MacroEnd =
Tok.getLocation();
821 if (!ArgTokens.empty() &&
822 ArgTokens.back().commaAfterElided()) {
823 FoundElidedComma =
true;
827 }
else if (
Tok.
is(tok::l_paren)) {
829 }
else if (
Tok.
is(tok::comma)) {
840 }
else if (NumParens == 0) {
846 if (NumFixedArgsLeft > 1)
849 }
else if (
Tok.
is(tok::comment) && !KeepMacroComments) {
853 }
else if (!
Tok.isAnnotation() &&
Tok.getIdentifierInfo() !=
nullptr) {
863 }
else if (
Tok.
is(tok::code_completion)) {
864 ContainsCodeCompletionTok =
true;
873 ArgTokens.push_back(
Tok);
878 if (ArgTokens.empty() &&
Tok.getKind() == tok::r_paren)
883 if (!isVariadic && NumFixedArgsLeft == 0 && TooManyArgsLoc.
isInvalid()) {
884 if (ArgTokens.size() != ArgTokenStart)
885 TooManyArgsLoc = ArgTokens[ArgTokenStart].getLocation();
887 TooManyArgsLoc = ArgStartLoc;
892 if (ArgTokens.size() == ArgTokenStart && !
getLangOpts().C99)
894 ? diag::warn_cxx98_compat_empty_fnmacro_arg
895 : diag::ext_empty_fnmacro_arg);
903 ArgTokens.push_back(EOFTok);
905 if (!ContainsCodeCompletionTok && NumFixedArgsLeft != 0)
915 if (!isVariadic && NumActuals > MinArgsExpected &&
916 !ContainsCodeCompletionTok) {
919 Diag(TooManyArgsLoc, diag::err_too_many_args_in_macro_invoc);
929 unsigned FixedNumArgs = 0;
932 ParenHints, InitLists)) {
933 if (!InitLists.empty()) {
936 diag::note_init_list_at_beginning_of_macro_argument);
942 if (FixedNumArgs != MinArgsExpected)
950 ArgTokens.swap(FixedArgTokens);
951 NumActuals = FixedNumArgs;
955 bool isVarargsElided =
false;
957 if (ContainsCodeCompletionTok) {
964 for (; NumActuals < MinArgsExpected; ++NumActuals)
965 ArgTokens.push_back(EOFTok);
968 if (NumActuals < MinArgsExpected) {
970 if (NumActuals == 0 && MinArgsExpected == 1) {
977 }
else if ((FoundElidedComma || MI->
isVariadic()) &&
978 (NumActuals+1 == MinArgsExpected ||
979 (NumActuals == 0 && MinArgsExpected == 2))) {
987 Diag(
Tok, diag::ext_missing_varargs_arg);
998 isVarargsElided =
true;
999 }
else if (!ContainsCodeCompletionTok) {
1001 Diag(
Tok, diag::err_too_few_args_in_macro_invoc);
1011 Tok.setLocation(EndLoc);
1013 ArgTokens.push_back(
Tok);
1016 if (NumActuals == 0 && MinArgsExpected == 2)
1017 ArgTokens.push_back(
Tok);
1019 }
else if (NumActuals > MinArgsExpected && !MI->
isVariadic() &&
1020 !ContainsCodeCompletionTok) {
1023 Diag(MacroName, diag::err_too_many_args_in_macro_invoc);
1043 size_t newIndex = MacroExpandedTokens.size();
1044 bool cacheNeedsToGrow = tokens.size() >
1045 MacroExpandedTokens.capacity()-MacroExpandedTokens.size();
1046 MacroExpandedTokens.append(tokens.begin(), tokens.end());
1048 if (cacheNeedsToGrow) {
1051 for (
const auto &
Lexer : MacroExpandingLexersStack) {
1054 std::tie(prevLexer, tokIndex) =
Lexer;
1055 prevLexer->Tokens = MacroExpandedTokens.data() + tokIndex;
1059 MacroExpandingLexersStack.push_back(std::make_pair(tokLexer, newIndex));
1060 return MacroExpandedTokens.data() + newIndex;
1063 void Preprocessor::removeCachedMacroExpandedTokensOfLastLexer() {
1064 assert(!MacroExpandingLexersStack.empty());
1065 size_t tokIndex = MacroExpandingLexersStack.back().second;
1066 assert(tokIndex < MacroExpandedTokens.size());
1068 MacroExpandedTokens.resize(tokIndex);
1069 MacroExpandingLexersStack.pop_back();
1077 time_t TT = time(
nullptr);
1078 struct tm *TM = localtime(&TT);
1080 static const char *
const Months[] = {
1081 "Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec" 1086 llvm::raw_svector_ostream TmpStream(TmpBuffer);
1087 TmpStream << llvm::format(
"\"%s %2d %4d\"", Months[TM->tm_mon],
1088 TM->tm_mday, TM->tm_year + 1900);
1097 llvm::raw_svector_ostream TmpStream(TmpBuffer);
1098 TmpStream << llvm::format(
"\"%02d:%02d:%02d\"",
1099 TM->tm_hour, TM->tm_min, TM->tm_sec);
1113 if (Feature.startswith(
"__") && Feature.endswith(
"__") && Feature.size() >= 4)
1114 Feature = Feature.substr(2, Feature.size() - 4);
1116 #define FEATURE(Name, Predicate) .Case(#Name, Predicate) 1117 return llvm::StringSwitch<bool>(Feature)
1118 #include "clang/Basic/Features.def" 1139 if (Extension.startswith(
"__") && Extension.endswith(
"__") &&
1140 Extension.size() >= 4)
1141 Extension = Extension.substr(2, Extension.size() - 4);
1145 #define EXTENSION(Name, Predicate) .Case(#Name, Predicate) 1146 return llvm::StringSwitch<bool>(Extension)
1147 #include "clang/Basic/Features.def" 1165 PP.
Diag(LParenLoc, diag::err_pp_directive_required) << II;
1167 assert(
Tok.
is(tok::identifier));
1168 Tok.setIdentifierInfo(II);
1176 }
while (
Tok.getKind() == tok::comment);
1182 PP.
Diag(LParenLoc, diag::err_pp_expected_after) << II << tok::l_paren;
1189 LParenLoc =
Tok.getLocation();
1195 PP.
Diag(
Tok.getLocation(), diag::err_pp_expects_filename);
1201 bool Invalid =
false;
1214 << II << tok::r_paren;
1215 PP.
Diag(LParenLoc, diag::note_matching) << tok::l_paren;
1229 CurDir,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr);
1236 Callbacks->HasInclude(FilenameLoc,
Filename, isAngled,
File, FileType);
1240 return File.hasValue();
1260 const FileEntry *LookupFromFile =
nullptr;
1267 PP.
Diag(
Tok, diag::pp_include_next_in_primary);
1274 }
else if (!Lookup) {
1275 PP.
Diag(
Tok, diag::pp_include_next_absolute_path);
1291 bool &HasLexedNextTok)> Op) {
1295 PP.
Diag(
Tok.getLocation(), diag::err_pp_expected_after) << II
1301 Tok.setKind(tok::numeric_constant);
1306 unsigned ParenDepth = 1;
1311 bool SuppressDiagnostic =
false;
1317 switch (
Tok.getKind()) {
1322 PP.
Diag(
Tok.getLocation(), diag::err_unterm_macro_invoc);
1326 if (!SuppressDiagnostic) {
1327 PP.
Diag(
Tok.getLocation(), diag::err_too_many_args_in_macro_invoc);
1328 SuppressDiagnostic =
true;
1334 if (Result.hasValue())
1336 if (!SuppressDiagnostic) {
1337 PP.
Diag(
Tok.getLocation(), diag::err_pp_nested_paren) << II;
1338 SuppressDiagnostic =
true;
1343 if (--ParenDepth > 0)
1348 if (Result.hasValue()) {
1349 OS << Result.getValue();
1352 if (Result.getValue() > 1)
1356 if (!SuppressDiagnostic)
1357 PP.
Diag(
Tok.getLocation(), diag::err_too_few_args_in_macro_invoc);
1359 Tok.setKind(tok::numeric_constant);
1364 if (Result.hasValue())
1367 bool HasLexedNextToken =
false;
1368 Result = Op(
Tok, HasLexedNextToken);
1370 if (HasLexedNextToken)
1377 if (!SuppressDiagnostic) {
1378 if (
auto Diag = PP.
Diag(
Tok.getLocation(), diag::err_pp_expected_after)) {
1385 PP.
Diag(LParenLoc, diag::note_matching) << tok::l_paren;
1386 SuppressDiagnostic =
true;
1397 if (!
Tok.isAnnotation() && (II =
Tok.getIdentifierInfo()))
1400 PP.
Diag(
Tok.getLocation(), DiagID);
1406 std::string ArchName = II->
getName().lower() +
"--";
1407 llvm::Triple Arch(ArchName);
1408 const llvm::Triple &TT = TI.
getTriple();
1411 if ((Arch.getSubArch() == llvm::Triple::NoSubArch ||
1412 Arch.getSubArch() == TT.getSubArch()) &&
1413 ((TT.getArch() == llvm::Triple::thumb &&
1414 Arch.getArch() == llvm::Triple::arm) ||
1415 (TT.getArch() == llvm::Triple::thumbeb &&
1416 Arch.getArch() == llvm::Triple::armeb)))
1421 return (Arch.getSubArch() == llvm::Triple::NoSubArch ||
1422 Arch.getSubArch() == TT.getSubArch()) &&
1423 Arch.getArch() == TT.getArch();
1428 StringRef VendorName = TI.
getTriple().getVendorName();
1429 if (VendorName.empty())
1430 VendorName =
"unknown";
1431 return VendorName.equals_lower(II->
getName());
1436 std::string OSName =
1437 (llvm::Twine(
"unknown-unknown-") + II->
getName().lower()).str();
1438 llvm::Triple OS(OSName);
1439 if (OS.getOS() == llvm::Triple::Darwin) {
1443 return TI.
getTriple().getOS() == OS.getOS();
1449 std::string EnvName = (llvm::Twine(
"---") + II->
getName().lower()).str();
1450 llvm::Triple Env(EnvName);
1451 return TI.
getTriple().getEnvironment() == Env.getEnvironment();
1456 const std::map<std::string, std::string, std::greater<std::string>>
1458 for (
const auto &Entry : MacroPrefixMap)
1459 if (llvm::sys::path::replace_path_prefix(Path, Entry.first, Entry.second))
1465 void Preprocessor::ExpandBuiltinMacro(
Token &
Tok) {
1468 assert(II &&
"Can't be a macro without id info!");
1472 if (II == Ident_Pragma)
1473 return Handle_Pragma(
Tok);
1474 else if (II == Ident__pragma)
1475 return HandleMicrosoft__pragma(
Tok);
1477 ++NumBuiltinMacroExpanded;
1480 llvm::raw_svector_ostream
OS(TmpBuffer);
1483 Tok.setIdentifierInfo(
nullptr);
1485 bool IsAtStartOfLine =
Tok.isAtStartOfLine();
1486 bool HasLeadingSpace =
Tok.hasLeadingSpace();
1488 if (II == Ident__LINE__) {
1508 Tok.setKind(tok::numeric_constant);
1509 }
else if (II == Ident__FILE__ || II == Ident__BASE_FILE__ ||
1510 II == Ident__FILE_NAME__) {
1517 if (II == Ident__BASE_FILE__ && PLoc.
isValid()) {
1533 if (II == Ident__FILE_NAME__) {
1536 StringRef PLFileName = llvm::sys::path::filename(PLoc.
getFilename());
1537 if (PLFileName !=
"")
1546 OS <<
'"' << FN <<
'"';
1548 Tok.setKind(tok::string_literal);
1549 }
else if (II == Ident__DATE__) {
1550 Diag(
Tok.getLocation(), diag::warn_pp_date_time);
1553 Tok.setKind(tok::string_literal);
1554 Tok.setLength(strlen(
"\"Mmm dd yyyy\""));
1559 }
else if (II == Ident__TIME__) {
1560 Diag(
Tok.getLocation(), diag::warn_pp_date_time);
1563 Tok.setKind(tok::string_literal);
1564 Tok.setLength(strlen(
"\"hh:mm:ss\""));
1569 }
else if (II == Ident__INCLUDE_LEVEL__) {
1583 Tok.setKind(tok::numeric_constant);
1584 }
else if (II == Ident__TIMESTAMP__) {
1585 Diag(
Tok.getLocation(), diag::warn_pp_date_time);
1599 time_t TT = CurFile->getModificationTime();
1600 struct tm *TM = localtime(&TT);
1603 Result =
"??? ??? ?? ??:??:?? ????\n";
1606 OS <<
'"' << StringRef(
Result).drop_back() <<
'"';
1607 Tok.setKind(tok::string_literal);
1608 }
else if (II == Ident__COUNTER__) {
1610 OS << CounterValue++;
1611 Tok.setKind(tok::numeric_constant);
1612 }
else if (II == Ident__has_feature) {
1614 [
this](
Token &
Tok,
bool &HasLexedNextToken) ->
int {
1616 diag::err_feature_check_malformed);
1619 }
else if (II == Ident__has_extension) {
1621 [
this](
Token &
Tok,
bool &HasLexedNextToken) ->
int {
1623 diag::err_feature_check_malformed);
1626 }
else if (II == Ident__has_builtin) {
1628 [
this](
Token &
Tok,
bool &HasLexedNextToken) ->
int {
1630 diag::err_feature_check_malformed);
1635 case Builtin::BI__builtin_operator_new:
1636 case Builtin::BI__builtin_operator_delete:
1644 }
else if (II->
getTokenID() != tok::identifier ||
1653 if (II->
getName().startswith(
"__builtin_") ||
1654 II->
getName().startswith(
"__is_") ||
1655 II->
getName().startswith(
"__has_"))
1657 return llvm::StringSwitch<bool>(II->
getName())
1658 .Case(
"__array_rank",
true)
1659 .Case(
"__array_extent",
true)
1660 .Case(
"__reference_binds_to_temporary",
true)
1661 .Case(
"__underlying_type",
true)
1664 return llvm::StringSwitch<bool>(II->
getName())
1666 .Case(
"__make_integer_seq",
getLangOpts().CPlusPlus)
1667 .Case(
"__type_pack_element",
getLangOpts().CPlusPlus)
1671 .Case(
"__is_target_arch",
true)
1672 .Case(
"__is_target_vendor",
true)
1673 .Case(
"__is_target_os",
true)
1674 .Case(
"__is_target_environment",
true)
1678 }
else if (II == Ident__is_identifier) {
1680 [](
Token &
Tok,
bool &HasLexedNextToken) ->
int {
1681 return Tok.
is(tok::identifier);
1683 }
else if (II == Ident__has_attribute) {
1685 [
this](
Token &
Tok,
bool &HasLexedNextToken) ->
int {
1687 diag::err_feature_check_malformed);
1691 }
else if (II == Ident__has_declspec) {
1693 [
this](
Token &
Tok,
bool &HasLexedNextToken) ->
int {
1695 diag::err_feature_check_malformed);
1698 return LangOpts.DeclSpecKeyword &&
1705 }
else if (II == Ident__has_cpp_attribute ||
1706 II == Ident__has_c_attribute) {
1707 bool IsCXX = II == Ident__has_cpp_attribute;
1709 OS,
Tok, II, *
this, [&](
Token &
Tok,
bool &HasLexedNextToken) ->
int {
1712 Tok, *
this, diag::err_feature_check_malformed);
1720 HasLexedNextToken =
true;
1725 diag::err_feature_check_malformed);
1733 }
else if (II == Ident__has_include ||
1734 II == Ident__has_include_next) {
1739 if (II == Ident__has_include)
1747 Tok.setKind(tok::numeric_constant);
1748 }
else if (II == Ident__has_warning) {
1751 [
this](
Token &
Tok,
bool &HasLexedNextToken) ->
int {
1752 std::string WarningName;
1755 HasLexedNextToken =
Tok.
is(tok::string_literal);
1762 if (WarningName.size() < 3 || WarningName[0] !=
'-' ||
1763 WarningName[1] !=
'W') {
1764 Diag(StrStartLoc, diag::warn_has_warning_invalid_option);
1775 WarningName.substr(2), Diags);
1777 }
else if (II == Ident__building_module) {
1782 [
this](
Token &
Tok,
bool &HasLexedNextToken) ->
int {
1784 diag::err_expected_id_building_module);
1788 }
else if (II == Ident__MODULE__) {
1792 Tok.setIdentifierInfo(ModuleII);
1794 }
else if (II == Ident__identifier) {
1803 << II << tok::l_paren;
1805 if (!
Tok.isAnnotation() &&
Tok.getIdentifierInfo())
1806 Tok.setKind(tok::identifier);
1813 if (!
Tok.isAnnotation() &&
Tok.getIdentifierInfo())
1814 Tok.setKind(tok::identifier);
1816 Diag(
Tok.getLocation(), diag::err_pp_identifier_arg_not_identifier)
1826 if (RParen.
isNot(tok::r_paren)) {
1828 <<
Tok.getKind() << tok::r_paren;
1829 Diag(LParenLoc, diag::note_matching) << tok::l_paren;
1832 }
else if (II == Ident__is_target_arch) {
1834 OS,
Tok, II, *
this, [
this](
Token &
Tok,
bool &HasLexedNextToken) ->
int {
1836 Tok, *
this, diag::err_feature_check_malformed);
1839 }
else if (II == Ident__is_target_vendor) {
1841 OS,
Tok, II, *
this, [
this](
Token &
Tok,
bool &HasLexedNextToken) ->
int {
1843 Tok, *
this, diag::err_feature_check_malformed);
1846 }
else if (II == Ident__is_target_os) {
1848 OS,
Tok, II, *
this, [
this](
Token &
Tok,
bool &HasLexedNextToken) ->
int {
1850 Tok, *
this, diag::err_feature_check_malformed);
1853 }
else if (II == Ident__is_target_environment) {
1855 OS,
Tok, II, *
this, [
this](
Token &
Tok,
bool &HasLexedNextToken) ->
int {
1857 Tok, *
this, diag::err_feature_check_malformed);
1861 llvm_unreachable(
"Unknown identifier!");
A diagnostic that indicates a problem or potential problem.
static IdentifierInfo * RegisterBuiltinMacro(Preprocessor &PP, const char *Name)
RegisterBuiltinMacro - Register the specified identifier in the identifier table and mark it as a bui...
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.
static bool CheckMatchedBrackets(const SmallVectorImpl< Token > &Tokens)
CheckMatchedBrackets - Returns true if the braces and parentheses in the token vector are properly ne...
Lexer - This provides a simple interface that turns a text buffer into a stream of tokens.
MacroInfo * AllocateMacroInfo(SourceLocation L)
Allocate a new MacroInfo object with the provided SourceLocation.
param_iterator param_begin() const
void setChangedSinceDeserialization()
Note that this identifier has changed since it was loaded from an AST file.
void markMacroAsUsed(MacroInfo *MI)
A macro is used, update information about macros that need unused warnings.
IdentifierInfo * getIdentifierInfo(StringRef Name) const
Return information about the specified preprocessor identifier token.
Defines the clang::FileManager interface and associated types.
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
void dumpMacroInfo(const IdentifierInfo *II)
bool isEnabled() const
Return true if this macro is enabled.
Is the identifier known as a __declspec-style attribute?
bool isInPrimaryFile() const
Return true if we're in the top-level file, not in a #include.
static bool EvaluateHasIncludeCommon(Token &Tok, IdentifierInfo *II, Preprocessor &PP, const DirectoryLookup *LookupFrom, const FileEntry *LookupFromFile)
EvaluateHasIncludeCommon - Process a '__has_include("path")' or '__has_include_next("path")' expressi...
Defines the clang::MacroInfo and clang::MacroDirective classes.
Is the identifier known as a GNU-style attribute?
Defines types useful for describing an Objective-C runtime.
A description of the current definition of a macro.
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...
bool isOutOfDate() const
Determine whether the information for this identifier is out of date with respect to the external sou...
static bool isTargetEnvironment(const TargetInfo &TI, const IdentifierInfo *II)
Implements the __is_target_environment builtin macro.
bool isCompilingModule() const
Are we compiling a module interface (.cppm or module map)?
bool isFromAST() const
Return true if the identifier in its current state was loaded from an AST file.
diag::Severity getExtensionHandlingBehavior() const
CharacteristicKind
Indicates whether a file or directory holds normal user code, system code, or system code which is im...
This interface provides a way to observe the actions of the preprocessor as it does its thing.
const MacroDirective * getPrevious() const
Get previous definition of the macro with the same name.
tok::TokenKind getKind() const
SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset=0)
Computes the source location just past the end of the token at this source location.
DefMacroDirective * appendDefMacroDirective(IdentifierInfo *II, MacroInfo *MI, SourceLocation Loc)
One of these records is kept for each identifier that is lexed.
Represents a macro directive exported by a module.
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...
void setHasMacroDefinition(bool Val)
static bool isTargetOS(const TargetInfo &TI, const IdentifierInfo *II)
Implements the __is_target_os builtin macro.
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...
bool hasCommaPasting() const
const TargetInfo & getTargetInfo() const
Token - This structure provides full information about a lexed token.
void setKind(tok::TokenKind K)
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
const LangOptions & getLangOpts() const
Describes a module or submodule.
static void ComputeDATE_TIME(SourceLocation &DATELoc, SourceLocation &TIMELoc, Preprocessor &PP)
ComputeDATE_TIME - Compute the current time, enter it into the specified scratch buffer,...
param_iterator param_end() const
SourceLocation AdvanceToTokenCharacter(SourceLocation TokStart, unsigned Char) const
Given a location that specifies the start of a token, return a new location that specifies a characte...
Module * getCurrentLexerSubmodule() const
Return the submodule owning the file being lexed.
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...
static ModuleMacro * create(Preprocessor &PP, Module *OwningModule, IdentifierInfo *II, MacroInfo *Macro, ArrayRef< ModuleMacro * > Overrides)
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 ...
HeaderSearch & getHeaderSearchInfo() const
tok::TokenKind getTokenID() const
If this is a source-language token (e.g.
static void EvaluateFeatureLikeBuiltinMacro(llvm::raw_svector_ostream &OS, Token &Tok, IdentifierInfo *II, Preprocessor &PP, llvm::function_ref< int(Token &Tok, bool &HasLexedNextTok)> Op)
Process single-argument builtin feature-like macros that return integer values.
const Token & getReplacementToken(unsigned Tok) const
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
void LexNonComment(Token &Result)
Lex a token.
bool GetIncludeFilenameSpelling(SourceLocation Loc, StringRef &Buffer)
Turn the specified lexer token into a fully checked and spelled filename, e.g.
void ExpandedMacro()
ExpandedMacro - When a macro is expanded with this lexer as the current buffer, this method is called...
static bool EvaluateHasInclude(Token &Tok, IdentifierInfo *II, Preprocessor &PP)
EvaluateHasInclude - Process a '__has_include("path")' expression.
void destroy(Preprocessor &PP)
destroy - Destroy and deallocate the memory for this object.
TokenLexer - This implements a lexer that returns tokens from a macro body or token stream instead of...
Present this diagnostic as an error.
int hasAttribute(AttrSyntax 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...
bool isUsed() const
Return false if this macro is defined in the main file and has not yet been used.
void appendMacroDirective(IdentifierInfo *II, MacroDirective *MD)
Add a directive to the macro directive history for this identifier.
void LexUnexpandedToken(Token &Result)
Just like Lex, but disables macro expansion of identifier tokens.
A little helper class used to produce diagnostics.
std::string CurrentModule
The name of the current module, of which the main source file is a part.
unsigned getNumParams() const
ModuleMacro * addModuleMacro(Module *Mod, IdentifierInfo *II, MacroInfo *Macro, ArrayRef< ModuleMacro * > Overrides, bool &IsNew)
Register an exported macro for a module and identifier.
Exposes information about the current target.
Defines the clang::LangOptions interface.
bool isInvalid() const
Return true if this object is invalid or uninitialized.
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
static bool isTargetVendor(const TargetInfo &TI, const IdentifierInfo *II)
Implements the __is_target_vendor builtin macro.
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
MacroArgs - An instance of this class captures information about the formal arguments specified to a ...
unsigned getLine() const
Return the presumed line number of this location.
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file.
Defines the clang::Preprocessor interface.
MultipleIncludeOpt MIOpt
A state machine that detects the #ifndef-wrapping a file idiom for the multiple-include optimization.
const MacroInfo * getMacroInfo(const IdentifierInfo *II) const
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Represents an unpacked "presumed" location which can be presented to the user.
PPCallbacks * getPPCallbacks() const
bool isObjectLike() const
The result type of a method or function.
static bool HasExtension(const Preprocessor &PP, StringRef Extension)
HasExtension - Return true if we recognize and implement the feature specified by the identifier,...
DirectoryLookup - This class represents one entry in the search list that specifies the search order ...
const DirectoryLookup * GetCurDirLookup()
Get the DirectoryLookup structure used to find the current FileEntry, if CurLexer is non-null and if ...
unsigned getBuiltinID() const
Return a value indicating whether this is a builtin function.
void setIsUsed(bool Val)
Set the value of the IsUsed flag.
const char * getFilename() const
Return the presumed filename of this location.
ExternalPreprocessorSource * getExternalSource() const
Encapsulates changes to the "macros namespace" (the location where the macro name became active,...
Encodes a location in the source.
static bool isTargetArch(const TargetInfo &TI, const IdentifierInfo *II)
Implements the __is_target_arch 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,...
void setLength(unsigned Len)
SourceLocation createExpansionLoc(SourceLocation Loc, SourceLocation ExpansionLocStart, SourceLocation ExpansionLocEnd, unsigned TokLength, bool ExpansionIsTokenRange=true, int LoadedID=0, unsigned LoadedOffset=0)
Return a new SourceLocation that encodes the fact that a token from SpellingLoc should actually be re...
MacroDirective * getLocalMacroDirectiveHistory(const IdentifierInfo *II) const
Given an identifier, return the latest non-imported macro directive for that identifier.
static bool EvaluateHasIncludeNext(Token &Tok, IdentifierInfo *II, Preprocessor &PP)
EvaluateHasIncludeNext - Process '__has_include_next("path")' expression.
IdentifierInfo * getIdentifierInfo() const
Cached information about one file (either on disk or in the virtual file system).
void setIsBuiltinMacro(bool Val=true)
Set or clear the isBuiltinMacro flag.
const char * getNameStart() const
Return the beginning of the actual null-terminated string for this identifier.
void setLoadedMacroDirective(IdentifierInfo *II, MacroDirective *ED, MacroDirective *MD)
Set a MacroDirective that was loaded from a PCH file.
PreprocessorLexer * getCurrentLexer() const
Return the current lexer being lexed from.
StringRef getName() const
Return the actual identifier string.
bool isNot(tok::TokenKind K) const
bool hadMacroDefinition() const
Returns true if this identifier was #defined to some value at any moment.
Dataflow Directional Tag Classes.
bool isWarnIfUnused() const
Return true if we should emit a warning if the macro is unused.
bool isValid() const
Return true if this is a valid SourceLocation object.
unsigned getNumTokens() const
Return the number of tokens that this macro expands to.
bool isFunctionLike() const
const FileEntry * getFileEntry() const
getFileEntry - Return the FileEntry corresponding to this FileID.
Optional< FileEntryRef > LookupFile(SourceLocation FilenameLoc, StringRef Filename, bool isAngled, const DirectoryLookup *FromDir, const FileEntry *FromFile, const DirectoryLookup *&CurDir, SmallVectorImpl< char > *SearchPath, SmallVectorImpl< char > *RelativePath, ModuleMap::KnownHeader *SuggestedModule, bool *IsMapped, bool *IsFrameworkFound, bool SkipCache=false)
Given a "foo" or <foo> reference, look up the indicated file.
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.
bool IsHeaderFile
Indicates whether the front-end is explicitly told that the input is a header file (i....
Encapsulates the data about a macro definition (e.g.
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
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...
virtual void updateOutOfDateIdentifier(IdentifierInfo &II)=0
Update an out-of-date identifier.
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 ...
SourceLocation getEnd() 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.
SourceLocation getDefinitionLoc() const
Return the location that the macro was defined at.
CharSourceRange getExpansionRange(SourceLocation Loc) const
Given a SourceLocation object, return the range of tokens covered by the expansion in the ultimate fi...
const IntrusiveRefCntPtr< DiagnosticIDs > & getDiagnosticIDs() const
Defines the clang::SourceLocation class and associated facilities.
bool hasRevertedTokenIDToIdentifier() const
True if revertTokenIDToIdentifier() was called.
ModuleMacro * getModuleMacro(Module *Mod, IdentifierInfo *II)
DiagnosticsEngine & getDiagnostics() const
bool isAmbiguous() const
true if the definition is ambiguous, false otherwise.
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.
bool isBuiltinMacro() const
Return true if this macro requires processing before expansion.
Defines the clang::TargetInfo interface.
void setPrevious(MacroDirective *Prev)
Set previous definition of the macro with the same name.
void forAllDefinitions(Fn F) const
MacroInfo * getMacroInfo() const
Get the MacroInfo that should be used for this definition.
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...
static void remapMacroPath(SmallString< 256 > &Path, const std::map< std::string, std::string, std::greater< std::string >> &MacroPrefixMap)
void setLocation(SourceLocation L)
bool isParsingIfOrElifDirective() const
True if we are currently preprocessing a if or #elif directive.
A trivial tuple used to represent a source range.
bool LexHeaderName(Token &Result, bool AllowMacroExpansion=true)
Lex a token, forming a header-name token if possible.
PreprocessorLexer * getCurrentFileLexer() const
Return the current file lexer being lexed from.
SourceLocation getIncludeLoc() const
Return the presumed include location of this location.
Defines the PreprocessorLexer interface.
virtual void CodeCompleteMacroArgument(IdentifierInfo *Macro, MacroInfo *MacroInfo, unsigned ArgumentIndex)
Callback invoked when performing code completion inside a function-like macro argument.
void Profile(llvm::FoldingSetNodeID &ID) const
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) const
Forwarding function for diagnostics.
Defines enum values for all the target-independent builtin functions.
void startToken()
Reset all flags to cleared.
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) ...
Engages in a tight little dance with the lexer to efficiently preprocess tokens.