aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-11-20 17:46:46 +0000
committerDouglas Gregor <dgregor@apple.com>2011-11-20 17:46:46 +0000
commit1c2e9332fa69727425a3a2b912e36e2ab62083f8 (patch)
treee37d5a66ca966268298e869872def24606e0c78f
parent1bea8807bcd2be10bf6309a3a848489434464ced (diff)
Allow preprocessor callbacks to recover from a "file not found" error,
from Jason Haslam! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@145012 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Lex/HeaderSearch.h12
-rw-r--r--include/clang/Lex/PPCallbacks.h23
-rw-r--r--include/clang/Lex/Preprocessor.h3
-rw-r--r--lib/Lex/HeaderSearch.cpp5
-rw-r--r--lib/Lex/PPDirectives.cpp27
5 files changed, 62 insertions, 8 deletions
diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h
index b56fba538a..a6d7520f29 100644
--- a/include/clang/Lex/HeaderSearch.h
+++ b/include/clang/Lex/HeaderSearch.h
@@ -207,6 +207,15 @@ public:
//LookupFileCache.clear();
}
+ /// AddSearchPath - Add an additional search path.
+ void AddSearchPath(const DirectoryLookup &dir, bool isAngled) {
+ unsigned idx = isAngled ? SystemDirIdx : AngledDirIdx;
+ SearchDirs.insert(SearchDirs.begin() + idx, dir);
+ if (!isAngled)
+ AngledDirIdx++;
+ SystemDirIdx++;
+ }
+
/// \brief Set the path to the module cache and the name of the module
/// we're building
void configureModules(StringRef CachePath, StringRef BuildingModule) {
@@ -266,7 +275,8 @@ public:
const FileEntry *CurFileEnt,
SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath,
- ModuleMap::Module **SuggestedModule);
+ ModuleMap::Module **SuggestedModule,
+ bool SkipCache = false);
/// LookupSubframeworkHeader - Look up a subframework for the specified
/// #include file. For example, if #include'ing <HIToolbox/HIToolbox.h> from
diff --git a/include/clang/Lex/PPCallbacks.h b/include/clang/Lex/PPCallbacks.h
index 1fc1a05db6..0c783d474d 100644
--- a/include/clang/Lex/PPCallbacks.h
+++ b/include/clang/Lex/PPCallbacks.h
@@ -58,6 +58,23 @@ public:
SrcMgr::CharacteristicKind FileType) {
}
+ /// FileNotFound - This callback is invoked whenever an inclusion directive
+ /// results in a file-not-found error.
+ ///
+ /// \param FileName The name of the file being included, as written in the
+ /// source code.
+ ///
+ /// \param RecoveryPath If this client indicates that it can recover from
+ /// this missing file, the client should set this as an additional header
+ /// search patch.
+ ///
+ /// \returns true to indicate that the preprocessor should attempt to recover
+ /// by adding \p RecoveryPath as a header search path.
+ virtual bool FileNotFound(StringRef FileName,
+ SmallVectorImpl<char> &RecoveryPath) {
+ return false;
+ }
+
/// \brief This callback is invoked whenever an inclusion directive of
/// any kind (\c #include, \c #import, etc.) has been processed, regardless
/// of whether the inclusion will actually result in an inclusion.
@@ -231,6 +248,12 @@ public:
Second->FileSkipped(ParentFile, FilenameTok, FileType);
}
+ virtual bool FileNotFound(StringRef FileName,
+ SmallVectorImpl<char> &RecoveryPath) {
+ return First->FileNotFound(FileName, RecoveryPath) ||
+ Second->FileNotFound(FileName, RecoveryPath);
+ }
+
virtual void InclusionDirective(SourceLocation HashLoc,
const Token &IncludeTok,
StringRef FileName,
diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h
index 90f64c4554..cf77824120 100644
--- a/include/clang/Lex/Preprocessor.h
+++ b/include/clang/Lex/Preprocessor.h
@@ -1008,7 +1008,8 @@ public:
const DirectoryLookup *&CurDir,
SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath,
- ModuleMap::Module **SuggestedModule);
+ ModuleMap::Module **SuggestedModule,
+ bool SkipCache = false);
/// GetCurLookup - The DirectoryLookup structure used to find the current
/// FileEntry, if CurLexer is non-null and if applicable. This allows us to
diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp
index 4deba60b9d..318e57dc01 100644
--- a/lib/Lex/HeaderSearch.cpp
+++ b/lib/Lex/HeaderSearch.cpp
@@ -408,7 +408,8 @@ const FileEntry *HeaderSearch::LookupFile(
const FileEntry *CurFileEnt,
SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath,
- ModuleMap::Module **SuggestedModule)
+ ModuleMap::Module **SuggestedModule,
+ bool SkipCache)
{
if (SuggestedModule)
*SuggestedModule = 0;
@@ -484,7 +485,7 @@ const FileEntry *HeaderSearch::LookupFile(
// If the entry has been previously looked up, the first value will be
// non-zero. If the value is equal to i (the start point of our search), then
// this is a matching hit.
- if (CacheLookup.first == i+1) {
+ if (!SkipCache && CacheLookup.first == i+1) {
// Skip querying potentially lots of directories for this lookup.
i = CacheLookup.second;
} else {
diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp
index 2444364f35..88d9429f00 100644
--- a/lib/Lex/PPDirectives.cpp
+++ b/lib/Lex/PPDirectives.cpp
@@ -486,7 +486,8 @@ const FileEntry *Preprocessor::LookupFile(
const DirectoryLookup *&CurDir,
SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath,
- ModuleMap::Module **SuggestedModule) {
+ ModuleMap::Module **SuggestedModule,
+ bool SkipCache) {
// If the header lookup mechanism may be relative to the current file, pass in
// info about where the current file is.
const FileEntry *CurFileEnt = 0;
@@ -510,7 +511,7 @@ const FileEntry *Preprocessor::LookupFile(
CurDir = CurDirLookup;
const FileEntry *FE = HeaderInfo.LookupFile(
Filename, isAngled, FromDir, CurDir, CurFileEnt,
- SearchPath, RelativePath, SuggestedModule);
+ SearchPath, RelativePath, SuggestedModule, SkipCache);
if (FE) return FE;
// Otherwise, see if this is a subframework header. If so, this is relative
@@ -1288,10 +1289,28 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
return;
}
- // Notify the callback object that we've seen an inclusion directive.
- if (Callbacks)
+ if (Callbacks) {
+ if (!File) {
+ // Give the clients a chance to recover.
+ llvm::SmallString<128> RecoveryPath;
+ if (Callbacks->FileNotFound(Filename, RecoveryPath)) {
+ if (const DirectoryEntry *DE = FileMgr.getDirectory(RecoveryPath)) {
+ // Add the recovery path to the list of search paths.
+ DirectoryLookup DL(DE, SrcMgr::C_User, true, false);
+ HeaderInfo.AddSearchPath(DL, isAngled);
+
+ // Try the lookup again, skipping the cache.
+ File = LookupFile(Filename, isAngled, LookupFrom, CurDir, 0, 0,
+ AutoModuleImport ? &SuggestedModule : 0,
+ /*SkipCache*/true);
+ }
+ }
+ }
+
+ // Notify the callback object that we've seen an inclusion directive.
Callbacks->InclusionDirective(HashLoc, IncludeTok, Filename, isAngled, File,
End, SearchPath, RelativePath);
+ }
if (File == 0) {
if (!SuppressIncludeNotFoundError)