forked from OSchip/llvm-project
Introduce a module import declaration, so that we properly represent, e.g.,
__import_module__ std.vector; in the AST. llvm-svn: 145725
This commit is contained in:
parent
45ccba64ab
commit
ba34552e79
|
@ -40,7 +40,8 @@ class DependentFunctionTemplateSpecializationInfo;
|
|||
class TypeLoc;
|
||||
class UnresolvedSetImpl;
|
||||
class LabelStmt;
|
||||
|
||||
class Module;
|
||||
|
||||
/// \brief A container of type source information.
|
||||
///
|
||||
/// A client can read the relevant info using TypeLoc wrappers, e.g:
|
||||
|
@ -3075,6 +3076,69 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/// \brief Describes a module import declaration, which makes the contents
|
||||
/// of the named module visible in the current translation unit.
|
||||
///
|
||||
/// An import declaration imports the named module (or submodule). For example:
|
||||
/// \code
|
||||
/// __import_module__ std.vector;
|
||||
/// \endcode
|
||||
///
|
||||
/// Import declarations can also be implicitly generated from #include/#import
|
||||
/// directives.
|
||||
class ImportDecl : public Decl {
|
||||
/// \brief The imported module, along with a bit that indicates whether
|
||||
/// we have source-location information for each identifier in the module
|
||||
/// name.
|
||||
///
|
||||
/// When the bit is false, we only have a single source location for the
|
||||
/// end of the import declaration.
|
||||
llvm::PointerIntPair<Module *, 1, bool> ImportedAndComplete;
|
||||
|
||||
friend class ASTReader;
|
||||
friend class ASTDeclReader;
|
||||
|
||||
ImportDecl(DeclContext *DC, SourceLocation ImportLoc, Module *Imported,
|
||||
ArrayRef<SourceLocation> IdentifierLocs);
|
||||
|
||||
ImportDecl(DeclContext *DC, SourceLocation ImportLoc, Module *Imported,
|
||||
SourceLocation EndLoc);
|
||||
|
||||
ImportDecl(EmptyShell Empty) : Decl(Import, Empty) { }
|
||||
|
||||
public:
|
||||
/// \brief Create a new module import declaration.
|
||||
static ImportDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation ImportLoc, Module *Imported,
|
||||
ArrayRef<SourceLocation> IdentifierLocs);
|
||||
|
||||
/// \brief Create a new module import declaration for an implicitly-generated
|
||||
/// import.
|
||||
static ImportDecl *CreateImplicit(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation ImportLoc, Module *Imported,
|
||||
SourceLocation EndLoc);
|
||||
|
||||
/// \brief Create a new module import declaration.
|
||||
static ImportDecl *CreateEmpty(ASTContext &C, unsigned NumLocations);
|
||||
|
||||
/// \brief Retrieve the module that was imported by the import declaration.
|
||||
Module *getImportedModule() const { return ImportedAndComplete.getPointer(); }
|
||||
|
||||
/// \brief Retrieves the locations of each of the identifiers that make up
|
||||
/// the complete module name in the import declaration.
|
||||
///
|
||||
/// This will return an empty array if the locations of the individual
|
||||
/// identifiers aren't available.
|
||||
ArrayRef<SourceLocation> getIdentifierLocs() const;
|
||||
|
||||
virtual SourceRange getSourceRange() const;
|
||||
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const ImportDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == Import; }
|
||||
};
|
||||
|
||||
|
||||
/// Insertion operator for diagnostics. This allows sending NamedDecl's
|
||||
/// into a diagnostic with <<.
|
||||
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
|
||||
|
|
|
@ -1131,6 +1131,8 @@ DEF_TRAVERSE_DECL(FileScopeAsmDecl, {
|
|||
TRY_TO(TraverseStmt(D->getAsmString()));
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_DECL(ImportDecl, { })
|
||||
|
||||
DEF_TRAVERSE_DECL(FriendDecl, {
|
||||
// Friend is either decl or a type.
|
||||
if (D->getFriendType())
|
||||
|
|
|
@ -75,3 +75,5 @@ def FriendTemplate : Decl;
|
|||
def StaticAssert : Decl;
|
||||
def Block : Decl, DeclContext;
|
||||
def ClassScopeFunctionSpecialization : Decl;
|
||||
def Import : Decl;
|
||||
|
||||
|
|
|
@ -909,7 +909,9 @@ namespace clang {
|
|||
DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK,
|
||||
/// \brief A ClassScopeFunctionSpecializationDecl record a class scope
|
||||
/// function specialization. (Microsoft extension).
|
||||
DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION
|
||||
DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION,
|
||||
/// \brief An ImportDecl recording a module import.
|
||||
DECL_IMPORT
|
||||
};
|
||||
|
||||
/// \brief Record codes for each kind of statement or expression.
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "clang/AST/ASTMutationListener.h"
|
||||
#include "clang/Basic/Builtins.h"
|
||||
#include "clang/Basic/IdentifierTable.h"
|
||||
#include "clang/Basic/Module.h"
|
||||
#include "clang/Basic/Specifiers.h"
|
||||
#include "clang/Basic/TargetInfo.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
|
@ -2609,3 +2610,81 @@ FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C, DeclContext *DC,
|
|||
SourceLocation RParenLoc) {
|
||||
return new (C) FileScopeAsmDecl(DC, Str, AsmLoc, RParenLoc);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ImportDecl Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// \brief Retrieve the number of module identifiers needed to name the given
|
||||
/// module.
|
||||
static unsigned getNumModuleIdentifiers(Module *Mod) {
|
||||
unsigned Result = 1;
|
||||
while (Mod->Parent) {
|
||||
Mod = Mod->Parent;
|
||||
++Result;
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
ImportDecl::ImportDecl(DeclContext *DC, SourceLocation ImportLoc,
|
||||
Module *Imported,
|
||||
ArrayRef<SourceLocation> IdentifierLocs)
|
||||
: Decl(Import, DC, ImportLoc), ImportedAndComplete(Imported, true)
|
||||
{
|
||||
assert(getNumModuleIdentifiers(Imported) == IdentifierLocs.size());
|
||||
SourceLocation *StoredLocs = reinterpret_cast<SourceLocation *>(this + 1);
|
||||
memcpy(StoredLocs, IdentifierLocs.data(),
|
||||
IdentifierLocs.size() * sizeof(SourceLocation));
|
||||
}
|
||||
|
||||
ImportDecl::ImportDecl(DeclContext *DC, SourceLocation ImportLoc,
|
||||
Module *Imported, SourceLocation EndLoc)
|
||||
: Decl(Import, DC, ImportLoc), ImportedAndComplete(Imported, false)
|
||||
{
|
||||
*reinterpret_cast<SourceLocation *>(this + 1) = EndLoc;
|
||||
}
|
||||
|
||||
ImportDecl *ImportDecl::Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation ImportLoc, Module *Imported,
|
||||
ArrayRef<SourceLocation> IdentifierLocs) {
|
||||
void *Mem = C.Allocate(sizeof(ImportDecl) +
|
||||
IdentifierLocs.size() * sizeof(SourceLocation));
|
||||
return new (Mem) ImportDecl(DC, ImportLoc, Imported, IdentifierLocs);
|
||||
}
|
||||
|
||||
ImportDecl *ImportDecl::CreateImplicit(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation ImportLoc,
|
||||
Module *Imported,
|
||||
SourceLocation EndLoc) {
|
||||
void *Mem = C.Allocate(sizeof(ImportDecl) + sizeof(SourceLocation));
|
||||
ImportDecl *Import
|
||||
= new (Mem) ImportDecl(DC, ImportLoc, Imported,
|
||||
ArrayRef<SourceLocation>(&EndLoc, 1));
|
||||
Import->setImplicit();
|
||||
return Import;
|
||||
}
|
||||
|
||||
ImportDecl *ImportDecl::CreateEmpty(ASTContext &C, unsigned NumLocations) {
|
||||
void *Mem = C.Allocate(sizeof(ImportDecl) +
|
||||
NumLocations * sizeof(SourceLocation));
|
||||
return new (Mem) ImportDecl(EmptyShell());
|
||||
}
|
||||
|
||||
ArrayRef<SourceLocation> ImportDecl::getIdentifierLocs() const {
|
||||
if (!ImportedAndComplete.getInt())
|
||||
return ArrayRef<SourceLocation>();
|
||||
|
||||
const SourceLocation *StoredLocs
|
||||
= reinterpret_cast<const SourceLocation *>(this + 1);
|
||||
return ArrayRef<SourceLocation>(StoredLocs,
|
||||
getNumModuleIdentifiers(getImportedModule()));
|
||||
}
|
||||
|
||||
SourceRange ImportDecl::getSourceRange() const {
|
||||
if (!ImportedAndComplete.getInt())
|
||||
return SourceRange(getLocation(),
|
||||
*reinterpret_cast<const SourceLocation *>(this + 1));
|
||||
|
||||
return SourceRange(getLocation(), getIdentifierLocs().back());
|
||||
}
|
||||
|
||||
|
|
|
@ -501,6 +501,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
|
|||
case ObjCImplementation:
|
||||
case ObjCCategory:
|
||||
case ObjCCategoryImpl:
|
||||
case Import:
|
||||
// Never looked up by name.
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "clang/AST/Expr.h"
|
||||
#include "clang/AST/ExprCXX.h"
|
||||
#include "clang/AST/PrettyPrinter.h"
|
||||
#include "clang/Basic/Module.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
using namespace clang;
|
||||
|
||||
|
@ -58,6 +59,7 @@ namespace {
|
|||
void VisitLabelDecl(LabelDecl *D);
|
||||
void VisitParmVarDecl(ParmVarDecl *D);
|
||||
void VisitFileScopeAsmDecl(FileScopeAsmDecl *D);
|
||||
void VisitImportDecl(ImportDecl *D);
|
||||
void VisitStaticAssertDecl(StaticAssertDecl *D);
|
||||
void VisitNamespaceDecl(NamespaceDecl *D);
|
||||
void VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
|
||||
|
@ -646,6 +648,11 @@ void DeclPrinter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) {
|
|||
Out << ")";
|
||||
}
|
||||
|
||||
void DeclPrinter::VisitImportDecl(ImportDecl *D) {
|
||||
Out << "__import_module__ " << D->getImportedModule()->getFullModuleName()
|
||||
<< ";\n";
|
||||
}
|
||||
|
||||
void DeclPrinter::VisitStaticAssertDecl(StaticAssertDecl *D) {
|
||||
Out << "static_assert(";
|
||||
D->getAssertExpr()->printPretty(Out, Context, 0, Policy, Indentation);
|
||||
|
|
|
@ -84,6 +84,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
|
|||
case Decl::NamespaceAlias:
|
||||
case Decl::StaticAssert: // static_assert(X, ""); [C++0x]
|
||||
case Decl::Label: // __label__ x;
|
||||
case Decl::Import:
|
||||
// None of these decls require codegen support.
|
||||
return;
|
||||
|
||||
|
|
|
@ -2335,6 +2335,7 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
|
|||
case Decl::TypeAliasTemplate:
|
||||
case Decl::NamespaceAlias:
|
||||
case Decl::Block:
|
||||
case Decl::Import:
|
||||
break;
|
||||
case Decl::CXXConstructor:
|
||||
// Skip function templates
|
||||
|
|
|
@ -9897,9 +9897,24 @@ DeclResult Sema::ActOnModuleImport(SourceLocation ImportLoc, ModuleIdPath Path)
|
|||
if (!Mod)
|
||||
return true;
|
||||
|
||||
// FIXME: Actually create a declaration to describe the module import.
|
||||
(void)Mod;
|
||||
return DeclResult((Decl *)0);
|
||||
llvm::SmallVector<SourceLocation, 2> IdentifierLocs;
|
||||
Module *ModCheck = Mod;
|
||||
for (unsigned I = 0, N = Path.size(); I != N; ++I) {
|
||||
// If we've run out of module parents, just drop the remaining identifiers.
|
||||
// We need the length to be consistent.
|
||||
if (!ModCheck)
|
||||
break;
|
||||
ModCheck = ModCheck->Parent;
|
||||
|
||||
IdentifierLocs.push_back(Path[I].second);
|
||||
}
|
||||
|
||||
ImportDecl *Import = ImportDecl::Create(Context,
|
||||
Context.getTranslationUnitDecl(),
|
||||
ImportLoc, Mod,
|
||||
IdentifierLocs);
|
||||
Context.getTranslationUnitDecl()->addDecl(Import);
|
||||
return Import;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -94,6 +94,10 @@ namespace clang {
|
|||
return Reader.getGlobalSubmoduleID(F, R[I++]);
|
||||
}
|
||||
|
||||
Module *readModule(const RecordData &R, unsigned &I) {
|
||||
return Reader.getSubmodule(readSubmoduleID(R, I));
|
||||
}
|
||||
|
||||
void ReadCXXDefinitionData(struct CXXRecordDecl::DefinitionData &Data,
|
||||
const RecordData &R, unsigned &I);
|
||||
|
||||
|
@ -168,6 +172,7 @@ namespace clang {
|
|||
void VisitUsingShadowDecl(UsingShadowDecl *D);
|
||||
void VisitLinkageSpecDecl(LinkageSpecDecl *D);
|
||||
void VisitFileScopeAsmDecl(FileScopeAsmDecl *AD);
|
||||
void VisitImportDecl(ImportDecl *D);
|
||||
void VisitAccessSpecDecl(AccessSpecDecl *D);
|
||||
void VisitFriendDecl(FriendDecl *D);
|
||||
void VisitFriendTemplateDecl(FriendTemplateDecl *D);
|
||||
|
@ -1054,6 +1059,16 @@ void ASTDeclReader::VisitCXXConversionDecl(CXXConversionDecl *D) {
|
|||
D->IsExplicitSpecified = Record[Idx++];
|
||||
}
|
||||
|
||||
void ASTDeclReader::VisitImportDecl(ImportDecl *D) {
|
||||
VisitDecl(D);
|
||||
D->ImportedAndComplete.setPointer(readModule(Record, Idx));
|
||||
D->ImportedAndComplete.setInt(Record[Idx++]);
|
||||
SourceLocation *StoredLocs = reinterpret_cast<SourceLocation *>(D + 1);
|
||||
for (unsigned I = 0, N = Record.back(); I != N; ++I)
|
||||
StoredLocs[I] = ReadSourceLocation(Record, Idx);
|
||||
++Idx;
|
||||
}
|
||||
|
||||
void ASTDeclReader::VisitAccessSpecDecl(AccessSpecDecl *D) {
|
||||
VisitDecl(D);
|
||||
D->setColonLoc(ReadSourceLocation(Record, Idx));
|
||||
|
@ -1760,6 +1775,11 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
|
|||
case DECL_CXX_BASE_SPECIFIERS:
|
||||
Error("attempt to read a C++ base-specifier record as a declaration");
|
||||
return 0;
|
||||
case DECL_IMPORT:
|
||||
// Note: last entry of the ImportDecl record is the number of stored source
|
||||
// locations.
|
||||
D = ImportDecl::CreateEmpty(Context, Record.back());
|
||||
break;
|
||||
}
|
||||
|
||||
assert(D && "Unknown declaration reading AST file");
|
||||
|
|
|
@ -94,6 +94,7 @@ namespace clang {
|
|||
void VisitUsingShadowDecl(UsingShadowDecl *D);
|
||||
void VisitLinkageSpecDecl(LinkageSpecDecl *D);
|
||||
void VisitFileScopeAsmDecl(FileScopeAsmDecl *D);
|
||||
void VisitImportDecl(ImportDecl *D);
|
||||
void VisitAccessSpecDecl(AccessSpecDecl *D);
|
||||
void VisitFriendDecl(FriendDecl *D);
|
||||
void VisitFriendTemplateDecl(FriendTemplateDecl *D);
|
||||
|
@ -972,6 +973,24 @@ void ASTDeclWriter::VisitCXXConversionDecl(CXXConversionDecl *D) {
|
|||
Code = serialization::DECL_CXX_CONVERSION;
|
||||
}
|
||||
|
||||
void ASTDeclWriter::VisitImportDecl(ImportDecl *D) {
|
||||
VisitDecl(D);
|
||||
Writer.SubmoduleIDs[D->getImportedModule()];
|
||||
ArrayRef<SourceLocation> IdentifierLocs = D->getIdentifierLocs();
|
||||
Record.push_back(!IdentifierLocs.empty());
|
||||
if (IdentifierLocs.empty()) {
|
||||
Writer.AddSourceLocation(D->getLocEnd(), Record);
|
||||
Record.push_back(1);
|
||||
} else {
|
||||
for (unsigned I = 0, N = IdentifierLocs.size(); I != N; ++I)
|
||||
Writer.AddSourceLocation(IdentifierLocs[I], Record);
|
||||
Record.push_back(IdentifierLocs.size());
|
||||
}
|
||||
// Note: the number of source locations must always be the last element in
|
||||
// the record.
|
||||
Code = serialization::DECL_IMPORT;
|
||||
}
|
||||
|
||||
void ASTDeclWriter::VisitAccessSpecDecl(AccessSpecDecl *D) {
|
||||
VisitDecl(D);
|
||||
Writer.AddSourceLocation(D->getColonLoc(), Record);
|
||||
|
|
|
@ -4000,6 +4000,7 @@ CXCursor clang_getCursorDefinition(CXCursor C) {
|
|||
case Decl::Block:
|
||||
case Decl::Label: // FIXME: Is this right??
|
||||
case Decl::ClassScopeFunctionSpecialization:
|
||||
case Decl::Import:
|
||||
return C;
|
||||
|
||||
// Declaration kinds that don't make any sense here, but are
|
||||
|
|
Loading…
Reference in New Issue