blob: cb935a0380d5914535ec1d25687e06c27212192c [file] [log] [blame]
//===--- Decl.h - Swift Language Declaration ASTs ---------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 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 Decl class and subclasses.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_DECL_H
#define SWIFT_DECL_H
#include "swift/AST/AccessScope.h"
#include "swift/AST/Attr.h"
#include "swift/AST/CaptureInfo.h"
#include "swift/AST/ClangNode.h"
#include "swift/AST/ConcreteDeclRef.h"
#include "swift/AST/DefaultArgumentKind.h"
#include "swift/AST/DiagnosticConsumer.h"
#include "swift/AST/DiagnosticEngine.h"
#include "swift/AST/GenericParamKey.h"
#include "swift/AST/IfConfigClause.h"
#include "swift/AST/LayoutConstraint.h"
#include "swift/AST/StorageImpl.h"
#include "swift/AST/TypeAlignments.h"
#include "swift/AST/TypeWalker.h"
#include "swift/AST/Types.h"
#include "swift/AST/Witness.h"
#include "swift/Basic/ArrayRefView.h"
#include "swift/Basic/Compiler.h"
#include "swift/Basic/InlineBitfield.h"
#include "swift/Basic/NullablePtr.h"
#include "swift/Basic/OptionalEnum.h"
#include "swift/Basic/Range.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/Support/TrailingObjects.h"
#include <type_traits>
namespace swift {
enum class AccessSemantics : unsigned char;
class AccessorDecl;
class ApplyExpr;
class AvailabilityContext;
class GenericEnvironment;
class ArchetypeType;
class ASTContext;
struct ASTNode;
class ASTPrinter;
class ASTWalker;
class ConstructorDecl;
class DestructorDecl;
class DiagnosticEngine;
class DynamicSelfType;
class Type;
class Expr;
class DeclRefExpr;
class ForeignErrorConvention;
class LiteralExpr;
class BraceStmt;
class DeclAttributes;
class GenericContext;
class GenericSignature;
class GenericTypeParamDecl;
class GenericTypeParamType;
class ModuleDecl;
class EnumCaseDecl;
class EnumElementDecl;
class ParameterList;
class ParameterTypeFlags;
class Pattern;
struct PrintOptions;
struct PropertyWrapperBackingPropertyInfo;
struct PropertyWrapperTypeInfo;
struct PropertyWrapperMutability;
class ProtocolDecl;
class ProtocolType;
struct RawComment;
enum class ResilienceExpansion : unsigned;
class TypeAliasDecl;
class Stmt;
class SubscriptDecl;
class UnboundGenericType;
class ValueDecl;
class VarDecl;
class OpaqueReturnTypeRepr;
enum class DeclKind : uint8_t {
#define DECL(Id, Parent) Id,
#define LAST_DECL(Id) Last_Decl = Id,
#define DECL_RANGE(Id, FirstId, LastId) \
First_##Id##Decl = FirstId, Last_##Id##Decl = LastId,
#include "swift/AST/DeclNodes.def"
};
enum : unsigned { NumDeclKindBits =
countBitsUsed(static_cast<unsigned>(DeclKind::Last_Decl)) };
/// Fine-grained declaration kind that provides a description of the
/// kind of entity a declaration represents, as it would be used in
/// diagnostics.
///
/// For example, \c FuncDecl is a single declaration class, but it has
/// several descriptive entries depending on whether it is an
/// operator, global function, local function, method, (observing)
/// accessor, etc.
enum class DescriptiveDeclKind : uint8_t {
Import,
Extension,
EnumCase,
TopLevelCode,
IfConfig,
PoundDiagnostic,
PatternBinding,
Var,
Param,
Let,
Property,
StaticProperty,
ClassProperty,
InfixOperator,
PrefixOperator,
PostfixOperator,
PrecedenceGroup,
TypeAlias,
GenericTypeParam,
AssociatedType,
Type,
Enum,
Struct,
Class,
Protocol,
GenericEnum,
GenericStruct,
GenericClass,
GenericType,
Subscript,
StaticSubscript,
ClassSubscript,
Constructor,
Destructor,
LocalFunction,
GlobalFunction,
OperatorFunction,
Method,
StaticMethod,
ClassMethod,
Getter,
Setter,
Addressor,
MutableAddressor,
ReadAccessor,
ModifyAccessor,
WillSet,
DidSet,
EnumElement,
Module,
MissingMember,
Requirement,
OpaqueResultType,
OpaqueVarType
};
/// Keeps track of stage of circularity checking for the given protocol.
enum class CircularityCheck {
/// Circularity has not yet been checked.
Unchecked,
/// We're currently checking circularity.
Checking,
/// Circularity has already been checked.
Checked
};
/// Describes which spelling was used in the source for the 'static' or 'class'
/// keyword.
enum class StaticSpellingKind : uint8_t {
None,
KeywordStatic,
KeywordClass,
};
/// Keeps track of whether an enum has cases that have associated values.
enum class AssociatedValueCheck {
/// We have not yet checked.
Unchecked,
/// The enum contains no cases or all cases contain no associated values.
NoAssociatedValues,
/// The enum contains at least one case with associated values.
HasAssociatedValues,
};
/// Diagnostic printing of \c StaticSpellingKind.
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, StaticSpellingKind SSK);
/// Encapsulation of the overload signature of a given declaration,
/// which is used to determine uniqueness of a declaration within a
/// given context.
///
/// Two definitions in the same context may not have the same overload
/// signature.
struct OverloadSignature {
/// The full name of the declaration.
DeclName Name;
/// The kind of unary operator.
UnaryOperatorKind UnaryOperator;
/// Whether this is an instance member.
unsigned IsInstanceMember : 1;
/// Whether this is a variable.
unsigned IsVariable : 1;
/// Whether this is a function.
unsigned IsFunction : 1;
/// Whether this is a enum element.
unsigned IsEnumElement : 1;
/// Whether this is a nominal type.
unsigned IsNominal : 1;
/// Whether this is a type alias.
unsigned IsTypeAlias : 1;
/// Whether this signature is part of a protocol extension.
unsigned InProtocolExtension : 1;
/// Whether this signature is of a member defined in an extension of a generic
/// type.
unsigned InExtensionOfGenericType : 1;
/// Whether this declaration has an opaque return type.
unsigned HasOpaqueReturnType : 1;
OverloadSignature()
: UnaryOperator(UnaryOperatorKind::None), IsInstanceMember(false),
IsVariable(false), IsFunction(false), InProtocolExtension(false),
InExtensionOfGenericType(false), HasOpaqueReturnType(false) {}
};
/// Determine whether two overload signatures conflict.
///
/// \param sig1 The overload signature of the first declaration.
/// \param sig2 The overload signature of the second declaration.
/// \param skipProtocolExtensionCheck If \c true, members of protocol extensions
/// will be allowed to conflict with members of protocol declarations.
bool conflicting(const OverloadSignature& sig1, const OverloadSignature& sig2,
bool skipProtocolExtensionCheck = false);
/// Determine whether two overload signatures and overload types conflict.
///
/// \param ctx The AST context.
/// \param sig1 The overload signature of the first declaration.
/// \param sig1Type The overload type of the first declaration.
/// \param sig2 The overload signature of the second declaration.
/// \param sig2Type The overload type of the second declaration.
/// \param wouldConflictInSwift5 If non-null, the referenced boolean will be set
/// to \c true iff the function returns \c false for this version of
/// Swift, but the given overloads will conflict in Swift 5 mode.
/// \param skipProtocolExtensionCheck If \c true, members of protocol extensions
/// will be allowed to conflict with members of protocol declarations.
bool conflicting(ASTContext &ctx,
const OverloadSignature& sig1, CanType sig1Type,
const OverloadSignature& sig2, CanType sig2Type,
bool *wouldConflictInSwift5 = nullptr,
bool skipProtocolExtensionCheck = false);
/// Decl - Base class for all declarations in Swift.
class alignas(1 << DeclAlignInBits) Decl {
public:
enum class ValidationState {
Unchecked,
Checking,
Checked,
};
protected:
union { uint64_t OpaqueBits;
SWIFT_INLINE_BITFIELD_BASE(Decl, bitmax(NumDeclKindBits,8)+1+1+1+1+2+1,
Kind : bitmax(NumDeclKindBits,8),
/// Whether this declaration is invalid.
Invalid : 1,
/// Whether this declaration was implicitly created, e.g.,
/// an implicit constructor in a struct.
Implicit : 1,
/// Whether this declaration was mapped directly from a Clang AST.
///
/// Use getClangNode() to retrieve the corresponding Clang AST.
FromClang : 1,
/// The validation state of this declaration.
ValidationState : 2,
/// Whether this declaration was added to the surrounding
/// DeclContext of an active #if config clause.
EscapedFromIfConfig : 1
);
SWIFT_INLINE_BITFIELD_FULL(PatternBindingDecl, Decl, 1+2+16,
/// Whether this pattern binding declares static variables.
IsStatic : 1,
/// Whether 'static' or 'class' was used.
StaticSpelling : 2,
: NumPadBits,
/// The number of pattern binding declarations.
NumPatternEntries : 16
);
SWIFT_INLINE_BITFIELD_FULL(EnumCaseDecl, Decl, 32,
: NumPadBits,
/// The number of tail-allocated element pointers.
NumElements : 32
);
SWIFT_INLINE_BITFIELD(ValueDecl, Decl, 1+1+1,
AlreadyInLookupTable : 1,
/// Whether we have already checked whether this declaration is a
/// redeclaration.
CheckedRedeclaration : 1,
/// Whether the decl can be accessed by swift users; for instance,
/// a.storage for lazy var a is a decl that cannot be accessed.
IsUserAccessible : 1
);
SWIFT_INLINE_BITFIELD(AbstractStorageDecl, ValueDecl, 1,
/// Whether this property is a type property (currently unfortunately
/// called 'static').
IsStatic : 1
);
SWIFT_INLINE_BITFIELD(VarDecl, AbstractStorageDecl, 1+1+1+1+1+1,
/// Encodes whether this is a 'let' binding.
Introducer : 1,
/// Whether this declaration was an element of a capture list.
IsCaptureList : 1,
/// Whether this vardecl has an initial value bound to it in a way
/// that isn't represented in the AST with an initializer in the pattern
/// binding. This happens in cases like "for i in ...", switch cases, etc.
HasNonPatternBindingInit : 1,
/// Whether this is a property used in expressions in the debugger.
/// It is up to the debugger to instruct SIL how to access this variable.
IsDebuggerVar : 1,
/// Whether this is the backing storage for a lazy property.
IsLazyStorageProperty : 1,
/// Whether this is the backing storage for a property wrapper.
IsPropertyWrapperBackingProperty : 1
);
SWIFT_INLINE_BITFIELD(ParamDecl, VarDecl, 2+1+NumDefaultArgumentKindBits,
/// The specifier associated with this parameter. This determines
/// the storage semantics of the value e.g. mutability.
Specifier : 2,
/// True if the type is implicitly specified in the source, but this has an
/// apparently valid typeRepr. This is used in accessors, which look like:
/// set (value) {
/// but need to get the typeRepr from the property as a whole so Sema can
/// resolve the type.
IsTypeLocImplicit : 1,
/// Information about a symbolic default argument, like #file.
defaultArgumentKind : NumDefaultArgumentKindBits
);
SWIFT_INLINE_BITFIELD(SubscriptDecl, VarDecl, 2,
StaticSpelling : 2
);
SWIFT_INLINE_BITFIELD(AbstractFunctionDecl, ValueDecl, 3+8+1+1+1+1+1+1,
/// \see AbstractFunctionDecl::BodyKind
BodyKind : 3,
/// Import as member status.
IAMStatus : 8,
/// Whether the function has an implicit 'self' parameter.
HasImplicitSelfDecl : 1,
/// Whether we are overridden later.
Overridden : 1,
/// Whether the function body throws.
Throws : 1,
/// Whether this member was synthesized as part of a derived
/// protocol conformance.
Synthesized : 1,
/// Whether this member's body consists of a single expression.
HasSingleExpressionBody : 1
);
SWIFT_INLINE_BITFIELD(FuncDecl, AbstractFunctionDecl, 1+1+2+1+1+2,
/// Whether we've computed the 'static' flag yet.
IsStaticComputed : 1,
/// Whether this function is a 'static' method.
IsStatic : 1,
/// Whether 'static' or 'class' was used.
StaticSpelling : 2,
/// Whether we are statically dispatched even if overridable
ForcedStaticDispatch : 1,
/// Whether we've computed the 'self' access kind yet.
SelfAccessComputed : 1,
/// Backing bits for 'self' access kind.
SelfAccess : 2
);
SWIFT_INLINE_BITFIELD(AccessorDecl, FuncDecl, 4+1+1,
/// The kind of accessor this is.
AccessorKind : 4,
/// Whether the accessor is transparent.
IsTransparent : 1,
/// Whether we have computed the above.
IsTransparentComputed : 1
);
SWIFT_INLINE_BITFIELD(ConstructorDecl, AbstractFunctionDecl, 3+1+1,
/// The body initialization kind (+1), or zero if not yet computed.
///
/// This value is cached but is not serialized, because it is a property
/// of the definition of the constructor that is useful only to semantic
/// analysis and SIL generation.
ComputedBodyInitKind : 3,
/// Whether this constructor can fail, by building an Optional type.
Failable : 1,
/// Whether this initializer is a stub placed into a subclass to
/// catch invalid delegations to a designated initializer not
/// overridden by the subclass. A stub will always trap at runtime.
///
/// Initializer stubs can be invoked from Objective-C or through
/// the Objective-C runtime; there is no way to directly express
/// an object construction that will invoke a stub.
HasStubImplementation : 1
);
SWIFT_INLINE_BITFIELD_EMPTY(TypeDecl, ValueDecl);
SWIFT_INLINE_BITFIELD_EMPTY(AbstractTypeParamDecl, TypeDecl);
SWIFT_INLINE_BITFIELD_FULL(GenericTypeParamDecl, AbstractTypeParamDecl, 16+16,
: NumPadBits,
Depth : 16,
Index : 16
);
SWIFT_INLINE_BITFIELD_EMPTY(GenericTypeDecl, TypeDecl);
SWIFT_INLINE_BITFIELD(TypeAliasDecl, GenericTypeDecl, 1+1,
/// Whether the typealias forwards perfectly to its underlying type.
IsCompatibilityAlias : 1,
/// Whether this was a global typealias synthesized by the debugger.
IsDebuggerAlias : 1
);
SWIFT_INLINE_BITFIELD(NominalTypeDecl, GenericTypeDecl, 1+1,
/// Whether we have already added implicitly-defined initializers
/// to this declaration.
AddedImplicitInitializers : 1,
/// Whether there is are lazily-loaded conformances for this nominal type.
HasLazyConformances : 1
);
SWIFT_INLINE_BITFIELD_FULL(ProtocolDecl, NominalTypeDecl, 1+1+1+1+1+1+1+2+1+1+8+16,
/// Whether the \c RequiresClass bit is valid.
RequiresClassValid : 1,
/// Whether this is a class-bounded protocol.
RequiresClass : 1,
/// Whether the \c ExistentialConformsToSelf bit is valid.
ExistentialConformsToSelfValid : 1,
/// Whether the existential of this protocol conforms to itself.
ExistentialConformsToSelf : 1,
/// Whether the \c ExistentialTypeSupported bit is valid.
ExistentialTypeSupportedValid : 1,
/// Whether the existential of this protocol can be represented.
ExistentialTypeSupported : 1,
/// True if the protocol has requirements that cannot be satisfied (e.g.
/// because they could not be imported from Objective-C).
HasMissingRequirements : 1,
/// The stage of the circularity check for this protocol.
Circularity : 2,
/// Whether we've computed the inherited protocols list yet.
InheritedProtocolsValid : 1,
/// Whether we have a lazy-loaded requirement signature.
HasLazyRequirementSignature : 1,
: NumPadBits,
/// If this is a compiler-known protocol, this will be a KnownProtocolKind
/// value, plus one. Otherwise, it will be 0.
KnownProtocol : 8, // '8' for speed. This only needs 6.
/// The number of requirements in the requirement signature.
NumRequirementsInSignature : 16
);
SWIFT_INLINE_BITFIELD(ClassDecl, NominalTypeDecl, 2+1+2+1+7+1+1+1+1+1+1,
/// The stage of the inheritance circularity check for this class.
Circularity : 2,
/// Whether this class inherits its superclass's convenience initializers.
InheritsSuperclassInits : 1,
/// \see ClassDecl::ForeignKind
RawForeignKind : 2,
/// \see ClassDecl::getEmittedMembers()
HasForcedEmittedMembers : 1,
HasMissingDesignatedInitializers : 1,
ComputedHasMissingDesignatedInitializers : 1,
HasMissingVTableEntries : 1,
ComputedHasMissingVTableEntries : 1,
/// Whether instances of this class are incompatible
/// with weak and unowned references.
IsIncompatibleWithWeakReferences : 1
);
SWIFT_INLINE_BITFIELD(StructDecl, NominalTypeDecl, 1,
/// True if this struct has storage for fields that aren't accessible in
/// Swift.
HasUnreferenceableStorage : 1
);
SWIFT_INLINE_BITFIELD(EnumDecl, NominalTypeDecl, 2+2+1,
/// The stage of the raw type circularity check for this class.
Circularity : 2,
/// True if the enum has cases and at least one case has associated values.
HasAssociatedValues : 2,
/// True if the enum has at least one case that has some availability
/// attribute. A single bit because it's lazily computed along with the
/// HasAssociatedValues bit.
HasAnyUnavailableValues : 1
);
SWIFT_INLINE_BITFIELD(ModuleDecl, TypeDecl, 1+1+1+1+1+1+1+1,
/// If the module was or is being compiled with `-enable-testing`.
TestingEnabled : 1,
/// If the module failed to load
FailedToLoad : 1,
/// Whether the module is resilient.
///
/// \sa ResilienceStrategy
RawResilienceStrategy : 1,
/// Whether all imports have been resolved. Used to detect circular imports.
HasResolvedImports : 1,
/// If the module was or is being compiled with `-enable-private-imports`.
PrivateImportsEnabled : 1,
/// If the module is compiled with `-enable-implicit-dynamic`.
ImplicitDynamicEnabled : 1,
/// Whether the module is a system module.
IsSystemModule : 1,
/// Whether the module was imported from Clang (or, someday, maybe another
/// language).
IsNonSwiftModule : 1
);
SWIFT_INLINE_BITFIELD(PrecedenceGroupDecl, Decl, 1+2,
/// Is this an assignment operator?
IsAssignment : 1,
/// The group's associativity. A value of the Associativity enum.
Associativity : 2
);
SWIFT_INLINE_BITFIELD(ImportDecl, Decl, 3+8,
ImportKind : 3,
/// The number of elements in this path.
NumPathElements : 8
);
SWIFT_INLINE_BITFIELD(ExtensionDecl, Decl, 3+1,
/// An encoding of the default and maximum access level for this extension.
///
/// This is encoded as (1 << (maxAccess-1)) | (1 << (defaultAccess-1)),
/// which works because the maximum is always greater than or equal to the
/// default, and 'private' is never used. 0 represents an uncomputed value.
DefaultAndMaxAccessLevel : 3,
/// Whether there is are lazily-loaded conformances for this extension.
HasLazyConformances : 1
);
SWIFT_INLINE_BITFIELD(IfConfigDecl, Decl, 1,
/// Whether this decl is missing its closing '#endif'.
HadMissingEnd : 1
);
SWIFT_INLINE_BITFIELD(PoundDiagnosticDecl, Decl, 1+1,
/// `true` if the diagnostic is an error, `false` if it's a warning.
IsError : 1,
/// Whether this diagnostic has already been emitted.
HasBeenEmitted : 1
);
SWIFT_INLINE_BITFIELD(MissingMemberDecl, Decl, 1+2,
NumberOfFieldOffsetVectorEntries : 1,
NumberOfVTableEntries : 2
);
} Bits;
// Storage for the declaration attributes.
DeclAttributes Attrs;
/// The next declaration in the list of declarations within this
/// member context.
Decl *NextDecl = nullptr;
friend class DeclIterator;
friend class IterableDeclContext;
friend class MemberLookupTable;
private:
llvm::PointerUnion<DeclContext *, ASTContext *> Context;
Decl(const Decl&) = delete;
void operator=(const Decl&) = delete;
SourceLoc getLocFromSource() const;
protected:
Decl(DeclKind kind, llvm::PointerUnion<DeclContext *, ASTContext *> context)
: Context(context) {
Bits.OpaqueBits = 0;
Bits.Decl.Kind = unsigned(kind);
Bits.Decl.Invalid = false;
Bits.Decl.Implicit = false;
Bits.Decl.FromClang = false;
Bits.Decl.ValidationState = unsigned(ValidationState::Unchecked);
Bits.Decl.EscapedFromIfConfig = false;
}
/// Get the Clang node associated with this declaration.
ClangNode getClangNodeImpl() const;
/// Set the Clang node associated with this declaration.
void setClangNode(ClangNode Node);
void updateClangNode(ClangNode node) {
assert(hasClangNode());
setClangNode(node);
}
friend class ClangImporter;
DeclContext *getDeclContextForModule() const;
public:
DeclKind getKind() const { return DeclKind(Bits.Decl.Kind); }
/// Retrieve the name of the given declaration kind.
///
/// This name should only be used for debugging dumps and other
/// developer aids, and should never be part of a diagnostic or exposed
/// to the user of the compiler in any way.
static StringRef getKindName(DeclKind K);
/// Retrieve the descriptive kind for this declaration.
DescriptiveDeclKind getDescriptiveKind() const;
/// Produce a name for the given descriptive declaration kind, which
/// is suitable for use in diagnostics.
static StringRef getDescriptiveKindName(DescriptiveDeclKind K);
/// Whether swift users should be able to access this decl. For instance,
/// var a.storage for lazy var a is an inaccessible decl. An inaccessible decl
/// has to be implicit; but an implicit decl does not have to be inaccessible,
/// for instance, self.
bool isUserAccessible() const;
/// Determine if the decl can have a comment. If false, a comment will
/// not be serialized.
bool canHaveComment() const;
LLVM_READONLY
DeclContext *getDeclContext() const {
if (auto dc = Context.dyn_cast<DeclContext *>())
return dc;
return getDeclContextForModule();
}
void setDeclContext(DeclContext *DC);
/// Retrieve the innermost declaration context corresponding to this
/// declaration, which will either be the declaration itself (if it's
/// also a declaration context) or its declaration context.
DeclContext *getInnermostDeclContext() const;
/// Retrieve the module in which this declaration resides.
LLVM_READONLY
ModuleDecl *getModuleContext() const;
/// getASTContext - Return the ASTContext that this decl lives in.
LLVM_READONLY
ASTContext &getASTContext() const {
if (auto dc = Context.dyn_cast<DeclContext *>())
return dc->getASTContext();
return *Context.get<ASTContext *>();
}
const DeclAttributes &getAttrs() const {
return Attrs;
}
DeclAttributes &getAttrs() {
return Attrs;
}
/// Returns the starting location of the entire declaration.
SourceLoc getStartLoc() const { return getSourceRange().Start; }
/// Returns the end location of the entire declaration.
SourceLoc getEndLoc() const { return getSourceRange().End; }
/// Returns the preferred location when referring to declarations
/// in diagnostics.
SourceLoc getLoc() const;
/// Returns the source range of the entire declaration.
SourceRange getSourceRange() const;
/// Returns the source range of the declaration including its attributes.
SourceRange getSourceRangeIncludingAttrs() const;
SourceLoc TrailingSemiLoc;
LLVM_ATTRIBUTE_DEPRECATED(
void dump() const LLVM_ATTRIBUTE_USED,
"only for use within the debugger");
LLVM_ATTRIBUTE_DEPRECATED(
void dump(const char *filename) const LLVM_ATTRIBUTE_USED,
"only for use within the debugger");
void dump(raw_ostream &OS, unsigned Indent = 0) const;
/// Pretty-print the given declaration.
///
/// \param OS Output stream to which the declaration will be printed.
void print(raw_ostream &OS) const;
void print(raw_ostream &OS, const PrintOptions &Opts) const;
/// Pretty-print the given declaration.
///
/// \param Printer ASTPrinter object.
///
/// \param Opts Options to control how pretty-printing is performed.
///
/// \returns true if the declaration was printed or false if the print options
/// required the declaration to be skipped from printing.
bool print(ASTPrinter &Printer, const PrintOptions &Opts) const;
/// Determine whether this declaration should be printed when
/// encountered in its declaration context's list of members.
bool shouldPrintInContext(const PrintOptions &PO) const;
bool walk(ASTWalker &walker);
/// Return whether this declaration has been determined invalid.
bool isInvalid() const { return Bits.Decl.Invalid; }
/// Mark this declaration invalid.
void setInvalid(bool isInvalid = true) { Bits.Decl.Invalid = isInvalid; }
/// Determine whether this declaration was implicitly generated by the
/// compiler (rather than explicitly written in source code).
bool isImplicit() const { return Bits.Decl.Implicit; }
/// Mark this declaration as implicit.
void setImplicit(bool implicit = true) { Bits.Decl.Implicit = implicit; }
/// Get the validation state.
ValidationState getValidationState() const {
return ValidationState(Bits.Decl.ValidationState);
}
private:
friend class DeclValidationRAII;
/// Set the validation state.
void setValidationState(ValidationState VS) {
assert(VS > getValidationState() && "Validation is unidirectional");
Bits.Decl.ValidationState = unsigned(VS);
}
public:
/// Whether the declaration is in the middle of validation or not.
bool isBeingValidated() const {
switch (getValidationState()) {
case ValidationState::Unchecked:
case ValidationState::Checked:
return false;
case ValidationState::Checking:
return true;
}
llvm_unreachable("Unknown ValidationState");
}
bool hasValidationStarted() const {
return getValidationState() > ValidationState::Unchecked;
}
bool escapedFromIfConfig() const {
return Bits.Decl.EscapedFromIfConfig;
}
void setEscapedFromIfConfig(bool Escaped) {
Bits.Decl.EscapedFromIfConfig = Escaped;
}
/// \returns the unparsed comment attached to this declaration.
RawComment getRawComment() const;
Optional<StringRef> getGroupName() const;
Optional<StringRef> getSourceFileName() const;
Optional<unsigned> getSourceOrder() const;
/// \returns the brief comment attached to this declaration.
StringRef getBriefComment() const;
/// Returns true if there is a Clang AST node associated
/// with self.
bool hasClangNode() const {
return Bits.Decl.FromClang;
}
/// Retrieve the Clang AST node from which this declaration was
/// synthesized, if any.
LLVM_READONLY
ClangNode getClangNode() const {
if (!Bits.Decl.FromClang)
return ClangNode();
return getClangNodeImpl();
}
/// Retrieve the Clang declaration from which this declaration was
/// synthesized, if any.
LLVM_READONLY
const clang::Decl *getClangDecl() const {
if (!Bits.Decl.FromClang)
return nullptr;
return getClangNodeImpl().getAsDecl();
}
/// Retrieve the Clang macro from which this declaration was
/// synthesized, if any.
LLVM_READONLY
const clang::MacroInfo *getClangMacro() {
if (!Bits.Decl.FromClang)
return nullptr;
return getClangNodeImpl().getAsMacro();
}
/// Return the GenericContext if the Decl has one.
LLVM_READONLY
const GenericContext *getAsGenericContext() const;
bool isPrivateStdlibDecl(bool treatNonBuiltinProtocolsAsPublic = true) const;
AvailabilityContext getAvailabilityForLinkage() const;
/// Whether this declaration or one of its outer contexts has the
/// @_weakLinked attribute.
bool isAlwaysWeakImported() const;
/// Whether this declaration is weak-imported from the given module,
/// either because of the presence of the @_weakLinked attribute, or
/// because of availability.
///
/// Note that \p fromModule should either be the "main module" or
/// nullptr. (This is because when it is non-null, we query the
/// current deployment target, and not the deployment target that
/// the module was built with.)
///
/// If \p fromModule is the main module, this returns false when the
/// declaration is part of the main module, or if the declaration is
/// at least as available as the current deployment target.
///
/// If \p fromModule is null, we instead return true if the
/// declaration is meant to be weak linked with _some_ deployment
/// target; that is, the presence of the @_weakLinked attribute or
/// any kind of availability is enough, irrespective of the current
/// deployment target.
bool isWeakImported(ModuleDecl *fromModule) const;
/// Returns true if the nature of this declaration allows overrides.
/// Note that this does not consider whether it is final or whether
/// the class it's on is final.
///
/// If this returns true, the decl can be safely casted to ValueDecl.
bool isPotentiallyOverridable() const;
/// Emit a diagnostic tied to this declaration.
template<typename ...ArgTypes>
InFlightDiagnostic diagnose(
Diag<ArgTypes...> ID,
typename detail::PassArgument<ArgTypes>::type... Args) const {
return getDiags().diagnose(this, ID, std::move(Args)...);
}
/// Retrieve the diagnostic engine for diagnostics emission.
LLVM_READONLY
DiagnosticEngine &getDiags() const;
// Make vanilla new/delete illegal for Decls.
void *operator new(size_t Bytes) = delete;
void operator delete(void *Data) SWIFT_DELETE_OPERATOR_DELETED;
// Only allow allocation of Decls using the allocator in ASTContext
// or by doing a placement new.
void *operator new(size_t Bytes, const ASTContext &C,
unsigned Alignment = alignof(Decl));
void *operator new(size_t Bytes, void *Mem) {
assert(Mem);
return Mem;
}
};
/// Use RAII to track Decl validation progress and non-reentrancy.
class DeclValidationRAII {
Decl *D;
public:
DeclValidationRAII(const DeclValidationRAII &) = delete;
DeclValidationRAII(DeclValidationRAII &&) = delete;
void operator =(const DeclValidationRAII &) = delete;
void operator =(DeclValidationRAII &&) = delete;
DeclValidationRAII(Decl *decl) : D(decl) {
D->setValidationState(Decl::ValidationState::Checking);
}
~DeclValidationRAII() {
D->setValidationState(Decl::ValidationState::Checked);
}
};
/// Allocates memory for a Decl with the given \p baseSize. If necessary,
/// it includes additional space immediately preceding the Decl for a ClangNode.
/// \note \p baseSize does not need to include space for a ClangNode if
/// requested -- the necessary space will be added automatically.
template <typename DeclTy, typename AllocatorTy>
void *allocateMemoryForDecl(AllocatorTy &allocator, size_t baseSize,
bool includeSpaceForClangNode) {
static_assert(alignof(DeclTy) >= sizeof(void *),
"A pointer must fit in the alignment of the DeclTy!");
size_t size = baseSize;
if (includeSpaceForClangNode)
size += alignof(DeclTy);
void *mem = allocator.Allocate(size, alignof(DeclTy));
if (includeSpaceForClangNode)
mem = reinterpret_cast<char *>(mem) + alignof(DeclTy);
return mem;
}
enum class RequirementReprKind : unsigned {
/// A type bound T : P, where T is a type that depends on a generic
/// parameter and P is some type that should bound T, either as a concrete
/// supertype or a protocol to which T must conform.
TypeConstraint,
/// A same-type requirement T == U, where T and U are types that shall be
/// equivalent.
SameType,
/// A layout bound T : L, where T is a type that depends on a generic
/// parameter and L is some layout specification that should bound T.
LayoutConstraint,
// Note: there is code that packs this enum in a 2-bit bitfield. Audit users
// when adding enumerators.
};
/// A single requirement in a 'where' clause, which places additional
/// restrictions on the generic parameters or associated types of a generic
/// function, type, or protocol.
///
/// This always represents a requirement spelled in the source code. It is
/// never generated implicitly.
///
/// \c GenericParamList assumes these are POD-like.
class RequirementRepr {
SourceLoc SeparatorLoc;
RequirementReprKind Kind : 2;
bool Invalid : 1;
TypeLoc FirstType;
/// The second element represents the right-hand side of the constraint.
/// It can be e.g. a type or a layout constraint.
union {
TypeLoc SecondType;
LayoutConstraintLoc SecondLayout;
};
/// Set during deserialization; used to print out the requirements accurately
/// for the generated interface.
StringRef AsWrittenString;
RequirementRepr(SourceLoc SeparatorLoc, RequirementReprKind Kind,
TypeLoc FirstType, TypeLoc SecondType)
: SeparatorLoc(SeparatorLoc), Kind(Kind), Invalid(false),
FirstType(FirstType), SecondType(SecondType) { }
RequirementRepr(SourceLoc SeparatorLoc, RequirementReprKind Kind,
TypeLoc FirstType, LayoutConstraintLoc SecondLayout)
: SeparatorLoc(SeparatorLoc), Kind(Kind), Invalid(false),
FirstType(FirstType), SecondLayout(SecondLayout) { }
void printImpl(ASTPrinter &OS, bool AsWritten) const;
public:
/// Construct a new type-constraint requirement.
///
/// \param Subject The type that must conform to the given protocol or
/// composition, or be a subclass of the given class type.
/// \param ColonLoc The location of the ':', or an invalid location if
/// this requirement was implied.
/// \param Constraint The protocol or protocol composition to which the
/// subject must conform, or superclass from which the subject must inherit.
static RequirementRepr getTypeConstraint(TypeLoc Subject,
SourceLoc ColonLoc,
TypeLoc Constraint) {
return { ColonLoc, RequirementReprKind::TypeConstraint, Subject, Constraint };
}
/// Construct a new same-type requirement.
///
/// \param FirstType The first type.
/// \param EqualLoc The location of the '==' in the same-type constraint, or
/// an invalid location if this requirement was implied.
/// \param SecondType The second type.
static RequirementRepr getSameType(TypeLoc FirstType,
SourceLoc EqualLoc,
TypeLoc SecondType) {
return { EqualLoc, RequirementReprKind::SameType, FirstType, SecondType };
}
/// Construct a new layout-constraint requirement.
///
/// \param Subject The type that must conform to the given layout
/// requirement.
/// \param ColonLoc The location of the ':', or an invalid location if
/// this requirement was implied.
/// \param Layout The layout requirement to which the
/// subject must conform.
static RequirementRepr getLayoutConstraint(TypeLoc Subject,
SourceLoc ColonLoc,
LayoutConstraintLoc Layout) {
return {ColonLoc, RequirementReprKind::LayoutConstraint, Subject,
Layout};
}
/// Determine the kind of requirement
RequirementReprKind getKind() const { return Kind; }
/// Determine whether this requirement is invalid.
bool isInvalid() const { return Invalid; }
/// Mark this requirement invalid.
void setInvalid() { Invalid = true; }
/// For a type-bound requirement, return the subject of the
/// conformance relationship.
Type getSubject() const {
assert(getKind() == RequirementReprKind::TypeConstraint ||
getKind() == RequirementReprKind::LayoutConstraint);
return FirstType.getType();
}
TypeRepr *getSubjectRepr() const {
assert(getKind() == RequirementReprKind::TypeConstraint ||
getKind() == RequirementReprKind::LayoutConstraint);
return FirstType.getTypeRepr();
}
TypeLoc &getSubjectLoc() {
assert(getKind() == RequirementReprKind::TypeConstraint ||
getKind() == RequirementReprKind::LayoutConstraint);
return FirstType;
}
const TypeLoc &getSubjectLoc() const {
assert(getKind() == RequirementReprKind::TypeConstraint ||
getKind() == RequirementReprKind::LayoutConstraint);
return FirstType;
}
/// For a type-bound requirement, return the protocol or to which
/// the subject conforms or superclass it inherits.
Type getConstraint() const {
assert(getKind() == RequirementReprKind::TypeConstraint);
return SecondType.getType();
}
TypeRepr *getConstraintRepr() const {
assert(getKind() == RequirementReprKind::TypeConstraint);
return SecondType.getTypeRepr();
}
TypeLoc &getConstraintLoc() {
assert(getKind() == RequirementReprKind::TypeConstraint);
return SecondType;
}
const TypeLoc &getConstraintLoc() const {
assert(getKind() == RequirementReprKind::TypeConstraint);
return SecondType;
}
LayoutConstraint getLayoutConstraint() const {
assert(getKind() == RequirementReprKind::LayoutConstraint);
return SecondLayout.getLayoutConstraint();
}
LayoutConstraintLoc &getLayoutConstraintLoc() {
assert(getKind() == RequirementReprKind::LayoutConstraint);
return SecondLayout;
}
const LayoutConstraintLoc &getLayoutConstraintLoc() const {
assert(getKind() == RequirementReprKind::LayoutConstraint);
return SecondLayout;
}
/// Retrieve the first type of a same-type requirement.
Type getFirstType() const {
assert(getKind() == RequirementReprKind::SameType);
return FirstType.getType();
}
TypeRepr *getFirstTypeRepr() const {
assert(getKind() == RequirementReprKind::SameType);
return FirstType.getTypeRepr();
}
TypeLoc &getFirstTypeLoc() {
assert(getKind() == RequirementReprKind::SameType);
return FirstType;
}
const TypeLoc &getFirstTypeLoc() const {
assert(getKind() == RequirementReprKind::SameType);
return FirstType;
}
/// Retrieve the second type of a same-type requirement.
Type getSecondType() const {
assert(getKind() == RequirementReprKind::SameType);
return SecondType.getType();
}
TypeRepr *getSecondTypeRepr() const {
assert(getKind() == RequirementReprKind::SameType);
return SecondType.getTypeRepr();
}
TypeLoc &getSecondTypeLoc() {
assert(getKind() == RequirementReprKind::SameType);
return SecondType;
}
const TypeLoc &getSecondTypeLoc() const {
assert(getKind() == RequirementReprKind::SameType);
return SecondType;
}
/// Retrieve the location of the ':' or '==' in an explicitly-written
/// conformance or same-type requirement respectively.
SourceLoc getSeparatorLoc() const {
return SeparatorLoc;
}
SourceRange getSourceRange() const {
if (getKind() == RequirementReprKind::LayoutConstraint)
return SourceRange(FirstType.getSourceRange().Start,
SecondLayout.getSourceRange().End);
return SourceRange(FirstType.getSourceRange().Start,
SecondType.getSourceRange().End);
}
/// Retrieve the first or subject type representation from the \c repr,
/// or \c nullptr if \c repr is null.
static TypeRepr *getFirstTypeRepr(const RequirementRepr *repr) {
if (!repr) return nullptr;
return repr->FirstType.getTypeRepr();
}
/// Retrieve the second or constraint type representation from the \c repr,
/// or \c nullptr if \c repr is null.
static TypeRepr *getSecondTypeRepr(const RequirementRepr *repr) {
if (!repr) return nullptr;
assert(repr->getKind() == RequirementReprKind::TypeConstraint ||
repr->getKind() == RequirementReprKind::SameType);
return repr->SecondType.getTypeRepr();
}
LLVM_ATTRIBUTE_DEPRECATED(
void dump() const LLVM_ATTRIBUTE_USED,
"only for use within the debugger");
void print(raw_ostream &OS) const;
void print(ASTPrinter &Printer) const;
};
/// GenericParamList - A list of generic parameters that is part of a generic
/// function or type, along with extra requirements placed on those generic
/// parameters and types derived from them.
class GenericParamList final :
private llvm::TrailingObjects<GenericParamList, GenericTypeParamDecl *> {
friend TrailingObjects;
SourceRange Brackets;
unsigned NumParams;
SourceLoc WhereLoc;
MutableArrayRef<RequirementRepr> Requirements;
GenericParamList *OuterParameters;
SourceLoc TrailingWhereLoc;
unsigned FirstTrailingWhereArg;
GenericParamList(SourceLoc LAngleLoc,
ArrayRef<GenericTypeParamDecl *> Params,
SourceLoc WhereLoc,
MutableArrayRef<RequirementRepr> Requirements,
SourceLoc RAngleLoc);
// Don't copy.
GenericParamList(const GenericParamList &) = delete;
GenericParamList &operator=(const GenericParamList &) = delete;
public:
/// create - Create a new generic parameter list within the given AST context.
///
/// \param Context The ASTContext in which the generic parameter list will
/// be allocated.
/// \param LAngleLoc The location of the opening angle bracket ('<')
/// \param Params The list of generic parameters, which will be copied into
/// ASTContext-allocated memory.
/// \param RAngleLoc The location of the closing angle bracket ('>')
static GenericParamList *create(ASTContext &Context,
SourceLoc LAngleLoc,
ArrayRef<GenericTypeParamDecl *> Params,
SourceLoc RAngleLoc);
/// create - Create a new generic parameter list and "where" clause within
/// the given AST context.
///
/// \param Context The ASTContext in which the generic parameter list will
/// be allocated.
/// \param LAngleLoc The location of the opening angle bracket ('<')
/// \param Params The list of generic parameters, which will be copied into
/// ASTContext-allocated memory.
/// \param WhereLoc The location of the 'where' keyword, if any.
/// \param Requirements The list of requirements, which will be copied into
/// ASTContext-allocated memory.
/// \param RAngleLoc The location of the closing angle bracket ('>')
static GenericParamList *create(const ASTContext &Context,
SourceLoc LAngleLoc,
ArrayRef<GenericTypeParamDecl *> Params,
SourceLoc WhereLoc,
ArrayRef<RequirementRepr> Requirements,
SourceLoc RAngleLoc);
MutableArrayRef<GenericTypeParamDecl *> getParams() {
return {getTrailingObjects<GenericTypeParamDecl *>(), NumParams};
}
ArrayRef<GenericTypeParamDecl *> getParams() const {
return {getTrailingObjects<GenericTypeParamDecl *>(), NumParams};
}
using iterator = GenericTypeParamDecl **;
using const_iterator = const GenericTypeParamDecl * const *;
unsigned size() const { return NumParams; }
iterator begin() { return getParams().begin(); }
iterator end() { return getParams().end(); }
const_iterator begin() const { return getParams().begin(); }
const_iterator end() const { return getParams().end(); }
/// Retrieve the location of the 'where' keyword, or an invalid
/// location if 'where' was not present.
SourceLoc getWhereLoc() const { return WhereLoc; }
/// Retrieve the set of additional requirements placed on these
/// generic parameters and types derived from them.
///
/// This list may contain both explicitly-written requirements as well as
/// implicitly-generated requirements, and may be non-empty even if no
/// 'where' keyword is present.
MutableArrayRef<RequirementRepr> getRequirements() { return Requirements; }
/// Retrieve the set of additional requirements placed on these
/// generic parameters and types derived from them.
///
/// This list may contain both explicitly-written requirements as well as
/// implicitly-generated requirements, and may be non-empty even if no
/// 'where' keyword is present.
ArrayRef<RequirementRepr> getRequirements() const { return Requirements; }
/// Retrieve only those requirements that are written within the brackets,
/// which does not include any requirements written in a trailing where
/// clause.
ArrayRef<RequirementRepr> getNonTrailingRequirements() const {
return Requirements.slice(0, FirstTrailingWhereArg);
}
/// Retrieve only those requirements written in a trailing where
/// clause.
ArrayRef<RequirementRepr> getTrailingRequirements() const {
return Requirements.slice(FirstTrailingWhereArg);
}
/// Determine whether the generic parameters have a trailing where clause.
bool hasTrailingWhereClause() const {
return FirstTrailingWhereArg < Requirements.size();
}
/// Add a trailing 'where' clause to the list of requirements.
///
/// Trailing where clauses are written outside the angle brackets, after the
/// main part of a declaration's signature.
void addTrailingWhereClause(ASTContext &ctx, SourceLoc trailingWhereLoc,
ArrayRef<RequirementRepr> trailingRequirements);
/// Retrieve the outer generic parameter list.
///
/// This is used for extensions of nested types, and in SIL mode, where a
/// single lexical context can have multiple logical generic parameter
/// lists.
GenericParamList *getOuterParameters() const { return OuterParameters; }
/// Set the outer generic parameter list. See \c getOuterParameters
/// for more information.
void setOuterParameters(GenericParamList *Outer) { OuterParameters = Outer; }
SourceLoc getLAngleLoc() const { return Brackets.Start; }
SourceLoc getRAngleLoc() const { return Brackets.End; }
SourceRange getSourceRange() const { return Brackets; }
/// Retrieve the source range covering the where clause.
SourceRange getWhereClauseSourceRange() const {
if (WhereLoc.isInvalid())
return SourceRange();
auto endLoc = Requirements[FirstTrailingWhereArg-1].getSourceRange().End;
return SourceRange(WhereLoc, endLoc);
}
/// Retrieve the source range covering the trailing where clause.
SourceRange getTrailingWhereClauseSourceRange() const {
if (!hasTrailingWhereClause())
return SourceRange();
return SourceRange(TrailingWhereLoc,
Requirements.back().getSourceRange().End);
}
/// Configure the depth of the generic parameters in this list.
void setDepth(unsigned depth);
/// Create a copy of the generic parameter list and all of its generic
/// parameter declarations. The copied generic parameters are re-parented
/// to the given DeclContext.
GenericParamList *clone(DeclContext *dc) const;
void print(raw_ostream &OS) const;
void dump();
};
/// A trailing where clause.
class alignas(RequirementRepr) TrailingWhereClause final :
private llvm::TrailingObjects<TrailingWhereClause, RequirementRepr> {
friend TrailingObjects;
SourceLoc WhereLoc;
/// The number of requirements. The actual requirements are tail-allocated.
unsigned NumRequirements;
TrailingWhereClause(SourceLoc whereLoc,
ArrayRef<RequirementRepr> requirements);
public:
/// Create a new trailing where clause with the given set of requirements.
static TrailingWhereClause *create(ASTContext &ctx, SourceLoc whereLoc,
ArrayRef<RequirementRepr> requirements);
/// Retrieve the location of the 'where' keyword.
SourceLoc getWhereLoc() const { return WhereLoc; }
/// Retrieve the set of requirements.
MutableArrayRef<RequirementRepr> getRequirements() {
return {getTrailingObjects<RequirementRepr>(), NumRequirements};
}
/// Retrieve the set of requirements.
ArrayRef<RequirementRepr> getRequirements() const {
return {getTrailingObjects<RequirementRepr>(), NumRequirements};
}
/// Compute the source range containing this trailing where clause.
SourceRange getSourceRange() const {
return SourceRange(WhereLoc,
getRequirements().back().getSourceRange().End);
}
};
// A private class for forcing exact field layout.
class alignas(8) _GenericContext {
// Not really public. See GenericContext.
public:
llvm::PointerIntPair<GenericParamList *, 1, bool> GenericParamsAndBit;
/// The trailing where clause.
///
/// Note that this is not currently serialized, because semantic analysis
/// moves the trailing where clause into the generic parameter list.
TrailingWhereClause *TrailingWhere = nullptr;
/// The generic signature of this declaration.
llvm::PointerIntPair<GenericSignature, 1, bool> GenericSigAndBit;
};
class GenericContext : private _GenericContext, public DeclContext {
friend class GenericParamListRequest;
friend class GenericSignatureRequest;
protected:
GenericContext(DeclContextKind Kind, DeclContext *Parent,
GenericParamList *Params);
public:
/// Retrieve the set of parameters to a generic context, or null if
/// this context is not generic.
GenericParamList *getGenericParams() const;
/// Determine whether this context has generic parameters
/// of its own.
///
/// \code
/// class C<T> {
/// func f1() {} // isGeneric == false
/// func f2<T>() {} // isGeneric == true
/// }
///
/// protocol P { // isGeneric == true due to implicit Self param
/// func p() // isGeneric == false
/// }
/// \endcode
bool isGeneric() const { return getGenericParams() != nullptr; }
bool hasComputedGenericSignature() const;
bool isComputingGenericSignature() const;
/// Retrieve the trailing where clause for this extension, if any.
TrailingWhereClause *getTrailingWhereClause() const {
return TrailingWhere;
}
/// Set the trailing where clause for this extension.
void setTrailingWhereClause(TrailingWhereClause *trailingWhereClause) {
TrailingWhere = trailingWhereClause;
}
/// Retrieve the generic signature for this context.
GenericSignature getGenericSignature() const;
/// Retrieve the generic context for this context.
GenericEnvironment *getGenericEnvironment() const;
/// Retrieve the innermost generic parameter types.
TypeArrayView<GenericTypeParamType> getInnermostGenericParamTypes() const;
/// Retrieve the generic requirements.
ArrayRef<Requirement> getGenericRequirements() const;
/// Set the generic signature of this context.
void setGenericSignature(GenericSignature genericSig);
/// Retrieve the position of any where clause for this context's
/// generic parameters.
SourceRange getGenericTrailingWhereClauseSourceRange() const;
};
static_assert(sizeof(_GenericContext) + sizeof(DeclContext) ==
sizeof(GenericContext), "Please add fields to _GenericContext");
/// Describes what kind of name is being imported.
///
/// If the enumerators here are changed, make sure to update all diagnostics
/// using ImportKind as a select index.
enum class ImportKind : uint8_t {
Module = 0,
Type,
Struct,
Class,
Enum,
Protocol,
Var,
Func
};
/// ImportDecl - This represents a single import declaration, e.g.:
/// import Swift
/// import typealias Swift.Int
class ImportDecl final : public Decl,
private llvm::TrailingObjects<ImportDecl, std::pair<Identifier,SourceLoc>> {
friend TrailingObjects;
friend class Decl;
public:
typedef std::pair<Identifier, SourceLoc> AccessPathElement;
private:
SourceLoc ImportLoc;
SourceLoc KindLoc;
/// The resolved module.
ModuleDecl *Mod = nullptr;
/// The resolved decls if this is a decl import.
ArrayRef<ValueDecl *> Decls;
ImportDecl(DeclContext *DC, SourceLoc ImportLoc, ImportKind K,
SourceLoc KindLoc, ArrayRef<AccessPathElement> Path);
public:
static ImportDecl *create(ASTContext &C, DeclContext *DC,
SourceLoc ImportLoc, ImportKind Kind,
SourceLoc KindLoc,
ArrayRef<AccessPathElement> Path,
ClangNode ClangN = ClangNode());
/// Returns the import kind that is most appropriate for \p VD.
///
/// Note that this will never return \c Type; an imported typealias will use
/// the more specific kind from its underlying type.
static ImportKind getBestImportKind(const ValueDecl *VD);
/// Returns the most appropriate import kind for the given list of decls.
///
/// If the list is non-homogeneous, or if there is more than one decl that
/// cannot be overloaded, returns None.
static Optional<ImportKind> findBestImportKind(ArrayRef<ValueDecl *> Decls);
ArrayRef<AccessPathElement> getFullAccessPath() const {
return {getTrailingObjects<AccessPathElement>(),
static_cast<size_t>(Bits.ImportDecl.NumPathElements)};
}
ArrayRef<AccessPathElement> getModulePath() const {
auto result = getFullAccessPath();
if (getImportKind() != ImportKind::Module)
result = result.slice(0, result.size()-1);
return result;
}
ArrayRef<AccessPathElement> getDeclPath() const {
if (getImportKind() == ImportKind::Module)
return {};
return getFullAccessPath().back();
}
ImportKind getImportKind() const {
return static_cast<ImportKind>(Bits.ImportDecl.ImportKind);
}
bool isExported() const {
return getAttrs().hasAttribute<ExportedAttr>();
}
ModuleDecl *getModule() const { return Mod; }
void setModule(ModuleDecl *M) { Mod = M; }
ArrayRef<ValueDecl *> getDecls() const { return Decls; }
void setDecls(ArrayRef<ValueDecl *> Ds) { Decls = Ds; }
const clang::Module *getClangModule() const {
return getClangNode().getClangModule();
}
SourceLoc getStartLoc() const { return ImportLoc; }
SourceLoc getLocFromSource() const { return getFullAccessPath().front().second; }
SourceRange getSourceRange() const {
return SourceRange(ImportLoc, getFullAccessPath().back().second);
}
SourceLoc getKindLoc() const { return KindLoc; }
static bool classof(const Decl *D) {
return D->getKind() == DeclKind::Import;
}
};
/// ExtensionDecl - This represents a type extension containing methods
/// associated with the type. This is not a ValueDecl and has no Type because
/// there are no runtime values of the Extension's type.
class ExtensionDecl final : public GenericContext, public Decl,
public IterableDeclContext {
SourceLoc ExtensionLoc; // Location of 'extension' keyword.
SourceRange Braces;
/// The type being extended.
TypeRepr *ExtendedTypeRepr;
/// The nominal type being extended.
///
/// The bit indicates whether binding has been attempted. The pointer can be
/// null if either no binding was attempted or if binding could not find the
/// extended nominal.
llvm::PointerIntPair<NominalTypeDecl *, 1, bool> ExtendedNominal;
MutableArrayRef<TypeLoc> Inherited;
/// The next extension in the linked list of extensions.
///
/// The bit indicates whether this extension has been resolved to refer to
/// a known nominal type.
llvm::PointerIntPair<ExtensionDecl *, 1, bool> NextExtension
= {nullptr, false};
/// Note that we have added a member into the iterable declaration context.
void addedMember(Decl *member);
friend class ExtensionIterator;
friend class NominalTypeDecl;
friend class MemberLookupTable;
friend class ConformanceLookupTable;
friend class IterableDeclContext;
ExtensionDecl(SourceLoc extensionLoc, TypeRepr *extendedType,
MutableArrayRef<TypeLoc> inherited,
DeclContext *parent,
TrailingWhereClause *trailingWhereClause);
/// Retrieve the conformance loader (if any), and removing it in the
/// same operation. The caller is responsible for loading the
/// conformances.
std::pair<LazyMemberLoader *, uint64_t> takeConformanceLoader() {
if (!Bits.ExtensionDecl.HasLazyConformances)
return { nullptr, 0 };
return takeConformanceLoaderSlow();
}
/// Slow path for \c takeConformanceLoader().
std::pair<LazyMemberLoader *, uint64_t> takeConformanceLoaderSlow();
friend class ExtendedNominalRequest;
friend class Decl;
public:
using Decl::getASTContext;
/// Create a new extension declaration.
static ExtensionDecl *create(ASTContext &ctx, SourceLoc extensionLoc,
TypeRepr *extendedType,
MutableArrayRef<TypeLoc> inherited,
DeclContext *parent,
TrailingWhereClause *trailingWhereClause,
ClangNode clangNode = ClangNode());
SourceLoc getStartLoc() const { return ExtensionLoc; }
SourceLoc getLocFromSource() const { return ExtensionLoc; }
SourceRange getSourceRange() const {
return { ExtensionLoc, Braces.End };
}
SourceRange getBraces() const { return Braces; }
void setBraces(SourceRange braces) { Braces = braces; }
bool hasBeenBound() const { return ExtendedNominal.getInt(); }
void setExtendedNominal(NominalTypeDecl *n) {
ExtendedNominal.setPointerAndInt(n, true);
}
/// Retrieve the type being extended.
///
/// Only use this entry point when the complete type, as spelled in the source,
/// is required. For most clients, \c getExtendedNominal(), which provides
/// only the \c NominalTypeDecl, will suffice.
Type getExtendedType() const;
/// Retrieve the nominal type declaration that is being extended.
/// Will trip an assertion if the declaration has not already been computed.
/// In order to fail fast when type checking work is attempted
/// before extension binding has taken place.
NominalTypeDecl *getExtendedNominal() const;
/// Compute the nominal type declaration that is being extended.
NominalTypeDecl *computeExtendedNominal() const;
/// \c hasBeenBound means nothing if this extension can never been bound
/// because it is not at the top level.
bool canNeverBeBound() const;
bool hasValidParent() const;
/// Determine whether this extension has already been bound to a nominal
/// type declaration.
bool alreadyBoundToNominal() const { return NextExtension.getInt(); }
/// Retrieve the extended type definition as written in the source, if it exists.
TypeRepr *getExtendedTypeRepr() const { return ExtendedTypeRepr; }
/// Retrieve the set of protocols that this type inherits (i.e,
/// explicitly conforms to).
MutableArrayRef<TypeLoc> getInherited() { return Inherited; }
ArrayRef<TypeLoc> getInherited() const { return Inherited; }
void setInherited(MutableArrayRef<TypeLoc> i) { Inherited = i; }
bool hasDefaultAccessLevel() const {
return Bits.ExtensionDecl.DefaultAndMaxAccessLevel != 0;
}
uint8_t getDefaultAndMaxAccessLevelBits() const {
return Bits.ExtensionDecl.DefaultAndMaxAccessLevel;
}
void setDefaultAndMaxAccessLevelBits(AccessLevel defaultAccess,
AccessLevel maxAccess) {
Bits.ExtensionDecl.DefaultAndMaxAccessLevel =
(1 << (static_cast<unsigned>(defaultAccess) - 1)) |
(1 << (static_cast<unsigned>(maxAccess) - 1));
}
AccessLevel getDefaultAccessLevel() const;
AccessLevel getMaxAccessLevel() const;
void setDefaultAndMaxAccess(AccessLevel defaultAccess,
AccessLevel maxAccess) {
assert(!hasDefaultAccessLevel() && "default access level already set");
assert(maxAccess >= defaultAccess);
assert(maxAccess != AccessLevel::Private && "private not valid");
assert(defaultAccess != AccessLevel::Private && "private not valid");
setDefaultAndMaxAccessLevelBits(defaultAccess, maxAccess);
assert(getDefaultAccessLevel() == defaultAccess && "not enough bits");
assert(getMaxAccessLevel() == maxAccess && "not enough bits");
}
void setConformanceLoader(LazyMemberLoader *resolver, uint64_t contextData);
/// Determine whether this is a constrained extension, which adds additional
/// requirements beyond those of the nominal type.
bool isConstrainedExtension() const;
/// Determine whether this extension context is interchangeable with the
/// original nominal type context.
///
/// False if any of the following properties hold:
/// - the extension is defined in a different module from the original
/// nominal type decl,
/// - the extension is constrained, or
/// - the extension is to a protocol.
/// FIXME: In a world where protocol extensions are dynamically dispatched,
/// "extension is to a protocol" would no longer be a reason to use the
/// extension mangling, because an extension method implementation could be
/// resiliently moved into the original protocol itself.
bool isEquivalentToExtendedContext() const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() == DeclKind::Extension;
}
static bool classof(const DeclContext *C) {
if (auto D = C->getAsDecl())
return classof(D);
return false;
}
static bool classof(const IterableDeclContext *C) {
return C->getIterableContextKind()
== IterableDeclContextKind::ExtensionDecl;
}
using DeclContext::operator new;
};
/// Iterator that walks the extensions of a particular type.
class ExtensionIterator {
ExtensionDecl *current;
public:
ExtensionIterator() : current() { }
explicit ExtensionIterator(ExtensionDecl *current) : current(current) { }
ExtensionDecl *operator*() const { return current; }
ExtensionDecl *operator->() const { return current; }
ExtensionIterator &operator++() {
current = current->NextExtension.getPointer();
return *this;
}
ExtensionIterator operator++(int) {
ExtensionIterator tmp = *this;
++(*this);
return tmp;
}
friend bool operator==(ExtensionIterator x, ExtensionIterator y) {
return x.current == y.current;
}
friend bool operator!=(ExtensionIterator x, ExtensionIterator y) {
return x.current != y.current;
}
};
/// Range that covers a set of extensions.
class ExtensionRange {
ExtensionIterator first;
ExtensionIterator last;
public:
ExtensionRange(ExtensionIterator first, ExtensionIterator last)
: first(first), last(last) { }
typedef ExtensionIterator iterator;
iterator begin() const { return first; }
iterator end() const { return last; }
};
/// This represents one entry in a PatternBindingDecl, which are pairs of
/// Pattern and Initialization expression. The pattern is always present, but
/// the initializer can be null if there is none.
class PatternBindingEntry {
enum class Flags {
Checked = 1 << 0,
Removed = 1 << 1,
/// Whether the contents of this initializer were subsumed by
/// some other initialization, e.g., a lazy property's initializer
/// gets subsumed by the getter body.
Subsumed = 1 << 2
};
llvm::PointerIntPair<Pattern *, 3, OptionSet<Flags>> PatternAndFlags;
struct InitializerAndEqualLoc {
// When the initializer is removed we don't actually clear the pointers
// because we might need to get initializer's source range. Since the
// initializer is ASTContext-allocated it is safe.
/// Exactly the expr the programmer wrote
Expr *originalInit;
/// Might be transformed, e.g. for a property wrapper. In the absence of
/// transformation or synthesis, holds the expr as parsed.
Expr *initAfterSynthesis;
/// The location of the equal '=' token.
SourceLoc EqualLoc;
};
union {
/// The initializer expression and its '=' token loc.
InitializerAndEqualLoc InitExpr;
/// The text of the initializer expression if deserialized from a module.
StringRef InitStringRepresentation;
};
/// The initializer context used for this pattern binding entry.
llvm::PointerIntPair<DeclContext *, 1, bool> InitContextAndIsText;
/// Values captured by this initializer.
CaptureInfo Captures;
friend class PatternBindingInitializer;
public:
/// \p E is the initializer as parsed.
PatternBindingEntry(Pattern *P, SourceLoc EqualLoc, Expr *E,
DeclContext *InitContext)
: PatternAndFlags(P, {}), InitExpr({E, E, EqualLoc}),
InitContextAndIsText({InitContext, false}) {
}
Pattern *getPattern() const { return PatternAndFlags.getPointer(); }
void setPattern(Pattern *P) { PatternAndFlags.setPointer(P); }
/// Whether the given pattern binding entry is initialized.
bool isInitialized() const;
Expr *getInit() const {
if (PatternAndFlags.getInt().contains(Flags::Removed) ||
InitContextAndIsText.getInt())
return nullptr;
return InitExpr.initAfterSynthesis;
}
/// Retrieve the initializer if it should be executed to initialize this
/// particular pattern binding.
Expr *getExecutableInit() const {
return isInitializerSubsumed() ? nullptr : getInit();
}
SourceRange getOriginalInitRange() const;
void setInit(Expr *E);
/// Gets the text of the initializer expression, stripping out inactive
/// branches of any #ifs inside the expression.
StringRef getInitStringRepresentation(SmallVectorImpl<char> &scratch) const;
/// Sets the initializer string representation to the string that was
/// deserialized from a partial module.
void setInitStringRepresentation(StringRef str) {
InitStringRepresentation = str;
InitContextAndIsText.setInt(true);
}
/// Whether this pattern entry can generate a string representation of its
/// initializer expression.
bool hasInitStringRepresentation() const;
/// Retrieve the location of the equal '=' token.
SourceLoc getEqualLoc() const {
return InitContextAndIsText.getInt() ? SourceLoc() : InitExpr.EqualLoc;
}
/// Set the location of the equal '=' token.
void setEqualLoc(SourceLoc equalLoc) {
assert(!InitContextAndIsText.getInt() &&
"cannot set equal loc for textual initializer");
InitExpr.EqualLoc = equalLoc;
}
/// Retrieve the initializer after the =, if any, as it was written in the
/// source.
Expr *getOriginalInit() const;
/// Set the initializer after the = as it was written in the source.
void setOriginalInit(Expr *);
bool isInitializerChecked() const {
return PatternAndFlags.getInt().contains(Flags::Checked);
}
void setInitializerChecked() {
PatternAndFlags.setInt(PatternAndFlags.getInt() | Flags::Checked);
}
bool isInitializerSubsumed() const {
return PatternAndFlags.getInt().contains(Flags::Subsumed);
}
void setInitializerSubsumed() {
PatternAndFlags.setInt(PatternAndFlags.getInt() | Flags::Subsumed);
}
// Return the first variable initialized by this pattern.
VarDecl *getAnchoringVarDecl() const;
// Retrieve the declaration context for the initializer.
DeclContext *getInitContext() const {
return InitContextAndIsText.getPointer();
}
/// Override the initializer context.
void setInitContext(DeclContext *dc) {
InitContextAndIsText.setPointer(dc);
}
SourceLoc getStartLoc() const;
/// Retrieve the end location covered by this pattern binding entry.
///
/// \param omitAccessors Whether the computation should omit the accessors
/// from the source range.
SourceLoc getEndLoc(bool omitAccessors = false) const;
/// Retrieve the source range covered by this pattern binding entry.
///
/// \param omitAccessors Whether the computation should omit the accessors
/// from the source range.
SourceRange getSourceRange(bool omitAccessors = false) const;
const CaptureInfo &getCaptureInfo() const { return Captures; }
void setCaptureInfo(const CaptureInfo &captures) { Captures = captures; }
private:
SourceLoc getLastAccessorEndLoc() const;
};
/// This decl contains a pattern and optional initializer for a set
/// of one or more VarDecls declared together.
///
/// For example, in
/// \code
/// var (a, b) = foo(), (c,d) = bar()
/// \endcode
///
/// this includes two entries in the pattern list. The first contains the
/// pattern "(a, b)" and the initializer "foo()". The second contains the
/// pattern "(c, d)" and the initializer "bar()".
///
class PatternBindingDecl final : public Decl,
private llvm::TrailingObjects<PatternBindingDecl, PatternBindingEntry> {
friend TrailingObjects;
friend class Decl;
SourceLoc StaticLoc; ///< Location of the 'static/class' keyword, if present.
SourceLoc VarLoc; ///< Location of the 'var' keyword.
friend class Decl;
PatternBindingDecl(SourceLoc StaticLoc, StaticSpellingKind StaticSpelling,
SourceLoc VarLoc, unsigned NumPatternEntries,
DeclContext *Parent);
SourceLoc getLocFromSource() const { return VarLoc; }
public:
static PatternBindingDecl *create(ASTContext &Ctx, SourceLoc StaticLoc,
StaticSpellingKind StaticSpelling,
SourceLoc VarLoc,
ArrayRef<PatternBindingEntry> PatternList,
DeclContext *Parent);
static PatternBindingDecl *create(ASTContext &Ctx, SourceLoc StaticLoc,
StaticSpellingKind StaticSpelling,
SourceLoc VarLoc, Pattern *Pat,
SourceLoc EqualLoc, Expr *E,
DeclContext *Parent);
static PatternBindingDecl *createImplicit(ASTContext &Ctx,
StaticSpellingKind StaticSpelling,
Pattern *Pat, Expr *E,
DeclContext *Parent,
SourceLoc VarLoc = SourceLoc());
static PatternBindingDecl *createDeserialized(
ASTContext &Ctx, SourceLoc StaticLoc,
StaticSpellingKind StaticSpelling,
SourceLoc VarLoc,
unsigned NumPatternEntries,
DeclContext *Parent);
SourceLoc getStartLoc() const {
return StaticLoc.isValid() ? StaticLoc : VarLoc;
}
SourceRange getSourceRange() const;
unsigned getNumPatternEntries() const {
return Bits.PatternBindingDecl.NumPatternEntries;
}
ArrayRef<PatternBindingEntry> getPatternList() const {
return const_cast<PatternBindingDecl*>(this)->getMutablePatternList();
}
void setInitStringRepresentation(unsigned i, StringRef str) {
getMutablePatternList()[i].setInitStringRepresentation(str);
}
/// Whether the given pattern entry is initialized.
bool isInitialized(unsigned i) const {
return getPatternList()[i].isInitialized();
}
Expr *getInit(unsigned i) const {
return getPatternList()[i].getInit();
}
Expr *getExecutableInit(unsigned i) const {
return getPatternList()[i].getExecutableInit();
}
SourceRange getOriginalInitRange(unsigned i) const {
return getPatternList()[i].getOriginalInitRange();
}
void setInit(unsigned i, Expr *E) {
getMutablePatternList()[i].setInit(E);
}
Pattern *getPattern(unsigned i) const {
return getPatternList()[i].getPattern();
}
void setPattern(unsigned i, Pattern *Pat, DeclContext *InitContext);
DeclContext *getInitContext(unsigned i) const {
return getPatternList()[i].getInitContext();
}
const CaptureInfo &getCaptureInfo(unsigned i) const {
return getPatternList()[i].getCaptureInfo();
}
void setCaptureInfo(unsigned i, const CaptureInfo &captures) {
getMutablePatternList()[i].setCaptureInfo(captures);
}
/// Given that this PBD is the parent pattern for the specified VarDecl,
/// return the entry of the VarDecl in our PatternList. For example, in:
///
/// let (a,b) = foo(), (c,d) = bar()
///
/// "a" and "b" will have index 0, since they correspond to the first pattern,
/// and "c" and "d" will have index 1 since they correspond to the second one.
unsigned getPatternEntryIndexForVarDecl(const VarDecl *VD) const;
/// Return the PatternEntry (a pattern + initializer pair) for the specified
/// VarDecl.
const PatternBindingEntry &getPatternEntryForVarDecl(
const VarDecl *VD) const {
return getPatternList()[getPatternEntryIndexForVarDecl(VD)];
}
bool isInitializerChecked(unsigned i) const {
return getPatternList()[i].isInitializerChecked();
}
void setInitializerChecked(unsigned i) {
getMutablePatternList()[i].setInitializerChecked();
}
bool isInitializerSubsumed(unsigned i) const {
return getPatternList()[i].isInitializerSubsumed();
}
void setInitializerSubsumed(unsigned i) {
getMutablePatternList()[i].setInitializerSubsumed();
}
/// Does this binding declare something that requires storage?
bool hasStorage() const;
/// Determines whether this binding either has an initializer expression, or is
/// default initialized, without performing any type checking on it.
bool isDefaultInitializable() const {
for (unsigned i = 0, e = getNumPatternEntries(); i < e; ++i)
if (!isDefaultInitializable(i))
return false;
return true;
}
/// Can the pattern at index i be default initialized?
bool isDefaultInitializable(unsigned i) const;
/// When the pattern binding contains only a single variable with no
/// destructuring, retrieve that variable.
VarDecl *getSingleVar() const;
bool isStatic() const { return Bits.PatternBindingDecl.IsStatic; }
void setStatic(bool s) { Bits.PatternBindingDecl.IsStatic = s; }
SourceLoc getStaticLoc() const { return StaticLoc; }
/// \returns the way 'static'/'class' was spelled in the source.
StaticSpellingKind getStaticSpelling() const {
return static_cast<StaticSpellingKind>(
Bits.PatternBindingDecl.StaticSpelling);
}
/// \returns the way 'static'/'class' should be spelled for this declaration.
StaticSpellingKind getCorrectStaticSpelling() const;
static bool classof(const Decl *D) {
return D->getKind() == DeclKind::PatternBinding;
}
private:
MutableArrayRef<PatternBindingEntry> getMutablePatternList() {
// Pattern entries are tail allocated.
return {getTrailingObjects<PatternBindingEntry>(), getNumPatternEntries()};
}
};
/// TopLevelCodeDecl - This decl is used as a container for top-level
/// expressions and statements in the main module. It is always a direct
/// child of a SourceFile. The primary reason for building these is to give
/// top-level statements a DeclContext which is distinct from the file itself.
/// This, among other things, makes it easier to distinguish between local
/// top-level variables (which are not live past the end of the statement) and
/// global variables.
class TopLevelCodeDecl : public DeclContext, public Decl {
BraceStmt *Body;
SourceLoc getLocFromSource() const { return getStartLoc(); }
friend class Decl;
public:
TopLevelCodeDecl(DeclContext *Parent, BraceStmt *Body = nullptr)
: DeclContext(DeclContextKind::TopLevelCodeDecl, Parent),
Decl(DeclKind::TopLevelCode, Parent),
Body(Body) {}
BraceStmt *getBody() const { return Body; }
void setBody(BraceStmt *b) { Body = b; }
SourceLoc getStartLoc() const;
SourceRange getSourceRange() const;
static bool classof(const Decl *D) {
return D->getKind() == DeclKind::TopLevelCode;
}
static bool classof(const DeclContext *C) {
if (auto D = C->getAsDecl())
return classof(D);
return false;
}
using DeclContext::operator new;
};
/// SerializedTopLevelCodeDeclContext - This represents what was originally a
/// TopLevelCodeDecl during serialization. It is preserved only to maintain the
/// correct AST structure and remangling after deserialization.
class SerializedTopLevelCodeDeclContext : public SerializedLocalDeclContext {
public:
SerializedTopLevelCodeDeclContext(DeclContext *Parent)
: SerializedLocalDeclContext(LocalDeclContextKind::TopLevelCodeDecl,
Parent) {}
static bool classof(const DeclContext *DC) {
if (auto LDC = dyn_cast<SerializedLocalDeclContext>(DC))
return LDC->getLocalDeclContextKind() ==
LocalDeclContextKind::TopLevelCodeDecl;
return false;
}
};
/// IfConfigDecl - This class represents #if/#else/#endif blocks.
/// Active and inactive block members are stored separately, with the intention
/// being that active members will be handed back to the enclosing context.
class IfConfigDecl : public Decl {
/// An array of clauses controlling each of the #if/#elseif/#else conditions.
/// The array is ASTContext allocated.
ArrayRef<IfConfigClause> Clauses;
SourceLoc EndLoc;
SourceLoc getLocFromSource() const { return Clauses[0].Loc; }
friend class Decl;
public:
IfConfigDecl(DeclContext *Parent, ArrayRef<IfConfigClause> Clauses,
SourceLoc EndLoc, bool HadMissingEnd)
: Decl(DeclKind::IfConfig, Parent), Clauses(Clauses), EndLoc(EndLoc)
{
Bits.IfConfigDecl.HadMissingEnd = HadMissingEnd;
}
ArrayRef<IfConfigClause> getClauses() const { return Clauses; }
/// Return the active clause, or null if there is no active one.
const IfConfigClause *getActiveClause() const {
for (auto &Clause : Clauses)
if (Clause.isActive) return &Clause;
return nullptr;
}
const ArrayRef<ASTNode> getActiveClauseElements() const {
if (auto *Clause = getActiveClause())
return Clause->Elements;
return {};
}
SourceLoc getEndLoc() const { return EndLoc; }
bool hadMissingEnd() const { return Bits.IfConfigDecl.HadMissingEnd; }
SourceRange getSourceRange() const;
static bool classof(const Decl *D) {
return D->getKind() == DeclKind::IfConfig;
}
};
class StringLiteralExpr;
class PoundDiagnosticDecl : public Decl {
SourceLoc StartLoc;
SourceLoc EndLoc;
StringLiteralExpr *Message;
SourceLoc getLocFromSource() const { return StartLoc; }
friend class Decl;
public:
PoundDiagnosticDecl(DeclContext *Parent, bool IsError, SourceLoc StartLoc,
SourceLoc EndLoc, StringLiteralExpr *Message)
: Decl(DeclKind::PoundDiagnostic, Parent), StartLoc(StartLoc),
EndLoc(EndLoc), Message(Message) {
Bits.PoundDiagnosticDecl.IsError = IsError;
Bits.PoundDiagnosticDecl.HasBeenEmitted = false;
}
DiagnosticKind getKind() {
return isError() ? DiagnosticKind::Error : DiagnosticKind::Warning;
}
StringLiteralExpr *getMessage() { return Message; }
bool isError() {
return Bits.PoundDiagnosticDecl.IsError;
}
bool hasBeenEmitted() {
return Bits.PoundDiagnosticDecl.HasBeenEmitted;
}
void markEmitted() {
Bits.PoundDiagnosticDecl.HasBeenEmitted = true;
}
SourceLoc getEndLoc() const { return EndLoc; };
SourceRange getSourceRange() const {
return SourceRange(StartLoc, EndLoc);
}
static bool classof(const Decl *D) {
return D->getKind() == DeclKind::PoundDiagnostic;
}
};
class OpaqueTypeDecl;
/// ValueDecl - All named decls that are values in the language. These can
/// have a type, etc.
class ValueDecl : public Decl {
DeclName Name;
SourceLoc NameLoc;
llvm::PointerIntPair<Type, 3, OptionalEnum<AccessLevel>> TypeAndAccess;
unsigned LocalDiscriminator = 0;
struct {
/// Whether the "IsObjC" bit has been computed yet.
unsigned isObjCComputed : 1;
/// Whether this declaration is exposed to Objective-C.
unsigned isObjC : 1;
/// Whether the "overridden" declarations have been computed already.
unsigned hasOverriddenComputed : 1;
/// Whether there are any "overridden" declarations. The actual overridden
/// declarations are kept in a side table in the ASTContext.
unsigned hasOverridden : 1;
/// Whether the "isDynamic" bit has been computed yet.
unsigned isDynamicComputed : 1;
/// Whether this declaration is 'dynamic', meaning that all uses of
/// the declaration will go through an extra level of indirection that
/// allows the entity to be replaced at runtime.
unsigned isDynamic : 1;
/// Whether the "isFinal" bit has been computed yet.
unsigned isFinalComputed : 1;
/// Whether this declaration is 'final'. A final class can't be subclassed,
/// a final class member can't be overriden.
unsigned isFinal : 1;
/// Whether the "isIUO" bit" has been computed yet.
unsigned isIUOComputed : 1;
/// Whether this declaration produces an implicitly unwrapped
/// optional result.
unsigned isIUO : 1;
} LazySemanticInfo = { };
friend class OverriddenDeclsRequest;
friend class IsObjCRequest;
friend class IsFinalRequest;
friend class IsDynamicRequest;
friend class IsImplicitlyUnwrappedOptionalRequest;
friend class Decl;
SourceLoc getLocFromSource() const { return NameLoc; }
protected:
ValueDecl(DeclKind K,
llvm::PointerUnion<DeclContext *, ASTContext *> context,
DeclName name, SourceLoc NameLoc)
: Decl(K, context), Name(name), NameLoc(NameLoc) {
Bits.ValueDecl.AlreadyInLookupTable = false;
Bits.ValueDecl.CheckedRedeclaration = false;
Bits.ValueDecl.IsUserAccessible = true;
}
// MemberLookupTable borrows a bit from this type
friend class MemberLookupTable;
bool isAlreadyInLookupTable() {
return Bits.ValueDecl.AlreadyInLookupTable;
}
void setAlreadyInLookupTable(bool value = true) {
Bits.ValueDecl.AlreadyInLookupTable = value;
}
public:
/// Return true if this protocol member is a protocol requirement.
///
/// Asserts if this is not a member of a protocol.
bool isProtocolRequirement() const;
/// Determine whether we have already checked whether this
/// declaration is a redeclaration.
bool alreadyCheckedRedeclaration() const {
return Bits.ValueDecl.CheckedRedeclaration;
}
/// Set whether we have already checked this declaration as a
/// redeclaration.
void setCheckedRedeclaration(bool checked) {
Bits.ValueDecl.CheckedRedeclaration = checked;
}
void setUserAccessible(bool Accessible) {
Bits.ValueDecl.IsUserAccessible = Accessible;
}
bool isUserAccessible() const {
return Bits.ValueDecl.IsUserAccessible;
}
bool hasName() const { return bool(Name); }
bool isOperator() const { return Name.isOperator(); }
/// Retrieve the full name of the declaration.
/// TODO: Rename to getName?
DeclName getFullName() const { return Name; }
void setName(DeclName name) { Name = name; }
/// Retrieve the base name of the declaration, ignoring any argument
/// names.
DeclBaseName getBaseName() const { return Name.getBaseName(); }
/// Retrieve the name to use for this declaration when interoperating
/// with the Objective-C runtime.
///
/// \returns A "selector" containing the runtime name. For non-method
/// entities (classes, protocols, properties), this operation will
/// return a zero-parameter selector with the appropriate name in its
/// first slot.
Optional<ObjCSelector> getObjCRuntimeName(
bool skipIsObjCResolution = false) const;
/// Determine whether the given declaration can infer @objc, or the
/// Objective-C name, if used to satisfy the given requirement.
bool canInferObjCFromRequirement(ValueDecl *requirement);
SourceLoc getNameLoc() const { return NameLoc; }
bool isUsableFromInline() const;
/// Returns \c true if this declaration is *not* intended to be used directly
/// by application developers despite the visibility.
bool shouldHideFromEditor() const;
bool hasAccess() const {
return TypeAndAccess.getInt().hasValue();
}
/// Access control is done by Requests.
friend class AccessLevelRequest;
/// Returns the access level specified explicitly by the user, or provided by
/// default according to language rules.
///
/// Most of the time this is not the interesting value to check; access is
/// limited by enclosing scopes per SE-0025. Use #getFormalAccessScope to
/// check if access control is being used consistently, and to take features
/// such as \c \@testable and \c \@usableFromInline into account.
///
/// \sa getFormalAccessScope
/// \sa hasOpenAccess
AccessLevel getFormalAccess() const;
/// Determine whether this Decl has either Private or FilePrivate access,
/// and its DeclContext does not.
bool isOutermostPrivateOrFilePrivateScope() const;
/// Returns the outermost DeclContext from which this declaration can be
/// accessed, or null if the declaration is public.
///
/// This is used when calculating if access control is being used
/// consistently. If \p useDC is provided (the location where the value is
/// being used), features that affect formal access such as \c \@testable are
/// taken into account.
///
/// \invariant
/// <code>value.isAccessibleFrom(
/// value.getFormalAccessScope().getDeclContext())</code>
///
/// If \p treatUsableFromInlineAsPublic is true, declarations marked with the
/// \c \@usableFromInline attribute are treated as public. This is normally
/// false for name lookup and other source language concerns, but true when
/// computing the linkage of generated functions.
///
/// \sa getFormalAccess
/// \sa isAccessibleFrom
/// \sa hasOpenAccess
AccessScope
getFormalAccessScope(const DeclContext *useDC = nullptr,
bool treatUsableFromInlineAsPublic = false) const;
/// Copy the formal access level and @usableFromInline attribute from
/// \p source.
///
/// If \p sourceIsParentContext is true, an access level of \c private will
/// be copied as \c fileprivate, to ensure that this declaration will be
/// available everywhere \p source is.
void copyFormalAccessFrom(const ValueDecl *source,
bool sourceIsParentContext = false);
/// Returns the access level that actually controls how a declaration should
/// be emitted and may be used.
///
/// This is the access used when making optimization and code generation
/// decisions. It should not be used at the AST or semantic level.
AccessLevel getEffectiveAccess() const;
void setAccess(AccessLevel access) {
assert(!hasAccess() && "access already set");
overwriteAccess(access);
}
/// Overwrite the access of this declaration.
///
/// This is needed in the LLDB REPL.
void overwriteAccess(AccessLevel access) {
TypeAndAccess.setInt(access);
}
/// Returns true if this declaration is accessible from the given context.
///
/// A private declaration is accessible from any DeclContext within the same
/// source file.
///
/// An internal declaration is accessible from any DeclContext within the same
/// module.
///
/// A public declaration is accessible everywhere.
///
/// If \p DC is null, returns true only if this declaration is public.
///
/// If \p forConformance is true, we ignore the visibility of the protocol
/// when evaluating protocol extension members. This language rule allows a
/// protocol extension of a private protocol to provide default
/// implementations for the requirements of a public protocol, even when
/// the default implementations are not visible to name lookup.
bool isAccessibleFrom(const DeclContext *DC,
bool forConformance = false) const;
/// Returns whether this declaration should be treated as \c open from
/// \p useDC. This is very similar to #getFormalAccess, but takes
/// \c \@testable into account.
///
/// This is mostly only useful when considering requirements on an override:
/// if the base declaration is \c open, the override might have to be too.
bool hasOpenAccess(const DeclContext *useDC) const;
/// FIXME: This is deprecated.
bool isRecursiveValidation() const;
/// Retrieve the "interface" type of this value, which uses
/// GenericTypeParamType if the declaration is generic. For a generic
/// function, this will have a GenericFunctionType with a
/// GenericSignature inside the type.
Type getInterfaceType() const;
bool hasInterfaceType() const;
/// Set the interface type for the given value.
void setInterfaceType(Type type);
/// isInstanceMember - Determine whether this value is an instance member
/// of an enum or protocol.
bool isInstanceMember() const;
/// Retrieve the context discriminator for this local value, which
/// is the index of this declaration in the sequence of
/// discriminated declarations with the same name in the current
/// context. Only local functions and variables with getters and
/// setters have discriminators.
unsigned getLocalDiscriminator() const;
void setLocalDiscriminator(unsigned index);
/// Retrieve the declaration that this declaration overrides, if any.
ValueDecl *getOverriddenDecl() const;
/// Retrieve the declarations that this declaration overrides, if any.
llvm::TinyPtrVector<ValueDecl *> getOverriddenDecls() const;
/// Set the declaration that this declaration overrides.
void setOverriddenDecl(ValueDecl *overridden) {
setOverriddenDecls(overridden);
}
/// Set the declarations that this declaration overrides.
void setOverriddenDecls(ArrayRef<ValueDecl *> overridden);
/// Whether the overridden declarations have already been computed.
bool overriddenDeclsComputed() const;
/// Compute the untyped overload signature for this declaration.
OverloadSignature getOverloadSignature() const;
/// Retrieve the type used to describe this entity for the purposes of
/// overload resolution.
CanType getOverloadSignatureType() const;
/// Returns true if the decl requires Objective-C interop.
///
/// This can be true even if there is no 'objc' attribute on the declaration.
/// In that case it was inferred by the type checker and set with a call to
/// markAsObjC().
bool isObjC() const;
/// Note whether this declaration is known to be exposed to Objective-C.
void setIsObjC(bool Value);
/// Is this declaration 'final'?
bool isFinal() const;
/// Is this declaration marked with 'dynamic'?
bool isDynamic() const;
bool isObjCDynamic() const {
return isObjC() && isDynamic();
}
bool isNativeDynamic() const {
return !isObjC() && isDynamic();
}
/// Set whether this type is 'dynamic' or not.
void setIsDynamic(bool value);
/// Whether the 'dynamic' bit has been computed already.
bool isDynamicComputed() const {
return LazySemanticInfo.isDynamicComputed;
}
/// Returns true if this decl can be found by id-style dynamic lookup.
bool canBeAccessedByDynamicLookup() const;
/// Returns true if this declaration has an implicitly unwrapped optional
/// result. The precise meaning depends on the declaration kind:
/// - for properties, the value is IUO
/// - for subscripts, the element type is IUO
/// - for functions, the result type is IUO
/// - for constructors, the failability kind is IUO
bool isImplicitlyUnwrappedOptional() const;
/// Should only be set on imported and deserialized declarations; parsed
/// declarations compute this lazily via a request.
void setImplicitlyUnwrappedOptional(bool isIUO) {
LazySemanticInfo.isIUOComputed = 1;
LazySemanticInfo.isIUO = isIUO;
}
/// Returns the protocol requirements that this decl conforms to.
ArrayRef<ValueDecl *>
getSatisfiedProtocolRequirements(bool Sorted = false) const;
/// Determines the kind of access that should be performed by a
/// DeclRefExpr or MemberRefExpr use of this value in the specified
/// context.
///
/// \param DC The declaration context.
///
/// \param isAccessOnSelf Whether this is a member access on the implicit
/// 'self' declaration of the declaration context.
AccessSemantics getAccessSemanticsFromContext(const DeclContext *DC,
bool isAccessOnSelf) const;
/// Print a reference to the given declaration.
std::string printRef() const;
/// Dump a reference to the given declaration.
void dumpRef(raw_ostream &os) const;
/// Dump a reference to the given declaration.
void dumpRef() const;
/// Returns true if the declaration is a static member of a type.
///
/// This is not necessarily the opposite of "isInstanceMember()". Both
/// predicates will be false for declarations that either categorically
/// can't be "static" or are in a context where "static" doesn't make sense.
bool isStatic() const;
/// Retrieve the location at which we should insert a new attribute or
/// modifier.
SourceLoc getAttributeInsertionLoc(bool forModifier) const;
static bool classof(const Decl *D) {
return D->getKind() >= DeclKind::First_ValueDecl &&
D->getKind() <= DeclKind::Last_ValueDecl;
}
/// True if this is a C function that was imported as a member of a type in
/// Swift.
bool isImportAsMember() const;
/// Returns true if the declaration's interface type is a function type with a
/// curried self parameter.
bool hasCurriedSelf() const;
/// Returns true if the declaration has a parameter list associated with it.
///
/// Note that not all declarations with function interface types have
/// parameter lists, for example an enum element without associated values.
bool hasParameterList() const;
/// Returns the number of curry levels in the declaration's interface type.
unsigned getNumCurryLevels() const;
/// Get the decl for this value's opaque result type, if it has one.
OpaqueTypeDecl *getOpaqueResultTypeDecl() const;
/// Get the representative for this value's opaque result type, if it has one.
OpaqueReturnTypeRepr *getOpaqueResultTypeRepr() const;
/// Retrieve the attribute associating this declaration with a
/// function builder, if there is one.
CustomAttr *getAttachedFunctionBuilder() const;
/// Retrieve the @functionBuilder type attached to this declaration,
/// if there is one.
Type getFunctionBuilderType() const;
};
/// This is a common base class for declarations which declare a type.
class TypeDecl : public ValueDecl {
MutableArrayRef<TypeLoc> Inherited;
protected:
TypeDecl(DeclKind K, llvm::PointerUnion<DeclContext *, ASTContext *> context,
Identifier name, SourceLoc NameLoc,
MutableArrayRef<TypeLoc> inherited) :
ValueDecl(K, context, name, NameLoc), Inherited(inherited) {}
public:
Identifier getName() const { return getFullName().getBaseIdentifier(); }
/// Returns the string for the base name, or "_" if this is unnamed.
StringRef getNameStr() const {
assert(!getFullName().isSpecial() && "Cannot get string for special names");
return hasName() ? getBaseName().getIdentifier().str() : "_";
}
/// The type of this declaration's values. For the type of the
/// declaration itself, use getInterfaceType(), which returns a
/// metatype.
Type getDeclaredInterfaceType() const;
/// Retrieve the set of protocols that this type inherits (i.e,
/// explicitly conforms to).
MutableArrayRef<TypeLoc> getInherited() { return Inherited; }
ArrayRef<TypeLoc> getInherited() const { return Inherited; }
void setInherited(MutableArrayRef<TypeLoc> i) { Inherited = i; }
static bool classof(const Decl *D) {
return D->getKind() >= DeclKind::First_TypeDecl &&
D->getKind() <= DeclKind::Last_TypeDecl;
}
/// Compute an ordering between two type declarations that is ABI-stable.
static int compare(const TypeDecl *type1, const TypeDecl *type2);
/// Compute an ordering between two type declarations that is ABI-stable.
/// This version takes a pointer-to-a-pointer for use with
/// llvm::array_pod_sort() and similar.
template<typename T>
static int compare(T * const* type1, T * const* type2) {
return compare(*type1, *type2);
}
};
/// A type declaration that can have generic parameters attached to it. Because
/// it has these generic parameters, it is always a DeclContext.
class GenericTypeDecl : public GenericContext, public TypeDecl {
public:
GenericTypeDecl(DeclKind K, DeclContext *DC,
Identifier name, SourceLoc nameLoc,
MutableArrayRef<TypeLoc> inherited,
GenericParamList *GenericParams);
// Resolve ambiguity due to multiple base classes.
using TypeDecl::getASTContext;
using DeclContext::operator new;
using TypeDecl::getDeclaredInterfaceType;
static bool classof(const DeclContext *C) {
if (auto D = C->getAsDecl())
return classof(D);
return false;
}
static bool classof(const Decl *D) {
return D->getKind() >= DeclKind::First_GenericTypeDecl &&
D->getKind() <= DeclKind::Last_GenericTypeDecl;
}
};
/// OpaqueTypeDecl - This is a declaration of an opaque type. The opaque type
/// is formally equivalent to its underlying type, but abstracts it away from
/// clients of the opaque type, only exposing the type as something conforming
/// to a given set of constraints.
///
/// Currently, opaque types do not normally have an explicit spelling in source
/// code. One is formed implicitly when a declaration is written with an opaque
/// result type, as in:
///
/// func foo() -> opaque SignedInteger { return 1 }
///
/// The declared type is a special kind of ArchetypeType representing the
/// abstracted underlying type.
class OpaqueTypeDecl : public GenericTypeDecl {
/// The original declaration that "names" the opaque type. Although a specific
/// opaque type cannot be explicitly named, oapque types can propagate
/// arbitrarily through expressions, so we need to know *which* opaque type is
/// propagated.
ValueDecl *NamingDecl;
/// The generic signature of the opaque interface to the type. This is the
/// outer generic signature with an added generic parameter representing the
/// underlying type.
GenericSignature OpaqueInterfaceGenericSignature;
/// The generic parameter that represents the underlying type.
GenericTypeParamType *UnderlyingInterfaceType;
/// If known, the underlying type and conformances of the opaque type,
/// expressed as a SubstitutionMap for the opaque interface generic signature.
/// This maps types in the interface generic signature to the outer generic
/// signature of the original declaration.
Optional<SubstitutionMap> UnderlyingTypeSubstitutions;
mutable Identifier OpaqueReturnTypeIdentifier;
public:
OpaqueTypeDecl(ValueDecl *NamingDecl,
GenericParamList *GenericParams,
DeclContext *DC,
GenericSignature OpaqueInterfaceGenericSignature,
GenericTypeParamType *UnderlyingInterfaceType);
ValueDecl *getNamingDecl() const { return NamingDecl; }
void setNamingDecl(ValueDecl *D) {
assert(!NamingDecl && "already have naming decl");
NamingDecl = D;
}
/// Is this opaque type the opaque return type of the given function?
///
/// This is more complex than just checking `getNamingDecl` because the
/// function could also be the getter of a storage declaration.
bool isOpaqueReturnTypeOfFunction(const AbstractFunctionDecl *func) const;
GenericSignature getOpaqueInterfaceGenericSignature() const {
return OpaqueInterfaceGenericSignature;
}
GenericTypeParamType *getUnderlyingInterfaceType() const {
return UnderlyingInterfaceType;
}
Optional<SubstitutionMap> getUnderlyingTypeSubstitutions() const {
return UnderlyingTypeSubstitutions;
}
void setUnderlyingTypeSubstitutions(SubstitutionMap subs) {
assert(!UnderlyingTypeSubstitutions.hasValue() && "resetting underlying type?!");
UnderlyingTypeSubstitutions = subs;
}
// Opaque type decls are currently always implicit
SourceRange getSourceRange() const { return SourceRange(); }
// Get the identifier string that can be used to cross-reference unnamed
// opaque return types across files.
Identifier getOpaqueReturnTypeIdentifier() const;
static bool classof(const Decl *D) {
return D->getKind() == DeclKind::OpaqueType;
}
static bool classof(const GenericTypeDecl *D) {
return D->getKind() == DeclKind::OpaqueType;
}
static bool classof(const DeclContext *C) {
if (auto D = C->getAsDecl())
return classof(D);
return false;
}
};
/// TypeAliasDecl - This is a declaration of a typealias, for example:
///
/// typealias Foo = Int
///
/// TypeAliasDecl's always have 'MetatypeType' type.
///
class TypeAliasDecl : public GenericTypeDecl {
friend class UnderlyingTypeRequest;
/// The location of the 'typealias' keyword
SourceLoc TypeAliasLoc;
/// The location of the equal '=' token
SourceLoc EqualLoc;
/// The end of the type, valid even when the type cannot be parsed
SourceLoc TypeEndLoc;
/// The location of the right-hand side of the typealias binding
TypeLoc UnderlyingTy;
public:
TypeAliasDecl(SourceLoc TypeAliasLoc, SourceLoc EqualLoc, Identifier Name,
SourceLoc NameLoc, GenericParamList *GenericParams,
DeclContext *DC);
SourceLoc getStartLoc() const { return TypeAliasLoc; }
SourceRange getSourceRange() const;
/// Returns the location of the equal '=' token
SourceLoc getEqualLoc() const {
return EqualLoc;
}
void setTypeEndLoc(SourceLoc e) { TypeEndLoc = e; }
/// Retrieve the TypeRepr corresponding to the parsed underlying type.
TypeRepr *getUnderlyingTypeRepr() const {
return UnderlyingTy.getTypeRepr();
}
void setUnderlyingTypeRepr(TypeRepr *repr) {
UnderlyingTy = repr;
}
/// Retrieve the interface type of the underlying type.
Type getUnderlyingType() const;
void setUnderlyingType(Type type);
/// For generic typealiases, return the unbound generic type.
UnboundGenericType *getUnboundGenericType() const;
/// Retrieve a sugared interface type containing the structure of the interface
/// type before any semantic validation has occured.
Type getStructuralType() const;
/// Set the interface type of this typealias declaration from the underlying type.
void computeType();
bool isCompatibilityAlias() const {
return Bits.TypeAliasDecl.IsCompatibilityAlias;
}
void markAsCompatibilityAlias(bool newValue = true) {
Bits.TypeAliasDecl.IsCompatibilityAlias = newValue;
}
/// Is this a special debugger variable?
bool isDebuggerAlias() const { return Bits.TypeAliasDecl.IsDebuggerAlias; }
void markAsDebuggerAlias(bool isDebuggerAlias) {
Bits.TypeAliasDecl.IsDebuggerAlias = isDebuggerAlias;
}
static bool classof(const Decl *D) {
return D->getKind() == DeclKind::TypeAlias;
}
static bool classof(const GenericTypeDecl *D) {
return D->getKind() == DeclKind::TypeAlias;
}
static bool classof(const DeclContext *C) {
if (auto D = C->getAsDecl())
return classof(D);
return false;
}
};
/// Abstract class describing generic type parameters and associated types,
/// whose common purpose is to anchor the abstract type parameter and specify
/// requirements for any corresponding type argument.
class AbstractTypeParamDecl : public TypeDecl {
protected:
AbstractTypeParamDecl(DeclKind kind, DeclContext *dc, Identifier name,
SourceLoc NameLoc)
: TypeDecl(kind, dc, name, NameLoc, { }) { }
public:
/// Return the superclass of the generic parameter.
Type getSuperclass() const;
/// Retrieve the set of protocols to which this abstract type
/// parameter conforms.
ArrayRef<ProtocolDecl *> getConformingProtocols() const;
static bool classof(const Decl *D) {
return D->getKind() >= DeclKind::First_AbstractTypeParamDecl &&
D->getKind() <= DeclKind::Last_AbstractTypeParamDecl;
}
};
/// A declaration of a generic type parameter.
///
/// A generic type parameter introduces a new, named type parameter along
/// with some set of requirements on any type argument used to realize this
/// type parameter. The requirements involve conformances to specific
/// protocols or inheritance from a specific class type.
///
/// In the following example, 'T' is a generic type parameter with the
/// requirement that the type argument conform to the 'Comparable' protocol.
///
/// \code
/// func min<T : Comparable>(x : T, y : T) -> T { ... }
/// \endcode
class GenericTypeParamDecl : public AbstractTypeParamDecl {
public:
static const unsigned InvalidDepth = 0xFFFF;
/// Construct a new generic type parameter.
///
/// \param dc The DeclContext in which the generic type parameter's owner
/// occurs. This should later be overwritten with the actual declaration
/// context that owns the type parameter.
///
/// \param name The name of the generic parameter.
/// \param nameLoc The location of the name.
GenericTypeParamDecl(DeclContext *dc, Identifier name, SourceLoc nameLoc,
unsigned depth, unsigned index);
/// The depth of this generic type parameter, i.e., the number of outer
/// levels of generic parameter lists that enclose this type parameter.
///
/// \code
/// struct X<T> {
/// func f<U>() { }
/// }
/// \endcode
///
/// Here 'T' has depth 0 and 'U' has depth 1. Both have index 0.
unsigned getDepth() const { return Bits.GenericTypeParamDecl.Depth; }
/// Set the depth of this generic type parameter.
///
/// \sa getDepth
void setDepth(unsigned depth) {
Bits.GenericTypeParamDecl.Depth = depth;
assert(Bits.GenericTypeParamDecl.Depth == depth && "Truncation");
}
/// The index of this generic type parameter within its generic parameter
/// list.
///
/// \code
/// struct X<T, U> {
/// func f<V>() { }
/// }
/// \endcode
///
/// Here 'T' and 'U' have indexes 0 and 1, respectively. 'V' has index 0.
unsigned getIndex() const { return Bits.GenericTypeParamDecl.Index; }
SourceLoc getStartLoc() const { return getNameLoc(); }
SourceRange getSourceRange() const;
static bool classof(const Decl *D) {
return D->getKind() == DeclKind::GenericTypeParam;
}
};
/// A declaration of an associated type.
///
/// An associated type introduces a new, named type in a protocol that
/// can vary from one conforming type to the next. Associated types have a
/// set of requirements to which the type that replaces it much realize,
/// described via conformance to specific protocols, or inheritance from a
/// specific class type.
///
/// In the following example, 'Element' is an associated type with no
/// requirements.
///
/// \code
/// protocol Enumerator {
/// typealias Element
/// func getNext() -> Element?
/// }
/// \endcode
class AssociatedTypeDecl : public AbstractTypeParamDecl {
/// The location of the initial keyword.
SourceLoc KeywordLoc;
/// The default definition.
TypeRepr *DefaultDefinition;
/// The where clause attached to the associated type.
TrailingWhereClause *TrailingWhere;
LazyMemberLoader *Resolver = nullptr;
uint64_t ResolverContextData;
friend class DefaultDefinitionTypeRequest;
public:
AssociatedTypeDecl(DeclContext *dc, SourceLoc keywordLoc, Identifier name,
SourceLoc nameLoc, TypeRepr *defaultDefinition,
TrailingWhereClause *trailingWhere);
AssociatedTypeDecl(DeclContext *dc, SourceLoc keywordLoc, Identifier name,
SourceLoc nameLoc, TrailingWhereClause *trailingWhere,
LazyMemberLoader *definitionResolver,
uint64_t resolverData);
/// Get the protocol in which this associated type is declared.
ProtocolDecl *getProtocol() const {
return cast<ProtocolDecl>(getDeclContext());
}
/// Check if we have a default definition type.
bool hasDefaultDefinitionType() const {
// If we have a TypeRepr, return true immediately without kicking off
// a request.
return DefaultDefinition || getDefaultDefinitionType();
}
/// Retrieve the default definition type.
Type getDefaultDefinitionType() const;
/// Retrieve the default definition as written in the source.
TypeRepr *getDefaultDefinitionTypeRepr() const {
return DefaultDefinition;
}
/// Retrieve the trailing where clause for this associated type, if any.
TrailingWhereClause *getTrailingWhereClause() const { return TrailingWhere; }
/// Set the trailing where clause for this associated type.
void setTrailingWhereClause(TrailingWhereClause *trailingWhereClause) {
TrailingWhere = trailingWhereClause;
}
/// Set the interface type of this associated type declaration to a dependent
/// member type of 'Self'.
void computeType();
/// Retrieve the associated type "anchor", which is the associated type
/// declaration that will be used to describe this associated type in the
/// ABI.
///
/// The associated type "anchor" is an associated type that does not
/// override any other associated type. There may be several such associated
/// types; select one deterministically.
AssociatedTypeDecl *getAssociatedTypeAnchor() const;
/// Retrieve the (first) overridden associated type declaration, if any.
AssociatedTypeDecl *getOverriddenDecl() const {
return cast_or_null<AssociatedTypeDecl>(
AbstractTypeParamDecl::getOverriddenDecl());
}
/// Retrieve the set of associated types overridden by this associated
/// type.
llvm::TinyPtrVector<AssociatedTypeDecl *> getOverriddenDecls() const;
SourceLoc getStartLoc() const { return KeywordLoc; }
SourceRange getSourceRange() const;
static bool classof(const Decl *D) {
return D->getKind() == DeclKind::AssociatedType;
}
};
class MemberLookupTable;
class ConformanceLookupTable;
// Kinds of pointer types.
enum PointerTypeKind : unsigned {
PTK_UnsafeMutableRawPointer,
PTK_UnsafeRawPointer,
PTK_UnsafeMutablePointer,
PTK_UnsafePointer,
PTK_AutoreleasingUnsafeMutablePointer,
};
static inline bool isRawPointerKind(PointerTypeKind PTK) {
switch (PTK) {
case PTK_UnsafeMutableRawPointer:
case PTK_UnsafeRawPointer:
return true;
case PTK_UnsafeMutablePointer:
case PTK_UnsafePointer:
case PTK_AutoreleasingUnsafeMutablePointer:
return false;
}
llvm_unreachable("Unhandled PointerTypeKind in switch.");
}
enum KeyPathTypeKind : unsigned char {
KPTK_AnyKeyPath,
KPTK_PartialKeyPath,
KPTK_KeyPath,
KPTK_WritableKeyPath,
KPTK_ReferenceWritableKeyPath
};
/// NominalTypeDecl - a declaration of a nominal type, like a struct.
class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext {
SourceRange Braces;
/// The first extension of this type.
ExtensionDecl *FirstExtension = nullptr;
/// The last extension of this type, used solely for efficient
/// insertion of new extensions.
ExtensionDecl *LastExtension = nullptr;
/// The generation at which we last loaded extensions.
unsigned ExtensionGeneration;
/// Prepare to traverse the list of extensions.
void prepareExtensions();
/// Retrieve the conformance loader (if any), and removing it in the
/// same operation. The caller is responsible for loading the
/// conformances.
std::pair<LazyMemberLoader *, uint64_t> takeConformanceLoader() {
if (!Bits.NominalTypeDecl.HasLazyConformances)
return { nullptr, 0 };
return takeConformanceLoaderSlow();
}
/// Slow path for \c takeConformanceLoader().
std::pair<LazyMemberLoader *, uint64_t> takeConformanceLoaderSlow();
/// A lookup table containing all of the members of this type and
/// its extensions.
///
/// The table itself is lazily constructed and updated when
/// lookupDirect() is called. The bit indicates whether the lookup
/// table has already added members by walking the declarations in
/// scope; it should be manipulated through \c isLookupTablePopulated()
/// and \c setLookupTablePopulated().
llvm::PointerIntPair<MemberLookupTable *, 1, bool> LookupTable;
/// Prepare the lookup table to make it ready for lookups.
void prepareLookupTable();
/// True if the entries in \c LookupTable are complete--that is, if a
/// name is present, it contains all members with that name.
bool isLookupTablePopulated() const;
void setLookupTablePopulated(bool value);
/// Note that we have added a member into the iterable declaration context,
/// so that it can also be added to the lookup table (if needed).
void addedMember(Decl *member);
/// Note that we have added an extension into the nominal type,
/// so that its members can eventually be added to the lookup table.
void addedExtension(ExtensionDecl *ext);
/// A lookup table used to find the protocol conformances of
/// a given nominal type.
mutable ConformanceLookupTable *ConformanceTable = nullptr;
/// Prepare the conformance table.
void prepareConformanceTable() const;
/// Returns the protocol requirements that \c Member conforms to.
ArrayRef<ValueDecl *>
getSatisfiedProtocolRequirementsForMember(const ValueDecl *Member,
bool Sorted) const;
friend class ASTContext;
friend class MemberLookupTable;
friend class ConformanceLookupTable;
friend class ExtensionDecl;
friend class DeclContext;
friend class IterableDeclContext;
friend ArrayRef<ValueDecl *>
ValueDecl::getSatisfiedProtocolRequirements(bool Sorted) const;
protected:
Type DeclaredTy;
Type DeclaredInterfaceTy;
NominalTypeDecl(DeclKind K, DeclContext *DC, Identifier name,
SourceLoc NameLoc,
MutableArrayRef<TypeLoc> inherited,
GenericParamList *GenericParams) :
GenericTypeDecl(K, DC, name, NameLoc, inherited, GenericParams),
IterableDeclContext(IterableDeclContextKind::NominalTypeDecl)
{
Bits.NominalTypeDecl.AddedImplicitInitializers = false;
ExtensionGeneration = 0;
Bits.NominalTypeDecl.HasLazyConformances = false;
}
friend class ProtocolType;
public:
using GenericTypeDecl::getASTContext;
SourceRange getBraces() const { return Braces; }
void setBraces(SourceRange braces) { Braces = braces; }
/// Should this declaration behave as if it must be accessed
/// resiliently, even when we're building a non-resilient module?
///
/// This is used for diagnostics, because we do not want a behavior
/// change between builds with resilience enabled and disabled.
bool isFormallyResilient() const;
/// Do we need to use resilient access patterns outside of this type's
/// resilience domain?
bool isResilient() const;
/// Do we need to use resilient access patterns when accessing this
/// type from the given module?
bool isResilient(ModuleDecl *M, ResilienceExpansion expansion) const;
/// Determine whether we have already attempted to add any
/// implicitly-defined initializers to this declaration.
bool addedImplicitInitializers() const {
return Bits.NominalTypeDecl.AddedImplicitInitializers;
}
/// Note that we have attempted to add implicit initializers.
void setAddedImplicitInitializers() {
Bits.NominalTypeDecl.AddedImplicitInitializers = true;
}
/// Set the interface type of this nominal type to the metatype of the
/// declared interface type.
void computeType();
/// getDeclaredType - Retrieve the type declared by this entity, without
/// any generic parameters bound if this is a generic type.
Type getDeclaredType() const;
/// getDeclaredInterfaceType - Retrieve the type declared by this entity, with
/// generic parameters bound if this is a generic type.
Type getDeclaredInterfaceType() const;
/// Add a new extension to this nominal type.
void addExtension(ExtensionDecl *extension);
/// Retrieve the set of extensions of this type.
ExtensionRange getExtensions();
/// Special-behaviour flags passed to lookupDirect()
enum class LookupDirectFlags {
/// Whether to include @_implements members.
/// Used by conformance-checking to find special @_implements members.
IncludeAttrImplements = 1 << 0,
};
/// Find all of the declarations with the given name within this nominal type
/// and its extensions.
///
/// This routine does not look into superclasses, nor does it consider
/// protocols to which the nominal type conforms. Furthermore, the resulting
/// set of declarations has not been filtered for visibility, nor have
/// overridden declarations been removed.
TinyPtrVector<ValueDecl *> lookupDirect(DeclName name,
OptionSet<LookupDirectFlags> flags =
OptionSet<LookupDirectFlags>());
/// Collect the set of protocols to which this type should implicitly
/// conform, such as AnyObject (for classes).
void getImplicitProtocols(SmallVectorImpl<ProtocolDecl *> &protocols);
/// Look for conformances of this nominal type to the given
/// protocol.
///
/// \param module The module from which we initiate the search.
/// FIXME: This is currently unused.
///
/// \param protocol The protocol whose conformance is requested.
/// \param conformances Will be populated with the set of protocol
/// conformances found for this protocol.
///
/// \returns true if any conformances were found.
bool lookupConformance(
ModuleDecl *module, ProtocolDecl *protocol,
SmallVectorImpl<ProtocolConformance *> &conformances) const;
/// Retrieve all of the protocols that this nominal type conforms to.
SmallVector<ProtocolDecl *, 2> getAllProtocols() const;
/// Retrieve all of the protocol conformances for this nominal type.
SmallVector<ProtocolConformance *, 2> getAllConformances(
bool sorted = false) const;
/// Register an externally-created protocol conformance in the
/// conformance lookup table.
///
/// This is used by deserialization of module files to report
/// conformances.
void registerProtocolConformance(ProtocolConformance *conformance);
void setConformanceLoader(LazyMemberLoader *resolver, uint64_t contextData);
/// Is this the decl for Optional<T>?
bool isOptionalDecl() const;
/// Is this a key path type?
Optional<KeyPathTypeKind> getKeyPathTypeKind() const;
/// Retrieve information about this type as a property wrapper.
PropertyWrapperTypeInfo getPropertyWrapperTypeInfo() const;
// SWIFT_ENABLE_TENSORFLOW
/// Get effective memberwise initializer for the given nominal type, if it
/// exists: either a synthesized memberwise initializer or a user-defined
/// initializer with the same signature.
ConstructorDecl *getEffectiveMemberwiseInitializer();
// SWIFT_ENABLE_TENSORFLOW
/// Add `@_fixed_layout` attribute to the nominal type, if possible.
void addFixedLayoutAttr();
private:
/// Predicate used to filter StoredPropertyRange.
struct ToStoredProperty {
ToStoredProperty(bool skipInaccessible = false) :
skipUserInaccessible(skipInaccessible) {}
bool skipUserInaccessible;
Optional<VarDecl *> operator()(Decl *decl) const;
};
public:
/// A range for iterating the stored member variables of a structure.
using StoredPropertyRange = OptionalTransformRange<DeclRange,
ToStoredProperty>;
/// Return a collection of the stored member variables of this type.
ArrayRef<VarDecl *> getStoredProperties() const;
/// Return a collection of the stored member variables of this type, along
/// with placeholders for unimportable stored properties.
ArrayRef<Decl *> getStoredPropertiesAndMissingMemberPlaceholders() const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() >= DeclKind::First_NominalTypeDecl &&
D->getKind() <= DeclKind::Last_NominalTypeDecl;
}
static bool classof(const GenericTypeDecl *D) {
return D->getKind() >= DeclKind::First_NominalTypeDecl &&
D->getKind() <= DeclKind::Last_NominalTypeDecl;
}
static bool classof(const DeclContext *C) {
if (auto D = C->getAsDecl())
return classof(D);
return false;
}
static bool classof(const IterableDeclContext *C) {
return C->getIterableContextKind()
== IterableDeclContextKind::NominalTypeDecl;
}
static bool classof(const NominalTypeDecl *D) { return true; }
static bool classof(const ExtensionDecl *D) { return false; }
};
/// This is the declaration of an enum.
///
/// For example:
///
/// \code
/// enum Bool {
/// case false
/// case true
/// }
///
/// enum Optional<T> {
/// case none
/// case some(T)
/// }
/// \endcode
///
/// The type of the decl itself is a MetatypeType; use getDeclaredType()
/// to get the declared type ("Bool" or "Optional" in the above example).
class EnumDecl final : public NominalTypeDecl {
SourceLoc EnumLoc;
enum SemanticInfoFlags : uint8_t {
// Is the raw type valid?
HasComputedRawType = 1 << 0,
// Is the complete set of (auto-incremented) raw values available?
HasFixedRawValues = 1 << 1,
// Is the complete set of raw values type checked?
HasFixedRawValuesAndTypes = 1 << 2,
};
struct {
/// The raw type and a bit to indicate whether the
/// raw was computed yet or not.
llvm::PointerIntPair<Type, 3, OptionSet<SemanticInfoFlags>> RawTypeAndFlags;
bool hasRawType() const {
return RawTypeAndFlags.getInt().contains(HasComputedRawType);
}
void cacheRawType(Type ty) {
auto flags = RawTypeAndFlags.getInt() | HasComputedRawType;
RawTypeAndFlags.setPointerAndInt(ty, flags);
}
bool hasFixedRawValues() const {
return RawTypeAndFlags.getInt().contains(HasFixedRawValues);
}
bool hasCheckedRawValues() const {
return RawTypeAndFlags.getInt().contains(HasFixedRawValuesAndTypes);
}
} LazySemanticInfo;
friend class EnumRawValuesRequest;
friend class EnumRawTypeRequest;
friend class TypeChecker;
public:
EnumDecl(SourceLoc EnumLoc, Identifier Name, SourceLoc NameLoc,
MutableArrayRef<TypeLoc> Inherited,
GenericParamList *GenericParams, DeclContext *DC);
SourceLoc getStartLoc() const { return EnumLoc; }
SourceRange getSourceRange() const {
return SourceRange(EnumLoc, getBraces().End);
}
EnumElementDecl *getElement(Identifier Name) const;
public:
/// A range for iterating the elements of an enum.
using ElementRange = DowncastFilterRange<EnumElementDecl, DeclRange>;
/// A range for iterating the cases of an enum.
using CaseRange = DowncastFilterRange<EnumCaseDecl, DeclRange>;
/// Return a range that iterates over all the elements of an enum.
ElementRange getAllElements() const {
return ElementRange(getMembers());
}
unsigned getNumElements() const {
auto eltRange = getAllElements();
return std::distance(eltRange.begin(), eltRange.end());
}
/// If this enum has a unique element, return it. A unique element can
/// either hold a value or not, and the existence of one unique element does
/// not imply the existence or non-existence of the opposite unique element.
EnumElementDecl *getUniqueElement(bool hasValue) const;
/// Return a range that iterates over all the cases of an enum.
CaseRange getAllCases() const {
return CaseRange(getMembers());
}
/// Insert all of the 'case' element declarations into a DenseSet.
void getAllElements(llvm::DenseSet<EnumElementDecl*> &elements) const {
for (auto elt : getAllElements())
elements.insert(elt);
}
/// Retrieve the status of circularity checking for class inheritance.
CircularityCheck getCircularityCheck() const {
return static_cast<CircularityCheck>(Bits.EnumDecl.Circularity);
}
/// Record the current stage of circularity checking.
void setCircularityCheck(CircularityCheck circularity) {
Bits.EnumDecl.Circularity = static_cast<unsigned>(circularity);
}
/// Record that this enum has had all of its raw values computed.
void setHasFixedRawValues();
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() == DeclKind::Enum;
}
static bool classof(const GenericTypeDecl *D) {
return D->getKind() == DeclKind::Enum;
}
static bool classof(const NominalTypeDecl *D) {
return D->getKind() == DeclKind::Enum;
}
static bool classof(const DeclContext *C) {
if (auto D = C->getAsDecl())
return classof(D);
return false;
}
static bool classof(const IterableDeclContext *C) {
auto NTD = dyn_cast<NominalTypeDecl>(C);
return NTD && classof(NTD);
}
/// Determine whether this enum declares a raw type in its inheritance clause.
bool hasRawType() const { return (bool)getRawType(); }
/// Retrieve the declared raw type of the enum from its inheritance clause,
/// or null if it has none.
Type getRawType() const;
/// Set the raw type of the enum from its inheritance clause.
void setRawType(Type rawType) {
auto flags = LazySemanticInfo.RawTypeAndFlags.getInt();
LazySemanticInfo.RawTypeAndFlags.setPointerAndInt(
rawType, flags | HasComputedRawType);
}
/// True if none of the enum cases have associated values.
///
/// Note that this is true for enums with absolutely no cases.
bool hasOnlyCasesWithoutAssociatedValues() const;
/// True if any of the enum cases have availability annotations.
///
/// Note that this is false for enums with absolutely no cases.
bool hasPotentiallyUnavailableCaseValue() const;
/// True if the enum has cases.
bool hasCases() const {
return !getAllElements().empty();
}
/// True if the enum is marked 'indirect'.
bool isIndirect() const {
return getAttrs().hasAttribute<IndirectAttr>();
}
/// True if the enum can be exhaustively switched within \p useDC.
///
/// Note that this property is \e not necessarily true for all children of
/// \p useDC. In particular, an inlinable function does not get to switch
/// exhaustively over a non-exhaustive enum declared in the same module.
///
/// This is the predicate used when deciding if a switch statement needs a
/// default case. It should not be used for optimization or code generation.
///
/// \sa isEffectivelyExhaustive
bool isFormallyExhaustive(const DeclContext *useDC) const;
/// True if the enum can be exhaustively switched within a function defined
/// within \p M, with \p expansion specifying whether the function is
/// inlinable.
///
/// This is the predicate used when making optimization and code generation
/// decisions. It should not be used at the AST or semantic level.
///
/// \sa isFormallyExhaustive
bool isEffectivelyExhaustive(ModuleDecl *M,
ResilienceExpansion expansion) const;
};
/// StructDecl - This is the declaration of a struct, for example:
///
/// struct Complex { var R : Double, I : Double }
///
/// The type of the decl itself is a MetatypeType; use getDeclaredType()
/// to get the declared type ("Complex" in the above example).
class StructDecl final : public NominalTypeDecl {
SourceLoc StructLoc;
public:
StructDecl(SourceLoc StructLoc, Identifier Name, SourceLoc NameLoc,
MutableArrayRef<TypeLoc> Inherited,
GenericParamList *GenericParams, DeclContext *DC);
SourceLoc getStartLoc() const { return StructLoc; }
SourceRange getSourceRange() const {
return SourceRange(StructLoc, getBraces().End);
}
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() == DeclKind::Struct;
}
static bool classof(const GenericTypeDecl *D) {
return D->getKind() == DeclKind::Struct;
}
static bool classof(const NominalTypeDecl *D) {
return D->getKind() == DeclKind::Struct;
}
static bool classof(const DeclContext *C) {
if (auto D = C->getAsDecl())
return classof(D);
return false;
}
static bool classof(const IterableDeclContext *C) {
auto NTD = dyn_cast<NominalTypeDecl>(C);
return NTD && classof(NTD);
}
/// Does this struct contain unreferenceable storage, such as C fields that
/// cannot be represented in Swift?
bool hasUnreferenceableStorage() const {
return Bits.StructDecl.HasUnreferenceableStorage;
}
void setHasUnreferenceableStorage(bool v) {
Bits.StructDecl.HasUnreferenceableStorage = v;
}
};
/// The kind of artificial main to generate for a class.
enum class ArtificialMainKind : uint8_t {
NSApplicationMain,
UIApplicationMain,
};
/// This is the base type for AncestryOptions. Each flag describes possible
/// interesting kinds of superclasses that a class may have.
enum class AncestryFlags : uint8_t {
/// The class or one of its superclasses is @objc.
ObjC = (1<<0),
/// The class or one of its superclasses is @objcMembers.
ObjCMembers = (1<<1),
/// The class or one of its superclasses is generic.
Generic = (1<<2),
/// The class or one of its superclasses is resilient.
Resilient = (1<<3),
/// The class or one of its superclasses has resilient metadata and is in a
/// different resilience domain.
ResilientOther = (1<<4),
/// The class or one of its superclasses is imported from Clang.
ClangImported = (1<<5),
/// The class or one of its superclasses requires stored property initializers.
RequiresStoredPropertyInits = (1<<6),
};
/// Return type of ClassDecl::checkAncestry(). Describes a set of interesting
/// kinds of superclasses that a class may have.
using AncestryOptions = OptionSet<AncestryFlags>;
/// ClassDecl - This is the declaration of a class, for example:
///
/// class Complex { var R : Double, I : Double }
///
/// The type of the decl itself is a MetatypeType; use getDeclaredType()
/// to get the declared type ("Complex" in the above example).
class ClassDecl final : public NominalTypeDecl {
class ObjCMethodLookupTable;
SourceLoc ClassLoc;
ObjCMethodLookupTable *ObjCMethodLookup = nullptr;
/// Create the Objective-C member lookup table.
void createObjCMethodLookup();
struct {
/// The superclass decl and a bit to indicate whether the
/// superclass was computed yet or not.
llvm::PointerIntPair<ClassDecl *, 1, bool> SuperclassDecl;
/// The superclass type and a bit to indicate whether the
/// superclass was computed yet or not.
llvm::PointerIntPair<Type, 1, bool> SuperclassType;
} LazySemanticInfo;
bool hasForcedEmittedMembers() const {
return Bits.ClassDecl.HasForcedEmittedMembers;
}
void setHasForcedEmittedMembers() {
Bits.ClassDecl.HasForcedEmittedMembers = true;
}
friend class SuperclassDeclRequest;
friend class SuperclassTypeRequest;
friend class EmittedMembersRequest;
friend class TypeChecker;
public:
ClassDecl(SourceLoc ClassLoc, Identifier Name, SourceLoc NameLoc,
MutableArrayRef<TypeLoc> Inherited,
GenericParamList *GenericParams, DeclContext *DC);
SourceLoc getStartLoc() const { return ClassLoc; }
SourceRange getSourceRange() const {
return SourceRange(ClassLoc, getBraces().End);
}
/// Determine whether the member area of this class's metadata (which consists
/// of field offsets and vtable entries) is to be considered opaque by clients.
///
/// Note that even @_fixed_layout classes have resilient metadata if they are
/// in a resilient module.
bool hasResilientMetadata() const;
/// Determine whether this class has resilient metadata when accessed from the
/// given module and resilience expansion.
bool hasResilientMetadata(ModuleDecl *M, ResilienceExpansion expansion) const;
/// Determine whether this class has a superclass.
bool hasSuperclass() const { return (bool)getSuperclassDecl(); }
/// Retrieve the superclass of this class, or null if there is no superclass.
Type getSuperclass() const;
/// Retrieve the ClassDecl for the superclass of this class, or null if there
/// is no superclass.
ClassDecl *getSuperclassDecl() const;
/// Check if this class is a superclass or equal to the given class.
bool isSuperclassOf(ClassDecl *other) const;
/// Set the superclass of this class.
void setSuperclass(Type superclass);
/// Retrieve the status of circularity checking for class inheritance.
CircularityCheck getCircularityCheck() const {
return static_cast<CircularityCheck>(Bits.ClassDecl.Circularity);
}
/// Record the current stage of circularity checking.
void setCircularityCheck(CircularityCheck circularity) {
Bits.ClassDecl.Circularity = static_cast<unsigned>(circularity);
}
/// Walk this class and all of the superclasses of this class, transitively,
/// invoking the callback function for each class.
///
/// \param fn The callback function that will be invoked for each superclass.
/// It can return \c Continue to continue the traversal. Returning
/// \c SkipChildren halts the search and returns \c false, while returning
/// \c Stop halts the search and returns \c true.
///
/// \returns \c true if \c fn returned \c Stop for any class, \c false
/// otherwise.
bool walkSuperclasses(
llvm::function_ref<TypeWalker::Action(ClassDecl *)> fn) const;
//// Whether this class requires all of its stored properties to
//// have initializers in the class definition.
bool requiresStoredPropertyInits() const {
return checkAncestry(AncestryFlags::RequiresStoredPropertyInits);
}
/// \see getForeignClassKind
enum class ForeignKind : uint8_t {
/// A normal Swift or Objective-C class.
Normal = 0,
/// An imported Core Foundation type. These are AnyObject-compatible but
/// do not have runtime metadata.
CFType,
/// An imported Objective-C type whose class and metaclass symbols are not
/// both available at link-time but can be accessed through the Objective-C
/// runtime.
RuntimeOnly
};
/// Whether this class is "foreign", meaning that it is implemented
/// by a runtime that Swift does not have first-class integration
/// with. This generally means that:
/// - class data is either abstracted or cannot be made to
/// fit with Swift's metatype schema, and/or
/// - there is no facility for subclassing or adding polymorphic
/// methods to the class.
///
/// We may find ourselves wanting to break this bit into more
/// precise chunks later.
ForeignKind getForeignClassKind() const {
return static_cast<ForeignKind>(Bits.ClassDecl.RawForeignKind);
}
void setForeignClassKind(ForeignKind kind) {
Bits.ClassDecl.RawForeignKind = static_cast<unsigned>(kind);
}
/// Returns true if this class is any kind of "foreign class".
///
/// \see getForeignClassKind
bool isForeign() const {
return getForeignClassKind() != ForeignKind::Normal;
}
/// Returns true if the class has designated initializers that are not listed
/// in its members.
///
/// This can occur, for example, if the class is an Objective-C class with
/// initializers that cannot be represented in Swift.
bool hasMissingDesignatedInitializers() const;
void setHasMissingDesignatedInitializers(bool newValue = true) {
Bits.ClassDecl.ComputedHasMissingDesignatedInitializers = 1;
Bits.ClassDecl.HasMissingDesignatedInitializers = newValue;
}
/// Returns true if the class has missing members that require vtable entries.
///
/// In this case, the class cannot be subclassed, because we cannot construct
/// the vtable for the subclass.
bool hasMissingVTableEntries() const;
void setHasMissingVTableEntries(bool newValue = true) {
Bits.ClassDecl.ComputedHasMissingVTableEntries = 1;
Bits.ClassDecl.HasMissingVTableEntries = newValue;
}
/// Returns true if this class cannot be used with weak or unowned
/// references.
///
/// Note that this is true if this class or any of its ancestor classes
/// are marked incompatible.
bool isIncompatibleWithWeakReferences() const;
void setIsIncompatibleWithWeakReferences(bool newValue = true) {
Bits.ClassDecl.IsIncompatibleWithWeakReferences = newValue;
}
/// Find a method of a class that overrides a given method.
/// Return nullptr, if no such method exists.
AbstractFunctionDecl *findOverridingDecl(
const AbstractFunctionDecl *method) const;
/// Find a method implementation which will be used when a given method
/// is invoked on an instance of this class. This implementation may stem
/// either from a class itself or its direct or indirect superclasses.
AbstractFunctionDecl *findImplementingMethod(
const AbstractFunctionDecl *method) const;
/// Retrieve the destructor for this class.
DestructorDecl *getDestructor() const;
/// Determine whether this class inherits the convenience initializers
/// from its superclass.
bool inheritsSuperclassInitializers();
/// Marks that this class inherits convenience initializers from its
/// superclass.
///
/// This is computed as part of adding implicit initializers.
void setInheritsSuperclassInitializers() {
assert(addedImplicitInitializers());
Bits.ClassDecl.InheritsSuperclassInits = true;
}
/// Walks the class hierarchy starting from this class, checking various
/// conditions.
AncestryOptions checkAncestry() const;
/// Check if the class has ancestry of the given kind.
bool checkAncestry(AncestryFlags flag) const {
return checkAncestry().contains(flag);
}
/// The type of metaclass to use for a class.
enum class MetaclassKind : uint8_t {
ObjC,
SwiftStub,
};
/// Determine which sort of metaclass to use for this class
MetaclassKind getMetaclassKind() const;
/// Retrieve the name to use for this class when interoperating with
/// the Objective-C runtime.
StringRef getObjCRuntimeName(llvm::SmallVectorImpl<char> &buffer) const;
/// Returns the appropriate kind of entry point to generate for this class,
/// based on its attributes.
///
/// It is an error to call this on a class that does not have a
/// *ApplicationMain attribute.
ArtificialMainKind getArtificialMainKind() const;
using NominalTypeDecl::lookupDirect;
/// Look in this class and its extensions (but not any of its protocols or
/// superclasses) for declarations with a given Objective-C selector.
///
/// Note that this can find methods, initializers, deinitializers,
/// getters, and setters.
///
/// \param selector The Objective-C selector of the method we're
/// looking for.
///
/// \param isInstance Whether we are looking for an instance method
/// (vs. a class method).
MutableArrayRef<AbstractFunctionDecl *> lookupDirect(ObjCSelector selector,
bool isInstance);
/// Record the presence of an @objc method with the given selector.
void recordObjCMethod(AbstractFunctionDecl *method, ObjCSelector selector);
/// Get all the members of this class, synthesizing any implicit members
/// that appear in the vtable if needed.
DeclRange getEmittedMembers() const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() == DeclKind::Class;
}
static bool classof(const GenericTypeDecl *D) {
return D->getKind() == DeclKind::Class;
}
static bool classof(const NominalTypeDecl *D) {
return D->getKind() == DeclKind::Class;
}
static bool classof(const DeclContext *C) {
if (auto D = C->getAsDecl())
return classof(D);
return false;
}
static bool classof(const IterableDeclContext *C) {
auto NTD = dyn_cast<NominalTypeDecl>(C);
return NTD && classof(NTD);
}
/// Returns true if the decl uses the Objective-C generics model.
///
/// This is true of imported Objective-C classes.
bool usesObjCGenericsModel() const {
return hasClangNode() && isGenericContext() && isObjC();
}
/// True if the class is known to be implemented in Swift.
bool hasKnownSwiftImplementation() const {
return !hasClangNode();
}
};
/// Describes whether a requirement refers to 'Self', for use in the
/// is-inheritable and is-available-existential checks.
struct SelfReferenceKind {
bool result;
bool parameter;
bool requirement;
bool other;
/// The type does not refer to 'Self' at all.
static SelfReferenceKind None() {
return SelfReferenceKind(false, false, false, false);
}
/// The type refers to 'Self', but only as the result type of a method.
static SelfReferenceKind Result() {
return SelfReferenceKind(true, false, false, false);
}
/// The type refers to 'Self', but only as the parameter type of a method.
static SelfReferenceKind Parameter() {
return SelfReferenceKind(false, true, false, false);
}
/// The type refers to 'Self' within a same-type requiement.
static SelfReferenceKind Requirement() {
return SelfReferenceKind(false, false, true, false);
}
/// The type refers to 'Self' in a position that is invariant.
static SelfReferenceKind Other() {
return SelfReferenceKind(false, false, false, true);
}
SelfReferenceKind flip() const {
return SelfReferenceKind(parameter, result, requirement, other);
}
SelfReferenceKind operator|=(SelfReferenceKind kind) {
result |= kind.result;
requirement |= kind.requirement;
parameter |= kind.parameter;
other |= kind.other;
return *this;
}
operator bool() const {
return result || parameter || requirement || other;
}
private:
SelfReferenceKind(bool result, bool parameter, bool requirement, bool other)
: result(result), parameter(parameter), requirement(requirement),
other(other) { }
};
/// ProtocolDecl - A declaration of a protocol, for example:
///
/// protocol Drawable {
/// func draw()
/// }
///
/// Every protocol has an implicitly-created 'Self' generic parameter that
/// stands for a type that conforms to the protocol. For example,
///
/// protocol Cloneable {
/// func clone() -> Self
/// }
///
class ProtocolDecl final : public NominalTypeDecl {
SourceLoc ProtocolLoc;
ArrayRef<ProtocolDecl *> InheritedProtocols;
struct {
/// The superclass decl and a bit to indicate whether the
/// superclass was computed yet or not.
llvm::PointerIntPair<ClassDecl *, 1, bool> SuperclassDecl;
/// The superclass type and a bit to indicate whether the
/// superclass was computed yet or not.
llvm::PointerIntPair<Type, 1, bool> SuperclassType;
} LazySemanticInfo;
/// The generic signature representing exactly the new requirements introduced
/// by this protocol.
const Requirement *RequirementSignature = nullptr;
/// Returns the cached result of \c requiresClass or \c None if it hasn't yet
/// been computed.
Optional<bool> getCachedRequiresClass() const {
if (Bits.ProtocolDecl.RequiresClassValid)
return Bits.ProtocolDecl.RequiresClass;
return None;
}
/// Caches the result of \c requiresClass
void setCachedRequiresClass(bool requiresClass) {
Bits.ProtocolDecl.RequiresClassValid = true;
Bits.ProtocolDecl.RequiresClass = requiresClass;
}
/// Returns the cached result of \c existentialConformsToSelf or \c None if it
/// hasn't yet been computed.
Optional<bool> getCachedExistentialConformsToSelf() const {
if (Bits.ProtocolDecl.ExistentialConformsToSelfValid)
return Bits.ProtocolDecl.ExistentialConformsToSelf;
return None;
}
/// Caches the result of \c existentialConformsToSelf
void setCachedExistentialConformsToSelf(bool result) {
Bits.ProtocolDecl.ExistentialConformsToSelfValid = true;
Bits.ProtocolDecl.ExistentialConformsToSelf = result;
}
/// Returns the cached result of \c existentialTypeSupported or \c None if it
/// hasn't yet been computed.
Optional<bool> getCachedExistentialTypeSupported() {
if (Bits.ProtocolDecl.ExistentialTypeSupportedValid)
return Bits.ProtocolDecl.ExistentialTypeSupported;
return None;
}
/// Caches the result of \c existentialTypeSupported
void setCachedExistentialTypeSupported(bool supported) {
Bits.ProtocolDecl.ExistentialTypeSupportedValid = true;
Bits.ProtocolDecl.ExistentialTypeSupported = supported;
}
ArrayRef<ProtocolDecl *> getInheritedProtocolsSlow();
bool hasLazyRequirementSignature() const {
return Bits.ProtocolDecl.HasLazyRequirementSignature;
}
friend class SuperclassDeclRequest;
friend class SuperclassTypeRequest;
friend class RequirementSignatureRequest;
friend class ProtocolRequiresClassRequest;
friend class ExistentialConformsToSelfRequest;
friend class ExistentialTypeSupportedRequest;
friend class TypeChecker;
public:
ProtocolDecl(DeclContext *DC, SourceLoc ProtocolLoc, SourceLoc NameLoc,
Identifier Name, MutableArrayRef<TypeLoc> Inherited,
TrailingWhereClause *TrailingWhere);
using Decl::getASTContext;
/// Retrieve the set of protocols inherited from this protocol.
ArrayRef<ProtocolDecl *> getInheritedProtocols() const {
if (Bits.ProtocolDecl.InheritedProtocolsValid)
return InheritedProtocols;
return const_cast<ProtocolDecl *>(this)->getInheritedProtocolsSlow();
}
/// Determine whether this protocol has a superclass.
bool hasSuperclass() const { return (bool)getSuperclassDecl(); }
/// Retrieve the superclass of this protocol, or null if there is no superclass.
Type getSuperclass() const;
/// Retrieve the ClassDecl for the superclass of this protocol, or null if there
/// is no superclass.
ClassDecl *getSuperclassDecl() const;
/// Set the superclass of this protocol.
void setSuperclass(Type superclass);
/// Retrieve the set of AssociatedTypeDecl members of this protocol; this
/// saves loading the set of members in cases where there's no possibility of
/// a protocol having nested types (ObjC protocols).
llvm::TinyPtrVector<AssociatedTypeDecl *> getAssociatedTypeMembers() const;
/// Returns a protocol requirement with the given name, or nullptr if the
/// name has multiple overloads, or no overloads at all.
ValueDecl *getSingleRequirement(DeclName name) const;
/// Returns an associated type with the given name, or nullptr if one does
/// not exist.
AssociatedTypeDecl *getAssociatedType(Identifier name) const;
/// Walk this protocol and all of the protocols inherited by this protocol,
/// transitively, invoking the callback function for each protocol.
///
/// \param fn The callback function that will be invoked for each inherited
/// protocol. It can return \c Continue to continue the traversal,
/// \c SkipChildren to avoid visiting the children of the given protocol
/// but continue the search, and \c Stop to halt the search.
///
/// \returns \c true if \c fn returned \c Stop for any protocol, \c false
/// otherwise.
bool walkInheritedProtocols(
llvm::function_ref<TypeWalker::Action(ProtocolDecl *)> fn) const;
/// Determine whether this protocol inherits from the given ("super")
/// protocol.
bool inheritsFrom(const ProtocolDecl *Super) const;
ProtocolType *getDeclaredType() const {
return reinterpret_cast<ProtocolType *>(
NominalTypeDecl::getDeclaredType().getPointer());
}
SourceLoc getStartLoc() const { return ProtocolLoc; }
SourceRange getSourceRange() const {
return SourceRange(ProtocolLoc, getBraces().End);
}
/// True if this protocol can only be conformed to by class types.
bool requiresClass() const;
/// Determine whether an existential conforming to this protocol can be
/// matched with a generic type parameter constrained to this protocol.
/// This is only permitted if there is nothing "non-trivial" that we
/// can do with the metatype, which means the protocol must not have
/// any static methods and must be declared @objc.
bool existentialConformsToSelf() const;
/// Does this protocol require a self-conformance witness table?
bool requiresSelfConformanceWitnessTable() const;
/// Find direct Self references within the given requirement.
///
/// \param allowCovariantParameters If true, 'Self' is assumed to be
/// covariant anywhere; otherwise, only in the return type of the top-level
/// function type.
///
/// \param skipAssocTypes If true, associated types of 'Self' are ignored;
/// otherwise, they count as an 'other' usage of 'Self'.
SelfReferenceKind findProtocolSelfReferences(const ValueDecl *decl,
bool allowCovariantParameters,
bool skipAssocTypes) const;
/// Determine whether we are allowed to refer to an existential type
/// conforming to this protocol. This is only permitted if the type of
/// the member does not contain any associated types, and does not
/// contain 'Self' in 'parameter' or 'other' position.
bool isAvailableInExistential(const ValueDecl *decl) const;
/// Determine whether we are allowed to refer to an existential type
/// conforming to this protocol. This is only permitted if the types of
/// all the members do not contain any associated types, and do not
/// contain 'Self' in 'parameter' or 'other' position.
bool existentialTypeSupported() const;
private:
void computeKnownProtocolKind() const;
public:
/// If this is known to be a compiler-known protocol, returns the kind.
/// Otherwise returns None.
Optional<KnownProtocolKind> getKnownProtocolKind() const {
if (Bits.ProtocolDecl.KnownProtocol == 0)
computeKnownProtocolKind();
if (Bits.ProtocolDecl.KnownProtocol == 1)
return None;
return static_cast<KnownProtocolKind>(Bits.ProtocolDecl.KnownProtocol - 2);
}
/// Check whether this protocol is of a specific, known protocol kind.
bool isSpecificProtocol(KnownProtocolKind kind) const {
if (auto knownKind = getKnownProtocolKind())
return *knownKind == kind;
return false;
}
/// Retrieve the status of circularity checking for protocol inheritance.
CircularityCheck getCircularityCheck() const {
return static_cast<CircularityCheck>(Bits.ProtocolDecl.Circularity);
}
/// Record the current stage of circularity checking.
void setCircularityCheck(CircularityCheck circularity) {
Bits.ProtocolDecl.Circularity = static_cast<unsigned>(circularity);
}
/// Returns true if the protocol has requirements that are not listed in its
/// members.
///
/// This can occur, for example, if the protocol is an Objective-C protocol
/// with requirements that cannot be represented in Swift.
bool hasMissingRequirements() const {
(void)getMembers();
return Bits.ProtocolDecl.HasMissingRequirements;
}
void setHasMissingRequirements(bool newValue) {
Bits.ProtocolDecl.HasMissingRequirements = newValue;
}
/// Returns the default type witness for an associated type, or a null
/// type if there is no default.
Type getDefaultTypeWitness(AssociatedTypeDecl *assocType) const;
/// Set the default type witness for an associated type.
void setDefaultTypeWitness(AssociatedTypeDecl *assocType, Type witness);
/// Returns the default witness for a requirement, or nullptr if there is
/// no default.
Witness getDefaultWitness(ValueDecl *requirement) const;
/// Record the default witness for a requirement.
void setDefaultWitness(ValueDecl *requirement, Witness witness);
/// Returns the default associated conformance witness for an associated
/// type, or \c None if there is no default.
Optional<ProtocolConformanceRef> getDefaultAssociatedConformanceWitness(
CanType association,
ProtocolDecl *requirement) const;
/// Set the default associated conformance witness for the given
/// associated conformance.
void setDefaultAssociatedConformanceWitness(
CanType association,
ProtocolDecl *requirement,
ProtocolConformanceRef conformance);
/// Retrieve the name to use for this protocol when interoperating
/// with the Objective-C runtime.
StringRef getObjCRuntimeName(llvm::SmallVectorImpl<char> &buffer) const;
/// Retrieve the requirements that describe this protocol.
///
/// These are the requirements including any inherited protocols
/// and conformances for associated types that are introduced in this
/// protocol. Requirements implied via any other protocol (e.g., inherited
/// protocols of the inherited protocols) are not mentioned. The conformance
/// requirements listed here become entries in the witness table.
ArrayRef<Requirement> getRequirementSignature() const;
/// Is the requirement signature currently being computed?
bool isComputingRequirementSignature() const;
/// Has the requirement signature been computed yet?
bool isRequirementSignatureComputed() const {
return RequirementSignature != nullptr;
}
void setRequirementSignature(ArrayRef<Requirement> requirements);
void setLazyRequirementSignature(LazyMemberLoader *lazyLoader,
uint64_t requirementSignatureData);
private:
ArrayRef<Requirement> getCachedRequirementSignature() const;
public:
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() == DeclKind::Protocol;
}
static bool classof(const GenericTypeDecl *D) {
return D->getKind() == DeclKind::Protocol;
}
static bool classof(const NominalTypeDecl *D) {
return D->getKind() == DeclKind::Protocol;
}
static bool classof(const DeclContext *C) {
if (auto D = C->getAsDecl())
return classof(D);
return false;
}
static bool classof(const IterableDeclContext *C) {
auto NTD = dyn_cast<NominalTypeDecl>(C);
return NTD && classof(NTD);
}
};
/// AbstractStorageDecl - This is the common superclass for VarDecl and
/// SubscriptDecl, representing potentially settable memory locations.
class AbstractStorageDecl : public ValueDecl {
friend class SetterAccessLevelRequest;
friend class IsGetterMutatingRequest;
friend class IsSetterMutatingRequest;
friend class OpaqueReadOwnershipRequest;
friend class StorageImplInfoRequest;
friend class RequiresOpaqueAccessorsRequest;
friend class RequiresOpaqueModifyCoroutineRequest;
friend class SynthesizeAccessorRequest;
public:
static const size_t MaxNumAccessors = 255;
private:
/// A record of the accessors for the declaration.
class alignas(1 << 3) AccessorRecord final :
private llvm::TrailingObjects<AccessorRecord, AccessorDecl*> {
friend TrailingObjects;
using AccessorIndex = uint8_t;
static const AccessorIndex InvalidIndex = 0;
/// The range of the braces around the accessor clause.
SourceRange Braces;
/// The number of accessors currently stored in this record.
AccessorIndex NumAccessors;
/// The storage capacity of this record for accessors. Always includes
/// enough space for adding opaque accessors to the record, which are the
/// only accessors that should ever be added retroactively; hence this
/// field is only here for the purposes of safety checks.
AccessorIndex AccessorsCapacity;
/// Either 0, meaning there is no registered accessor of the given kind,
/// or the index+1 of the accessor in the accessors array.
AccessorIndex AccessorIndices[NumAccessorKinds];
AccessorRecord(SourceRange braces,
ArrayRef<AccessorDecl*> accessors,
AccessorIndex accessorsCapacity);
public:
static AccessorRecord *create(ASTContext &ctx, SourceRange braces,
ArrayRef<AccessorDecl*> accessors);
SourceRange getBracesRange() const { return Braces; }
inline AccessorDecl *getAccessor(AccessorKind kind) const;
ArrayRef<AccessorDecl *> getAllAccessors() const {
return { getTrailingObjects<AccessorDecl*>(), NumAccessors };
}
void addOpaqueAccessor(AccessorDecl *accessor);
private:
MutableArrayRef<AccessorDecl *> getAccessorsBuffer() {
return { getTrailingObjects<AccessorDecl*>(), NumAccessors };
}
bool registerAccessor(AccessorDecl *accessor, AccessorIndex index);
};
llvm::PointerIntPair<AccessorRecord*, 3, OptionalEnum<AccessLevel>> Accessors;
struct {
unsigned IsGetterMutatingComputed : 1;
unsigned IsGetterMutating : 1;
unsigned IsSetterMutatingComputed : 1;
unsigned IsSetterMutating : 1;
unsigned OpaqueReadOwnershipComputed : 1;
unsigned OpaqueReadOwnership : 2;
unsigned ImplInfoComputed : 1;
unsigned RequiresOpaqueAccessorsComputed : 1;
unsigned RequiresOpaqueAccessors : 1;
unsigned RequiresOpaqueModifyCoroutineComputed : 1;
unsigned RequiresOpaqueModifyCoroutine : 1;
} LazySemanticInfo = { };
/// The implementation info for the accessors.
StorageImplInfo ImplInfo;
/// Add a synthesized accessor.
void setSynthesizedAccessor(AccessorKind kind, AccessorDecl *getter);
protected:
AbstractStorageDecl(DeclKind Kind, bool IsStatic, DeclContext *DC,
DeclName Name, SourceLoc NameLoc,
StorageIsMutable_t supportsMutation)
: ValueDecl(Kind, DC, Name, NameLoc),
ImplInfo(StorageImplInfo::getSimpleStored(supportsMutation)) {
Bits.AbstractStorageDecl.IsStatic = IsStatic;
}
public:
/// Should this declaration be treated as if annotated with transparent
/// attribute.
bool isTransparent() const;
/// Is this a type ('static') variable?
bool isStatic() const {
return Bits.AbstractStorageDecl.IsStatic;
}
void setStatic(bool IsStatic) {
Bits.AbstractStorageDecl.IsStatic = IsStatic;
}
/// \returns the way 'static'/'class' should be spelled for this declaration.
StaticSpellingKind getCorrectStaticSpelling() const;
/// Return the interface type of the stored value.
Type getValueInterfaceType() const;
/// Determine how this storage is implemented.
StorageImplInfo getImplInfo() const;
/// Overwrite the registered implementation-info. This should be
/// used carefully.
void setImplInfo(StorageImplInfo implInfo) {
LazySemanticInfo.ImplInfoComputed = 1;
ImplInfo = implInfo;
}
ReadImplKind getReadImpl() const {
return getImplInfo().getReadImpl();
}
WriteImplKind getWriteImpl() const {
return getImplInfo().getWriteImpl();
}
ReadWriteImplKind getReadWriteImpl() const {
return getImplInfo().getReadWriteImpl();
}
/// Return true if this is a VarDecl that has storage associated with
/// it.
bool hasStorage() const {
return getImplInfo().hasStorage();
}
/// Return true if this storage has the basic accessors/capability
/// to be mutated. This is generally constant after the accessors are
/// installed by the parser/importer/whatever.
///
/// Note that this is different from the mutability of the declaration
/// in the user language: sometimes we can assign to declarations that
/// don't support mutation (e.g. to initialize them), and sometimes we
/// can't mutate things that do support mutation (e.g. because their
/// setter is private).
StorageIsMutable_t supportsMutation() const {
return getImplInfo().supportsMutation();
}
/// isSettable - Determine whether references to this decl may appear
/// on the left-hand side of an assignment or as the operand of a
/// `&` or 'inout' operator.
bool isSettable(const DeclContext *UseDC,
const DeclRefExpr *base = nullptr) const;
/// Does this storage declaration have explicitly-defined accessors
/// written in the source?
bool hasParsedAccessors() const;
/// Return the ownership of values opaquely read from this storage.
OpaqueReadOwnership getOpaqueReadOwnership() const;
void setOpaqueReadOwnership(OpaqueReadOwnership ownership) {
LazySemanticInfo.OpaqueReadOwnership = unsigned(ownership);
LazySemanticInfo.OpaqueReadOwnershipComputed = true;
}
/// Return true if reading this storage requires the ability to
/// modify the base value.
bool isGetterMutating() const;
void setIsGetterMutating(bool isMutating) {
LazySemanticInfo.IsGetterMutating = isMutating;
LazySemanticInfo.IsGetterMutatingComputed = true;
}
/// Return true if modifying this storage requires the ability to
/// modify the base value.
bool isSetterMutating() const;
void setIsSetterMutating(bool isMutating) {
LazySemanticInfo.IsSetterMutating = isMutating;
LazySemanticInfo.IsSetterMutatingComputed = true;
}
AccessorDecl *getAccessor(AccessorKind kind) const {
if (auto info = Accessors.getPointer())
return info->getAccessor(kind);
return nullptr;
}
ArrayRef<AccessorDecl*> getAllAccessors() const {
if (const auto *info = Accessors.getPointer())
return info->getAllAccessors();
return {};
}
/// Return an accessor that this storage is expected to have, synthesizing
/// one if necessary. Note that will always synthesize one, even if the
/// accessor is not part of the expected opaque set for the storage, so use
/// with caution.
AccessorDecl *getSynthesizedAccessor(AccessorKind kind) const;
/// Return an accessor part of the set of opaque accessors dictated by the
/// requirements of the ABI.
///
/// This will synthesize the accessor if one is required but not specified
/// in source; for example, most of the time a mutable property is required
/// to have a 'modify' accessor, but if the property was only written with
/// 'get' and 'set' accessors, 'modify' will be synthesized to call 'get'
/// followed by 'set'.
///
/// If the accessor is not needed for ABI reasons, this returns nullptr.
/// To ensure an accessor is always returned, use getSynthesizedAccessor().
AccessorDecl *getOpaqueAccessor(AccessorKind kind) const;
/// Return an accessor that was written in source. Returns null if the
/// accessor was not explicitly defined by the user.
AccessorDecl *getParsedAccessor(AccessorKind kind) const;
/// Visit all parsed accessors.
void visitParsedAccessors(llvm::function_ref<void (AccessorDecl*)>) const;
/// Visit all opaque accessor kinds.
void visitExpectedOpaqueAccessors(
llvm::function_ref<void (AccessorKind)>) const;
/// Visit all opaque accessors.
void visitOpaqueAccessors(llvm::function_ref<void (AccessorDecl*)>) const;
/// Visit all eagerly emitted accessors.
///
/// This is the union of the parsed and opaque sets.
void visitEmittedAccessors(llvm::function_ref<void (AccessorDecl*)>) const;
void setAccessors(SourceLoc lbraceLoc, ArrayRef<AccessorDecl*> accessors,
SourceLoc rbraceLoc);
/// Add a setter to an existing Computed var.
///
/// This should only be used by the ClangImporter.
void setComputedSetter(AccessorDecl *Set);
/// Does this storage require opaque accessors of any kind?
bool requiresOpaqueAccessors() const;
/// Does this storage require an opaque accessor of the given kind?
bool requiresOpaqueAccessor(AccessorKind kind) const;
/// Does this storage require a 'get' accessor in its opaque-accessors set?
bool requiresOpaqueGetter() const {
return getOpaqueReadOwnership() != OpaqueReadOwnership::Borrowed;
}
/// Does this storage require a 'read' accessor in its opaque-accessors set?
bool requiresOpaqueReadCoroutine() const {
return getOpaqueReadOwnership() != OpaqueReadOwnership::Owned;
}
/// Does this storage require a 'set' accessor in its opaque-accessors set?
bool requiresOpaqueSetter() const { return supportsMutation(); }
/// Does this storage require a 'modify' accessor in its opaque-accessors set?
bool requiresOpaqueModifyCoroutine() const;
SourceRange getBracesRange() const {
if (auto info = Accessors.getPointer())
return info->getBracesRange();
return SourceRange();
}
AccessLevel getSetterFormalAccess() const;
AccessScope
getSetterFormalAccessScope(const DeclContext *useDC = nullptr,
bool treatUsableFromInlineAsPublic = false) const;
void setSetterAccess(AccessLevel accessLevel) {
assert(!Accessors.getInt().hasValue());
overwriteSetterAccess(accessLevel);
}
void overwriteSetterAccess(AccessLevel accessLevel);
/// Given that this is an Objective-C property or subscript declaration,
/// produce its getter selector.
ObjCSelector
getObjCGetterSelector(Identifier preferredName = Identifier()) const;
/// Given that this is an Objective-C property or subscript declaration,
/// produce its setter selector.
ObjCSelector
getObjCSetterSelector(Identifier preferredName = Identifier()) const;
AbstractStorageDecl *getOverriddenDecl() const {
return cast_or_null<AbstractStorageDecl>(ValueDecl::getOverriddenDecl());
}
/// Returns the location of 'override' keyword, if any.
SourceLoc getOverrideLoc() const;
/// Returns true if this declaration has a setter accessible from the given
/// context.
///
/// If \p DC is null, returns true only if the setter is public.
///
/// See \c isAccessibleFrom for a discussion of the \p forConformance
/// parameter.
bool isSetterAccessibleFrom(const DeclContext *DC,
bool forConformance=false) const;
/// Determine how this storage declaration should actually be accessed.
AccessStrategy getAccessStrategy(AccessSemantics semantics,
AccessKind accessKind,
ModuleDecl *module,
ResilienceExpansion expansion) const;
/// Should this declaration behave as if it must be accessed
/// resiliently, even when we're building a non-resilient module?
///
/// This is used for diagnostics, because we do not want a behavior
/// change between builds with resilience enabled and disabled.
bool isFormallyResilient() const;
/// Do we need to use resilient access patterns outside of this
/// property's resilience domain?
bool isResilient() const;
/// Do we need to use resilient access patterns when accessing this
/// property from the given module?
bool isResilient(ModuleDecl *M, ResilienceExpansion expansion) const;
/// True if the storage can be referenced by a keypath directly.
/// Otherwise, its override must be referenced.
bool isValidKeyPathComponent() const;
/// True if the storage exports a property descriptor for key paths in
/// other modules.
bool exportsPropertyDescriptor() const;
/// True if any of the accessors to the storage is private or fileprivate.
bool hasPrivateAccessor() const;
bool hasDidSetOrWillSetDynamicReplacement() const;
bool hasAnyNativeDynamicAccessors() const;
bool hasAnyDynamicReplacementAccessors() const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() >= DeclKind::First_AbstractStorageDecl &&
D->getKind() <= DeclKind::Last_AbstractStorageDecl;
}
};
/// Describes which synthesized property for a property with an attached
/// wrapper is being referenced.
enum class PropertyWrapperSynthesizedPropertyKind {
/// The backing storage property, which is a stored property of the
/// wrapper type.
Backing,
/// A storage wrapper (e.g., `$foo`), which is a wrapper over the
/// wrapper instance's `projectedValue` property.
StorageWrapper,
};
/// VarDecl - 'var' and 'let' declarations.
class VarDecl : public AbstractStorageDecl {
public:
enum class Introducer : uint8_t {
Let = 0,
Var = 1
};
protected:
PointerUnion<PatternBindingDecl *, Stmt *, VarDecl *> Parent;
VarDecl(DeclKind kind, bool isStatic, Introducer introducer,
bool issCaptureList, SourceLoc nameLoc, Identifier name,
DeclContext *dc, StorageIsMutable_t supportsMutation);
/// This is the type specified, including location information.
TypeLoc typeLoc;
Type typeInContext;
public:
VarDecl(bool isStatic, Introducer introducer, bool isCaptureList,
SourceLoc nameLoc, Identifier name, DeclContext *dc)
: VarDecl(DeclKind::Var, isStatic, introducer, isCaptureList, nameLoc,
name, dc, StorageIsMutable_t(introducer == Introducer::Var)) {}
SourceRange getSourceRange() const;
Identifier getName() const { return getFullName().getBaseIdentifier(); }
/// Returns the string for the base name, or "_" if this is unnamed.
StringRef getNameStr() const {
assert(!getFullName().isSpecial() && "Cannot get string for special names");
return hasName() ? getBaseName().getIdentifier().str() : "_";
}
TypeLoc &getTypeLoc() { return typeLoc; }
TypeLoc getTypeLoc() const { return typeLoc; }
bool hasType() const {
// We have a type if either the type has been computed already or if
// this is a deserialized declaration with an interface type.
return !typeInContext.isNull();
}
/// Get the type of the variable within its context. If the context is generic,
/// this will use archetypes.
Type getType() const;
/// Set the type of the variable within its context.
void setType(Type t);
void markInvalid();
/// Retrieve the source range of the variable type, or an invalid range if the
/// variable's type is not explicitly written in the source.
///
/// Only for use in diagnostics. It is not always possible to always
/// precisely point to the variable type because of type aliases.
SourceRange getTypeSourceRangeForDiagnostics() const;
/// Returns whether the var is settable in the specified context: this
/// is either because it is a stored var, because it has a custom setter, or
/// is a let member in an initializer.
///
/// Pass a null context and null base to check if it's always settable.
bool isSettable(const DeclContext *UseDC,
const DeclRefExpr *base = nullptr) const;
/// Return the parent pattern binding that may provide an initializer for this
/// VarDecl. This returns null if there is none associated with the VarDecl.
PatternBindingDecl *getParentPatternBinding() const {
if (!Parent)
return nullptr;
return Parent.dyn_cast<PatternBindingDecl *>();
}
void setParentPatternBinding(PatternBindingDecl *PBD) {
assert(PBD);
Parent = PBD;
}
/// Return the Pattern involved in initializing this VarDecl. However, recall
/// that the Pattern may be involved in initializing more than just this one
/// vardecl. For example, if this is a VarDecl for "x", the pattern may be
/// "(x, y)" and the initializer on the PatternBindingDecl may be "(1,2)" or
/// "foo()".
///
/// If this has no parent pattern binding decl or statement associated, it
/// returns null.
///
Pattern *getParentPattern() const;
/// Return the statement that owns the pattern associated with this VarDecl,
/// if one exists.
///
/// NOTE: After parsing and before type checking, all VarDecls from
/// CaseLabelItem's Patterns return their CaseStmt. After type checking, we
/// will have constructed the CaseLabelItem VarDecl linked list implying this
/// will return nullptr. After type checking, if one wishes to find a parent
/// pattern of a VarDecl of a CaseStmt, \see getRecursiveParentPatternStmt
/// instead.
Stmt *getParentPatternStmt() const {
if (!Parent)
return nullptr;
return Parent.dyn_cast<Stmt *>();
}
void setParentPatternStmt(Stmt *s) {
assert(s);
Parent = s;
}
/// Look for the parent pattern stmt of this var decl, recursively
/// looking through var decl pointers and then through any
/// fallthroughts.
Stmt *getRecursiveParentPatternStmt() const;
/// Returns the var decl that this var decl is an implicit reference to if
/// such a var decl exists.
VarDecl *getParentVarDecl() const {
if (!Parent)
return nullptr;
return Parent.dyn_cast<VarDecl *>();
}
/// Set \p v to be the pattern produced VarDecl that is the parent of this
/// var decl.
void setParentVarDecl(VarDecl *v) {
assert(v && v != this);
Parent = v;
}
/// If this is a VarDecl that does not belong to a CaseLabelItem's pattern,
/// return this. Otherwise, this VarDecl must belong to a CaseStmt's
/// CaseLabelItem. In that case, return the first case label item of the first
/// case stmt in a sequence of case stmts that fallthrough into each other.
///
/// NOTE: During type checking, we emit an error if we have a single case
/// label item with a pattern that has multiple var decls of the same
/// name. This means that during type checking and before type checking, we
/// may have a _malformed_ switch stmt var decl linked list since var decls in
/// the same case label item that have the same name will point at the same
/// canonical var decl, namely the first var decl with the name in the
/// canonical case label item's var decl list. This is ok, since we are going
/// to emit the error, but it requires us to be more careful/cautious before
/// type checking has been complete when relying on canonical var decls
/// matching up.
VarDecl *getCanonicalVarDecl() const;
/// If this is a case stmt var decl, return the var decl that corresponds to
/// this var decl in the first case label item of the case stmt. Returns
/// nullptr if this isn't a VarDecl that is part of a case stmt.
NullablePtr<VarDecl> getCorrespondingFirstCaseLabelItemVarDecl() const;
/// If this is a case stmt var decl, return the case body var decl that this
/// var decl maps to.
NullablePtr<VarDecl> getCorrespondingCaseBodyVariable() const;
/// Return true if this var decl is an implicit var decl belonging to a case
/// stmt's body.
bool isCaseBodyVariable() const;
/// True if the global stored property requires lazy initialization.
bool isLazilyInitializedGlobal() const;
/// Return the initializer involved in this VarDecl. Recall that the
/// initializer may be involved in initializing more than just this one
/// vardecl though. For example, if this is a VarDecl for "x", the pattern
/// may be "(x, y)" and the initializer on the PatternBindingDecl may be
/// "(1,2)" or "foo()".
///
/// If this has no parent pattern binding decl associated, or if that pattern
/// binding has no initial value, this returns null.
///
Expr *getParentInitializer() const {
if (auto *PBD = getParentPatternBinding())
return PBD->getPatternEntryForVarDecl(this).getInit();
return nullptr;
}
/// Whether there exists an initializer for this \c VarDecl.
bool isParentInitialized() const {
if (auto *PBD = getParentPatternBinding())
return PBD->getPatternEntryForVarDecl(this).isInitialized();
return false;
}
// Return whether this VarDecl has an initial value, either by checking
// if it has an initializer in its parent pattern binding or if it has
// the @_hasInitialValue attribute.
bool hasInitialValue() const {
return getAttrs().hasAttribute<HasInitialValueAttr>() ||
isParentInitialized();
}
VarDecl *getOverriddenDecl() const {
return cast_or_null<VarDecl>(AbstractStorageDecl::getOverriddenDecl());
}
/// Is this an immutable 'let' property?
///
/// If this is a ParamDecl, isLet() is true iff
/// getSpecifier() == Specifier::Default.
bool isLet() const { return getIntroducer() == Introducer::Let; }
Introducer getIntroducer() const {
return Introducer(Bits.VarDecl.Introducer);
}
void setIntroducer(Introducer value) {
Bits.VarDecl.Introducer = uint8_t(value);
}
/// Is this an element in a capture list?
bool isCaptureList() const { return Bits.VarDecl.IsCaptureList; }
/// Return true if this vardecl has an initial value bound to it in a way
/// that isn't represented in the AST with an initializer in the pattern
/// binding. This happens in cases like "for i in ...", switch cases, etc.
bool hasNonPatternBindingInit() const {
return Bits.VarDecl.HasNonPatternBindingInit;
}
void setHasNonPatternBindingInit(bool V = true) {
Bits.VarDecl.HasNonPatternBindingInit = V;
}
/// Determines if this var has an initializer expression that should be
/// exposed to clients.
/// There's a very narrow case when we would: if the decl is an instance
/// member with an initializer expression and the parent type is
/// @frozen and resides in a resilient module.
bool isInitExposedToClients() const;
/// Is this a special debugger variable?
bool isDebuggerVar() const { return Bits.VarDecl.IsDebuggerVar; }
void setDebuggerVar(bool IsDebuggerVar) {
Bits.VarDecl.IsDebuggerVar = IsDebuggerVar;
}
/// Is this the synthesized storage for a 'lazy' property?
bool isLazyStorageProperty() const {
return Bits.VarDecl.IsLazyStorageProperty;
}
void setLazyStorageProperty(bool IsLazyStorage) {
Bits.VarDecl.IsLazyStorageProperty = IsLazyStorage;
}
/// Retrieve the custom attributes that attach property wrappers to this
/// property. The returned list contains all of the attached property wrapper attributes in source order,
/// which means the outermost wrapper attribute is provided first.
llvm::TinyPtrVector<CustomAttr *> getAttachedPropertyWrappers() const;
/// Whether this property has any attached property wrappers.
bool hasAttachedPropertyWrapper() const;
/// Whether all of the attached property wrappers have an init(initialValue:) initializer.
bool allAttachedPropertyWrappersHaveInitialValueInit() const;
/// Retrieve the type of the attached property wrapper as a contextual
/// type.
///
/// \param index Which property wrapper type is being computed, where 0
/// indicates the first (outermost) attached property wrapper.
///
/// \returns a NULL type for properties without attached wrappers,
/// an error type when the property wrapper type itself is erroneous,
/// or the wrapper type itself, which may involve unbound generic
/// types.
Type getAttachedPropertyWrapperType(unsigned index) const;
/// Retrieve information about the attached property wrapper type.
///
/// \param i Which attached property wrapper type is being queried, where 0 is the outermost (first)
/// attached property wrapper type.
PropertyWrapperTypeInfo getAttachedPropertyWrapperTypeInfo(unsigned i) const;
/// Retrieve the fully resolved attached property wrapper type.
///
/// This type will be the fully-resolved form of
/// \c getAttachedPropertyWrapperType(0), which will not contain any
/// unbound generic types. It will be the type of the backing property.
Type getPropertyWrapperBackingPropertyType() const;
/// Retrieve information about the backing properties of the attached
/// property wrapper.
PropertyWrapperBackingPropertyInfo
getPropertyWrapperBackingPropertyInfo() const;
/// Retrieve information about the mutability of the composed
/// property wrappers.
Optional<PropertyWrapperMutability>
getPropertyWrapperMutability() const;
/// Retrieve the backing storage property for a property that has an
/// attached property wrapper.
///
/// The backing storage property will be a stored property of the
/// wrapper's type. This will be equivalent to
/// \c getAttachedPropertyWrapperType(0) when it is fully-specified;
/// if \c getAttachedPropertyWrapperType(0) involves an unbound
/// generic type, the backing storage property will be the appropriate
/// bound generic version.
VarDecl *getPropertyWrapperBackingProperty() const;
/// Retreive the storage wrapper for a property that has an attached
/// property wrapper.
VarDecl *getPropertyWrapperStorageWrapper() const;
/// Retrieve the backing storage property for a lazy property.
VarDecl *getLazyStorageProperty() const;
/// Whether this is a property with a property wrapper that was initialized
/// via a value of the original type, e.g.,
///
/// \code
/// @Lazy var i = 17
/// \end
bool isPropertyWrapperInitializedWithInitialValue() const;
/// Whether the memberwise initializer parameter for a property with a property wrapper type
/// uses the wrapped type.
bool isPropertyMemberwiseInitializedWithWrappedType() const;
/// If this property is the backing storage for a property with an attached
/// property wrapper, return the original property.
///
/// \param kind If not \c None, only returns the original property when
/// \c this property is the specified synthesized property.
VarDecl *getOriginalWrappedProperty(
Optional<PropertyWrapperSynthesizedPropertyKind> kind = None) const;
/// Set the property that wraps to this property as it's backing
/// property.
void setOriginalWrappedProperty(VarDecl *originalProperty);
/// Return the Objective-C runtime name for this property.
Identifier getObjCPropertyName() const;
/// Retrieve the default Objective-C selector for the getter of a
/// property of the given name.
static ObjCSelector getDefaultObjCGetterSelector(ASTContext &ctx,
Identifier propertyName);
/// Retrieve the default Objective-C selector for the setter of a
/// property of the given name.
static ObjCSelector getDefaultObjCSetterSelector(ASTContext &ctx,
Identifier propertyName);
/// If this is a simple 'let' constant, emit a note with a fixit indicating
/// that it can be rewritten to a 'var'. This is used in situations where the
/// compiler detects obvious attempts to mutate a constant.
void emitLetToVarNoteIfSimple(DeclContext *UseDC) const;
/// Returns true if the name is the self identifier and is implicit.
bool isSelfParameter() const;
/// Determine whether this property will be part of the implicit memberwise
/// initializer.
///
/// \param preferDeclaredProperties When encountering a `lazy` property
/// or a property that has an attached property wrapper, prefer the
/// actual declared property (which may or may not be considered "stored"
/// as the moment) to the backing storage property. Otherwise, the stored
/// backing property will be treated as the member-initialized property.
bool isMemberwiseInitialized(bool preferDeclaredProperties) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() == DeclKind::Var || D->getKind() == DeclKind::Param;
}
};
/// A function parameter declaration.
class ParamDecl : public VarDecl {
Identifier ArgumentName;
SourceLoc ParameterNameLoc;
SourceLoc ArgumentNameLoc;
SourceLoc SpecifierLoc;
struct StoredDefaultArgument {
PointerUnion<Expr *, VarDecl *> DefaultArg;
Initializer *InitContext = nullptr;
StringRef StringRepresentation;
CaptureInfo Captures;
};
enum class Flags : uint8_t {
/// Whether or not this parameter is vargs.
IsVariadic = 1 << 0,
/// Whether or not this parameter is `@autoclosure`.
IsAutoClosure = 1 << 1,
};
/// The default value, if any, along with flags.
llvm::PointerIntPair<StoredDefaultArgument *, 2, OptionSet<Flags>>
DefaultValueAndFlags;
public:
enum class Specifier : uint8_t {
Default = 0,
InOut = 1,
Shared = 2,
Owned = 3,
};
ParamDecl(Specifier specifier,
SourceLoc specifierLoc, SourceLoc argumentNameLoc,
Identifier argumentName, SourceLoc parameterNameLoc,
Identifier parameterName, DeclContext *dc);
/// Clone constructor, allocates a new ParamDecl identical to the first.
/// Intentionally not defined as a typical copy constructor to avoid
/// accidental copies.
ParamDecl(ParamDecl *PD, bool withTypes);
/// Retrieve the argument (API) name for this function parameter.
Identifier getArgumentName() const { return ArgumentName; }
/// Retrieve the parameter (local) name for this function parameter.
Identifier getParameterName() const { return getName(); }
/// Retrieve the source location of the argument (API) name.
///
/// The resulting source location will be valid if the argument name
/// was specified separately from the parameter name.
SourceLoc getArgumentNameLoc() const { return ArgumentNameLoc; }
SourceLoc getParameterNameLoc() const { return ParameterNameLoc; }
SourceLoc getSpecifierLoc() const { return SpecifierLoc; }
bool isTypeLocImplicit() const { return Bits.ParamDecl.IsTypeLocImplicit; }
void setIsTypeLocImplicit(bool val) { Bits.ParamDecl.IsTypeLocImplicit = val; }
DefaultArgumentKind getDefaultArgumentKind() const {
return static_cast<DefaultArgumentKind>(Bits.ParamDecl.defaultArgumentKind);
}
bool isDefaultArgument() const {
return getDefaultArgumentKind() != DefaultArgumentKind::None;
}
void setDefaultArgumentKind(DefaultArgumentKind K) {
Bits.ParamDecl.defaultArgumentKind = static_cast<unsigned>(K);
}
Expr *getDefaultValue() const {
if (auto stored = DefaultValueAndFlags.getPointer())
return stored->DefaultArg.dyn_cast<Expr *>();
return nullptr;
}
VarDecl *getStoredProperty() const {
if (auto stored = DefaultValueAndFlags.getPointer())
return stored->DefaultArg.dyn_cast<VarDecl *>();
return nullptr;
}
void setDefaultValue(Expr *E);
void setStoredProperty(VarDecl *var);
Initializer *getDefaultArgumentInitContext() const {
if (auto stored = DefaultValueAndFlags.getPointer())
return stored->InitContext;
return nullptr;
}
void setDefaultArgumentInitContext(Initializer *initContext);
const CaptureInfo &getDefaultArgumentCaptureInfo() const {
assert(DefaultValueAndFlags.getPointer());
return DefaultValueAndFlags.getPointer()->Captures;
}
void setDefaultArgumentCaptureInfo(const CaptureInfo &captures);
/// Extracts the text of the default argument attached to the provided
/// ParamDecl, removing all inactive #if clauses and providing only the
/// text of active #if clauses.
///
/// For example, the default argument:
/// ```
/// {
/// #if false
/// print("false")
/// #else
/// print("true")
/// #endif
/// }
/// ```
/// will return
/// ```
/// {
/// print("true")
/// }
/// ```
/// \sa getDefaultValue
StringRef getDefaultValueStringRepresentation(
SmallVectorImpl<char> &scratch) const;
void setDefaultValueStringRepresentation(StringRef stringRepresentation);
/// Whether or not this parameter is varargs.
bool isVariadic() const {
return DefaultValueAndFlags.getInt().contains(Flags::IsVariadic);
}
void setVariadic(bool value = true) {
auto flags = DefaultValueAndFlags.getInt();
DefaultValueAndFlags.setInt(value ? flags | Flags::IsVariadic
: flags - Flags::IsVariadic);
}
/// Whether or not this parameter is marked with `@autoclosure`.
bool isAutoClosure() const {
return DefaultValueAndFlags.getInt().contains(Flags::IsAutoClosure);
}
void setAutoClosure(bool value = true) {
auto flags = DefaultValueAndFlags.getInt();
DefaultValueAndFlags.setInt(value ? flags | Flags::IsAutoClosure
: flags - Flags::IsAutoClosure);
}
/// Remove the type of this varargs element designator, without the array
/// type wrapping it. A parameter like "Int..." will have formal parameter
/// type of "[Int]" and this returns "Int".
static Type getVarargBaseTy(Type VarArgT);
/// Remove the type of this varargs element designator, without the array
/// type wrapping it.
Type getVarargBaseTy() const {
assert(isVariadic());
return getVarargBaseTy(getInterfaceType());
}
/// Determine whether this declaration is an anonymous closure parameter.
bool isAnonClosureParam() const;
/// Return the raw specifier value for this parameter.
Specifier getSpecifier() const {
return static_cast<Specifier>(Bits.ParamDecl.Specifier);
}
void setSpecifier(Specifier Spec);
/// Is the type of this parameter 'inout'?
bool isInOut() const { return getSpecifier() == Specifier::InOut; }
/// Is this an immutable 'shared' property?
bool isShared() const { return getSpecifier() == Specifier::Shared; }
/// Is this an immutable 'owned' property?
bool isOwned() const { return getSpecifier() == Specifier::Owned; }
bool isImmutable() const {
return isImmutableSpecifier(getSpecifier());
}
static bool isImmutableSpecifier(Specifier sp) {
switch (sp) {
case Specifier::Default:
case Specifier::Shared:
case Specifier::Owned:
return true;
case Specifier::InOut:
return false;
}
llvm_unreachable("unhandled specifier");
}
ValueOwnership getValueOwnership() const {
return getValueOwnershipForSpecifier(getSpecifier());
}
static ValueOwnership getValueOwnershipForSpecifier(Specifier specifier) {
switch (specifier) {
case Specifier::Default:
return ValueOwnership::Default;
case Specifier::InOut:
return ValueOwnership::InOut;
case Specifier::Shared:
return ValueOwnership::Shared;
case Specifier::Owned:
return ValueOwnership::Owned;
}
llvm_unreachable("unhandled specifier");
}
static Specifier
getParameterSpecifierForValueOwnership(ValueOwnership ownership) {
switch (ownership) {
case ValueOwnership::Default:
return Specifier::Default;
case ValueOwnership::Shared:
return Specifier::Shared;
case ValueOwnership::InOut:
return Specifier::InOut;
case ValueOwnership::Owned:
return Specifier::Owned;
}
llvm_unreachable("unhandled ownership");
}
SourceRange getSourceRange() const;
AnyFunctionType::Param toFunctionParam(Type type = Type()) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() == DeclKind::Param;
}
};
/// Describes the kind of subscripting used in Objective-C.
enum class ObjCSubscriptKind {
/// Objective-C indexed subscripting, which is based on an integral
/// index.
Indexed,
/// Objective-C keyed subscripting, which is based on an object
/// argument or metatype thereof.
Keyed
};
/// Declares a subscripting operator for a type.
///
/// A subscript declaration is defined as a get/set pair that produces a
/// specific type. For example:
///
/// \code
/// subscript (i : Int) -> String {
/// get { /* return ith String */ }
/// set { /* set ith string to value */ }
/// }
/// \endcode
///
/// A type with a subscript declaration can be used as the base of a subscript
/// expression a[i], where a is of the subscriptable type and i is the type
/// of the index. A subscript can have multiple indices:
///
/// \code
/// struct Matrix {
/// subscript (i : Int, j : Int) -> Double {
/// get { /* return element at position (i, j) */ }
/// set { /* set element at position (i, j) */ }
/// }
/// }
/// \endcode
///
/// A given type can have multiple subscript declarations, so long as the
/// signatures (indices and element type) are distinct.
///
class SubscriptDecl : public GenericContext, public AbstractStorageDecl {
SourceLoc StaticLoc;
SourceLoc ArrowLoc;
SourceLoc EndLoc;
ParameterList *Indices;
TypeLoc ElementTy;
public:
SubscriptDecl(DeclName Name,
SourceLoc StaticLoc, StaticSpellingKind StaticSpelling,
SourceLoc SubscriptLoc, ParameterList *Indices,
SourceLoc ArrowLoc, TypeLoc ElementTy, DeclContext *Parent,
GenericParamList *GenericParams)
: GenericContext(DeclContextKind::SubscriptDecl, Parent, GenericParams),
AbstractStorageDecl(DeclKind::Subscript,
StaticSpelling != StaticSpellingKind::None,
Parent, Name, SubscriptLoc,
/*will be overwritten*/ StorageIsNotMutable),
StaticLoc(StaticLoc), ArrowLoc(ArrowLoc),
Indices(nullptr), ElementTy(ElementTy) {
Bits.SubscriptDecl.StaticSpelling = static_cast<unsigned>(StaticSpelling);
setIndices(Indices);
}
/// \returns the way 'static'/'class' was spelled in the source.
StaticSpellingKind getStaticSpelling() const {
return static_cast<StaticSpellingKind>(Bits.SubscriptDecl.StaticSpelling);
}
SourceLoc getStaticLoc() const { return StaticLoc; }
SourceLoc getSubscriptLoc() const { return getNameLoc(); }
SourceLoc getStartLoc() const {
return getStaticLoc().isValid() ? getStaticLoc() : getSubscriptLoc();
}
SourceLoc getEndLoc() const { return EndLoc; }
void setEndLoc(SourceLoc sl) { EndLoc = sl; }
SourceRange getSourceRange() const;
SourceRange getSignatureSourceRange() const;
/// Retrieve the indices for this subscript operation.
ParameterList *getIndices() { return Indices; }
const ParameterList *getIndices() const { return Indices; }
void setIndices(ParameterList *p);
/// Retrieve the type of the element referenced by a subscript
/// operation.
Type getElementInterfaceType() const;
TypeLoc &getElementTypeLoc() { return ElementTy; }
const TypeLoc &getElementTypeLoc() const { return ElementTy; }
/// Compute the interface type of this subscript from the parameter and
/// element types.
void computeType();
/// Determine the kind of Objective-C subscripting this declaration
/// implies.
ObjCSubscriptKind getObjCSubscriptKind() const;
SubscriptDecl *getOverriddenDecl() const {
return cast_or_null<SubscriptDecl>(
AbstractStorageDecl::getOverriddenDecl());
}
static bool classof(const Decl *D) {
return D->getKind() == DeclKind::Subscript;
}
static bool classof(const DeclContext *DC) {
if (auto D = DC->getAsDecl())
return classof(D);
return false;
}
using DeclContext::operator new;
using Decl::getASTContext;
};
/// Encodes imported-as-member status for C functions that get imported
/// as methods.
class ImportAsMemberStatus {
friend class AbstractFunctionDecl;
// non-0 denotes import-as-member. 1 denotes no self index. n+2 denotes self
// index of n
uint8_t rawValue;
public:
ImportAsMemberStatus(uint8_t rawValue = 0) : rawValue(rawValue) {}
uint8_t getRawValue() const { return rawValue; }
bool isImportAsMember() const { return rawValue != 0; }
bool isInstance() const { return rawValue >= 2; }
bool isStatic() const { return rawValue == 1; }
uint8_t getSelfIndex() const {
assert(isInstance() && "not set");
return rawValue - 2;
}
void setStatic() {
assert(!isStatic() && "already set");
rawValue = 1;
}
void setSelfIndex(uint8_t idx) {
assert(!isImportAsMember() && "already set");
assert(idx <= UINT8_MAX-2 && "out of bounds");
rawValue = idx + 2;
}
};
/// Base class for function-like declarations.
class AbstractFunctionDecl : public GenericContext, public ValueDecl {
friend class NeedsNewVTableEntryRequest;
public:
enum class BodyKind {
/// The function did not have a body in the source code file.
None,
/// Function body is delayed, to be parsed later.
Unparsed,
/// Function body is parsed and available as an AST subtree.
Parsed,
/// Function body is not available, although it was written in the source.
Skipped,
/// Function body will be synthesized on demand.
Synthesize,
/// Function body is present and type-checked.
TypeChecked,
/// This is a memberwise initializer that will be synthesized by SILGen.
MemberwiseInitializer,
/// Function body text was deserialized from a .swiftmodule.
Deserialized
// This enum currently needs to fit in a 3-bit bitfield.
};
BodyKind getBodyKind() const {
return BodyKind(Bits.AbstractFunctionDecl.BodyKind);
}
struct BodySynthesizer {
std::pair<BraceStmt *, bool> (* Fn)(AbstractFunctionDecl *, void *);
void *Context;
};
private:
ParameterList *Params;
protected:
// If a function has a body at all, we have either a parsed body AST node or
// we have saved the end location of the unparsed body.
union {
/// This enum member is active if getBodyKind() is BodyKind::Parsed or
/// BodyKind::TypeChecked.
BraceStmt *Body;
/// This enum member is active if getBodyKind() is BodyKind::Deserialized.
StringRef BodyStringRepresentation;
/// This enum member is active if getBodyKind() == BodyKind::Synthesize.
BodySynthesizer Synthesizer;
/// The location of the function body when the body is delayed or skipped.
///
/// This enum member is active if getBodyKind() is BodyKind::Unparsed or
/// BodyKind::Skipped.
SourceRange BodyRange;
};
friend class ParseAbstractFunctionBodyRequest;
CaptureInfo Captures;
/// Location of the 'throws' token.
SourceLoc ThrowsLoc;
struct {
unsigned NeedsNewVTableEntryComputed : 1;
unsigned NeedsNewVTableEntry : 1;
} LazySemanticInfo = { };
AbstractFunctionDecl(DeclKind Kind, DeclContext *Parent, DeclName Name,
SourceLoc NameLoc, bool Throws, SourceLoc ThrowsLoc,
bool HasImplicitSelfDecl,
GenericParamList *GenericParams)
: GenericContext(DeclContextKind::AbstractFunctionDecl, Parent, GenericParams),
ValueDecl(Kind, Parent, Name, NameLoc),
Body(nullptr), ThrowsLoc(ThrowsLoc) {
setBodyKind(BodyKind::None);
Bits.AbstractFunctionDecl.HasImplicitSelfDecl = HasImplicitSelfDecl;
Bits.AbstractFunctionDecl.Overridden = false;
Bits.AbstractFunctionDecl.Throws = Throws;
Bits.AbstractFunctionDecl.Synthesized = false;
Bits.AbstractFunctionDecl.HasSingleExpressionBody = false;
}
void setBodyKind(BodyKind K) {
Bits.AbstractFunctionDecl.BodyKind = unsigned(K);
}
public:
void setHasSingleExpressionBody(bool Has = true) {
Bits.AbstractFunctionDecl.HasSingleExpressionBody = Has;
}
bool hasSingleExpressionBody() const {
return Bits.AbstractFunctionDecl.HasSingleExpressionBody;
}
Expr *getSingleExpressionBody() const;
void setSingleExpressionBody(Expr *NewBody);
/// Returns the string for the base name, or "_" if this is unnamed.
StringRef getNameStr() const {
assert(!getFullName().isSpecial() && "Cannot get string for special names");
return hasName() ? getBaseName().getIdentifier().str() : "_";
}
/// Should this declaration be treated as if annotated with transparent
/// attribute.
bool isTransparent() const;
// Expose our import as member status
ImportAsMemberStatus getImportAsMemberStatus() const {
return ImportAsMemberStatus(Bits.AbstractFunctionDecl.IAMStatus);
}
bool isImportAsMember() const {
return getImportAsMemberStatus().isImportAsMember();
}
bool isImportAsInstanceMember() const {
return getImportAsMemberStatus().isInstance();
}
bool isImportAsStaticMember() const {
return getImportAsMemberStatus().isStatic();
}
uint8_t getSelfIndex() const {
return getImportAsMemberStatus().getSelfIndex();
}
void setImportAsStaticMember() {
auto newValue = getImportAsMemberStatus();
newValue.setStatic();
Bits.AbstractFunctionDecl.IAMStatus = newValue.getRawValue();
}
void setSelfIndex(uint8_t idx) {
auto newValue = getImportAsMemberStatus();
newValue.setSelfIndex(idx);
Bits.AbstractFunctionDecl.IAMStatus = newValue.getRawValue();
}
/// Retrieve the location of the 'throws' keyword, if present.
SourceLoc getThrowsLoc() const { return ThrowsLoc; }
/// Returns true if the function body throws.
bool hasThrows() const { return Bits.AbstractFunctionDecl.Throws; }
// FIXME: Hack that provides names with keyword arguments for accessors.
DeclName getEffectiveFullName() const;
/// Returns true if the function has a body written in the source file.
///
/// Note that a true return value does not imply that the body was actually
/// parsed.
bool hasBody() const {
return getBodyKind() != BodyKind::None &&
getBodyKind() != BodyKind::Skipped;
}
/// Returns true if the text of this function's body can be retrieved either
/// by extracting the text from the source buffer or reading the inlinable
/// body from a deserialized swiftmodule.
bool hasInlinableBodyText() const;
/// Returns the function body, if it was parsed, or nullptr otherwise.
///
/// Note that a null return value does not imply that the source code did not
/// have a body for this function.
///
/// \sa hasBody()
BraceStmt *getBody(bool canSynthesize = true) const;
void setBody(BraceStmt *S, BodyKind NewBodyKind = BodyKind::Parsed) {
assert(getBodyKind() != BodyKind::Skipped &&
"cannot set a body if it was skipped");
Body = S;
setBodyKind(NewBodyKind);
}
/// Note that the body was skipped for this function. Function body
/// cannot be attached after this call.
void setBodySkipped(SourceRange bodyRange) {
// FIXME: Remove 'Parsed' from this once we can delay parsing function
// bodies. Right now -experimental-skip-non-inlinable-function-bodies
// requires being able to change the state from Parsed to Skipped,
// because we're still eagerly parsing function bodies.
assert(getBodyKind() == BodyKind::None ||
getBodyKind() == BodyKind::Unparsed ||
getBodyKind() == BodyKind::Parsed);
assert(bodyRange.isValid());
BodyRange = bodyRange;
setBodyKind(BodyKind::Skipped);
}
/// Note that parsing for the body was delayed.
void setBodyDelayed(SourceRange bodyRange) {
assert(getBodyKind() == BodyKind::None);
assert(bodyRange.isValid());
BodyRange = bodyRange;
setBodyKind(BodyKind::Unparsed);
}
/// Provide the parsed body for the function.
void setBodyParsed(BraceStmt *S) {
setBody(S, BodyKind::Parsed);
}
/// Note that parsing for the body was delayed.
///
/// The function should return the body statement and a flag indicating
/// whether that body is already type-checked.
void setBodySynthesizer(
std::pair<BraceStmt *, bool> (* fn)(AbstractFunctionDecl *, void *),
void *context = nullptr) {
assert(getBodyKind() == BodyKind::None);
Synthesizer = {fn, context};
setBodyKind(BodyKind::Synthesize);
}
/// Note that this is a memberwise initializer and thus the body will be
/// generated by SILGen.
void setIsMemberwiseInitializer() {
assert(getBodyKind() == BodyKind::None);
assert(isa<ConstructorDecl>(this));
setBodyKind(BodyKind::MemberwiseInitializer);
}
/// Gets the body of this function, stripping the unused portions of #if
/// configs inside the body. If this function was not deserialized from a
/// .swiftmodule, this body is reconstructed from the original
/// source buffer.
StringRef getInlinableBodyText(SmallVectorImpl<char> &scratch) const;
void setBodyStringRepresentation(StringRef body) {
assert(getBodyKind() == BodyKind::None);
setBodyKind(BodyKind::Deserialized);
BodyStringRepresentation = body;
}
bool isBodyTypeChecked() const {
return getBodyKind() == BodyKind::TypeChecked;
}
bool isBodySkipped() const {
return getBodyKind() == BodyKind::Skipped;
}
bool isMemberwiseInitializer() const {
return getBodyKind() == BodyKind::MemberwiseInitializer;
}
/// For a method of a class, checks whether it will require a new entry in the
/// vtable.
bool needsNewVTableEntry() const;
bool isEffectiveLinkageMoreVisibleThan(ValueDecl *other) const {
return (std::min(getEffectiveAccess(), AccessLevel::Public) >
std::min(other->getEffectiveAccess(), AccessLevel::Public));
}
bool isSynthesized() const {
return Bits.AbstractFunctionDecl.Synthesized;
}
void setSynthesized(bool value = true) {
Bits.AbstractFunctionDecl.Synthesized = value;
}
private:
void computeNeedsNewVTableEntry();
void computeSelfDeclType();
public:
/// Compute the interface type of this function declaration from the
/// parameter types.
void computeType(AnyFunctionType::ExtInfo Info = FunctionType::ExtInfo());
/// Retrieve the source range of the function body.
SourceRange getBodySourceRange() const;
/// Retrieve the source range of the function declaration name + patterns.
SourceRange getSignatureSourceRange() const;
const CaptureInfo &getCaptureInfo() const { return Captures; }
void setCaptureInfo(const CaptureInfo &captures) { Captures = captures; }
/// Retrieve the Objective-C selector that names this method.
ObjCSelector getObjCSelector(DeclName preferredName = DeclName(),
bool skipIsObjCResolution = false) const;
/// Determine whether the given method would produce an Objective-C
/// instance method.
bool isObjCInstanceMethod() const;
/// Determine whether the name of an argument is an API name by default
/// depending on the function context.
bool argumentNameIsAPIByDefault() const;
/// Retrieve the function's parameter list, not including 'self' if present.
ParameterList *getParameters() {
return Params;
}
const ParameterList *getParameters() const {
return Params;
}
void setParameters(ParameterList *Params);
bool hasImplicitSelfDecl() const {
return Bits.AbstractFunctionDecl.HasImplicitSelfDecl;
}
ParamDecl **getImplicitSelfDeclStorage();
/// Retrieve the implicit 'self' parameter for methods. Returns nullptr for
/// free functions.
const ParamDecl *getImplicitSelfDecl(bool createIfNeeded=true) const {
return const_cast<AbstractFunctionDecl*>(this)
->getImplicitSelfDecl(createIfNeeded);
}
ParamDecl *getImplicitSelfDecl(bool createIfNeeded=true);
/// Retrieve the declaration that this method overrides, if any.
AbstractFunctionDecl *getOverriddenDecl() const {
return cast_or_null<AbstractFunctionDecl>(ValueDecl::getOverriddenDecl());
}
/// Whether the declaration is later overridden in the module
///
/// Overrides are resolved during type checking; only query this field after
/// the whole module has been checked
bool isOverridden() const { return Bits.AbstractFunctionDecl.Overridden; }
/// The declaration has been overridden in the module
///
/// Resolved during type checking
void setIsOverridden() { Bits.AbstractFunctionDecl.Overridden = true; }
/// Set information about the foreign error convention used by this
/// declaration.
void setForeignErrorConvention(const ForeignErrorConvention &convention);
/// Get information about the foreign error convention used by this
/// declaration, given that it is @objc and 'throws'.
Optional<ForeignErrorConvention> getForeignErrorConvention() const;
/// If this is a foreign C function imported as a method, get the index of
/// the foreign parameter imported as `self`. If the function is imported
/// as a static method, `-1` is returned to represent the `self` parameter
/// being dropped altogether. `None` is returned for a normal function
/// or method.
Optional<int> getForeignFunctionAsMethodSelfParameterIndex() const;
static bool classof(const Decl *D) {
return D->getKind() >= DeclKind::First_AbstractFunctionDecl &&
D->getKind() <= DeclKind::Last_AbstractFunctionDecl;
}
static bool classof(const DeclContext *DC) {
if (auto D = DC->getAsDecl())
return classof(D);
return false;
}
/// True if the declaration is forced to be statically dispatched.
bool hasForcedStaticDispatch() const;
/// Get the type of this declaration without the Self clause.
/// Asserts if not in type context.
Type getMethodInterfaceType() const;
/// Tests if this is a function returning a DynamicSelfType, or a
/// constructor.
bool hasDynamicSelfResult() const;
using DeclContext::operator new;
using Decl::getASTContext;
};
class OperatorDecl;
enum class SelfAccessKind : uint8_t {
NonMutating,
Mutating,
Consuming,
};
/// Diagnostic printing of \c SelfAccessKind.
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, SelfAccessKind SAK);
/// FuncDecl - 'func' declaration.
class FuncDecl : public AbstractFunctionDecl {
friend class AbstractFunctionDecl;
friend class SelfAccessKindRequest;
friend class IsStaticRequest;
SourceLoc StaticLoc; // Location of the 'static' token or invalid.
SourceLoc FuncLoc; // Location of the 'func' token.
TypeLoc FnRetType;
protected:
FuncDecl(DeclKind Kind,
SourceLoc StaticLoc, StaticSpellingKind StaticSpelling,
SourceLoc FuncLoc,
DeclName Name, SourceLoc NameLoc,
bool Throws, SourceLoc ThrowsLoc,
bool HasImplicitSelfDecl,
GenericParamList *GenericParams, DeclContext *Parent)
: AbstractFunctionDecl(Kind, Parent,
Name, NameLoc,
Throws, ThrowsLoc,
HasImplicitSelfDecl, GenericParams),
StaticLoc(StaticLoc), FuncLoc(FuncLoc) {
assert(!Name.getBaseName().isSpecial());
Bits.FuncDecl.StaticSpelling = static_cast<unsigned>(StaticSpelling);
Bits.FuncDecl.ForcedStaticDispatch = false;
Bits.FuncDecl.SelfAccess =
static_cast<unsigned>(SelfAccessKind::NonMutating);
Bits.FuncDecl.SelfAccessComputed = false;
Bits.FuncDecl.IsStaticComputed = false;
Bits.FuncDecl.IsStatic = false;
}
private:
static FuncDecl *createImpl(ASTContext &Context, SourceLoc StaticLoc,
StaticSpellingKind StaticSpelling,
SourceLoc FuncLoc,
DeclName Name, SourceLoc NameLoc,
bool Throws, SourceLoc ThrowsLoc,
GenericParamList *GenericParams,
DeclContext *Parent,
ClangNode ClangN);
Optional<SelfAccessKind> getCachedSelfAccessKind() const {
if (Bits.FuncDecl.SelfAccessComputed)
return static_cast<SelfAccessKind>(Bits.FuncDecl.SelfAccess);
return None;
}
Optional<bool> getCachedIsStatic() const {
if (Bits.FuncDecl.IsStaticComputed)
return Bits.FuncDecl.IsStatic;
return None;
}
public:
/// Factory function only for use by deserialization.
static FuncDecl *createDeserialized(ASTContext &Context, SourceLoc StaticLoc,
StaticSpellingKind StaticSpelling,
SourceLoc FuncLoc,
DeclName Name, SourceLoc NameLoc,
bool Throws, SourceLoc ThrowsLoc,
GenericParamList *GenericParams,
DeclContext *Parent);
static FuncDecl *create(ASTContext &Context, SourceLoc StaticLoc,
StaticSpellingKind StaticSpelling,
SourceLoc FuncLoc,
DeclName Name, SourceLoc NameLoc,
bool Throws, SourceLoc ThrowsLoc,
GenericParamList *GenericParams,
ParameterList *ParameterList,
TypeLoc FnRetType, DeclContext *Parent,
ClangNode ClangN = ClangNode());
Identifier getName() const { return getFullName().getBaseIdentifier(); }
bool isStatic() const;
bool isCallable() const {
return getName().str() == "callAsFunction" && isInstanceMember();
}
/// \returns the way 'static'/'class' was spelled in the source.
StaticSpellingKind getStaticSpelling() const {
return static_cast<StaticSpellingKind>(Bits.FuncDecl.StaticSpelling);
}
/// \returns the way 'static'/'class' should be spelled for this declaration.
StaticSpellingKind getCorrectStaticSpelling() const;
void setStatic(bool IsStatic = true) {
Bits.FuncDecl.IsStaticComputed = true;
Bits.FuncDecl.IsStatic = IsStatic;
}
bool isMutating() const {
return getSelfAccessKind() == SelfAccessKind::Mutating;
}
bool isNonMutating() const {
return getSelfAccessKind() == SelfAccessKind::NonMutating;
}
bool isConsuming() const {
return getSelfAccessKind() == SelfAccessKind::Consuming;
}
bool isCallAsFunctionMethod() const;
SelfAccessKind getSelfAccessKind() const;
void setSelfAccessKind(SelfAccessKind mod) {
Bits.FuncDecl.SelfAccess = static_cast<unsigned>(mod);
Bits.FuncDecl.SelfAccessComputed = true;
}
SourceLoc getStaticLoc() const { return StaticLoc; }
SourceLoc getFuncLoc() const { return FuncLoc; }
SourceLoc getStartLoc() const {
return StaticLoc.isValid() && !isa<AccessorDecl>(this)
? StaticLoc : FuncLoc;
}
SourceRange getSourceRange() const;
TypeLoc &getBodyResultTypeLoc() { return FnRetType; }
const TypeLoc &getBodyResultTypeLoc() const { return FnRetType; }
/// Retrieve the result interface type of this function.
Type getResultInterfaceType() const;
/// isUnaryOperator - Determine whether this is a unary operator
/// implementation. This check is a syntactic rather than type-based check,
/// which looks at the number of parameters specified, in order to allow
/// for the definition of unary operators on tuples, as in:
///
/// prefix func + (param : (a:Int, b:Int))
///
/// This also allows the unary-operator-ness of a func decl to be determined
/// prior to type checking.
bool isUnaryOperator() const;
/// isBinaryOperator - Determine whether this is a binary operator
/// implementation. This check is a syntactic rather than type-based check,
/// which looks at the number of parameters specified, in order to allow
/// distinguishing a binary operator from a unary operator on tuples, as in:
///
/// prefix func + (_:(a:Int, b:Int)) // unary operator +(1,2)
/// infix func + (a:Int, b:Int) // binary operator 1 + 2
///
/// This also allows the binary-operator-ness of a func decl to be determined
/// prior to type checking.
bool isBinaryOperator() const;
void getLocalCaptures(SmallVectorImpl<CapturedValue> &Result) const {
return getCaptureInfo().getLocalCaptures(Result);
}
ParamDecl **getImplicitSelfDeclStorage();
/// Get the supertype method this method overrides, if any.
FuncDecl *getOverriddenDecl() const {
return cast_or_null<FuncDecl>(AbstractFunctionDecl::getOverriddenDecl());
}
OperatorDecl *getOperatorDecl() const;
/// Returns true if the function is forced to be statically dispatched.
bool hasForcedStaticDispatch() const {
return Bits.FuncDecl.ForcedStaticDispatch;
}
void setForcedStaticDispatch(bool flag) {
Bits.FuncDecl.ForcedStaticDispatch = flag;
}
static bool classof(const Decl *D) {
return D->getKind() == DeclKind::Func ||
D->getKind() == DeclKind::Accessor;
}
static bool classof(const AbstractFunctionDecl *D) {
return classof(static_cast<const Decl*>(D));
}
static bool classof(const DeclContext *DC) {
if (auto D = DC->getAsDecl())
return classof(D);
return false;
}
/// True if the function is a defer body.
bool isDeferBody() const;
/// Perform basic checking to determine whether the @IBAction or
/// @IBSegueAction attribute can be applied to this function.
bool isPotentialIBActionTarget() const;
};
/// This represents an accessor function, such as a getter or setter.
class AccessorDecl final : public FuncDecl {
/// Location of the accessor keyword, e.g. 'set'.
SourceLoc AccessorKeywordLoc;
AbstractStorageDecl *Storage;
AccessorDecl(SourceLoc declLoc, SourceLoc accessorKeywordLoc,
AccessorKind accessorKind, AbstractStorageDecl *storage,
SourceLoc staticLoc, StaticSpellingKind staticSpelling,
bool throws, SourceLoc throwsLoc,
bool hasImplicitSelfDecl, GenericParamList *genericParams,
DeclContext *parent)
: FuncDecl(DeclKind::Accessor,
staticLoc, staticSpelling, /*func loc*/ declLoc,
/*name*/ Identifier(), /*name loc*/ declLoc,
throws, throwsLoc, hasImplicitSelfDecl, genericParams, parent),
AccessorKeywordLoc(accessorKeywordLoc),
Storage(storage) {
Bits.AccessorDecl.AccessorKind = unsigned(accessorKind);
}
static AccessorDecl *createImpl(ASTContext &ctx,
SourceLoc declLoc,
SourceLoc accessorKeywordLoc,
AccessorKind accessorKind,
AbstractStorageDecl *storage,
SourceLoc staticLoc,
StaticSpellingKind staticSpelling,
bool throws, SourceLoc throwsLoc,
GenericParamList *genericParams,
DeclContext *parent,
ClangNode clangNode);
Optional<bool> getCachedIsTransparent() const {
if (Bits.AccessorDecl.IsTransparentComputed)
return Bits.AccessorDecl.IsTransparent;
return None;
}
friend class IsAccessorTransparentRequest;
public:
static AccessorDecl *createDeserialized(ASTContext &ctx,
SourceLoc declLoc,
SourceLoc accessorKeywordLoc,
AccessorKind accessorKind,
AbstractStorageDecl *storage,
SourceLoc staticLoc,
StaticSpellingKind staticSpelling,
bool throws, SourceLoc throwsLoc,
GenericParamList *genericParams,
DeclContext *parent);
static AccessorDecl *create(ASTContext &ctx, SourceLoc declLoc,
SourceLoc accessorKeywordLoc,
AccessorKind accessorKind,
AbstractStorageDecl *storage,
SourceLoc staticLoc,
StaticSpellingKind staticSpelling,
bool throws, SourceLoc throwsLoc,
GenericParamList *genericParams,
ParameterList *parameterList,
TypeLoc fnRetType, DeclContext *parent,
ClangNode clangNode = ClangNode());
SourceLoc getAccessorKeywordLoc() const { return AccessorKeywordLoc; }
AbstractStorageDecl *getStorage() const {
return Storage;
}
AccessorKind getAccessorKind() const {
return AccessorKind(Bits.AccessorDecl.AccessorKind);
}
bool isGetter() const { return getAccessorKind() == AccessorKind::Get; }
bool isSetter() const { return getAccessorKind() == AccessorKind::Set; }
bool isAnyAddressor() const {
auto kind = getAccessorKind();
return kind == AccessorKind::Address
|| kind == AccessorKind::MutableAddress;
}
/// isGetterOrSetter - Determine whether this is specifically a getter or
/// a setter, as opposed to some other kind of accessor.
///
/// For example, only getters and setters can be exposed to Objective-C.
bool isGetterOrSetter() const { return isGetter() || isSetter(); }
bool isObservingAccessor() const {
switch (getAccessorKind()) {
#define OBSERVING_ACCESSOR(ID, KEYWORD) \
case AccessorKind::ID: return true;
#define ACCESSOR(ID) \
case AccessorKind::ID: return false;
#include "swift/AST/AccessorKinds.def"
}
llvm_unreachable("bad accessor kind");
}
/// \returns true if this is non-mutating due to applying a 'mutating'
/// attribute. For example a "mutating set" accessor.
bool isExplicitNonMutating() const;
/// Is the accesor one of the kinds that's assumed nonmutating by default?
bool isAssumedNonMutating() const;
/// Is this accessor one of the kinds that's implicitly a coroutine?
bool isCoroutine() const {
switch (getAccessorKind()) {
#define COROUTINE_ACCESSOR(ID, KEYWORD) \
case AccessorKind::ID: return true;
#define ACCESSOR(ID) \
case AccessorKind::ID: return false;
#include "swift/AST/AccessorKinds.def"
}
llvm_unreachable("bad accessor kind");
}
void setIsTransparent(bool transparent) {
Bits.AccessorDecl.IsTransparent = transparent;
Bits.AccessorDecl.IsTransparentComputed = 1;
}
static bool classof(const Decl *D) {
return D->getKind() == DeclKind::Accessor;
}
static bool classof(const AbstractFunctionDecl *D) {
return classof(static_cast<const Decl*>(D));
}
static bool classof(const DeclContext *DC) {
if (auto D = DC->getAsDecl())
return classof(D);
return false;
}
};
inline AccessorDecl *
AbstractStorageDecl::AccessorRecord::getAccessor(AccessorKind kind) const {
if (auto optIndex = AccessorIndices[unsigned(kind)]) {
auto accessor = getAllAccessors()[optIndex - 1];
assert(accessor && accessor->getAccessorKind() == kind);
return accessor;
}
return nullptr;
}
/// This represents a 'case' declaration in an 'enum', which may declare
/// one or more individual comma-separated EnumElementDecls.
class EnumCaseDecl final
: public Decl,
private llvm::TrailingObjects<EnumCaseDecl, EnumElementDecl *> {
friend TrailingObjects;
friend class Decl;
SourceLoc CaseLoc;
EnumCaseDecl(SourceLoc CaseLoc,
ArrayRef<EnumElementDecl *> Elements,
DeclContext *DC)
: Decl(DeclKind::EnumCase, DC),
CaseLoc(CaseLoc)
{
Bits.EnumCaseDecl.NumElements = Elements.size();
std::uninitialized_copy(Elements.begin(), Elements.end(),
getTrailingObjects<EnumElementDecl *>());
}
SourceLoc getLocFromSource() const { return CaseLoc; }
public:
static EnumCaseDecl *create(SourceLoc CaseLoc,
ArrayRef<EnumElementDecl*> Elements,
DeclContext *DC);
/// Get the list of elements declared in this case.
ArrayRef<EnumElementDecl *> getElements() const {
return {getTrailingObjects<EnumElementDecl *>(),
Bits.EnumCaseDecl.NumElements};
}
SourceRange getSourceRange() const;
static bool classof(const Decl *D) {
return D->getKind() == DeclKind::EnumCase;
}
};
/// This represents a single case of an 'enum' declaration.
///
/// For example, the X, Y, and Z in this enum:
///
/// \code
/// enum V {
/// case X(Int), Y(Int)
/// case Z
/// }
/// \endcode
///
/// The type of an EnumElementDecl is always the EnumType for the containing
/// enum. EnumElementDecls are represented in the AST as members of their
/// parent EnumDecl, although syntactically they are subordinate to the
/// EnumCaseDecl.
class EnumElementDecl : public DeclContext, public ValueDecl {
friend class EnumRawValuesRequest;
/// This is the type specified with the enum element, for
/// example 'Int' in 'case Y(Int)'. This is null if there is no type
/// associated with this element, as in 'case Z' or in all elements of enum
/// definitions.
ParameterList *Params;
SourceLoc EqualsLoc;
/// The raw value literal for the enum element, or null.
LiteralExpr *RawValueExpr;
public:
EnumElementDecl(SourceLoc IdentifierLoc, DeclName Name,
ParameterList *Params,
SourceLoc EqualsLoc,
LiteralExpr *RawValueExpr,
DeclContext *DC)
: DeclContext(DeclContextKind::EnumElementDecl, DC),
ValueDecl(DeclKind::EnumElement, DC, Name, IdentifierLoc),
Params(Params),
EqualsLoc(EqualsLoc),
RawValueExpr(RawValueExpr)
{}
Identifier getName() const { return getFullName().getBaseIdentifier(); }
/// Returns the string for the base name, or "_" if this is unnamed.
StringRef getNameStr() const {
assert(!getFullName().isSpecial() && "Cannot get string for special names");
return hasName() ? getBaseName().getIdentifier().str() : "_";
}
/// Set the interface type of this enum element to the constructor function
/// type; (Self.Type) -> Self or (Self.Type) -> (Args...) -> Self.
void computeType();
Type getArgumentInterfaceType() const;
ParameterList *getParameterList() const { return Params; }
/// Retrieves a fully typechecked raw value expression associated
/// with this enum element, if it exists.
LiteralExpr *getRawValueExpr() const;
/// Retrieves a "structurally" checked raw value expression associated
/// with this enum element, if it exists.
///
/// The structural raw value may or may not have a type set, but it is
/// guaranteed to be suitable for retrieving any non-semantic information
/// like digit text for an integral raw value or user text for a string raw value.
LiteralExpr *getStructuralRawValueExpr() const;
/// Reset the raw value expression.
void setRawValueExpr(LiteralExpr *e);
/// Return the containing EnumDecl.
EnumDecl *getParentEnum() const {
return cast<EnumDecl>(getDeclContext());
}
/// Return the containing EnumCaseDecl.
EnumCaseDecl *getParentCase() const;
SourceLoc getStartLoc() const {
return getNameLoc();
}
SourceRange getSourceRange() const;
bool hasAssociatedValues() const {
return getParameterList() != nullptr;
}
/// True if the case is marked 'indirect'.
bool isIndirect() const {
return getAttrs().hasAttribute<IndirectAttr>();
}
/// Do not call this!
/// It exists to let the AST walkers get the raw value without forcing a request.
LiteralExpr *getRawValueUnchecked() const { return RawValueExpr; }
static bool classof(const Decl *D) {
return D->getKind() == DeclKind::EnumElement;
}
static bool classof(const DeclContext *DC) {
if (auto D = DC->getAsDecl())
return classof(D);
return false;
}
using DeclContext::operator new;
using Decl::getASTContext;
};
inline SourceRange EnumCaseDecl::getSourceRange() const {
auto subRange = getElements().back()->getSourceRange();
if (subRange.isValid())
return {CaseLoc, subRange.End};
return {};
}
/// Describes the kind of initializer.
enum class CtorInitializerKind {
/// A designated initializer is an initializer responsible for initializing
/// the stored properties of the current class and chaining to a superclass's
/// designated initializer (for non-root classes).
///
/// Designated initializers are never inherited.
Designated,
/// A convenience initializer is an initializer that initializes a complete
/// object by delegating to another initializer (eventually reaching a
/// designated initializer).
///
/// Convenience initializers are inherited into subclasses that override
/// all of their superclass's designated initializers.
Convenience,
/// A convenience factory initializer is a convenience initializer introduced
/// by an imported Objective-C factory method.
///
/// Convenience factory initializers cannot be expressed directly in
/// Swift; rather, they are produced by the Clang importer when importing
/// an instancetype factory method from Objective-C.
ConvenienceFactory,
/// A factory initializer is an initializer that is neither designated nor
/// convenience: it can be used to create an object of the given type, but
/// cannot be chained to via "super.init" nor is it inherited.
///
/// A factory initializer is written with a return type of the class name
/// itself. FIXME: However, this is only a presentation form, and at present
/// the only factory initializers are produced by importing an Objective-C
/// factory method that does not return instancetype.
///
/// FIXME: Arguably, structs and enums only have factory initializers, and
/// using designated initializers for them is a misnomer.
Factory
};
/// ConstructorDecl - Declares a constructor for a type. For example:
///
/// \code
/// struct X {
/// var x : Int
/// init(i : Int) {
/// x = i
/// }
/// }
/// \endcode
class ConstructorDecl : public AbstractFunctionDecl {
/// The location of the '!' or '?' for a failable initializer.
SourceLoc FailabilityLoc;
ParamDecl *SelfDecl;
/// The interface type of the initializing constructor.
Type InitializerInterfaceType;
/// The typechecked call to super.init expression, which needs to be
/// inserted at the end of the initializer by SILGen.
Expr *CallToSuperInit = nullptr;
public:
ConstructorDecl(DeclName Name, SourceLoc ConstructorLoc,
bool Failable, SourceLoc FailabilityLoc,
bool Throws, SourceLoc ThrowsLoc,
ParameterList *BodyParams,
GenericParamList *GenericParams,
DeclContext *Parent);
SourceLoc getConstructorLoc() const { return getNameLoc(); }
SourceLoc getStartLoc() const { return getConstructorLoc(); }
SourceRange getSourceRange() const;
/// Get the interface type of the constructed object.
Type getResultInterfaceType() const;
/// Get the interface type of the initializing constructor.
Type getInitializerInterfaceType();
/// Get the typechecked call to super.init expression, which needs to be
/// inserted at the end of the initializer by SILGen.
Expr *getSuperInitCall() { return CallToSuperInit; }
void setSuperInitCall(Expr *CallExpr) { CallToSuperInit = CallExpr; }
ParamDecl **getImplicitSelfDeclStorage() { return &SelfDecl; }
/// Specifies the kind of initialization call performed within the body
/// of the constructor, e.g., self.init or super.init.
enum class BodyInitKind {
/// There are no calls to self.init or super.init.
None,
/// There is a call to self.init, which delegates to another (peer)
/// initializer.
Delegating,
/// There is a call to super.init, which chains to a superclass initializer.
Chained,
/// There are no calls to self.init or super.init explicitly in the body of
/// the constructor, but a 'super.init' call will be implicitly added
/// by semantic analysis.
ImplicitChained
};
/// Determine whether the body of this constructor contains any delegating
/// or superclass initializations (\c self.init or \c super.init,
/// respectively) within its body.
///
/// \param diags If non-null, this check will ensure that the constructor
/// body is consistent in its use of delegation vs. chaining and emit any
/// diagnostics through the given diagnostic engine.
///
/// \param init If non-null and there is an explicit \c self.init or
/// \c super.init within the body, will be set to point at that
/// initializer.
BodyInitKind getDelegatingOrChainedInitKind(DiagnosticEngine *diags,
ApplyExpr **init = nullptr) const;
/// Whether this constructor is required.
bool isRequired() const {
return getAttrs().hasAttribute<RequiredAttr>();
}
/// Determine the kind of initializer this is.
CtorInitializerKind getInitKind() const;
/// Whether this is a designated initializer.
bool isDesignatedInit() const {
return getInitKind() == CtorInitializerKind::Designated;
}
/// Whether this is a convenience initializer.
bool isConvenienceInit() const {
return getInitKind() == CtorInitializerKind::Convenience ||
getInitKind() == CtorInitializerKind::ConvenienceFactory;
}
/// Whether this is a factory initializer.
bool isFactoryInit() const {
switch (getInitKind()) {
case CtorInitializerKind::Designated:
case CtorInitializerKind::Convenience:
return false;
case CtorInitializerKind::Factory:
case CtorInitializerKind::ConvenienceFactory:
return true;
}
llvm_unreachable("bad CtorInitializerKind");
}
/// Determine whether this initializer is inheritable.
bool isInheritable() const {
switch (getInitKind()) {
case CtorInitializerKind::Designated:
case CtorInitializerKind::Factory:
return false;
case CtorInitializerKind::Convenience:
case CtorInitializerKind::ConvenienceFactory:
return true;
}
llvm_unreachable("bad CtorInitializerKind");
}
/// Determine if this is a failable initializer.
bool isFailable() const {
return Bits.ConstructorDecl.Failable;
}
/// Retrieve the location of the '!' or '?' in a failable initializer.
SourceLoc getFailabilityLoc() const { return FailabilityLoc; }
/// Whether the implementation of this method is a stub that traps at runtime.
bool hasStubImplementation() const {
return Bits.ConstructorDecl.HasStubImplementation;
}
/// Set whether the implementation of this method is a stub that
/// traps at runtime.
void setStubImplementation(bool stub) {
Bits.ConstructorDecl.HasStubImplementation = stub;
}
ConstructorDecl *getOverriddenDecl() const {
return cast_or_null<ConstructorDecl>(
AbstractFunctionDecl::getOverriddenDecl());
}
/// Determine whether this initializer falls into the special case for
/// Objective-C initializers with selectors longer than "init", e.g.,
/// \c initForMemory.
///
/// In such cases, one can write the Swift initializer
/// with a single parameter of type '()', e.g,
///
/// \code
/// @objc init(forMemory: ())
/// \endcode
bool isObjCZeroParameterWithLongSelector() const;
static bool classof(const Decl *D) {
return D->getKind() == DeclKind::Constructor;
}
static bool classof(const AbstractFunctionDecl *D) {
return classof(static_cast<const Decl*>(D));
}
static bool classof(const DeclContext *DC) {
if (auto D = DC->getAsDecl())
return classof(D);
return false;
}
};
/// DestructorDecl - Declares a destructor for a type. For example:
///
/// \code
/// struct X {
/// var fd : Int
/// deinit {
/// close(fd)
/// }
/// }
/// \endcode
class DestructorDecl : public AbstractFunctionDecl {
ParamDecl *SelfDecl;
public:
DestructorDecl(SourceLoc DestructorLoc, DeclContext *Parent);
ParamDecl **getImplicitSelfDeclStorage() { return &SelfDecl; }
SourceLoc getDestructorLoc() const { return getNameLoc(); }
SourceLoc getStartLoc() const { return getDestructorLoc(); }
SourceRange getSourceRange() const;
/// Retrieve the Objective-C selector for destructors.
ObjCSelector getObjCSelector() const;
static bool classof(const Decl *D) {
return D->getKind() == DeclKind::Destructor;
}
static bool classof(const AbstractFunctionDecl *D) {
return classof(static_cast<const Decl*>(D));
}
static bool classof(const DeclContext *DC) {
if (auto D = DC->getAsDecl())
return classof(D);
return false;
}
};
/// Declares a precedence group. For example:
///
/// \code
/// precedencegroup MultiplicativePrecedence {
/// associativity: right
/// higherThan: AdditivePrecedence
/// }
/// \endcode
class PrecedenceGroupDecl : public Decl {
public:
struct Relation {
SourceLoc NameLoc;
Identifier Name;
PrecedenceGroupDecl *Group;
};
private:
SourceLoc PrecedenceGroupLoc, NameLoc, LBraceLoc, RBraceLoc;
SourceLoc AssociativityKeywordLoc, AssociativityValueLoc;
SourceLoc AssignmentKeywordLoc, AssignmentValueLoc;
SourceLoc HigherThanLoc, LowerThanLoc;
Identifier Name;
unsigned NumHigherThan, NumLowerThan;
// Tail-allocated array of Relations
Relation *getHigherThanBuffer() {
return reinterpret_cast<Relation*>(this + 1);
}
const Relation *getHigherThanBuffer() const {
return reinterpret_cast<const Relation*>(this + 1);
}
Relation *getLowerThanBuffer() {
return getHigherThanBuffer() + NumHigherThan;
}
const Relation *getLowerThanBuffer() const {
return getHigherThanBuffer() + NumHigherThan;
}
PrecedenceGroupDecl(DeclContext *DC,
SourceLoc precedenceGroupLoc,
SourceLoc nameLoc, Identifier name,
SourceLoc lbraceLoc,
SourceLoc associativityKeywordLoc,
SourceLoc associativityValueLoc,
Associativity associativity,
SourceLoc assignmentKeywordLoc,
SourceLoc assignmentValueLoc,
bool isAssignment,
SourceLoc higherThanLoc, ArrayRef<Relation> higherThan,
SourceLoc lowerThanLoc, ArrayRef<Relation> lowerThan,
SourceLoc rbraceLoc);
friend class Decl;
SourceLoc getLocFromSource() const { return NameLoc; }
public:
static PrecedenceGroupDecl *create(DeclContext *dc,
SourceLoc precedenceGroupLoc,
SourceLoc nameLoc,
Identifier name,
SourceLoc lbraceLoc,
SourceLoc associativityKeywordLoc,
SourceLoc associativityValueLoc,
Associativity associativity,
SourceLoc assignmentKeywordLoc,
SourceLoc assignmentValueLoc,
bool isAssignment,
SourceLoc higherThanLoc,
ArrayRef<Relation> higherThan,
SourceLoc lowerThanLoc,
ArrayRef<Relation> lowerThan,
SourceLoc rbraceLoc);
SourceRange getSourceRange() const {
return { PrecedenceGroupLoc, RBraceLoc };
}
/// Return the location of 'precedencegroup' in:
/// precedencegroup MultiplicativePrecedence { ... }
SourceLoc getPrecedenceGroupLoc() const { return PrecedenceGroupLoc; }
/// Return the location of 'MultiplicativePrecedence' in:
/// precedencegroup MultiplicativePrecedence { ... }
SourceLoc getNameLoc() const {
return NameLoc;
}
Identifier getName() const {
return Name;
}
SourceLoc getLBraceLoc() const { return LBraceLoc; }
SourceLoc getRBraceLoc() const { return RBraceLoc; }
bool isAssociativityImplicit() const {
return AssociativityKeywordLoc.isInvalid();
}
/// Return the location of 'associativity' in:
/// associativity: left
SourceLoc getAssociativityKeywordLoc() const {
return AssociativityKeywordLoc;
}
/// Return the location of 'right' in:
/// associativity: right
SourceLoc getAssociativityValueLoc() const {
return AssociativityValueLoc;
}
Associativity getAssociativity() const {
return Associativity(Bits.PrecedenceGroupDecl.Associativity);
}
bool isLeftAssociative() const {
return getAssociativity() == Associativity::Left;
}
bool isRightAssociative() const {
return getAssociativity() == Associativity::Right;
}
bool isNonAssociative() const {
return getAssociativity() == Associativity::None;
}
bool isAssignmentImplicit() const {
return AssignmentKeywordLoc.isInvalid();
}
/// Return the location of 'assignment' in:
/// assignment: true
SourceLoc getAssignmentKeywordLoc() const {
return AssignmentKeywordLoc;
}
/// Return the location of 'assignment' in:
/// assignment: true
SourceLoc getAssignmentValueLoc() const {
return AssignmentValueLoc;
}
bool isAssignment() const {
return Bits.PrecedenceGroupDecl.IsAssignment;
}
bool isHigherThanImplicit() const {
return HigherThanLoc.isInvalid();
}
/// Return the location of 'higherThan' in:
/// higherThan: AdditivePrecedence
SourceLoc getHigherThanLoc() const {
return HigherThanLoc;
}
ArrayRef<Relation> getHigherThan() const {
return { getHigherThanBuffer(), NumHigherThan };
}
MutableArrayRef<Relation> getMutableHigherThan() {
return { getHigherThanBuffer(), NumHigherThan };
}
bool isLowerThanImplicit() const {
return LowerThanLoc.isInvalid();
}
/// Return the location of 'lowerThan' in:
/// lowerThan: MultiplicativePrecedence
SourceLoc getLowerThanLoc() const {
return LowerThanLoc;
}
ArrayRef<Relation> getLowerThan() const {
return { getLowerThanBuffer(), NumLowerThan };
}
MutableArrayRef<Relation> getMutableLowerThan() {
return { getLowerThanBuffer(), NumLowerThan };
}
static bool classof(const Decl *D) {
return D->getKind() == DeclKind::PrecedenceGroup;
}
};
/// Abstract base class of operator declarations.
class OperatorDecl : public Decl {
SourceLoc OperatorLoc, NameLoc;
Identifier name;
ArrayRef<Identifier> Identifiers;
ArrayRef<SourceLoc> IdentifierLocs;
ArrayRef<NominalTypeDecl *> DesignatedNominalTypes;
SourceLoc getLocFromSource() const { return NameLoc; }
friend class Decl;
public:
OperatorDecl(DeclKind kind, DeclContext *DC, SourceLoc OperatorLoc,
Identifier Name, SourceLoc NameLoc,
ArrayRef<Identifier> Identifiers,
ArrayRef<SourceLoc> IdentifierLocs)
: Decl(kind, DC), OperatorLoc(OperatorLoc), NameLoc(NameLoc), name(Name),
Identifiers(Identifiers), IdentifierLocs(IdentifierLocs) {}
OperatorDecl(DeclKind kind, DeclContext *DC, SourceLoc OperatorLoc,
Identifier Name, SourceLoc NameLoc,
ArrayRef<NominalTypeDecl *> DesignatedNominalTypes)
: Decl(kind, DC), OperatorLoc(OperatorLoc), NameLoc(NameLoc), name(Name),
DesignatedNominalTypes(DesignatedNominalTypes) {}
SourceLoc getOperatorLoc() const { return OperatorLoc; }
SourceLoc getNameLoc() const { return NameLoc; }
Identifier getName() const { return name; }
ArrayRef<Identifier> getIdentifiers() const {
return Identifiers;
}
ArrayRef<SourceLoc> getIdentifierLocs() const {
return IdentifierLocs;
}
ArrayRef<NominalTypeDecl *> getDesignatedNominalTypes() const {
return DesignatedNominalTypes;
}
void setDesignatedNominalTypes(ArrayRef<NominalTypeDecl *> nominalTypes) {
DesignatedNominalTypes = nominalTypes;
}
static bool classof(const Decl *D) {
// Workaround: http://llvm.org/PR35906
if (DeclKind::Last_Decl == DeclKind::Last_OperatorDecl)
return D->getKind() >= DeclKind::First_OperatorDecl;
return D->getKind() >= DeclKind::First_OperatorDecl
&& D->getKind() <= DeclKind::Last_OperatorDecl;
}
};
/// Declares the behavior of an infix operator. For example:
///
/// \code
/// infix operator /+/ : AdditionPrecedence, Numeric
/// \endcode
class InfixOperatorDecl : public OperatorDecl {
SourceLoc ColonLoc;
public:
InfixOperatorDecl(DeclContext *DC, SourceLoc operatorLoc, Identifier name,
SourceLoc nameLoc, SourceLoc colonLoc,
ArrayRef<Identifier> identifiers,
ArrayRef<SourceLoc> identifierLocs)
: OperatorDecl(DeclKind::InfixOperator, DC, operatorLoc, name, nameLoc,
identifiers, identifierLocs),
ColonLoc(colonLoc) {}
SourceLoc getEndLoc() const {
auto identifierLocs = getIdentifierLocs();
if (identifierLocs.empty())
return getNameLoc();
return identifierLocs.back();
}
SourceRange getSourceRange() const {
return { getOperatorLoc(), getEndLoc() };
}
SourceLoc getColonLoc() const { return ColonLoc; }
PrecedenceGroupDecl *getPrecedenceGroup() const;
/// True if this decl's attributes conflict with those declared by another
/// operator.
bool conflictsWith(InfixOperatorDecl *other) {
return getPrecedenceGroup() != other->getPrecedenceGroup();
}
static bool classof(const Decl *D) {
return D->getKind() == DeclKind::InfixOperator;
}
};
/// Declares the behavior of a prefix operator. For example:
///
/// \code
/// prefix operator /+/ {}
/// \endcode
class PrefixOperatorDecl : public OperatorDecl {
public:
PrefixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name,
SourceLoc NameLoc,
ArrayRef<Identifier> Identifiers,
ArrayRef<SourceLoc> IdentifierLocs)
: OperatorDecl(DeclKind::PrefixOperator, DC, OperatorLoc, Name, NameLoc,
Identifiers, IdentifierLocs) {}
PrefixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name,
SourceLoc NameLoc,
ArrayRef<NominalTypeDecl *> designatedNominalTypes)
: OperatorDecl(DeclKind::PrefixOperator, DC, OperatorLoc, Name, NameLoc,
designatedNominalTypes) {}
SourceRange getSourceRange() const {
return { getOperatorLoc(), getNameLoc() };
}
/// True if this decl's attributes conflict with those declared by another
/// PrefixOperatorDecl.
bool conflictsWith(PrefixOperatorDecl *other) {
return false;
}
static bool classof(const Decl *D) {
return D->getKind() == DeclKind::PrefixOperator;
}
};
/// Declares the behavior of a postfix operator. For example:
///
/// \code
/// postfix operator /+/ {}
/// \endcode
class PostfixOperatorDecl : public OperatorDecl {
public:
PostfixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name,
SourceLoc NameLoc,
ArrayRef<Identifier> Identifiers,
ArrayRef<SourceLoc> IdentifierLocs)
: OperatorDecl(DeclKind::PostfixOperator, DC, OperatorLoc, Name, NameLoc,
Identifiers, IdentifierLocs) {}
PostfixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name,
SourceLoc NameLoc,
ArrayRef<NominalTypeDecl *> designatedNominalTypes)
: OperatorDecl(DeclKind::PostfixOperator, DC, OperatorLoc, Name, NameLoc,
designatedNominalTypes) {}
SourceRange getSourceRange() const {
return { getOperatorLoc(), getNameLoc() };
}
/// True if this decl's attributes conflict with those declared by another
/// PostfixOperatorDecl.
bool conflictsWith(PostfixOperatorDecl *other) {
return false;
}
static bool classof(const Decl *D) {
return D->getKind() == DeclKind::PostfixOperator;
}
};
/// Represents a hole where a declaration should have been.
///
/// Among other things, these are used to keep vtable layout consistent.
class MissingMemberDecl : public Decl {
DeclName Name;
MissingMemberDecl(DeclContext *DC, DeclName name,
unsigned vtableEntries,
unsigned fieldOffsetVectorEntries)
: Decl(DeclKind::MissingMember, DC), Name(name) {
Bits.MissingMemberDecl.NumberOfVTableEntries = vtableEntries;
assert(getNumberOfVTableEntries() == vtableEntries && "not enough bits");
Bits.MissingMemberDecl.NumberOfFieldOffsetVectorEntries =
fieldOffsetVectorEntries;
assert(getNumberOfFieldOffsetVectorEntries() == fieldOffsetVectorEntries
&& "not enough bits");
setImplicit();
}
friend class Decl;
SourceLoc getLocFromSource() const {
return SourceLoc();
}
public:
static MissingMemberDecl *
create(ASTContext &ctx, DeclContext *DC, DeclName name,
unsigned numVTableEntries, bool hasStorage) {
assert(!numVTableEntries || isa<ProtocolDecl>(DC) || isa<ClassDecl>(DC) &&
"Only classes and protocols have vtable/witness table entries");
assert(!hasStorage || !isa<ProtocolDecl>(DC) &&
"Protocols cannot have missing stored properties");
return new (ctx) MissingMemberDecl(DC, name, numVTableEntries, hasStorage);
}
DeclName getFullName() const {
return Name;
}
unsigned getNumberOfVTableEntries() const {
return Bits.MissingMemberDecl.NumberOfVTableEntries;
}
unsigned getNumberOfFieldOffsetVectorEntries() const {
return Bits.MissingMemberDecl.NumberOfFieldOffsetVectorEntries;
}
SourceRange getSourceRange() const {
return SourceRange();
}
static bool classof(const Decl *D) {
return D->getKind() == DeclKind::MissingMember;
}
};
inline bool AbstractStorageDecl::isSettable(const DeclContext *UseDC,
const DeclRefExpr *base) const {
if (auto vd = dyn_cast<VarDecl>(this))
return vd->isSettable(UseDC, base);
auto sd = cast<SubscriptDecl>(this);
return sd->supportsMutation();
}
inline void
AbstractStorageDecl::overwriteSetterAccess(AccessLevel accessLevel) {
Accessors.setInt(accessLevel);
if (auto setter = getAccessor(AccessorKind::Set))
setter->overwriteAccess(accessLevel);
if (auto modify = getAccessor(AccessorKind::Modify))
modify->overwriteAccess(accessLevel);
if (auto mutableAddressor = getAccessor(AccessorKind::MutableAddress))
mutableAddressor->overwriteAccess(accessLevel);
}
/// Constructors and destructors always have a 'self' parameter,
/// which is stored in an instance member. Functions only have a
/// 'self' if they are declared inside of a nominal type or extension,
/// in which case we tail-allocate storage for it.
inline ParamDecl **AbstractFunctionDecl::getImplicitSelfDeclStorage() {
switch (getKind()) {
default: llvm_unreachable("Unknown AbstractFunctionDecl!");
case DeclKind::Constructor:
return cast<ConstructorDecl>(this)->getImplicitSelfDeclStorage();
case DeclKind::Destructor:
return cast<DestructorDecl>(this)->getImplicitSelfDeclStorage();
case DeclKind::Func:
case DeclKind::Accessor:
return cast<FuncDecl>(this)->getImplicitSelfDeclStorage();
}
}
inline ParamDecl **FuncDecl::getImplicitSelfDeclStorage() {
if (!hasImplicitSelfDecl())
return nullptr;
if (!isa<AccessorDecl>(this)) {
assert(getKind() == DeclKind::Func && "no new kinds of functions");
return reinterpret_cast<ParamDecl **>(this+1);
}
return reinterpret_cast<ParamDecl **>(static_cast<AccessorDecl*>(this)+1);
}
inline DeclIterator &DeclIterator::operator++() {
Current = Current->NextDecl;
return *this;
}
inline bool AbstractFunctionDecl::hasForcedStaticDispatch() const {
if (auto func = dyn_cast<FuncDecl>(this))
return func->hasForcedStaticDispatch();
return false;
}
inline bool ValueDecl::isStatic() const {
// Currently, only storage and function decls can be static/class.
if (auto storage = dyn_cast<AbstractStorageDecl>(this))
return storage->isStatic();
if (auto func = dyn_cast<FuncDecl>(this))
return func->isStatic();
return false;
}
inline bool ValueDecl::isImportAsMember() const {
if (auto func = dyn_cast<AbstractFunctionDecl>(this))
return func->isImportAsMember();
return false;
}
inline bool ValueDecl::hasCurriedSelf() const {
if (auto *afd = dyn_cast<AbstractFunctionDecl>(this))
return afd->hasImplicitSelfDecl();
if (isa<EnumElementDecl>(this))
return true;
return false;
}
inline bool ValueDecl::hasParameterList() const {
if (auto *eed = dyn_cast<EnumElementDecl>(this))
return eed->hasAssociatedValues();
return isa<AbstractFunctionDecl>(this) || isa<SubscriptDecl>(this);
}
inline unsigned ValueDecl::getNumCurryLevels() const {
unsigned curryLevels = 0;
if (hasParameterList())
curryLevels++;
if (hasCurriedSelf())
curryLevels++;
return curryLevels;
}
inline bool Decl::isPotentiallyOverridable() const {
if (isa<VarDecl>(this) ||
isa<SubscriptDecl>(this) ||
isa<FuncDecl>(this) ||
isa<DestructorDecl>(this)) {
return getDeclContext()->getSelfClassDecl();
} else {
return false;
}
}
inline GenericParamKey::GenericParamKey(const GenericTypeParamDecl *d)
: Depth(d->getDepth()), Index(d->getIndex()) { }
inline const GenericContext *Decl::getAsGenericContext() const {
switch (getKind()) {
default: return nullptr;
#define DECL(Id, Parent) // See previous line
#define GENERIC_DECL(Id, Parent) \
case DeclKind::Id: \
return static_cast<const Id##Decl*>(this);
#include "swift/AST/DeclNodes.def"
}
}
inline bool DeclContext::classof(const Decl *D) {
switch (D->getKind()) { //
default: return false;
#define DECL(ID, PARENT) // See previous line
#define CONTEXT_DECL(ID, PARENT) \
case DeclKind::ID: return true;
#include "swift/AST/DeclNodes.def"
}
}
inline DeclContext *DeclContext::castDeclToDeclContext(const Decl *D) {
// XXX -- ModuleDecl is not defined in Decl.h, but because DeclContexts
// preface decls in memory, any DeclContext type will due.
const DeclContext *DC = static_cast<const ExtensionDecl*>(D);
switch (D->getKind()) {
default: llvm_unreachable("Not a DeclContext");
#define DECL(ID, PARENT) // See previous line
#define CONTEXT_DECL(ID, PARENT) \
case DeclKind::ID:
#include "swift/AST/DeclNodes.def"
return const_cast<DeclContext *>(DC);
}
}
inline EnumElementDecl *EnumDecl::getUniqueElement(bool hasValue) const {
EnumElementDecl *result = nullptr;
bool found = false;
for (auto elt : getAllElements()) {
if (elt->hasAssociatedValues() == hasValue) {
if (found)
return nullptr;
found = true;
result = elt;
}
}
return result;
}
/// Retrieve parameter declaration from the given source at given index.
const ParamDecl *getParameterAt(const ValueDecl *source, unsigned index);
/// Display Decl subclasses.
void simple_display(llvm::raw_ostream &out, const Decl *decl);
/// Display ValueDecl subclasses.
void simple_display(llvm::raw_ostream &out, const ValueDecl *decl);
/// Display ExtensionDecls.
inline void simple_display(llvm::raw_ostream &out, const ExtensionDecl *decl) {
simple_display(out, static_cast<const Decl *>(decl));
}
/// Display NominalTypeDecls.
inline void simple_display(llvm::raw_ostream &out,
const NominalTypeDecl *decl) {
simple_display(out, static_cast<const Decl *>(decl));
}
/// Display GenericContext.
///
/// The template keeps this sorted down in the overload set relative to the
/// more concrete overloads with Decl pointers thereby breaking a potential ambiguity.
template <typename T>
inline typename std::enable_if<std::is_same<T, GenericContext>::value>::type
simple_display(llvm::raw_ostream &out, const T *GC) {
simple_display(out, GC->getAsDecl());
}
/// Display GenericParamList.
void simple_display(llvm::raw_ostream &out, const GenericParamList *GPL);
/// Extract the source location from the given declaration.
SourceLoc extractNearestSourceLoc(const Decl *decl);
/// Extract the source location from the given declaration.
inline SourceLoc extractNearestSourceLoc(const ExtensionDecl *ext) {
return extractNearestSourceLoc(static_cast<const Decl *>(ext));
}
/// Extract the source location from the given declaration.
inline SourceLoc extractNearestSourceLoc(const GenericTypeDecl *type) {
return extractNearestSourceLoc(static_cast<const Decl *>(type));
}
/// Extract the source location from the given declaration.
inline SourceLoc extractNearestSourceLoc(const NominalTypeDecl *type) {
return extractNearestSourceLoc(static_cast<const Decl *>(type));
}
/// Extract the source location from the given declaration.
inline SourceLoc extractNearestSourceLoc(const AbstractFunctionDecl *func) {
return extractNearestSourceLoc(static_cast<const Decl *>(func));
}
} // end namespace swift
#endif