Skip to content

Commit d5ee1da

Browse files
committed
Sema: Put the AvailabilityContext inside the ExportContext
1 parent e7b0902 commit d5ee1da

8 files changed

+83
-49
lines changed

lib/Sema/BuilderTransform.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1244,8 +1244,9 @@ class BuilderClosureRewriter
12441244
if (!nominal)
12451245
return false;
12461246

1247+
ExportContext where = ExportContext::forFunctionBody(dc, loc);
12471248
if (auto reason = TypeChecker::checkDeclarationAvailability(
1248-
nominal, loc, dc)) {
1249+
nominal, where)) {
12491250
ctx.Diags.diagnose(
12501251
loc, diag::result_builder_missing_limited_availability,
12511252
builderTransform.builderType);

lib/Sema/ConstraintSystem.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
//===----------------------------------------------------------------------===//
1818
#include "CSDiagnostics.h"
1919
#include "TypeChecker.h"
20+
#include "TypeCheckAvailability.h"
2021
#include "TypeCheckType.h"
2122
#include "swift/AST/Initializer.h"
2223
#include "swift/AST/GenericEnvironment.h"
@@ -5057,7 +5058,8 @@ bool ConstraintSystem::isDeclUnavailable(const Decl *D,
50575058
}
50585059

50595060
// If not, let's check contextual unavailability.
5060-
auto result = TypeChecker::checkDeclarationAvailability(D, loc, DC);
5061+
ExportContext where = ExportContext::forFunctionBody(DC, loc);
5062+
auto result = TypeChecker::checkDeclarationAvailability(D, where);
50615063
return result.hasValue();
50625064
}
50635065

