diff options
author | Douglas Gregor <dgregor@apple.com> | 2012-10-23 06:18:24 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2012-10-23 06:18:24 +0000 |
commit | fc9e7a2969650e52a87864a6a79bd37b42ea33e3 (patch) | |
tree | 6c2443b774cf45deb6725e8ba96d5d9f2323cc0b /clang/lib/Frontend/FrontendAction.cpp | |
parent | abf836cffa8ea53e67f56fddc49ed7063f7a0e85 (diff) | |
download | llvm-fc9e7a2969650e52a87864a6a79bd37b42ea33e3.zip llvm-fc9e7a2969650e52a87864a6a79bd37b42ea33e3.tar.gz llvm-fc9e7a2969650e52a87864a6a79bd37b42ea33e3.tar.bz2 |
If the precompiled header named by "-include" is actually a directory,
check each of the files within that directory to determine if any of
them is an AST file that matches the language and target options. If
so, the first matching AST file is loaded. This fixes a longstanding
discrepency with GCC's precompiled header implementation.
llvm-svn: 166469
Diffstat (limited to 'clang/lib/Frontend/FrontendAction.cpp')
-rw-r--r-- | clang/lib/Frontend/FrontendAction.cpp | 45 |
1 files changed, 43 insertions, 2 deletions
diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp index c8e41de..b7b93a9 100644 --- a/clang/lib/Frontend/FrontendAction.cpp +++ b/clang/lib/Frontend/FrontendAction.cpp @@ -23,10 +23,12 @@ #include "clang/Parse/ParseAST.h" #include "clang/Serialization/ASTDeserializationListener.h" #include "clang/Serialization/ASTReader.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/Timer.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/system_error.h" +#include "llvm/Support/Timer.h" using namespace clang; namespace { @@ -155,6 +157,7 @@ ASTConsumer* FrontendAction::CreateWrappedASTConsumer(CompilerInstance &CI, return new MultiplexConsumer(Consumers); } + bool FrontendAction::BeginSourceFile(CompilerInstance &CI, const FrontendInputFile &Input) { assert(!Instance && "Already processing a source file!"); @@ -224,6 +227,44 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, return true; } + // If the implicit PCH include is actually a directory, rather than + // a single file, search for a suitable PCH file in that directory. + if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) { + FileManager &FileMgr = CI.getFileManager(); + PreprocessorOptions &PPOpts = CI.getPreprocessorOpts(); + StringRef PCHInclude = PPOpts.ImplicitPCHInclude; + if (const DirectoryEntry *PCHDir = FileMgr.getDirectory(PCHInclude)) { + llvm::error_code EC; + SmallString<128> DirNative; + llvm::sys::path::native(PCHDir->getName(), DirNative); + bool Found = false; + for (llvm::sys::fs::directory_iterator Dir(DirNative.str(), EC), DirEnd; + Dir != DirEnd && !EC; Dir.increment(EC)) { + // Check whether this is an acceptable AST file. + if (ASTReader::isAcceptableASTFile(Dir->path(), FileMgr, + CI.getLangOpts(), + CI.getTargetOpts())) { + for (unsigned I = 0, N = PPOpts.Includes.size(); I != N; ++I) { + if (PPOpts.Includes[I] == PPOpts.ImplicitPCHInclude) { + PPOpts.Includes[I] = Dir->path(); + PPOpts.ImplicitPCHInclude = Dir->path(); + Found = true; + break; + } + } + + assert(Found && "Implicit PCH include not in includes list?"); + break; + } + } + + if (!Found) { + CI.getDiagnostics().Report(diag::err_fe_no_pch_in_dir) << PCHInclude; + return true; + } + } + } + // Set up the preprocessor. CI.createPreprocessor(); |