mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
WIP Update to use clang::ModuleMacro instead of clang::MacroInfo.
Untested and still missing a few pieces.
This commit is contained in:
@@ -18,6 +18,7 @@
|
|||||||
namespace clang {
|
namespace clang {
|
||||||
class Decl;
|
class Decl;
|
||||||
class MacroInfo;
|
class MacroInfo;
|
||||||
|
class ModuleMacro;
|
||||||
class Module;
|
class Module;
|
||||||
class SourceLocation;
|
class SourceLocation;
|
||||||
class SourceRange;
|
class SourceRange;
|
||||||
@@ -40,18 +41,21 @@ namespace detail {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents a clang declaration, macro, or module.
|
/// Represents a clang declaration, macro, or module. A macro definition
|
||||||
|
/// imported from a module is recorded as the ModuleMacro, and a macro
|
||||||
|
/// defined locally is represented by the MacroInfo.
|
||||||
class ClangNode {
|
class ClangNode {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using Box = detail::ClangNodeBox<T>;
|
using Box = detail::ClangNodeBox<T>;
|
||||||
|
|
||||||
llvm::PointerUnion3<Box<clang::Decl>, Box<clang::MacroInfo>,
|
llvm::PointerUnion4<Box<clang::Decl>, Box<clang::MacroInfo>,
|
||||||
Box<clang::Module>> Ptr;
|
Box<clang::ModuleMacro>, Box<clang::Module>> Ptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ClangNode() = default;
|
ClangNode() = default;
|
||||||
ClangNode(const clang::Decl *D) : Ptr(D) {}
|
ClangNode(const clang::Decl *D) : Ptr(D) {}
|
||||||
ClangNode(const clang::MacroInfo *MI) : Ptr(MI) {}
|
ClangNode(const clang::MacroInfo *MI) : Ptr(MI) {}
|
||||||
|
ClangNode(const clang::ModuleMacro *MM) : Ptr(MM) {}
|
||||||
ClangNode(const clang::Module *Mod) : Ptr(Mod) {}
|
ClangNode(const clang::Module *Mod) : Ptr(Mod) {}
|
||||||
|
|
||||||
bool isNull() const { return Ptr.isNull(); }
|
bool isNull() const { return Ptr.isNull(); }
|
||||||
@@ -60,9 +64,12 @@ public:
|
|||||||
const clang::Decl *getAsDecl() const {
|
const clang::Decl *getAsDecl() const {
|
||||||
return Ptr.dyn_cast<Box<clang::Decl>>().value;
|
return Ptr.dyn_cast<Box<clang::Decl>>().value;
|
||||||
}
|
}
|
||||||
const clang::MacroInfo *getAsMacro() const {
|
const clang::MacroInfo *getAsMacroInfo() const {
|
||||||
return Ptr.dyn_cast<Box<clang::MacroInfo>>().value;
|
return Ptr.dyn_cast<Box<clang::MacroInfo>>().value;
|
||||||
}
|
}
|
||||||
|
const clang::ModuleMacro *getAsModuleMacro() const {
|
||||||
|
return Ptr.dyn_cast<Box<clang::ModuleMacro>>().value;
|
||||||
|
}
|
||||||
const clang::Module *getAsModule() const {
|
const clang::Module *getAsModule() const {
|
||||||
return Ptr.dyn_cast<Box<clang::Module>>().value;
|
return Ptr.dyn_cast<Box<clang::Module>>().value;
|
||||||
}
|
}
|
||||||
@@ -70,13 +77,20 @@ public:
|
|||||||
const clang::Decl *castAsDecl() const {
|
const clang::Decl *castAsDecl() const {
|
||||||
return Ptr.get<Box<clang::Decl>>().value;
|
return Ptr.get<Box<clang::Decl>>().value;
|
||||||
}
|
}
|
||||||
const clang::MacroInfo *castAsMacro() const {
|
const clang::MacroInfo *castAsMacroInfo() const {
|
||||||
return Ptr.get<Box<clang::MacroInfo>>().value;
|
return Ptr.get<Box<clang::MacroInfo>>().value;
|
||||||
}
|
}
|
||||||
|
const clang::ModuleMacro *castAsModuleMacro() const {
|
||||||
|
return Ptr.get<Box<clang::ModuleMacro>>().value;
|
||||||
|
}
|
||||||
const clang::Module *castAsModule() const {
|
const clang::Module *castAsModule() const {
|
||||||
return Ptr.get<Box<clang::Module>>().value;
|
return Ptr.get<Box<clang::Module>>().value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the MacroInfo for a local definition, one imported from a
|
||||||
|
// ModuleMacro, or null if it's neither.
|
||||||
|
const clang::MacroInfo *getAsMacro() const;
|
||||||
|
|
||||||
/// Returns the module either the one wrapped directly, the one from a
|
/// Returns the module either the one wrapped directly, the one from a
|
||||||
/// clang::ImportDecl or null if it's neither.
|
/// clang::ImportDecl or null if it's neither.
|
||||||
const clang::Module *getClangModule() const;
|
const clang::Module *getClangModule() const;
|
||||||
|
|||||||
@@ -61,6 +61,12 @@ STATISTIC(NumLazyGenericEnvironments,
|
|||||||
STATISTIC(NumLazyGenericEnvironmentsLoaded,
|
STATISTIC(NumLazyGenericEnvironmentsLoaded,
|
||||||
"# of lazily-deserialized generic environments loaded");
|
"# of lazily-deserialized generic environments loaded");
|
||||||
|
|
||||||
|
const clang::MacroInfo *ClangNode::getAsMacro() const {
|
||||||
|
if (auto MM = getAsModuleMacro())
|
||||||
|
return MM->getMacroInfo();
|
||||||
|
return getAsMacroInfo();
|
||||||
|
}
|
||||||
|
|
||||||
clang::SourceLocation ClangNode::getLocation() const {
|
clang::SourceLocation ClangNode::getLocation() const {
|
||||||
if (auto D = getAsDecl())
|
if (auto D = getAsDecl())
|
||||||
return D->getLocation();
|
return D->getLocation();
|
||||||
|
|||||||
@@ -1878,15 +1878,21 @@ static bool isDeclaredInModule(const ClangModuleUnit *ModuleFilter,
|
|||||||
return ModuleFilter == ContainingUnit;
|
return ModuleFilter == ContainingUnit;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const clang::Module *getClangOwningModule(ClangNode Node,
|
static const clang::Module *
|
||||||
const clang::ASTContext &ClangCtx) {
|
getClangOwningModule(ClangNode Node, const clang::ASTContext &ClangCtx) {
|
||||||
|
assert(!Node.getAsModule() && "not implemented for modules");
|
||||||
|
|
||||||
|
if (const clang::Decl *D = Node.getAsDecl()) {
|
||||||
auto ExtSource = ClangCtx.getExternalSource();
|
auto ExtSource = ClangCtx.getExternalSource();
|
||||||
assert(ExtSource);
|
assert(ExtSource);
|
||||||
if (const clang::Decl *D = Node.getAsDecl())
|
|
||||||
return ExtSource->getModule(D->getOwningModuleID());
|
return ExtSource->getModule(D->getOwningModuleID());
|
||||||
if (const clang::MacroInfo *MI = Node.getAsMacro())
|
}
|
||||||
return ExtSource->getModule(MI->getOwningModuleID());
|
|
||||||
|
|
||||||
|
if (const clang::ModuleMacro *M = Node.getAsModuleMacro())
|
||||||
|
return M->getOwningModule();
|
||||||
|
|
||||||
|
// A locally-defined MacroInfo does not have an owning module.
|
||||||
|
assert(Node.getAsMacroInfo());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2075,6 +2081,17 @@ public:
|
|||||||
|
|
||||||
} // unnamed namespace
|
} // unnamed namespace
|
||||||
|
|
||||||
|
/// Translate a MacroDefinition to a ClangNode, either a ModuleMacro for
|
||||||
|
/// a definition imported from a module or a MacroInfo for a macro defined
|
||||||
|
/// locally.
|
||||||
|
ClangNode getClangNodeForMacroDefinition(clang::MacroDefinition &M) {
|
||||||
|
if (!M.getModuleMacros().empty())
|
||||||
|
return ClangNode(M.getModuleMacros().back()->getMacroInfo());
|
||||||
|
if (auto *MD = M.getLocalDirective())
|
||||||
|
return ClangNode(MD->getMacroInfo());
|
||||||
|
return ClangNode();
|
||||||
|
}
|
||||||
|
|
||||||
void ClangImporter::lookupBridgingHeaderDecls(
|
void ClangImporter::lookupBridgingHeaderDecls(
|
||||||
llvm::function_ref<bool(ClangNode)> filter,
|
llvm::function_ref<bool(ClangNode)> filter,
|
||||||
llvm::function_ref<void(Decl*)> receiver) const {
|
llvm::function_ref<void(Decl*)> receiver) const {
|
||||||
@@ -2094,10 +2111,12 @@ void ClangImporter::lookupBridgingHeaderDecls(
|
|||||||
|
|
||||||
auto &ClangPP = Impl.getClangPreprocessor();
|
auto &ClangPP = Impl.getClangPreprocessor();
|
||||||
for (clang::IdentifierInfo *II : Impl.BridgeHeaderMacros) {
|
for (clang::IdentifierInfo *II : Impl.BridgeHeaderMacros) {
|
||||||
if (auto *MI = ClangPP.getMacroInfo(II)) {
|
auto MD = ClangPP.getMacroDefinition(II);
|
||||||
if (filter(MI)) {
|
if (auto macroNode = getClangNodeForMacroDefinition(MD)) {
|
||||||
|
if (filter(macroNode)) {
|
||||||
|
auto MI = macroNode.getAsMacro();
|
||||||
Identifier Name = Impl.getNameImporter().importMacroName(II, MI);
|
Identifier Name = Impl.getNameImporter().importMacroName(II, MI);
|
||||||
if (Decl *imported = Impl.importMacro(Name, MI))
|
if (Decl *imported = Impl.importMacro(Name, macroNode))
|
||||||
receiver(imported);
|
receiver(imported);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2169,12 +2188,14 @@ bool ClangImporter::lookupDeclsFromHeader(StringRef Filename,
|
|||||||
clang::PreprocessedEntity *PPE = *I;
|
clang::PreprocessedEntity *PPE = *I;
|
||||||
if (!PPE)
|
if (!PPE)
|
||||||
continue;
|
continue;
|
||||||
if (auto *MD = dyn_cast<clang::MacroDefinitionRecord>(PPE)) {
|
if (auto *MDR = dyn_cast<clang::MacroDefinitionRecord>(PPE)) {
|
||||||
auto *II = const_cast<clang::IdentifierInfo*>(MD->getName());
|
auto *II = const_cast<clang::IdentifierInfo*>(MDR->getName());
|
||||||
if (auto *MI = ClangPP.getMacroInfo(II)) {
|
auto MD = ClangPP.getMacroDefinition(II);
|
||||||
if (filter(MI)) {
|
if (auto macroNode = getClangNodeForMacroDefinition(MD)) {
|
||||||
|
if (filter(macroNode)) {
|
||||||
|
auto MI = macroNode.getAsMacro();
|
||||||
Identifier Name = Impl.getNameImporter().importMacroName(II, MI);
|
Identifier Name = Impl.getNameImporter().importMacroName(II, MI);
|
||||||
if (Decl *imported = Impl.importMacro(Name, MI))
|
if (Decl *imported = Impl.importMacro(Name, macroNode))
|
||||||
receiver(imported);
|
receiver(imported);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2378,11 +2399,9 @@ static bool isVisibleClangEntry(clang::ASTContext &ctx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check whether the macro is defined.
|
// Check whether the macro is defined.
|
||||||
auto clangMacro = entry.get<clang::MacroInfo *>();
|
// auto clangMacro = entry.get<clang::MacroInfo *>();
|
||||||
if (auto moduleID = clangMacro->getOwningModuleID()) {
|
// if (module)
|
||||||
if (auto module = ctx.getExternalSource()->getModule(moduleID))
|
// return module->NameVisibility == clang::Module::AllVisible;
|
||||||
return module->NameVisibility == clang::Module::AllVisible;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -2616,6 +2635,11 @@ const clang::CompilerInstance &ClangImporter::getClangInstance() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const clang::Module *ClangImporter::getClangOwningModule(ClangNode Node) const {
|
const clang::Module *ClangImporter::getClangOwningModule(ClangNode Node) const {
|
||||||
|
return Impl.getClangOwningModule(Node);
|
||||||
|
}
|
||||||
|
|
||||||
|
const clang::Module *
|
||||||
|
ClangImporter::Implementation::getClangOwningModule(ClangNode Node) const {
|
||||||
return ::getClangOwningModule(Node, getClangASTContext());
|
return ::getClangOwningModule(Node, getClangASTContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2943,8 +2967,12 @@ void ClangImporter::Implementation::lookupValue(
|
|||||||
if (!decl) continue;
|
if (!decl) continue;
|
||||||
} else if (!name.isSpecial()) {
|
} else if (!name.isSpecial()) {
|
||||||
// Try to import a macro.
|
// Try to import a macro.
|
||||||
auto clangMacro = entry.get<clang::MacroInfo *>();
|
if (auto modMacro = entry.dyn_cast<clang::ModuleMacro *>())
|
||||||
|
decl = importMacro(name.getBaseIdentifier(), modMacro);
|
||||||
|
else if (auto clangMacro = entry.dyn_cast<clang::MacroInfo *>())
|
||||||
decl = importMacro(name.getBaseIdentifier(), clangMacro);
|
decl = importMacro(name.getBaseIdentifier(), clangMacro);
|
||||||
|
else
|
||||||
|
llvm_unreachable("new kind of lookup table entry");
|
||||||
if (!decl) continue;
|
if (!decl) continue;
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -32,28 +32,6 @@
|
|||||||
using namespace swift;
|
using namespace swift;
|
||||||
using namespace importer;
|
using namespace importer;
|
||||||
|
|
||||||
Optional<clang::Module *>
|
|
||||||
ClangImporter::Implementation::getClangSubmoduleForMacro(
|
|
||||||
const clang::MacroInfo *MI) {
|
|
||||||
auto *ExternalSource = getClangASTContext().getExternalSource();
|
|
||||||
return ExternalSource->getModule(MI->getOwningModuleID());
|
|
||||||
}
|
|
||||||
|
|
||||||
ClangModuleUnit *ClangImporter::Implementation::getClangModuleForMacro(
|
|
||||||
const clang::MacroInfo *MI) {
|
|
||||||
auto maybeModule = getClangSubmoduleForMacro(MI);
|
|
||||||
if (!maybeModule)
|
|
||||||
return nullptr;
|
|
||||||
if (!maybeModule.getValue())
|
|
||||||
return ImportedHeaderUnit;
|
|
||||||
|
|
||||||
// Get the parent module because currently we don't represent submodules with
|
|
||||||
// ClangModule.
|
|
||||||
auto *M = maybeModule.getValue()->getTopLevelModule();
|
|
||||||
|
|
||||||
return getWrapperForModule(M);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T = clang::Expr>
|
template <typename T = clang::Expr>
|
||||||
static const T *
|
static const T *
|
||||||
parseNumericLiteral(ClangImporter::Implementation &impl,
|
parseNumericLiteral(ClangImporter::Implementation &impl,
|
||||||
@@ -90,7 +68,7 @@ static ValueDecl *importNumericLiteral(ClangImporter::Implementation &Impl,
|
|||||||
Identifier name,
|
Identifier name,
|
||||||
const clang::Token *signTok,
|
const clang::Token *signTok,
|
||||||
const clang::Token &tok,
|
const clang::Token &tok,
|
||||||
const clang::MacroInfo *ClangN,
|
ClangNode ClangN,
|
||||||
clang::QualType castType) {
|
clang::QualType castType) {
|
||||||
assert(tok.getKind() == clang::tok::numeric_constant &&
|
assert(tok.getKind() == clang::tok::numeric_constant &&
|
||||||
"not a numeric token");
|
"not a numeric token");
|
||||||
@@ -189,7 +167,7 @@ static ValueDecl *importStringLiteral(ClangImporter::Implementation &Impl,
|
|||||||
Identifier name,
|
Identifier name,
|
||||||
const clang::Token &tok,
|
const clang::Token &tok,
|
||||||
MappedStringLiteralKind kind,
|
MappedStringLiteralKind kind,
|
||||||
const clang::MacroInfo *ClangN) {
|
ClangNode ClangN) {
|
||||||
assert(isStringToken(tok));
|
assert(isStringToken(tok));
|
||||||
|
|
||||||
clang::ActionResult<clang::Expr*> result =
|
clang::ActionResult<clang::Expr*> result =
|
||||||
@@ -215,7 +193,7 @@ static ValueDecl *importLiteral(ClangImporter::Implementation &Impl,
|
|||||||
const clang::MacroInfo *MI,
|
const clang::MacroInfo *MI,
|
||||||
Identifier name,
|
Identifier name,
|
||||||
const clang::Token &tok,
|
const clang::Token &tok,
|
||||||
const clang::MacroInfo *ClangN,
|
ClangNode ClangN,
|
||||||
clang::QualType castType) {
|
clang::QualType castType) {
|
||||||
switch (tok.getKind()) {
|
switch (tok.getKind()) {
|
||||||
case clang::tok::numeric_constant:
|
case clang::tok::numeric_constant:
|
||||||
@@ -235,7 +213,7 @@ static ValueDecl *importLiteral(ClangImporter::Implementation &Impl,
|
|||||||
|
|
||||||
static ValueDecl *importNil(ClangImporter::Implementation &Impl,
|
static ValueDecl *importNil(ClangImporter::Implementation &Impl,
|
||||||
DeclContext *DC, Identifier name,
|
DeclContext *DC, Identifier name,
|
||||||
const clang::MacroInfo *clangN) {
|
ClangNode clangN) {
|
||||||
// We use a dummy type since we don't have a convenient type for 'nil'. Any
|
// We use a dummy type since we don't have a convenient type for 'nil'. Any
|
||||||
// use of this will be an error anyway.
|
// use of this will be an error anyway.
|
||||||
auto type = TupleType::getEmpty(Impl.SwiftContext);
|
auto type = TupleType::getEmpty(Impl.SwiftContext);
|
||||||
@@ -310,6 +288,8 @@ static Optional<std::pair<llvm::APSInt, Type>>
|
|||||||
|
|
||||||
auto rawID = token.getIdentifierInfo();
|
auto rawID = token.getIdentifierInfo();
|
||||||
auto macroInfo = impl.getClangPreprocessor().getMacroInfo(rawID);
|
auto macroInfo = impl.getClangPreprocessor().getMacroInfo(rawID);
|
||||||
|
if (!macroInfo)
|
||||||
|
return None;
|
||||||
auto importedID = impl.getNameImporter().importMacroName(rawID, macroInfo);
|
auto importedID = impl.getNameImporter().importMacroName(rawID, macroInfo);
|
||||||
impl.importMacro(importedID, macroInfo);
|
impl.importMacro(importedID, macroInfo);
|
||||||
|
|
||||||
@@ -332,7 +312,7 @@ static ValueDecl *importMacro(ClangImporter::Implementation &impl,
|
|||||||
DeclContext *DC,
|
DeclContext *DC,
|
||||||
Identifier name,
|
Identifier name,
|
||||||
const clang::MacroInfo *macro,
|
const clang::MacroInfo *macro,
|
||||||
const clang::MacroInfo *ClangN,
|
ClangNode ClangN,
|
||||||
clang::QualType castType) {
|
clang::QualType castType) {
|
||||||
if (name.empty()) return nullptr;
|
if (name.empty()) return nullptr;
|
||||||
|
|
||||||
@@ -636,7 +616,8 @@ static ValueDecl *importMacro(ClangImporter::Implementation &impl,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ValueDecl *ClangImporter::Implementation::importMacro(Identifier name,
|
ValueDecl *ClangImporter::Implementation::importMacro(Identifier name,
|
||||||
clang::MacroInfo *macro) {
|
ClangNode macroNode) {
|
||||||
|
const clang::MacroInfo *macro = macroNode.getAsMacro();
|
||||||
if (!macro)
|
if (!macro)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
@@ -665,11 +646,17 @@ ValueDecl *ClangImporter::Implementation::importMacro(Identifier name,
|
|||||||
// We haven't tried to import this macro yet. Do so now, and cache the
|
// We haven't tried to import this macro yet. Do so now, and cache the
|
||||||
// result.
|
// result.
|
||||||
|
|
||||||
DeclContext *DC = getClangModuleForMacro(macro);
|
DeclContext *DC;
|
||||||
if (!DC)
|
if (const clang::Module *module = getClangOwningModule(macroNode)) {
|
||||||
return nullptr;
|
// Get the parent module because currently we don't model Clang submodules
|
||||||
|
// in Swift.
|
||||||
|
DC = getWrapperForModule(module->getTopLevelModule());
|
||||||
|
} else {
|
||||||
|
DC = ImportedHeaderUnit;
|
||||||
|
}
|
||||||
|
|
||||||
auto valueDecl = ::importMacro(*this, DC, name, macro, macro, /*castType*/{});
|
auto valueDecl = ::importMacro(*this, DC, name, macro, macroNode,
|
||||||
|
/*castType*/{});
|
||||||
ImportedMacros[name].push_back({macro, valueDecl});
|
ImportedMacros[name].push_back({macro, valueDecl});
|
||||||
return valueDecl;
|
return valueDecl;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -375,7 +375,8 @@ public:
|
|||||||
/// Multiple macro definitions can map to the same declaration if the
|
/// Multiple macro definitions can map to the same declaration if the
|
||||||
/// macros are identically defined.
|
/// macros are identically defined.
|
||||||
llvm::DenseMap<Identifier,
|
llvm::DenseMap<Identifier,
|
||||||
SmallVector<std::pair<clang::MacroInfo *, ValueDecl *>, 2>>
|
SmallVector<std::pair<const clang::MacroInfo *, ValueDecl *>,
|
||||||
|
2>>
|
||||||
ImportedMacros;
|
ImportedMacros;
|
||||||
|
|
||||||
// Mapping from macro to value for macros that expand to constant values.
|
// Mapping from macro to value for macros that expand to constant values.
|
||||||
@@ -606,10 +607,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// The returned module may be null (but not \c None) if \p MI comes from
|
/// The returned module may be null (but not \c None) if \p MI comes from
|
||||||
/// an imported header.
|
/// an imported header.
|
||||||
Optional<clang::Module *>
|
const clang::Module *getClangOwningModule(ClangNode Node) const;
|
||||||
getClangSubmoduleForMacro(const clang::MacroInfo *MI);
|
|
||||||
|
|
||||||
ClangModuleUnit *getClangModuleForMacro(const clang::MacroInfo *MI);
|
|
||||||
|
|
||||||
/// Whether NSUInteger can be imported as Int in certain contexts. If false,
|
/// Whether NSUInteger can be imported as Int in certain contexts. If false,
|
||||||
/// should always be imported as UInt.
|
/// should always be imported as UInt.
|
||||||
@@ -667,9 +665,11 @@ public:
|
|||||||
|
|
||||||
/// \brief Import the given Clang preprocessor macro as a Swift value decl.
|
/// \brief Import the given Clang preprocessor macro as a Swift value decl.
|
||||||
///
|
///
|
||||||
|
/// \p macroNode must be a MacroInfo or a ModuleMacro.
|
||||||
|
///
|
||||||
/// \returns The imported declaration, or null if the macro could not be
|
/// \returns The imported declaration, or null if the macro could not be
|
||||||
/// translated into Swift.
|
/// translated into Swift.
|
||||||
ValueDecl *importMacro(Identifier name, clang::MacroInfo *macro);
|
ValueDecl *importMacro(Identifier name, ClangNode macroNode);
|
||||||
|
|
||||||
/// Map a Clang identifier name to its imported Swift equivalent.
|
/// Map a Clang identifier name to its imported Swift equivalent.
|
||||||
StringRef getSwiftNameFromClangName(StringRef name);
|
StringRef getSwiftNameFromClangName(StringRef name);
|
||||||
|
|||||||
@@ -79,44 +79,44 @@ considerReplacingExistingMacro(const clang::MacroInfo *newMacro,
|
|||||||
assert(PP);
|
assert(PP);
|
||||||
assert(newMacro);
|
assert(newMacro);
|
||||||
assert(existingMacro);
|
assert(existingMacro);
|
||||||
assert(newMacro->getOwningModuleID() == 0);
|
// assert(newMacro->getOwningModuleID() == 0);
|
||||||
assert(existingMacro->getOwningModuleID() == 0);
|
// assert(existingMacro->getOwningModuleID() == 0);
|
||||||
|
|
||||||
if (PP->getLangOpts().CurrentModule.empty())
|
// if (PP->getLangOpts().CurrentModule.empty())
|
||||||
return MacroConflictAction::Discard;
|
return MacroConflictAction::Discard;
|
||||||
|
|
||||||
clang::ModuleMap &moduleInfo = PP->getHeaderSearchInfo().getModuleMap();
|
// clang::ModuleMap &moduleInfo = PP->getHeaderSearchInfo().getModuleMap();
|
||||||
const clang::SourceManager &sourceMgr = PP->getSourceManager();
|
// const clang::SourceManager &sourceMgr = PP->getSourceManager();
|
||||||
|
//
|
||||||
auto findContainingExplicitModule =
|
// auto findContainingExplicitModule =
|
||||||
[&moduleInfo, &sourceMgr](const clang::MacroInfo *macro)
|
// [&moduleInfo, &sourceMgr](const clang::MacroInfo *macro)
|
||||||
-> const clang::Module * {
|
// -> const clang::Module * {
|
||||||
|
//
|
||||||
clang::SourceLocation definitionLoc = macro->getDefinitionLoc();
|
// clang::SourceLocation definitionLoc = macro->getDefinitionLoc();
|
||||||
assert(definitionLoc.isValid() &&
|
// assert(definitionLoc.isValid() &&
|
||||||
"implicitly-defined macros shouldn't show up in a module's lookup");
|
// "implicitly-defined macros shouldn't show up in a module's lookup");
|
||||||
clang::FullSourceLoc fullLoc(definitionLoc, sourceMgr);
|
// clang::FullSourceLoc fullLoc(definitionLoc, sourceMgr);
|
||||||
|
//
|
||||||
const clang::Module *module = moduleInfo.inferModuleFromLocation(fullLoc);
|
// const clang::Module *module = moduleInfo.inferModuleFromLocation(fullLoc);
|
||||||
assert(module && "we are building a module; everything should be modular");
|
// assert(module && "we are building a module; everything should be modular");
|
||||||
|
//
|
||||||
while (module->isSubModule()) {
|
// while (module->isSubModule()) {
|
||||||
if (module->IsExplicit)
|
// if (module->IsExplicit)
|
||||||
break;
|
// break;
|
||||||
module = module->Parent;
|
// module = module->Parent;
|
||||||
}
|
// }
|
||||||
return module;
|
// return module;
|
||||||
};
|
// };
|
||||||
|
//
|
||||||
const clang::Module *newModule = findContainingExplicitModule(newMacro);
|
// const clang::Module *newModule = findContainingExplicitModule(newMacro);
|
||||||
const clang::Module *existingModule =
|
// const clang::Module *existingModule =
|
||||||
findContainingExplicitModule(existingMacro);
|
// findContainingExplicitModule(existingMacro);
|
||||||
|
//
|
||||||
if (existingModule == newModule)
|
// if (existingModule == newModule)
|
||||||
return MacroConflictAction::Discard;
|
// return MacroConflictAction::Discard;
|
||||||
if (existingModule->isSubModuleOf(newModule))
|
// if (existingModule->isSubModuleOf(newModule))
|
||||||
return MacroConflictAction::Replace;
|
// return MacroConflictAction::Replace;
|
||||||
return MacroConflictAction::AddAsAlternative;
|
// return MacroConflictAction::AddAsAlternative;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace swift {
|
namespace swift {
|
||||||
@@ -201,7 +201,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \returns true if we found anything, false otherwise.
|
/// \returns true if we found anything, false otherwise.
|
||||||
bool lookupGlobalsAsMembers(SwiftLookupTable::StoredContext context,
|
bool lookupGlobalsAsMembers(SwiftLookupTable::StoredContext context,
|
||||||
SmallVectorImpl<uintptr_t> &entries);
|
SmallVectorImpl<uint64_t> &entries);
|
||||||
};
|
};
|
||||||
} // namespace swift
|
} // namespace swift
|
||||||
|
|
||||||
@@ -432,11 +432,12 @@ static bool isGlobalAsMember(SwiftLookupTable::SingleEntry entry,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool SwiftLookupTable::addLocalEntry(SingleEntry newEntry,
|
bool SwiftLookupTable::addLocalEntry(SingleEntry newEntry,
|
||||||
SmallVectorImpl<uintptr_t> &entries,
|
SmallVectorImpl<uint64_t> &entries,
|
||||||
const clang::Preprocessor *PP) {
|
const clang::Preprocessor *PP) {
|
||||||
// Check whether this entry matches any existing entry.
|
// Check whether this entry matches any existing entry.
|
||||||
auto decl = newEntry.dyn_cast<clang::NamedDecl *>();
|
auto decl = newEntry.dyn_cast<clang::NamedDecl *>();
|
||||||
auto macro = newEntry.dyn_cast<clang::MacroInfo *>();
|
auto macro = newEntry.dyn_cast<clang::MacroInfo *>();
|
||||||
|
auto moduleMacro = newEntry.dyn_cast<clang::ModuleMacro *>();
|
||||||
for (auto &existingEntry : entries) {
|
for (auto &existingEntry : entries) {
|
||||||
// If it matches an existing declaration, there's nothing to do.
|
// If it matches an existing declaration, there's nothing to do.
|
||||||
if (decl && isDeclEntry(existingEntry) &&
|
if (decl && isDeclEntry(existingEntry) &&
|
||||||
@@ -445,27 +446,30 @@ bool SwiftLookupTable::addLocalEntry(SingleEntry newEntry,
|
|||||||
|
|
||||||
// If it matches an existing macro, decide on the best course of action.
|
// If it matches an existing macro, decide on the best course of action.
|
||||||
if (macro && isMacroEntry(existingEntry)) {
|
if (macro && isMacroEntry(existingEntry)) {
|
||||||
MacroConflictAction action =
|
|
||||||
considerReplacingExistingMacro(macro,
|
|
||||||
mapStoredMacro(existingEntry),
|
|
||||||
PP);
|
|
||||||
switch (action) {
|
|
||||||
case MacroConflictAction::Discard:
|
|
||||||
return false;
|
return false;
|
||||||
case MacroConflictAction::Replace:
|
// MacroConflictAction action =
|
||||||
existingEntry = encodeEntry(macro);
|
// considerReplacingExistingMacro(macro,
|
||||||
return false;
|
// mapStoredMacro(existingEntry),
|
||||||
case MacroConflictAction::AddAsAlternative:
|
// PP);
|
||||||
break;
|
// switch (action) {
|
||||||
}
|
// case MacroConflictAction::Discard:
|
||||||
|
// return false;
|
||||||
|
// case MacroConflictAction::Replace:
|
||||||
|
// existingEntry = encodeEntry(macro);
|
||||||
|
// return false;
|
||||||
|
// case MacroConflictAction::AddAsAlternative:
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add an entry to this context.
|
// Add an entry to this context.
|
||||||
if (decl)
|
if (decl)
|
||||||
entries.push_back(encodeEntry(decl));
|
entries.push_back(encodeEntry(decl));
|
||||||
else
|
else if (macro)
|
||||||
entries.push_back(encodeEntry(macro));
|
entries.push_back(encodeEntry(macro));
|
||||||
|
else
|
||||||
|
entries.push_back(encodeEntry(moduleMacro));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -502,6 +506,7 @@ void SwiftLookupTable::addEntry(DeclName name, SingleEntry newEntry,
|
|||||||
auto &entries = LookupTable[name.getBaseIdentifier().str()];
|
auto &entries = LookupTable[name.getBaseIdentifier().str()];
|
||||||
auto decl = newEntry.dyn_cast<clang::NamedDecl *>();
|
auto decl = newEntry.dyn_cast<clang::NamedDecl *>();
|
||||||
auto macro = newEntry.dyn_cast<clang::MacroInfo *>();
|
auto macro = newEntry.dyn_cast<clang::MacroInfo *>();
|
||||||
|
auto moduleMacro = newEntry.dyn_cast<clang::ModuleMacro *>();
|
||||||
for (auto &entry : entries) {
|
for (auto &entry : entries) {
|
||||||
if (entry.Context == context) {
|
if (entry.Context == context) {
|
||||||
// We have entries for this context.
|
// We have entries for this context.
|
||||||
@@ -515,8 +520,10 @@ void SwiftLookupTable::addEntry(DeclName name, SingleEntry newEntry,
|
|||||||
entry.Context = context;
|
entry.Context = context;
|
||||||
if (decl)
|
if (decl)
|
||||||
entry.DeclsOrMacros.push_back(encodeEntry(decl));
|
entry.DeclsOrMacros.push_back(encodeEntry(decl));
|
||||||
else
|
else if (macro)
|
||||||
entry.DeclsOrMacros.push_back(encodeEntry(macro));
|
entry.DeclsOrMacros.push_back(encodeEntry(macro));
|
||||||
|
else
|
||||||
|
entry.DeclsOrMacros.push_back(encodeEntry(moduleMacro));
|
||||||
entries.push_back(entry);
|
entries.push_back(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -562,7 +569,8 @@ SwiftLookupTable::lookup(StringRef baseName,
|
|||||||
|
|
||||||
// Map each of the declarations.
|
// Map each of the declarations.
|
||||||
for (auto &stored : entry.DeclsOrMacros)
|
for (auto &stored : entry.DeclsOrMacros)
|
||||||
result.push_back(mapStored(stored));
|
if (auto entry = mapStored(stored))
|
||||||
|
result.push_back(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -581,7 +589,7 @@ SwiftLookupTable::lookupGlobalsAsMembers(StoredContext context) {
|
|||||||
if (!Reader) return result;
|
if (!Reader) return result;
|
||||||
|
|
||||||
// Lookup this base name in the module extension file.
|
// Lookup this base name in the module extension file.
|
||||||
SmallVector<uintptr_t, 2> results;
|
SmallVector<uint64_t, 2> results;
|
||||||
(void)Reader->lookupGlobalsAsMembers(context, results);
|
(void)Reader->lookupGlobalsAsMembers(context, results);
|
||||||
|
|
||||||
// Add an entry to the table so we don't look again.
|
// Add an entry to the table so we don't look again.
|
||||||
@@ -789,12 +797,41 @@ static void printStoredContext(SwiftLookupTable::StoredContext context,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t getEncodedDeclID(uint64_t entry) {
|
||||||
|
assert(SwiftLookupTable::isSerializationIDEntry(entry));
|
||||||
|
assert(SwiftLookupTable::isDeclEntry(entry));
|
||||||
|
return entry >> 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
struct LocalMacroIDs {
|
||||||
|
uint32_t moduleID;
|
||||||
|
uint32_t nameOrMacroID;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static LocalMacroIDs getEncodedModuleMacroIDs(uint64_t entry) {
|
||||||
|
assert(SwiftLookupTable::isSerializationIDEntry(entry));
|
||||||
|
assert(SwiftLookupTable::isMacroEntry(entry));
|
||||||
|
return {static_cast<uint32_t>((entry & 0xFFFFFFFF) >> 2),
|
||||||
|
static_cast<uint32_t>(entry >> 32)};
|
||||||
|
}
|
||||||
|
|
||||||
/// Print a stored entry (Clang macro or declaration) for debugging purposes.
|
/// Print a stored entry (Clang macro or declaration) for debugging purposes.
|
||||||
static void printStoredEntry(const SwiftLookupTable *table, uintptr_t entry,
|
static void printStoredEntry(const SwiftLookupTable *table, uint64_t entry,
|
||||||
llvm::raw_ostream &out) {
|
llvm::raw_ostream &out) {
|
||||||
if (SwiftLookupTable::isSerializationIDEntry(entry)) {
|
if (SwiftLookupTable::isSerializationIDEntry(entry)) {
|
||||||
llvm::errs() << (SwiftLookupTable::isMacroEntry(entry) ? "macro" : "decl")
|
if (SwiftLookupTable::isDeclEntry(entry)) {
|
||||||
<< " ID #" << SwiftLookupTable::getSerializationID(entry);
|
llvm::errs() << "decl ID #" << getEncodedDeclID(entry);
|
||||||
|
} else {
|
||||||
|
LocalMacroIDs macroIDs = getEncodedModuleMacroIDs(entry);
|
||||||
|
if (macroIDs.moduleID == 0) {
|
||||||
|
llvm::errs() << "macro ID #" << macroIDs.nameOrMacroID;
|
||||||
|
} else {
|
||||||
|
llvm::errs() << "macro with name ID #" << macroIDs.nameOrMacroID
|
||||||
|
<< "in submodule #" << macroIDs.moduleID;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (SwiftLookupTable::isMacroEntry(entry)) {
|
} else if (SwiftLookupTable::isMacroEntry(entry)) {
|
||||||
llvm::errs() << "Macro";
|
llvm::errs() << "Macro";
|
||||||
} else {
|
} else {
|
||||||
@@ -820,7 +857,7 @@ void SwiftLookupTable::dump() const {
|
|||||||
llvm::errs() << ": ";
|
llvm::errs() << ": ";
|
||||||
|
|
||||||
interleave(entry.DeclsOrMacros.begin(), entry.DeclsOrMacros.end(),
|
interleave(entry.DeclsOrMacros.begin(), entry.DeclsOrMacros.end(),
|
||||||
[this](uintptr_t entry) {
|
[this](uint64_t entry) {
|
||||||
printStoredEntry(this, entry, llvm::errs());
|
printStoredEntry(this, entry, llvm::errs());
|
||||||
},
|
},
|
||||||
[] {
|
[] {
|
||||||
@@ -867,7 +904,7 @@ void SwiftLookupTable::dump() const {
|
|||||||
|
|
||||||
const auto &entries = GlobalsAsMembers.find(context)->second;
|
const auto &entries = GlobalsAsMembers.find(context)->second;
|
||||||
interleave(entries.begin(), entries.end(),
|
interleave(entries.begin(), entries.end(),
|
||||||
[this](uintptr_t entry) {
|
[this](uint64_t entry) {
|
||||||
printStoredEntry(this, entry, llvm::errs());
|
printStoredEntry(this, entry, llvm::errs());
|
||||||
},
|
},
|
||||||
[] {
|
[] {
|
||||||
@@ -957,8 +994,7 @@ namespace {
|
|||||||
dataLength += sizeof(uint16_t);
|
dataLength += sizeof(uint16_t);
|
||||||
|
|
||||||
// Actual entries.
|
// Actual entries.
|
||||||
dataLength += (sizeof(clang::serialization::DeclID) *
|
dataLength += (sizeof(uint64_t) * entry.DeclsOrMacros.size());
|
||||||
entry.DeclsOrMacros.size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
endian::Writer<little> writer(out);
|
endian::Writer<little> writer(out);
|
||||||
@@ -978,6 +1014,7 @@ namespace {
|
|||||||
// # of entries
|
// # of entries
|
||||||
writer.write<uint16_t>(data.size());
|
writer.write<uint16_t>(data.size());
|
||||||
|
|
||||||
|
bool isModule = Writer.getLangOpts().isCompilingModule();
|
||||||
for (auto &fullEntry : data) {
|
for (auto &fullEntry : data) {
|
||||||
// Context.
|
// Context.
|
||||||
writer.write<uint8_t>(static_cast<uint8_t>(fullEntry.Context.first));
|
writer.write<uint8_t>(static_cast<uint8_t>(fullEntry.Context.first));
|
||||||
@@ -991,15 +1028,22 @@ namespace {
|
|||||||
|
|
||||||
// Write the declarations and macros.
|
// Write the declarations and macros.
|
||||||
for (auto &entry : fullEntry.DeclsOrMacros) {
|
for (auto &entry : fullEntry.DeclsOrMacros) {
|
||||||
uint32_t id;
|
uint64_t id;
|
||||||
if (SwiftLookupTable::isDeclEntry(entry)) {
|
auto mappedEntry = Table.mapStored(entry, isModule);
|
||||||
auto decl = Table.mapStoredDecl(entry);
|
if (auto *decl = mappedEntry.dyn_cast<clang::NamedDecl *>()) {
|
||||||
id = (Writer.getDeclID(decl) << 2) | 0x02;
|
id = (Writer.getDeclID(decl) << 2) | 0x02;
|
||||||
|
} else if (auto *macro = mappedEntry.dyn_cast<clang::MacroInfo *>()) {
|
||||||
|
id = static_cast<uint64_t>(Writer.getMacroID(macro)) << 32;
|
||||||
|
id |= 0x02 | 0x01;
|
||||||
} else {
|
} else {
|
||||||
auto macro = Table.mapStoredMacro(entry);
|
auto *moduleMacro = mappedEntry.get<clang::ModuleMacro *>();
|
||||||
id = (Writer.getMacroID(macro) << 2) | 0x02 | 0x01;
|
uint32_t nameID = Writer.getIdentifierRef(moduleMacro->getName());
|
||||||
|
uint32_t submoduleID = Writer.getLocalOrImportedSubmoduleID(
|
||||||
|
moduleMacro->getOwningModule());
|
||||||
|
id = (static_cast<uint64_t>(nameID) << 32) | (submoduleID << 2);
|
||||||
|
id |= 0x02 | 0x01;
|
||||||
}
|
}
|
||||||
writer.write<uint32_t>(id);
|
writer.write<uint64_t>(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1014,7 +1058,7 @@ namespace {
|
|||||||
public:
|
public:
|
||||||
using key_type = std::pair<SwiftLookupTable::ContextKind, StringRef>;
|
using key_type = std::pair<SwiftLookupTable::ContextKind, StringRef>;
|
||||||
using key_type_ref = key_type;
|
using key_type_ref = key_type;
|
||||||
using data_type = SmallVector<uintptr_t, 2>;
|
using data_type = SmallVector<uint64_t, 2>;
|
||||||
using data_type_ref = data_type &;
|
using data_type_ref = data_type &;
|
||||||
using hash_value_type = uint32_t;
|
using hash_value_type = uint32_t;
|
||||||
using offset_type = unsigned;
|
using offset_type = unsigned;
|
||||||
@@ -1039,7 +1083,7 @@ namespace {
|
|||||||
|
|
||||||
// # of entries
|
// # of entries
|
||||||
uint32_t dataLength =
|
uint32_t dataLength =
|
||||||
sizeof(uint16_t) + sizeof(clang::serialization::DeclID) * data.size();
|
sizeof(uint16_t) + sizeof(uint64_t) * data.size();
|
||||||
|
|
||||||
endian::Writer<little> writer(out);
|
endian::Writer<little> writer(out);
|
||||||
writer.write<uint16_t>(keyLength);
|
writer.write<uint16_t>(keyLength);
|
||||||
@@ -1062,16 +1106,24 @@ namespace {
|
|||||||
writer.write<uint16_t>(data.size());
|
writer.write<uint16_t>(data.size());
|
||||||
|
|
||||||
// Actual entries.
|
// Actual entries.
|
||||||
|
bool isModule = Writer.getLangOpts().isCompilingModule();
|
||||||
for (auto &entry : data) {
|
for (auto &entry : data) {
|
||||||
uint32_t id;
|
uint64_t id;
|
||||||
if (SwiftLookupTable::isDeclEntry(entry)) {
|
auto mappedEntry = Table.mapStored(entry, isModule);
|
||||||
auto decl = Table.mapStoredDecl(entry);
|
if (auto *decl = mappedEntry.dyn_cast<clang::NamedDecl *>()) {
|
||||||
id = (Writer.getDeclID(decl) << 2) | 0x02;
|
id = (Writer.getDeclID(decl) << 2) | 0x02;
|
||||||
|
} else if (auto *macro = mappedEntry.dyn_cast<clang::MacroInfo *>()) {
|
||||||
|
id = static_cast<uint64_t>(Writer.getMacroID(macro)) << 32;
|
||||||
|
id |= 0x02 | 0x01;
|
||||||
} else {
|
} else {
|
||||||
auto macro = Table.mapStoredMacro(entry);
|
auto *moduleMacro = mappedEntry.get<clang::ModuleMacro *>();
|
||||||
id = (Writer.getMacroID(macro) << 2) | 0x02 | 0x01;
|
uint32_t nameID = Writer.getIdentifierRef(moduleMacro->getName());
|
||||||
|
uint32_t submoduleID = Writer.getLocalOrImportedSubmoduleID(
|
||||||
|
moduleMacro->getOwningModule());
|
||||||
|
id = (static_cast<uint64_t>(nameID) << 32) | (submoduleID << 2);
|
||||||
|
id |= 0x02 | 0x01;
|
||||||
}
|
}
|
||||||
writer.write<uint32_t>(id);
|
writer.write<uint64_t>(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1221,7 +1273,7 @@ namespace {
|
|||||||
unsigned numDeclsOrMacros =
|
unsigned numDeclsOrMacros =
|
||||||
endian::readNext<uint16_t, little, unaligned>(data);
|
endian::readNext<uint16_t, little, unaligned>(data);
|
||||||
while (numDeclsOrMacros--) {
|
while (numDeclsOrMacros--) {
|
||||||
auto id = endian::readNext<uint32_t, little, unaligned>(data);
|
auto id = endian::readNext<uint64_t, little, unaligned>(data);
|
||||||
entry.DeclsOrMacros.push_back(id);
|
entry.DeclsOrMacros.push_back(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1237,7 +1289,7 @@ namespace {
|
|||||||
public:
|
public:
|
||||||
using internal_key_type = SwiftLookupTable::StoredContext;
|
using internal_key_type = SwiftLookupTable::StoredContext;
|
||||||
using external_key_type = internal_key_type;
|
using external_key_type = internal_key_type;
|
||||||
using data_type = SmallVector<uintptr_t, 2>;
|
using data_type = SmallVector<uint64_t, 2>;
|
||||||
using hash_value_type = uint32_t;
|
using hash_value_type = uint32_t;
|
||||||
using offset_type = unsigned;
|
using offset_type = unsigned;
|
||||||
|
|
||||||
@@ -1280,7 +1332,7 @@ namespace {
|
|||||||
|
|
||||||
// Read all of the entries.
|
// Read all of the entries.
|
||||||
while (numEntries--) {
|
while (numEntries--) {
|
||||||
auto id = endian::readNext<uint32_t, little, unaligned>(data);
|
auto id = endian::readNext<uint64_t, little, unaligned>(data);
|
||||||
result.push_back(id);
|
result.push_back(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1297,7 +1349,7 @@ namespace swift {
|
|||||||
llvm::OnDiskIterableChainedHashTable<GlobalsAsMembersTableReaderInfo>;
|
llvm::OnDiskIterableChainedHashTable<GlobalsAsMembersTableReaderInfo>;
|
||||||
} // namespace swift
|
} // namespace swift
|
||||||
|
|
||||||
clang::NamedDecl *SwiftLookupTable::mapStoredDecl(uintptr_t &entry) {
|
clang::NamedDecl *SwiftLookupTable::mapStoredDecl(uint64_t &entry) {
|
||||||
assert(isDeclEntry(entry) && "Not a declaration entry");
|
assert(isDeclEntry(entry) && "Not a declaration entry");
|
||||||
|
|
||||||
// If we have an AST node here, just cast it.
|
// If we have an AST node here, just cast it.
|
||||||
@@ -1307,7 +1359,7 @@ clang::NamedDecl *SwiftLookupTable::mapStoredDecl(uintptr_t &entry) {
|
|||||||
|
|
||||||
// Otherwise, resolve the declaration.
|
// Otherwise, resolve the declaration.
|
||||||
assert(Reader && "Cannot resolve the declaration without a reader");
|
assert(Reader && "Cannot resolve the declaration without a reader");
|
||||||
clang::serialization::DeclID declID = getSerializationID(entry);
|
uint32_t declID = getEncodedDeclID(entry);
|
||||||
auto decl = cast_or_null<clang::NamedDecl>(
|
auto decl = cast_or_null<clang::NamedDecl>(
|
||||||
Reader->getASTReader().GetLocalDecl(Reader->getModuleFile(),
|
Reader->getASTReader().GetLocalDecl(Reader->getModuleFile(),
|
||||||
declID));
|
declID));
|
||||||
@@ -1317,33 +1369,66 @@ clang::NamedDecl *SwiftLookupTable::mapStoredDecl(uintptr_t &entry) {
|
|||||||
return decl;
|
return decl;
|
||||||
}
|
}
|
||||||
|
|
||||||
clang::MacroInfo *SwiftLookupTable::mapStoredMacro(uintptr_t &entry) {
|
static bool isPCH(SwiftLookupTableReader &reader) {
|
||||||
|
return reader.getModuleFile().Kind == clang::serialization::MK_PCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
SwiftLookupTable::SingleEntry
|
||||||
|
SwiftLookupTable::mapStoredMacro(uint64_t &entry, bool assumeModule) {
|
||||||
assert(isMacroEntry(entry) && "Not a macro entry");
|
assert(isMacroEntry(entry) && "Not a macro entry");
|
||||||
|
|
||||||
// If we have an AST node here, just cast it.
|
// If we have an AST node here, just cast it.
|
||||||
if (isASTNodeEntry(entry)) {
|
if (isASTNodeEntry(entry)) {
|
||||||
|
if (assumeModule || (Reader && !isPCH(*Reader)))
|
||||||
|
return static_cast<clang::ModuleMacro *>(getPointerFromEntry(entry));
|
||||||
|
else
|
||||||
return static_cast<clang::MacroInfo *>(getPointerFromEntry(entry));
|
return static_cast<clang::MacroInfo *>(getPointerFromEntry(entry));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, resolve the macro.
|
// Otherwise, resolve the macro.
|
||||||
assert(Reader && "Cannot resolve the macro without a reader");
|
assert(Reader && "Cannot resolve the macro without a reader");
|
||||||
clang::serialization::MacroID macroID = getSerializationID(entry);
|
clang::ASTReader &astReader = Reader->getASTReader();
|
||||||
auto macro = cast_or_null<clang::MacroInfo>(
|
|
||||||
Reader->getASTReader().getMacro(
|
LocalMacroIDs macroIDs = getEncodedModuleMacroIDs(entry);
|
||||||
Reader->getASTReader().getGlobalMacroID(
|
if (!assumeModule && macroIDs.moduleID == 0) {
|
||||||
Reader->getModuleFile(),
|
assert(isPCH(*Reader));
|
||||||
macroID)));
|
// Not a module, and the second key is actually a macroID.
|
||||||
|
auto macro =
|
||||||
|
astReader.getMacro(astReader.getGlobalMacroID(Reader->getModuleFile(),
|
||||||
|
macroIDs.nameOrMacroID));
|
||||||
|
|
||||||
// Update the entry now that we've resolved the macro.
|
// Update the entry now that we've resolved the macro.
|
||||||
entry = encodeEntry(macro);
|
entry = encodeEntry(macro);
|
||||||
return macro;
|
return macro;
|
||||||
}
|
}
|
||||||
|
|
||||||
SwiftLookupTable::SingleEntry SwiftLookupTable::mapStored(uintptr_t &entry) {
|
// FIXME: Clang should help us out here, but it doesn't. It can only give us
|
||||||
|
// MacroInfos and not ModuleMacros.
|
||||||
|
assert(!isPCH(*Reader));
|
||||||
|
clang::IdentifierInfo *name =
|
||||||
|
astReader.getLocalIdentifier(Reader->getModuleFile(),
|
||||||
|
macroIDs.nameOrMacroID);
|
||||||
|
auto submoduleID = astReader.getGlobalSubmoduleID(Reader->getModuleFile(),
|
||||||
|
macroIDs.moduleID);
|
||||||
|
clang::Module *submodule = astReader.getSubmodule(submoduleID);
|
||||||
|
assert(submodule);
|
||||||
|
|
||||||
|
clang::Preprocessor &pp = Reader->getASTReader().getPreprocessor();
|
||||||
|
// Force the ModuleMacro to be loaded if this module is visible.
|
||||||
|
(void)pp.getLeafModuleMacros(name);
|
||||||
|
clang::ModuleMacro *macro = pp.getModuleMacro(submodule, name);
|
||||||
|
// This might still be NULL if the module has been imported but not made
|
||||||
|
// visible. We need a better answer here.
|
||||||
|
if (macro)
|
||||||
|
entry = encodeEntry(macro);
|
||||||
|
return macro;
|
||||||
|
}
|
||||||
|
|
||||||
|
SwiftLookupTable::SingleEntry SwiftLookupTable::mapStored(uint64_t &entry,
|
||||||
|
bool assumeModule) {
|
||||||
if (isDeclEntry(entry))
|
if (isDeclEntry(entry))
|
||||||
return mapStoredDecl(entry);
|
return mapStoredDecl(entry);
|
||||||
|
return mapStoredMacro(entry, assumeModule);
|
||||||
return mapStoredMacro(entry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SwiftLookupTableReader::~SwiftLookupTableReader() {
|
SwiftLookupTableReader::~SwiftLookupTableReader() {
|
||||||
@@ -1486,7 +1571,7 @@ SwiftLookupTableReader::getGlobalsAsMembersContexts() {
|
|||||||
|
|
||||||
bool SwiftLookupTableReader::lookupGlobalsAsMembers(
|
bool SwiftLookupTableReader::lookupGlobalsAsMembers(
|
||||||
SwiftLookupTable::StoredContext context,
|
SwiftLookupTable::StoredContext context,
|
||||||
SmallVectorImpl<uintptr_t> &entries) {
|
SmallVectorImpl<uint64_t> &entries) {
|
||||||
auto table =
|
auto table =
|
||||||
static_cast<SerializedGlobalsAsMembersTable*>(GlobalsAsMembersTable);
|
static_cast<SerializedGlobalsAsMembersTable*>(GlobalsAsMembersTable);
|
||||||
if (!table) return false;
|
if (!table) return false;
|
||||||
@@ -1596,49 +1681,52 @@ void importer::addEntryToLookupTable(SwiftLookupTable &table,
|
|||||||
void importer::addMacrosToLookupTable(SwiftLookupTable &table,
|
void importer::addMacrosToLookupTable(SwiftLookupTable &table,
|
||||||
NameImporter &nameImporter) {
|
NameImporter &nameImporter) {
|
||||||
auto &pp = nameImporter.getClangPreprocessor();
|
auto &pp = nameImporter.getClangPreprocessor();
|
||||||
|
auto *tu = nameImporter.getClangContext().getTranslationUnitDecl();
|
||||||
for (const auto ¯o : pp.macros(false)) {
|
for (const auto ¯o : pp.macros(false)) {
|
||||||
// Find the local history of this macro directive.
|
auto maybeAddMacro = [&](clang::MacroInfo *info,
|
||||||
clang::MacroDirective *MD = pp.getLocalMacroDirectiveHistory(macro.first);
|
clang::ModuleMacro *moduleMacro) {
|
||||||
|
// If this is a #undef, return.
|
||||||
// Walk the history.
|
if (!info)
|
||||||
for (; MD; MD = MD->getPrevious()) {
|
return;
|
||||||
// Don't look at any definitions that are followed by undefs.
|
|
||||||
// FIXME: This isn't quite correct across explicit submodules -- one
|
|
||||||
// submodule might define a macro, while another defines and then
|
|
||||||
// undefines the same macro. If they are processed in that order, the
|
|
||||||
// history will have the undef at the end, and we'll miss the first
|
|
||||||
// definition.
|
|
||||||
if (isa<clang::UndefMacroDirective>(MD))
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Only interested in macro definitions.
|
|
||||||
auto *defMD = dyn_cast<clang::DefMacroDirective>(MD);
|
|
||||||
if (!defMD)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Is this definition from this module?
|
|
||||||
auto info = defMD->getInfo();
|
|
||||||
if (!info || info->isFromASTFile())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// If we hit a builtin macro, we're done.
|
// If we hit a builtin macro, we're done.
|
||||||
if (info->isBuiltinMacro())
|
if (info->isBuiltinMacro())
|
||||||
break;
|
return;
|
||||||
|
|
||||||
// If we hit a macro with invalid or predefined location, we're done.
|
// If we hit a macro with invalid or predefined location, we're done.
|
||||||
auto loc = defMD->getLocation();
|
auto loc = info->getDefinitionLoc();
|
||||||
if (loc.isInvalid())
|
if (loc.isInvalid())
|
||||||
break;
|
return;
|
||||||
if (pp.getSourceManager().getFileID(loc) == pp.getPredefinesFileID())
|
if (pp.getSourceManager().getFileID(loc) == pp.getPredefinesFileID())
|
||||||
break;
|
return;
|
||||||
|
|
||||||
// Add this entry.
|
// Add this entry.
|
||||||
auto name = nameImporter.importMacroName(macro.first, info);
|
auto name = nameImporter.importMacroName(macro.first, info);
|
||||||
if (name.empty())
|
if (name.empty())
|
||||||
|
return;
|
||||||
|
if (moduleMacro)
|
||||||
|
table.addEntry(name, moduleMacro, tu, &pp);
|
||||||
|
else
|
||||||
|
table.addEntry(name, info, tu, &pp);
|
||||||
|
};
|
||||||
|
|
||||||
|
ArrayRef<clang::ModuleMacro *> moduleMacros =
|
||||||
|
macro.second.getActiveModuleMacros(pp, macro.first);
|
||||||
|
if (moduleMacros.empty()) {
|
||||||
|
// Handle the bridging header case.
|
||||||
|
clang::MacroDirective *MD = pp.getLocalMacroDirective(macro.first);
|
||||||
|
if (!MD)
|
||||||
continue;
|
continue;
|
||||||
table.addEntry(name, info,
|
|
||||||
nameImporter.getClangContext().getTranslationUnitDecl(),
|
// If we hit a builtin macro, we're done.
|
||||||
&pp);
|
maybeAddMacro(MD->getMacroInfo(), nullptr);
|
||||||
|
} else {
|
||||||
|
for (clang::ModuleMacro *moduleMacro : moduleMacros) {
|
||||||
|
clang::Module *owningModule = moduleMacro->getOwningModule();
|
||||||
|
if (!owningModule->isSubModuleOf(pp.getCurrentModule()))
|
||||||
|
continue;
|
||||||
|
maybeAddMacro(moduleMacro->getMacroInfo(), moduleMacro);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ namespace clang {
|
|||||||
class NamedDecl;
|
class NamedDecl;
|
||||||
class DeclContext;
|
class DeclContext;
|
||||||
class MacroInfo;
|
class MacroInfo;
|
||||||
|
class ModuleMacro;
|
||||||
class ObjCCategoryDecl;
|
class ObjCCategoryDecl;
|
||||||
class TypedefNameDecl;
|
class TypedefNameDecl;
|
||||||
}
|
}
|
||||||
@@ -204,7 +205,8 @@ public:
|
|||||||
static bool contextRequiresName(ContextKind kind);
|
static bool contextRequiresName(ContextKind kind);
|
||||||
|
|
||||||
/// A single entry referencing either a named declaration or a macro.
|
/// A single entry referencing either a named declaration or a macro.
|
||||||
typedef llvm::PointerUnion<clang::NamedDecl *, clang::MacroInfo *>
|
typedef llvm::PointerUnion3<clang::NamedDecl *, clang::MacroInfo *,
|
||||||
|
clang::ModuleMacro *>
|
||||||
SingleEntry;
|
SingleEntry;
|
||||||
|
|
||||||
/// A stored version of the context of an entity, which is Clang
|
/// A stored version of the context of an entity, which is Clang
|
||||||
@@ -224,50 +226,51 @@ public:
|
|||||||
/// The low bit indicates whether we have a declaration or macro
|
/// The low bit indicates whether we have a declaration or macro
|
||||||
/// (declaration = unset, macro = set) and the second lowest bit
|
/// (declaration = unset, macro = set) and the second lowest bit
|
||||||
/// indicates whether we have a serialization ID (set = DeclID or
|
/// indicates whether we have a serialization ID (set = DeclID or
|
||||||
/// MacroID, as appropriate) vs. a pointer (unset,
|
/// {IdentifierID,SubmoduleID}, as appropriate) vs. a pointer (unset,
|
||||||
/// clang::NamedDecl * or clang::MacroInfo *). In the ID case, the
|
/// clang::NamedDecl *, clang::MacroInfo *, clang::ModuleMacro *).
|
||||||
/// upper N-2 bits are the ID value; in the pointer case, the
|
/// In the ID case, the upper N-2 bits are the ID value; in the pointer
|
||||||
/// lower two bits will always be clear due to the alignment of
|
/// case, the lower two bits will always be clear due to the alignment of
|
||||||
/// the Clang pointers.
|
/// the Clang pointers.
|
||||||
llvm::SmallVector<uintptr_t, 2> DeclsOrMacros;
|
llvm::SmallVector<uint64_t, 2> DeclsOrMacros;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Whether the given entry is a macro entry.
|
/// Whether the given entry is a macro entry.
|
||||||
static bool isMacroEntry(uintptr_t entry) { return entry & 0x01; }
|
static bool isMacroEntry(uint64_t entry) { return entry & 0x01; }
|
||||||
|
|
||||||
/// Whether the given entry is a declaration entry.
|
/// Whether the given entry is a declaration entry.
|
||||||
static bool isDeclEntry(uintptr_t entry) { return !isMacroEntry(entry); }
|
static bool isDeclEntry(uint64_t entry) { return !isMacroEntry(entry); }
|
||||||
|
|
||||||
/// Whether the given entry is a serialization ID.
|
/// Whether the given entry is a serialization ID.
|
||||||
static bool isSerializationIDEntry(uintptr_t entry) { return (entry & 0x02); }
|
static bool isSerializationIDEntry(uint64_t entry) { return (entry & 0x02); }
|
||||||
|
|
||||||
/// Whether the given entry is an AST node.
|
/// Whether the given entry is an AST node.
|
||||||
static bool isASTNodeEntry(uintptr_t entry) {
|
static bool isASTNodeEntry(uint64_t entry) {
|
||||||
return !isSerializationIDEntry(entry);
|
return !isSerializationIDEntry(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieve the serialization ID for an entry.
|
|
||||||
static uint32_t getSerializationID(uintptr_t entry) {
|
|
||||||
assert(isSerializationIDEntry(entry) && "Not a serialization entry");
|
|
||||||
return entry >> 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Retrieve the pointer for an entry.
|
/// Retrieve the pointer for an entry.
|
||||||
static void *getPointerFromEntry(uintptr_t entry) {
|
static void *getPointerFromEntry(uint64_t entry) {
|
||||||
assert(isASTNodeEntry(entry) && "Not an AST node entry");
|
assert(isASTNodeEntry(entry) && "Not an AST node entry");
|
||||||
const uintptr_t mask = ~static_cast<uintptr_t>(0x03);
|
const uint64_t mask = ~static_cast<uint64_t>(0x03);
|
||||||
return reinterpret_cast<void *>(entry & mask);
|
return reinterpret_cast<void *>(entry & mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Encode a Clang named declaration as an entry in the table.
|
/// Encode a Clang named declaration as an entry in the table.
|
||||||
static uintptr_t encodeEntry(clang::NamedDecl *decl) {
|
static uint64_t encodeEntry(clang::NamedDecl *decl) {
|
||||||
auto bits = reinterpret_cast<uintptr_t>(decl);
|
auto bits = reinterpret_cast<uintptr_t>(decl);
|
||||||
assert((bits & 0x03) == 0 && "low bits set?");
|
assert((bits & 0x03) == 0 && "low bits set?");
|
||||||
return bits;
|
return bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encode a Clang macro as an entry in the table.
|
// Encode a Clang macro as an entry in the table.
|
||||||
static uintptr_t encodeEntry(clang::MacroInfo *macro) {
|
static uint64_t encodeEntry(clang::MacroInfo *macro) {
|
||||||
|
auto bits = reinterpret_cast<uintptr_t>(macro);
|
||||||
|
assert((bits & 0x03) == 0 && "low bits set?");
|
||||||
|
return bits | 0x01;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encode a Clang macro as an entry in the table.
|
||||||
|
static uint64_t encodeEntry(clang::ModuleMacro *macro) {
|
||||||
auto bits = reinterpret_cast<uintptr_t>(macro);
|
auto bits = reinterpret_cast<uintptr_t>(macro);
|
||||||
assert((bits & 0x03) == 0 && "low bits set?");
|
assert((bits & 0x03) == 0 && "low bits set?");
|
||||||
return bits | 0x01;
|
return bits | 0x01;
|
||||||
@@ -286,7 +289,7 @@ private:
|
|||||||
///
|
///
|
||||||
/// The values use the same representation as
|
/// The values use the same representation as
|
||||||
/// FullTableEntry::DeclsOrMacros.
|
/// FullTableEntry::DeclsOrMacros.
|
||||||
llvm::DenseMap<StoredContext, SmallVector<uintptr_t, 2>> GlobalsAsMembers;
|
llvm::DenseMap<StoredContext, SmallVector<uint64_t, 2>> GlobalsAsMembers;
|
||||||
|
|
||||||
/// The reader responsible for lazily loading the contents of this table.
|
/// The reader responsible for lazily loading the contents of this table.
|
||||||
SwiftLookupTableReader *Reader;
|
SwiftLookupTableReader *Reader;
|
||||||
@@ -307,20 +310,20 @@ private:
|
|||||||
/// present.
|
/// present.
|
||||||
///
|
///
|
||||||
/// \returns true if the entry was added, false otherwise.
|
/// \returns true if the entry was added, false otherwise.
|
||||||
bool addLocalEntry(SingleEntry newEntry, SmallVectorImpl<uintptr_t> &entries,
|
bool addLocalEntry(SingleEntry newEntry, SmallVectorImpl<uint64_t> &entries,
|
||||||
const clang::Preprocessor *PP);
|
const clang::Preprocessor *PP);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit SwiftLookupTable(SwiftLookupTableReader *reader) : Reader(reader) { }
|
explicit SwiftLookupTable(SwiftLookupTableReader *reader) : Reader(reader) { }
|
||||||
|
|
||||||
/// Maps a stored declaration entry to an actual Clang declaration.
|
/// Maps a stored declaration entry to an actual Clang declaration.
|
||||||
clang::NamedDecl *mapStoredDecl(uintptr_t &entry);
|
clang::NamedDecl *mapStoredDecl(uint64_t &entry);
|
||||||
|
|
||||||
/// Maps a stored macro entry to an actual Clang macro.
|
/// Maps a stored macro entry to an actual Clang macro.
|
||||||
clang::MacroInfo *mapStoredMacro(uintptr_t &entry);
|
SingleEntry mapStoredMacro(uint64_t &entry, bool assumeModule = false);
|
||||||
|
|
||||||
/// Maps a stored entry to an actual Clang AST node.
|
/// Maps a stored entry to an actual Clang AST node.
|
||||||
SingleEntry mapStored(uintptr_t &entry);
|
SingleEntry mapStored(uint64_t &entry, bool assumeModule = false);
|
||||||
|
|
||||||
/// Translate a Clang DeclContext into a context kind and name.
|
/// Translate a Clang DeclContext into a context kind and name.
|
||||||
static llvm::Optional<StoredContext> translateDeclContext(
|
static llvm::Optional<StoredContext> translateDeclContext(
|
||||||
|
|||||||
Reference in New Issue
Block a user