mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Merge pull request #20252 from slavapestov/move-get-type-for-mangling-to-ast
Move getTypeForMangling() to AST
This commit is contained in:
165
include/swift/AST/ASTDemangler.h
Normal file
165
include/swift/AST/ASTDemangler.h
Normal file
@@ -0,0 +1,165 @@
|
||||
//===--- ASTDemangler.h - Swift AST symbol demangling -----------*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Defines a builder concept for the TypeDecoder and MetadataReader which builds
|
||||
// AST Types, and a utility function wrapper which takes a mangled string and
|
||||
// feeds it through the TypeDecoder instance.
|
||||
//
|
||||
// The RemoteAST library defines a MetadataReader instance that uses this
|
||||
// concept, together with some additional utilities.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef __SWIFT_AST_ASTDEMANGLER_H__
|
||||
#define __SWIFT_AST_ASTDEMANGLER_H__
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "swift/AST/Types.h"
|
||||
#include "swift/AST/TypeRepr.h"
|
||||
#include "swift/Demangling/Demangler.h"
|
||||
#include "swift/Demangling/TypeDecoder.h"
|
||||
|
||||
namespace swift {
|
||||
|
||||
namespace Demangle {
|
||||
|
||||
Type getTypeForMangling(ASTContext &ctx,
|
||||
llvm::StringRef mangling);
|
||||
|
||||
/// An implementation of MetadataReader's BuilderType concept that
|
||||
/// just finds and builds things in the AST.
|
||||
class ASTBuilder {
|
||||
ASTContext &Ctx;
|
||||
Demangle::NodeFactory Factory;
|
||||
|
||||
/// The notional context in which we're writing and type-checking code.
|
||||
/// Created lazily.
|
||||
DeclContext *NotionalDC = nullptr;
|
||||
|
||||
public:
|
||||
using BuiltType = swift::Type;
|
||||
using BuiltNominalTypeDecl = swift::NominalTypeDecl *;
|
||||
using BuiltProtocolDecl = swift::ProtocolDecl *;
|
||||
explicit ASTBuilder(ASTContext &ctx) : Ctx(ctx) {}
|
||||
|
||||
ASTContext &getASTContext() { return Ctx; }
|
||||
DeclContext *getNotionalDC();
|
||||
|
||||
Demangle::NodeFactory &getNodeFactory() { return Factory; }
|
||||
|
||||
Type createBuiltinType(const std::string &mangledName);
|
||||
|
||||
NominalTypeDecl *createNominalTypeDecl(StringRef mangledName);
|
||||
|
||||
NominalTypeDecl *createNominalTypeDecl(const Demangle::NodePointer &node);
|
||||
|
||||
ProtocolDecl *createProtocolDecl(const Demangle::NodePointer &node);
|
||||
|
||||
Type createNominalType(NominalTypeDecl *decl);
|
||||
|
||||
Type createNominalType(NominalTypeDecl *decl, Type parent);
|
||||
|
||||
Type createBoundGenericType(NominalTypeDecl *decl, ArrayRef<Type> args);
|
||||
|
||||
Type createBoundGenericType(NominalTypeDecl *decl, ArrayRef<Type> args,
|
||||
Type parent);
|
||||
|
||||
Type createTupleType(ArrayRef<Type> eltTypes, StringRef labels,
|
||||
bool isVariadic);
|
||||
|
||||
Type createFunctionType(ArrayRef<Demangle::FunctionParam<Type>> params,
|
||||
Type output, FunctionTypeFlags flags);
|
||||
|
||||
Type createProtocolCompositionType(ArrayRef<ProtocolDecl *> protocols,
|
||||
Type superclass,
|
||||
bool isClassBound);
|
||||
|
||||
Type createExistentialMetatypeType(Type instance);
|
||||
|
||||
Type createMetatypeType(Type instance, bool wasAbstract=false);
|
||||
|
||||
Type createGenericTypeParameterType(unsigned depth, unsigned index);
|
||||
|
||||
Type createDependentMemberType(StringRef member, Type base,
|
||||
ProtocolDecl *protocol);
|
||||
|
||||
#define REF_STORAGE(Name, ...) \
|
||||
Type create##Name##StorageType(Type base);
|
||||
#include "swift/AST/ReferenceStorage.def"
|
||||
|
||||
Type createSILBoxType(Type base);
|
||||
|
||||
Type createObjCClassType(StringRef name);
|
||||
|
||||
ProtocolDecl *createObjCProtocolDecl(StringRef name);
|
||||
|
||||
Type createForeignClassType(StringRef mangledName);
|
||||
|
||||
Type getUnnamedForeignClassType();
|
||||
|
||||
Type getOpaqueType();
|
||||
|
||||
private:
|
||||
bool validateNominalParent(NominalTypeDecl *decl, Type parent);
|
||||
DeclContext *findDeclContext(const Demangle::NodePointer &node);
|
||||
ModuleDecl *findModule(const Demangle::NodePointer &node);
|
||||
Demangle::NodePointer findModuleNode(const Demangle::NodePointer &node);
|
||||
|
||||
enum class ForeignModuleKind {
|
||||
Imported,
|
||||
SynthesizedByImporter
|
||||
};
|
||||
|
||||
Optional<ForeignModuleKind>
|
||||
getForeignModuleKind(const Demangle::NodePointer &node);
|
||||
|
||||
NominalTypeDecl *findNominalTypeDecl(DeclContext *dc,
|
||||
Identifier name,
|
||||
Identifier privateDiscriminator,
|
||||
Demangle::Node::Kind kind);
|
||||
NominalTypeDecl *findForeignNominalTypeDecl(StringRef name,
|
||||
StringRef relatedEntityKind,
|
||||
ForeignModuleKind lookupKind,
|
||||
Demangle::Node::Kind kind);
|
||||
|
||||
Type checkTypeRepr(TypeRepr *repr);
|
||||
|
||||
static NominalTypeDecl *getAcceptableNominalTypeCandidate(ValueDecl *decl,
|
||||
Demangle::Node::Kind kind);
|
||||
|
||||
class TypeReprList {
|
||||
SmallVector<FixedTypeRepr, 4> Reprs;
|
||||
SmallVector<TypeRepr*, 4> Refs;
|
||||
|
||||
public:
|
||||
explicit TypeReprList(ArrayRef<Type> types) {
|
||||
Reprs.reserve(types.size());
|
||||
Refs.reserve(types.size());
|
||||
|
||||
for (auto type : types) {
|
||||
Reprs.emplace_back(type, SourceLoc());
|
||||
Refs.push_back(&Reprs.back());
|
||||
}
|
||||
}
|
||||
|
||||
ArrayRef<TypeRepr*> getList() const {
|
||||
return Refs;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace Demangle
|
||||
|
||||
} // namespace swift
|
||||
|
||||
#endif // __SWIFT_AST_ASTDEMANGLER_H__
|
||||
@@ -28,7 +28,6 @@
|
||||
#include "swift/Basic/OptionSet.h"
|
||||
#include "swift/Basic/STLExtras.h"
|
||||
#include "swift/Basic/SourceLoc.h"
|
||||
#include "swift/Parse/SyntaxParsingCache.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
@@ -79,6 +78,7 @@ namespace swift {
|
||||
class ValueDecl;
|
||||
class VarDecl;
|
||||
class VisibleDeclConsumer;
|
||||
class SyntaxParsingCache;
|
||||
|
||||
namespace syntax {
|
||||
class SourceFileSyntax;
|
||||
|
||||
@@ -221,9 +221,6 @@ public:
|
||||
Type staticType);
|
||||
};
|
||||
|
||||
Type getTypeForMangling(ASTContext &ctx,
|
||||
StringRef mangling);
|
||||
|
||||
} // end namespace remoteAST
|
||||
} // end namespace swift
|
||||
|
||||
|
||||
@@ -426,7 +426,8 @@ FOR_KNOWN_FOUNDATION_TYPES(CACHE_FOUNDATION_DECL)
|
||||
};
|
||||
|
||||
ASTContext::Implementation::Implementation()
|
||||
: IdentifierTable(Allocator), TheSyntaxArena(new SyntaxArena()) {}
|
||||
: IdentifierTable(Allocator),
|
||||
TheSyntaxArena(new syntax::SyntaxArena()) {}
|
||||
ASTContext::Implementation::~Implementation() {
|
||||
delete Resolver;
|
||||
|
||||
|
||||
687
lib/AST/ASTDemangler.cpp
Normal file
687
lib/AST/ASTDemangler.cpp
Normal file
@@ -0,0 +1,687 @@
|
||||
//===--- ASTDemangler.cpp ----------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Defines a builder concept for the TypeDecoder and MetadataReader which builds
|
||||
// AST Types, and a utility function wrapper which takes a mangled string and
|
||||
// feeds it through the TypeDecoder instance.
|
||||
//
|
||||
// The RemoteAST library defines a MetadataReader instance that uses this
|
||||
// concept, together with some additional utilities.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "swift/AST/ASTDemangler.h"
|
||||
|
||||
#include "swift/Subsystems.h"
|
||||
#include "swift/AST/ASTContext.h"
|
||||
#include "swift/AST/Decl.h"
|
||||
#include "swift/AST/GenericSignature.h"
|
||||
#include "swift/AST/Module.h"
|
||||
#include "swift/AST/NameLookup.h"
|
||||
#include "swift/AST/Type.h"
|
||||
#include "swift/AST/Types.h"
|
||||
#include "swift/ClangImporter/ClangImporter.h"
|
||||
#include "swift/Demangling/Demangler.h"
|
||||
|
||||
using namespace swift;
|
||||
|
||||
Type swift::Demangle::getTypeForMangling(ASTContext &ctx,
|
||||
StringRef mangling) {
|
||||
Demangle::Context Dem;
|
||||
auto node = Dem.demangleSymbolAsNode(mangling);
|
||||
if (!node)
|
||||
return Type();
|
||||
|
||||
ASTBuilder builder(ctx);
|
||||
return swift::Demangle::decodeMangledType(builder, node);
|
||||
}
|
||||
|
||||
|
||||
Type
|
||||
ASTBuilder::createBuiltinType(const std::string &mangledName) {
|
||||
// TODO
|
||||
return Type();
|
||||
}
|
||||
|
||||
NominalTypeDecl *
|
||||
ASTBuilder::createNominalTypeDecl(StringRef mangledName) {
|
||||
Demangle::Demangler Dem;
|
||||
Demangle::NodePointer node = Dem.demangleType(mangledName);
|
||||
if (!node) return nullptr;
|
||||
|
||||
return createNominalTypeDecl(node);
|
||||
}
|
||||
|
||||
ProtocolDecl *
|
||||
ASTBuilder::createProtocolDecl(const Demangle::NodePointer &node) {
|
||||
return dyn_cast_or_null<ProtocolDecl>(createNominalTypeDecl(node));
|
||||
}
|
||||
|
||||
Type ASTBuilder::createNominalType(NominalTypeDecl *decl) {
|
||||
// If the declaration is generic, fail.
|
||||
if (decl->isGenericContext())
|
||||
return Type();
|
||||
|
||||
return decl->getDeclaredType();
|
||||
}
|
||||
|
||||
Type ASTBuilder::createNominalType(NominalTypeDecl *decl, Type parent) {
|
||||
// If the declaration is generic, fail.
|
||||
if (decl->getGenericParams())
|
||||
return Type();
|
||||
|
||||
// Validate the parent type.
|
||||
if (!validateNominalParent(decl, parent))
|
||||
return Type();
|
||||
|
||||
return NominalType::get(decl, parent, Ctx);
|
||||
}
|
||||
|
||||
Type ASTBuilder::createBoundGenericType(NominalTypeDecl *decl,
|
||||
ArrayRef<Type> args) {
|
||||
// If the declaration isn't generic, fail.
|
||||
if (!decl->isGenericContext())
|
||||
return Type();
|
||||
|
||||
// Build a SubstitutionMap.
|
||||
auto *genericSig = decl->getGenericSignature();
|
||||
|
||||
SmallVector<GenericTypeParamType *, 4> genericParams;
|
||||
genericSig->forEachParam([&](GenericTypeParamType *gp, bool canonical) {
|
||||
if (canonical)
|
||||
genericParams.push_back(gp);
|
||||
});
|
||||
if (genericParams.size() != args.size())
|
||||
return Type();
|
||||
|
||||
auto subMap = SubstitutionMap::get(
|
||||
genericSig,
|
||||
[&](SubstitutableType *t) -> Type {
|
||||
for (unsigned i = 0, e = genericParams.size(); i < e; ++i) {
|
||||
if (t->isEqual(genericParams[i]))
|
||||
return args[i];
|
||||
}
|
||||
return Type();
|
||||
},
|
||||
// FIXME: Wrong module
|
||||
LookUpConformanceInModule(decl->getParentModule()));
|
||||
|
||||
auto origType = decl->getDeclaredInterfaceType();
|
||||
|
||||
// FIXME: We're not checking that the type satisfies the generic
|
||||
// requirements of the signature here.
|
||||
auto substType = origType.subst(subMap);
|
||||
return substType;
|
||||
}
|
||||
|
||||
Type ASTBuilder::createBoundGenericType(NominalTypeDecl *decl,
|
||||
ArrayRef<Type> args,
|
||||
Type parent) {
|
||||
// If the declaration isn't generic, fail.
|
||||
if (!decl->getGenericParams())
|
||||
return Type();
|
||||
|
||||
// Validate the parent type.
|
||||
if (!validateNominalParent(decl, parent))
|
||||
return Type();
|
||||
|
||||
// Make a generic type repr that's been resolved to this decl.
|
||||
TypeReprList genericArgReprs(args);
|
||||
auto genericRepr = GenericIdentTypeRepr::create(Ctx, SourceLoc(),
|
||||
decl->getName(),
|
||||
genericArgReprs.getList(),
|
||||
SourceRange());
|
||||
// FIXME
|
||||
genericRepr->setValue(decl, nullptr);
|
||||
|
||||
Type genericType;
|
||||
|
||||
// If we have a parent type, we need to build a compound type repr.
|
||||
if (parent) {
|
||||
// Life would be much easier if we could just use a FixedTypeRepr for
|
||||
// the parent. But we can't! So we have to recursively expand
|
||||
// like this; and recursing with a lambda isn't impossible, so it gets
|
||||
// even worse.
|
||||
SmallVector<Type, 4> ancestry;
|
||||
for (auto p = parent; p; p = p->getNominalParent()) {
|
||||
ancestry.push_back(p);
|
||||
}
|
||||
|
||||
struct GenericRepr {
|
||||
TypeReprList GenericArgs;
|
||||
GenericIdentTypeRepr *Ident;
|
||||
|
||||
GenericRepr(const ASTContext &Ctx, BoundGenericType *type)
|
||||
: GenericArgs(type->getGenericArgs()),
|
||||
Ident(GenericIdentTypeRepr::create(Ctx, SourceLoc(),
|
||||
type->getDecl()->getName(),
|
||||
GenericArgs.getList(),
|
||||
SourceRange())) {
|
||||
// FIXME
|
||||
Ident->setValue(type->getDecl(), nullptr);
|
||||
}
|
||||
|
||||
// SmallVector::emplace_back will never need to call this because
|
||||
// we reserve the right size, but it does try statically.
|
||||
GenericRepr(const GenericRepr &other) : GenericArgs({}), Ident(nullptr) {
|
||||
llvm_unreachable("should not be called dynamically");
|
||||
}
|
||||
};
|
||||
|
||||
// Pre-allocate the component vectors so that we can form references
|
||||
// into them safely.
|
||||
SmallVector<SimpleIdentTypeRepr, 4> simpleComponents;
|
||||
SmallVector<GenericRepr, 4> genericComponents;
|
||||
simpleComponents.reserve(ancestry.size());
|
||||
genericComponents.reserve(ancestry.size());
|
||||
|
||||
// Build the parent hierarchy.
|
||||
SmallVector<ComponentIdentTypeRepr*, 4> componentReprs;
|
||||
for (size_t i = ancestry.size(); i != 0; --i) {
|
||||
Type p = ancestry[i - 1];
|
||||
if (auto boundGeneric = p->getAs<BoundGenericType>()) {
|
||||
genericComponents.emplace_back(Ctx, boundGeneric);
|
||||
componentReprs.push_back(genericComponents.back().Ident);
|
||||
} else {
|
||||
auto nominal = p->castTo<NominalType>();
|
||||
simpleComponents.emplace_back(SourceLoc(),
|
||||
nominal->getDecl()->getName());
|
||||
// FIXME
|
||||
simpleComponents.back().setValue(nominal->getDecl(), nullptr);
|
||||
componentReprs.push_back(&simpleComponents.back());
|
||||
}
|
||||
}
|
||||
componentReprs.push_back(genericRepr);
|
||||
|
||||
auto compoundRepr = CompoundIdentTypeRepr::create(Ctx, componentReprs);
|
||||
genericType = checkTypeRepr(compoundRepr);
|
||||
} else {
|
||||
genericType = checkTypeRepr(genericRepr);
|
||||
}
|
||||
|
||||
// If type-checking failed, we've failed.
|
||||
if (!genericType) return Type();
|
||||
|
||||
// Validate that we used the right decl.
|
||||
if (auto bgt = genericType->getAs<BoundGenericType>()) {
|
||||
if (bgt->getDecl() != decl)
|
||||
return Type();
|
||||
}
|
||||
|
||||
return genericType;
|
||||
}
|
||||
|
||||
Type ASTBuilder::createTupleType(ArrayRef<Type> eltTypes,
|
||||
StringRef labels,
|
||||
bool isVariadic) {
|
||||
// Just bail out on variadic tuples for now.
|
||||
if (isVariadic) return Type();
|
||||
|
||||
SmallVector<TupleTypeElt, 4> elements;
|
||||
elements.reserve(eltTypes.size());
|
||||
for (auto eltType : eltTypes) {
|
||||
Identifier label;
|
||||
if (!labels.empty()) {
|
||||
auto split = labels.split(' ');
|
||||
if (!split.first.empty())
|
||||
label = Ctx.getIdentifier(split.first);
|
||||
labels = split.second;
|
||||
}
|
||||
elements.emplace_back(eltType, label);
|
||||
}
|
||||
|
||||
return TupleType::get(elements, Ctx);
|
||||
}
|
||||
|
||||
Type ASTBuilder::createFunctionType(
|
||||
ArrayRef<Demangle::FunctionParam<Type>> params,
|
||||
Type output, FunctionTypeFlags flags) {
|
||||
FunctionTypeRepresentation representation;
|
||||
switch (flags.getConvention()) {
|
||||
case FunctionMetadataConvention::Swift:
|
||||
representation = FunctionTypeRepresentation::Swift;
|
||||
break;
|
||||
case FunctionMetadataConvention::Block:
|
||||
representation = FunctionTypeRepresentation::Block;
|
||||
break;
|
||||
case FunctionMetadataConvention::Thin:
|
||||
representation = FunctionTypeRepresentation::Thin;
|
||||
break;
|
||||
case FunctionMetadataConvention::CFunctionPointer:
|
||||
representation = FunctionTypeRepresentation::CFunctionPointer;
|
||||
break;
|
||||
}
|
||||
|
||||
auto einfo = AnyFunctionType::ExtInfo(representation,
|
||||
/*throws*/ flags.throws());
|
||||
if (flags.isEscaping())
|
||||
einfo = einfo.withNoEscape(false);
|
||||
else
|
||||
einfo = einfo.withNoEscape(true);
|
||||
|
||||
// The result type must be materializable.
|
||||
if (!output->isMaterializable()) return Type();
|
||||
|
||||
llvm::SmallVector<AnyFunctionType::Param, 8> funcParams;
|
||||
for (const auto ¶m : params) {
|
||||
auto type = param.getType();
|
||||
|
||||
// All the argument types must be materializable.
|
||||
if (!type->isMaterializable())
|
||||
return Type();
|
||||
|
||||
auto label = Ctx.getIdentifier(param.getLabel());
|
||||
auto flags = param.getFlags();
|
||||
auto ownership = flags.getValueOwnership();
|
||||
auto parameterFlags = ParameterTypeFlags()
|
||||
.withValueOwnership(ownership)
|
||||
.withVariadic(flags.isVariadic())
|
||||
.withAutoClosure(flags.isAutoClosure());
|
||||
|
||||
funcParams.push_back(AnyFunctionType::Param(type, label, parameterFlags));
|
||||
}
|
||||
|
||||
return FunctionType::get(funcParams, output, einfo);
|
||||
}
|
||||
|
||||
Type ASTBuilder::createProtocolCompositionType(
|
||||
ArrayRef<ProtocolDecl *> protocols,
|
||||
Type superclass,
|
||||
bool isClassBound) {
|
||||
std::vector<Type> members;
|
||||
for (auto protocol : protocols)
|
||||
members.push_back(protocol->getDeclaredType());
|
||||
if (superclass && superclass->getClassOrBoundGenericClass())
|
||||
members.push_back(superclass);
|
||||
return ProtocolCompositionType::get(Ctx, members, isClassBound);
|
||||
}
|
||||
|
||||
Type ASTBuilder::createExistentialMetatypeType(Type instance) {
|
||||
if (!instance->isAnyExistentialType())
|
||||
return Type();
|
||||
return ExistentialMetatypeType::get(instance);
|
||||
}
|
||||
|
||||
Type ASTBuilder::createMetatypeType(Type instance,
|
||||
bool wasAbstract) {
|
||||
// FIXME: Plumb through metatype representation and generalize silly
|
||||
// 'wasAbstract' flag
|
||||
return MetatypeType::get(instance);
|
||||
}
|
||||
|
||||
Type ASTBuilder::createGenericTypeParameterType(unsigned depth,
|
||||
unsigned index) {
|
||||
return GenericTypeParamType::get(depth, index, Ctx);
|
||||
}
|
||||
|
||||
Type ASTBuilder::createDependentMemberType(StringRef member,
|
||||
Type base,
|
||||
ProtocolDecl *protocol) {
|
||||
if (!base->isTypeParameter())
|
||||
return Type();
|
||||
|
||||
auto flags = OptionSet<NominalTypeDecl::LookupDirectFlags>();
|
||||
flags |= NominalTypeDecl::LookupDirectFlags::IgnoreNewExtensions;
|
||||
for (auto member : protocol->lookupDirect(Ctx.getIdentifier(member),
|
||||
flags)) {
|
||||
if (auto assocType = dyn_cast<AssociatedTypeDecl>(member))
|
||||
return DependentMemberType::get(base, assocType);
|
||||
}
|
||||
|
||||
return Type();
|
||||
}
|
||||
|
||||
#define REF_STORAGE(Name, ...) \
|
||||
Type ASTBuilder::create##Name##StorageType(Type base) { \
|
||||
if (!base->allowsOwnership()) \
|
||||
return Type(); \
|
||||
return Name##StorageType::get(base, Ctx); \
|
||||
}
|
||||
#include "swift/AST/ReferenceStorage.def"
|
||||
|
||||
Type ASTBuilder::createSILBoxType(Type base) {
|
||||
return SILBoxType::get(base->getCanonicalType());
|
||||
}
|
||||
|
||||
Type ASTBuilder::createObjCClassType(StringRef name) {
|
||||
auto typeDecl =
|
||||
findForeignNominalTypeDecl(name, /*relatedEntityKind*/{},
|
||||
ForeignModuleKind::Imported,
|
||||
Demangle::Node::Kind::Class);
|
||||
if (!typeDecl) return Type();
|
||||
return createNominalType(typeDecl, /*parent*/ Type());
|
||||
}
|
||||
|
||||
ProtocolDecl *ASTBuilder::createObjCProtocolDecl(StringRef name) {
|
||||
auto typeDecl =
|
||||
findForeignNominalTypeDecl(name, /*relatedEntityKind*/{},
|
||||
ForeignModuleKind::Imported,
|
||||
Demangle::Node::Kind::Protocol);
|
||||
if (auto *protocolDecl = dyn_cast_or_null<ProtocolDecl>(typeDecl))
|
||||
return protocolDecl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Type ASTBuilder::createForeignClassType(StringRef mangledName) {
|
||||
auto typeDecl = createNominalTypeDecl(mangledName);
|
||||
if (!typeDecl) return Type();
|
||||
|
||||
return createNominalType(typeDecl, /*parent*/ Type());
|
||||
}
|
||||
|
||||
Type ASTBuilder::getUnnamedForeignClassType() {
|
||||
return Type();
|
||||
}
|
||||
|
||||
Type ASTBuilder::getOpaqueType() {
|
||||
return Type();
|
||||
}
|
||||
|
||||
bool ASTBuilder::validateNominalParent(NominalTypeDecl *decl,
|
||||
Type parent) {
|
||||
auto parentDecl = decl->getDeclContext()->getSelfNominalTypeDecl();
|
||||
|
||||
// If we don't have a parent type, fast-path.
|
||||
if (!parent) {
|
||||
return parentDecl == nullptr;
|
||||
}
|
||||
|
||||
// We do have a parent type. If the nominal type doesn't, it's an error.
|
||||
if (!parentDecl) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// FIXME: validate that the parent is a correct application of the
|
||||
// enclosing context?
|
||||
return true;
|
||||
}
|
||||
|
||||
Type ASTBuilder::checkTypeRepr(TypeRepr *repr) {
|
||||
DeclContext *dc = getNotionalDC();
|
||||
|
||||
TypeLoc loc(repr);
|
||||
if (performTypeLocChecking(Ctx, loc, dc, /*diagnose*/ false))
|
||||
return Type();
|
||||
|
||||
return loc.getType();
|
||||
}
|
||||
|
||||
NominalTypeDecl *
|
||||
ASTBuilder::getAcceptableNominalTypeCandidate(ValueDecl *decl,
|
||||
Demangle::Node::Kind kind) {
|
||||
if (kind == Demangle::Node::Kind::Class) {
|
||||
return dyn_cast<ClassDecl>(decl);
|
||||
} else if (kind == Demangle::Node::Kind::Enum) {
|
||||
return dyn_cast<EnumDecl>(decl);
|
||||
} else if (kind == Demangle::Node::Kind::Protocol) {
|
||||
return dyn_cast<ProtocolDecl>(decl);
|
||||
} else {
|
||||
assert(kind == Demangle::Node::Kind::Structure);
|
||||
return dyn_cast<StructDecl>(decl);
|
||||
}
|
||||
}
|
||||
|
||||
DeclContext *ASTBuilder::getNotionalDC() {
|
||||
if (!NotionalDC) {
|
||||
NotionalDC = ModuleDecl::create(Ctx.getIdentifier(".RemoteAST"), Ctx);
|
||||
NotionalDC = new (Ctx) TopLevelCodeDecl(NotionalDC);
|
||||
}
|
||||
return NotionalDC;
|
||||
}
|
||||
|
||||
NominalTypeDecl *
|
||||
ASTBuilder::createNominalTypeDecl(const Demangle::NodePointer &node) {
|
||||
auto DC = findDeclContext(node);
|
||||
if (!DC)
|
||||
return nullptr;
|
||||
|
||||
auto decl = dyn_cast<NominalTypeDecl>(DC);
|
||||
if (!decl) return nullptr;
|
||||
|
||||
return decl;
|
||||
}
|
||||
|
||||
ModuleDecl *
|
||||
ASTBuilder::findModule(const Demangle::NodePointer &node) {
|
||||
assert(node->getKind() == Demangle::Node::Kind::Module);
|
||||
const auto &moduleName = node->getText();
|
||||
return Ctx.getModuleByName(moduleName);
|
||||
}
|
||||
|
||||
Demangle::NodePointer
|
||||
ASTBuilder::findModuleNode(const Demangle::NodePointer &node) {
|
||||
if (node->getKind() == Demangle::Node::Kind::Module)
|
||||
return node;
|
||||
|
||||
if (!node->hasChildren()) return nullptr;
|
||||
const auto &child = node->getFirstChild();
|
||||
if (child->getKind() != Demangle::Node::Kind::DeclContext)
|
||||
return nullptr;
|
||||
|
||||
return findModuleNode(child->getFirstChild());
|
||||
}
|
||||
|
||||
Optional<ASTBuilder::ForeignModuleKind>
|
||||
ASTBuilder::getForeignModuleKind(const Demangle::NodePointer &node) {
|
||||
if (node->getKind() == Demangle::Node::Kind::DeclContext)
|
||||
return getForeignModuleKind(node->getFirstChild());
|
||||
|
||||
if (node->getKind() != Demangle::Node::Kind::Module)
|
||||
return None;
|
||||
|
||||
return llvm::StringSwitch<Optional<ForeignModuleKind>>(node->getText())
|
||||
.Case(MANGLING_MODULE_OBJC, ForeignModuleKind::Imported)
|
||||
.Case(MANGLING_MODULE_CLANG_IMPORTER,
|
||||
ForeignModuleKind::SynthesizedByImporter)
|
||||
.Default(None);
|
||||
}
|
||||
|
||||
DeclContext *
|
||||
ASTBuilder::findDeclContext(const Demangle::NodePointer &node) {
|
||||
switch (node->getKind()) {
|
||||
case Demangle::Node::Kind::DeclContext:
|
||||
case Demangle::Node::Kind::Type:
|
||||
return findDeclContext(node->getFirstChild());
|
||||
|
||||
case Demangle::Node::Kind::Module:
|
||||
return findModule(node);
|
||||
|
||||
case Demangle::Node::Kind::Class:
|
||||
case Demangle::Node::Kind::Enum:
|
||||
case Demangle::Node::Kind::Protocol:
|
||||
case Demangle::Node::Kind::Structure:
|
||||
case Demangle::Node::Kind::TypeAlias: {
|
||||
const auto &declNameNode = node->getChild(1);
|
||||
|
||||
// Handle local declarations.
|
||||
if (declNameNode->getKind() == Demangle::Node::Kind::LocalDeclName) {
|
||||
// Find the AST node for the defining module.
|
||||
auto moduleNode = findModuleNode(node);
|
||||
if (!moduleNode) return nullptr;
|
||||
|
||||
auto module = findModule(moduleNode);
|
||||
if (!module) return nullptr;
|
||||
|
||||
// Look up the local type by its mangling.
|
||||
auto mangledName = Demangle::mangleNode(node);
|
||||
auto decl = module->lookupLocalType(mangledName);
|
||||
if (!decl) return nullptr;
|
||||
|
||||
return dyn_cast<DeclContext>(decl);
|
||||
}
|
||||
|
||||
StringRef name;
|
||||
StringRef relatedEntityKind;
|
||||
Identifier privateDiscriminator;
|
||||
if (declNameNode->getKind() == Demangle::Node::Kind::Identifier) {
|
||||
name = declNameNode->getText();
|
||||
|
||||
} else if (declNameNode->getKind() ==
|
||||
Demangle::Node::Kind::PrivateDeclName) {
|
||||
name = declNameNode->getChild(1)->getText();
|
||||
privateDiscriminator =
|
||||
Ctx.getIdentifier(declNameNode->getChild(0)->getText());
|
||||
|
||||
} else if (declNameNode->getKind() ==
|
||||
Demangle::Node::Kind::RelatedEntityDeclName) {
|
||||
name = declNameNode->getChild(0)->getText();
|
||||
relatedEntityKind = declNameNode->getText();
|
||||
|
||||
// Ignore any other decl-name productions for now.
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DeclContext *dc = findDeclContext(node->getChild(0));
|
||||
if (!dc) {
|
||||
// Do some backup logic for foreign type declarations.
|
||||
if (privateDiscriminator.empty()) {
|
||||
if (auto foreignModuleKind = getForeignModuleKind(node->getChild(0))) {
|
||||
return findForeignNominalTypeDecl(name, relatedEntityKind,
|
||||
foreignModuleKind.getValue(),
|
||||
node->getKind());
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return findNominalTypeDecl(dc, Ctx.getIdentifier(name),
|
||||
privateDiscriminator, node->getKind());
|
||||
}
|
||||
|
||||
case Demangle::Node::Kind::Global:
|
||||
return findDeclContext(node->getChild(0));
|
||||
|
||||
// Bail out on other kinds of contexts.
|
||||
// TODO: extensions
|
||||
// TODO: local contexts
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
NominalTypeDecl *
|
||||
ASTBuilder::findNominalTypeDecl(DeclContext *dc,
|
||||
Identifier name,
|
||||
Identifier privateDiscriminator,
|
||||
Demangle::Node::Kind kind) {
|
||||
auto module = dc->getParentModule();
|
||||
|
||||
SmallVector<ValueDecl *, 4> lookupResults;
|
||||
module->lookupMember(lookupResults, dc, name, privateDiscriminator);
|
||||
|
||||
NominalTypeDecl *result = nullptr;
|
||||
for (auto decl : lookupResults) {
|
||||
// Ignore results that are not the right kind of nominal type declaration.
|
||||
NominalTypeDecl *candidate = getAcceptableNominalTypeCandidate(decl, kind);
|
||||
if (!candidate)
|
||||
continue;
|
||||
|
||||
// Ignore results that aren't actually from the defining module.
|
||||
if (candidate->getParentModule() != module)
|
||||
continue;
|
||||
|
||||
// This is a viable result.
|
||||
|
||||
// If we already have a viable result, it's ambiguous, so give up.
|
||||
if (result) return nullptr;
|
||||
result = candidate;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static Optional<ClangTypeKind>
|
||||
getClangTypeKindForNodeKind(Demangle::Node::Kind kind) {
|
||||
switch (kind) {
|
||||
case Demangle::Node::Kind::Protocol:
|
||||
return ClangTypeKind::ObjCProtocol;
|
||||
case Demangle::Node::Kind::Class:
|
||||
return ClangTypeKind::ObjCClass;
|
||||
case Demangle::Node::Kind::TypeAlias:
|
||||
return ClangTypeKind::Typedef;
|
||||
case Demangle::Node::Kind::Structure:
|
||||
case Demangle::Node::Kind::Enum:
|
||||
return ClangTypeKind::Tag;
|
||||
default:
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
NominalTypeDecl *
|
||||
ASTBuilder::findForeignNominalTypeDecl(StringRef name,
|
||||
StringRef relatedEntityKind,
|
||||
ForeignModuleKind foreignKind,
|
||||
Demangle::Node::Kind kind) {
|
||||
// Check to see if we have an importer loaded.
|
||||
auto importer = static_cast<ClangImporter *>(Ctx.getClangModuleLoader());
|
||||
if (!importer) return nullptr;
|
||||
|
||||
// Find the unique declaration that has the right kind.
|
||||
struct Consumer : VisibleDeclConsumer {
|
||||
Demangle::Node::Kind ExpectedKind;
|
||||
NominalTypeDecl *Result = nullptr;
|
||||
bool HadError = false;
|
||||
|
||||
explicit Consumer(Demangle::Node::Kind kind) : ExpectedKind(kind) {}
|
||||
|
||||
void foundDecl(ValueDecl *decl, DeclVisibilityKind reason) override {
|
||||
if (HadError) return;
|
||||
if (decl == Result) return;
|
||||
if (!Result) {
|
||||
// A synthesized type from the Clang importer may resolve to a
|
||||
// compatibility alias.
|
||||
if (auto resultAlias = dyn_cast<TypeAliasDecl>(decl)) {
|
||||
if (resultAlias->isCompatibilityAlias()) {
|
||||
Result = resultAlias->getUnderlyingTypeLoc().getType()
|
||||
->getAnyNominal();
|
||||
}
|
||||
} else {
|
||||
Result = dyn_cast<NominalTypeDecl>(decl);
|
||||
}
|
||||
HadError |= !Result;
|
||||
} else {
|
||||
HadError = true;
|
||||
Result = nullptr;
|
||||
}
|
||||
}
|
||||
} consumer(kind);
|
||||
|
||||
switch (foreignKind) {
|
||||
case ForeignModuleKind::SynthesizedByImporter:
|
||||
if (!relatedEntityKind.empty()) {
|
||||
Optional<ClangTypeKind> lookupKind = getClangTypeKindForNodeKind(kind);
|
||||
if (!lookupKind)
|
||||
return nullptr;
|
||||
importer->lookupRelatedEntity(name, lookupKind.getValue(),
|
||||
relatedEntityKind, [&](TypeDecl *found) {
|
||||
consumer.foundDecl(found, DeclVisibilityKind::VisibleAtTopLevel);
|
||||
});
|
||||
break;
|
||||
}
|
||||
importer->lookupValue(Ctx.getIdentifier(name), consumer);
|
||||
if (consumer.Result)
|
||||
consumer.Result = getAcceptableNominalTypeCandidate(consumer.Result,kind);
|
||||
break;
|
||||
case ForeignModuleKind::Imported: {
|
||||
Optional<ClangTypeKind> lookupKind = getClangTypeKindForNodeKind(kind);
|
||||
if (!lookupKind)
|
||||
return nullptr;
|
||||
importer->lookupTypeDecl(name, lookupKind.getValue(),
|
||||
[&](TypeDecl *found) {
|
||||
consumer.foundDecl(found, DeclVisibilityKind::VisibleAtTopLevel);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return consumer.Result;
|
||||
}
|
||||
@@ -7,6 +7,7 @@ add_swift_host_library(swiftAST STATIC
|
||||
AccessScopeChecker.cpp
|
||||
AccessRequests.cpp
|
||||
ASTContext.cpp
|
||||
ASTDemangler.cpp
|
||||
ASTDumper.cpp
|
||||
ASTMangler.cpp
|
||||
ASTNode.cpp
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "swift/AST/DiagnosticsParse.h"
|
||||
#include "swift/AST/Module.h"
|
||||
#include "swift/Basic/Defer.h"
|
||||
#include "swift/Parse/SyntaxParsingCache.h"
|
||||
#include "swift/Parse/Token.h"
|
||||
#include "swift/Syntax/RawSyntax.h"
|
||||
#include "swift/Syntax/References.h"
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "swift/Strings.h"
|
||||
#include "swift/Subsystems.h"
|
||||
#include "swift/AST/ASTContext.h"
|
||||
#include "swift/AST/ASTDemangler.h"
|
||||
#include "swift/AST/Decl.h"
|
||||
#include "swift/AST/ExistentialLayout.h"
|
||||
#include "swift/AST/GenericSignature.h"
|
||||
@@ -86,733 +87,12 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/// An implementation of MetadataReader's BuilderType concept that
|
||||
/// just finds and builds things in the AST.
|
||||
class RemoteASTTypeBuilder {
|
||||
ASTContext &Ctx;
|
||||
Demangle::NodeFactory Factory;
|
||||
|
||||
/// The notional context in which we're writing and type-checking code.
|
||||
/// Created lazily.
|
||||
DeclContext *NotionalDC = nullptr;
|
||||
|
||||
Optional<Failure> CurFailure;
|
||||
|
||||
public:
|
||||
using BuiltType = swift::Type;
|
||||
using BuiltNominalTypeDecl = swift::NominalTypeDecl *;
|
||||
using BuiltProtocolDecl = swift::ProtocolDecl *;
|
||||
explicit RemoteASTTypeBuilder(ASTContext &ctx) : Ctx(ctx) {}
|
||||
|
||||
std::unique_ptr<IRGenContext> createIRGenContext() {
|
||||
return IRGenContext::create(Ctx, getNotionalDC());
|
||||
}
|
||||
|
||||
template <class Result, class FailureKindTy, class... FailureArgTys>
|
||||
Result fail(FailureKindTy kind, FailureArgTys &&...failureArgs) {
|
||||
if (!CurFailure) {
|
||||
CurFailure.emplace(kind, std::forward<FailureArgTys>(failureArgs)...);
|
||||
}
|
||||
return Result();
|
||||
}
|
||||
|
||||
template <class T, class DefaultFailureKindTy, class... DefaultFailureArgTys>
|
||||
Result<T> getFailureAsResult(DefaultFailureKindTy defaultFailureKind,
|
||||
DefaultFailureArgTys &&...defaultFailureArgs) {
|
||||
// If we already have a failure, use that.
|
||||
if (CurFailure) {
|
||||
Result<T> result = std::move(*CurFailure);
|
||||
CurFailure.reset();
|
||||
return result;
|
||||
}
|
||||
|
||||
// Otherwise, use the default failure.
|
||||
return Result<T>::emplaceFailure(defaultFailureKind,
|
||||
std::forward<DefaultFailureArgTys>(defaultFailureArgs)...);
|
||||
}
|
||||
|
||||
Demangle::NodeFactory &getNodeFactory() { return Factory; }
|
||||
|
||||
Type createBuiltinType(const std::string &mangledName) {
|
||||
// TODO
|
||||
return Type();
|
||||
}
|
||||
|
||||
NominalTypeDecl *createNominalTypeDecl(StringRef mangledName) {
|
||||
Demangle::Demangler Dem;
|
||||
Demangle::NodePointer node = Dem.demangleType(mangledName);
|
||||
if (!node) return nullptr;
|
||||
|
||||
return createNominalTypeDecl(node);
|
||||
}
|
||||
|
||||
NominalTypeDecl *createNominalTypeDecl(const Demangle::NodePointer &node);
|
||||
|
||||
ProtocolDecl *createProtocolDecl(const Demangle::NodePointer &node) {
|
||||
return dyn_cast_or_null<ProtocolDecl>(createNominalTypeDecl(node));
|
||||
}
|
||||
|
||||
Type createNominalType(NominalTypeDecl *decl) {
|
||||
// If the declaration is generic, fail.
|
||||
if (decl->isGenericContext())
|
||||
return Type();
|
||||
|
||||
return decl->getDeclaredType();
|
||||
}
|
||||
|
||||
Type createNominalType(NominalTypeDecl *decl, Type parent) {
|
||||
// If the declaration is generic, fail.
|
||||
if (decl->getGenericParams())
|
||||
return Type();
|
||||
|
||||
// Validate the parent type.
|
||||
if (!validateNominalParent(decl, parent))
|
||||
return Type();
|
||||
|
||||
return NominalType::get(decl, parent, Ctx);
|
||||
}
|
||||
|
||||
Type createBoundGenericType(NominalTypeDecl *decl, ArrayRef<Type> args) {
|
||||
// If the declaration isn't generic, fail.
|
||||
if (!decl->isGenericContext())
|
||||
return Type();
|
||||
|
||||
// Build a SubstitutionMap.
|
||||
auto *genericSig = decl->getGenericSignature();
|
||||
|
||||
SmallVector<GenericTypeParamType *, 4> genericParams;
|
||||
genericSig->forEachParam([&](GenericTypeParamType *gp, bool canonical) {
|
||||
if (canonical)
|
||||
genericParams.push_back(gp);
|
||||
});
|
||||
if (genericParams.size() != args.size())
|
||||
return Type();
|
||||
|
||||
auto subMap = SubstitutionMap::get(
|
||||
genericSig,
|
||||
[&](SubstitutableType *t) -> Type {
|
||||
for (unsigned i = 0, e = genericParams.size(); i < e; ++i) {
|
||||
if (t->isEqual(genericParams[i]))
|
||||
return args[i];
|
||||
}
|
||||
return Type();
|
||||
},
|
||||
// FIXME: Wrong module
|
||||
LookUpConformanceInModule(decl->getParentModule()));
|
||||
|
||||
auto origType = decl->getDeclaredInterfaceType();
|
||||
|
||||
// FIXME: We're not checking that the type satisfies the generic
|
||||
// requirements of the signature here.
|
||||
auto substType = origType.subst(subMap);
|
||||
return substType;
|
||||
}
|
||||
|
||||
Type createBoundGenericType(NominalTypeDecl *decl, ArrayRef<Type> args,
|
||||
Type parent) {
|
||||
// If the declaration isn't generic, fail.
|
||||
if (!decl->getGenericParams())
|
||||
return Type();
|
||||
|
||||
// Validate the parent type.
|
||||
if (!validateNominalParent(decl, parent))
|
||||
return Type();
|
||||
|
||||
// Make a generic type repr that's been resolved to this decl.
|
||||
TypeReprList genericArgReprs(args);
|
||||
auto genericRepr = GenericIdentTypeRepr::create(Ctx, SourceLoc(),
|
||||
decl->getName(),
|
||||
genericArgReprs.getList(),
|
||||
SourceRange());
|
||||
// FIXME
|
||||
genericRepr->setValue(decl, nullptr);
|
||||
|
||||
Type genericType;
|
||||
|
||||
// If we have a parent type, we need to build a compound type repr.
|
||||
if (parent) {
|
||||
// Life would be much easier if we could just use a FixedTypeRepr for
|
||||
// the parent. But we can't! So we have to recursively expand
|
||||
// like this; and recursing with a lambda isn't impossible, so it gets
|
||||
// even worse.
|
||||
SmallVector<Type, 4> ancestry;
|
||||
for (auto p = parent; p; p = p->getNominalParent()) {
|
||||
ancestry.push_back(p);
|
||||
}
|
||||
|
||||
struct GenericRepr {
|
||||
TypeReprList GenericArgs;
|
||||
GenericIdentTypeRepr *Ident;
|
||||
|
||||
GenericRepr(const ASTContext &Ctx, BoundGenericType *type)
|
||||
: GenericArgs(type->getGenericArgs()),
|
||||
Ident(GenericIdentTypeRepr::create(Ctx, SourceLoc(),
|
||||
type->getDecl()->getName(),
|
||||
GenericArgs.getList(),
|
||||
SourceRange())) {
|
||||
// FIXME
|
||||
Ident->setValue(type->getDecl(), nullptr);
|
||||
}
|
||||
|
||||
// SmallVector::emplace_back will never need to call this because
|
||||
// we reserve the right size, but it does try statically.
|
||||
GenericRepr(const GenericRepr &other) : GenericArgs({}), Ident(nullptr) {
|
||||
llvm_unreachable("should not be called dynamically");
|
||||
}
|
||||
};
|
||||
|
||||
// Pre-allocate the component vectors so that we can form references
|
||||
// into them safely.
|
||||
SmallVector<SimpleIdentTypeRepr, 4> simpleComponents;
|
||||
SmallVector<GenericRepr, 4> genericComponents;
|
||||
simpleComponents.reserve(ancestry.size());
|
||||
genericComponents.reserve(ancestry.size());
|
||||
|
||||
// Build the parent hierarchy.
|
||||
SmallVector<ComponentIdentTypeRepr*, 4> componentReprs;
|
||||
for (size_t i = ancestry.size(); i != 0; --i) {
|
||||
Type p = ancestry[i - 1];
|
||||
if (auto boundGeneric = p->getAs<BoundGenericType>()) {
|
||||
genericComponents.emplace_back(Ctx, boundGeneric);
|
||||
componentReprs.push_back(genericComponents.back().Ident);
|
||||
} else {
|
||||
auto nominal = p->castTo<NominalType>();
|
||||
simpleComponents.emplace_back(SourceLoc(),
|
||||
nominal->getDecl()->getName());
|
||||
// FIXME
|
||||
simpleComponents.back().setValue(nominal->getDecl(), nullptr);
|
||||
componentReprs.push_back(&simpleComponents.back());
|
||||
}
|
||||
}
|
||||
componentReprs.push_back(genericRepr);
|
||||
|
||||
auto compoundRepr = CompoundIdentTypeRepr::create(Ctx, componentReprs);
|
||||
genericType = checkTypeRepr(compoundRepr);
|
||||
} else {
|
||||
genericType = checkTypeRepr(genericRepr);
|
||||
}
|
||||
|
||||
// If type-checking failed, we've failed.
|
||||
if (!genericType) return Type();
|
||||
|
||||
// Validate that we used the right decl.
|
||||
if (auto bgt = genericType->getAs<BoundGenericType>()) {
|
||||
if (bgt->getDecl() != decl)
|
||||
return Type();
|
||||
}
|
||||
|
||||
return genericType;
|
||||
}
|
||||
|
||||
Type createTupleType(ArrayRef<Type> eltTypes, StringRef labels,
|
||||
bool isVariadic) {
|
||||
// Just bail out on variadic tuples for now.
|
||||
if (isVariadic) return Type();
|
||||
|
||||
SmallVector<TupleTypeElt, 4> elements;
|
||||
elements.reserve(eltTypes.size());
|
||||
for (auto eltType : eltTypes) {
|
||||
Identifier label;
|
||||
if (!labels.empty()) {
|
||||
auto split = labels.split(' ');
|
||||
if (!split.first.empty())
|
||||
label = Ctx.getIdentifier(split.first);
|
||||
labels = split.second;
|
||||
}
|
||||
elements.emplace_back(eltType, label);
|
||||
}
|
||||
|
||||
return TupleType::get(elements, Ctx);
|
||||
}
|
||||
|
||||
Type createFunctionType(ArrayRef<remote::FunctionParam<Type>> params,
|
||||
Type output, FunctionTypeFlags flags) {
|
||||
FunctionTypeRepresentation representation;
|
||||
switch (flags.getConvention()) {
|
||||
case FunctionMetadataConvention::Swift:
|
||||
representation = FunctionTypeRepresentation::Swift;
|
||||
break;
|
||||
case FunctionMetadataConvention::Block:
|
||||
representation = FunctionTypeRepresentation::Block;
|
||||
break;
|
||||
case FunctionMetadataConvention::Thin:
|
||||
representation = FunctionTypeRepresentation::Thin;
|
||||
break;
|
||||
case FunctionMetadataConvention::CFunctionPointer:
|
||||
representation = FunctionTypeRepresentation::CFunctionPointer;
|
||||
break;
|
||||
}
|
||||
|
||||
auto einfo = AnyFunctionType::ExtInfo(representation,
|
||||
/*throws*/ flags.throws());
|
||||
if (flags.isEscaping())
|
||||
einfo = einfo.withNoEscape(false);
|
||||
else
|
||||
einfo = einfo.withNoEscape(true);
|
||||
|
||||
// The result type must be materializable.
|
||||
if (!output->isMaterializable()) return Type();
|
||||
|
||||
llvm::SmallVector<AnyFunctionType::Param, 8> funcParams;
|
||||
for (const auto ¶m : params) {
|
||||
auto type = param.getType();
|
||||
|
||||
// All the argument types must be materializable.
|
||||
if (!type->isMaterializable())
|
||||
return Type();
|
||||
|
||||
auto label = Ctx.getIdentifier(param.getLabel());
|
||||
auto flags = param.getFlags();
|
||||
auto ownership = flags.getValueOwnership();
|
||||
auto parameterFlags = ParameterTypeFlags()
|
||||
.withValueOwnership(ownership)
|
||||
.withVariadic(flags.isVariadic())
|
||||
.withAutoClosure(flags.isAutoClosure());
|
||||
|
||||
funcParams.push_back(AnyFunctionType::Param(type, label, parameterFlags));
|
||||
}
|
||||
|
||||
return FunctionType::get(funcParams, output, einfo);
|
||||
}
|
||||
|
||||
Type createProtocolCompositionType(ArrayRef<ProtocolDecl *> protocols,
|
||||
Type superclass,
|
||||
bool isClassBound) {
|
||||
std::vector<Type> members;
|
||||
for (auto protocol : protocols)
|
||||
members.push_back(protocol->getDeclaredType());
|
||||
if (superclass && superclass->getClassOrBoundGenericClass())
|
||||
members.push_back(superclass);
|
||||
return ProtocolCompositionType::get(Ctx, members, isClassBound);
|
||||
}
|
||||
|
||||
Type createExistentialMetatypeType(Type instance) {
|
||||
if (!instance->isAnyExistentialType())
|
||||
return Type();
|
||||
return ExistentialMetatypeType::get(instance);
|
||||
}
|
||||
|
||||
Type createMetatypeType(Type instance, bool wasAbstract=false) {
|
||||
// FIXME: Plumb through metatype representation and generalize silly
|
||||
// 'wasAbstract' flag
|
||||
return MetatypeType::get(instance);
|
||||
}
|
||||
|
||||
Type createGenericTypeParameterType(unsigned depth, unsigned index) {
|
||||
return GenericTypeParamType::get(depth, index, Ctx);
|
||||
}
|
||||
|
||||
Type createDependentMemberType(StringRef member, Type base,
|
||||
ProtocolDecl *protocol) {
|
||||
if (!base->isTypeParameter())
|
||||
return Type();
|
||||
|
||||
auto flags = OptionSet<NominalTypeDecl::LookupDirectFlags>();
|
||||
flags |= NominalTypeDecl::LookupDirectFlags::IgnoreNewExtensions;
|
||||
for (auto member : protocol->lookupDirect(Ctx.getIdentifier(member),
|
||||
flags)) {
|
||||
if (auto assocType = dyn_cast<AssociatedTypeDecl>(member))
|
||||
return DependentMemberType::get(base, assocType);
|
||||
}
|
||||
|
||||
return Type();
|
||||
}
|
||||
|
||||
#define REF_STORAGE(Name, ...) \
|
||||
Type create##Name##StorageType(Type base) { \
|
||||
if (!base->allowsOwnership()) \
|
||||
return Type(); \
|
||||
return Name##StorageType::get(base, Ctx); \
|
||||
}
|
||||
#include "swift/AST/ReferenceStorage.def"
|
||||
|
||||
Type createSILBoxType(Type base) {
|
||||
return SILBoxType::get(base->getCanonicalType());
|
||||
}
|
||||
|
||||
Type createObjCClassType(StringRef name) {
|
||||
auto typeDecl =
|
||||
findForeignNominalTypeDecl(name, /*relatedEntityKind*/{},
|
||||
ForeignModuleKind::Imported,
|
||||
Demangle::Node::Kind::Class);
|
||||
if (!typeDecl) return Type();
|
||||
return createNominalType(typeDecl, /*parent*/ Type());
|
||||
}
|
||||
|
||||
ProtocolDecl *createObjCProtocolDecl(StringRef name) {
|
||||
auto typeDecl =
|
||||
findForeignNominalTypeDecl(name, /*relatedEntityKind*/{},
|
||||
ForeignModuleKind::Imported,
|
||||
Demangle::Node::Kind::Protocol);
|
||||
if (auto *protocolDecl = dyn_cast_or_null<ProtocolDecl>(typeDecl))
|
||||
return protocolDecl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Type createForeignClassType(StringRef mangledName) {
|
||||
auto typeDecl = createNominalTypeDecl(mangledName);
|
||||
if (!typeDecl) return Type();
|
||||
|
||||
return createNominalType(typeDecl, /*parent*/ Type());
|
||||
}
|
||||
|
||||
Type getUnnamedForeignClassType() {
|
||||
return Type();
|
||||
}
|
||||
|
||||
Type getOpaqueType() {
|
||||
return Type();
|
||||
}
|
||||
|
||||
private:
|
||||
bool validateNominalParent(NominalTypeDecl *decl, Type parent) {
|
||||
auto parentDecl = decl->getDeclContext()->getSelfNominalTypeDecl();
|
||||
|
||||
// If we don't have a parent type, fast-path.
|
||||
if (!parent) {
|
||||
return parentDecl == nullptr;
|
||||
}
|
||||
|
||||
// We do have a parent type. If the nominal type doesn't, it's an error.
|
||||
if (!parentDecl) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// FIXME: validate that the parent is a correct application of the
|
||||
// enclosing context?
|
||||
return true;
|
||||
}
|
||||
|
||||
DeclContext *findDeclContext(const Demangle::NodePointer &node);
|
||||
ModuleDecl *findModule(const Demangle::NodePointer &node);
|
||||
Demangle::NodePointer findModuleNode(const Demangle::NodePointer &node);
|
||||
|
||||
enum class ForeignModuleKind {
|
||||
Imported,
|
||||
SynthesizedByImporter
|
||||
};
|
||||
|
||||
Optional<ForeignModuleKind>
|
||||
getForeignModuleKind(const Demangle::NodePointer &node);
|
||||
|
||||
NominalTypeDecl *findNominalTypeDecl(DeclContext *dc,
|
||||
Identifier name,
|
||||
Identifier privateDiscriminator,
|
||||
Demangle::Node::Kind kind);
|
||||
NominalTypeDecl *findForeignNominalTypeDecl(StringRef name,
|
||||
StringRef relatedEntityKind,
|
||||
ForeignModuleKind lookupKind,
|
||||
Demangle::Node::Kind kind);
|
||||
|
||||
Type checkTypeRepr(TypeRepr *repr) {
|
||||
DeclContext *dc = getNotionalDC();
|
||||
|
||||
TypeLoc loc(repr);
|
||||
if (performTypeLocChecking(Ctx, loc, dc, /*diagnose*/ false))
|
||||
return Type();
|
||||
|
||||
return loc.getType();
|
||||
}
|
||||
|
||||
static NominalTypeDecl *getAcceptableNominalTypeCandidate(ValueDecl *decl,
|
||||
Demangle::Node::Kind kind) {
|
||||
if (kind == Demangle::Node::Kind::Class) {
|
||||
return dyn_cast<ClassDecl>(decl);
|
||||
} else if (kind == Demangle::Node::Kind::Enum) {
|
||||
return dyn_cast<EnumDecl>(decl);
|
||||
} else if (kind == Demangle::Node::Kind::Protocol) {
|
||||
return dyn_cast<ProtocolDecl>(decl);
|
||||
} else {
|
||||
assert(kind == Demangle::Node::Kind::Structure);
|
||||
return dyn_cast<StructDecl>(decl);
|
||||
}
|
||||
}
|
||||
|
||||
DeclContext *getNotionalDC() {
|
||||
if (!NotionalDC) {
|
||||
NotionalDC = ModuleDecl::create(Ctx.getIdentifier(".RemoteAST"), Ctx);
|
||||
NotionalDC = new (Ctx) TopLevelCodeDecl(NotionalDC);
|
||||
}
|
||||
return NotionalDC;
|
||||
}
|
||||
|
||||
class TypeReprList {
|
||||
SmallVector<FixedTypeRepr, 4> Reprs;
|
||||
SmallVector<TypeRepr*, 4> Refs;
|
||||
|
||||
public:
|
||||
explicit TypeReprList(ArrayRef<Type> types) {
|
||||
Reprs.reserve(types.size());
|
||||
Refs.reserve(types.size());
|
||||
|
||||
for (auto type : types) {
|
||||
Reprs.emplace_back(type, SourceLoc());
|
||||
Refs.push_back(&Reprs.back());
|
||||
}
|
||||
}
|
||||
|
||||
ArrayRef<TypeRepr*> getList() const {
|
||||
return Refs;
|
||||
}
|
||||
};
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
NominalTypeDecl *
|
||||
RemoteASTTypeBuilder::createNominalTypeDecl(const Demangle::NodePointer &node) {
|
||||
auto DC = findDeclContext(node);
|
||||
if (!DC) {
|
||||
return fail<NominalTypeDecl*>(Failure::CouldNotResolveTypeDecl,
|
||||
Demangle::mangleNode(node));
|
||||
}
|
||||
|
||||
auto decl = dyn_cast<NominalTypeDecl>(DC);
|
||||
if (!decl) return nullptr;
|
||||
|
||||
return decl;
|
||||
}
|
||||
|
||||
ModuleDecl *RemoteASTTypeBuilder::findModule(const Demangle::NodePointer &node){
|
||||
assert(node->getKind() == Demangle::Node::Kind::Module);
|
||||
const auto &moduleName = node->getText();
|
||||
return Ctx.getModuleByName(moduleName);
|
||||
}
|
||||
|
||||
Demangle::NodePointer
|
||||
RemoteASTTypeBuilder::findModuleNode(const Demangle::NodePointer &node) {
|
||||
if (node->getKind() == Demangle::Node::Kind::Module)
|
||||
return node;
|
||||
|
||||
if (!node->hasChildren()) return nullptr;
|
||||
const auto &child = node->getFirstChild();
|
||||
if (child->getKind() != Demangle::Node::Kind::DeclContext)
|
||||
return nullptr;
|
||||
|
||||
return findModuleNode(child->getFirstChild());
|
||||
}
|
||||
|
||||
Optional<RemoteASTTypeBuilder::ForeignModuleKind>
|
||||
RemoteASTTypeBuilder::getForeignModuleKind(const Demangle::NodePointer &node) {
|
||||
if (node->getKind() == Demangle::Node::Kind::DeclContext)
|
||||
return getForeignModuleKind(node->getFirstChild());
|
||||
|
||||
if (node->getKind() != Demangle::Node::Kind::Module)
|
||||
return None;
|
||||
|
||||
return llvm::StringSwitch<Optional<ForeignModuleKind>>(node->getText())
|
||||
.Case(MANGLING_MODULE_OBJC, ForeignModuleKind::Imported)
|
||||
.Case(MANGLING_MODULE_CLANG_IMPORTER,
|
||||
ForeignModuleKind::SynthesizedByImporter)
|
||||
.Default(None);
|
||||
}
|
||||
|
||||
DeclContext *
|
||||
RemoteASTTypeBuilder::findDeclContext(const Demangle::NodePointer &node) {
|
||||
switch (node->getKind()) {
|
||||
case Demangle::Node::Kind::DeclContext:
|
||||
case Demangle::Node::Kind::Type:
|
||||
return findDeclContext(node->getFirstChild());
|
||||
|
||||
case Demangle::Node::Kind::Module:
|
||||
return findModule(node);
|
||||
|
||||
case Demangle::Node::Kind::Class:
|
||||
case Demangle::Node::Kind::Enum:
|
||||
case Demangle::Node::Kind::Protocol:
|
||||
case Demangle::Node::Kind::Structure:
|
||||
case Demangle::Node::Kind::TypeAlias: {
|
||||
const auto &declNameNode = node->getChild(1);
|
||||
|
||||
// Handle local declarations.
|
||||
if (declNameNode->getKind() == Demangle::Node::Kind::LocalDeclName) {
|
||||
// Find the AST node for the defining module.
|
||||
auto moduleNode = findModuleNode(node);
|
||||
if (!moduleNode) return nullptr;
|
||||
|
||||
auto module = findModule(moduleNode);
|
||||
if (!module) return nullptr;
|
||||
|
||||
// Look up the local type by its mangling.
|
||||
auto mangledName = Demangle::mangleNode(node);
|
||||
auto decl = module->lookupLocalType(mangledName);
|
||||
if (!decl) return nullptr;
|
||||
|
||||
return dyn_cast<DeclContext>(decl);
|
||||
}
|
||||
|
||||
StringRef name;
|
||||
StringRef relatedEntityKind;
|
||||
Identifier privateDiscriminator;
|
||||
if (declNameNode->getKind() == Demangle::Node::Kind::Identifier) {
|
||||
name = declNameNode->getText();
|
||||
|
||||
} else if (declNameNode->getKind() ==
|
||||
Demangle::Node::Kind::PrivateDeclName) {
|
||||
name = declNameNode->getChild(1)->getText();
|
||||
privateDiscriminator =
|
||||
Ctx.getIdentifier(declNameNode->getChild(0)->getText());
|
||||
|
||||
} else if (declNameNode->getKind() ==
|
||||
Demangle::Node::Kind::RelatedEntityDeclName) {
|
||||
name = declNameNode->getChild(0)->getText();
|
||||
relatedEntityKind = declNameNode->getText();
|
||||
|
||||
// Ignore any other decl-name productions for now.
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DeclContext *dc = findDeclContext(node->getChild(0));
|
||||
if (!dc) {
|
||||
// Do some backup logic for foreign type declarations.
|
||||
if (privateDiscriminator.empty()) {
|
||||
if (auto foreignModuleKind = getForeignModuleKind(node->getChild(0))) {
|
||||
return findForeignNominalTypeDecl(name, relatedEntityKind,
|
||||
foreignModuleKind.getValue(),
|
||||
node->getKind());
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return findNominalTypeDecl(dc, Ctx.getIdentifier(name),
|
||||
privateDiscriminator, node->getKind());
|
||||
}
|
||||
|
||||
case Demangle::Node::Kind::Global:
|
||||
return findDeclContext(node->getChild(0));
|
||||
|
||||
// Bail out on other kinds of contexts.
|
||||
// TODO: extensions
|
||||
// TODO: local contexts
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
NominalTypeDecl *
|
||||
RemoteASTTypeBuilder::findNominalTypeDecl(DeclContext *dc,
|
||||
Identifier name,
|
||||
Identifier privateDiscriminator,
|
||||
Demangle::Node::Kind kind) {
|
||||
auto module = dc->getParentModule();
|
||||
|
||||
SmallVector<ValueDecl *, 4> lookupResults;
|
||||
module->lookupMember(lookupResults, dc, name, privateDiscriminator);
|
||||
|
||||
NominalTypeDecl *result = nullptr;
|
||||
for (auto decl : lookupResults) {
|
||||
// Ignore results that are not the right kind of nominal type declaration.
|
||||
NominalTypeDecl *candidate = getAcceptableNominalTypeCandidate(decl, kind);
|
||||
if (!candidate)
|
||||
continue;
|
||||
|
||||
// Ignore results that aren't actually from the defining module.
|
||||
if (candidate->getParentModule() != module)
|
||||
continue;
|
||||
|
||||
// This is a viable result.
|
||||
|
||||
// If we already have a viable result, it's ambiguous, so give up.
|
||||
if (result) return nullptr;
|
||||
result = candidate;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static Optional<ClangTypeKind>
|
||||
getClangTypeKindForNodeKind(Demangle::Node::Kind kind) {
|
||||
switch (kind) {
|
||||
case Demangle::Node::Kind::Protocol:
|
||||
return ClangTypeKind::ObjCProtocol;
|
||||
case Demangle::Node::Kind::Class:
|
||||
return ClangTypeKind::ObjCClass;
|
||||
case Demangle::Node::Kind::TypeAlias:
|
||||
return ClangTypeKind::Typedef;
|
||||
case Demangle::Node::Kind::Structure:
|
||||
case Demangle::Node::Kind::Enum:
|
||||
return ClangTypeKind::Tag;
|
||||
default:
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
NominalTypeDecl *
|
||||
RemoteASTTypeBuilder::findForeignNominalTypeDecl(StringRef name,
|
||||
StringRef relatedEntityKind,
|
||||
ForeignModuleKind foreignKind,
|
||||
Demangle::Node::Kind kind) {
|
||||
// Check to see if we have an importer loaded.
|
||||
auto importer = static_cast<ClangImporter *>(Ctx.getClangModuleLoader());
|
||||
if (!importer) return nullptr;
|
||||
|
||||
// Find the unique declaration that has the right kind.
|
||||
struct Consumer : VisibleDeclConsumer {
|
||||
Demangle::Node::Kind ExpectedKind;
|
||||
NominalTypeDecl *Result = nullptr;
|
||||
bool HadError = false;
|
||||
|
||||
explicit Consumer(Demangle::Node::Kind kind) : ExpectedKind(kind) {}
|
||||
|
||||
void foundDecl(ValueDecl *decl, DeclVisibilityKind reason) override {
|
||||
if (HadError) return;
|
||||
if (decl == Result) return;
|
||||
if (!Result) {
|
||||
// A synthesized type from the Clang importer may resolve to a
|
||||
// compatibility alias.
|
||||
if (auto resultAlias = dyn_cast<TypeAliasDecl>(decl)) {
|
||||
if (resultAlias->isCompatibilityAlias()) {
|
||||
Result = resultAlias->getUnderlyingTypeLoc().getType()
|
||||
->getAnyNominal();
|
||||
}
|
||||
} else {
|
||||
Result = dyn_cast<NominalTypeDecl>(decl);
|
||||
}
|
||||
HadError |= !Result;
|
||||
} else {
|
||||
HadError = true;
|
||||
Result = nullptr;
|
||||
}
|
||||
}
|
||||
} consumer(kind);
|
||||
|
||||
switch (foreignKind) {
|
||||
case ForeignModuleKind::SynthesizedByImporter:
|
||||
if (!relatedEntityKind.empty()) {
|
||||
Optional<ClangTypeKind> lookupKind = getClangTypeKindForNodeKind(kind);
|
||||
if (!lookupKind)
|
||||
return nullptr;
|
||||
importer->lookupRelatedEntity(name, lookupKind.getValue(),
|
||||
relatedEntityKind, [&](TypeDecl *found) {
|
||||
consumer.foundDecl(found, DeclVisibilityKind::VisibleAtTopLevel);
|
||||
});
|
||||
break;
|
||||
}
|
||||
importer->lookupValue(Ctx.getIdentifier(name), consumer);
|
||||
if (consumer.Result)
|
||||
consumer.Result = getAcceptableNominalTypeCandidate(consumer.Result,kind);
|
||||
break;
|
||||
case ForeignModuleKind::Imported: {
|
||||
Optional<ClangTypeKind> lookupKind = getClangTypeKindForNodeKind(kind);
|
||||
if (!lookupKind)
|
||||
return nullptr;
|
||||
importer->lookupTypeDecl(name, lookupKind.getValue(),
|
||||
[&](TypeDecl *found) {
|
||||
consumer.foundDecl(found, DeclVisibilityKind::VisibleAtTopLevel);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return consumer.Result;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
/// The basic implementation of the RemoteASTContext interface.
|
||||
/// The template subclasses do target-specific logic.
|
||||
class RemoteASTContextImpl {
|
||||
std::unique_ptr<IRGenContext> IRGen;
|
||||
Optional<Failure> CurFailure;
|
||||
|
||||
public:
|
||||
RemoteASTContextImpl() = default;
|
||||
virtual ~RemoteASTContextImpl() = default;
|
||||
@@ -852,9 +132,24 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
template <class T, class DefaultFailureKindTy, class... DefaultFailureArgTys>
|
||||
Result<T> getFailureAsResult(DefaultFailureKindTy defaultFailureKind,
|
||||
DefaultFailureArgTys &&...defaultFailureArgs) {
|
||||
// If we already have a failure, use that.
|
||||
if (CurFailure) {
|
||||
Result<T> result = std::move(*CurFailure);
|
||||
CurFailure.reset();
|
||||
return result;
|
||||
}
|
||||
|
||||
// Otherwise, use the default failure.
|
||||
return Result<T>::emplaceFailure(defaultFailureKind,
|
||||
std::forward<DefaultFailureArgTys>(defaultFailureArgs)...);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
Result<T> getFailure() {
|
||||
return getBuilder().getFailureAsResult<T>(Failure::Unknown);
|
||||
return getFailureAsResult<T>(Failure::Unknown);
|
||||
}
|
||||
|
||||
template <class T, class KindTy, class... ArgTys>
|
||||
@@ -863,7 +158,7 @@ protected:
|
||||
}
|
||||
|
||||
private:
|
||||
virtual RemoteASTTypeBuilder &getBuilder() = 0;
|
||||
virtual ASTBuilder &getBuilder() = 0;
|
||||
virtual MemoryReader &getReader() = 0;
|
||||
virtual bool readWordOffset(RemoteAddress address, int64_t *offset) = 0;
|
||||
virtual std::unique_ptr<IRGenContext> createIRGenContext() = 0;
|
||||
@@ -1102,9 +397,9 @@ private:
|
||||
/// RemoteASTContext interface.
|
||||
template <class Runtime>
|
||||
class RemoteASTContextConcreteImpl final : public RemoteASTContextImpl {
|
||||
MetadataReader<Runtime, RemoteASTTypeBuilder> Reader;
|
||||
MetadataReader<Runtime, ASTBuilder> Reader;
|
||||
|
||||
RemoteASTTypeBuilder &getBuilder() override {
|
||||
ASTBuilder &getBuilder() override {
|
||||
return Reader.Builder;
|
||||
}
|
||||
|
||||
@@ -1153,7 +448,8 @@ public:
|
||||
}
|
||||
|
||||
std::unique_ptr<IRGenContext> createIRGenContext() override {
|
||||
return getBuilder().createIRGenContext();
|
||||
return IRGenContext::create(getBuilder().getASTContext(),
|
||||
getBuilder().getNotionalDC());
|
||||
}
|
||||
|
||||
Result<uint64_t>
|
||||
@@ -1343,14 +639,3 @@ RemoteASTContext::getDynamicTypeAndAddressForExistential(
|
||||
return asImpl(Impl)->getDynamicTypeAndAddressForExistential(address,
|
||||
staticType);
|
||||
}
|
||||
|
||||
Type swift::remoteAST::getTypeForMangling(ASTContext &ctx,
|
||||
StringRef mangling) {
|
||||
Demangle::Context Dem;
|
||||
auto node = Dem.demangleSymbolAsNode(mangling);
|
||||
if (!node)
|
||||
return Type();
|
||||
|
||||
RemoteASTTypeBuilder builder(ctx);
|
||||
return swift::Demangle::decodeMangledType(builder, node);
|
||||
}
|
||||
|
||||
@@ -43,6 +43,10 @@ namespace swift {
|
||||
class ValueDecl;
|
||||
enum class AccessorKind;
|
||||
|
||||
namespace syntax {
|
||||
class SourceFileSyntax;
|
||||
}
|
||||
|
||||
namespace ide {
|
||||
class CodeCompletionCache;
|
||||
class OnDiskCodeCompletionCache;
|
||||
@@ -111,7 +115,7 @@ public:
|
||||
static void reportDocumentStructure(swift::SourceFile &SrcFile,
|
||||
EditorConsumer &Consumer);
|
||||
|
||||
const llvm::Optional<swift::SourceFileSyntax> &getSyntaxTree() const;
|
||||
const llvm::Optional<swift::syntax::SourceFileSyntax> &getSyntaxTree() const;
|
||||
|
||||
std::string getFilePath() const;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user