Teach the preprocessor how to handle module import declarations that

involve submodules (e.g., importing std.vector), rather than always
importing the top-level module.

llvm-svn: 145478
This commit is contained in:
Douglas Gregor 2011-11-30 04:26:53 +00:00
parent 5196bc6b39
commit 1805b8a42f
4 changed files with 47 additions and 9 deletions

View File

@ -109,6 +109,14 @@ class CompilerInstance : public ModuleLoader {
/// along with the module map
llvm::DenseMap<const IdentifierInfo *, KnownModule> KnownModules;
/// \brief The location of the module-import keyword for the last module
/// import.
SourceLocation LastModuleImportLoc;
/// \brief The result of the last module import.
///
KnownModule LastModuleImportResult;
/// \brief Holds information about the output file.
///
/// If TempFilename is not empty we must rename it to Filename at the end.

View File

@ -167,6 +167,14 @@ class Preprocessor : public llvm::RefCountedBase<Preprocessor> {
/// lexed, if any.
SourceLocation ModuleImportLoc;
/// \brief The module import path that we're currently processing.
llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2>
ModuleImportPath;
/// \brief Whether the module import expectes an identifier next. Otherwise,
/// it expects a '.' or ';'.
bool ModuleImportExpectsIdentifier;
/// \brief The source location of the currently-active
/// #pragma clang arc_cf_code_audited begin.
SourceLocation PragmaARCCFCodeAuditedLoc;

View File

@ -1070,6 +1070,12 @@ static void compileModule(CompilerInstance &ImportingInstance,
ModuleKey CompilerInstance::loadModule(SourceLocation ImportLoc,
ModuleIdPath Path) {
// If we've already handled this import, just return the cached result.
// This one-element cache is important to eliminate redundant diagnostics
// when both the preprocessor and parser see the same import declaration.
if (!ImportLoc.isInvalid() && LastModuleImportLoc == ImportLoc)
return LastModuleImportResult.getOpaqueValue();
// Determine what file we're searching from.
SourceManager &SourceMgr = getSourceManager();
SourceLocation ExpandedImportLoc = SourceMgr.getExpansionLoc(ImportLoc);
@ -1241,6 +1247,8 @@ ModuleKey CompilerInstance::loadModule(SourceLocation ImportLoc,
// FIXME: The module file's FileEntry makes a poor key indeed! Once we
// eliminate the need for FileEntry here, the module itself will become the
// key (which does make sense).
LastModuleImportLoc = ImportLoc;
LastModuleImportResult = Known;
return Known.getOpaqueValue();
}

View File

@ -546,6 +546,8 @@ void Preprocessor::HandleIdentifier(Token &Identifier) {
if (II.getTokenID() == tok::kw___import_module__ &&
!InMacroArgs && !DisableMacroExpansion) {
ModuleImportLoc = Identifier.getLocation();
ModuleImportPath.clear();
ModuleImportExpectsIdentifier = true;
CurLexerKind = CLK_LexAfterModuleImport;
}
}
@ -567,19 +569,31 @@ void Preprocessor::LexAfterModuleImport(Token &Result) {
// The token sequence
//
// __import_module__ identifier
// __import_module__ identifier (. identifier)*
//
// indicates a module import directive. We already saw the __import_module__
// keyword, so now we're looking for the identifier.
if (Result.getKind() != tok::identifier)
// keyword, so now we're looking for the identifiers.
if (ModuleImportExpectsIdentifier && Result.getKind() == tok::identifier) {
// We expected to see an identifier here, and we did; continue handling
// identifiers.
ModuleImportPath.push_back(std::make_pair(Result.getIdentifierInfo(),
Result.getLocation()));
ModuleImportExpectsIdentifier = false;
CurLexerKind = CLK_LexAfterModuleImport;
return;
}
// Load the module.
llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> Path;
Path.push_back(std::make_pair(Result.getIdentifierInfo(),
Result.getLocation()));
(void)TheModuleLoader.loadModule(ModuleImportLoc, Path);
// If we're expecting a '.' or a ';', and we got a '.', then wait until we
// see the next identifier.
if (!ModuleImportExpectsIdentifier && Result.getKind() == tok::period) {
ModuleImportExpectsIdentifier = true;
CurLexerKind = CLK_LexAfterModuleImport;
return;
}
// If we have a non-empty module path, load the named module.
if (!ModuleImportPath.empty())
(void)TheModuleLoader.loadModule(ModuleImportLoc, ModuleImportPath);
}
void Preprocessor::AddCommentHandler(CommentHandler *Handler) {