AST: Add a GenericParamList::clone() method

This will be immediately needed for generic subscripts, and also
for fixing the remaining cases where initializer inheritance
doesn't work.
This commit is contained in:
Slava Pestov
2017-02-22 15:26:56 -08:00
parent ecda075792
commit fdb0a18647
4 changed files with 91 additions and 2 deletions

View File

@@ -1332,6 +1332,11 @@ public:
return depth;
}
/// Create a copy of the generic parameter list and all of its generic
/// parameter declarations. The copied generic parameters are re-parented
/// to the given DeclContext.
GenericParamList *clone(DeclContext *dc) const;
void print(raw_ostream &OS);
void dump();
};
@@ -2501,6 +2506,8 @@ class GenericTypeParamDecl : public AbstractTypeParamDecl {
unsigned Index : 16;
public:
static const unsigned InvalidDepth = 0xFFFF;
/// Construct a new generic type parameter.
///
/// \param dc The DeclContext in which the generic type parameter's owner

View File

@@ -506,6 +506,66 @@ GenericParamList::create(const ASTContext &Context,
RAngleLoc);
}
GenericParamList *
GenericParamList::clone(DeclContext *dc) const {
auto &ctx = dc->getASTContext();
SmallVector<GenericTypeParamDecl *, 2> params;
for (auto param : getParams()) {
auto *newParam = new (ctx) GenericTypeParamDecl(
dc, param->getName(), param->getNameLoc(),
GenericTypeParamDecl::InvalidDepth,
param->getIndex());
params.push_back(newParam);
SmallVector<TypeLoc, 2> inherited;
for (auto loc : param->getInherited())
inherited.push_back(loc.clone(ctx));
newParam->setInherited(ctx.AllocateCopy(inherited));
}
SmallVector<RequirementRepr, 2> requirements;
for (auto reqt : getRequirements()) {
switch (reqt.getKind()) {
case RequirementReprKind::TypeConstraint: {
auto first = reqt.getSubjectLoc();
auto second = reqt.getConstraintLoc();
reqt = RequirementRepr::getTypeConstraint(
first.clone(ctx),
reqt.getColonLoc(),
second.clone(ctx));
break;
}
case RequirementReprKind::SameType: {
auto first = reqt.getFirstTypeLoc();
auto second = reqt.getSecondTypeLoc();
reqt = RequirementRepr::getSameType(
first.clone(ctx),
reqt.getEqualLoc(),
second.clone(ctx));
break;
}
case RequirementReprKind::LayoutConstraint: {
auto first = reqt.getSubjectLoc();
auto layout = reqt.getLayoutConstraintLoc();
reqt = RequirementRepr::getLayoutConstraint(
first.clone(ctx),
reqt.getColonLoc(),
layout);
break;
}
}
requirements.push_back(reqt);
}
return GenericParamList::create(ctx,
getLAngleLoc(),
params,
getWhereLoc(),
requirements,
getRAngleLoc());
}
void GenericParamList::addTrailingWhereClause(
ASTContext &ctx,
SourceLoc trailingWhereLoc,
@@ -3812,7 +3872,7 @@ ParamDecl::ParamDecl(ParamDecl *PD)
DefaultValueAndIsVariadic(nullptr, PD->DefaultValueAndIsVariadic.getInt()),
IsTypeLocImplicit(PD->IsTypeLocImplicit),
defaultArgumentKind(PD->defaultArgumentKind) {
typeLoc = PD->getTypeLoc();
typeLoc = PD->getTypeLoc().clone(PD->getASTContext());
if (PD->hasInterfaceType())
setInterfaceType(PD->getInterfaceType());
}

View File

@@ -1181,7 +1181,8 @@ CanType TypeBase::getCanonicalType() {
case TypeKind::GenericTypeParam: {
GenericTypeParamType *gp = cast<GenericTypeParamType>(this);
auto gpDecl = gp->getDecl();
assert(gpDecl->getDepth() != 0xFFFF && "parameter hasn't been validated");
assert(gpDecl->getDepth() != GenericTypeParamDecl::InvalidDepth &&
"parameter hasn't been validated");
Result = GenericTypeParamType::get(gpDecl->getDepth(), gpDecl->getIndex(),
gpDecl->getASTContext());
break;

View File

@@ -4219,6 +4219,27 @@ void Parser::ParsedAccessors::record(Parser &P, AbstractStorageDecl *storage,
}
}
#if 0
// Subscript accessors are not logically nested inside the subscript,
// once all the accessors are in place, we must clone the subscript's
// generic parameter list for each accessor.
if (auto *subscript = dyn_cast<SubscriptDecl>(storage)) {
if (auto *genericParams = subscript->getGenericParams()) {
auto prepareSubscriptAccessor = [&](FuncDecl *func) {
if (func)
func->setGenericParams(genericParams->clone(func));
};
prepareSubscriptAccessor(Get);
prepareSubscriptAccessor(Set);
prepareSubscriptAccessor(Addressor);
prepareSubscriptAccessor(MutableAddressor);
prepareSubscriptAccessor(WillSet);
prepareSubscriptAccessor(DidSet);
}
}
#endif
if (Set || Get) {
if (attrs.hasAttribute<SILStoredAttr>())
// Turn this into a stored property with trivial accessors.