[modules] Add support for #include_next.
#include_next interacts poorly with modules: it depends on where in the list of
include paths the current file was found. Files covered by module maps are not
found in include search paths when building the module (and are not found in
include search paths when @importing the module either), so this isn't really
meaningful. Instead, we fake up the result that #include_next *should* have
given: find the first path that would have resulted in the given file being
picked, and search from there onwards.
llvm-svn: 220177
diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp
index 0af63e1..5885f42 100644
--- a/clang/lib/Lex/ModuleMap.cpp
+++ b/clang/lib/Lex/ModuleMap.cpp
@@ -1749,12 +1749,14 @@
Role = ModuleMap::PrivateHeader;
else
assert(LeadingToken == MMToken::HeaderKeyword);
-
- Map.addHeader(ActiveModule, File, Role);
-
- // If there is a builtin counterpart to this file, add it now.
+
+ // If there is a builtin counterpart to this file, add it now, before
+ // the "real" header, so we build the built-in one first when building
+ // the module.
if (BuiltinFile)
Map.addHeader(ActiveModule, BuiltinFile, Role);
+
+ Map.addHeader(ActiveModule, File, Role);
}
} else if (LeadingToken != MMToken::ExcludeKeyword) {
// Ignore excluded header files. They're optional anyway.
diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp
index 4250619..739ebd4 100644
--- a/clang/lib/Lex/PPDirectives.cpp
+++ b/clang/lib/Lex/PPDirectives.cpp
@@ -534,6 +534,7 @@
StringRef Filename,
bool isAngled,
const DirectoryLookup *FromDir,
+ const FileEntry *FromFile,
const DirectoryLookup *&CurDir,
SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath,
@@ -543,7 +544,7 @@
// stack, record the parent #includes.
SmallVector<std::pair<const FileEntry *, const DirectoryEntry *>, 16>
Includers;
- if (!FromDir) {
+ if (!FromDir && !FromFile) {
FileID FID = getCurrentFileLexer()->getFileID();
const FileEntry *FileEnt = SourceMgr.getFileEntryForID(FID);
@@ -575,8 +576,30 @@
}
}
- // Do a standard file entry lookup.
CurDir = CurDirLookup;
+
+ if (FromFile) {
+ // We're supposed to start looking from after a particular file. Search
+ // the include path until we find that file or run out of files.
+ const DirectoryLookup *TmpCurDir = CurDir;
+ const DirectoryLookup *TmpFromDir = nullptr;
+ while (const FileEntry *FE = HeaderInfo.LookupFile(
+ Filename, FilenameLoc, isAngled, TmpFromDir, TmpCurDir,
+ Includers, SearchPath, RelativePath, SuggestedModule,
+ SkipCache)) {
+ // Keep looking as if this file did a #include_next.
+ TmpFromDir = TmpCurDir;
+ ++TmpFromDir;
+ if (FE == FromFile) {
+ // Found it.
+ FromDir = TmpFromDir;
+ CurDir = TmpCurDir;
+ break;
+ }
+ }
+ }
+
+ // Do a standard file entry lookup.
const FileEntry *FE = HeaderInfo.LookupFile(
Filename, FilenameLoc, isAngled, FromDir, CurDir, Includers, SearchPath,
RelativePath, SuggestedModule, SkipCache);
@@ -1353,6 +1376,7 @@
void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
Token &IncludeTok,
const DirectoryLookup *LookupFrom,
+ const FileEntry *LookupFromFile,
bool isImport) {
Token FilenameTok;
@@ -1450,8 +1474,8 @@
}
const FileEntry *File = LookupFile(
FilenameLoc, LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename,
- isAngled, LookupFrom, CurDir, Callbacks ? &SearchPath : nullptr,
- Callbacks ? &RelativePath : nullptr,
+ isAngled, LookupFrom, LookupFromFile, CurDir,
+ Callbacks ? &SearchPath : nullptr, Callbacks ? &RelativePath : nullptr,
HeaderInfo.getHeaderSearchOpts().ModuleMaps ? &SuggestedModule : nullptr);
if (Callbacks) {
@@ -1465,14 +1489,13 @@
HeaderInfo.AddSearchPath(DL, isAngled);
// Try the lookup again, skipping the cache.
- File = LookupFile(FilenameLoc,
- LangOpts.MSVCCompat ? NormalizedPath.c_str()
- : Filename,
- isAngled, LookupFrom, CurDir, nullptr, nullptr,
- HeaderInfo.getHeaderSearchOpts().ModuleMaps
- ? &SuggestedModule
- : nullptr,
- /*SkipCache*/ true);
+ File = LookupFile(
+ FilenameLoc,
+ LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename, isAngled,
+ LookupFrom, LookupFromFile, CurDir, nullptr, nullptr,
+ HeaderInfo.getHeaderSearchOpts().ModuleMaps ? &SuggestedModule
+ : nullptr,
+ /*SkipCache*/ true);
}
}
}
@@ -1494,8 +1517,10 @@
// provide the user with a possible fixit.
if (isAngled) {
File = LookupFile(
- FilenameLoc, LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename,
- false, LookupFrom, CurDir, Callbacks ? &SearchPath : nullptr,
+ FilenameLoc,
+ LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename, false,
+ LookupFrom, LookupFromFile, CurDir,
+ Callbacks ? &SearchPath : nullptr,
Callbacks ? &RelativePath : nullptr,
HeaderInfo.getHeaderSearchOpts().ModuleMaps ? &SuggestedModule
: nullptr);
@@ -1692,9 +1717,16 @@
// the current found directory. If we can't do this, issue a
// diagnostic.
const DirectoryLookup *Lookup = CurDirLookup;
+ const FileEntry *LookupFromFile = nullptr;
if (isInPrimaryFile()) {
Lookup = nullptr;
Diag(IncludeNextTok, diag::pp_include_next_in_primary);
+ } else if (CurSubmodule) {
+ // Start looking up in the directory *after* the one in which the current
+ // file would be found, if any.
+ assert(CurPPLexer && "#include_next directive in macro?");
+ LookupFromFile = CurPPLexer->getFileEntry();
+ Lookup = nullptr;
} else if (!Lookup) {
Diag(IncludeNextTok, diag::pp_include_next_absolute_path);
} else {
@@ -1702,7 +1734,8 @@
++Lookup;
}
- return HandleIncludeDirective(HashLoc, IncludeNextTok, Lookup);
+ return HandleIncludeDirective(HashLoc, IncludeNextTok, Lookup,
+ LookupFromFile);
}
/// HandleMicrosoftImportDirective - Implements \#import for Microsoft Mode
@@ -1728,7 +1761,7 @@
return HandleMicrosoftImportDirective(ImportTok);
Diag(ImportTok, diag::ext_pp_import_directive);
}
- return HandleIncludeDirective(HashLoc, ImportTok, nullptr, true);
+ return HandleIncludeDirective(HashLoc, ImportTok, nullptr, nullptr, true);
}
/// HandleIncludeMacrosDirective - The -imacros command line option turns into a
@@ -1749,7 +1782,7 @@
// Treat this as a normal #include for checking purposes. If this is
// successful, it will push a new lexer onto the include stack.
- HandleIncludeDirective(HashLoc, IncludeMacrosTok, nullptr, false);
+ HandleIncludeDirective(HashLoc, IncludeMacrosTok);
Token TmpTok;
do {
diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp
index e875860..48e83ed 100644
--- a/clang/lib/Lex/PPMacroExpansion.cpp
+++ b/clang/lib/Lex/PPMacroExpansion.cpp
@@ -1053,7 +1053,8 @@
/// Returns true if successful.
static bool EvaluateHasIncludeCommon(Token &Tok,
IdentifierInfo *II, Preprocessor &PP,
- const DirectoryLookup *LookupFrom) {
+ const DirectoryLookup *LookupFrom,
+ const FileEntry *LookupFromFile) {
// Save the location of the current token. If a '(' is later found, use
// that location. If not, use the end of this location instead.
SourceLocation LParenLoc = Tok.getLocation();
@@ -1148,8 +1149,8 @@
// Search include directories.
const DirectoryLookup *CurDir;
const FileEntry *File =
- PP.LookupFile(FilenameLoc, Filename, isAngled, LookupFrom, CurDir,
- nullptr, nullptr, nullptr);
+ PP.LookupFile(FilenameLoc, Filename, isAngled, LookupFrom, LookupFromFile,
+ CurDir, nullptr, nullptr, nullptr);
// Get the result value. A result of true means the file exists.
return File != nullptr;
@@ -1159,7 +1160,7 @@
/// Returns true if successful.
static bool EvaluateHasInclude(Token &Tok, IdentifierInfo *II,
Preprocessor &PP) {
- return EvaluateHasIncludeCommon(Tok, II, PP, nullptr);
+ return EvaluateHasIncludeCommon(Tok, II, PP, nullptr, nullptr);
}
/// EvaluateHasIncludeNext - Process '__has_include_next("path")' expression.
@@ -1169,10 +1170,19 @@
// __has_include_next is like __has_include, except that we start
// searching after the current found directory. If we can't do this,
// issue a diagnostic.
+ // FIXME: Factor out duplication wiht
+ // Preprocessor::HandleIncludeNextDirective.
const DirectoryLookup *Lookup = PP.GetCurDirLookup();
+ const FileEntry *LookupFromFile = nullptr;
if (PP.isInPrimaryFile()) {
Lookup = nullptr;
PP.Diag(Tok, diag::pp_include_next_in_primary);
+ } else if (PP.getCurrentSubmodule()) {
+ // Start looking up in the directory *after* the one in which the current
+ // file would be found, if any.
+ assert(PP.getCurrentLexer() && "#include_next directive in macro?");
+ LookupFromFile = PP.getCurrentLexer()->getFileEntry();
+ Lookup = nullptr;
} else if (!Lookup) {
PP.Diag(Tok, diag::pp_include_next_absolute_path);
} else {
@@ -1180,7 +1190,7 @@
++Lookup;
}
- return EvaluateHasIncludeCommon(Tok, II, PP, Lookup);
+ return EvaluateHasIncludeCommon(Tok, II, PP, Lookup, LookupFromFile);
}
/// \brief Process __building_module(identifier) expression.
diff --git a/clang/lib/Lex/Pragma.cpp b/clang/lib/Lex/Pragma.cpp
index b784c29..b91030f 100644
--- a/clang/lib/Lex/Pragma.cpp
+++ b/clang/lib/Lex/Pragma.cpp
@@ -472,9 +472,9 @@
// Search include directories for this file.
const DirectoryLookup *CurDir;
- const FileEntry *File = LookupFile(FilenameTok.getLocation(), Filename,
- isAngled, nullptr, CurDir, nullptr,
- nullptr, nullptr);
+ const FileEntry *File =
+ LookupFile(FilenameTok.getLocation(), Filename, isAngled, nullptr,
+ nullptr, CurDir, nullptr, nullptr, nullptr);
if (!File) {
if (!SuppressIncludeNotFoundError)
Diag(FilenameTok, diag::err_pp_file_not_found) << Filename;