Files
swift-mirror/include/swift/AST/AvailabilitySpec.h
Allan Shortlidge d0f63a0753 AST: Split Availability.h into multiple headers.
Put AvailabilityRange into its own header with very few dependencies so that it
can be included freely in other headers that need to use it as a complete type.

NFC.
2025-01-03 18:36:04 -08:00

235 lines
8.6 KiB
C++

//===--- AvailabilitySpec.h - Swift Availability Query ASTs -----*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file defines the availability specification AST classes.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_AST_AVAILABILITY_SPEC_H
#define SWIFT_AST_AVAILABILITY_SPEC_H
#include "swift/AST/Identifier.h"
#include "swift/AST/PlatformKind.h"
#include "swift/Basic/SourceLoc.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/VersionTuple.h"
namespace swift {
class ASTContext;
enum class VersionComparison { GreaterThanEqual };
enum class AvailabilitySpecKind {
/// A platform-version constraint of the form "PlatformName X.Y.Z"
PlatformVersionConstraint,
/// A wildcard constraint, spelled '*', that is equivalent
/// to CurrentPlatformName >= MinimumDeploymentTargetVersion
OtherPlatform,
/// A language-version constraint of the form "swift X.Y.Z"
LanguageVersionConstraint,
/// A PackageDescription version constraint of the form "_PackageDescription X.Y.Z"
PackageDescriptionVersionConstraint,
};
/// The root class for specifications of API availability in availability
/// queries.
class AvailabilitySpec : public ASTAllocated<AvailabilitySpec> {
AvailabilitySpecKind Kind;
public:
AvailabilitySpec(AvailabilitySpecKind Kind) : Kind(Kind) {}
AvailabilitySpecKind getKind() const { return Kind; }
SourceRange getSourceRange() const;
};
/// An availability specification that guards execution based on the
/// run-time platform and version, e.g., OS X >= 10.10.
class PlatformVersionConstraintAvailabilitySpec : public AvailabilitySpec {
PlatformKind Platform;
SourceLoc PlatformLoc;
llvm::VersionTuple Version;
// For macOS Big Sur, we canonicalize 10.16 to 11.0 for compile-time
// checking since clang canonicalizes availability markup. However, to
// support Beta versions of macOS Big Sur where the OS
// reports 10.16 at run time, we need to compare against 10.16,
//
// This means for:
//
// if #available(macOS 10.16, *) { ... }
//
// we need to keep around both a canonical version for use in compile-time
// checks and an uncanonicalized version for the version to actually codegen
// with.
llvm::VersionTuple RuntimeVersion;
SourceRange VersionSrcRange;
// Location of the macro expanded to create this spec.
SourceLoc MacroLoc;
public:
PlatformVersionConstraintAvailabilitySpec(PlatformKind Platform,
SourceLoc PlatformLoc,
llvm::VersionTuple Version,
llvm::VersionTuple RuntimeVersion,
SourceRange VersionSrcRange)
: AvailabilitySpec(AvailabilitySpecKind::PlatformVersionConstraint),
Platform(Platform),
PlatformLoc(PlatformLoc), Version(Version),
RuntimeVersion(RuntimeVersion),
VersionSrcRange(VersionSrcRange) {}
/// The required platform.
PlatformKind getPlatform() const { return Platform; }
SourceLoc getPlatformLoc() const { return PlatformLoc; }
/// Returns true when the constraint is for a platform that was not
/// recognized. This enables better recovery during parsing but should never
/// be true after parsing is completed.
bool isUnrecognizedPlatform() const { return Platform == PlatformKind::none; }
// The platform version to compare against.
llvm::VersionTuple getVersion() const { return Version; }
SourceRange getVersionSrcRange() const { return VersionSrcRange; }
// The version to be used in codegen for version comparisons at run time.
// This is required to support beta versions of macOS Big Sur that
// report 10.16 at run time.
llvm::VersionTuple getRuntimeVersion() const { return RuntimeVersion; }
SourceRange getSourceRange() const;
// Location of the macro expanded to create this spec.
SourceLoc getMacroLoc() const { return MacroLoc; }
void setMacroLoc(SourceLoc loc) { MacroLoc = loc; }
void print(raw_ostream &OS, unsigned Indent) const;
static bool classof(const AvailabilitySpec *Spec) {
return Spec->getKind() == AvailabilitySpecKind::PlatformVersionConstraint;
}
void *
operator new(size_t Bytes, ASTContext &C,
unsigned Alignment = alignof(PlatformVersionConstraintAvailabilitySpec)){
return AvailabilitySpec::operator new(Bytes, C, AllocationArena::Permanent,
Alignment);
}
};
/// An availability specification that guards execution based on the
/// compile-time platform agnostic version, e.g., swift >= 3.0.1,
/// package-description >= 4.0.
class PlatformAgnosticVersionConstraintAvailabilitySpec : public AvailabilitySpec {
SourceLoc PlatformAgnosticNameLoc;
llvm::VersionTuple Version;
SourceRange VersionSrcRange;
public:
PlatformAgnosticVersionConstraintAvailabilitySpec(
AvailabilitySpecKind AvailabilitySpecKind,
SourceLoc PlatformAgnosticNameLoc, llvm::VersionTuple Version,
SourceRange VersionSrcRange)
: AvailabilitySpec(AvailabilitySpecKind),
PlatformAgnosticNameLoc(PlatformAgnosticNameLoc), Version(Version),
VersionSrcRange(VersionSrcRange) {
assert(AvailabilitySpecKind == AvailabilitySpecKind::LanguageVersionConstraint ||
AvailabilitySpecKind == AvailabilitySpecKind::PackageDescriptionVersionConstraint);
}
SourceLoc getPlatformAgnosticNameLoc() const { return PlatformAgnosticNameLoc; }
// The platform version to compare against.
llvm::VersionTuple getVersion() const { return Version; }
SourceRange getVersionSrcRange() const { return VersionSrcRange; }
SourceRange getSourceRange() const;
bool isLanguageVersionSpecific() const {
return getKind() == AvailabilitySpecKind::LanguageVersionConstraint;
}
void print(raw_ostream &OS, unsigned Indent) const;
static bool classof(const AvailabilitySpec *Spec) {
return Spec->getKind() == AvailabilitySpecKind::LanguageVersionConstraint ||
Spec->getKind() == AvailabilitySpecKind::PackageDescriptionVersionConstraint;
}
void *
operator new(size_t Bytes, ASTContext &C,
unsigned Alignment = alignof(PlatformAgnosticVersionConstraintAvailabilitySpec)){
return AvailabilitySpec::operator new(Bytes, C, AllocationArena::Permanent,
Alignment);
}
};
/// A wildcard availability specification that guards execution
/// by checking that the run-time version is greater than the minimum
/// deployment target. This specification is designed to ease porting
/// to new platforms. Because new platforms typically branch from
/// existing platforms, the wildcard allows an #available() check to do the
/// "right" thing (executing the guarded branch) on the new platform without
/// requiring a modification to every availability guard in the program. Note
/// that we still do compile-time availability checking with '*', so the
/// compiler will still catch references to potentially unavailable symbols.
class OtherPlatformAvailabilitySpec : public AvailabilitySpec {
SourceLoc StarLoc;
public:
OtherPlatformAvailabilitySpec(SourceLoc StarLoc)
: AvailabilitySpec(AvailabilitySpecKind::OtherPlatform),
StarLoc(StarLoc) {}
SourceLoc getStarLoc() const { return StarLoc; }
SourceRange getSourceRange() const { return SourceRange(StarLoc, StarLoc); }
void print(raw_ostream &OS, unsigned Indent) const;
static bool classof(const AvailabilitySpec *Spec) {
return Spec->getKind() == AvailabilitySpecKind::OtherPlatform;
}
void *
operator new(size_t Bytes, ASTContext &C,
unsigned Alignment = alignof(OtherPlatformAvailabilitySpec)) {
return AvailabilitySpec::operator new(Bytes, C, AllocationArena::Permanent,
Alignment);
}
};
/// Maps of macro name and version to availability specifications.
/// Organized as two nested \c DenseMap keyed first on the macro name then
/// the macro version. This structure allows to peek at macro names before
/// parsing a version tuple.
class AvailabilityMacroMap {
public:
typedef llvm::DenseMap<llvm::VersionTuple,
SmallVector<AvailabilitySpec *, 4>> VersionEntry;
bool WasParsed = false;
llvm::DenseMap<StringRef, VersionEntry> Impl;
};
} // end namespace swift
#endif