diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-11-30 04:26:53 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-11-30 04:26:53 +0000 |
commit | b514c792821a8f053027d88444e13bfaa8efef76 (patch) | |
tree | 123cd461e4098e78e066dcef4281686d30674fa5 | |
parent | 49009ec701feb3009450e57e40c656e2ad7c1f41 (diff) |
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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@145478 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Frontend/CompilerInstance.h | 8 | ||||
-rw-r--r-- | include/clang/Lex/Preprocessor.h | 8 | ||||
-rw-r--r-- | lib/Frontend/CompilerInstance.cpp | 8 | ||||
-rw-r--r-- | lib/Lex/Preprocessor.cpp | 32 |
4 files changed, 47 insertions, 9 deletions
diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h index 90de3138a4..09b27e14df 100644 --- a/include/clang/Frontend/CompilerInstance.h +++ b/include/clang/Frontend/CompilerInstance.h @@ -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. diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index cf77824120..671d6ae986 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -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; diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index dfc98e8bfb..66b381e522 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -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(); } diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp index aeba32f96a..b01113041e 100644 --- a/lib/Lex/Preprocessor.cpp +++ b/lib/Lex/Preprocessor.cpp @@ -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) { |