Keep track of all of the import declarations that are parsed or

implicitly generated in a translation unit. Modules will need this
information to identify the actual imports that occurred.

llvm-svn: 145734
This commit is contained in:
Douglas Gregor 2011-12-03 00:30:27 +00:00
parent 934cb05e40
commit 0f2a3607e0
5 changed files with 85 additions and 4 deletions

View File

@ -326,6 +326,9 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
typedef llvm::DenseMap<const VarDecl *, unsigned> ParameterIndexTable;
ParameterIndexTable ParamIndices;
ImportDecl *FirstLocalImport;
ImportDecl *LastLocalImport;
TranslationUnitDecl *TUDecl;
/// SourceMgr - The associated SourceManager object.
@ -481,6 +484,56 @@ public:
void addOverriddenMethod(const CXXMethodDecl *Method,
const CXXMethodDecl *Overridden);
/// \brief Notify the AST context that a new import declaration has been
/// parsed or implicitly created within this translation unit.
void addedLocalImportDecl(ImportDecl *Import);
static ImportDecl *getNextLocalImport(ImportDecl *Import) {
return Import->NextLocalImport;
}
/// \brief Iterator that visits import declarations.
class import_iterator {
ImportDecl *Import;
public:
typedef ImportDecl *value_type;
typedef ImportDecl *reference;
typedef ImportDecl *pointer;
typedef int difference_type;
typedef std::forward_iterator_tag iterator_category;
import_iterator() : Import() { }
explicit import_iterator(ImportDecl *Import) : Import(Import) { }
reference operator*() const { return Import; }
pointer operator->() const { return Import; }
import_iterator &operator++() {
Import = ASTContext::getNextLocalImport(Import);
return *this;
}
import_iterator operator++(int) {
import_iterator Other(*this);
++(*this);
return Other;
}
friend bool operator==(import_iterator X, import_iterator Y) {
return X.Import == Y.Import;
}
friend bool operator!=(import_iterator X, import_iterator Y) {
return X.Import != Y.Import;
}
};
import_iterator local_import_begin() const {
return import_iterator(FirstLocalImport);
}
import_iterator local_import_end() const { return import_iterator(); }
TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; }

View File

@ -3095,8 +3095,13 @@ class ImportDecl : public Decl {
/// end of the import declaration.
llvm::PointerIntPair<Module *, 1, bool> ImportedAndComplete;
/// \brief The next import in the list of imports local to the translation
/// unit being parsed (not loaded from an AST file).
ImportDecl *NextLocalImport;
friend class ASTReader;
friend class ASTDeclReader;
friend class ASTContext;
ImportDecl(DeclContext *DC, SourceLocation ImportLoc, Module *Imported,
ArrayRef<SourceLocation> IdentifierLocs);
@ -3104,7 +3109,7 @@ class ImportDecl : public Decl {
ImportDecl(DeclContext *DC, SourceLocation ImportLoc, Module *Imported,
SourceLocation EndLoc);
ImportDecl(EmptyShell Empty) : Decl(Import, Empty) { }
ImportDecl(EmptyShell Empty) : Decl(Import, Empty), NextLocalImport() { }
public:
/// \brief Create a new module import declaration.

View File

@ -230,7 +230,8 @@ ASTContext::ASTContext(LangOptions& LOpts, SourceManager &SM,
jmp_bufDecl(0), sigjmp_bufDecl(0), ucontext_tDecl(0),
BlockDescriptorType(0), BlockDescriptorExtendedType(0),
cudaConfigureCallDecl(0),
NullTypeSourceInfo(QualType()),
NullTypeSourceInfo(QualType()),
FirstLocalImport(), LastLocalImport(),
SourceMgr(SM), LangOpts(LOpts),
AddrSpaceMap(0), Target(t), PrintingPolicy(LOpts),
Idents(idents), Selectors(sels),
@ -682,6 +683,19 @@ void ASTContext::addOverriddenMethod(const CXXMethodDecl *Method,
OverriddenMethods[Method].push_back(Overridden);
}
void ASTContext::addedLocalImportDecl(ImportDecl *Import) {
assert(!Import->NextLocalImport && "Import declaration already in the chain");
assert(!Import->isFromASTFile() && "Non-local import declaration");
if (!FirstLocalImport) {
FirstLocalImport = Import;
LastLocalImport = Import;
return;
}
LastLocalImport->NextLocalImport = Import;
LastLocalImport = Import;
}
//===----------------------------------------------------------------------===//
// Type Sizing and Analysis
//===----------------------------------------------------------------------===//

View File

@ -2629,7 +2629,8 @@ static unsigned getNumModuleIdentifiers(Module *Mod) {
ImportDecl::ImportDecl(DeclContext *DC, SourceLocation ImportLoc,
Module *Imported,
ArrayRef<SourceLocation> IdentifierLocs)
: Decl(Import, DC, ImportLoc), ImportedAndComplete(Imported, true)
: Decl(Import, DC, ImportLoc), ImportedAndComplete(Imported, true),
NextLocalImport()
{
assert(getNumModuleIdentifiers(Imported) == IdentifierLocs.size());
SourceLocation *StoredLocs = reinterpret_cast<SourceLocation *>(this + 1);
@ -2639,7 +2640,8 @@ ImportDecl::ImportDecl(DeclContext *DC, SourceLocation ImportLoc,
ImportDecl::ImportDecl(DeclContext *DC, SourceLocation ImportLoc,
Module *Imported, SourceLocation EndLoc)
: Decl(Import, DC, ImportLoc), ImportedAndComplete(Imported, false)
: Decl(Import, DC, ImportLoc), ImportedAndComplete(Imported, false),
NextLocalImport()
{
*reinterpret_cast<SourceLocation *>(this + 1) = EndLoc;
}

View File

@ -1010,6 +1010,13 @@ void DeclContext::addHiddenDecl(Decl *D) {
// update it's class-specific state.
if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(this))
Record->addedMember(D);
// If this is a newly-created (not de-serialized) import declaration, wire
// it in to the list of local import declarations.
if (!D->isFromASTFile()) {
if (ImportDecl *Import = dyn_cast<ImportDecl>(D))
D->getASTContext().addedLocalImportDecl(Import);
}
}
void DeclContext::addDecl(Decl *D) {