Switch the module-loading interfaces and parser from a simple

top-level module name to a module path (e.g., std.vector). We're still
missing a number of pieces for this actually to do something.

llvm-svn: 145462
This commit is contained in:
Douglas Gregor 2011-11-30 00:36:36 +00:00
parent 607fb70750
commit 71944203de
9 changed files with 69 additions and 51 deletions

View File

@ -781,9 +781,7 @@ public:
/// \returns True if an error occurred, false otherwise.
bool serialize(raw_ostream &OS);
virtual ModuleKey loadModule(SourceLocation ImportLoc,
IdentifierInfo &ModuleName,
SourceLocation ModuleNameLoc) {
virtual ModuleKey loadModule(SourceLocation ImportLoc, ModuleIdPath Path) {
// ASTUnit doesn't know how to load modules (not that this matters).
return 0;
}

View File

@ -12,12 +12,14 @@
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Lex/ModuleLoader.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/OwningPtr.h"
#include <cassert>
#include <list>
#include <string>
#include <utility>
namespace llvm {
class raw_fd_ostream;
@ -624,9 +626,7 @@ public:
/// }
virtual ModuleKey loadModule(SourceLocation ImportLoc,
IdentifierInfo &ModuleName,
SourceLocation ModuleNameLoc);
virtual ModuleKey loadModule(SourceLocation ImportLoc, ModuleIdPath Path);
};
} // end namespace clang

View File

@ -15,6 +15,7 @@
#define LLVM_CLANG_LEX_MODULE_LOADER_H
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/ArrayRef.h"
namespace clang {
@ -24,6 +25,10 @@ class IdentifierInfo;
/// interpreted by the module loader itself.
typedef void *ModuleKey;
/// \brief A sequence of identifier/location pairs used to describe a particular
/// module or submodule, e.g., std.vector.
typedef llvm::ArrayRef<std::pair<IdentifierInfo*, SourceLocation> > ModuleIdPath;
/// \brief Abstract interface for a module loader.
///
/// This abstract interface describes a module loader, which is responsible
@ -39,15 +44,13 @@ public:
/// parameters.
///
/// \param ImportLoc The location of the 'import' keyword.
/// \param ModuleName The name of the module to be loaded.
/// \param ModuleNameLoc The location of the module name.
/// \param Path The identifiers (and their locations) of the module
/// "path", e.g., "std.vector" would be split into "std" and "vector".
///
/// \returns If successful, a non-NULL module key describing this module.
/// Otherwise, returns NULL to indicate that the module could not be
/// loaded.
virtual ModuleKey loadModule(SourceLocation ImportLoc,
IdentifierInfo &ModuleName,
SourceLocation ModuleNameLoc) = 0;
virtual ModuleKey loadModule(SourceLocation ImportLoc, ModuleIdPath Path) = 0;
};
}

View File

@ -29,6 +29,7 @@
#include "clang/AST/DeclarationName.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Lex/ModuleLoader.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/TemplateKinds.h"
#include "clang/Basic/TypeTraits.h"
@ -1109,12 +1110,8 @@ public:
///
/// \param ImportLoc The location of the '__import_module__' keyword.
///
/// \param ModuleName The name of the module.
///
/// \param ModuleNameLoc The location of the module name.
DeclResult ActOnModuleImport(SourceLocation ImportLoc,
IdentifierInfo &ModuleName,
SourceLocation ModuleNameLoc);
/// \param Path The module access path.
DeclResult ActOnModuleImport(SourceLocation ImportLoc, ModuleIdPath Path);
/// \brief Diagnose that \p New is a module-private redeclaration of
/// \p Old.

View File

