248#include "clang/Lex/LexDiagnostic.h"
249#include "clang/Lex/MacroArgs.h"
250#include "clang/Lex/PPCallbacks.h"
251#include "llvm/ADT/SmallSet.h"
252#include "llvm/ADT/StringSet.h"
253#include "llvm/Support/raw_ostream.h"
270 clang::SourceLocation Loc) {
272 return std::string(
"(none)");
274 return Loc.printToString(PP.getSourceManager());
279 clang::SourceLocation Loc) {
281 size_t Offset = Source.find(
':', 2);
282 if (Offset == std::string::npos)
284 return Source.substr(0, Offset);
289 clang::SourceLocation Loc,
int &Line,
291 clang::PresumedLoc PLoc = PP.getSourceManager().getPresumedLoc(Loc);
292 if (PLoc.isInvalid()) {
297 Line = PLoc.getLine();
298 Column = PLoc.getColumn();
303 clang::SourceRange Range) {
304 clang::SourceLocation BeginLoc = Range.getBegin();
305 clang::SourceLocation EndLoc = Range.getEnd();
306 const char *BeginPtr = PP.getSourceManager().getCharacterData(BeginLoc);
307 const char *EndPtr = PP.getSourceManager().getCharacterData(EndLoc);
308 size_t Length = EndPtr - BeginPtr;
309 return llvm::StringRef(BeginPtr, Length).trim().str();
314 clang::SourceLocation Loc) {
315 llvm::MemoryBufferRef MemBuffer = PP.getSourceManager().getBufferOrFake(
316 PP.getSourceManager().getFileID(Loc));
317 const char *Buffer = MemBuffer.getBufferStart();
318 const char *BufferEnd = MemBuffer.getBufferEnd();
319 const char *BeginPtr = PP.getSourceManager().getCharacterData(Loc);
320 const char *EndPtr = BeginPtr;
321 while (BeginPtr > Buffer) {
322 if (*BeginPtr ==
'\n') {
328 while (EndPtr < BufferEnd) {
329 if (*EndPtr ==
'\n') {
334 size_t Length = EndPtr - BeginPtr;
335 return llvm::StringRef(BeginPtr, Length).str();
339static std::string
getSourceLine(clang::Preprocessor &PP, clang::FileID FileID,
341 llvm::MemoryBufferRef MemBuffer =
342 PP.getSourceManager().getBufferOrFake(FileID);
343 const char *Buffer = MemBuffer.getBufferStart();
344 const char *BufferEnd = MemBuffer.getBufferEnd();
345 const char *BeginPtr = Buffer;
346 const char *EndPtr = BufferEnd;
351 while (Buffer < BufferEnd) {
352 if (*Buffer ==
'\n') {
353 if (++LineCounter == Line) {
354 BeginPtr = Buffer++ + 1;
361 while (Buffer < BufferEnd) {
362 if (*Buffer ==
'\n') {
368 size_t Length = EndPtr - BeginPtr;
369 return llvm::StringRef(BeginPtr, Length).str();
378 clang::Preprocessor &PP,
379 llvm::StringRef MacroName,
380 const clang::MacroInfo *MI) {
381 clang::SourceLocation BeginLoc(Range.getBegin());
382 const char *BeginPtr = PP.getSourceManager().getCharacterData(BeginLoc);
384 if (MI->isFunctionLike()) {
385 clang::SourceLocation EndLoc(Range.getEnd());
386 const char *EndPtr = PP.getSourceManager().getCharacterData(EndLoc) + 1;
387 Length = (EndPtr - BeginPtr) + 1;
389 Length = MacroName.size();
390 return llvm::StringRef(BeginPtr, Length).trim().str();
402 llvm::StringRef MacroName,
403 const clang::MacroInfo *MI,
404 const clang::MacroArgs *Args) {
405 std::string Expanded;
407 for (
const auto &T : MI->tokens()) {
408 clang::IdentifierInfo *II = T.getIdentifierInfo();
409 int ArgNo = (II && Args ? MI->getParameterNum(II) : -1);
413 Expanded += PP.getSpelling(T);
416 std::string Name = II->getName().str();
418 clang::MacroInfo *MacroInfo = PP.getMacroInfo(II);
419 if (MacroInfo && (Name != MacroName))
427 const clang::Token *ResultArgToks;
428 const clang::Token *ArgTok = Args->getUnexpArgument(ArgNo);
429 if (Args->ArgNeedsPreexpansion(ArgTok, PP))
430 ResultArgToks = &(
const_cast<clang::MacroArgs *
>(Args))
431 ->getPreExpArgument(ArgNo, PP)[0];
433 ResultArgToks = ArgTok;
435 if (ResultArgToks->is(clang::tok::eof))
437 unsigned NumToks = clang::MacroArgs::getArgLength(ResultArgToks);
439 for (
unsigned ArgumentIndex = 0; ArgumentIndex < NumToks; ++ArgumentIndex) {
440 const clang::Token &AT = ResultArgToks[ArgumentIndex];
441 clang::IdentifierInfo *II = AT.getIdentifierInfo();
443 Expanded += PP.getSpelling(AT);
446 std::string Name = II->getName().str();
447 clang::MacroInfo *MacroInfo = PP.getMacroInfo(II);
462ConditionValueKindStrings[] = {
463 "(not evaluated)",
"false",
"true"
477 clang::SourceLocation Loc)
478 : Name(Name), File(File) {
482 : Name(Name), File(File), Line(Line), Column(Column) {}
483 PPItemKey(
const PPItemKey &Other)
484 : Name(Other.Name), File(Other.File), Line(Other.Line),
485 Column(Other.Column) {}
487 bool operator==(
const PPItemKey &Other)
const {
488 if (Name != Other.Name)
490 if (File != Other.File)
492 if (Line != Other.Line)
494 return Column == Other.Column;
496 bool operator<(
const PPItemKey &Other)
const {
497 return std::tie(Name, File, Line, Column) <
498 std::tie(Other.Name, Other.File, Other.Line, Other.Column);
507class HeaderInclusionPath {
509 HeaderInclusionPath(std::vector<HeaderHandle> HeaderInclusionPath)
510 : Path(HeaderInclusionPath) {}
511 HeaderInclusionPath(
const HeaderInclusionPath &Other) : Path(Other.Path) {}
512 HeaderInclusionPath() {}
513 std::vector<HeaderHandle> Path;
521class MacroExpansionInstance {
524 PPItemKey &DefinitionLocation,
527 : MacroExpanded(MacroExpanded), DefinitionLocation(DefinitionLocation),
528 DefinitionSourceLine(DefinitionSourceLine) {
529 InclusionPathHandles.push_back(H);
531 MacroExpansionInstance() {}
536 for (
auto I = InclusionPathHandles.begin(), E = InclusionPathHandles.end();
545 if (!haveInclusionPathHandle(H))
546 InclusionPathHandles.push_back(H);
552 PPItemKey DefinitionLocation;
556 std::vector<InclusionPathHandle> InclusionPathHandles;
565class MacroExpansionTracker {
570 PPItemKey &DefinitionLocation,
573 : MacroUnexpanded(MacroUnexpanded),
574 InstanceSourceLine(InstanceSourceLine) {
575 addMacroExpansionInstance(MacroExpanded, DefinitionLocation,
578 MacroExpansionTracker() {}
581 MacroExpansionInstance *
583 PPItemKey &DefinitionLocation) {
584 for (
auto I = MacroExpansionInstances.begin(),
585 E = MacroExpansionInstances.end();
587 if ((I->MacroExpanded == MacroExpanded) &&
588 (I->DefinitionLocation == DefinitionLocation)) {
596 void addMacroExpansionInstance(
StringHandle MacroExpanded,
597 PPItemKey &DefinitionLocation,
600 MacroExpansionInstances.push_back(
601 MacroExpansionInstance(MacroExpanded, DefinitionLocation,
606 bool hasMismatch() {
return MacroExpansionInstances.size() > 1; }
615 std::vector<MacroExpansionInstance> MacroExpansionInstances;
623class ConditionalExpansionInstance {
625 ConditionalExpansionInstance(clang::PPCallbacks::ConditionValueKind ConditionValue,
InclusionPathHandle H)
626 : ConditionValue(ConditionValue) {
627 InclusionPathHandles.push_back(H);
629 ConditionalExpansionInstance() {}
634 for (
auto I = InclusionPathHandles.begin(), E = InclusionPathHandles.end();
643 if (!haveInclusionPathHandle(H))
644 InclusionPathHandles.push_back(H);
648 clang::PPCallbacks::ConditionValueKind ConditionValue;
650 std::vector<InclusionPathHandle> InclusionPathHandles;
660class ConditionalTracker {
662 ConditionalTracker(clang::tok::PPKeywordKind DirectiveKind,
663 clang::PPCallbacks::ConditionValueKind ConditionValue,
666 : DirectiveKind(DirectiveKind), ConditionUnexpanded(ConditionUnexpanded) {
669 ConditionalTracker() {}
672 ConditionalExpansionInstance *
673 findConditionalExpansionInstance(clang::PPCallbacks::ConditionValueKind ConditionValue) {
674 for (
auto I = ConditionalExpansionInstances.begin(),
675 E = ConditionalExpansionInstances.end();
677 if (I->ConditionValue == ConditionValue) {
686 addConditionalExpansionInstance(clang::PPCallbacks::ConditionValueKind ConditionValue,
688 ConditionalExpansionInstances.push_back(
693 bool hasMismatch() {
return ConditionalExpansionInstances.size() > 1; }
696 clang::tok::PPKeywordKind DirectiveKind;
702 std::vector<ConditionalExpansionInstance> ConditionalExpansionInstances;
705class PreprocessorTrackerImpl;
713class PreprocessorCallbacks :
public clang::PPCallbacks {
715 PreprocessorCallbacks(PreprocessorTrackerImpl &ppTracker,
716 clang::Preprocessor &PP, llvm::StringRef rootHeaderFile)
717 : PPTracker(ppTracker), PP(PP), RootHeaderFile(rootHeaderFile) {}
718 ~PreprocessorCallbacks()
override {}
722 InclusionDirective(clang::SourceLocation HashLoc,
723 const clang::Token &IncludeTok, llvm::StringRef FileName,
724 bool IsAngled, clang::CharSourceRange FilenameRange,
725 clang::OptionalFileEntryRef File,
726 llvm::StringRef SearchPath, llvm::StringRef RelativePath,
727 const clang::Module *SuggestedModule,
bool ModuleImported,
728 clang::SrcMgr::CharacteristicKind FileType)
override;
729 void FileChanged(clang::SourceLocation Loc,
730 clang::PPCallbacks::FileChangeReason Reason,
731 clang::SrcMgr::CharacteristicKind FileType,
732 clang::FileID PrevFID = clang::FileID())
override;
733 void MacroExpands(
const clang::Token &MacroNameTok,
734 const clang::MacroDefinition &MD, clang::SourceRange Range,
735 const clang::MacroArgs *Args)
override;
736 void Defined(
const clang::Token &MacroNameTok,
737 const clang::MacroDefinition &MD,
738 clang::SourceRange Range)
override;
739 void If(clang::SourceLocation Loc, clang::SourceRange ConditionRange,
740 clang::PPCallbacks::ConditionValueKind ConditionResult)
override;
741 void Elif(clang::SourceLocation Loc, clang::SourceRange ConditionRange,
742 clang::PPCallbacks::ConditionValueKind ConditionResult,
743 clang::SourceLocation IfLoc)
override;
744 void Ifdef(clang::SourceLocation Loc,
const clang::Token &MacroNameTok,
745 const clang::MacroDefinition &MD)
override;
746 void Ifndef(clang::SourceLocation Loc,
const clang::Token &MacroNameTok,
747 const clang::MacroDefinition &MD)
override;
750 PreprocessorTrackerImpl &PPTracker;
751 clang::Preprocessor &PP;
752 std::string RootHeaderFile;
756typedef std::map<PPItemKey, MacroExpansionTracker> MacroExpansionMap;
757typedef std::map<PPItemKey, MacroExpansionTracker>::iterator
758MacroExpansionMapIter;
761typedef std::map<PPItemKey, ConditionalTracker> ConditionalExpansionMap;
762typedef std::map<PPItemKey, ConditionalTracker>::iterator
763ConditionalExpansionMapIter;
771 PreprocessorTrackerImpl(llvm::SmallVector<std::string, 32> &Headers,
772 bool DoBlockCheckHeaderListOnly)
773 : BlockCheckHeaderListOnly(DoBlockCheckHeaderListOnly),
775 InNestedHeader(false) {
777 for (llvm::ArrayRef<std::string>::iterator I = Headers.begin(),
780 HeaderList.push_back(getCanonicalPath(*I));
784 ~PreprocessorTrackerImpl()
override {}
787 void handlePreprocessorEntry(clang::Preprocessor &PP,
788 llvm::StringRef rootHeaderFile)
override {
789 HeadersInThisCompile.clear();
790 assert((HeaderStack.size() == 0) &&
"Header stack should be empty.");
791 pushHeaderHandle(addHeader(rootHeaderFile));
792 PP.addPPCallbacks(std::make_unique<PreprocessorCallbacks>(*
this, PP,
796 void handlePreprocessorExit()
override { HeaderStack.clear(); }
802 void handleIncludeDirective(llvm::StringRef DirectivePath,
int DirectiveLine,
804 llvm::StringRef TargetPath)
override {
807 if (BlockCheckHeaderListOnly && !isHeaderListHeader(TargetPath))
809 HeaderHandle CurrentHeaderHandle = findHeaderHandle(DirectivePath);
810 StringHandle IncludeHeaderHandle = addString(TargetPath);
811 for (std::vector<PPItemKey>::const_iterator I = IncludeDirectives.begin(),
812 E = IncludeDirectives.end();
815 if ((I->File == CurrentHeaderHandle) && (I->Line == DirectiveLine))
818 PPItemKey IncludeDirectiveItem(IncludeHeaderHandle, CurrentHeaderHandle,
819 DirectiveLine, DirectiveColumn);
820 IncludeDirectives.push_back(IncludeDirectiveItem);
826 bool checkForIncludesInBlock(clang::Preprocessor &PP,
827 clang::SourceRange BlockSourceRange,
828 const char *BlockIdentifierMessage,
829 llvm::raw_ostream &OS)
override {
830 clang::SourceLocation BlockStartLoc = BlockSourceRange.getBegin();
831 clang::SourceLocation BlockEndLoc = BlockSourceRange.getEnd();
834 clang::FileID FileID = PP.getSourceManager().getFileID(BlockStartLoc);
837 HeaderHandle SourceHandle = findHeaderHandle(SourcePath);
838 if (SourceHandle == -1)
840 int BlockStartLine, BlockStartColumn, BlockEndLine, BlockEndColumn;
841 bool returnValue =
true;
846 for (std::vector<PPItemKey>::const_iterator I = IncludeDirectives.begin(),
847 E = IncludeDirectives.end();
850 if ((I->File == SourceHandle) && (I->Line >= BlockStartLine) &&
851 (I->Line < BlockEndLine)) {
853 OS << SourcePath <<
":" << I->Line <<
":" << I->Column <<
":\n";
856 OS << std::string(I->Column - 1,
' ') <<
"^\n";
857 OS <<
"error: Include directive within " << BlockIdentifierMessage
859 OS << SourcePath <<
":" << BlockStartLine <<
":" << BlockStartColumn
862 if (BlockStartColumn > 0)
863 OS << std::string(BlockStartColumn - 1,
' ') <<
"^\n";
864 OS <<
"The \"" << BlockIdentifierMessage <<
"\" block is here.\n";
871 void handleHeaderEntry(clang::Preprocessor &PP, llvm::StringRef HeaderPath) {
873 if (HeaderPath.starts_with(
"<"))
876 if (H != getCurrentHeaderHandle())
880 InNestedHeader = !HeadersInThisCompile.insert(H).second;
884 void handleHeaderExit(llvm::StringRef HeaderPath) {
886 if (HeaderPath.starts_with(
"<"))
890 if (isHeaderHandleInStack(H)) {
892 TH = getCurrentHeaderHandle();
894 }
while ((TH != H) && (HeaderStack.size() != 0));
896 InNestedHeader =
false;
901 return Strings.insert(Str).first->first();
906 std::string CanonicalPath(path);
907 llvm::replace(CanonicalPath,
'\\',
'/');
908 return CanonicalPath;
912 bool isHeaderListHeader(llvm::StringRef HeaderPath)
const {
914 for (llvm::ArrayRef<std::string>::iterator I = HeaderList.begin(),
915 E = HeaderList.end();
917 if (*I == CanonicalPath)
925 HeaderHandle findHeaderHandle(llvm::StringRef HeaderPath)
const {
928 for (
auto I = HeaderPaths.begin(), E = HeaderPaths.end(); I != E;
930 if (*I == CanonicalPath)
942 H = HeaderPaths.size();
943 HeaderPaths.push_back(addString(CanonicalPath));
951 return HeaderPaths[H];
957 HeaderStack.push_back(H);
958 return CurrentInclusionPathHandle = addInclusionPathHandle(HeaderStack);
961 void popHeaderHandle() {
963 if (HeaderStack.size() != 0) {
964 HeaderStack.pop_back();
965 CurrentInclusionPathHandle = addInclusionPathHandle(HeaderStack);
970 if (HeaderStack.size() != 0)
971 return HeaderStack.back();
977 return llvm::is_contained(HeaderStack, H);
983 findInclusionPathHandle(
const std::vector<HeaderHandle> &Path)
const {
985 for (
auto I = InclusionPaths.begin(), E = InclusionPaths.end(); I != E;
995 addInclusionPathHandle(
const std::vector<HeaderHandle> &Path) {
998 H = InclusionPaths.size();
999 InclusionPaths.push_back(HeaderInclusionPath(Path));
1005 return CurrentInclusionPathHandle;
1009 const std::vector<HeaderHandle> &
1012 return InclusionPaths[H].Path;
1013 static std::vector<HeaderHandle>
Empty;
1018 void addMacroExpansionInstance(clang::Preprocessor &PP,
HeaderHandle H,
1019 clang::SourceLocation InstanceLoc,
1020 clang::SourceLocation DefinitionLoc,
1021 clang::IdentifierInfo *II,
1022 llvm::StringRef MacroUnexpanded,
1023 llvm::StringRef MacroExpanded,
1028 PPItemKey InstanceKey(PP, MacroName, H, InstanceLoc);
1029 PPItemKey DefinitionKey(PP, MacroName, H, DefinitionLoc);
1030 auto I = MacroExpansions.find(InstanceKey);
1032 if (I == MacroExpansions.end()) {
1033 std::string InstanceSourceLine =
1036 std::string DefinitionSourceLine =
1039 MacroExpansions[InstanceKey] = MacroExpansionTracker(
1040 addString(MacroUnexpanded), addString(MacroExpanded),
1041 addString(InstanceSourceLine), DefinitionKey,
1045 MacroExpansionTracker &CondTracker = I->second;
1047 MacroExpansionInstance *MacroInfo =
1048 CondTracker.findMacroExpansionInstance(addString(MacroExpanded),
1055 std::string DefinitionSourceLine =
1058 CondTracker.addMacroExpansionInstance(
1059 addString(MacroExpanded), DefinitionKey,
1067 addConditionalExpansionInstance(clang::Preprocessor &PP,
HeaderHandle H,
1068 clang::SourceLocation InstanceLoc,
1069 clang::tok::PPKeywordKind DirectiveKind,
1070 clang::PPCallbacks::ConditionValueKind ConditionValue,
1071 llvm::StringRef ConditionUnexpanded,
1076 StringHandle ConditionUnexpandedHandle(addString(ConditionUnexpanded));
1077 PPItemKey InstanceKey(PP, ConditionUnexpandedHandle, H, InstanceLoc);
1078 auto I = ConditionalExpansions.find(InstanceKey);
1080 if (I == ConditionalExpansions.end()) {
1081 std::string InstanceSourceLine =
1084 ConditionalExpansions[InstanceKey] =
1085 ConditionalTracker(DirectiveKind, ConditionValue,
1089 ConditionalTracker &CondTracker = I->second;
1091 ConditionalExpansionInstance *MacroInfo =
1092 CondTracker.findConditionalExpansionInstance(ConditionValue);
1098 CondTracker.addConditionalExpansionInstance(ConditionValue,
1106 bool reportInconsistentMacros(llvm::raw_ostream &OS)
override {
1107 bool ReturnValue =
false;
1109 for (
auto I = MacroExpansions.begin(), E = MacroExpansions.end(); I != E;
1111 const PPItemKey &ItemKey = I->first;
1112 MacroExpansionTracker &MacroExpTracker = I->second;
1114 if (!MacroExpTracker.hasMismatch())
1119 OS << MacroExpTracker.InstanceSourceLine;
1120 if (ItemKey.Column > 0)
1121 OS << std::string(ItemKey.Column - 1,
' ') <<
"^\n";
1122 OS <<
"error: Macro instance '" << MacroExpTracker.MacroUnexpanded
1123 <<
"' has different values in this header, depending on how it was "
1126 for (
auto IMT = MacroExpTracker.MacroExpansionInstances.begin(),
1127 EMT = MacroExpTracker.MacroExpansionInstances.end();
1128 IMT != EMT; ++IMT) {
1129 MacroExpansionInstance &MacroInfo = *IMT;
1130 OS <<
" '" << MacroExpTracker.MacroUnexpanded <<
"' expanded to: '"
1131 << MacroInfo.MacroExpanded
1132 <<
"' with respect to these inclusion paths:\n";
1134 for (
auto IIP = MacroInfo.InclusionPathHandles.begin(),
1135 EIP = MacroInfo.InclusionPathHandles.end();
1136 IIP != EIP; ++IIP) {
1137 const std::vector<HeaderHandle> &ip = getInclusionPath(*IIP);
1138 auto Count = (int)ip.size();
1139 for (
int Index = 0; Index < Count; ++Index) {
1141 OS << std::string((Index * 2) + 4,
' ') << getHeaderFilePath(H)
1148 if (MacroInfo.DefinitionLocation.Line != ItemKey.Line) {
1149 OS << MacroInfo.DefinitionSourceLine;
1150 if (MacroInfo.DefinitionLocation.Column > 0)
1151 OS << std::string(MacroInfo.DefinitionLocation.Column - 1,
' ')
1153 OS <<
"Macro defined here.\n";
1155 OS <<
"(no macro definition)"
1164 bool reportInconsistentConditionals(llvm::raw_ostream &OS)
override {
1165 bool ReturnValue =
false;
1167 for (
auto I = ConditionalExpansions.begin(),
1168 E = ConditionalExpansions.end();
1170 const PPItemKey &ItemKey = I->first;
1171 ConditionalTracker &CondTracker = I->second;
1172 if (!CondTracker.hasMismatch())
1177 OS << HeaderPaths[ItemKey.File] <<
":" << ItemKey.Line <<
":"
1178 << ItemKey.Column <<
"\n";
1179 OS <<
"#" << getDirectiveSpelling(CondTracker.DirectiveKind) <<
" "
1180 << CondTracker.ConditionUnexpanded <<
"\n";
1182 OS <<
"error: Conditional expression instance '"
1183 << CondTracker.ConditionUnexpanded
1184 <<
"' has different values in this header, depending on how it was "
1187 for (
auto IMT = CondTracker.ConditionalExpansionInstances.begin(),
1188 EMT = CondTracker.ConditionalExpansionInstances.end();
1189 IMT != EMT; ++IMT) {
1190 ConditionalExpansionInstance &MacroInfo = *IMT;
1191 OS <<
" '" << CondTracker.ConditionUnexpanded <<
"' expanded to: '"
1192 << ConditionValueKindStrings[MacroInfo.ConditionValue]
1193 <<
"' with respect to these inclusion paths:\n";
1195 for (
auto IIP = MacroInfo.InclusionPathHandles.begin(),
1196 EIP = MacroInfo.InclusionPathHandles.end();
1197 IIP != EIP; ++IIP) {
1198 const std::vector<HeaderHandle> &ip = getInclusionPath(*IIP);
1199 auto Count = (int)ip.size();
1200 for (
int Index = 0; Index < Count; ++Index) {
1202 OS << std::string((Index * 2) + 4,
' ') << getHeaderFilePath(H)
1212 static const char *getDirectiveSpelling(clang::tok::PPKeywordKind kind) {
1214 case clang::tok::pp_if:
1216 case clang::tok::pp_elif:
1218 case clang::tok::pp_ifdef:
1220 case clang::tok::pp_ifndef:
1228 llvm::SmallVector<std::string, 32> HeaderList;
1230 bool BlockCheckHeaderListOnly;
1231 llvm::StringSet<> Strings;
1232 std::vector<StringHandle> HeaderPaths;
1233 std::vector<HeaderHandle> HeaderStack;
1234 std::vector<HeaderInclusionPath> InclusionPaths;
1236 llvm::SmallSet<HeaderHandle, 32> HeadersInThisCompile;
1237 std::vector<PPItemKey> IncludeDirectives;
1238 MacroExpansionMap MacroExpansions;
1239 ConditionalExpansionMap ConditionalExpansions;
1240 bool InNestedHeader;
1252 llvm::SmallVector<std::string, 32> &Headers,
1253 bool DoBlockCheckHeaderListOnly) {
1254 return new PreprocessorTrackerImpl(Headers, DoBlockCheckHeaderListOnly);
1260void PreprocessorCallbacks::InclusionDirective(
1261 clang::SourceLocation HashLoc,
const clang::Token &IncludeTok,
1262 llvm::StringRef FileName,
bool IsAngled,
1263 clang::CharSourceRange FilenameRange, clang::OptionalFileEntryRef File,
1264 llvm::StringRef SearchPath, llvm::StringRef RelativePath,
1265 const clang::Module *SuggestedModule,
bool ModuleImported,
1266 clang::SrcMgr::CharacteristicKind FileType) {
1267 int DirectiveLine, DirectiveColumn;
1270 PPTracker.handleIncludeDirective(HeaderPath, DirectiveLine, DirectiveColumn,
1275void PreprocessorCallbacks::FileChanged(
1276 clang::SourceLocation Loc, clang::PPCallbacks::FileChangeReason Reason,
1277 clang::SrcMgr::CharacteristicKind FileType, clang::FileID PrevFID) {
1280 PPTracker.handleHeaderEntry(PP, getSourceLocationFile(PP, Loc));
1283 clang::OptionalFileEntryRef F =
1284 PP.getSourceManager().getFileEntryRefForID(PrevFID);
1286 PPTracker.handleHeaderExit(F->getName());
1288 case SystemHeaderPragma:
1295void PreprocessorCallbacks::MacroExpands(
const clang::Token &MacroNameTok,
1296 const clang::MacroDefinition &MD,
1297 clang::SourceRange Range,
1298 const clang::MacroArgs *Args) {
1299 clang::SourceLocation Loc = Range.getBegin();
1301 if (!Loc.isFileID())
1303 clang::IdentifierInfo *II = MacroNameTok.getIdentifierInfo();
1304 const clang::MacroInfo *MI = MD.getMacroInfo();
1305 std::string MacroName = II->getName().str();
1308 PPTracker.addMacroExpansionInstance(
1309 PP, PPTracker.getCurrentHeaderHandle(), Loc, MI->getDefinitionLoc(), II,
1310 Unexpanded, Expanded, PPTracker.getCurrentInclusionPathHandle());
1313void PreprocessorCallbacks::Defined(
const clang::Token &MacroNameTok,
1314 const clang::MacroDefinition &MD,
1315 clang::SourceRange Range) {
1316 clang::SourceLocation Loc(Range.getBegin());
1317 clang::IdentifierInfo *II = MacroNameTok.getIdentifierInfo();
1318 const clang::MacroInfo *MI = MD.getMacroInfo();
1320 PPTracker.addMacroExpansionInstance(
1321 PP, PPTracker.getCurrentHeaderHandle(), Loc,
1322 (MI ? MI->getDefinitionLoc() : Loc), II, Unexpanded,
1323 (MI ?
"true" :
"false"), PPTracker.getCurrentInclusionPathHandle());
1326void PreprocessorCallbacks::If(clang::SourceLocation Loc,
1327 clang::SourceRange ConditionRange,
1328 clang::PPCallbacks::ConditionValueKind ConditionResult) {
1330 PPTracker.addConditionalExpansionInstance(
1331 PP, PPTracker.getCurrentHeaderHandle(), Loc, clang::tok::pp_if,
1332 ConditionResult, Unexpanded, PPTracker.getCurrentInclusionPathHandle());
1335void PreprocessorCallbacks::Elif(clang::SourceLocation Loc,
1336 clang::SourceRange ConditionRange,
1337 clang::PPCallbacks::ConditionValueKind ConditionResult,
1338 clang::SourceLocation IfLoc) {
1340 PPTracker.addConditionalExpansionInstance(
1341 PP, PPTracker.getCurrentHeaderHandle(), Loc, clang::tok::pp_elif,
1342 ConditionResult, Unexpanded, PPTracker.getCurrentInclusionPathHandle());
1345void PreprocessorCallbacks::Ifdef(clang::SourceLocation Loc,
1346 const clang::Token &MacroNameTok,
1347 const clang::MacroDefinition &MD) {
1348 clang::PPCallbacks::ConditionValueKind IsDefined =
1349 (MD ? clang::PPCallbacks::CVK_True : clang::PPCallbacks::CVK_False );
1350 PPTracker.addConditionalExpansionInstance(
1351 PP, PPTracker.getCurrentHeaderHandle(), Loc, clang::tok::pp_ifdef,
1352 IsDefined, PP.getSpelling(MacroNameTok),
1353 PPTracker.getCurrentInclusionPathHandle());
1356void PreprocessorCallbacks::Ifndef(clang::SourceLocation Loc,
1357 const clang::Token &MacroNameTok,
1358 const clang::MacroDefinition &MD) {
1359 clang::PPCallbacks::ConditionValueKind IsNotDefined =
1360 (!MD ? clang::PPCallbacks::CVK_True : clang::PPCallbacks::CVK_False );
1361 PPTracker.addConditionalExpansionInstance(
1362 PP, PPTracker.getCurrentHeaderHandle(), Loc, clang::tok::pp_ifndef,
1363 IsNotDefined, PP.getSpelling(MacroNameTok),
1364 PPTracker.getCurrentInclusionPathHandle());
ModularizeUtilities class definition.
Macro expansions and preprocessor conditional consistency checker.
static std::string getCanonicalPath(llvm::StringRef FilePath)
Convert header path to canonical form.
Preprocessor tracker for modularize.
virtual ~PreprocessorTracker()
static PreprocessorTracker * create(llvm::SmallVector< std::string, 32 > &Headers, bool DoBlockCheckHeaderListOnly)
static std::string getMacroUnexpandedString(clang::SourceRange Range, clang::Preprocessor &PP, llvm::StringRef MacroName, const clang::MacroInfo *MI)
static std::string getSourceLocationFile(clang::Preprocessor &PP, clang::SourceLocation Loc)
static void getSourceLocationLineAndColumn(clang::Preprocessor &PP, clang::SourceLocation Loc, int &Line, int &Column)
static std::string getSourceLine(clang::Preprocessor &PP, clang::SourceLocation Loc)
static std::string getSourceString(clang::Preprocessor &PP, clang::SourceRange Range)
llvm::StringRef StringHandle
const InclusionPathHandle InclusionPathHandleInvalid
static std::string getMacroExpandedString(clang::Preprocessor &PP, llvm::StringRef MacroName, const clang::MacroInfo *MI, const clang::MacroArgs *Args)
const HeaderHandle HeaderHandleInvalid
static std::string getSourceLocationString(clang::Preprocessor &PP, clang::SourceLocation Loc)
bool operator==(const Inclusion &LHS, const Inclusion &RHS)
std::optional< std::string > getCanonicalPath(const FileEntryRef F, FileManager &FileMgr)
Get the canonical path of F.
bool operator<(const Ref &L, const Ref &R)