246 #include "clang/Lex/LexDiagnostic.h" 248 #include "clang/Lex/MacroArgs.h" 249 #include "clang/Lex/PPCallbacks.h" 250 #include "llvm/ADT/SmallSet.h" 251 #include "llvm/Support/StringPool.h" 252 #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 const llvm::MemoryBuffer *MemBuffer =
316 PP.getSourceManager().getBuffer(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();
339 static std::string
getSourceLine(clang::Preprocessor &PP, clang::FileID FileID,
341 const llvm::MemoryBuffer *MemBuffer = PP.getSourceManager().getBuffer(FileID);
342 const char *Buffer = MemBuffer->getBufferStart();
343 const char *BufferEnd = MemBuffer->getBufferEnd();
344 const char *BeginPtr = Buffer;
345 const char *EndPtr = BufferEnd;
350 while (Buffer < BufferEnd) {
351 if (*Buffer ==
'\n') {
352 if (++LineCounter == Line) {
353 BeginPtr = Buffer++ + 1;
360 while (Buffer < BufferEnd) {
361 if (*Buffer ==
'\n') {
367 size_t Length = EndPtr - BeginPtr;
368 return llvm::StringRef(BeginPtr, Length).str();
377 clang::Preprocessor &PP,
378 llvm::StringRef MacroName,
379 const clang::MacroInfo *MI) {
380 clang::SourceLocation BeginLoc(Range.getBegin());
381 const char *BeginPtr = PP.getSourceManager().getCharacterData(BeginLoc);
383 std::string Unexpanded;
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);
463 "(not evaluated)",
"false",
"true" 466 bool operator<(
const StringHandle &H1,
const StringHandle &H2) {
467 const char *S1 = (H1 ? *H1 :
"");
468 const char *S2 = (H2 ? *H2 :
"");
469 int Diff = strcmp(S1, S2);
472 bool operator>(
const StringHandle &H1,
const StringHandle &H2) {
473 const char *S1 = (H1 ? *H1 :
"");
474 const char *S2 = (H2 ? *H2 :
"");
475 int Diff = strcmp(S1, S2);
489 PPItemKey(clang::Preprocessor &PP, StringHandle
Name, HeaderHandle File,
490 clang::SourceLocation
Loc)
491 :
Name(Name), File(File) {
494 PPItemKey(StringHandle Name, HeaderHandle File,
int Line,
int Column)
496 PPItemKey(
const PPItemKey &Other)
497 :
Name(Other.Name), File(Other.File),
Line(Other.Line),
499 PPItemKey() : File(HeaderHandleInvalid),
Line(0),
Column(0) {}
500 bool operator==(
const PPItemKey &Other)
const {
501 if (Name != Other.Name)
503 if (File != Other.File)
505 if (Line != Other.Line)
507 return Column == Other.Column;
509 bool operator<(
const PPItemKey &Other)
const {
510 if (Name < Other.Name)
512 else if (Name > Other.Name)
514 if (File < Other.File)
516 else if (File > Other.File)
518 if (Line < Other.Line)
520 else if (Line > Other.Line)
522 return Column < Other.Column;
531 class HeaderInclusionPath {
533 HeaderInclusionPath(std::vector<HeaderHandle> HeaderInclusionPath)
534 :
Path(HeaderInclusionPath) {}
535 HeaderInclusionPath(
const HeaderInclusionPath &Other) :
Path(Other.Path) {}
536 HeaderInclusionPath() {}
537 std::vector<HeaderHandle>
Path;
545 class MacroExpansionInstance {
550 InclusionPathHandle H)
555 MacroExpansionInstance() {}
559 bool haveInclusionPathHandle(InclusionPathHandle H) {
568 void addInclusionPathHandle(InclusionPathHandle H) {
569 if (!haveInclusionPathHandle(H))
589 class MacroExpansionTracker {
596 InclusionPathHandle InclusionPathHandle)
599 addMacroExpansionInstance(MacroExpanded, DefinitionLocation,
600 DefinitionSourceLine, InclusionPathHandle);
602 MacroExpansionTracker() {}
605 MacroExpansionInstance *
606 findMacroExpansionInstance(StringHandle MacroExpanded,
607 PPItemKey &DefinitionLocation) {
611 if ((I->MacroExpanded == MacroExpanded) &&
620 void addMacroExpansionInstance(StringHandle MacroExpanded,
621 PPItemKey &DefinitionLocation,
622 StringHandle DefinitionSourceLine,
623 InclusionPathHandle InclusionPathHandle) {
625 MacroExpansionInstance(MacroExpanded, DefinitionLocation,
626 DefinitionSourceLine, InclusionPathHandle));
647 class ConditionalExpansionInstance {
649 ConditionalExpansionInstance(clang::PPCallbacks::ConditionValueKind
ConditionValue, InclusionPathHandle H)
653 ConditionalExpansionInstance() {}
657 bool haveInclusionPathHandle(InclusionPathHandle H) {
666 void addInclusionPathHandle(InclusionPathHandle H) {
667 if (!haveInclusionPathHandle(H))
684 class ConditionalTracker {
689 InclusionPathHandle InclusionPathHandle)
691 addConditionalExpansionInstance(ConditionValue, InclusionPathHandle);
693 ConditionalTracker() {}
696 ConditionalExpansionInstance *
697 findConditionalExpansionInstance(clang::PPCallbacks::ConditionValueKind ConditionValue) {
701 if (I->ConditionValue == ConditionValue) {
710 addConditionalExpansionInstance(clang::PPCallbacks::ConditionValueKind ConditionValue,
711 InclusionPathHandle InclusionPathHandle) {
713 ConditionalExpansionInstance(ConditionValue, InclusionPathHandle));
729 class PreprocessorTrackerImpl;
737 class PreprocessorCallbacks :
public clang::PPCallbacks {
739 PreprocessorCallbacks(PreprocessorTrackerImpl &ppTracker,
740 clang::Preprocessor &PP, llvm::StringRef rootHeaderFile)
741 : PPTracker(ppTracker), PP(PP), RootHeaderFile(rootHeaderFile) {}
742 ~PreprocessorCallbacks()
override {}
745 void InclusionDirective(clang::SourceLocation HashLoc,
746 const clang::Token &IncludeTok,
748 clang::CharSourceRange FilenameRange,
749 const clang::FileEntry *File,
750 llvm::StringRef SearchPath,
751 llvm::StringRef RelativePath,
752 const clang::Module *Imported,
753 clang::SrcMgr::CharacteristicKind FileType)
override;
754 void FileChanged(clang::SourceLocation
Loc,
755 clang::PPCallbacks::FileChangeReason Reason,
756 clang::SrcMgr::CharacteristicKind FileType,
757 clang::FileID PrevFID = clang::FileID())
override;
758 void MacroExpands(
const clang::Token &MacroNameTok,
759 const clang::MacroDefinition &
MD, clang::SourceRange
Range,
760 const clang::MacroArgs *Args)
override;
761 void Defined(
const clang::Token &MacroNameTok,
762 const clang::MacroDefinition &
MD,
763 clang::SourceRange
Range)
override;
764 void If(clang::SourceLocation Loc, clang::SourceRange ConditionRange,
765 clang::PPCallbacks::ConditionValueKind ConditionResult)
override;
766 void Elif(clang::SourceLocation Loc, clang::SourceRange ConditionRange,
767 clang::PPCallbacks::ConditionValueKind ConditionResult,
768 clang::SourceLocation IfLoc)
override;
769 void Ifdef(clang::SourceLocation Loc,
const clang::Token &MacroNameTok,
770 const clang::MacroDefinition &
MD)
override;
771 void Ifndef(clang::SourceLocation Loc,
const clang::Token &MacroNameTok,
772 const clang::MacroDefinition &
MD)
override;
775 PreprocessorTrackerImpl &PPTracker;
776 clang::Preprocessor &PP;
777 std::string RootHeaderFile;
781 typedef std::map<PPItemKey, MacroExpansionTracker> MacroExpansionMap;
782 typedef std::map<PPItemKey, MacroExpansionTracker>::iterator
783 MacroExpansionMapIter;
786 typedef std::map<PPItemKey, ConditionalTracker> ConditionalExpansionMap;
787 typedef std::map<PPItemKey, ConditionalTracker>::iterator
788 ConditionalExpansionMapIter;
794 class PreprocessorTrackerImpl :
public PreprocessorTracker {
796 PreprocessorTrackerImpl(llvm::SmallVector<std::string, 32> &Headers,
797 bool DoBlockCheckHeaderListOnly)
799 CurrentInclusionPathHandle(InclusionPathHandleInvalid),
800 InNestedHeader(false) {
802 for (llvm::ArrayRef<std::string>::iterator I = Headers.begin(),
809 ~PreprocessorTrackerImpl()
override {}
812 void handlePreprocessorEntry(clang::Preprocessor &PP,
813 llvm::StringRef rootHeaderFile)
override {
814 HeadersInThisCompile.clear();
815 assert((HeaderStack.size() == 0) &&
"Header stack should be empty.");
816 pushHeaderHandle(addHeader(rootHeaderFile));
817 PP.addPPCallbacks(llvm::make_unique<PreprocessorCallbacks>(*
this, PP,
821 void handlePreprocessorExit()
override { HeaderStack.clear(); }
827 void handleIncludeDirective(llvm::StringRef DirectivePath,
int DirectiveLine,
829 llvm::StringRef TargetPath)
override {
834 HeaderHandle CurrentHeaderHandle = findHeaderHandle(DirectivePath);
835 StringHandle IncludeHeaderHandle = addString(TargetPath);
836 for (std::vector<PPItemKey>::const_iterator I = IncludeDirectives.begin(),
837 E = IncludeDirectives.end();
840 if ((I->File == CurrentHeaderHandle) && (I->Line == DirectiveLine))
843 PPItemKey IncludeDirectiveItem(IncludeHeaderHandle, CurrentHeaderHandle,
844 DirectiveLine, DirectiveColumn);
845 IncludeDirectives.push_back(IncludeDirectiveItem);
851 bool checkForIncludesInBlock(clang::Preprocessor &PP,
852 clang::SourceRange BlockSourceRange,
853 const char *BlockIdentifierMessage,
854 llvm::raw_ostream &OS)
override {
855 clang::SourceLocation BlockStartLoc = BlockSourceRange.getBegin();
856 clang::SourceLocation BlockEndLoc = BlockSourceRange.getEnd();
859 clang::FileID FileID = PP.getSourceManager().getFileID(BlockStartLoc);
862 HeaderHandle SourceHandle = findHeaderHandle(SourcePath);
863 if (SourceHandle == -1)
865 int BlockStartLine, BlockStartColumn, BlockEndLine, BlockEndColumn;
866 bool returnValue =
true;
871 for (std::vector<PPItemKey>::const_iterator I = IncludeDirectives.begin(),
872 E = IncludeDirectives.end();
875 if ((I->File == SourceHandle) && (I->Line >= BlockStartLine) &&
876 (I->Line < BlockEndLine)) {
878 OS << SourcePath <<
":" << I->Line <<
":" << I->Column <<
":\n";
881 OS << std::string(I->Column - 1,
' ') <<
"^\n";
882 OS <<
"error: Include directive within " << BlockIdentifierMessage
884 OS << SourcePath <<
":" << BlockStartLine <<
":" << BlockStartColumn
887 if (BlockStartColumn > 0)
888 OS << std::string(BlockStartColumn - 1,
' ') <<
"^\n";
889 OS <<
"The \"" << BlockIdentifierMessage <<
"\" block is here.\n";
896 void handleHeaderEntry(clang::Preprocessor &PP, llvm::StringRef HeaderPath) {
898 if (HeaderPath.startswith(
"<"))
900 HeaderHandle H = addHeader(HeaderPath);
901 if (H != getCurrentHeaderHandle())
905 InNestedHeader = !HeadersInThisCompile.insert(H).second;
909 void handleHeaderExit(llvm::StringRef HeaderPath) {
911 if (HeaderPath.startswith(
"<"))
913 HeaderHandle H = findHeaderHandle(HeaderPath);
915 if (isHeaderHandleInStack(H)) {
917 TH = getCurrentHeaderHandle();
919 }
while ((TH != H) && (HeaderStack.size() != 0));
921 InNestedHeader =
false;
925 StringHandle addString(llvm::StringRef Str) {
return Strings.intern(Str); }
929 std::string CanonicalPath(path);
930 std::replace(CanonicalPath.begin(), CanonicalPath.end(),
'\\',
'/');
931 return CanonicalPath;
935 bool isHeaderListHeader(llvm::StringRef HeaderPath)
const {
937 for (llvm::ArrayRef<std::string>::iterator I = HeaderList.begin(),
938 E = HeaderList.end();
940 if (*I == CanonicalPath)
948 HeaderHandle findHeaderHandle(llvm::StringRef HeaderPath)
const {
951 for (
auto I = HeaderPaths.begin(), E = HeaderPaths.end(); I != E;
953 if (**I == CanonicalPath)
961 HeaderHandle addHeader(llvm::StringRef HeaderPath) {
963 HeaderHandle H = findHeaderHandle(CanonicalPath);
964 if (H == HeaderHandleInvalid) {
965 H = HeaderPaths.size();
966 HeaderPaths.push_back(addString(CanonicalPath));
972 StringHandle getHeaderFilePath(HeaderHandle H)
const {
973 if ((H >= 0) && (H < (HeaderHandle)HeaderPaths.size()))
974 return HeaderPaths[H];
979 InclusionPathHandle pushHeaderHandle(HeaderHandle H) {
980 HeaderStack.push_back(H);
981 return CurrentInclusionPathHandle = addInclusionPathHandle(HeaderStack);
984 void popHeaderHandle() {
986 if (HeaderStack.size() != 0) {
987 HeaderStack.pop_back();
988 CurrentInclusionPathHandle = addInclusionPathHandle(HeaderStack);
992 HeaderHandle getCurrentHeaderHandle()
const {
993 if (HeaderStack.size() != 0)
994 return HeaderStack.back();
999 bool isHeaderHandleInStack(HeaderHandle H)
const {
1000 for (
auto I = HeaderStack.begin(), E = HeaderStack.end(); I != E; ++I) {
1010 findInclusionPathHandle(
const std::vector<HeaderHandle> &
Path)
const {
1011 InclusionPathHandle H = 0;
1012 for (
auto I = InclusionPaths.begin(), E = InclusionPaths.end(); I != E;
1014 if (I->Path == Path)
1022 addInclusionPathHandle(
const std::vector<HeaderHandle> &Path) {
1023 InclusionPathHandle H = findInclusionPathHandle(Path);
1024 if (H == HeaderHandleInvalid) {
1025 H = InclusionPaths.size();
1026 InclusionPaths.push_back(HeaderInclusionPath(Path));
1031 InclusionPathHandle getCurrentInclusionPathHandle()
const {
1032 return CurrentInclusionPathHandle;
1036 const std::vector<HeaderHandle> &
1037 getInclusionPath(InclusionPathHandle H)
const {
1038 if ((H >= 0) && (H <= (InclusionPathHandle)InclusionPaths.size()))
1039 return InclusionPaths[H].Path;
1040 static std::vector<HeaderHandle>
Empty;
1045 void addMacroExpansionInstance(clang::Preprocessor &PP, HeaderHandle H,
1046 clang::SourceLocation InstanceLoc,
1047 clang::SourceLocation DefinitionLoc,
1048 clang::IdentifierInfo *II,
1051 InclusionPathHandle InclusionPathHandle) {
1054 StringHandle MacroName = addString(II->getName());
1055 PPItemKey InstanceKey(PP, MacroName, H, InstanceLoc);
1056 PPItemKey DefinitionKey(PP, MacroName, H, DefinitionLoc);
1057 auto I = MacroExpansions.find(InstanceKey);
1059 if (I == MacroExpansions.end()) {
1066 MacroExpansions[InstanceKey] = MacroExpansionTracker(
1067 addString(MacroUnexpanded), addString(MacroExpanded),
1068 addString(InstanceSourceLine), DefinitionKey,
1069 addString(DefinitionSourceLine), InclusionPathHandle);
1072 MacroExpansionTracker &CondTracker = I->second;
1074 MacroExpansionInstance *MacroInfo =
1075 CondTracker.findMacroExpansionInstance(addString(MacroExpanded),
1079 MacroInfo->addInclusionPathHandle(InclusionPathHandle);
1082 std::string DefinitionSourceLine =
1085 CondTracker.addMacroExpansionInstance(
1086 addString(MacroExpanded), DefinitionKey,
1087 addString(DefinitionSourceLine), InclusionPathHandle);
1094 addConditionalExpansionInstance(clang::Preprocessor &PP, HeaderHandle H,
1095 clang::SourceLocation InstanceLoc,
1099 InclusionPathHandle InclusionPathHandle) {
1103 StringHandle ConditionUnexpandedHandle(addString(ConditionUnexpanded));
1104 PPItemKey InstanceKey(PP, ConditionUnexpandedHandle, H, InstanceLoc);
1105 auto I = ConditionalExpansions.find(InstanceKey);
1107 if (I == ConditionalExpansions.end()) {
1108 std::string InstanceSourceLine =
1111 ConditionalExpansions[InstanceKey] =
1112 ConditionalTracker(DirectiveKind, ConditionValue,
1113 ConditionUnexpandedHandle, InclusionPathHandle);
1116 ConditionalTracker &CondTracker = I->second;
1118 ConditionalExpansionInstance *MacroInfo =
1119 CondTracker.findConditionalExpansionInstance(ConditionValue);
1122 MacroInfo->addInclusionPathHandle(InclusionPathHandle);
1125 CondTracker.addConditionalExpansionInstance(ConditionValue,
1126 InclusionPathHandle);
1133 bool reportInconsistentMacros(llvm::raw_ostream &OS)
override {
1134 bool ReturnValue =
false;
1136 for (
auto I = MacroExpansions.begin(), E = MacroExpansions.end(); I != E;
1138 const PPItemKey &ItemKey = I->first;
1139 MacroExpansionTracker &MacroExpTracker = I->second;
1141 if (!MacroExpTracker.hasMismatch())
1146 OS << *MacroExpTracker.InstanceSourceLine;
1147 if (ItemKey.Column > 0)
1148 OS << std::string(ItemKey.Column - 1,
' ') <<
"^\n";
1149 OS <<
"error: Macro instance '" << *MacroExpTracker.MacroUnexpanded
1150 <<
"' has different values in this header, depending on how it was " 1153 for (
auto IMT = MacroExpTracker.MacroExpansionInstances.begin(),
1154 EMT = MacroExpTracker.MacroExpansionInstances.end();
1155 IMT != EMT; ++IMT) {
1156 MacroExpansionInstance &MacroInfo = *IMT;
1157 OS <<
" '" << *MacroExpTracker.MacroUnexpanded <<
"' expanded to: '" 1158 << *MacroInfo.MacroExpanded
1159 <<
"' with respect to these inclusion paths:\n";
1161 for (
auto IIP = MacroInfo.InclusionPathHandles.begin(),
1162 EIP = MacroInfo.InclusionPathHandles.end();
1163 IIP != EIP; ++IIP) {
1164 const std::vector<HeaderHandle> &ip = getInclusionPath(*IIP);
1165 auto Count = (int)ip.size();
1167 HeaderHandle H = ip[
Index];
1168 OS << std::string((
Index * 2) + 4,
' ') << *getHeaderFilePath(H)
1175 if (MacroInfo.DefinitionLocation.Line != ItemKey.Line) {
1176 OS << *MacroInfo.DefinitionSourceLine;
1177 if (MacroInfo.DefinitionLocation.Column > 0)
1178 OS << std::string(MacroInfo.DefinitionLocation.Column - 1,
' ')
1180 OS <<
"Macro defined here.\n";
1182 OS <<
"(no macro definition)" 1191 bool reportInconsistentConditionals(llvm::raw_ostream &OS)
override {
1192 bool ReturnValue =
false;
1194 for (
auto I = ConditionalExpansions.begin(),
1195 E = ConditionalExpansions.end();
1197 const PPItemKey &ItemKey = I->first;
1198 ConditionalTracker &CondTracker = I->second;
1199 if (!CondTracker.hasMismatch())
1204 OS << *HeaderPaths[ItemKey.File] <<
":" << ItemKey.Line <<
":" 1205 << ItemKey.Column <<
"\n";
1206 OS <<
"#" << getDirectiveSpelling(CondTracker.DirectiveKind) <<
" " 1207 << *CondTracker.ConditionUnexpanded <<
"\n";
1209 OS <<
"error: Conditional expression instance '" 1210 << *CondTracker.ConditionUnexpanded
1211 <<
"' has different values in this header, depending on how it was " 1214 for (
auto IMT = CondTracker.ConditionalExpansionInstances.begin(),
1215 EMT = CondTracker.ConditionalExpansionInstances.end();
1216 IMT != EMT; ++IMT) {
1217 ConditionalExpansionInstance &MacroInfo = *IMT;
1218 OS <<
" '" << *CondTracker.ConditionUnexpanded <<
"' expanded to: '" 1219 << ConditionValueKindStrings[MacroInfo.ConditionValue]
1220 <<
"' with respect to these inclusion paths:\n";
1222 for (
auto IIP = MacroInfo.InclusionPathHandles.begin(),
1223 EIP = MacroInfo.InclusionPathHandles.end();
1224 IIP != EIP; ++IIP) {
1225 const std::vector<HeaderHandle> &ip = getInclusionPath(*IIP);
1226 auto Count = (int)ip.size();
1228 HeaderHandle H = ip[
Index];
1229 OS << std::string((
Index * 2) + 4,
' ') << *getHeaderFilePath(H)
1239 static const char *getDirectiveSpelling(clang::tok::PPKeywordKind kind) {
1241 case clang::tok::pp_if:
1243 case clang::tok::pp_elif:
1245 case clang::tok::pp_ifdef:
1247 case clang::tok::pp_ifndef:
1255 llvm::SmallVector<std::string, 32> HeaderList;
1259 std::vector<StringHandle> HeaderPaths;
1260 std::vector<HeaderHandle> HeaderStack;
1261 std::vector<HeaderInclusionPath> InclusionPaths;
1262 InclusionPathHandle CurrentInclusionPathHandle;
1263 llvm::SmallSet<HeaderHandle, 32> HeadersInThisCompile;
1264 std::vector<PPItemKey> IncludeDirectives;
1265 MacroExpansionMap MacroExpansions;
1266 ConditionalExpansionMap ConditionalExpansions;
1267 bool InNestedHeader;
1279 llvm::SmallVector<std::string, 32> &Headers,
1280 bool DoBlockCheckHeaderListOnly) {
1281 return new PreprocessorTrackerImpl(Headers, DoBlockCheckHeaderListOnly);
1287 void PreprocessorCallbacks::InclusionDirective(
1288 clang::SourceLocation HashLoc,
const clang::Token &IncludeTok,
1290 clang::CharSourceRange FilenameRange,
const clang::FileEntry *File,
1291 llvm::StringRef SearchPath, llvm::StringRef RelativePath,
1292 const clang::Module *Imported, clang::SrcMgr::CharacteristicKind FileType) {
1293 int DirectiveLine, DirectiveColumn;
1296 PPTracker.handleIncludeDirective(HeaderPath, DirectiveLine, DirectiveColumn,
1301 void PreprocessorCallbacks::FileChanged(
1302 clang::SourceLocation
Loc, clang::PPCallbacks::FileChangeReason Reason,
1303 clang::SrcMgr::CharacteristicKind FileType, clang::FileID PrevFID) {
1309 const clang::FileEntry *F =
1310 PP.getSourceManager().getFileEntryForID(PrevFID);
1312 PPTracker.handleHeaderExit(F->getName());
1314 case SystemHeaderPragma:
1321 void PreprocessorCallbacks::MacroExpands(
const clang::Token &MacroNameTok,
1322 const clang::MacroDefinition &
MD,
1323 clang::SourceRange
Range,
1324 const clang::MacroArgs *Args) {
1325 clang::SourceLocation Loc = Range.getBegin();
1327 if (!Loc.isFileID())
1329 clang::IdentifierInfo *II = MacroNameTok.getIdentifierInfo();
1330 const clang::MacroInfo *MI = MD.getMacroInfo();
1331 std::string MacroName = II->getName().str();
1334 PPTracker.addMacroExpansionInstance(
1335 PP, PPTracker.getCurrentHeaderHandle(),
Loc, MI->getDefinitionLoc(), II,
1336 Unexpanded, Expanded, PPTracker.getCurrentInclusionPathHandle());
1339 void PreprocessorCallbacks::Defined(
const clang::Token &MacroNameTok,
1340 const clang::MacroDefinition &MD,
1341 clang::SourceRange Range) {
1342 clang::SourceLocation
Loc(Range.getBegin());
1343 clang::IdentifierInfo *II = MacroNameTok.getIdentifierInfo();
1344 const clang::MacroInfo *MI = MD.getMacroInfo();
1345 std::string MacroName = II->getName().str();
1347 PPTracker.addMacroExpansionInstance(
1348 PP, PPTracker.getCurrentHeaderHandle(),
Loc,
1349 (MI ? MI->getDefinitionLoc() :
Loc), II, Unexpanded,
1350 (MI ?
"true" :
"false"), PPTracker.getCurrentInclusionPathHandle());
1353 void PreprocessorCallbacks::If(clang::SourceLocation Loc,
1354 clang::SourceRange ConditionRange,
1355 clang::PPCallbacks::ConditionValueKind ConditionResult) {
1357 PPTracker.addConditionalExpansionInstance(
1358 PP, PPTracker.getCurrentHeaderHandle(),
Loc, clang::tok::pp_if,
1359 ConditionResult, Unexpanded, PPTracker.getCurrentInclusionPathHandle());
1362 void PreprocessorCallbacks::Elif(clang::SourceLocation Loc,
1363 clang::SourceRange ConditionRange,
1364 clang::PPCallbacks::ConditionValueKind ConditionResult,
1365 clang::SourceLocation IfLoc) {
1367 PPTracker.addConditionalExpansionInstance(
1368 PP, PPTracker.getCurrentHeaderHandle(),
Loc, clang::tok::pp_elif,
1369 ConditionResult, Unexpanded, PPTracker.getCurrentInclusionPathHandle());
1372 void PreprocessorCallbacks::Ifdef(clang::SourceLocation Loc,
1373 const clang::Token &MacroNameTok,
1374 const clang::MacroDefinition &MD) {
1375 clang::PPCallbacks::ConditionValueKind IsDefined =
1376 (MD ? clang::PPCallbacks::CVK_True : clang::PPCallbacks::CVK_False );
1377 PPTracker.addConditionalExpansionInstance(
1378 PP, PPTracker.getCurrentHeaderHandle(),
Loc, clang::tok::pp_ifdef,
1379 IsDefined, PP.getSpelling(MacroNameTok),
1380 PPTracker.getCurrentInclusionPathHandle());
1383 void PreprocessorCallbacks::Ifndef(clang::SourceLocation Loc,
1384 const clang::Token &MacroNameTok,
1385 const clang::MacroDefinition &MD) {
1386 clang::PPCallbacks::ConditionValueKind IsNotDefined =
1387 (!MD ? clang::PPCallbacks::CVK_True : clang::PPCallbacks::CVK_False );
1388 PPTracker.addConditionalExpansionInstance(
1389 PP, PPTracker.getCurrentHeaderHandle(),
Loc, clang::tok::pp_ifndef,
1390 IsNotDefined, PP.getSpelling(MacroNameTok),
1391 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)
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)
static std::string replace(llvm::StringRef Haystack, llvm::StringRef Needle, llvm::StringRef Repl)
ModularizeUtilities class definition.
static std::string getMacroUnexpandedString(clang::SourceRange Range, clang::Preprocessor &PP, llvm::StringRef MacroName, const clang::MacroInfo *MI)
clang::tok::PPKeywordKind DirectiveKind
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 operator<(const Ref &L, const Ref &R)
bool operator==(const Ref &L, const Ref &R)
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
static const char *const ConditionValueKindStrings[]
clang::PPCallbacks::ConditionValueKind ConditionValue
std::vector< llvm::StringRef > Strings
static PreprocessorTracker * create(llvm::SmallVector< std::string, 32 > &Headers, bool DoBlockCheckHeaderListOnly)
PPItemKey DefinitionLocation
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