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 *Imported,
51 SrcMgr::CharacteristicKind FileType)
override;
53 void MacroDefined(
const Token &MacroNameTok,
54 const MacroDirective *MD)
override;
56 void MacroUndefined(
const Token &MacroNameTok,
const MacroDefinition &MD,
57 const MacroDirective *Undef)
override;
61 SmallVector<FileList> Files;
62 DuplicateIncludeCheck &Check;
63 const SourceManager &SM;
66void DuplicateIncludeCallbacks::FileChanged(SourceLocation
Loc,
67 FileChangeReason Reason,
68 SrcMgr::CharacteristicKind FileType,
70 if (Reason == EnterFile)
72 else if (Reason == ExitFile)
76void DuplicateIncludeCallbacks::InclusionDirective(
77 SourceLocation HashLoc,
const Token &IncludeTok, StringRef
FileName,
78 bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File,
79 StringRef SearchPath, StringRef RelativePath,
const Module *Imported,
80 SrcMgr::CharacteristicKind FileType) {
81 if (llvm::is_contained(Files.back(),
FileName)) {
84 SourceLocation Start =
88 Check.diag(HashLoc,
"duplicate include")
89 << FixItHint::CreateRemoval(SourceRange{Start, End});
94void DuplicateIncludeCallbacks::MacroDefined(
const Token &MacroNameTok,
95 const MacroDirective *MD) {
99void DuplicateIncludeCallbacks::MacroUndefined(
const Token &MacroNameTok,
100 const MacroDefinition &MD,
101 const MacroDirective *Undef) {
102 Files.back().clear();
108 const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
109 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)