Skip to content

Commit cf541c1

Browse files
committed
[NFC] Hoist getAttributeInsertionLoc() up to Decl
This functionality was previously reserved for ValueDecls. Move it all the way up to Decl; in the process, make it correctly handle EnumElementDecls and EnumCaseDecls. This change also allows us to generalize `swift::fixDeclarationObjCName()` to work on extensions, though we do not use that capability in this commit.
1 parent 0fbea28 commit cf541c1

File tree

5 files changed

+85
-38
lines changed

5 files changed

+85
-38
lines changed

include/swift/AST/Decl.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,6 +1025,10 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
10251025
/// Returns the source range of the declaration including its attributes.
10261026
SourceRange getSourceRangeIncludingAttrs() const;
10271027

1028+
/// Retrieve the location at which we should insert a new attribute or
1029+
/// modifier.
1030+
SourceLoc getAttributeInsertionLoc(bool forModifier) const;
1031+
10281032
using ImportAccessLevel = std::optional<AttributedImport<ImportedModule>>;
10291033

10301034
/// Returns the import that may restrict the access to this decl
@@ -3172,10 +3176,6 @@ class ValueDecl : public Decl {
31723176
/// can't be "static" or are in a context where "static" doesn't make sense.
31733177
bool isStatic() const;
31743178

3175-
/// Retrieve the location at which we should insert a new attribute or
3176-
/// modifier.
3177-
SourceLoc getAttributeInsertionLoc(bool forModifier) const;
3178-
31793179
static bool classof(const Decl *D) {
31803180
return D->getKind() >= DeclKind::First_ValueDecl &&
31813181
D->getKind() <= DeclKind::Last_ValueDecl;

lib/AST/Decl.cpp

Lines changed: 74 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4021,25 +4021,86 @@ bool ValueDecl::canInferObjCFromRequirement(ValueDecl *requirement) {
40214021
return false;
40224022
}
40234023

4024-
SourceLoc ValueDecl::getAttributeInsertionLoc(bool forModifier) const {
4025-
if (isImplicit())
4024+
SourceLoc Decl::getAttributeInsertionLoc(bool forModifier) const {
4025+
// Some decls have a parent/child split where the introducer keyword is on the
4026+
// parent, but the attributes are on the children. If this is a child in such
4027+
// a pair, `introDecl` will be changed to point to the parent. (The parent
4028+
// decl should delegate to one of its children.)
4029+
const Decl *introDecl = this;
4030+
4031+
switch (getKind()) {
4032+
case DeclKind::Module:
4033+
case DeclKind::TopLevelCode:
4034+
case DeclKind::IfConfig:
4035+
case DeclKind::PoundDiagnostic:
4036+
case DeclKind::Missing:
4037+
case DeclKind::MissingMember:
4038+
case DeclKind::MacroExpansion:
4039+
case DeclKind::BuiltinTuple:
4040+
// These don't take attributes.
40264041
return SourceLoc();
40274042

4028-
if (auto var = dyn_cast<VarDecl>(this)) {
4029-
// [attrs] var ...
4030-
// The attributes are part of the VarDecl, but the 'var' is part of the PBD.
4031-
SourceLoc resultLoc = var->getAttrs().getStartLoc(forModifier);
4032-
if (resultLoc.isValid()) {
4033-
return resultLoc;
4034-
} else if (auto pbd = var->getParentPatternBinding()) {
4035-
return pbd->getStartLoc();
4036-
} else {
4037-
return var->getStartLoc();
4043+
case DeclKind::EnumCase:
4044+
// An ECD's attributes are attached to its elements.
4045+
if (auto elem = cast<EnumCaseDecl>(this)->getFirstElement())
4046+
return elem->getAttributeInsertionLoc(forModifier);
4047+
break;
4048+
4049+
case DeclKind::EnumElement:
4050+
// An EED's introducer keyword is on its parent case.
4051+
if (auto parent = cast<EnumElementDecl>(this)->getParentCase())
4052+
introDecl = parent;
4053+
break;
4054+
4055+
case DeclKind::PatternBinding: {
4056+
// A PBD's attributes are attached to the vars in its patterns.
4057+
auto pbd = cast<PatternBindingDecl>(this);
4058+
4059+
for (unsigned i = 0; i < pbd->getNumPatternEntries(); i++) {
4060+
if (auto var = pbd->getAnchoringVarDecl(i)) {
4061+
return var->getAttributeInsertionLoc(forModifier);
4062+
}
40384063
}
4064+
4065+
break;
4066+
}
4067+
4068+
case DeclKind::Var:
4069+
case DeclKind::Param:
4070+
// A VarDecl's introducer keyword, if it has one, is on its pattern binding.
4071+
if (auto pbd = cast<VarDecl>(this)->getParentPatternBinding())
4072+
introDecl = pbd;
4073+
break;
4074+
4075+
case DeclKind::Enum:
4076+
case DeclKind::Struct:
4077+
case DeclKind::Class:
4078+
case DeclKind::Protocol:
4079+
case DeclKind::OpaqueType:
4080+
case DeclKind::TypeAlias:
4081+
case DeclKind::GenericTypeParam:
4082+
case DeclKind::AssociatedType:
4083+
case DeclKind::Subscript:
4084+
case DeclKind::Constructor:
4085+
case DeclKind::Destructor:
4086+
case DeclKind::Func:
4087+
case DeclKind::Accessor:
4088+
case DeclKind::Macro:
4089+
case DeclKind::Extension:
4090+
case DeclKind::Import:
4091+
case DeclKind::PrecedenceGroup:
4092+
case DeclKind::InfixOperator:
4093+
case DeclKind::PrefixOperator:
4094+
case DeclKind::PostfixOperator:
4095+
// Both the introducer keyword and the attributes are on `this`.
4096+
break;
40394097
}
40404098

4099+
if (isImplicit())
4100+
return SourceLoc();
4101+
40414102
SourceLoc resultLoc = getAttrs().getStartLoc(forModifier);
4042-
return resultLoc.isValid() ? resultLoc : getStartLoc();
4103+
return resultLoc.isValid() ? resultLoc : introDecl->getStartLoc();
40434104
}
40444105

40454106
/// Returns true if \p VD needs to be treated as publicly-accessible

lib/Sema/TypeCheckAvailability.cpp

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1841,26 +1841,15 @@ static void fixAvailabilityForDecl(SourceRange ReferenceRange, const Decl *D,
18411841
// parsing.
18421842
const Decl *ConcDecl = concreteSyntaxDeclForAvailableAttribute(D);
18431843

1844-
DescriptiveDeclKind KindForDiagnostic = ConcDecl->getDescriptiveKind();
1845-
SourceLoc InsertLoc;
1846-
18471844
// To avoid exposing the pattern binding declaration to the user, get the
1848-
// descriptive kind from one of the VarDecls. We get the Fix-It location
1849-
// from the PatternBindingDecl unless the VarDecl has attributes,
1850-
// in which case we get the start location of the VarDecl attributes.
1851-
DeclAttributes AttrsForLoc;
1845+
// descriptive kind from one of the VarDecls.
1846+
DescriptiveDeclKind KindForDiagnostic = ConcDecl->getDescriptiveKind();
18521847
if (KindForDiagnostic == DescriptiveDeclKind::PatternBinding) {
18531848
KindForDiagnostic = D->getDescriptiveKind();
1854-
AttrsForLoc = D->getAttrs();
1855-
} else {
1856-
InsertLoc = ConcDecl->getAttrs().getStartLoc(/*forModifiers=*/false);
1857-
}
1858-
1859-
InsertLoc = D->getAttrs().getStartLoc(/*forModifiers=*/false);
1860-
if (InsertLoc.isInvalid()) {
1861-
InsertLoc = ConcDecl->getStartLoc();
18621849
}
18631850

1851+
SourceLoc InsertLoc =
1852+
ConcDecl->getAttributeInsertionLoc(/*forModifier=*/false);
18641853
if (InsertLoc.isInvalid())
18651854
return;
18661855

@@ -4489,10 +4478,7 @@ void swift::checkExplicitAvailability(Decl *decl) {
44894478

44904479
auto suggestPlatform = ctx.LangOpts.RequireExplicitAvailabilityTarget;
44914480
if (!suggestPlatform.empty()) {
4492-
auto InsertLoc = decl->getAttrs().getStartLoc(/*forModifiers=*/false);
4493-
if (InsertLoc.isInvalid())
4494-
InsertLoc = decl->getStartLoc();
4495-
4481+
auto InsertLoc = decl->getAttributeInsertionLoc(/*forModifiers=*/false);
44964482
if (InsertLoc.isInvalid())
44974483
return;
44984484

lib/Sema/TypeCheckDeclObjC.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2128,7 +2128,7 @@ bool swift::fixDeclarationName(InFlightDiagnostic &diag, const ValueDecl *decl,
21282128
}
21292129

21302130
bool swift::fixDeclarationObjCName(InFlightDiagnostic &diag,
2131-
const ValueDecl *decl,
2131+
const Decl *decl,
21322132
std::optional<ObjCSelector> nameOpt,
21332133
std::optional<ObjCSelector> targetNameOpt,
21342134
bool ignoreImpliedName) {

lib/Sema/TypeCheckObjC.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ bool fixDeclarationName(InFlightDiagnostic &diag, const ValueDecl *decl,
212212
///
213213
/// For properties, the selector should be a zero-parameter selector of the
214214
/// given property's name.
215-
bool fixDeclarationObjCName(InFlightDiagnostic &diag, const ValueDecl *decl,
215+
bool fixDeclarationObjCName(InFlightDiagnostic &diag, const Decl *decl,
216216
std::optional<ObjCSelector> nameOpt,
217217
std::optional<ObjCSelector> targetNameOpt,
218218
bool ignoreImpliedName = false);

0 commit comments

Comments
 (0)