aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Frontend/FrontendAction.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2012-10-23 06:18:24 +0000
committerDouglas Gregor <dgregor@apple.com>2012-10-23 06:18:24 +0000
commitfc9e7a2969650e52a87864a6a79bd37b42ea33e3 (patch)
tree6c2443b774cf45deb6725e8ba96d5d9f2323cc0b /clang/lib/Frontend/FrontendAction.cpp
parentabf836cffa8ea53e67f56fddc49ed7063f7a0e85 (diff)
downloadllvm-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.cpp45
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();