Skip to content

Commit 526dcfb

Browse files
committed
[AST] Factor out AccessorDecl::createParsed
Move the logic for splicing together the accessor's parameter list out of the parser so that ASTGen will be able to use it too.
1 parent 28cfe4b commit 526dcfb

File tree

4 files changed

+124
-118
lines changed

4 files changed

+124
-118
lines changed

include/swift/AST/Decl.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7886,6 +7886,23 @@ class AccessorDecl final : public FuncDecl {
78867886
TypeLoc thrownType, ParameterList *parameterList, Type fnRetType,
78877887
DeclContext *parent, ClangNode clangNode = ClangNode());
78887888

7889+
/// Create a parsed accessor.
7890+
///
7891+
/// \param paramList A parameter list for e.g \c set(newValue), or \c nullptr
7892+
/// if the accessor doesn't have any user-specified arguments.
7893+
static AccessorDecl *createParsed(ASTContext &ctx, AccessorKind accessorKind,
7894+
AbstractStorageDecl *storage,
7895+
SourceLoc declLoc,
7896+
SourceLoc accessorKeywordLoc,
7897+
ParameterList *paramList,
7898+
SourceLoc asyncLoc, SourceLoc throwsLoc,
7899+
TypeRepr *thrownType, DeclContext *dc);
7900+
7901+
/// Retrieve the implicit parameter name for the given accessor kind (e.g
7902+
/// \c oldValue for `didSet`, `newValue` for `set`), or an empty string if
7903+
/// the kind does not have an implicit parameter name.
7904+
static StringRef implicitParameterNameFor(AccessorKind kind);
7905+
78897906
SourceLoc getAccessorKeywordLoc() const { return AccessorKeywordLoc; }
78907907

