Index: include/clang/Lex/PPCallbacks.h =================================================================== --- include/clang/Lex/PPCallbacks.h +++ include/clang/Lex/PPCallbacks.h @@ -258,6 +258,10 @@ virtual void Defined(const Token &MacroNameTok, const MacroDefinition &MD, SourceRange Range) { } + + /// \brief Callback invoked when a has_include directive is read. + virtual void HasInclude(SourceLocation Loc, const FileEntry *File) { + } /// \brief Hook called when a source range is skipped. /// \param Range The SourceRange that was skipped. The range begins at the @@ -411,6 +415,11 @@ Second->PragmaDiagnostic(Loc, Namespace, mapping, Str); } + void HasInclude(SourceLocation Loc, const FileEntry *File) override { + First->HasInclude(Loc, File); + Second->HasInclude(Loc, File); + } + void PragmaOpenCLExtension(SourceLocation NameLoc, const IdentifierInfo *Name, SourceLocation StateLoc, unsigned State) override { First->PragmaOpenCLExtension(NameLoc, Name, StateLoc, State); Index: lib/Frontend/DependencyFile.cpp =================================================================== --- lib/Frontend/DependencyFile.cpp +++ lib/Frontend/DependencyFile.cpp @@ -196,6 +196,8 @@ StringRef SearchPath, StringRef RelativePath, const Module *Imported) override; + void HasInclude(SourceLocation Loc, const FileEntry *File) override; + void EndOfMainFile() override { OutputDependencyFile(); } @@ -319,6 +321,12 @@ } } +void DFGImpl::HasInclude(SourceLocation Loc, const FileEntry *File) { + if (!File) + return; + AddFilename(llvm::sys::path::remove_leading_dotslash(File->getName())); +} + void DFGImpl::AddFilename(StringRef Filename) { if (FilesSet.insert(Filename).second) Files.push_back(Filename); Index: lib/Lex/PPMacroExpansion.cpp =================================================================== --- lib/Lex/PPMacroExpansion.cpp +++ lib/Lex/PPMacroExpansion.cpp @@ -1424,6 +1424,9 @@ PP.LookupFile(FilenameLoc, Filename, isAngled, LookupFrom, LookupFromFile, CurDir, nullptr, nullptr, nullptr); + if (PPCallbacks *Callbacks = PP.getPPCallbacks()) + Callbacks->HasInclude(FilenameLoc, File); + // Get the result value. A result of true means the file exists. return File != nullptr; } Index: test/Frontend/dependency-gen-has-include.c =================================================================== --- /dev/null +++ test/Frontend/dependency-gen-has-include.c @@ -0,0 +1,17 @@ +// REQUIRES: shell + +// Basic test +// RUN: rm -rf %t.dir +// RUN: mkdir %t.dir +// RUN: mkdir %t.dir/a +// RUN: echo "#ifndef HEADER_A" > %t.dir/a/header.h +// RUN: echo "#define HEADER_A" >> %t.dir/a/header.h +// RUN: echo "#endif" >> %t.dir/a/header.h + +// RUN: %clang -MD -MF %t.dir/file.deps %s -fsyntax-only -I %t.dir +// RUN: FileCheck -input-file=%t.dir/file.deps %s +// CHECK: dependency-gen-has-include.o +// CHECK: dependency-gen-has-include.c +// CHECK: a/header.h +#if __has_include("a/header.h") +#endif