blob: ea5943e97a04e23e591c9fcfdbe951ec7ea6793d [file] [log] [blame]
Alexander Kornienkoe4a75fd2016-02-24 13:36:34 +00001//===--- DeprecatedHeadersCheck.cpp - clang-tidy---------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "DeprecatedHeadersCheck.h"
11#include "clang/Frontend/CompilerInstance.h"
12#include "clang/Lex/PPCallbacks.h"
13#include "clang/Lex/Preprocessor.h"
14#include "llvm/ADT/StringMap.h"
Kirill Bobyrev8694cb92016-08-10 18:01:45 +000015#include "llvm/ADT/StringSet.h"
Alexander Kornienkoe4a75fd2016-02-24 13:36:34 +000016
17#include <vector>
18
19namespace clang {
20namespace tidy {
21namespace modernize {
22
23namespace {
24class IncludeModernizePPCallbacks : public PPCallbacks {
25public:
26 explicit IncludeModernizePPCallbacks(ClangTidyCheck &Check,
27 LangOptions LangOpts);
28
29 void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
30 StringRef FileName, bool IsAngled,
31 CharSourceRange FilenameRange, const FileEntry *File,
32 StringRef SearchPath, StringRef RelativePath,
33 const Module *Imported) override;
34
35private:
36 ClangTidyCheck &Check;
37 LangOptions LangOpts;
38 llvm::StringMap<std::string> CStyledHeaderToCxx;
Kirill Bobyrev8694cb92016-08-10 18:01:45 +000039 llvm::StringSet<> DeleteHeaders;
Alexander Kornienkoe4a75fd2016-02-24 13:36:34 +000040};
41} // namespace
42
43void DeprecatedHeadersCheck::registerPPCallbacks(CompilerInstance &Compiler) {
44 if (this->getLangOpts().CPlusPlus) {
45 Compiler.getPreprocessor().addPPCallbacks(
46 ::llvm::make_unique<IncludeModernizePPCallbacks>(*this,
47 this->getLangOpts()));
48 }
49}
50
51IncludeModernizePPCallbacks::IncludeModernizePPCallbacks(ClangTidyCheck &Check,
52 LangOptions LangOpts)
Alexander Kornienko4f933372016-02-25 00:39:11 +000053 : Check(Check), LangOpts(LangOpts) {
54 for (const auto &KeyValue :
55 std::vector<std::pair<llvm::StringRef, std::string>>(
Kirill Bobyrev8694cb92016-08-10 18:01:45 +000056 {{"assert.h", "cassert"},
57 {"complex.h", "complex"},
58 {"ctype.h", "cctype"},
59 {"errno.h", "cerrno"},
60 {"float.h", "cfloat"},
61 {"limits.h", "climits"},
62 {"locale.h", "clocale"},
63 {"math.h", "cmath"},
64 {"setjmp.h", "csetjmp"},
65 {"signal.h", "csignal"},
66 {"stdarg.h", "cstdarg"},
67 {"stddef.h", "cstddef"},
68 {"stdio.h", "cstdio"},
69 {"stdlib.h", "cstdlib"},
70 {"string.h", "cstring"},
71 {"time.h", "ctime"},
72 {"wchar.h", "cwchar"},
Alexander Kornienko4f933372016-02-25 00:39:11 +000073 {"wctype.h", "cwctype"}})) {
74 CStyledHeaderToCxx.insert(KeyValue);
75 }
Alexander Kornienkoe4a75fd2016-02-24 13:36:34 +000076 // Add C++ 11 headers.
77 if (LangOpts.CPlusPlus11) {
Alexander Kornienko4432e122016-02-24 23:48:24 +000078 for (const auto &KeyValue :
Alexander Kornienko4f933372016-02-25 00:39:11 +000079 std::vector<std::pair<llvm::StringRef, std::string>>(
Alexander Kornienkoe4a75fd2016-02-24 13:36:34 +000080 {{"fenv.h", "cfenv"},
Kirill Bobyrev8694cb92016-08-10 18:01:45 +000081 {"stdint.h", "cstdint"},
82 {"inttypes.h", "cinttypes"},
Alexander Kornienkoe4a75fd2016-02-24 13:36:34 +000083 {"tgmath.h", "ctgmath"},
84 {"uchar.h", "cuchar"}})) {
Alexander Kornienko4432e122016-02-24 23:48:24 +000085 CStyledHeaderToCxx.insert(KeyValue);
Alexander Kornienkoe4a75fd2016-02-24 13:36:34 +000086 }
87 }
Kirill Bobyrev8694cb92016-08-10 18:01:45 +000088 for (const auto &Key :
89 std::vector<std::string>({"stdalign.h", "stdbool.h", "iso646.h"})) {
90 DeleteHeaders.insert(Key);
91 }
Alexander Kornienkoe4a75fd2016-02-24 13:36:34 +000092}
93
94void IncludeModernizePPCallbacks::InclusionDirective(
95 SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName,
96 bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File,
97 StringRef SearchPath, StringRef RelativePath, const Module *Imported) {
98 // FIXME: Take care of library symbols from the global namespace.
99 //
100 // Reasonable options for the check:
101 //
Kirill Bobyrev8694cb92016-08-10 18:01:45 +0000102 // 1. Insert std prefix for every such symbol occurrence.
Alexander Kornienkoe4a75fd2016-02-24 13:36:34 +0000103 // 2. Insert `using namespace std;` to the beginning of TU.
104 // 3. Do nothing and let the user deal with the migration himself.
105 if (CStyledHeaderToCxx.count(FileName) != 0) {
106 std::string Replacement =
107 (llvm::Twine("<") + CStyledHeaderToCxx[FileName] + ">").str();
Kirill Bobyrev8694cb92016-08-10 18:01:45 +0000108 Check.diag(FilenameRange.getBegin(), "inclusion of deprecated C++ header "
109 "'%0'; consider using '%1' instead")
Alexander Kornienkoe4a75fd2016-02-24 13:36:34 +0000110 << FileName << CStyledHeaderToCxx[FileName]
111 << FixItHint::CreateReplacement(FilenameRange.getAsRange(),
112 Replacement);
Kirill Bobyrev8694cb92016-08-10 18:01:45 +0000113 } else if (DeleteHeaders.count(FileName) != 0) {
114 Check.diag(FilenameRange.getBegin(),
115 "including '%0' has no effect in C++; consider removing it")
116 << FileName << FixItHint::CreateRemoval(
117 SourceRange(HashLoc, FilenameRange.getEnd()));
Alexander Kornienkoe4a75fd2016-02-24 13:36:34 +0000118 }
119}
120
121} // namespace modernize
122} // namespace tidy
123} // namespace clang