78917908
AbstractStorageDecl *getStorage() const {

include/swift/Parse/Parser.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1270,7 +1270,7 @@ class Parser {
12701270

12711271
bool parseAccessorAfterIntroducer(
12721272
SourceLoc Loc, AccessorKind Kind, ParsedAccessors &accessors,
1273-
bool &hasEffectfulGet, ParameterList *Indices, bool &parsingLimitedSyntax,
1273+
bool &hasEffectfulGet, bool &parsingLimitedSyntax,
12741274
DeclAttributes &Attributes, ParseDeclOptions Flags,
12751275
AbstractStorageDecl *storage, ParserStatus &Status);
12761276

lib/AST/Decl.cpp

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10077,6 +10077,92 @@ AccessorDecl *AccessorDecl::create(ASTContext &ctx, SourceLoc declLoc,
1007710077
return D;
1007810078
}
1007910079

10080+
AccessorDecl *AccessorDecl::createParsed(
10081+
ASTContext &ctx, AccessorKind accessorKind, AbstractStorageDecl *storage,
10082+
SourceLoc declLoc, SourceLoc accessorKeywordLoc, ParameterList *paramList,
10083+
SourceLoc asyncLoc, SourceLoc throwsLoc, TypeRepr *thrownType,
10084+
DeclContext *dc) {
10085+
auto *accessor = AccessorDecl::createImpl(
10086+
ctx, declLoc, accessorKeywordLoc, accessorKind, storage,
10087+
/*async*/ asyncLoc.isValid(), asyncLoc,
10088+
/*throws*/ throwsLoc.isValid(), throwsLoc, thrownType, dc,
10089+
/*clangNode*/ ClangNode());
10090+
10091+
// Set up the parameter list. This is the "newValue" name (for setters),
10092+
// followed by the index list (for subscripts). For non-subscript getters,
10093+
// this degenerates down to "()".
10094+
//
10095+
// We put the 'newValue' argument before the subscript index list as a
10096+
// micro-optimization for Objective-C thunk generation.
10097+
SmallVector<ParamDecl *, 2> newParams;
10098+
SourceLoc paramsStart, paramsEnd;
10099+
if (paramList) {
10100+
assert(paramList->size() == 1 &&
10101+
"Should only have a single parameter in the list");
10102+
newParams.push_back(paramList->get(0));
10103+
paramsStart = paramList->getStartLoc();
10104+
paramsEnd = paramList->getEndLoc();
10105+
} else {
10106+
// No parameter list, if we have an implicit parameter name, fill it in.
10107+
auto implicitName = AccessorDecl::implicitParameterNameFor(accessorKind);
10108+
if (!implicitName.empty()) {
10109+
auto *implicitParam = new (ctx)
10110+
ParamDecl(SourceLoc(), SourceLoc(), Identifier(), declLoc,
10111+
ctx.getIdentifier(implicitName), /*declContext*/ accessor);
10112+
implicitParam->setImplicit();
10113+
newParams.push_back(implicitParam);
10114+
}
10115+
}
10116+
10117+
// If this is a subscript accessor, we need to splice in the subscript
10118+
// parameters into the accessor's parameter list.
10119+
if (auto *SD = dyn_cast<SubscriptDecl>(storage)) {
10120+
auto *indices = SD->getIndices();
10121+
if (paramsStart.isInvalid()) {
10122+
paramsStart = indices->getStartLoc();
10123+
paramsEnd = indices->getEndLoc();
10124+
}
10125+
for (auto *subscriptParam : *indices) {
10126+
// Clone the parameter.
10127+
auto *param = new (ctx) ParamDecl(
10128+
subscriptParam->getSpecifierLoc(),
10129+
subscriptParam->getArgumentNameLoc(),
10130+
subscriptParam->getArgumentName(), subscriptParam->getNameLoc(),
10131+
subscriptParam->getName(), /*declContext*/ accessor);
10132+
param->setAutoClosure(subscriptParam->isAutoClosure());
10133+
10134+
// The cloned parameter is implicit.
10135+
param->setImplicit();
10136+
10137+
// It has no default arguments; these will be always be taken
10138+
// from the subscript declaration.
10139+
param->setDefaultArgumentKind(DefaultArgumentKind::None);
10140+
10141+
newParams.push_back(param);
10142+
}
10143+
}
10144+
accessor->setParameters(
10145+
ParameterList::create(ctx, paramsStart, newParams, paramsEnd));
10146+
return accessor;
10147+
}
10148+
10149+
StringRef AccessorDecl::implicitParameterNameFor(AccessorKind kind) {
10150+
switch (kind) {
10151+
case AccessorKind::Set:
10152+
case AccessorKind::WillSet:
10153+
case AccessorKind::Init:
10154+
return "newValue";
10155+
case AccessorKind::DidSet:
10156+
return "oldValue";
10157+
case AccessorKind::Get:
10158+
case AccessorKind::Read:
10159+
case AccessorKind::Modify:
10160+
case AccessorKind::Address:
10161+
case AccessorKind::MutableAddress:
10162+
return StringRef();
10163+
}
10164+
}
10165+
1008010166
bool AccessorDecl::isAssumedNonMutating() const {
1008110167
switch (getAccessorKind()) {
1008210168
case AccessorKind::Get:

lib/Parse/ParseDecl.cpp

Lines changed: 20 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -7347,100 +7347,6 @@ ParserResult<TypeDecl> Parser::parseDeclAssociatedType(Parser::ParseDeclOptions
73477347
return makeParserResult(Status, assocType);
73487348
}
73497349

7350-
/// This function creates an accessor function (with no body) for a computed
7351-
/// property or subscript.
7352-
static AccessorDecl *
7353-
createAccessorFunc(SourceLoc DeclLoc, ParameterList *param,
7354-
ParameterList *Indices, Parser::ParseDeclOptions Flags,
7355-
AccessorKind Kind, AbstractStorageDecl *storage, Parser *P,
7356-
SourceLoc AccessorKeywordLoc, SourceLoc asyncLoc,
7357-
SourceLoc throwsLoc, TypeRepr *thrownTy) {
7358-
// First task, set up the value argument list. This is the "newValue" name
7359-
// (for setters) followed by the index list (for subscripts). For
7360-
// non-subscript getters, this degenerates down to "()".
7361-
//
7362-
// We put the 'newValue' argument before the subscript index list as a
7363-
// micro-optimization for Objective-C thunk generation.
7364-
ParameterList *ValueArg;
7365-
{
7366-
SmallVector<ParamDecl*, 2> ValueArgElements;
7367-
SourceLoc StartLoc, EndLoc;
7368-
if (param) {
7369-
assert(param->size() == 1 &&
7370-
"Should only have a single parameter in the list");
7371-
ValueArgElements.push_back(param->get(0));
7372-
StartLoc = param->getStartLoc();
7373-
EndLoc = param->getEndLoc();
7374-
}
7375-
7376-
if (Indices) {
7377-
// Create parameter declarations corresponding to each of the
7378-
// parameter declarations from the subscript declaration.
7379-
for (ParamDecl *storageParam : *Indices) {
7380-
// Clone the parameter. Do not clone the parameter type;
7381-
// this will be filled in by the type-checker.
7382-
auto accessorParam =
7383-
new (P->Context) ParamDecl(storageParam->getSpecifierLoc(),
7384-
storageParam->getArgumentNameLoc(),
7385-
storageParam->getArgumentName(),
7386-
storageParam->getNameLoc(),
7387-
storageParam->getName(),
7388-
P->CurDeclContext);
7389-
accessorParam->setAutoClosure(storageParam->isAutoClosure());
7390-
7391-
// The cloned parameter is implicit.
7392-
accessorParam->setImplicit();
7393-
7394-
// It has no default arguments; these will be always be taken
7395-
// from the subscript declaration.
7396-
accessorParam->setDefaultArgumentKind(DefaultArgumentKind::None);
7397-
7398-
ValueArgElements.push_back(accessorParam);
7399-
}
7400-
7401-
if (StartLoc.isInvalid()) {
7402-
StartLoc = Indices->getStartLoc();
7403-
EndLoc = Indices->getEndLoc();
7404-
}
7405-
}
7406-
7407-
ValueArg = ParameterList::create(P->Context, StartLoc, ValueArgElements,
7408-
EndLoc);
7409-
}
7410-
7411-
// Start the function.
7412-
auto *D = AccessorDecl::create(P->Context,
7413-
/*FIXME FuncLoc=*/DeclLoc, AccessorKeywordLoc,
7414-
Kind, storage, asyncLoc.isValid(), asyncLoc,
7415-
throwsLoc.isValid(), throwsLoc, thrownTy,
7416-
ValueArg, Type(), P->CurDeclContext);
7417-
7418-
return D;
7419-
}
7420-
7421-
static ParamDecl *createSetterAccessorArgument(SourceLoc nameLoc,
7422-
Identifier name,
7423-
AccessorKind accessorKind,
7424-
Parser &P) {
7425-
// Add the parameter. If no name was specified, the name defaults to
7426-
// 'value'.
7427-
bool isNameImplicit = name.empty();
7428-
if (isNameImplicit) {
7429-
const char *implName =
7430-
accessorKind == AccessorKind::DidSet ? "oldValue" : "newValue";
7431-
name = P.Context.getIdentifier(implName);
7432-
}
7433-
7434-
auto result = new (P.Context)
7435-
ParamDecl(SourceLoc(), SourceLoc(),
7436-
Identifier(), nameLoc, name, P.CurDeclContext);
7437-
7438-
if (isNameImplicit)
7439-
result->setImplicit();
7440-
7441-
return result;
7442-
}
7443-
74447350
/// Parse a "(value)" specifier for "set" or "willSet" if present. Create a
74457351
/// parameter list to represent the spelled argument or return null if none is
74467352
/// present.
@@ -7482,9 +7388,12 @@ static ParameterList *parseOptionalAccessorArgument(SourceLoc SpecifierLoc,
74827388
P.parseMatchingToken(tok::r_paren, EndLoc, DiagID, StartLoc);
74837389
}
74847390
}
7391+
if (Name.empty())
7392+
return nullptr;
7393+
7394+
auto *param = new (P.Context) ParamDecl(
7395+
SourceLoc(), SourceLoc(), Identifier(), NameLoc, Name, P.CurDeclContext);
74857396

7486-
if (Name.empty()) NameLoc = SpecifierLoc;
7487-
auto param = createSetterAccessorArgument(NameLoc, Name, Kind, P);
74887397
return ParameterList::create(P.Context, StartLoc, param, EndLoc);
74897398
}
74907399

@@ -7740,10 +7649,10 @@ ParserStatus Parser::parseGetEffectSpecifier(ParsedAccessors &accessors,
77407649

77417650
bool Parser::parseAccessorAfterIntroducer(
77427651
SourceLoc Loc, AccessorKind Kind, ParsedAccessors &accessors,
7743-
bool &hasEffectfulGet, ParameterList *Indices, bool &parsingLimitedSyntax,
7652+
bool &hasEffectfulGet, bool &parsingLimitedSyntax,
77447653
DeclAttributes &Attributes, ParseDeclOptions Flags,
77457654
AbstractStorageDecl *storage, ParserStatus &Status) {
7746-
auto *ValueNamePattern = parseOptionalAccessorArgument(Loc, *this, Kind);
7655+
auto *param = parseOptionalAccessorArgument(Loc, *this, Kind);
77477656

77487657
// Next, parse effects specifiers. While it's only valid to have them
77497658
// on 'get' accessors, we also emit diagnostics if they show up on others.
@@ -7754,15 +7663,14 @@ bool Parser::parseAccessorAfterIntroducer(
77547663
hasEffectfulGet, Kind, Loc);
77557664

77567665
// Set up a function declaration.
7757-
auto accessor =
7758-
createAccessorFunc(Loc, ValueNamePattern, Indices, Flags, Kind, storage,
7759-
this, Loc, asyncLoc, throwsLoc, thrownTy);
7666+
auto *accessor = AccessorDecl::createParsed(
7667+
Context, Kind, storage, /*declLoc*/ Loc, /*accessorKeywordLoc*/ Loc,
7668+
param, asyncLoc, throwsLoc, thrownTy, CurDeclContext);
77607669
accessor->getAttrs() = Attributes;
77617670

77627671
// Collect this accessor and detect conflicts.
77637672
if (auto existingAccessor = accessors.add(accessor)) {
7764-
diagnoseRedundantAccessors(*this, Loc, Kind,
7765-
/*subscript*/Indices != nullptr,
7673+
diagnoseRedundantAccessors(*this, Loc, Kind, isa<SubscriptDecl>(storage),
77667674
existingAccessor);
77677675
}
77687676

@@ -7841,12 +7749,11 @@ ParserStatus Parser::parseGetSet(ParseDeclOptions Flags, ParameterList *Indices,
78417749
auto parseImplicitGetter = [&]() {
78427750
assert(Tok.is(tok::l_brace));
78437751
accessors.LBLoc = Tok.getLoc();
7844-
auto getter =
7845-
createAccessorFunc(Tok.getLoc(), /*ValueNamePattern*/ nullptr, Indices,
7846-
Flags, AccessorKind::Get, storage, this,
7847-
/*AccessorKeywordLoc*/ SourceLoc(),
7848-
/*asyncLoc*/ SourceLoc(), /*throwsLoc*/ SourceLoc(),
7849-
/*thrownTy*/ nullptr);
7752+
auto *getter = AccessorDecl::createParsed(
7753+
Context, AccessorKind::Get, storage, /*declLoc*/ Tok.getLoc(),
7754+
/*accessorKeywordLoc*/ SourceLoc(), /*paramList*/ nullptr,
7755+
/*asyncLoc*/ SourceLoc(), /*throwsLoc*/ SourceLoc(),
7756+
/*thrownTy*/ nullptr, CurDeclContext);
78507757
accessors.add(getter);
78517758
parseAbstractFunctionBody(getter);
78527759
accessors.RBLoc = getter->getEndLoc();
@@ -7932,8 +7839,8 @@ ParserStatus Parser::parseGetSet(ParseDeclOptions Flags, ParameterList *Indices,
79327839
}
79337840

79347841
if (parseAccessorAfterIntroducer(Loc, Kind, accessors, hasEffectfulGet,
7935-
Indices, parsingLimitedSyntax, Attributes,
7936-
Flags, storage, Status))
7842+
parsingLimitedSyntax, Attributes, Flags,
7843+
storage, Status))
79377844
break;
79387845
}
79397846
backtrack->cancelBacktrack();
@@ -7956,10 +7863,6 @@ void Parser::parseTopLevelAccessors(
79567863
if (Tok.is(tok::NUM_TOKENS))
79577864
consumeTokenWithoutFeedingReceiver();
79587865

7959-
ParameterList *indices = nullptr;
7960-
if (auto subscript = dyn_cast<SubscriptDecl>(storage))
7961-
indices = subscript->getIndices();
7962-
79637866
bool hadLBrace = consumeIf(tok::l_brace);
79647867

79657868
// Prepopulate the field for any accessors that were already parsed parsed accessors
@@ -7982,8 +7885,8 @@ void Parser::parseTopLevelAccessors(
79827885
break;
79837886

79847887
(void)parseAccessorAfterIntroducer(loc, kind, accessors, hasEffectfulGet,
7985-
indices, parsingLimitedSyntax,
7986-
attributes, PD_Default, storage, status);
7888+
parsingLimitedSyntax, attributes,
7889+
PD_Default, storage, status);
79877890
}
79887891

79897892
if (hadLBrace && Tok.is(tok::r_brace)) {

0 commit comments

Comments
 (0)