Skip to content

Commit fa267fe

Browse files
authored
Merge pull request #83051 from tshortli/diagnose-more-invalid-os-versions
Sema: Diagnose invalid platform versions in more places
2 parents 2689ef3 + d09e117 commit fa267fe

21 files changed

+274
-70
lines changed

include/swift/AST/Attr.h

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2399,6 +2399,11 @@ class ProjectedValuePropertyAttr : public DeclAttribute {
23992399
/// The variable \p foo was originally defined in another module called
24002400
/// \p Original prior to OSX 10.15
24012401
class OriginallyDefinedInAttr: public DeclAttribute {
2402+
const StringRef ManglingModuleName;
2403+
const StringRef LinkerModuleName;
2404+
const PlatformKind Platform;
2405+
const llvm::VersionTuple MovedVersion;
2406+
24022407
public:
24032408
OriginallyDefinedInAttr(SourceLoc AtLoc, SourceRange Range,
24042409
StringRef OriginalModuleName,
@@ -2420,16 +2425,22 @@ class OriginallyDefinedInAttr: public DeclAttribute {
24202425
OriginallyDefinedInAttr *clone(ASTContext &C, bool implicit) const;
24212426

24222427
// The original module name for mangling.
2423-
const StringRef ManglingModuleName;
2428+
StringRef getManglingModuleName() const { return ManglingModuleName; }
24242429

24252430
// The original module name for linker directives.
2426-
const StringRef LinkerModuleName;
2431+
StringRef getLinkerModuleName() const { return LinkerModuleName; }
24272432

24282433
/// The platform of the symbol.
2429-
const PlatformKind Platform;
2434+
PlatformKind getPlatform() const { return Platform; }
24302435

2431-
/// Indicates when the symbol was moved here.
2432-
const llvm::VersionTuple MovedVersion;
2436+
/// The version of the platform that the symbol was moved in, as it was
2437+
/// written in source.
2438+
llvm::VersionTuple getParsedMovedVersion() const { return MovedVersion; }
2439+
2440+
/// The version of the platform that the symbol was moved in. This may be
2441+
/// different than the version that was written in source due to
2442+
/// canonicalization.
2443+
llvm::VersionTuple getMovedVersion() const;
24332444

24342445
struct ActiveVersion {
24352446
StringRef ManglingModuleName;
@@ -2928,17 +2939,25 @@ class UnavailableFromAsyncAttr : public DeclAttribute {
29282939
/// available for back deployment to older OSes via emission into the client
29292940
/// binary.
29302941
class BackDeployedAttr : public DeclAttribute {
2942+
const PlatformKind Platform;
2943+
const llvm::VersionTuple Version;
2944+
29312945
public:
29322946
BackDeployedAttr(SourceLoc AtLoc, SourceRange Range, PlatformKind Platform,
29332947
const llvm::VersionTuple &Version, bool Implicit)
29342948
: DeclAttribute(DeclAttrKind::BackDeployed, AtLoc, Range, Implicit),
29352949
Platform(Platform), Version(Version) {}
29362950

29372951
/// The platform the decl is available for back deployment in.
2938-
const PlatformKind Platform;
2952+
PlatformKind getPlatform() const { return Platform; }
29392953

2940-
/// The earliest platform version that may use the back deployed implementation.
2941-
const llvm::VersionTuple Version;
2954+
/// The `before:` version tuple that was written in source.
2955+
llvm::VersionTuple getParsedVersion() const { return Version; }
2956+
2957+
/// The `before:` version, which is the earliest platform version that may use
2958+
/// the back deployed implementation. This may be different from the version
2959+
/// that was written in source due to canonicalization.
2960+
llvm::VersionTuple getVersion() const;
29422961

29432962
/// Returns true if this attribute is active given the current platform.
29442963
bool isActivePlatform(const ASTContext &ctx, bool forTargetVariant) const;

lib/AST/ASTDumper.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5121,9 +5121,10 @@ class PrintAttribute : public AttributeVisitor<PrintAttribute, void, Label>,
51215121
}
51225122
void visitBackDeployedAttr(BackDeployedAttr *Attr, Label label) {
51235123
printCommon(Attr, "back_deployed_attr", label);
5124-
printField(Attr->Platform, Label::always("platform"));
5125-
printFieldRaw([&](auto &out) { out << Attr->Version.getAsString(); },
5126-
Label::always("version"));
5124+
printField(Attr->getPlatform(), Label::always("platform"));
5125+
printFieldRaw(
5126+
[&](auto &out) { out << Attr->getParsedVersion().getAsString(); },
5127+
Label::always("version"));
51275128
printFoot();
51285129
}
51295130
void visitCDeclAttr(CDeclAttr *Attr, Label label) {
@@ -5347,11 +5348,12 @@ class PrintAttribute : public AttributeVisitor<PrintAttribute, void, Label>,
53475348
void visitOriginallyDefinedInAttr(OriginallyDefinedInAttr *Attr,
53485349
Label label) {
53495350
printCommon(Attr, "originally_defined_in_attr", label);
5350-
printField(Attr->ManglingModuleName, Label::always("mangling_module"));
5351-
printField(Attr->LinkerModuleName, Label::always("linker_module"));
5352-
printField(Attr->Platform, Label::always("platform"));
5353-
printFieldRaw([&](auto &out) { out << Attr->MovedVersion.getAsString(); },
5354-
Label::always("moved_version"));
5351+
printField(Attr->getManglingModuleName(), Label::always("mangling_module"));
5352+
printField(Attr->getLinkerModuleName(), Label::always("linker_module"));
5353+
printField(Attr->getPlatform(), Label::always("platform"));
5354+
printFieldRaw(
5355+
[&](auto &out) { out << Attr->getParsedMovedVersion().getAsString(); },
5356+
Label::always("moved_version"));
53555357
printFoot();
53565358
}
53575359
void visitPrivateImportAttr(PrivateImportAttr *Attr, Label label) {

lib/AST/ASTPrinter.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6058,9 +6058,9 @@ class TypePrinter : public TypeVisitor<TypePrinter, void, NonRecursivePrintOptio
60586058
if (Options.UseOriginallyDefinedInModuleNames) {
60596059
Decl *D = Ty->getDecl();
60606060
for (auto attr: D->getAttrs().getAttributes<OriginallyDefinedInAttr>()) {
6061-
Name = Mod->getASTContext()
6062-
.getIdentifier(const_cast<OriginallyDefinedInAttr*>(attr)
6063-
->ManglingModuleName);
6061+
Name = Mod->getASTContext().getIdentifier(
6062+
const_cast<OriginallyDefinedInAttr *>(attr)
6063+
->getManglingModuleName());
60646064
break;
60656065
}
60666066
}

lib/AST/Attr.cpp

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -421,8 +421,9 @@ DeclAttributes::getBackDeployed(const ASTContext &ctx,
421421

422422
// We have an attribute that is active for the platform, but
423423
// is it more specific than our current best?
424-
if (!bestAttr || inheritsAvailabilityFromPlatform(
425-
backDeployedAttr->Platform, bestAttr->Platform)) {
424+
if (!bestAttr ||
425+
inheritsAvailabilityFromPlatform(backDeployedAttr->getPlatform(),
426+
bestAttr->getPlatform())) {
426427
bestAttr = backDeployedAttr;
427428
}
428429
}
@@ -557,8 +558,8 @@ static void printShortFormBackDeployed(ArrayRef<const DeclAttribute *> Attrs,
557558
if (!isFirst)
558559
Printer << ", ";
559560
auto *attr = cast<BackDeployedAttr>(DA);
560-
Printer << platformString(attr->Platform) << " "
561-
<< attr->Version.getAsString();
561+
Printer << platformString(attr->getPlatform()) << " "
562+
<< attr->getVersion().getAsString();
562563
isFirst = false;
563564
}
564565
Printer << ")";
@@ -771,9 +772,9 @@ static std::optional<PlatformKind> referencedPlatform(const DeclAttribute *attr,
771772
}
772773
return std::nullopt;
773774
case DeclAttrKind::BackDeployed:
774-
return static_cast<const BackDeployedAttr *>(attr)->Platform;
775+
return static_cast<const BackDeployedAttr *>(attr)->getPlatform();
775776
case DeclAttrKind::OriginallyDefinedIn:
776-
return static_cast<const OriginallyDefinedInAttr *>(attr)->Platform;
777+
return static_cast<const OriginallyDefinedInAttr *>(attr)->getPlatform();
777778
default:
778779
return std::nullopt;
779780
}
@@ -1094,7 +1095,7 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
10941095
case DeclAttrKind::OriginallyDefinedIn: {
10951096
auto Attr = cast<OriginallyDefinedInAttr>(this);
10961097
auto Name = D->getDeclContext()->getParentModule()->getName().str();
1097-
if (Options.IsForSwiftInterface && Attr->ManglingModuleName == Name)
1098+
if (Options.IsForSwiftInterface && Attr->getManglingModuleName() == Name)
10981099
return false;
10991100
break;
11001101
}
@@ -1195,13 +1196,15 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
11951196
Printer.printAttrName("@_originallyDefinedIn");
11961197
Printer << "(module: ";
11971198
auto Attr = cast<OriginallyDefinedInAttr>(this);
1198-
Printer << "\"" << Attr->ManglingModuleName;
1199-
ASSERT(!Attr->ManglingModuleName.empty());
1200-
ASSERT(!Attr->LinkerModuleName.empty());
1201-
if (Attr->LinkerModuleName != Attr->ManglingModuleName)
1202-
Printer << ";" << Attr->LinkerModuleName;
1203-
Printer << "\", " << platformString(Attr->Platform) << " " <<
1204-
Attr->MovedVersion.getAsString();
1199+
auto ManglingModuleName = Attr->getManglingModuleName();
1200+
auto LinkerModuleName = Attr->getLinkerModuleName();
1201+
Printer << "\"" << ManglingModuleName;
1202+
ASSERT(!ManglingModuleName.empty());
1203+
ASSERT(!LinkerModuleName.empty());
1204+
if (LinkerModuleName != ManglingModuleName)
1205+
Printer << ";" << LinkerModuleName;
1206+
Printer << "\", " << platformString(Attr->getPlatform()) << " "
1207+
<< Attr->getMovedVersion().getAsString();
12051208
Printer << ")";
12061209
break;
12071210
}
@@ -1517,8 +1520,8 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
15171520
Printer.printAttrName("@backDeployed");
15181521
Printer << "(before: ";
15191522
auto Attr = cast<BackDeployedAttr>(this);
1520-
Printer << platformString(Attr->Platform) << " " <<
1521-
Attr->Version.getAsString();
1523+
Printer << platformString(Attr->getPlatform()) << " "
1524+
<< Attr->getVersion().getAsString();
15221525
Printer << ")";
15231526
break;
15241527
}
@@ -2348,6 +2351,10 @@ AvailableAttr *AvailableAttr::createUnavailableInEmbedded(ASTContext &C,
23482351
/*Implicit=*/false, /*IsSPI=*/false);
23492352
}
23502353

2354+
llvm::VersionTuple BackDeployedAttr::getVersion() const {
2355+
return canonicalizePlatformVersion(getPlatform(), getParsedVersion());
2356+
}
2357+
23512358
bool BackDeployedAttr::isActivePlatform(const ASTContext &ctx,
23522359
bool forTargetVariant) const {
23532360
return isPlatformActive(Platform, ctx.LangOpts, forTargetVariant);
@@ -2375,14 +2382,14 @@ bool AvailableAttr::isEquivalent(const AvailableAttr *other,
23752382
== attachedTo->getSemanticAvailableAttr(other)->getDomain();
23762383
}
23772384

2378-
static StringRef getManglingModuleName(StringRef OriginalModuleName) {
2385+
static StringRef parseManglingModuleName(StringRef OriginalModuleName) {
23792386
auto index = OriginalModuleName.find(";");
23802387
return index == StringRef::npos
23812388
? OriginalModuleName
23822389
: OriginalModuleName.slice(0, index);
23832390
}
23842391

2385-
static StringRef getLinkerModuleName(StringRef OriginalModuleName) {
2392+
static StringRef parseLinkerModuleName(StringRef OriginalModuleName) {
23862393
auto index = OriginalModuleName.find(";");
23872394
return index == StringRef::npos
23882395
? OriginalModuleName
@@ -2393,16 +2400,19 @@ OriginallyDefinedInAttr::OriginallyDefinedInAttr(
23932400
SourceLoc AtLoc, SourceRange Range, StringRef OriginalModuleName,
23942401
PlatformKind Platform, const llvm::VersionTuple MovedVersion, bool Implicit)
23952402
: DeclAttribute(DeclAttrKind::OriginallyDefinedIn, AtLoc, Range, Implicit),
2396-
ManglingModuleName(getManglingModuleName(OriginalModuleName)),
2397-
LinkerModuleName(getLinkerModuleName(OriginalModuleName)),
2398-
Platform(Platform),
2399-
MovedVersion(canonicalizePlatformVersion(Platform, MovedVersion)) {}
2403+
ManglingModuleName(parseManglingModuleName(OriginalModuleName)),
2404+
LinkerModuleName(parseLinkerModuleName(OriginalModuleName)),
2405+
Platform(Platform), MovedVersion(MovedVersion) {}
2406+
2407+
llvm::VersionTuple OriginallyDefinedInAttr::getMovedVersion() const {
2408+
return canonicalizePlatformVersion(getPlatform(), getParsedMovedVersion());
2409+
}
24002410

24012411
std::optional<OriginallyDefinedInAttr::ActiveVersion>
24022412
OriginallyDefinedInAttr::isActivePlatform(const ASTContext &ctx) const {
24032413
OriginallyDefinedInAttr::ActiveVersion Result;
24042414
Result.Platform = Platform;
2405-
Result.Version = MovedVersion;
2415+
Result.Version = getMovedVersion();
24062416
Result.ManglingModuleName = ManglingModuleName;
24072417
Result.LinkerModuleName = LinkerModuleName;
24082418
if (isPlatformActive(Platform, ctx.LangOpts, /*TargetVariant*/false)) {

lib/AST/Availability.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ bool AvailabilityInference::updateBeforeAvailabilityDomainForFallback(
370370
if (!hasRemap)
371371
return false;
372372

373-
auto beforeVersion = attr->Version;
373+
auto beforeVersion = attr->getVersion();
374374
auto potentiallyRemappedIntroducedVersion =
375375
getRemappedIntroducedVersionForFallbackPlatform(ctx, beforeVersion);
376376
if (potentiallyRemappedIntroducedVersion.has_value()) {

lib/AST/Decl.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -611,7 +611,7 @@ std::optional<std::pair<const BackDeployedAttr *, AvailabilityRange>>
611611
Decl::getBackDeployedAttrAndRange(ASTContext &Ctx,
612612
bool forTargetVariant) const {
613613
if (auto *attr = getAttrs().getBackDeployed(Ctx, forTargetVariant)) {
614-
auto version = attr->Version;
614+
auto version = attr->getVersion();
615615
AvailabilityDomain ignoredDomain;
616616
AvailabilityInference::updateBeforeAvailabilityDomainForFallback(
617617
attr, getASTContext(), ignoredDomain, version);
@@ -1142,7 +1142,7 @@ StringRef Decl::getAlternateModuleName() const {
11421142
for (auto *Att: Attrs) {
11431143
if (auto *OD = dyn_cast<OriginallyDefinedInAttr>(Att)) {
11441144
if (!OD->isInvalid() && OD->isActivePlatform(getASTContext())) {
1145-
return OD->ManglingModuleName;
1145+
return OD->getManglingModuleName();
11461146
}
11471147
}
11481148
}

lib/IRGen/IRGenDebugInfo.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2540,10 +2540,10 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
25402540
if (auto Attribute =
25412541
ND->getAttrs().getAttribute<OriginallyDefinedInAttr>()) {
25422542
auto Identifier = IGM.getSILModule().getASTContext().getIdentifier(
2543-
Attribute->ManglingModuleName);
2543+
Attribute->getManglingModuleName());
25442544
void *Key = (void *)Identifier.get();
2545-
Scope = getOrCreateModule(Key, TheCU, Attribute->ManglingModuleName, {},
2546-
{});
2545+
Scope = getOrCreateModule(Key, TheCU,
2546+
Attribute->getManglingModuleName(), {}, {});
25472547
} else {
25482548
Context = ND->getParent();
25492549
}

lib/Sema/MiscDiagnostics.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5195,8 +5195,8 @@ static bool diagnoseAvailabilityCondition(PoundAvailableInfo *info,
51955195
return true;
51965196
}
51975197

5198+
auto rawVersion = parsedSpec->getRawVersion();
51985199
if (hasVersion) {
5199-
auto rawVersion = parsedSpec->getRawVersion();
52005200
if (!VersionRange::isValidVersion(rawVersion)) {
52015201
diags
52025202
.diagnose(loc, diag::availability_unsupported_version_number,
@@ -5211,6 +5211,12 @@ static bool diagnoseAvailabilityCondition(PoundAvailableInfo *info,
52115211
diags.diagnose(loc, diag::avail_query_expected_version_number);
52125212
return true;
52135213
}
5214+
5215+
if (!domain.isVersionValid(rawVersion)) {
5216+
diags.diagnose(loc,
5217+
diag::availability_invalid_version_number_for_domain,
5218+
rawVersion, domain);
5219+
}
52145220
} else if (hasVersion) {
52155221
diags.diagnose(loc, diag::availability_unexpected_version, domain)
52165222
.highlight(parsedSpec->getVersionSrcRange());

lib/Sema/TypeCheckAttr.cpp

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4916,14 +4916,21 @@ void AttributeChecker::checkOriginalDefinedInAttrs(
49164916
// Attrs are in the reverse order of the source order. We need to visit them
49174917
// in source order to diagnose the later attribute.
49184918
for (auto *Attr: Attrs) {
4919+
auto AtLoc = Attr->AtLoc;
4920+
auto Platform = Attr->getPlatform();
4921+
auto Domain = AvailabilityDomain::forPlatform(Platform);
4922+
auto ParsedVersion = Attr->getParsedMovedVersion();
4923+
if (!Domain.isVersionValid(ParsedVersion)) {
4924+
diagnose(AtLoc, diag::availability_invalid_version_number_for_domain,
4925+
ParsedVersion, Domain);
4926+
}
4927+
49194928
if (!Attr->isActivePlatform(Ctx))
49204929
continue;
49214930

49224931
if (diagnoseAndRemoveAttrIfDeclIsNonPublic(Attr, /*isError=*/false))
49234932
continue;
49244933

4925-
auto AtLoc = Attr->AtLoc;
4926-
auto Platform = Attr->Platform;
49274934
if (!seenPlatforms.insert({Platform, AtLoc}).second) {
49284935
// We've seen the platform before, emit error to the previous one which
49294936
// comes later in the source order.
@@ -4941,7 +4948,7 @@ void AttributeChecker::checkOriginalDefinedInAttrs(
49414948
return;
49424949

49434950
auto IntroVer = D->getIntroducedOSVersion(Platform);
4944-
if (IntroVer.value() > Attr->MovedVersion) {
4951+
if (IntroVer.value() > Attr->getMovedVersion()) {
49454952
diagnose(AtLoc,
49464953
diag::originally_definedin_must_not_before_available_version);
49474954
return;
@@ -5115,6 +5122,13 @@ void AttributeChecker::checkBackDeployedAttrs(
51155122
ActiveAttr = AttrAndRange->first;
51165123

51175124
for (auto *Attr : Attrs) {
5125+
auto Domain = Attr->getAvailabilityDomain();
5126+
if (!Domain.isVersionValid(Attr->getParsedVersion())) {
5127+
diagnose(Attr->getLocation(),
5128+
diag::availability_invalid_version_number_for_domain,
5129+
Attr->getParsedVersion(), Domain);
5130+
}
5131+
51185132
// Back deployment only makes sense for public declarations.
51195133
if (diagnoseAndRemoveAttrIfDeclIsNonPublic(Attr, /*isError=*/true))
51205134
continue;
@@ -5162,7 +5176,7 @@ void AttributeChecker::checkBackDeployedAttrs(
51625176
}
51635177

51645178
auto AtLoc = Attr->AtLoc;
5165-
auto Platform = Attr->Platform;
5179+
auto Platform = Attr->getPlatform();
51665180

51675181
if (!seenPlatforms.insert({Platform, AtLoc}).second) {
51685182
// We've seen the platform before, emit error to the previous one which
@@ -5203,9 +5217,8 @@ void AttributeChecker::checkBackDeployedAttrs(
52035217
D->getLoc(), D->getInnermostDeclContext());
52045218

52055219
// Unavailable decls cannot be back deployed.
5206-
auto backDeployedDomain = Attr->getAvailabilityDomain();
5207-
if (availability.containsUnavailableDomain(backDeployedDomain)) {
5208-
auto domainForDiagnostics = backDeployedDomain;
5220+
if (availability.containsUnavailableDomain(Domain)) {
5221+
auto domainForDiagnostics = Domain;
52095222
llvm::VersionTuple ignoredVersion;
52105223

52115224
AvailabilityInference::updateBeforeAvailabilityDomainForFallback(
@@ -5237,7 +5250,7 @@ void AttributeChecker::checkBackDeployedAttrs(
52375250
if (auto availableRangeAttrPair =
52385251
getSemanticAvailableRangeDeclAndAttr(VD)) {
52395252
auto beforeDomain = Attr->getAvailabilityDomain();
5240-
auto beforeVersion = Attr->Version;
5253+
auto beforeVersion = Attr->getVersion();
52415254
auto availableAttr = availableRangeAttrPair.value().first;
52425255
auto introVersion = availableAttr.getIntroduced().value();
52435256
AvailabilityDomain introDomain = availableAttr.getDomain();
@@ -5247,7 +5260,7 @@ void AttributeChecker::checkBackDeployedAttrs(
52475260
AvailabilityInference::updateIntroducedAvailabilityDomainForFallback(
52485261
availableAttr, Ctx, introDomain, introVersion);
52495262

5250-
if (Attr->Version <= introVersion) {
5263+
if (beforeVersion <= introVersion) {
52515264
diagnose(AtLoc, diag::attr_has_no_effect_decl_not_available_before,
52525265
Attr, VD, beforeDomain, AvailabilityRange(beforeVersion));
52535266
diagnose(availableAttr.getParsedAttr()->AtLoc,

0 commit comments

Comments
 (0)