247 #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/Support/StringPool.h" 253 #include "llvm/Support/raw_ostream.h" 271 clang::SourceLocation
Loc) {
273 return std::string(
"(none)");
275 return Loc.printToString(PP.getSourceManager());
280 clang::SourceLocation
Loc) {
282 size_t Offset = Source.find(
':', 2);
283 if (Offset == std::string::npos)
285 return Source.substr(0, Offset);
290 clang::SourceLocation
Loc,
int &
Line,
292 clang::PresumedLoc PLoc = PP.getSourceManager().getPresumedLoc(Loc);
293 if (PLoc.isInvalid()) {
298 Line = PLoc.getLine();
299 Column = PLoc.getColumn();
304 clang::SourceRange
Range) {
305 clang::SourceLocation BeginLoc = Range.getBegin();
306 clang::SourceLocation EndLoc = Range.getEnd();
307 const char *BeginPtr = PP.getSourceManager().getCharacterData(BeginLoc);
308 const char *EndPtr = PP.getSourceManager().getCharacterData(EndLoc);
309 size_t Length = EndPtr - BeginPtr;
310 return llvm::StringRef(BeginPtr, Length).trim().str();
315 clang::SourceLocation
Loc) {
316 const llvm::MemoryBuffer *MemBuffer =
317 PP.getSourceManager().getBuffer(PP.getSourceManager().getFileID(Loc));
318 const char *Buffer = MemBuffer->getBufferStart();
319 const char *BufferEnd = MemBuffer->getBufferEnd();
320 const char *BeginPtr = PP.getSourceManager().getCharacterData(Loc);
321 const char *EndPtr = BeginPtr;
322 while (BeginPtr > Buffer) {
323 if (*BeginPtr ==
'\n') {
329 while (EndPtr < BufferEnd) {
330 if (*EndPtr ==
'\n') {
335 size_t Length = EndPtr - BeginPtr;
336 return llvm::StringRef(BeginPtr, Length).str();
340 static std::string
getSourceLine(clang::Preprocessor &PP, clang::FileID FileID,
342 const llvm::MemoryBuffer *MemBuffer = PP.getSourceManager().getBuffer(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 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;
390 Length = MacroName.size();
391 return llvm::StringRef(BeginPtr, Length).trim().str();
403 llvm::StringRef MacroName,
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);
420 if (MacroInfo && (Name != MacroName))
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);
464 "(not evaluated)",
"false",
"true" 467 bool operator<(
const StringHandle &H1,
const StringHandle &H2) {
468 const char *S1 = (H1 ? *H1 :
"");
469 const char *S2 = (H2 ? *H2 :
"");
470 int Diff = strcmp(S1, S2);
473 bool operator>(
const StringHandle &H1,
const StringHandle &H2) {
474 const char *S1 = (H1 ? *H1 :
"");
475 const char *S2 = (H2 ? *H2 :
"");
476 int Diff = strcmp(S1, S2);
490 PPItemKey(clang::Preprocessor &PP, StringHandle
Name, HeaderHandle File,
491 clang::SourceLocation
Loc)
492 :
Name(Name), File(File) {
495 PPItemKey(StringHandle Name, HeaderHandle File,
int Line,
int Column)
497 PPItemKey(
const PPItemKey &Other)
498 :
Name(Other.Name), File(Other.File),
Line(Other.Line),
500 PPItemKey() : File(HeaderHandleInvalid),
Line(0),
Column(0) {}
501 bool operator==(
const PPItemKey &Other)
const {
502 if (Name != Other.Name)
504 if (File != Other.File)
506 if (Line != Other.Line)
508 return Column == Other.Column;
510 bool operator<(
const PPItemKey &Other)
const {
511 if (Name < Other.Name)
513 else if (Name > Other.Name)
515 if (File < Other.File)
517 else if (File > Other.File)
519 if (Line < Other.Line)
521 else if (Line > Other.Line)
523 return Column < Other.Column;
532 class HeaderInclusionPath {
534 HeaderInclusionPath(std::vector<HeaderHandle> HeaderInclusionPath)
535 :
Path(HeaderInclusionPath) {}
536 HeaderInclusionPath(
const HeaderInclusionPath &Other) :
Path(Other.Path) {}
537 HeaderInclusionPath() {}
538 std::vector<HeaderHandle>
Path;
546 class MacroExpansionInstance {
551 InclusionPathHandle H)
556 MacroExpansionInstance() {}
560 bool haveInclusionPathHandle(InclusionPathHandle H) {
569 void addInclusionPathHandle(InclusionPathHandle H) {
570 if (!haveInclusionPathHandle(H))
590 class MacroExpansionTracker {
597 InclusionPathHandle InclusionPathHandle)
600 addMacroExpansionInstance(MacroExpanded, DefinitionLocation,
601 DefinitionSourceLine, InclusionPathHandle);
603 MacroExpansionTracker() {}
606 MacroExpansionInstance *
607 findMacroExpansionInstance(StringHandle MacroExpanded,
608 PPItemKey &DefinitionLocation) {
612 if ((I->MacroExpanded == MacroExpanded) &&
621 void addMacroExpansionInstance(StringHandle MacroExpanded,
622 PPItemKey &DefinitionLocation,
623 StringHandle DefinitionSourceLine,
624 InclusionPathHandle InclusionPathHandle) {
626 MacroExpansionInstance(MacroExpanded, DefinitionLocation,
627 DefinitionSourceLine, InclusionPathHandle));
648 class ConditionalExpansionInstance {
650 ConditionalExpansionInstance(clang::PPCallbacks::ConditionValueKind
ConditionValue, InclusionPathHandle H)
654 ConditionalExpansionInstance() {}
658 bool haveInclusionPathHandle(InclusionPathHandle H) {
667 void addInclusionPathHandle(InclusionPathHandle H) {
668 if (!haveInclusionPathHandle(H))
685 class ConditionalTracker {
690 InclusionPathHandle InclusionPathHandle)
692 addConditionalExpansionInstance(ConditionValue, InclusionPathHandle);
694 ConditionalTracker() {}
697 ConditionalExpansionInstance *
698 findConditionalExpansionInstance(clang::PPCallbacks::ConditionValueKind ConditionValue) {
702 if (I->ConditionValue == ConditionValue) {
711 addConditionalExpansionInstance(clang::PPCallbacks::ConditionValueKind ConditionValue,
712 InclusionPathHandle InclusionPathHandle) {
714 ConditionalExpansionInstance(ConditionValue, InclusionPathHandle));
730 class PreprocessorTrackerImpl;
738 class PreprocessorCallbacks :
public clang::PPCallbacks {
740 PreprocessorCallbacks(PreprocessorTrackerImpl &ppTracker,
741 clang::Preprocessor &PP, llvm::StringRef rootHeaderFile)
742 : PPTracker(ppTracker), PP(PP), RootHeaderFile(rootHeaderFile) {}
743 ~PreprocessorCallbacks()
override {}
746 void InclusionDirective(clang::SourceLocation HashLoc,
747 const clang::Token &IncludeTok,
749 clang::CharSourceRange FilenameRange,
750 const clang::FileEntry *File,
751 llvm::StringRef SearchPath,
752 llvm::StringRef RelativePath,
753 const clang::Module *Imported,
754 clang::SrcMgr::CharacteristicKind FileType)
override;
755 void FileChanged(clang::SourceLocation
Loc,
756 clang::PPCallbacks::FileChangeReason Reason,
757 clang::SrcMgr::CharacteristicKind FileType,
758 clang::FileID PrevFID = clang::FileID())
override;
759 void MacroExpands(
const clang::Token &MacroNameTok,
760 const clang::MacroDefinition &
MD, clang::SourceRange
Range,
761 const clang::MacroArgs *Args)
override;
762 void Defined(
const clang::Token &MacroNameTok,
763 const clang::MacroDefinition &
MD,
764 clang::SourceRange
Range)
override;
765 void If(clang::SourceLocation Loc, clang::SourceRange ConditionRange,
766 clang::PPCallbacks::ConditionValueKind ConditionResult)
override;
767 void Elif(clang::SourceLocation Loc, clang::SourceRange ConditionRange,
768 clang::PPCallbacks::ConditionValueKind ConditionResult,
769 clang::SourceLocation IfLoc)
override;
770 void Ifdef(clang::SourceLocation Loc,
const clang::Token &MacroNameTok,
771 const clang::MacroDefinition &
MD)
override;
772 void Ifndef(clang::SourceLocation Loc,
const clang::Token &MacroNameTok,
773 const clang::MacroDefinition &
MD)
override;
776 PreprocessorTrackerImpl &PPTracker;
777 clang::Preprocessor &PP;
778 std::string RootHeaderFile;
782 typedef std::map<PPItemKey, MacroExpansionTracker> MacroExpansionMap;
783 typedef std::map<PPItemKey, MacroExpansionTracker>::iterator
784 MacroExpansionMapIter;
787 typedef std::map<PPItemKey, ConditionalTracker> ConditionalExpansionMap;
788 typedef std::map<PPItemKey, ConditionalTracker>::iterator
789 ConditionalExpansionMapIter;
795 class PreprocessorTrackerImpl :
public PreprocessorTracker {
797 PreprocessorTrackerImpl(llvm::SmallVector<std::string, 32> &Headers,
798 bool DoBlockCheckHeaderListOnly)
800 CurrentInclusionPathHandle(InclusionPathHandleInvalid),
801 InNestedHeader(false) {
803 for (llvm::ArrayRef<std::string>::iterator I = Headers.begin(),
810 ~PreprocessorTrackerImpl()
override {}
813 void handlePreprocessorEntry(clang::Preprocessor &PP,
814 llvm::StringRef rootHeaderFile)
override {
815 HeadersInThisCompile.clear();
816 assert((HeaderStack.size() == 0) &&
"Header stack should be empty.");
817 pushHeaderHandle(addHeader(rootHeaderFile));
818 PP.addPPCallbacks(llvm::make_unique<PreprocessorCallbacks>(*
this, PP,
822 void handlePreprocessorExit()
override { HeaderStack.clear(); }
828 void handleIncludeDirective(llvm::StringRef DirectivePath,
int DirectiveLine,
830 llvm::StringRef TargetPath)
override {
835 HeaderHandle CurrentHeaderHandle = findHeaderHandle(DirectivePath);
836 StringHandle IncludeHeaderHandle = addString(TargetPath);
837 for (std::vector<PPItemKey>::const_iterator I = IncludeDirectives.begin(),
838 E = IncludeDirectives.end();
841 if ((I->File == CurrentHeaderHandle) && (I->Line == DirectiveLine))
844 PPItemKey IncludeDirectiveItem(IncludeHeaderHandle, CurrentHeaderHandle,
845 DirectiveLine, DirectiveColumn);
846 IncludeDirectives.push_back(IncludeDirectiveItem);
852 bool checkForIncludesInBlock(clang::Preprocessor &PP,
853 clang::SourceRange BlockSourceRange,
854 const char *BlockIdentifierMessage,
855 llvm::raw_ostream &OS)
override {
856 clang::SourceLocation BlockStartLoc = BlockSourceRange.getBegin();
857 clang::SourceLocation BlockEndLoc = BlockSourceRange.getEnd();
860 clang::FileID FileID = PP.getSourceManager().getFileID(BlockStartLoc);
863 HeaderHandle SourceHandle = findHeaderHandle(SourcePath);
864 if (SourceHandle == -1)
866 int BlockStartLine, BlockStartColumn, BlockEndLine, BlockEndColumn;
867 bool returnValue =
true;
872 for (std::vector<PPItemKey>::const_iterator I = IncludeDirectives.begin(),
873 E = IncludeDirectives.end();
876 if ((I->File == SourceHandle) && (I->Line >= BlockStartLine) &&
877 (I->Line < BlockEndLine)) {
879 OS << SourcePath <<
":" << I->Line <<
":" << I->Column <<
":\n";
882 OS << std::string(I->Column - 1,
' ') <<
"^\n";
883 OS <<
"error: Include directive within " << BlockIdentifierMessage
885 OS << SourcePath <<
":" << BlockStartLine <<
":" << BlockStartColumn
888 if (BlockStartColumn > 0)
889 OS << std::string(BlockStartColumn - 1,
' ') <<
"^\n";
890 OS <<
"The \"" << BlockIdentifierMessage <<
"\" block is here.\n";
897 void handleHeaderEntry(clang::Preprocessor &PP, llvm::StringRef HeaderPath) {
899 if (HeaderPath.startswith(
"<"))
901 HeaderHandle H = addHeader(HeaderPath);
902 if (H != getCurrentHeaderHandle())
906 InNestedHeader = !HeadersInThisCompile.insert(H).second;
910 void handleHeaderExit(llvm::StringRef HeaderPath) {
912 if (HeaderPath.startswith(
"<"))
914 HeaderHandle H = findHeaderHandle(HeaderPath);
916 if (isHeaderHandleInStack(H)) {
918 TH = getCurrentHeaderHandle();
920 }
while ((TH != H) && (HeaderStack.size() != 0));
922 InNestedHeader =
false;
926 StringHandle addString(llvm::StringRef Str) {
return Strings.intern(Str); }
930 std::string CanonicalPath(path);
931 std::replace(CanonicalPath.begin(), CanonicalPath.end(),
'\\',
'/');
932 return CanonicalPath;
936 bool isHeaderListHeader(llvm::StringRef HeaderPath)
const {
938 for (llvm::ArrayRef<std::string>::iterator I = HeaderList.begin(),
939 E = HeaderList.end();
941 if (*I == CanonicalPath)
949 HeaderHandle findHeaderHandle(llvm::StringRef HeaderPath)
const {
952 for (
auto I = HeaderPaths.begin(), E = HeaderPaths.end(); I != E;
954 if (**I == CanonicalPath)
962 HeaderHandle addHeader(llvm::StringRef HeaderPath) {
964 HeaderHandle H = findHeaderHandle(CanonicalPath);
965 if (H == HeaderHandleInvalid) {
966 H = HeaderPaths.size();
967 HeaderPaths.push_back(addString(CanonicalPath));
973 StringHandle getHeaderFilePath(HeaderHandle H)
const {
974 if ((H >= 0) && (H < (HeaderHandle)HeaderPaths.size()))
975 return HeaderPaths[H];
980 InclusionPathHandle pushHeaderHandle(HeaderHandle H) {
981 HeaderStack.push_back(H);
982 return CurrentInclusionPathHandle = addInclusionPathHandle(HeaderStack);
985 void popHeaderHandle() {
987 if (HeaderStack.size() != 0) {
988 HeaderStack.pop_back();
989 CurrentInclusionPathHandle = addInclusionPathHandle(HeaderStack);
993 HeaderHandle getCurrentHeaderHandle()
const {
994 if (HeaderStack.size() != 0)
995 return HeaderStack.back();
1000 bool isHeaderHandleInStack(HeaderHandle H)
const {
1001 for (
auto I = HeaderStack.begin(), E = HeaderStack.end(); I != E; ++I) {
1011 findInclusionPathHandle(
const std::vector<HeaderHandle> &
Path)
const {
1012 InclusionPathHandle H = 0;
1013 for (
auto I = InclusionPaths.begin(), E = InclusionPaths.end(); I != E;
1015 if (I->Path == Path)
1023 addInclusionPathHandle(
const std::vector<HeaderHandle> &Path) {
1024 InclusionPathHandle H = findInclusionPathHandle(Path);
1025 if (H == HeaderHandleInvalid) {
1026 H = InclusionPaths.size();
1027 InclusionPaths.push_back(HeaderInclusionPath(Path));
1032 InclusionPathHandle getCurrentInclusionPathHandle()
const {
1033 return CurrentInclusionPathHandle;
1037 const std::vector<HeaderHandle> &
1038 getInclusionPath(InclusionPathHandle H)
const {
1039 if ((H >= 0) && (H <= (InclusionPathHandle)InclusionPaths.size()))
1040 return InclusionPaths[H].Path;
1041 static std::vector<HeaderHandle>
Empty;
1046 void addMacroExpansionInstance(clang::Preprocessor &PP, HeaderHandle H,
1047 clang::SourceLocation InstanceLoc,
1048 clang::SourceLocation DefinitionLoc,
1049 clang::IdentifierInfo *II,
1052 InclusionPathHandle InclusionPathHandle) {
1055 StringHandle MacroName = addString(II->getName());
1056 PPItemKey InstanceKey(PP, MacroName, H, InstanceLoc);
1057 PPItemKey DefinitionKey(PP, MacroName, H, DefinitionLoc);
1058 auto I = MacroExpansions.find(InstanceKey);
1060 if (I == MacroExpansions.end()) {
1067 MacroExpansions[InstanceKey] = MacroExpansionTracker(
1068 addString(MacroUnexpanded), addString(MacroExpanded),
1069 addString(InstanceSourceLine), DefinitionKey,
1070 addString(DefinitionSourceLine), InclusionPathHandle);
1073 MacroExpansionTracker &CondTracker = I->second;
1075 MacroExpansionInstance *MacroInfo =
1076 CondTracker.findMacroExpansionInstance(addString(MacroExpanded),
1080 MacroInfo->addInclusionPathHandle(InclusionPathHandle);
1083 std::string DefinitionSourceLine =
1086 CondTracker.addMacroExpansionInstance(
1087 addString(MacroExpanded), DefinitionKey,
1088 addString(DefinitionSourceLine), InclusionPathHandle);
1095 addConditionalExpansionInstance(clang::Preprocessor &PP, HeaderHandle H,
1096 clang::SourceLocation InstanceLoc,
1100 InclusionPathHandle InclusionPathHandle) {
1104 StringHandle ConditionUnexpandedHandle(addString(ConditionUnexpanded));
1105 PPItemKey InstanceKey(PP, ConditionUnexpandedHandle, H, InstanceLoc);
1106 auto I = ConditionalExpansions.find(InstanceKey);
1108 if (I == ConditionalExpansions.end()) {
1109 std::string InstanceSourceLine =
1112 ConditionalExpansions[InstanceKey] =
1113 ConditionalTracker(DirectiveKind, ConditionValue,
1114 ConditionUnexpandedHandle, InclusionPathHandle);
1117 ConditionalTracker &CondTracker = I->second;
1119 ConditionalExpansionInstance *MacroInfo =
1120 CondTracker.findConditionalExpansionInstance(ConditionValue);
1123 MacroInfo->addInclusionPathHandle(InclusionPathHandle);
1126 CondTracker.addConditionalExpansionInstance(ConditionValue,
1127 InclusionPathHandle);
1134 bool reportInconsistentMacros(llvm::raw_ostream &OS)
override {
1135 bool ReturnValue =
false;
1137 for (
auto I = MacroExpansions.begin(), E = MacroExpansions.end(); I != E;
1139 const PPItemKey &ItemKey = I->first;
1140 MacroExpansionTracker &MacroExpTracker = I->second;
1142 if (!MacroExpTracker.hasMismatch())
1147 OS << *MacroExpTracker.InstanceSourceLine;
1148 if (ItemKey.Column > 0)
1149 OS << std::string(ItemKey.Column - 1,
' ') <<
"^\n";
1150 OS <<
"error: Macro instance '" << *MacroExpTracker.MacroUnexpanded
1151 <<
"' has different values in this header, depending on how it was " 1154 for (
auto IMT = MacroExpTracker.MacroExpansionInstances.begin(),
1155 EMT = MacroExpTracker.MacroExpansionInstances.end();
1156 IMT != EMT; ++IMT) {
1157 MacroExpansionInstance &MacroInfo = *IMT;
1158 OS <<
" '" << *MacroExpTracker.MacroUnexpanded <<
"' expanded to: '" 1159 << *MacroInfo.MacroExpanded
1160 <<
"' with respect to these inclusion paths:\n";
1162 for (
auto IIP = MacroInfo.InclusionPathHandles.begin(),
1163 EIP = MacroInfo.InclusionPathHandles.end();
1164 IIP != EIP; ++IIP) {
1165 const std::vector<HeaderHandle> &ip = getInclusionPath(*IIP);
1166 auto Count = (int)ip.size();
1168 HeaderHandle H = ip[
Index];
1169 OS << std::string((
Index * 2) + 4,
' ') << *getHeaderFilePath(H)
1176 if (MacroInfo.DefinitionLocation.Line != ItemKey.Line) {
1177 OS << *MacroInfo.DefinitionSourceLine;
1178 if (MacroInfo.DefinitionLocation.Column > 0)
1179 OS << std::string(MacroInfo.DefinitionLocation.Column - 1,
' ')
1181 OS <<
"Macro defined here.\n";
1183 OS <<
"(no macro definition)" 1192 bool reportInconsistentConditionals(llvm::raw_ostream &OS)
override {
1193 bool ReturnValue =
false;
1195 for (
auto I = ConditionalExpansions.begin(),
1196 E = ConditionalExpansions.end();
1198 const PPItemKey &ItemKey = I->first;
1199 ConditionalTracker &CondTracker = I->second;
1200 if (!CondTracker.hasMismatch())
1205 OS << *HeaderPaths[ItemKey.File] <<
":" << ItemKey.Line <<
":" 1206 << ItemKey.Column <<
"\n";
1207 OS <<
"#" << getDirectiveSpelling(CondTracker.DirectiveKind) <<
" " 1208 << *CondTracker.ConditionUnexpanded <<
"\n";
1210 OS <<
"error: Conditional expression instance '" 1211 << *CondTracker.ConditionUnexpanded
1212 <<
"' has different values in this header, depending on how it was " 1215 for (
auto IMT = CondTracker.ConditionalExpansionInstances.begin(),
1216 EMT = CondTracker.ConditionalExpansionInstances.end();
1217 IMT != EMT; ++IMT) {
1218 ConditionalExpansionInstance &MacroInfo = *IMT;
1219 OS <<
" '" << *CondTracker.ConditionUnexpanded <<
"' expanded to: '" 1220 << ConditionValueKindStrings[MacroInfo.ConditionValue]
1221 <<
"' with respect to these inclusion paths:\n";
1223 for (
auto IIP = MacroInfo.InclusionPathHandles.begin(),
1224 EIP = MacroInfo.InclusionPathHandles.end();
1225 IIP != EIP; ++IIP) {
1226 const std::vector<HeaderHandle> &ip = getInclusionPath(*IIP);
1227 auto Count = (int)ip.size();
1229 HeaderHandle H = ip[
Index];
1230 OS << std::string((
Index * 2) + 4,
' ') << *getHeaderFilePath(H)
1240 static const char *getDirectiveSpelling(clang::tok::PPKeywordKind kind) {
1242 case clang::tok::pp_if:
1244 case clang::tok::pp_elif:
1246 case clang::tok::pp_ifdef:
1248 case clang::tok::pp_ifndef:
1256 llvm::SmallVector<std::string, 32> HeaderList;
1260 std::vector<StringHandle> HeaderPaths;
1261 std::vector<HeaderHandle> HeaderStack;
1262 std::vector<HeaderInclusionPath> InclusionPaths;
1263 InclusionPathHandle CurrentInclusionPathHandle;
1264 llvm::SmallSet<HeaderHandle, 32> HeadersInThisCompile;
1265 std::vector<PPItemKey> IncludeDirectives;
1266 MacroExpansionMap MacroExpansions;
1267 ConditionalExpansionMap ConditionalExpansions;
1268 bool InNestedHeader;
1280 llvm::SmallVector<std::string, 32> &Headers,
1281 bool DoBlockCheckHeaderListOnly) {
1282 return new PreprocessorTrackerImpl(Headers, DoBlockCheckHeaderListOnly);
1288 void PreprocessorCallbacks::InclusionDirective(
1289 clang::SourceLocation HashLoc,
const clang::Token &IncludeTok,
1291 clang::CharSourceRange FilenameRange,
const clang::FileEntry *File,
1292 llvm::StringRef SearchPath, llvm::StringRef RelativePath,
1293 const clang::Module *Imported, clang::SrcMgr::CharacteristicKind FileType) {
1294 int DirectiveLine, DirectiveColumn;
1297 PPTracker.handleIncludeDirective(HeaderPath, DirectiveLine, DirectiveColumn,
1302 void PreprocessorCallbacks::FileChanged(
1303 clang::SourceLocation
Loc, clang::PPCallbacks::FileChangeReason Reason,
1304 clang::SrcMgr::CharacteristicKind FileType, clang::FileID PrevFID) {
1310 const clang::FileEntry *F =
1311 PP.getSourceManager().getFileEntryForID(PrevFID);
1313 PPTracker.handleHeaderExit(F->getName());
1315 case SystemHeaderPragma:
1322 void PreprocessorCallbacks::MacroExpands(
const clang::Token &MacroNameTok,
1323 const clang::MacroDefinition &
MD,
1324 clang::SourceRange
Range,
1325 const clang::MacroArgs *Args) {
1326 clang::SourceLocation Loc = Range.getBegin();
1328 if (!Loc.isFileID())
1330 clang::IdentifierInfo *II = MacroNameTok.getIdentifierInfo();
1331 const clang::MacroInfo *MI = MD.getMacroInfo();
1332 std::string MacroName = II->getName().str();
1335 PPTracker.addMacroExpansionInstance(
1336 PP, PPTracker.getCurrentHeaderHandle(),
Loc, MI->getDefinitionLoc(), II,
1337 Unexpanded, Expanded, PPTracker.getCurrentInclusionPathHandle());
1340 void PreprocessorCallbacks::Defined(
const clang::Token &MacroNameTok,
1341 const clang::MacroDefinition &MD,
1342 clang::SourceRange Range) {
1343 clang::SourceLocation
Loc(Range.getBegin());
1344 clang::IdentifierInfo *II = MacroNameTok.getIdentifierInfo();
1345 const clang::MacroInfo *MI = MD.getMacroInfo();
1346 std::string MacroName = II->getName().str();
1348 PPTracker.addMacroExpansionInstance(
1349 PP, PPTracker.getCurrentHeaderHandle(),
Loc,
1350 (MI ? MI->getDefinitionLoc() :
Loc), II, Unexpanded,
1351 (MI ?
"true" :
"false"), PPTracker.getCurrentInclusionPathHandle());
1354 void PreprocessorCallbacks::If(clang::SourceLocation Loc,
1355 clang::SourceRange ConditionRange,
1356 clang::PPCallbacks::ConditionValueKind ConditionResult) {
1358 PPTracker.addConditionalExpansionInstance(
1359 PP, PPTracker.getCurrentHeaderHandle(),
Loc, clang::tok::pp_if,
1360 ConditionResult, Unexpanded, PPTracker.getCurrentInclusionPathHandle());
1363 void PreprocessorCallbacks::Elif(clang::SourceLocation Loc,
1364 clang::SourceRange ConditionRange,
1365 clang::PPCallbacks::ConditionValueKind ConditionResult,
1366 clang::SourceLocation IfLoc) {
1368 PPTracker.addConditionalExpansionInstance(
1369 PP, PPTracker.getCurrentHeaderHandle(),
Loc, clang::tok::pp_elif,
1370 ConditionResult, Unexpanded, PPTracker.getCurrentInclusionPathHandle());
1373 void PreprocessorCallbacks::Ifdef(clang::SourceLocation Loc,
1374 const clang::Token &MacroNameTok,
1375 const clang::MacroDefinition &MD) {
1376 clang::PPCallbacks::ConditionValueKind IsDefined =
1377 (MD ? clang::PPCallbacks::CVK_True : clang::PPCallbacks::CVK_False );
1378 PPTracker.addConditionalExpansionInstance(
1379 PP, PPTracker.getCurrentHeaderHandle(),
Loc, clang::tok::pp_ifdef,
1380 IsDefined, PP.getSpelling(MacroNameTok),
1381 PPTracker.getCurrentInclusionPathHandle());
1384 void PreprocessorCallbacks::Ifndef(clang::SourceLocation Loc,
1385 const clang::Token &MacroNameTok,
1386 const clang::MacroDefinition &MD) {
1387 clang::PPCallbacks::ConditionValueKind IsNotDefined =
1388 (!MD ? clang::PPCallbacks::CVK_True : clang::PPCallbacks::CVK_False );
1389 PPTracker.addConditionalExpansionInstance(
1390 PP, PPTracker.getCurrentHeaderHandle(),
Loc, clang::tok::pp_ifndef,
1391 IsNotDefined, PP.getSpelling(MacroNameTok),
1392 PPTracker.getCurrentInclusionPathHandle());
StringHandle DefinitionSourceLine
SourceLocation Loc
'#' location in the include directive
StringHandle InstanceSourceLine
static std::string getCanonicalPath(llvm::StringRef FilePath)
Convert header path to canonical form.
static std::string getSourceString(clang::Preprocessor &PP, clang::SourceRange Range)
bool operator==(const SymbolLocation::Position &L, const SymbolLocation::Position &R)
static void getSourceLocationLineAndColumn(clang::Preprocessor &PP, clang::SourceLocation Loc, int &Line, int &Column)
virtual ~PreprocessorTracker()
const HeaderHandle HeaderHandleInvalid
std::vector< HeaderHandle > Path
static std::string getSourceLocationFile(clang::Preprocessor &PP, clang::SourceLocation Loc)
ModularizeUtilities class definition.
static std::string getMacroUnexpandedString(clang::SourceRange Range, clang::Preprocessor &PP, llvm::StringRef MacroName, const clang::MacroInfo *MI)
clang::tok::PPKeywordKind DirectiveKind
bool operator<(const SymbolLocation::Position &L, const SymbolLocation::Position &R)
StringHandle MacroUnexpanded
static cl::opt< bool > BlockCheckHeaderListOnly("block-check-header-list-only", cl::init(false), cl::desc("Only warn if #include directives are inside extern or namespace" " blocks if the included header is in the header list."))
const InclusionPathHandle InclusionPathHandleInvalid
StringHandle MacroExpanded
std::vector< MacroExpansionInstance > MacroExpansionInstances
bool IsAngled
true if this was an include with angle brackets
static std::string getSourceLine(clang::Preprocessor &PP, clang::SourceLocation Loc)
StringHandle ConditionUnexpanded
std::vector< InclusionPathHandle > InclusionPathHandles
clang::PPCallbacks::ConditionValueKind ConditionValue
std::vector< llvm::StringRef > Strings
static PreprocessorTracker * create(llvm::SmallVector< std::string, 32 > &Headers, bool DoBlockCheckHeaderListOnly)
PPItemKey DefinitionLocation
static const char *const ConditionValueKindStrings[]
static GeneratorRegistry::Add< MDGenerator > MD(MDGenerator::Format, "Generator for MD output.")
CharSourceRange Range
SourceRange for the file name.
llvm::Optional< std::string > getCanonicalPath(const FileEntry *F, const SourceManager &SourceMgr)
Get the canonical path of F.
Macro expansions and preprocessor conditional consistency checker.
static std::string getSourceLocationString(clang::Preprocessor &PP, clang::SourceLocation Loc)
static std::string getMacroExpandedString(clang::Preprocessor &PP, llvm::StringRef MacroName, const clang::MacroInfo *MI, const clang::MacroArgs *Args)
Preprocessor tracker for modularize.
std::vector< ConditionalExpansionInstance > ConditionalExpansionInstances
const SymbolIndex * Index
llvm::PooledStringPtr StringHandle