10#include "../utils/FileExtensionsUtils.h"
11#include "clang/AST/ASTContext.h"
12#include "clang/Lex/Preprocessor.h"
18class SuspiciousIncludePPCallbacks :
public PPCallbacks {
20 explicit SuspiciousIncludePPCallbacks(SuspiciousIncludeCheck &Check,
21 const SourceManager &SM,
23 : Check(Check), PP(PP) {}
25 void InclusionDirective(SourceLocation HashLoc,
const Token &IncludeTok,
27 CharSourceRange FilenameRange,
28 OptionalFileEntryRef File, StringRef SearchPath,
29 StringRef RelativePath,
const Module *SuggestedModule,
31 SrcMgr::CharacteristicKind FileType)
override;
34 SuspiciousIncludeCheck &Check;
42 HeaderFileExtensions(Context->getHeaderFileExtensions()),
43 ImplementationFileExtensions(Context->getImplementationFileExtensions()) {
47 const SourceManager &SM, Preprocessor *
PP, Preprocessor *ModuleExpanderPP) {
49 ::std::make_unique<SuspiciousIncludePPCallbacks>(*
this, SM,
PP));
52void 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)
60 SourceLocation DiagLoc = FilenameRange.getBegin().getLocWithOffset(1);
62 const std::optional<StringRef> IFE =
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);
79 Check.diag(DiagLoc,
"did you mean to include '%0'?", DiagnosticIDs::Note)
llvm::SmallString< 256U > Name
bool IsAngled
true if this was an include with angle brackets
Base class for all clang-tidy checks.
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) override
Override this to register PPCallbacks in the preprocessor.
SuspiciousIncludeCheck(StringRef Name, ClangTidyContext *Context)
std::optional< StringRef > getFileExtension(StringRef FileName, const FileExtensionsSet &FileExtensions)
Decides whether a file has a header file extension.