10 #include "clang/Frontend/CompilerInstance.h"
11 #include "clang/Lex/PPCallbacks.h"
12 #include "clang/Lex/Preprocessor.h"
13 #include "llvm/ADT/StringMap.h"
14 #include "llvm/ADT/StringSet.h"
23 class IncludeModernizePPCallbacks :
public PPCallbacks {
25 explicit IncludeModernizePPCallbacks(ClangTidyCheck &Check,
26 LangOptions LangOpts);
28 void InclusionDirective(SourceLocation HashLoc,
const Token &IncludeTok,
30 CharSourceRange FilenameRange,
const FileEntry *File,
31 StringRef SearchPath, StringRef RelativePath,
32 const Module *Imported,
33 SrcMgr::CharacteristicKind FileType)
override;
36 ClangTidyCheck &Check;
38 llvm::StringMap<std::string> CStyledHeaderToCxx;
39 llvm::StringSet<> DeleteHeaders;
44 const SourceManager &SM, Preprocessor *
PP, Preprocessor *ModuleExpanderPP) {
46 ::std::make_unique<IncludeModernizePPCallbacks>(*
this,
getLangOpts()));
49 IncludeModernizePPCallbacks::IncludeModernizePPCallbacks(
ClangTidyCheck &Check,
51 : Check(Check), LangOpts(LangOpts) {
52 for (
const auto &KeyValue :
53 std::vector<std::pair<llvm::StringRef, std::string>>(
54 {{
"assert.h",
"cassert"},
55 {
"complex.h",
"complex"},
56 {
"ctype.h",
"cctype"},
57 {
"errno.h",
"cerrno"},
58 {
"float.h",
"cfloat"},
59 {
"limits.h",
"climits"},
60 {
"locale.h",
"clocale"},
62 {
"setjmp.h",
"csetjmp"},
63 {
"signal.h",
"csignal"},
64 {
"stdarg.h",
"cstdarg"},
65 {
"stddef.h",
"cstddef"},
66 {
"stdio.h",
"cstdio"},
67 {
"stdlib.h",
"cstdlib"},
68 {
"string.h",
"cstring"},
70 {
"wchar.h",
"cwchar"},
71 {
"wctype.h",
"cwctype"}})) {
72 CStyledHeaderToCxx.insert(KeyValue);
75 if (LangOpts.CPlusPlus11) {
76 for (
const auto &KeyValue :
77 std::vector<std::pair<llvm::StringRef, std::string>>(
79 {
"stdint.h",
"cstdint"},
80 {
"inttypes.h",
"cinttypes"},
81 {
"tgmath.h",
"ctgmath"},
82 {
"uchar.h",
"cuchar"}})) {
83 CStyledHeaderToCxx.insert(KeyValue);
86 for (
const auto &Key :
87 std::vector<std::string>({
"stdalign.h",
"stdbool.h",
"iso646.h"})) {
88 DeleteHeaders.insert(Key);
92 void IncludeModernizePPCallbacks::InclusionDirective(
93 SourceLocation HashLoc,
const Token &IncludeTok, StringRef
FileName,
94 bool IsAngled, CharSourceRange FilenameRange,
const FileEntry *File,
95 StringRef SearchPath, StringRef RelativePath,
const Module *Imported,
96 SrcMgr::CharacteristicKind FileType) {
104 if (CStyledHeaderToCxx.count(
FileName) != 0) {
105 std::string Replacement =
106 (llvm::Twine(
"<") + CStyledHeaderToCxx[
FileName] +
">").str();
107 Check.diag(FilenameRange.getBegin(),
"inclusion of deprecated C++ header "
108 "'%0'; consider using '%1' instead")
110 << FixItHint::CreateReplacement(FilenameRange.getAsRange(),
112 }
else if (DeleteHeaders.count(
FileName) != 0) {
113 Check.diag(FilenameRange.getBegin(),
114 "including '%0' has no effect in C++; consider removing it")
115 <<
FileName << FixItHint::CreateRemoval(
116 SourceRange(HashLoc, FilenameRange.getEnd()));