@ -1068,9 +1068,8 @@ static void compileModule(CompilerInstance &ImportingInstance,
llvm::sys::Path(TempModuleMapFileName).eraseFromDisk();
}
ModuleKey CompilerInstance::loadModule(SourceLocation ImportLoc,
IdentifierInfo &ModuleName,
SourceLocation ModuleNameLoc) {
ModuleKey CompilerInstance::loadModule(SourceLocation ImportLoc,
ModuleIdPath Path) {
// Determine what file we're searching from.
SourceManager &SourceMgr = getSourceManager();
SourceLocation ExpandedImportLoc = SourceMgr.getExpansionLoc(ImportLoc);
@ -1079,13 +1078,19 @@ ModuleKey CompilerInstance::loadModule(SourceLocation ImportLoc,
if (!CurFile)
CurFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
StringRef ModuleName = Path[0].first->getName();
SourceLocation ModuleNameLoc = Path[0].second;
// Search for a module with the given name.
ModuleMap::Module *Module = 0;
std::string ModuleFileName;
const FileEntry *ModuleFile
= PP->getHeaderSearchInfo().lookupModule(ModuleName.getName(), Module,
= PP->getHeaderSearchInfo().lookupModule(ModuleName, Module,
&ModuleFileName);
// FIXME: Verify that the rest of the module path actually corresponds to
// a submodule, and pass that information through.
bool BuildingModule = false;
if (!ModuleFile && Module) {
// The module is not cached, but we have a module map from which we can
@ -1095,23 +1100,22 @@ ModuleKey CompilerInstance::loadModule(SourceLocation ImportLoc,
SmallVectorImpl<std::string> &ModuleBuildPath
= getPreprocessorOpts().ModuleBuildPath;
SmallVectorImpl<std::string>::iterator Pos
= std::find(ModuleBuildPath.begin(), ModuleBuildPath.end(),
ModuleName.getName());
= std::find(ModuleBuildPath.begin(), ModuleBuildPath.end(), ModuleName);
if (Pos != ModuleBuildPath.end()) {
llvm::SmallString<256> CyclePath;
for (; Pos != ModuleBuildPath.end(); ++Pos) {
CyclePath += *Pos;
CyclePath += " -> ";
}
CyclePath += ModuleName.getName();
CyclePath += ModuleName;
getDiagnostics().Report(ModuleNameLoc, diag::err_module_cycle)
<< ModuleName.getName() << CyclePath;
<< ModuleName << CyclePath;
return 0;
}
getDiagnostics().Report(ModuleNameLoc, diag::warn_module_build)
<< ModuleName.getName();
<< ModuleName;
BuildingModule = true;
compileModule(*this, Module, ModuleFileName);
ModuleFile = FileMgr->getFile(ModuleFileName);
@ -1121,7 +1125,7 @@ ModuleKey CompilerInstance::loadModule(SourceLocation ImportLoc,
getDiagnostics().Report(ModuleNameLoc,
BuildingModule? diag::err_module_not_built
: diag::err_module_not_found)
<< ModuleName.getName()
<< ModuleName
<< SourceRange(ImportLoc, ModuleNameLoc);
return 0;
}

View File

@ -1279,13 +1279,17 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
// If we are supposed to import a module rather than including the header,
// do so now.
if (SuggestedModule) {
// FIXME: Actually load the submodule that we were given.
while (SuggestedModule->Parent)
SuggestedModule = SuggestedModule->Parent;
TheModuleLoader.loadModule(IncludeTok.getLocation(),
Identifiers.get(SuggestedModule->Name),
FilenameTok.getLocation());
// Compute the module access path corresponding to this module.
// FIXME: Should we have a second loadModule() overload to avoid this
// extra lookup step?
llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> Path;
for (ModuleMap::Module *Mod = SuggestedModule; Mod; Mod = Mod->Parent)
Path.push_back(std::make_pair(getIdentifierInfo(Mod->Name),
FilenameTok.getLocation()));
std::reverse(Path.begin(), Path.end());
// Load the module.
TheModuleLoader.loadModule(IncludeTok.getLocation(), Path);
return;
}

View File

@ -575,9 +575,11 @@ void Preprocessor::LexAfterModuleImport(Token &Result) {
return;
// Load the module.
(void)TheModuleLoader.loadModule(ModuleImportLoc,
*Result.getIdentifierInfo(),
Result.getLocation());
llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> Path;
Path.push_back(std::make_pair(Result.getIdentifierInfo(),
Result.getLocation()));
(void)TheModuleLoader.loadModule(ModuleImportLoc, Path);
}
void Preprocessor::AddCommentHandler(CommentHandler *Handler) {

View File

@ -1570,16 +1570,29 @@ Parser::DeclGroupPtrTy Parser::ParseModuleImport() {
"Improper start to module import");
SourceLocation ImportLoc = ConsumeToken();
// Parse the module name.
if (!Tok.is(tok::identifier)) {
Diag(Tok, diag::err_module_expected_ident);
SkipUntil(tok::semi);
return DeclGroupPtrTy();
}
llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> Path;
IdentifierInfo &ModuleName = *Tok.getIdentifierInfo();
SourceLocation ModuleNameLoc = ConsumeToken();
DeclResult Import = Actions.ActOnModuleImport(ImportLoc, ModuleName, ModuleNameLoc);
// Parse the module path.
do {
if (!Tok.is(tok::identifier)) {
Diag(Tok, diag::err_module_expected_ident);
SkipUntil(tok::semi);
return DeclGroupPtrTy();
}
// Record this part of the module path.
Path.push_back(std::make_pair(Tok.getIdentifierInfo(), Tok.getLocation()));
ConsumeToken();
if (Tok.is(tok::period)) {
ConsumeToken();
continue;
}
break;
} while (true);
DeclResult Import = Actions.ActOnModuleImport(ImportLoc, Path);
ExpectAndConsumeSemi(diag::err_module_expected_semi);
if (Import.isInvalid())
return DeclGroupPtrTy();

View File

@ -9891,11 +9891,8 @@ Decl *Sema::ActOnFileScopeAsmDecl(Expr *expr,
return New;
}
DeclResult Sema::ActOnModuleImport(SourceLocation ImportLoc,
IdentifierInfo &ModuleName,
SourceLocation ModuleNameLoc) {
ModuleKey Module = PP.getModuleLoader().loadModule(ImportLoc,
ModuleName, ModuleNameLoc);
DeclResult Sema::ActOnModuleImport(SourceLocation ImportLoc, ModuleIdPath Path) {
ModuleKey Module = PP.getModuleLoader().loadModule(ImportLoc, Path);
if (!Module)
return true;