10#include "clang/Frontend/CompilerInstance.h"
11#include "clang/Lex/Preprocessor.h"
12#include "llvm/ADT/STLExtras.h"
13#include "llvm/ADT/SmallVector.h"
21 const FileID
Id = SM.getFileID(Start);
22 const unsigned LineNumber = SM.getSpellingLineNumber(Start);
23 while (SM.getFileID(Start) ==
Id &&
24 SM.getSpellingLineNumber(Start.getLocWithOffset(
Offset)) == LineNumber)
25 Start = Start.getLocWithOffset(
Offset);
31using FileList = SmallVector<StringRef>;
33class DuplicateIncludeCallbacks :
public PPCallbacks {
35 DuplicateIncludeCallbacks(DuplicateIncludeCheck &Check,
36 const SourceManager &SM)
37 : Check(Check), SM(SM) {
42 void FileChanged(SourceLocation
Loc, FileChangeReason Reason,
43 SrcMgr::CharacteristicKind FileType,
44 FileID PrevFID)
override;
46 void InclusionDirective(SourceLocation HashLoc,
const Token &IncludeTok,
48 CharSourceRange FilenameRange,
49 OptionalFileEntryRef File, StringRef SearchPath,
50 StringRef RelativePath,
const Module *SuggestedModule,
52 SrcMgr::CharacteristicKind FileType)
override;
54 void MacroDefined(
const Token &MacroNameTok,
55 const MacroDirective *MD)
override;
57 void MacroUndefined(
const Token &MacroNameTok,
const MacroDefinition &MD,
58 const MacroDirective *Undef)
override;
62 SmallVector<FileList> Files;
63 DuplicateIncludeCheck &Check;
64 const SourceManager &SM;
67void DuplicateIncludeCallbacks::FileChanged(SourceLocation
Loc,
68 FileChangeReason Reason,
69 SrcMgr::CharacteristicKind FileType,
71 if (Reason == EnterFile)
73 else if (Reason == ExitFile)
77void DuplicateIncludeCallbacks::InclusionDirective(
78 SourceLocation HashLoc,
const Token &IncludeTok, StringRef
FileName,
79 bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File,
80 StringRef SearchPath, StringRef RelativePath,
const Module *SuggestedModule,
81 bool ModuleImported, SrcMgr::CharacteristicKind FileType) {
83 if (FilenameRange.getBegin().isMacroID() ||
84 FilenameRange.getEnd().isMacroID())
86 if (llvm::is_contained(Files.back(),
FileName)) {
89 SourceLocation Start =
93 Check.diag(HashLoc,
"duplicate include")
94 << FixItHint::CreateRemoval(SourceRange{Start, End});
99void DuplicateIncludeCallbacks::MacroDefined(
const Token &MacroNameTok,
100 const MacroDirective *MD) {
101 Files.back().clear();
104void DuplicateIncludeCallbacks::MacroUndefined(
const Token &MacroNameTok,
105 const MacroDefinition &MD,
106 const MacroDirective *Undef) {
107 Files.back().clear();
113 const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
114 PP->addPPCallbacks(std::make_unique<DuplicateIncludeCallbacks>(*
this, SM));
bool IsAngled
true if this was an include with angle brackets
void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) override
Override this to register PPCallbacks in the preprocessor.
static SourceLocation advanceBeyondCurrentLine(const SourceManager &SM, SourceLocation Start, int Offset)