Skip to content

Commit b45d278

Browse files
committed
AST: Fix AvailabilityContext::forDeclSignature().
For declarations that aren't in source files there isn't an `AvailabilityScope` tree to consult to find their `AvailabilityContext`. The fallback mechanism used by `AvailabilityContext::forLocation()` walks up the `DeclContext` hierarchy to build up the context for implicit code but this isn't entirely correct since it skips over certain kinds of decls (like property declarations). Instead, we need to walk up the parent decl hierarchy that is used for availability inference to ensure that no decls with relevant availability attributes are skipped.
1 parent aa199aa commit b45d278

File tree

1 file changed

+38
-25
lines changed

1 file changed

+38
-25
lines changed

lib/AST/AvailabilityContext.cpp

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "swift/AST/AvailabilityScope.h"
1919
#include "swift/AST/Decl.h"
2020
#include "swift/AST/Module.h"
21+
#include "swift/AST/SourceFile.h"
2122
#include "swift/Basic/Assertions.h"
2223

2324
using namespace swift;
@@ -155,6 +156,30 @@ AvailabilityContext::forDeploymentTarget(const ASTContext &ctx) {
155156
AvailabilityRange::forDeploymentTarget(ctx), ctx);
156157
}
157158

159+
static AvailabilityContext
160+
contextForLocationInSourceFile(SourceLoc loc, SourceFile *sf,
161+
AvailabilityContext baseAvailability,
162+
const AvailabilityScope **refinedScope) {
163+
if (!sf || loc.isInvalid())
164+
return baseAvailability;
165+
166+
auto &ctx = sf->getASTContext();
167+
auto *rootScope = AvailabilityScope::getOrBuildForSourceFile(*sf);
168+
if (!rootScope)
169+
return baseAvailability;
170+
171+
auto *scope = rootScope->findMostRefinedSubContext(loc, ctx);
172+
if (!scope)
173+
return baseAvailability;
174+
175+
if (refinedScope)
176+
*refinedScope = scope;
177+
178+
auto availability = scope->getAvailabilityContext();
179+
availability.constrainWithContext(baseAvailability, ctx);
180+
return availability;
181+
}
182+
158183
AvailabilityContext
159184
AvailabilityContext::forLocation(SourceLoc loc, const DeclContext *declContext,
160185
const AvailabilityScope **refinedScope) {
@@ -191,37 +216,25 @@ AvailabilityContext::forLocation(SourceLoc loc, const DeclContext *declContext,
191216
declContext = decl->getDeclContext();
192217
}
193218

194-
if (!sf || loc.isInvalid())
195-
return baseAvailability;
196-
197-
auto *rootScope = AvailabilityScope::getOrBuildForSourceFile(*sf);
198-
if (!rootScope)
199-
return baseAvailability;
200-
201-
auto *scope = rootScope->findMostRefinedSubContext(loc, ctx);
202-
if (!scope)
203-
return baseAvailability;
204-
205-
if (refinedScope)
206-
*refinedScope = scope;
207-
208-
auto availability = scope->getAvailabilityContext();
209-
availability.constrainWithContext(baseAvailability, ctx);
210-
return availability;
219+
return contextForLocationInSourceFile(loc, sf, baseAvailability,
220+
refinedScope);
211221
}
212222

213223
AvailabilityContext AvailabilityContext::forDeclSignature(const Decl *decl) {
214-
// For decls with valid source locations, query the availability scope tree.
224+
// For decls with valid source locations in source files, we can query the
225+
// availability scope tree.
215226
auto loc = decl->getLoc();
216-
if (loc.isValid())
217-
return forLocation(loc, decl->getInnermostDeclContext());
218-
219-
// Otherwise, walk the decl hierarchy to compute availability. This can't be
220-
// delegated to `AvailabilityContext::forLocation()` since it walks up the
221-
// `DeclContext` hierachy for invalid source locations and that may skip
222-
// some declarations with availability attributes.
223227
auto &ctx = decl->getASTContext();
224228
auto availability = forInliningTarget(ctx);
229+
230+
if (loc.isValid()) {
231+
if (auto sf = decl->getDeclContext()
232+
->getParentModule()
233+
->getSourceFileContainingLocation(loc))
234+
return contextForLocationInSourceFile(loc, sf, availability, nullptr);
235+
}
236+
237+
// Otherwise, just walk the decl hierarchy to compute availability.
225238
while (decl) {
226239
availability.constrainWithDecl(decl);
227240
decl = decl->parentDeclForAvailability();

0 commit comments

Comments
 (0)