• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===--- DeprecatedHeadersCheck.cpp - clang-tidy---------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "DeprecatedHeadersCheck.h"
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"
15 
16 #include <vector>
17 
18 namespace clang {
19 namespace tidy {
20 namespace modernize {
21 
22 namespace {
23 class IncludeModernizePPCallbacks : public PPCallbacks {
24 public:
25   explicit IncludeModernizePPCallbacks(ClangTidyCheck &Check,
26                                        LangOptions LangOpts);
27 
28   void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
29                           StringRef FileName, bool IsAngled,
30                           CharSourceRange FilenameRange, const FileEntry *File,
31                           StringRef SearchPath, StringRef RelativePath,
32                           const Module *Imported,
33                           SrcMgr::CharacteristicKind FileType) override;
34 
35 private:
36   ClangTidyCheck &Check;
37   LangOptions LangOpts;
38   llvm::StringMap<std::string> CStyledHeaderToCxx;
39   llvm::StringSet<> DeleteHeaders;
40 };
41 } // namespace
42 
registerPPCallbacks(const SourceManager & SM,Preprocessor * PP,Preprocessor * ModuleExpanderPP)43 void DeprecatedHeadersCheck::registerPPCallbacks(
44     const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
45     PP->addPPCallbacks(
46         ::std::make_unique<IncludeModernizePPCallbacks>(*this, getLangOpts()));
47 }
48 
IncludeModernizePPCallbacks(ClangTidyCheck & Check,LangOptions LangOpts)49 IncludeModernizePPCallbacks::IncludeModernizePPCallbacks(ClangTidyCheck &Check,
50                                                          LangOptions LangOpts)
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"},
61             {"math.h", "cmath"},
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"},
69             {"time.h", "ctime"},
70             {"wchar.h", "cwchar"},
71             {"wctype.h", "cwctype"}})) {
72     CStyledHeaderToCxx.insert(KeyValue);
73   }
74   // Add C++ 11 headers.
75   if (LangOpts.CPlusPlus11) {
76     for (const auto &KeyValue :
77          std::vector<std::pair<llvm::StringRef, std::string>>(
78              {{"fenv.h", "cfenv"},
79               {"stdint.h", "cstdint"},
80               {"inttypes.h", "cinttypes"},
81               {"tgmath.h", "ctgmath"},
82               {"uchar.h", "cuchar"}})) {
83       CStyledHeaderToCxx.insert(KeyValue);
84     }
85   }
86   for (const auto &Key :
87        std::vector<std::string>({"stdalign.h", "stdbool.h", "iso646.h"})) {
88     DeleteHeaders.insert(Key);
89   }
90 }
91 
InclusionDirective(SourceLocation HashLoc,const Token & IncludeTok,StringRef FileName,bool IsAngled,CharSourceRange FilenameRange,const FileEntry * File,StringRef SearchPath,StringRef RelativePath,const Module * Imported,SrcMgr::CharacteristicKind FileType)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) {
97   // FIXME: Take care of library symbols from the global namespace.
98   //
99   // Reasonable options for the check:
100   //
101   // 1. Insert std prefix for every such symbol occurrence.
102   // 2. Insert `using namespace std;` to the beginning of TU.
103   // 3. Do nothing and let the user deal with the migration himself.
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")
109         << FileName << CStyledHeaderToCxx[FileName]
110         << FixItHint::CreateReplacement(FilenameRange.getAsRange(),
111                                         Replacement);
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()));
117   }
118 }
119 
120 } // namespace modernize
121 } // namespace tidy
122 } // namespace clang
123