clang-tools  14.0.0git
SuspiciousIncludeCheck.cpp
Go to the documentation of this file.
1 //===--- SuspiciousIncludeCheck.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 
10 #include "clang/AST/ASTContext.h"
11 #include "clang/Lex/Preprocessor.h"
12 
13 namespace clang {
14 namespace tidy {
15 namespace bugprone {
16 
17 namespace {
18 class SuspiciousIncludePPCallbacks : public PPCallbacks {
19 public:
20  explicit SuspiciousIncludePPCallbacks(SuspiciousIncludeCheck &Check,
21  const SourceManager &SM,
22  Preprocessor *PP)
23  : Check(Check), PP(PP) {}
24 
25  void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
26  StringRef FileName, bool IsAngled,
27  CharSourceRange FilenameRange, const FileEntry *File,
28  StringRef SearchPath, StringRef RelativePath,
29  const Module *Imported,
30  SrcMgr::CharacteristicKind FileType) override;
31 
32 private:
33  SuspiciousIncludeCheck &Check;
34  Preprocessor *PP;
35 };
36 } // namespace
37 
39  ClangTidyContext *Context)
40  : ClangTidyCheck(Name, Context),
41  RawStringHeaderFileExtensions(Options.getLocalOrGlobal(
42  "HeaderFileExtensions", utils::defaultHeaderFileExtensions())),
43  RawStringImplementationFileExtensions(Options.getLocalOrGlobal(
44  "ImplementationFileExtensions",
46  if (!utils::parseFileExtensions(RawStringImplementationFileExtensions,
49  this->configurationDiag("Invalid implementation file extension: '%0'")
50  << RawStringImplementationFileExtensions;
51  }
52 
53  if (!utils::parseFileExtensions(RawStringHeaderFileExtensions,
56  this->configurationDiag("Invalid header file extension: '%0'")
57  << RawStringHeaderFileExtensions;
58  }
59 }
60 
62  Options.store(Opts, "ImplementationFileExtensions",
63  RawStringImplementationFileExtensions);
64  Options.store(Opts, "HeaderFileExtensions", RawStringHeaderFileExtensions);
65 }
66 
68  const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
69  PP->addPPCallbacks(
70  ::std::make_unique<SuspiciousIncludePPCallbacks>(*this, SM, PP));
71 }
72 
73 void SuspiciousIncludePPCallbacks::InclusionDirective(
74  SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName,
75  bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File,
76  StringRef SearchPath, StringRef RelativePath, const Module *Imported,
77  SrcMgr::CharacteristicKind FileType) {
78  if (IncludeTok.getIdentifierInfo()->getPPKeywordID() == tok::pp_import)
79  return;
80 
81  SourceLocation DiagLoc = FilenameRange.getBegin().getLocWithOffset(1);
82 
83  const Optional<StringRef> IFE =
84  utils::getFileExtension(FileName, Check.ImplementationFileExtensions);
85  if (!IFE)
86  return;
87 
88  Check.diag(DiagLoc, "suspicious #%0 of file with '%1' extension")
89  << IncludeTok.getIdentifierInfo()->getName() << *IFE;
90 
91  for (const auto &HFE : Check.HeaderFileExtensions) {
92  SmallString<128> GuessedFileName(FileName);
93  llvm::sys::path::replace_extension(GuessedFileName,
94  (HFE.size() ? "." : "") + HFE);
95 
96  const DirectoryLookup *CurDir;
97  Optional<FileEntryRef> File =
98  PP->LookupFile(DiagLoc, GuessedFileName, IsAngled, nullptr, nullptr,
99  CurDir, nullptr, nullptr, nullptr, nullptr, nullptr);
100  if (File) {
101  Check.diag(DiagLoc, "did you mean to include '%0'?", DiagnosticIDs::Note)
102  << GuessedFileName;
103  }
104  }
105 }
106 
107 } // namespace bugprone
108 } // namespace tidy
109 } // namespace clang
clang::tidy::ClangTidyOptions::OptionMap
llvm::StringMap< ClangTidyValue > OptionMap
Definition: ClangTidyOptions.h:115
clang::tidy::utils::getFileExtension
llvm::Optional< StringRef > getFileExtension(StringRef FileName, const FileExtensionsSet &FileExtensions)
Decides whether a file has a header file extension.
Definition: FileExtensionsUtils.cpp:57
clang::tidy::bugprone::SuspiciousIncludeCheck::SuspiciousIncludeCheck
SuspiciousIncludeCheck(StringRef Name, ClangTidyContext *Context)
Definition: SuspiciousIncludeCheck.cpp:38
clang::tidy::ClangTidyCheck
Base class for all clang-tidy checks.
Definition: ClangTidyCheck.h:54
clang::tidy::bugprone::SuspiciousIncludeCheck::storeOptions
void storeOptions(ClangTidyOptions::OptionMap &Opts) override
Should store all options supported by this check with their current values or default values for opti...
Definition: SuspiciousIncludeCheck.cpp:61
clang::tidy::bugprone::SuspiciousIncludeCheck::ImplementationFileExtensions
utils::FileExtensionsSet ImplementationFileExtensions
Definition: SuspiciousIncludeCheck.h:46
SuspiciousIncludeCheck.h
clang::tidy::utils::parseFileExtensions
bool parseFileExtensions(StringRef AllFileExtensions, FileExtensionsSet &FileExtensions, StringRef Delimiters)
Parses header file extensions from a semicolon-separated list.
Definition: FileExtensionsUtils.cpp:35
clang::tidy::utils::defaultFileExtensionDelimiters
StringRef defaultFileExtensionDelimiters()
Returns recommended default value for the list of file extension delimiters.
Definition: FileExtensionsUtils.h:48
clang::tidy::ClangTidyCheck::Options
OptionsView Options
Definition: ClangTidyCheck.h:416
clang::tidy::ClangTidyContext
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
Definition: ClangTidyDiagnosticConsumer.h:71
Name
static constexpr llvm::StringLiteral Name
Definition: UppercaseLiteralSuffixCheck.cpp:28
clang::tidy::bugprone::SuspiciousIncludeCheck::registerPPCallbacks
void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) override
Override this to register PPCallbacks in the preprocessor.
Definition: SuspiciousIncludeCheck.cpp:67
FileName
StringRef FileName
Definition: KernelNameRestrictionCheck.cpp:46
clang::tidy::bugprone::PP
static Preprocessor * PP
Definition: BadSignalToKillThreadCheck.cpp:29
IsAngled
bool IsAngled
true if this was an include with angle brackets
Definition: IncludeOrderCheck.cpp:40
clang::tidy::utils::defaultImplementationFileExtensions
StringRef defaultImplementationFileExtensions()
Returns recommended default value for the list of implementation file extensions.
Definition: FileExtensionsUtils.h:42
clang::tidy::ClangTidyCheck::configurationDiag
DiagnosticBuilder configurationDiag(StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning) const
Adds a diagnostic to report errors in the check's configuration.
Definition: ClangTidyCheck.cpp:36
PPCallbacks
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
SM
const SourceManager & SM
Definition: IncludeCleaner.cpp:140
clang::tidy::ClangTidyCheck::OptionsView::store
void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, StringRef Value) const
Stores an option with the check-local name LocalName with string value Value to Options.
Definition: ClangTidyCheck.cpp:120
clang::tidy::bugprone::SuspiciousIncludeCheck::HeaderFileExtensions
utils::FileExtensionsSet HeaderFileExtensions
Definition: SuspiciousIncludeCheck.h:45
clang::tidy::utils::defaultHeaderFileExtensions
StringRef defaultHeaderFileExtensions()
Returns recommended default value for the list of header file extensions.
Definition: FileExtensionsUtils.h:38