Skip to content

Commit 5ed2616

Browse files
committed
[Sema] Report availability macros in inlinable code
Availability macros can’t be used in inlinable code as inlinable is copied textually in the generated swiftinterface files. Further would could lift this limitation.
1 parent c6fc53e commit 5ed2616

File tree

5 files changed

+55
-2
lines changed

5 files changed

+55
-2
lines changed

include/swift/AST/AvailabilitySpec.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ class PlatformVersionConstraintAvailabilitySpec : public AvailabilitySpec {
8585

8686
SourceRange VersionSrcRange;
8787

88+
// Location of the macro expanded to create this spec.
89+
SourceLoc MacroLoc;
90+
8891
public:
8992
PlatformVersionConstraintAvailabilitySpec(PlatformKind Platform,
9093
SourceLoc PlatformLoc,
@@ -117,6 +120,10 @@ class PlatformVersionConstraintAvailabilitySpec : public AvailabilitySpec {
117120

118121
SourceRange getSourceRange() const;
119122

123+
// Location of the macro expanded to create this spec.
124+
SourceLoc getMacroLoc() const { return MacroLoc; }
125+
void setMacroLoc(SourceLoc loc) { MacroLoc = loc; }
126+
120127
void print(raw_ostream &OS, unsigned Indent) const;
121128

122129
static bool classof(const AvailabilitySpec *Spec) {

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4922,6 +4922,10 @@ WARNING(public_decl_needs_availability, none,
49224922
"public declarations should have an availability attribute when building "
49234923
"with -require-explicit-availability", ())
49244924

4925+
ERROR(availability_macro_in_inlinable, none,
4926+
"availability macro cannot be used in inlinable %0",
4927+
(DescriptiveDeclKind))
4928+
49254929
// This doesn't display as an availability diagnostic, but it's
49264930
// implemented there and fires when these subscripts are marked
49274931
// unavailable, so it seems appropriate to put it here.

lib/Parse/ParseDecl.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1408,8 +1408,18 @@ Parser::parseAvailabilityMacro(SmallVectorImpl<AvailabilitySpec *> &Specs) {
14081408
return makeParserError(); // Failed to match the version, that's an error.
14091409
}
14101410

1411-
Specs.append(VersionMatch->getSecond().begin(),
1412-
VersionMatch->getSecond().end());
1411+
// Make a copy of the specs to add the macro source location
1412+
// for the diagnostic about the use of macros in inlinable code.
1413+
SourceLoc MacroLoc = Tok.getLoc();
1414+
for (auto *Spec : VersionMatch->getSecond())
1415+
if (auto *PlatformVersionSpec =
1416+
dyn_cast<PlatformVersionConstraintAvailabilitySpec>(Spec)) {
1417+
auto SpecCopy =
1418+
new (Context) PlatformVersionConstraintAvailabilitySpec(
1419+
*PlatformVersionSpec);
1420+
SpecCopy->setMacroLoc(MacroLoc);
1421+
Specs.push_back(SpecCopy);
1422+
}
14131423

14141424
return makeParserSuccess();
14151425
}

lib/Sema/TypeCheckStmt.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,24 @@ static bool typeCheckConditionForStatement(LabeledConditionalStmt *stmt,
465465
for (auto &elt : cond) {
466466
if (elt.getKind() == StmtConditionElement::CK_Availability) {
467467
hadAnyFalsable = true;
468+
469+
// Reject inlinable code using availability macros.
470+
PoundAvailableInfo *info = elt.getAvailability();
471+
if (auto *decl = dc->getAsDecl()) {
472+
if (decl->getAttrs().hasAttribute<InlinableAttr>() ||
473+
decl->getAttrs().hasAttribute<AlwaysEmitIntoClientAttr>())
474+
for (auto queries : info->getQueries())
475+
if (auto availSpec =
476+
dyn_cast<PlatformVersionConstraintAvailabilitySpec>(queries))
477+
if (availSpec->getMacroLoc().isValid()) {
478+
Context.Diags.diagnose(
479+
availSpec->getMacroLoc(),
480+
swift::diag::availability_macro_in_inlinable,
481+
decl->getDescriptiveKind());
482+
break;
483+
}
484+
}
485+
468486
continue;
469487
}
470488

test/Sema/availability_define.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,17 @@ func client() {
5858

5959
if #available(_unknownMacro, *) { } // expected-error {{expected version number}}
6060
}
61+
62+
@inlinable
63+
public func forbidMacrosInInlinableCode() {
64+
if #available(_iOS9Aligned, *) { } // expected-error {{availability macro cannot be used in inlinable global function}}
65+
if #available(_iOS9, _macOS10_11, *) { } // expected-error {{availability macro cannot be used in inlinable global function}}
66+
if #available(iOS 9.0, _macOS10_11, tvOS 9.0, *) { } // expected-error {{availability macro cannot be used in inlinable global function}}
67+
}
68+
69+
@_alwaysEmitIntoClient
70+
public func forbidMacrosInInlinableCode1() {
71+
if #available(_iOS9Aligned, *) { } // expected-error {{availability macro cannot be used in inlinable global function}}
72+
if #available(_iOS9, _macOS10_11, *) { } // expected-error {{availability macro cannot be used in inlinable global function}}
73+
if #available(iOS 9.0, _macOS10_11, tvOS 9.0, *) { } // expected-error {{availability macro cannot be used in inlinable global function}}
74+
}

0 commit comments

Comments
 (0)