1eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar//===--- HeaderIncludes.cpp - Generate Header Includes --------------------===// 2eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar// 3eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar// The LLVM Compiler Infrastructure 4eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar// 5eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar// This file is distributed under the University of Illinois Open Source 6eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar// License. See LICENSE.TXT for details. 7eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar// 8eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar//===----------------------------------------------------------------------===// 9eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar 10eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar#include "clang/Frontend/Utils.h" 11eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar#include "clang/Basic/SourceManager.h" 12f704c61b3c88659a0c9946ea26d1bbff99803792Daniel Dunbar#include "clang/Frontend/FrontendDiagnostic.h" 13eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar#include "clang/Lex/Preprocessor.h" 148fe83e1df954d72c0f4ffc15d20a5222ec151c21Benjamin Kramer#include "llvm/ADT/SmallString.h" 15f704c61b3c88659a0c9946ea26d1bbff99803792Daniel Dunbar#include "llvm/Support/raw_ostream.h" 16eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbarusing namespace clang; 17eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar 18eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbarnamespace { 19eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbarclass HeaderIncludesCallback : public PPCallbacks { 20eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar SourceManager &SM; 215f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner raw_ostream *OutputFile; 22eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar unsigned CurrentIncludeDepth; 23eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar bool HasProcessedPredefines; 24b34d69b9292534c1c574f168f0ac10aea652adcaDaniel Dunbar bool OwnsOutputFile; 25b34d69b9292534c1c574f168f0ac10aea652adcaDaniel Dunbar bool ShowAllHeaders; 26da60885cb4ee85d167cf704061f10b758067cf5aDaniel Dunbar bool ShowDepth; 27708002ede3938256a6223d153a0c040f7a40f5ccHans Wennborg bool MSStyle; 28eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar 29eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbarpublic: 30b34d69b9292534c1c574f168f0ac10aea652adcaDaniel Dunbar HeaderIncludesCallback(const Preprocessor *PP, bool ShowAllHeaders_, 315f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner raw_ostream *OutputFile_, bool OwnsOutputFile_, 32708002ede3938256a6223d153a0c040f7a40f5ccHans Wennborg bool ShowDepth_, bool MSStyle_) 33b34d69b9292534c1c574f168f0ac10aea652adcaDaniel Dunbar : SM(PP->getSourceManager()), OutputFile(OutputFile_), 34b34d69b9292534c1c574f168f0ac10aea652adcaDaniel Dunbar CurrentIncludeDepth(0), HasProcessedPredefines(false), 35da60885cb4ee85d167cf704061f10b758067cf5aDaniel Dunbar OwnsOutputFile(OwnsOutputFile_), ShowAllHeaders(ShowAllHeaders_), 36708002ede3938256a6223d153a0c040f7a40f5ccHans Wennborg ShowDepth(ShowDepth_), MSStyle(MSStyle_) {} 37b34d69b9292534c1c574f168f0ac10aea652adcaDaniel Dunbar 38b34d69b9292534c1c574f168f0ac10aea652adcaDaniel Dunbar ~HeaderIncludesCallback() { 39b34d69b9292534c1c574f168f0ac10aea652adcaDaniel Dunbar if (OwnsOutputFile) 40f704c61b3c88659a0c9946ea26d1bbff99803792Daniel Dunbar delete OutputFile; 41b34d69b9292534c1c574f168f0ac10aea652adcaDaniel Dunbar } 42eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar 43651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void FileChanged(SourceLocation Loc, FileChangeReason Reason, 44651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SrcMgr::CharacteristicKind FileType, 45651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FileID PrevFID) override; 46eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar}; 47eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar} 48eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar 49b376e5e71aa3e608c0481a9a7facb5d8b29d3163Daniel Dunbarvoid clang::AttachHeaderIncludeGen(Preprocessor &PP, bool ShowAllHeaders, 50708002ede3938256a6223d153a0c040f7a40f5ccHans Wennborg StringRef OutputPath, bool ShowDepth, 51708002ede3938256a6223d153a0c040f7a40f5ccHans Wennborg bool MSStyle) { 52ef8225444452a1486bd721f3285301fe84643b00Stephen Hines raw_ostream *OutputFile = MSStyle ? &llvm::outs() : &llvm::errs(); 53f704c61b3c88659a0c9946ea26d1bbff99803792Daniel Dunbar bool OwnsOutputFile = false; 54b34d69b9292534c1c574f168f0ac10aea652adcaDaniel Dunbar 55b34d69b9292534c1c574f168f0ac10aea652adcaDaniel Dunbar // Open the output file, if used. 56f704c61b3c88659a0c9946ea26d1bbff99803792Daniel Dunbar if (!OutputPath.empty()) { 57f704c61b3c88659a0c9946ea26d1bbff99803792Daniel Dunbar std::string Error; 58f704c61b3c88659a0c9946ea26d1bbff99803792Daniel Dunbar llvm::raw_fd_ostream *OS = new llvm::raw_fd_ostream( 59651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OutputPath.str().c_str(), Error, 60651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines llvm::sys::fs::F_Append | llvm::sys::fs::F_Text); 61f704c61b3c88659a0c9946ea26d1bbff99803792Daniel Dunbar if (!Error.empty()) { 62f704c61b3c88659a0c9946ea26d1bbff99803792Daniel Dunbar PP.getDiagnostics().Report( 63f704c61b3c88659a0c9946ea26d1bbff99803792Daniel Dunbar clang::diag::warn_fe_cc_print_header_failure) << Error; 64f704c61b3c88659a0c9946ea26d1bbff99803792Daniel Dunbar delete OS; 65f704c61b3c88659a0c9946ea26d1bbff99803792Daniel Dunbar } else { 66f704c61b3c88659a0c9946ea26d1bbff99803792Daniel Dunbar OS->SetUnbuffered(); 67f704c61b3c88659a0c9946ea26d1bbff99803792Daniel Dunbar OS->SetUseAtomicWrites(true); 68f704c61b3c88659a0c9946ea26d1bbff99803792Daniel Dunbar OutputFile = OS; 69f704c61b3c88659a0c9946ea26d1bbff99803792Daniel Dunbar OwnsOutputFile = true; 70f704c61b3c88659a0c9946ea26d1bbff99803792Daniel Dunbar } 71b34d69b9292534c1c574f168f0ac10aea652adcaDaniel Dunbar } 72b34d69b9292534c1c574f168f0ac10aea652adcaDaniel Dunbar 73b34d69b9292534c1c574f168f0ac10aea652adcaDaniel Dunbar PP.addPPCallbacks(new HeaderIncludesCallback(&PP, ShowAllHeaders, 74da60885cb4ee85d167cf704061f10b758067cf5aDaniel Dunbar OutputFile, OwnsOutputFile, 75708002ede3938256a6223d153a0c040f7a40f5ccHans Wennborg ShowDepth, MSStyle)); 76eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar} 77eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar 78eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbarvoid HeaderIncludesCallback::FileChanged(SourceLocation Loc, 79eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar FileChangeReason Reason, 80c892c5fa92db137ff68d95afb13fe969d17f4fb2Argyrios Kyrtzidis SrcMgr::CharacteristicKind NewFileType, 81c892c5fa92db137ff68d95afb13fe969d17f4fb2Argyrios Kyrtzidis FileID PrevFID) { 82eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar // Unless we are exiting a #include, make sure to skip ahead to the line the 83eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar // #include directive was at. 84eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar PresumedLoc UserLoc = SM.getPresumedLoc(Loc); 85eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar if (UserLoc.isInvalid()) 86eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar return; 87b34d69b9292534c1c574f168f0ac10aea652adcaDaniel Dunbar 88eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar // Adjust the current include depth. 89eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar if (Reason == PPCallbacks::EnterFile) { 90eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar ++CurrentIncludeDepth; 914dddebfef924be24de74b8bdf722a5cff3f3333fSebastian Redl } else if (Reason == PPCallbacks::ExitFile) { 92eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar if (CurrentIncludeDepth) 93eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar --CurrentIncludeDepth; 94eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar 95eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar // We track when we are done with the predefines by watching for the first 964dddebfef924be24de74b8bdf722a5cff3f3333fSebastian Redl // place where we drop back to a nesting depth of 1. 974dddebfef924be24de74b8bdf722a5cff3f3333fSebastian Redl if (CurrentIncludeDepth == 1 && !HasProcessedPredefines) 98eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar HasProcessedPredefines = true; 994dddebfef924be24de74b8bdf722a5cff3f3333fSebastian Redl 1004dddebfef924be24de74b8bdf722a5cff3f3333fSebastian Redl return; 1014dddebfef924be24de74b8bdf722a5cff3f3333fSebastian Redl } else 1024dddebfef924be24de74b8bdf722a5cff3f3333fSebastian Redl return; 103b376e5e71aa3e608c0481a9a7facb5d8b29d3163Daniel Dunbar 104b376e5e71aa3e608c0481a9a7facb5d8b29d3163Daniel Dunbar // Show the header if we are (a) past the predefines, or (b) showing all 105b376e5e71aa3e608c0481a9a7facb5d8b29d3163Daniel Dunbar // headers and in the predefines at a depth past the initial file and command 106b376e5e71aa3e608c0481a9a7facb5d8b29d3163Daniel Dunbar // line buffers. 107b376e5e71aa3e608c0481a9a7facb5d8b29d3163Daniel Dunbar bool ShowHeader = (HasProcessedPredefines || 108b376e5e71aa3e608c0481a9a7facb5d8b29d3163Daniel Dunbar (ShowAllHeaders && CurrentIncludeDepth > 2)); 109b376e5e71aa3e608c0481a9a7facb5d8b29d3163Daniel Dunbar 110b376e5e71aa3e608c0481a9a7facb5d8b29d3163Daniel Dunbar // Dump the header include information we are past the predefines buffer or 111b376e5e71aa3e608c0481a9a7facb5d8b29d3163Daniel Dunbar // are showing all headers. 112b376e5e71aa3e608c0481a9a7facb5d8b29d3163Daniel Dunbar if (ShowHeader && Reason == PPCallbacks::EnterFile) { 113eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar // Write to a temporary string to avoid unnecessary flushing on errs(). 114f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<512> Filename(UserLoc.getFilename()); 115708002ede3938256a6223d153a0c040f7a40f5ccHans Wennborg if (!MSStyle) 116708002ede3938256a6223d153a0c040f7a40f5ccHans Wennborg Lexer::Stringify(Filename); 117eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar 118f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<256> Msg; 119708002ede3938256a6223d153a0c040f7a40f5ccHans Wennborg if (MSStyle) 120708002ede3938256a6223d153a0c040f7a40f5ccHans Wennborg Msg += "Note: including file:"; 121708002ede3938256a6223d153a0c040f7a40f5ccHans Wennborg 122da60885cb4ee85d167cf704061f10b758067cf5aDaniel Dunbar if (ShowDepth) { 1234dddebfef924be24de74b8bdf722a5cff3f3333fSebastian Redl // The main source file is at depth 1, so skip one dot. 1244dddebfef924be24de74b8bdf722a5cff3f3333fSebastian Redl for (unsigned i = 1; i != CurrentIncludeDepth; ++i) 125708002ede3938256a6223d153a0c040f7a40f5ccHans Wennborg Msg += MSStyle ? ' ' : '.'; 126708002ede3938256a6223d153a0c040f7a40f5ccHans Wennborg 127708002ede3938256a6223d153a0c040f7a40f5ccHans Wennborg if (!MSStyle) 128708002ede3938256a6223d153a0c040f7a40f5ccHans Wennborg Msg += ' '; 129da60885cb4ee85d167cf704061f10b758067cf5aDaniel Dunbar } 130eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar Msg += Filename; 131eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar Msg += '\n'; 132eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar 133f704c61b3c88659a0c9946ea26d1bbff99803792Daniel Dunbar OutputFile->write(Msg.data(), Msg.size()); 134eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar } 135eef63e0997e0f6d6436736ea919b851cfe34955aDaniel Dunbar} 136