Skip to content

Commit fa6924a

Browse files
committed
ParamDecl: Defend against default argument kind overwrites
1 parent 516efdf commit fa6924a

File tree

3 files changed

+40
-22
lines changed

3 files changed

+40
-22
lines changed

include/swift/AST/Decl.h

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6670,8 +6670,15 @@ class ParamDecl : public VarDecl {
66706670
Identifier argumentName, SourceLoc parameterNameLoc,
66716671
Identifier parameterName, DeclContext *dc);
66726672

6673-
/// Create a new ParamDecl identical to the first except without the interface type.
6674-
static ParamDecl *cloneWithoutType(const ASTContext &Ctx, ParamDecl *PD);
6673+
/// Create a new `ParamDecl` identical to the given one except without the
6674+
/// interface type.
6675+
///
6676+
/// \param PD The parameter to clone.
6677+
/// \param defaultArgKind The default argument kind for the cloned parameter.
6678+
/// If \c std::nullopt, use the default argument kind of \p PD.
6679+
static ParamDecl *cloneWithoutType(
6680+
const ASTContext &Ctx, ParamDecl *PD,
6681+
std::optional<DefaultArgumentKind> defaultArgKind = std::nullopt);
66756682

66766683
/// Create a an identical copy of this ParamDecl.
66776684
static ParamDecl *clone(const ASTContext &Ctx, ParamDecl *PD);
@@ -6736,9 +6743,8 @@ class ParamDecl : public VarDecl {
67366743
bool isDefaultArgument() const {
67376744
return getDefaultArgumentKind() != DefaultArgumentKind::None;
67386745
}
6739-
void setDefaultArgumentKind(DefaultArgumentKind K) {
6740-
Bits.ParamDecl.defaultArgumentKind = static_cast<unsigned>(K);
6741-
}
6746+
6747+
void setDefaultArgumentKind(DefaultArgumentKind K);
67426748

67436749
void setDefaultArgumentKind(ArgumentAttrs K) {
67446750
setDefaultArgumentKind(K.argumentKind);

lib/AST/Decl.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8253,13 +8253,19 @@ ParamDecl::ParamDecl(SourceLoc specifierLoc, SourceLoc argumentNameLoc,
82538253
static_cast<unsigned>(DefaultArgumentKind::None);
82548254
}
82558255

8256-
ParamDecl *ParamDecl::cloneWithoutType(const ASTContext &Ctx, ParamDecl *PD) {
8256+
ParamDecl *
8257+
ParamDecl::cloneWithoutType(const ASTContext &Ctx, ParamDecl *PD,
8258+
std::optional<DefaultArgumentKind> defaultArgKind) {
82578259
auto *Clone = new (Ctx) ParamDecl(
82588260
SourceLoc(), SourceLoc(), PD->getArgumentName(),
82598261
SourceLoc(), PD->getParameterName(), PD->getDeclContext());
82608262
Clone->setOptionsAndPointers(nullptr, nullptr, PD->getOptions());
8261-
Clone->Bits.ParamDecl.defaultArgumentKind =
8262-
PD->Bits.ParamDecl.defaultArgumentKind;
8263+
8264+
if (defaultArgKind) {
8265+
Clone->setDefaultArgumentKind(*defaultArgKind);
8266+
} else {
8267+
Clone->setDefaultArgumentKind(PD->getDefaultArgumentKind());
8268+
}
82638269

82648270
Clone->setSpecifier(PD->getSpecifier());
82658271
Clone->setImplicitlyUnwrappedOptional(PD->isImplicitlyUnwrappedOptional());
@@ -8367,6 +8373,12 @@ ParamDecl *ParamDecl::createParsed(ASTContext &Context, SourceLoc specifierLoc,
83678373
return decl;
83688374
}
83698375

8376+
void ParamDecl::setDefaultArgumentKind(DefaultArgumentKind K) {
8377+
assert(getDefaultArgumentKind() == DefaultArgumentKind::None &&
8378+
"Overwrite of default argument kind");
8379+
Bits.ParamDecl.defaultArgumentKind = static_cast<unsigned>(K);
8380+
}
8381+
83708382
/// Retrieve the type of 'self' for the given context.
83718383
Type DeclContext::getSelfTypeInContext() const {
83728384
return mapTypeIntoContext(getSelfInterfaceType());

lib/AST/Parameter.cpp

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -64,32 +64,32 @@ ParameterList *ParameterList::clone(const ASTContext &C,
6464
for (auto &decl : params) {
6565
auto defaultArgKind = decl->getDefaultArgumentKind();
6666

67-
decl = ParamDecl::cloneWithoutType(C, decl);
68-
if (options & Implicit)
69-
decl->setImplicit();
70-
71-
// If the argument isn't named, give the parameter a name so that
72-
// silgen will produce a value for it.
73-
if (decl->getName().empty() && (options & NamedArguments)) {
74-
llvm::SmallString<16> s;
75-
{ llvm::raw_svector_ostream(s) << "__argument" << ++i; }
76-
decl->setName(C.getIdentifier(s));
77-
}
78-
7967
// If we're inheriting a default argument, mark it as such.
8068
// FIXME: Figure out how to clone default arguments as well.
8169
if (options & Inherited) {
8270
switch (defaultArgKind) {
8371
case DefaultArgumentKind::Normal:
8472
case DefaultArgumentKind::StoredProperty:
85-
decl->setDefaultArgumentKind(DefaultArgumentKind::Inherited);
73+
defaultArgKind = DefaultArgumentKind::Inherited;
8674
break;
8775

8876
default:
8977
break;
9078
}
9179
} else {
92-
decl->setDefaultArgumentKind(DefaultArgumentKind::None);
80+
defaultArgKind = DefaultArgumentKind::None;
81+
}
82+
83+
decl = ParamDecl::cloneWithoutType(C, decl, defaultArgKind);
84+
if (options & Implicit)
85+
decl->setImplicit();
86+
87+
// If the argument isn't named, give the parameter a name so that
88+
// silgen will produce a value for it.
89+
if (decl->getName().empty() && (options & NamedArguments)) {
90+
llvm::SmallString<16> s;
91+
{ llvm::raw_svector_ostream(s) << "__argument" << ++i; }
92+
decl->setName(C.getIdentifier(s));
9393
}
9494
}
9595

0 commit comments

Comments
 (0)