@@ -5242,8 +5244,9 @@ bool ConstraintSystem::isReadOnlyKeyPathComponent(
52425244
// If the setter is unavailable, then the keypath ought to be read-only
52435245
// in this context.
52445246
if (auto setter = storage->getOpaqueAccessor(AccessorKind::Set)) {
5247+
ExportContext where = ExportContext::forFunctionBody(DC, referenceLoc);
52455248
auto maybeUnavail =
5246-
TypeChecker::checkDeclarationAvailability(setter, referenceLoc, DC);
5249+
TypeChecker::checkDeclarationAvailability(setter, where);
52475250
if (maybeUnavail.hasValue()) {
52485251
return true;
52495252
}

lib/Sema/TypeCheckAccess.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1496,11 +1496,7 @@ class DeclAvailabilityChecker : public DeclVisitor<DeclAvailabilityChecker> {
14961496
if (allowUnavailableProtocol)
14971497
flags |= DeclAvailabilityFlag::AllowPotentiallyUnavailableProtocol;
14981498

1499-
auto loc = context->getLoc();
1500-
if (auto *varDecl = dyn_cast<VarDecl>(context))
1501-
loc = varDecl->getNameLoc();
1502-
1503-
diagnoseTypeAvailability(typeRepr, type, loc,
1499+
diagnoseTypeAvailability(typeRepr, type, context->getLoc(),
15041500
Where.withReason(reason), flags);
15051501
}
15061502

lib/Sema/TypeCheckAvailability.cpp

Lines changed: 53 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,12 @@
3737
#include "llvm/Support/SaveAndRestore.h"
3838
using namespace swift;
3939

40-
ExportContext::ExportContext(DeclContext *DC, FragileFunctionKind kind,
40+
ExportContext::ExportContext(DeclContext *DC,
41+
AvailabilityContext runningOSVersion,
42+
FragileFunctionKind kind,
4143
bool spi, bool exported, bool implicit, bool deprecated,
4244
Optional<PlatformKind> unavailablePlatformKind)
43-
: DC(DC), FragileKind(kind) {
45+
: DC(DC), RunningOSVersion(runningOSVersion), FragileKind(kind) {
4446
SPI = spi;
4547
Exported = exported;
4648
Implicit = implicit;
@@ -169,7 +171,10 @@ ExportContext ExportContext::forDeclSignature(Decl *D) {
169171

170172
auto *DC = D->getInnermostDeclContext();
171173
auto fragileKind = DC->getFragileFunctionKind();
172-
174+
auto runningOSVersion =
175+
(Ctx.LangOpts.DisableAvailabilityChecking
176+
? AvailabilityContext::alwaysAvailable()
177+
: TypeChecker::overApproximateAvailabilityAtLocation(D->getEndLoc(), DC));
173178
bool spi = false;
174179
bool implicit = false;
175180
bool deprecated = false;
@@ -185,14 +190,19 @@ ExportContext ExportContext::forDeclSignature(Decl *D) {
185190

186191
bool exported = ::isExported(D);
187192

188-
return ExportContext(DC, fragileKind, spi, exported, implicit, deprecated,
193+
return ExportContext(DC, runningOSVersion, fragileKind,
194+
spi, exported, implicit, deprecated,
189195
unavailablePlatformKind);
190196
}
191197

192-
ExportContext ExportContext::forFunctionBody(DeclContext *DC) {
198+
ExportContext ExportContext::forFunctionBody(DeclContext *DC, SourceLoc loc) {
193199
auto &Ctx = DC->getASTContext();
194200

195201
auto fragileKind = DC->getFragileFunctionKind();
202+
auto runningOSVersion =
203+
(Ctx.LangOpts.DisableAvailabilityChecking
204+
? AvailabilityContext::alwaysAvailable()
205+
: TypeChecker::overApproximateAvailabilityAtLocation(loc, DC));
196206

197207
bool spi = false;
198208
bool implicit = false;
@@ -207,7 +217,8 @@ ExportContext ExportContext::forFunctionBody(DeclContext *DC) {
207217

208218
bool exported = false;
209219

210-
return ExportContext(DC, fragileKind, spi, exported, implicit, deprecated,
220+
return ExportContext(DC, runningOSVersion, fragileKind,
221+
spi, exported, implicit, deprecated,
211222
unavailablePlatformKind);
212223
}
213224

@@ -915,8 +926,8 @@ TypeChecker::overApproximateAvailabilityAtLocation(SourceLoc loc,
915926
}
916927

917928
Optional<UnavailabilityReason>
918-
TypeChecker::checkDeclarationAvailability(const Decl *D, SourceLoc referenceLoc,
919-
const DeclContext *referenceDC) {
929+
TypeChecker::checkDeclarationAvailability(const Decl *D, ExportContext where) {
930+
auto *referenceDC = where.getDeclContext();
920931
ASTContext &Context = referenceDC->getASTContext();
921932
if (Context.LangOpts.DisableAvailabilityChecking) {
922933
return None;
@@ -929,7 +940,7 @@ TypeChecker::checkDeclarationAvailability(const Decl *D, SourceLoc referenceLoc,
929940
}
930941

931942
AvailabilityContext runningOSOverApprox =
932-
overApproximateAvailabilityAtLocation(referenceLoc, referenceDC);
943+
where.getAvailabilityContext();
933944

934945
AvailabilityContext safeRangeUnderApprox{
935946
AvailabilityInference::availableRange(D, Context)};
@@ -2073,8 +2084,7 @@ void TypeChecker::diagnoseIfDeprecated(SourceRange ReferenceRange,
20732084
auto *ReferenceDC = Where.getDeclContext();
20742085
auto &Context = ReferenceDC->getASTContext();
20752086
if (!Context.LangOpts.DisableAvailabilityChecking) {
2076-
AvailabilityContext RunningOSVersions =
2077-
overApproximateAvailabilityAtLocation(ReferenceRange.Start,ReferenceDC);
2087+
AvailabilityContext RunningOSVersions = Where.getAvailabilityContext();
20782088
if (RunningOSVersions.isKnownUnreachable()) {
20792089
// Suppress a deprecation warning if the availability checking machinery
20802090
// thinks the reference program location will not execute on any
@@ -2510,6 +2520,17 @@ class ExprAvailabilityWalker : public ASTWalker {
25102520
return E;
25112521
}
25122522

2523+
std::pair<bool, Stmt *> walkToStmtPre(Stmt *S) override {
2524+
// We end up here when checking the output of the result builder transform,
2525+
// which includes closures that are not "separately typechecked" and yet
2526+
// contain statements and declarations. We need to walk them recursively,
2527+
// since these availability for these statements is not diagnosed from
2528+
// typeCheckStmt() as usual.
2529+
diagnoseStmtAvailability(S, Where.getDeclContext(),
2530+
/*walkRecursively=*/true);
2531+
return std::make_pair(false, S);
2532+
}
2533+
25132534
bool diagnoseDeclRefAvailability(ConcreteDeclRef declRef, SourceRange R,
25142535
const ApplyExpr *call = nullptr,
25152536
DeclAvailabilityFlags flags = None) const;
@@ -2768,11 +2789,11 @@ swift::diagnoseDeclAvailability(const ValueDecl *D,
27682789
&& isa<ProtocolDecl>(D))
27692790
return false;
27702791

2771-
auto *DC = Where.getDeclContext();
2772-
27732792
// Diagnose (and possibly signal) for potential unavailability
2774-
auto maybeUnavail = TypeChecker::checkDeclarationAvailability(D, R.Start, DC);
2793+
auto maybeUnavail = TypeChecker::checkDeclarationAvailability(D, Where);
27752794
if (maybeUnavail.hasValue()) {
2795+
auto *DC = Where.getDeclContext();
2796+
27762797
if (accessor) {
27772798
bool forInout = Flags.contains(DeclAvailabilityFlag::ForInout);
27782799
TypeChecker::diagnosePotentialAccessorUnavailability(accessor, R, DC,
@@ -2943,7 +2964,7 @@ ExprAvailabilityWalker::diagnoseMemoryLayoutMigration(const ValueDecl *D,
29432964

29442965
/// Diagnose uses of unavailable declarations.
29452966
void swift::diagnoseExprAvailability(const Expr *E, DeclContext *DC) {
2946-
auto where = ExportContext::forFunctionBody(DC);
2967+
auto where = ExportContext::forFunctionBody(DC, E->getStartLoc());
29472968
if (where.isImplicit())
29482969
return;
29492970
ExprAvailabilityWalker walker(where);
@@ -2953,50 +2974,51 @@ void swift::diagnoseExprAvailability(const Expr *E, DeclContext *DC) {
29532974
namespace {
29542975

29552976
class StmtAvailabilityWalker : public ASTWalker {
2956-
ExportContext Where;
2977+
DeclContext *DC;
2978+
bool WalkRecursively;
29572979

29582980
public:
2959-
explicit StmtAvailabilityWalker(ExportContext where)
2960-
: Where(where) {}
2981+
explicit StmtAvailabilityWalker(DeclContext *dc, bool walkRecursively)
2982+
: DC(dc), WalkRecursively(walkRecursively) {}
29612983

2962-
/// We'll visit each element of a BraceStmt individually.
29632984
std::pair<bool, Stmt *> walkToStmtPre(Stmt *S) override {
2964-
if (isa<BraceStmt>(S))
2985+
if (!WalkRecursively && isa<BraceStmt>(S))
29652986
return std::make_pair(false, S);
29662987

29672988
return std::make_pair(true, S);
29682989
}
29692990

2970-
/// We'll visit the expression from performSyntacticExprDiagnostics().
29712991
std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
2992+
if (WalkRecursively)
2993+
diagnoseExprAvailability(E, DC);
29722994
return std::make_pair(false, E);
29732995
}
29742996

29752997
bool walkToTypeReprPre(TypeRepr *T) override {
2976-
diagnoseTypeReprAvailability(T, Where);
2998+
auto where = ExportContext::forFunctionBody(DC, T->getStartLoc());
2999+
diagnoseTypeReprAvailability(T, where);
29773000
return false;
29783001
}
29793002

29803003
std::pair<bool, Pattern *> walkToPatternPre(Pattern *P) override {
2981-
if (auto *IP = dyn_cast<IsPattern>(P))
2982-
diagnoseTypeAvailability(IP->getCastType(), P->getLoc(), Where);
3004+
if (auto *IP = dyn_cast<IsPattern>(P)) {
3005+
auto where = ExportContext::forFunctionBody(DC, P->getLoc());
3006+
diagnoseTypeAvailability(IP->getCastType(), P->getLoc(), where);
3007+
}
29833008

29843009
return std::make_pair(true, P);
29853010
}
29863011
};
29873012

29883013
}
29893014

2990-
void swift::diagnoseStmtAvailability(const Stmt *S, DeclContext *DC) {
3015+
void swift::diagnoseStmtAvailability(const Stmt *S, DeclContext *DC,
3016+
bool walkRecursively) {
29913017
// We'll visit the individual statements when we check them.
2992-
if (isa<BraceStmt>(S))
2993-
return;
2994-
2995-
auto where = ExportContext::forFunctionBody(DC);
2996-
if (where.isImplicit())
3018+
if (!walkRecursively && isa<BraceStmt>(S))
29973019
return;
29983020

2999-
StmtAvailabilityWalker walker(where);
3021+
StmtAvailabilityWalker walker(DC, walkRecursively);
30003022
const_cast<Stmt*>(S)->walk(walker);
30013023
}
30023024

lib/Sema/TypeCheckAvailability.h

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include "swift/AST/DeclContext.h"
1717
#include "swift/AST/AttrKind.h"
18+
#include "swift/AST/Availability.h"
1819
#include "swift/AST/Identifier.h"
1920
#include "swift/Basic/LLVM.h"
2021
#include "swift/Basic/SourceLoc.h"
@@ -92,6 +93,7 @@ enum class ExportabilityReason : unsigned {
9293
/// without producing a warning or error, respectively.
9394
class ExportContext {
9495
DeclContext *DC;
96+
AvailabilityContext RunningOSVersion;
9597
FragileFunctionKind FragileKind;
9698
unsigned SPI : 1;
9799
unsigned Exported : 1;
@@ -101,7 +103,9 @@ class ExportContext {
101103
unsigned Platform : 8;
102104
unsigned Reason : 2;
103105

104-
ExportContext(DeclContext *DC, FragileFunctionKind kind,
106+
ExportContext(DeclContext *DC,
107+
AvailabilityContext runningOSVersion,
108+
FragileFunctionKind kind,
105109
bool spi, bool exported, bool implicit, bool deprecated,
106110
Optional<PlatformKind> unavailablePlatformKind);
107111

@@ -121,7 +125,7 @@ class ExportContext {
121125
/// referencing ABI-public declarations only. Furthermore, if the function
122126
/// is exported, referenced declarations must also be exported. Otherwise
123127
/// it can reference anything.
124-
static ExportContext forFunctionBody(DeclContext *DC);
128+
static ExportContext forFunctionBody(DeclContext *DC, SourceLoc loc);
125129

126130
/// Produce a new context with the same properties as this one, except
127131
/// changing the ExportabilityReason. This only affects diagnostics.
@@ -137,6 +141,10 @@ class ExportContext {
137141

138142
DeclContext *getDeclContext() const { return DC; }
139143

144+
AvailabilityContext getAvailabilityContext() const {
145+
return RunningOSVersion;
146+
}
147+
140148
/// If not 'None', the context has the inlinable function body restriction.
141149
FragileFunctionKind getFragileFunctionKind() const { return FragileKind; }
142150

@@ -175,9 +183,13 @@ bool isExported(const Decl *D);
175183
/// Diagnose uses of unavailable declarations in expressions.
176184
void diagnoseExprAvailability(const Expr *E, DeclContext *DC);
177185

178-
/// Diagnose uses of unavailable declarations in statements (via patterns, etc),
179-
/// without walking into expressions.
180-
void diagnoseStmtAvailability(const Stmt *S, DeclContext *DC);
186+
/// Diagnose uses of unavailable declarations in statements (via patterns, etc)
187+
/// but not expressions, unless \p walkRecursively was specified.
188+
///
189+
/// \param walkRecursively Whether nested statements and expressions should
190+
/// be visited, too.
191+
void diagnoseStmtAvailability(const Stmt *S, DeclContext *DC,
192+
bool walkRecursively=false);
181193

182194
/// Diagnose uses of unavailable declarations in types.
183195
bool diagnoseTypeReprAvailability(const TypeRepr *T,

lib/Sema/TypeCheckPattern.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ using namespace swift;
3737
static EnumElementDecl *
3838
extractEnumElement(DeclContext *DC, SourceLoc UseLoc,
3939
const VarDecl *constant) {
40-
ExportContext where = ExportContext::forFunctionBody(DC);
40+
ExportContext where = ExportContext::forFunctionBody(DC, UseLoc);
4141
diagnoseExplicitUnavailability(constant, UseLoc, where, nullptr);
4242

4343
const FuncDecl *getter = constant->getAccessor(AccessorKind::Get);

lib/Sema/TypeCheckStmt.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1696,9 +1696,10 @@ static bool checkSuperInit(ConstructorDecl *fromCtor,
16961696
}
16971697

16981698
// Make sure we can reference the designated initializer correctly.
1699+
auto loc = fromCtor->getLoc();
16991700
diagnoseDeclAvailability(
1700-
ctor, fromCtor->getLoc(), nullptr,
1701-
ExportContext::forFunctionBody(fromCtor));
1701+
ctor, loc, nullptr,
1702+
ExportContext::forFunctionBody(fromCtor, loc));
17021703
}
17031704

17041705

lib/Sema/TypeChecker.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1010,8 +1010,7 @@ diagnosticIfDeclCannotBePotentiallyUnavailable(const Decl *D);
10101010
/// declaration is unavailable. Returns None is the declaration is
10111011
/// definitely available.
10121012
Optional<UnavailabilityReason>
1013-
checkDeclarationAvailability(const Decl *D, SourceLoc referenceLoc,
1014-
const DeclContext *referenceDC);
1013+
checkDeclarationAvailability(const Decl *D, ExportContext where);
10151014

10161015
/// Checks an "ignored" expression to see if it's okay for it to be ignored.
10171016
///

0 commit comments

Comments
 (0)