11 #include "clang/Frontend/CompilerInstance.h" 12 #include "clang/Lex/PPCallbacks.h" 13 #include "clang/Lex/Preprocessor.h" 14 #include "llvm/ADT/StringMap.h" 15 #include "llvm/ADT/StringSet.h" 24 class IncludeModernizePPCallbacks :
public PPCallbacks {
26 explicit IncludeModernizePPCallbacks(ClangTidyCheck &Check,
27 LangOptions LangOpts);
29 void InclusionDirective(SourceLocation HashLoc,
const Token &IncludeTok,
31 CharSourceRange FilenameRange,
const FileEntry *File,
32 StringRef SearchPath, StringRef RelativePath,
33 const Module *Imported,
34 SrcMgr::CharacteristicKind FileType)
override;
37 ClangTidyCheck &Check;
39 llvm::StringMap<std::string> CStyledHeaderToCxx;
40 llvm::StringSet<> DeleteHeaders;
45 if (this->getLangOpts().CPlusPlus) {
46 Compiler.getPreprocessor().addPPCallbacks(
47 ::llvm::make_unique<IncludeModernizePPCallbacks>(*
this,
48 this->getLangOpts()));
52 IncludeModernizePPCallbacks::IncludeModernizePPCallbacks(
ClangTidyCheck &Check,
54 : Check(Check), LangOpts(LangOpts) {
55 for (
const auto &KeyValue :
56 std::vector<std::pair<llvm::StringRef, std::string>>(
57 {{
"assert.h",
"cassert"},
58 {
"complex.h",
"complex"},
59 {
"ctype.h",
"cctype"},
60 {
"errno.h",
"cerrno"},
61 {
"float.h",
"cfloat"},
62 {
"limits.h",
"climits"},
63 {
"locale.h",
"clocale"},
65 {
"setjmp.h",
"csetjmp"},
66 {
"signal.h",
"csignal"},
67 {
"stdarg.h",
"cstdarg"},
68 {
"stddef.h",
"cstddef"},
69 {
"stdio.h",
"cstdio"},
70 {
"stdlib.h",
"cstdlib"},
71 {
"string.h",
"cstring"},
73 {
"wchar.h",
"cwchar"},
74 {
"wctype.h",
"cwctype"}})) {
75 CStyledHeaderToCxx.insert(KeyValue);
78 if (LangOpts.CPlusPlus11) {
79 for (
const auto &KeyValue :
80 std::vector<std::pair<llvm::StringRef, std::string>>(
82 {
"stdint.h",
"cstdint"},
83 {
"inttypes.h",
"cinttypes"},
84 {
"tgmath.h",
"ctgmath"},
85 {
"uchar.h",
"cuchar"}})) {
86 CStyledHeaderToCxx.insert(KeyValue);
89 for (
const auto &Key :
90 std::vector<std::string>({
"stdalign.h",
"stdbool.h",
"iso646.h"})) {
91 DeleteHeaders.insert(Key);
95 void IncludeModernizePPCallbacks::InclusionDirective(
96 SourceLocation HashLoc,
const Token &IncludeTok, StringRef
FileName,
97 bool IsAngled, CharSourceRange FilenameRange,
const FileEntry *
File,
98 StringRef SearchPath, StringRef RelativePath,
const Module *Imported,
99 SrcMgr::CharacteristicKind FileType) {
107 if (CStyledHeaderToCxx.count(FileName) != 0) {
108 std::string Replacement =
109 (llvm::Twine(
"<") + CStyledHeaderToCxx[
FileName] +
">").str();
110 Check.
diag(FilenameRange.getBegin(),
"inclusion of deprecated C++ header " 111 "'%0'; consider using '%1' instead")
112 << FileName << CStyledHeaderToCxx[FileName]
113 << FixItHint::CreateReplacement(FilenameRange.getAsRange(),
115 }
else if (DeleteHeaders.count(FileName) != 0) {
116 Check.
diag(FilenameRange.getBegin(),
117 "including '%0' has no effect in C++; consider removing it")
118 << FileName << FixItHint::CreateRemoval(
119 SourceRange(HashLoc, FilenameRange.getEnd()));
Base class for all clang-tidy checks.
bool IsAngled
true if this was an include with angle brackets
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Add a diagnostic with the check's name.