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,
380 const clang::MacroInfo *MI) {
381 clang::SourceLocation BeginLoc(
Range.getBegin());
382 const char *BeginPtr = PP.getSourceManager().getCharacterData(BeginLoc);
384 std::string Unexpanded;
385 if (MI->isFunctionLike()) {
386 clang::SourceLocation EndLoc(
Range.getEnd());
387 const char *EndPtr = PP.getSourceManager().getCharacterData(EndLoc) + 1;
388 Length = (EndPtr - BeginPtr) + 1;
391 return llvm::StringRef(BeginPtr,
Length).trim().str();
404 const clang::MacroInfo *MI,
405 const clang::MacroArgs *
Args) {
406 std::string Expanded;
408 for (
const auto &T : MI->tokens()) {
409 clang::IdentifierInfo *II = T.getIdentifierInfo();
410 int ArgNo = (II &&
Args ? MI->getParameterNum(II) : -1);
414 Expanded += PP.getSpelling(T);
417 std::string
Name = II->getName().str();
419 clang::MacroInfo *MacroInfo = PP.getMacroInfo(II);
428 const clang::Token *ResultArgToks;
429 const clang::Token *ArgTok =
Args->getUnexpArgument(ArgNo);
430 if (
Args->ArgNeedsPreexpansion(ArgTok, PP))
431 ResultArgToks = &(
const_cast<clang::MacroArgs *
>(
Args))
432 ->getPreExpArgument(ArgNo, PP)[0];
434 ResultArgToks = ArgTok;
436 if (ResultArgToks->is(clang::tok::eof))
438 unsigned NumToks = clang::MacroArgs::getArgLength(ResultArgToks);
440 for (
unsigned ArgumentIndex = 0; ArgumentIndex < NumToks; ++ArgumentIndex) {
441 const clang::Token &AT = ResultArgToks[ArgumentIndex];
442 clang::IdentifierInfo *II = AT.getIdentifierInfo();
444 Expanded += PP.getSpelling(AT);
447 std::string
Name = II->getName().str();
448 clang::MacroInfo *MacroInfo = PP.getMacroInfo(II);
463ConditionValueKindStrings[] = {
464 "(not evaluated)",
"false",
"true"
478 clang::SourceLocation
Loc)
484 PPItemKey(
const PPItemKey &Other)
488 bool operator==(
const PPItemKey &Other)
const {
489 if (Name != Other.Name)
491 if (File != Other.File)
493 if (Line != Other.Line)
495 return Column == Other.Column;
497 bool operator<(
const PPItemKey &Other)
const {
498 if (Name < Other.Name)
500 else if (Name > Other.Name)
502 if (File < Other.File)
504 else if (File > Other.File)
506 if (Line < Other.Line)
508 else if (Line > Other.Line)
510 return Column < Other.Column;
519class HeaderInclusionPath {
521 HeaderInclusionPath(std::vector<HeaderHandle> HeaderInclusionPath)
522 :
Path(HeaderInclusionPath) {}
523 HeaderInclusionPath(
const HeaderInclusionPath &Other) :
Path(Other.
Path) {}
524 HeaderInclusionPath() {}
525 std::vector<HeaderHandle> Path;
533class MacroExpansionInstance {
543 MacroExpansionInstance() {}
557 if (!haveInclusionPathHandle(H))
577class MacroExpansionTracker {
590 MacroExpansionTracker() {}
593 MacroExpansionInstance *
635class ConditionalExpansionInstance {
641 ConditionalExpansionInstance() {}
655 if (!haveInclusionPathHandle(H))
672class ConditionalTracker {
681 ConditionalTracker() {}
684 ConditionalExpansionInstance *
685 findConditionalExpansionInstance(clang::PPCallbacks::ConditionValueKind
ConditionValue) {
698 addConditionalExpansionInstance(clang::PPCallbacks::ConditionValueKind
ConditionValue,
717class PreprocessorTrackerImpl;
725class PreprocessorCallbacks :
public clang::PPCallbacks {
727 PreprocessorCallbacks(PreprocessorTrackerImpl &ppTracker,
728 clang::Preprocessor &PP, llvm::StringRef rootHeaderFile)
729 : PPTracker(ppTracker), PP(PP), RootHeaderFile(rootHeaderFile) {}
730 ~PreprocessorCallbacks()
override {}
734 InclusionDirective(clang::SourceLocation HashLoc,
735 const clang::Token &IncludeTok, llvm::StringRef
FileName,
736 bool IsAngled, clang::CharSourceRange FilenameRange,
737 clang::OptionalFileEntryRef File,
738 llvm::StringRef SearchPath, llvm::StringRef RelativePath,
739 const clang::Module *SuggestedModule,
bool ModuleImported,
740 clang::SrcMgr::CharacteristicKind FileType)
override;
741 void FileChanged(clang::SourceLocation
Loc,
742 clang::PPCallbacks::FileChangeReason Reason,
743 clang::SrcMgr::CharacteristicKind FileType,
744 clang::FileID PrevFID = clang::FileID())
override;
745 void MacroExpands(
const clang::Token &MacroNameTok,
746 const clang::MacroDefinition &MD, clang::SourceRange
Range,
747 const clang::MacroArgs *
Args)
override;
748 void Defined(
const clang::Token &MacroNameTok,
749 const clang::MacroDefinition &MD,
750 clang::SourceRange
Range)
override;
751 void If(clang::SourceLocation
Loc, clang::SourceRange ConditionRange,
752 clang::PPCallbacks::ConditionValueKind ConditionResult)
override;
753 void Elif(clang::SourceLocation
Loc, clang::SourceRange ConditionRange,
754 clang::PPCallbacks::ConditionValueKind ConditionResult,
755 clang::SourceLocation IfLoc)
override;
756 void Ifdef(clang::SourceLocation
Loc,
const clang::Token &MacroNameTok,
757 const clang::MacroDefinition &MD)
override;
758 void Ifndef(clang::SourceLocation
Loc,
const clang::Token &MacroNameTok,
759 const clang::MacroDefinition &MD)
override;
762 PreprocessorTrackerImpl &PPTracker;
763 clang::Preprocessor &PP;
764 std::string RootHeaderFile;
768typedef std::map<PPItemKey, MacroExpansionTracker> MacroExpansionMap;
769typedef std::map<PPItemKey, MacroExpansionTracker>::iterator
770MacroExpansionMapIter;
773typedef std::map<PPItemKey, ConditionalTracker> ConditionalExpansionMap;
774typedef std::map<PPItemKey, ConditionalTracker>::iterator
775ConditionalExpansionMapIter;
781class PreprocessorTrackerImpl :
public PreprocessorTracker {
783 PreprocessorTrackerImpl(llvm::SmallVector<std::string, 32> &Headers,
784 bool DoBlockCheckHeaderListOnly)
785 : BlockCheckHeaderListOnly(DoBlockCheckHeaderListOnly),
787 InNestedHeader(false) {
789 for (llvm::ArrayRef<std::string>::iterator I = Headers.begin(),
796 ~PreprocessorTrackerImpl()
override {}
799 void handlePreprocessorEntry(clang::Preprocessor &PP,
800 llvm::StringRef rootHeaderFile)
override {
801 HeadersInThisCompile.clear();
802 assert((HeaderStack.size() == 0) &&
"Header stack should be empty.");
803 pushHeaderHandle(addHeader(rootHeaderFile));
804 PP.addPPCallbacks(std::make_unique<PreprocessorCallbacks>(*
this, PP,
808 void handlePreprocessorExit()
override { HeaderStack.clear(); }
814 void handleIncludeDirective(llvm::StringRef DirectivePath,
int DirectiveLine,
816 llvm::StringRef TargetPath)
override {
819 if (BlockCheckHeaderListOnly && !isHeaderListHeader(TargetPath))
821 HeaderHandle CurrentHeaderHandle = findHeaderHandle(DirectivePath);
822 StringHandle IncludeHeaderHandle = addString(TargetPath);
823 for (std::vector<PPItemKey>::const_iterator I = IncludeDirectives.begin(),
824 E = IncludeDirectives.end();
827 if ((I->File == CurrentHeaderHandle) && (I->Line ==
DirectiveLine))
830 PPItemKey IncludeDirectiveItem(IncludeHeaderHandle, CurrentHeaderHandle,
832 IncludeDirectives.push_back(IncludeDirectiveItem);
838 bool checkForIncludesInBlock(clang::Preprocessor &PP,
839 clang::SourceRange BlockSourceRange,
840 const char *BlockIdentifierMessage,
841 llvm::raw_ostream &
OS)
override {
842 clang::SourceLocation BlockStartLoc = BlockSourceRange.getBegin();
843 clang::SourceLocation BlockEndLoc = BlockSourceRange.getEnd();
846 clang::FileID FileID = PP.getSourceManager().getFileID(BlockStartLoc);
849 HeaderHandle SourceHandle = findHeaderHandle(SourcePath);
850 if (SourceHandle == -1)
852 int BlockStartLine, BlockStartColumn, BlockEndLine, BlockEndColumn;
853 bool returnValue =
true;
858 for (std::vector<PPItemKey>::const_iterator I = IncludeDirectives.begin(),
859 E = IncludeDirectives.end();
862 if ((I->File == SourceHandle) && (I->Line >= BlockStartLine) &&
863 (I->Line < BlockEndLine)) {
865 OS << SourcePath <<
":" << I->Line <<
":" << I->Column <<
":\n";
868 OS << std::string(I->Column - 1,
' ') <<
"^\n";
869 OS <<
"error: Include directive within " << BlockIdentifierMessage
871 OS << SourcePath <<
":" << BlockStartLine <<
":" << BlockStartColumn
874 if (BlockStartColumn > 0)
875 OS << std::string(BlockStartColumn - 1,
' ') <<
"^\n";
876 OS <<
"The \"" << BlockIdentifierMessage <<
"\" block is here.\n";
883 void handleHeaderEntry(clang::Preprocessor &PP, llvm::StringRef HeaderPath) {
885 if (HeaderPath.starts_with(
"<"))
888 if (H != getCurrentHeaderHandle())
892 InNestedHeader = !HeadersInThisCompile.insert(H).second;
896 void handleHeaderExit(llvm::StringRef HeaderPath) {
898 if (HeaderPath.starts_with(
"<"))
902 if (isHeaderHandleInStack(H)) {
904 TH = getCurrentHeaderHandle();
906 }
while ((TH != H) && (HeaderStack.size() != 0));
908 InNestedHeader =
false;
913 return Strings.insert(Str).first->first();
918 std::string CanonicalPath(path);
919 std::replace(CanonicalPath.begin(), CanonicalPath.end(),
'\\',
'/');
920 return CanonicalPath;
924 bool isHeaderListHeader(llvm::StringRef HeaderPath)
const {
926 for (llvm::ArrayRef<std::string>::iterator I = HeaderList.begin(),
927 E = HeaderList.end();
929 if (*I == CanonicalPath)
937 HeaderHandle findHeaderHandle(llvm::StringRef HeaderPath)
const {
940 for (
auto I = HeaderPaths.begin(),
E = HeaderPaths.end(); I !=
E;
942 if (*I == CanonicalPath)
954 H = HeaderPaths.size();
955 HeaderPaths.push_back(addString(CanonicalPath));
963 return HeaderPaths[H];
969 HeaderStack.push_back(H);
970 return CurrentInclusionPathHandle = addInclusionPathHandle(HeaderStack);
973 void popHeaderHandle() {
975 if (HeaderStack.size() != 0) {
976 HeaderStack.pop_back();
977 CurrentInclusionPathHandle = addInclusionPathHandle(HeaderStack);
982 if (HeaderStack.size() != 0)
983 return HeaderStack.back();
989 return llvm::is_contained(HeaderStack, H);
995 findInclusionPathHandle(
const std::vector<HeaderHandle> &
Path)
const {
997 for (
auto I = InclusionPaths.begin(),
E = InclusionPaths.end(); I !=
E;
1007 addInclusionPathHandle(
const std::vector<HeaderHandle> &
Path) {
1010 H = InclusionPaths.size();
1011 InclusionPaths.push_back(HeaderInclusionPath(
Path));
1017 return CurrentInclusionPathHandle;
1021 const std::vector<HeaderHandle> &
1024 return InclusionPaths[H].Path;
1025 static std::vector<HeaderHandle>
Empty;
1030 void addMacroExpansionInstance(clang::Preprocessor &PP,
HeaderHandle H,
1031 clang::SourceLocation InstanceLoc,
1032 clang::SourceLocation DefinitionLoc,
1033 clang::IdentifierInfo *II,
1040 PPItemKey InstanceKey(PP,
MacroName, H, InstanceLoc);
1041 PPItemKey DefinitionKey(PP,
MacroName, H, DefinitionLoc);
1042 auto I = MacroExpansions.find(InstanceKey);
1044 if (I == MacroExpansions.end()) {
1051 MacroExpansions[InstanceKey] = MacroExpansionTracker(
1057 MacroExpansionTracker &CondTracker = I->second;
1059 MacroExpansionInstance *MacroInfo =
1060 CondTracker.findMacroExpansionInstance(addString(
MacroExpanded),
1070 CondTracker.addMacroExpansionInstance(
1079 addConditionalExpansionInstance(clang::Preprocessor &PP,
HeaderHandle H,
1080 clang::SourceLocation InstanceLoc,
1089 PPItemKey InstanceKey(PP, ConditionUnexpandedHandle, H, InstanceLoc);
1090 auto I = ConditionalExpansions.find(InstanceKey);
1092 if (I == ConditionalExpansions.end()) {
1096 ConditionalExpansions[InstanceKey] =
1101 ConditionalTracker &CondTracker = I->second;
1103 ConditionalExpansionInstance *MacroInfo =
1118 bool reportInconsistentMacros(llvm::raw_ostream &
OS)
override {
1119 bool ReturnValue =
false;
1121 for (
auto I = MacroExpansions.begin(),
E = MacroExpansions.end(); I !=
E;
1123 const PPItemKey &ItemKey = I->first;
1124 MacroExpansionTracker &MacroExpTracker = I->second;
1126 if (!MacroExpTracker.hasMismatch())
1131 OS << MacroExpTracker.InstanceSourceLine;
1132 if (ItemKey.Column > 0)
1133 OS << std::string(ItemKey.Column - 1,
' ') <<
"^\n";
1134 OS <<
"error: Macro instance '" << MacroExpTracker.MacroUnexpanded
1135 <<
"' has different values in this header, depending on how it was "
1138 for (
auto IMT = MacroExpTracker.MacroExpansionInstances.begin(),
1139 EMT = MacroExpTracker.MacroExpansionInstances.end();
1140 IMT != EMT; ++IMT) {
1141 MacroExpansionInstance &MacroInfo = *IMT;
1142 OS <<
" '" << MacroExpTracker.MacroUnexpanded <<
"' expanded to: '"
1143 << MacroInfo.MacroExpanded
1144 <<
"' with respect to these inclusion paths:\n";
1146 for (
auto IIP = MacroInfo.InclusionPathHandles.begin(),
1147 EIP = MacroInfo.InclusionPathHandles.end();
1148 IIP != EIP; ++IIP) {
1149 const std::vector<HeaderHandle> &ip = getInclusionPath(*IIP);
1150 auto Count = (int)ip.size();
1151 for (
int Index = 0; Index < Count; ++Index) {
1153 OS << std::string((Index * 2) + 4,
' ') << getHeaderFilePath(H)
1160 if (MacroInfo.DefinitionLocation.Line != ItemKey.Line) {
1161 OS << MacroInfo.DefinitionSourceLine;
1162 if (MacroInfo.DefinitionLocation.Column > 0)
1163 OS << std::string(MacroInfo.DefinitionLocation.Column - 1,
' ')
1165 OS <<
"Macro defined here.\n";
1167 OS <<
"(no macro definition)"
1176 bool reportInconsistentConditionals(llvm::raw_ostream &
OS)
override {
1177 bool ReturnValue =
false;
1179 for (
auto I = ConditionalExpansions.begin(),
1180 E = ConditionalExpansions.end();
1182 const PPItemKey &ItemKey = I->first;
1183 ConditionalTracker &CondTracker = I->second;
1184 if (!CondTracker.hasMismatch())
1189 OS << HeaderPaths[ItemKey.File] <<
":" << ItemKey.Line <<
":"
1190 << ItemKey.Column <<
"\n";
1191 OS <<
"#" << getDirectiveSpelling(CondTracker.DirectiveKind) <<
" "
1192 << CondTracker.ConditionUnexpanded <<
"\n";
1194 OS <<
"error: Conditional expression instance '"
1195 << CondTracker.ConditionUnexpanded
1196 <<
"' has different values in this header, depending on how it was "
1199 for (
auto IMT = CondTracker.ConditionalExpansionInstances.begin(),
1200 EMT = CondTracker.ConditionalExpansionInstances.end();
1201 IMT != EMT; ++IMT) {
1202 ConditionalExpansionInstance &MacroInfo = *IMT;
1203 OS <<
" '" << CondTracker.ConditionUnexpanded <<
"' expanded to: '"
1204 << ConditionValueKindStrings[MacroInfo.ConditionValue]
1205 <<
"' with respect to these inclusion paths:\n";
1207 for (
auto IIP = MacroInfo.InclusionPathHandles.begin(),
1208 EIP = MacroInfo.InclusionPathHandles.end();
1209 IIP != EIP; ++IIP) {
1210 const std::vector<HeaderHandle> &ip = getInclusionPath(*IIP);
1211 auto Count = (int)ip.size();
1212 for (
int Index = 0; Index < Count; ++Index) {
1214 OS << std::string((Index * 2) + 4,
' ') << getHeaderFilePath(H)
1224 static const char *getDirectiveSpelling(clang::tok::PPKeywordKind kind) {
1226 case clang::tok::pp_if:
1228 case clang::tok::pp_elif:
1230 case clang::tok::pp_ifdef:
1232 case clang::tok::pp_ifndef:
1240 llvm::SmallVector<std::string, 32> HeaderList;
1242 bool BlockCheckHeaderListOnly;
1244 std::vector<StringHandle> HeaderPaths;
1245 std::vector<HeaderHandle> HeaderStack;
1246 std::vector<HeaderInclusionPath> InclusionPaths;
1248 llvm::SmallSet<HeaderHandle, 32> HeadersInThisCompile;
1249 std::vector<PPItemKey> IncludeDirectives;
1250 MacroExpansionMap MacroExpansions;
1251 ConditionalExpansionMap ConditionalExpansions;
1252 bool InNestedHeader;
1264 llvm::SmallVector<std::string, 32> &Headers,
1265 bool DoBlockCheckHeaderListOnly) {
1266 return new PreprocessorTrackerImpl(Headers, DoBlockCheckHeaderListOnly);
1272void PreprocessorCallbacks::InclusionDirective(
1273 clang::SourceLocation HashLoc,
const clang::Token &IncludeTok,
1275 clang::CharSourceRange FilenameRange, clang::OptionalFileEntryRef File,
1276 llvm::StringRef SearchPath, llvm::StringRef RelativePath,
1277 const clang::Module *SuggestedModule,
bool ModuleImported,
1278 clang::SrcMgr::CharacteristicKind FileType) {
1282 PPTracker.handleIncludeDirective(HeaderPath,
DirectiveLine, DirectiveColumn,
1287void PreprocessorCallbacks::FileChanged(
1288 clang::SourceLocation
Loc, clang::PPCallbacks::FileChangeReason Reason,
1289 clang::SrcMgr::CharacteristicKind FileType, clang::FileID PrevFID) {
1295 clang::OptionalFileEntryRef F =
1296 PP.getSourceManager().getFileEntryRefForID(PrevFID);
1298 PPTracker.handleHeaderExit(F->getName());
1300 case SystemHeaderPragma:
1307void PreprocessorCallbacks::MacroExpands(
const clang::Token &MacroNameTok,
1308 const clang::MacroDefinition &MD,
1309 clang::SourceRange
Range,
1310 const clang::MacroArgs *
Args) {
1311 clang::SourceLocation
Loc =
Range.getBegin();
1313 if (!
Loc.isFileID())
1315 clang::IdentifierInfo *II = MacroNameTok.getIdentifierInfo();
1316 const clang::MacroInfo *MI = MD.getMacroInfo();
1317 std::string
MacroName = II->getName().str();
1320 PPTracker.addMacroExpansionInstance(
1321 PP, PPTracker.getCurrentHeaderHandle(),
Loc, MI->getDefinitionLoc(), II,
1322 Unexpanded, Expanded, PPTracker.getCurrentInclusionPathHandle());
1325void PreprocessorCallbacks::Defined(
const clang::Token &MacroNameTok,
1326 const clang::MacroDefinition &MD,
1327 clang::SourceRange
Range) {
1328 clang::SourceLocation
Loc(
Range.getBegin());
1329 clang::IdentifierInfo *II = MacroNameTok.getIdentifierInfo();
1330 const clang::MacroInfo *MI = MD.getMacroInfo();
1331 std::string
MacroName = II->getName().str();
1333 PPTracker.addMacroExpansionInstance(
1334 PP, PPTracker.getCurrentHeaderHandle(),
Loc,
1335 (MI ? MI->getDefinitionLoc() :
Loc), II, Unexpanded,
1336 (MI ?
"true" :
"false"), PPTracker.getCurrentInclusionPathHandle());
1339void PreprocessorCallbacks::If(clang::SourceLocation
Loc,
1340 clang::SourceRange ConditionRange,
1341 clang::PPCallbacks::ConditionValueKind ConditionResult) {
1343 PPTracker.addConditionalExpansionInstance(
1344 PP, PPTracker.getCurrentHeaderHandle(),
Loc, clang::tok::pp_if,
1345 ConditionResult, Unexpanded, PPTracker.getCurrentInclusionPathHandle());
1348void PreprocessorCallbacks::Elif(clang::SourceLocation
Loc,
1349 clang::SourceRange ConditionRange,
1350 clang::PPCallbacks::ConditionValueKind ConditionResult,
1351 clang::SourceLocation IfLoc) {
1353 PPTracker.addConditionalExpansionInstance(
1354 PP, PPTracker.getCurrentHeaderHandle(),
Loc, clang::tok::pp_elif,
1355 ConditionResult, Unexpanded, PPTracker.getCurrentInclusionPathHandle());
1358void PreprocessorCallbacks::Ifdef(clang::SourceLocation
Loc,
1359 const clang::Token &MacroNameTok,
1360 const clang::MacroDefinition &MD) {
1361 clang::PPCallbacks::ConditionValueKind IsDefined =
1362 (MD ? clang::PPCallbacks::CVK_True : clang::PPCallbacks::CVK_False );
1363 PPTracker.addConditionalExpansionInstance(
1364 PP, PPTracker.getCurrentHeaderHandle(),
Loc, clang::tok::pp_ifdef,
1365 IsDefined, PP.getSpelling(MacroNameTok),
1366 PPTracker.getCurrentInclusionPathHandle());
1369void PreprocessorCallbacks::Ifndef(clang::SourceLocation
Loc,
1370 const clang::Token &MacroNameTok,
1371 const clang::MacroDefinition &MD) {
1372 clang::PPCallbacks::ConditionValueKind IsNotDefined =
1373 (!MD ? clang::PPCallbacks::CVK_True : clang::PPCallbacks::CVK_False );
1374 PPTracker.addConditionalExpansionInstance(
1375 PP, PPTracker.getCurrentHeaderHandle(),
Loc, clang::tok::pp_ifndef,
1376 IsNotDefined, PP.getSpelling(MacroNameTok),
1377 PPTracker.getCurrentInclusionPathHandle());
llvm::SmallString< 256U > Name
CharSourceRange Range
SourceRange for the file name.
bool IsAngled
true if this was an include with angle brackets
ModularizeUtilities class definition.
StringHandle MacroExpanded
clang::tok::PPKeywordKind DirectiveKind
std::vector< InclusionPathHandle > InclusionPathHandles
StringHandle DefinitionSourceLine
StringHandle InstanceSourceLine
std::vector< HeaderHandle > Path
StringHandle ConditionUnexpanded
PPItemKey DefinitionLocation
StringHandle MacroUnexpanded
std::vector< ConditionalExpansionInstance > ConditionalExpansionInstances
clang::PPCallbacks::ConditionValueKind ConditionValue
std::vector< MacroExpansionInstance > MacroExpansionInstances
Macro expansions and preprocessor conditional consistency checker.
std::vector< llvm::StringRef > Strings
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)
std::string Path
A typedef to represent a file path.
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)