workflows/premerge: Fix condition for macos job (#125237)
[llvm-project.git] / clang-tools-extra / clang-tidy / bugprone / SuspiciousIncludeCheck.cpp
blob09ba79f05575258d71be53923d5dbc94c3ebc41c
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 //===----------------------------------------------------------------------===//
9 #include "SuspiciousIncludeCheck.h"
10 #include "../utils/FileExtensionsUtils.h"
11 #include "clang/AST/ASTContext.h"
12 #include "clang/Lex/Preprocessor.h"
13 #include <optional>
15 namespace clang::tidy::bugprone {
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) {}
25 void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
26 StringRef FileName, bool IsAngled,
27 CharSourceRange FilenameRange,
28 OptionalFileEntryRef File, StringRef SearchPath,
29 StringRef RelativePath, const Module *SuggestedModule,
30 bool ModuleImported,
31 SrcMgr::CharacteristicKind FileType) override;
33 private:
34 SuspiciousIncludeCheck &Check;
35 Preprocessor *PP;
37 } // namespace
39 SuspiciousIncludeCheck::SuspiciousIncludeCheck(StringRef Name,
40 ClangTidyContext *Context)
41 : ClangTidyCheck(Name, Context),
42 HeaderFileExtensions(Context->getHeaderFileExtensions()),
43 ImplementationFileExtensions(Context->getImplementationFileExtensions()) {
46 void SuspiciousIncludeCheck::registerPPCallbacks(
47 const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
48 PP->addPPCallbacks(
49 ::std::make_unique<SuspiciousIncludePPCallbacks>(*this, SM, PP));
52 void SuspiciousIncludePPCallbacks::InclusionDirective(
53 SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName,
54 bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File,
55 StringRef SearchPath, StringRef RelativePath, const Module *SuggestedModule,
56 bool ModuleImported, SrcMgr::CharacteristicKind FileType) {
57 if (IncludeTok.getIdentifierInfo()->getPPKeywordID() == tok::pp_import)
58 return;
60 SourceLocation DiagLoc = FilenameRange.getBegin().getLocWithOffset(1);
62 const std::optional<StringRef> IFE =
63 utils::getFileExtension(FileName, Check.ImplementationFileExtensions);
64 if (!IFE)
65 return;
67 Check.diag(DiagLoc, "suspicious #%0 of file with '%1' extension")
68 << IncludeTok.getIdentifierInfo()->getName() << *IFE;
70 for (const auto &HFE : Check.HeaderFileExtensions) {
71 SmallString<128> GuessedFileName(FileName);
72 llvm::sys::path::replace_extension(GuessedFileName,
73 (!HFE.empty() ? "." : "") + HFE);
75 OptionalFileEntryRef File =
76 PP->LookupFile(DiagLoc, GuessedFileName, IsAngled, nullptr, nullptr,
77 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
78 if (File) {
79 Check.diag(DiagLoc, "did you mean to include '%0'?", DiagnosticIDs::Note)
80 << GuessedFileName;
85 } // namespace clang::tidy::bugprone