blob: 285747832d1a0a36309c0cd1fe93f432d5f2bbed [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 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file defines the 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/GenericSignature.h"
#include "swift/AST/GenericParamKey.h"
#include "swift/AST/IfConfigClause.h"
#include "swift/AST/LayoutConstraint.h"
#include "swift/AST/LazyResolver.h"
#include "swift/AST/TypeAlignments.h"
#include "swift/AST/TypeWalker.h"
#include "swift/AST/Witness.h"
#include "swift/Basic/Compiler.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"
namespace swift {
enum class AccessSemantics : unsigned char;
class ApplyExpr;
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 FuncDecl;
class BraceStmt;
class DeclAttributes;
class GenericSignature;
class GenericTypeParamDecl;
class GenericTypeParamType;
class ModuleDecl;
class NameAliasType;
class EnumCaseDecl;
class EnumElementDecl;
class ParameterList;
class ParameterTypeFlags;
class Pattern;
struct PrintOptions;
class ProtocolDecl;
class ProtocolType;
struct RawComment;
enum class ResilienceExpansion : unsigned;
class TypeAliasDecl;
class Stmt;
class SubscriptDecl;
class UnboundGenericType;
class ValueDecl;
class VarDecl;
enum class DeclKind : uint8_t {
#define DECL(Id, Parent) Id,
#define DECL_RANGE(Id, FirstId, LastId) \
First_##Id##Decl = FirstId, Last_##Id##Decl = LastId,
#include "swift/AST/DeclNodes.def"
};
/// 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,
PatternBinding,
Var,
Param,
Let,
StaticVar,
StaticLet,
ClassVar,
ClassLet,
InfixOperator,
PrefixOperator,
PostfixOperator,
PrecedenceGroup,
TypeAlias,
GenericTypeParam,
AssociatedType,
Enum,
Struct,
Class,
Protocol,
GenericEnum,
GenericStruct,
GenericClass,
Subscript,
Constructor,
Destructor,
LocalFunction,
GlobalFunction,
OperatorFunction,
Method,
StaticMethod,
ClassMethod,
Getter,
Setter,
MaterializeForSet,
Addressor,
MutableAddressor,
WillSet,
DidSet,
EnumElement,
Module,
MissingMember,
};
/// 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
};
/// Keeps track of whether a given class inherits initializers from its
/// superclass.
enum class StoredInheritsSuperclassInits {
/// We have not yet checked.
Unchecked,
/// Superclass initializers are not inherited.
NotInherited,
/// Convenience initializers in the superclass are inherited.
Inherited
};
/// 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,
};
/// Describes if an enum element constructor directly or indirectly references
/// its enclosing type.
enum class ElementRecursiveness {
/// The element does not reference its enclosing type.
NotRecursive,
/// The element is currently being validated, and may references its enclosing
/// type.
PotentiallyRecursive,
/// The element does not reference its enclosing type.
Recursive
};
/// 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 interface type of the declaration, when relevant to the
/// overload signature.
CanType InterfaceType;
/// The kind of unary operator.
UnaryOperatorKind UnaryOperator = UnaryOperatorKind::None;
/// Whether this is an instance member.
bool IsInstanceMember = false;
/// Whether this is a property.
bool IsProperty = false;
/// Whether this signature is part of a protocol extension.
bool InProtocolExtension = false;
};
/// Determine whether two overload signatures conflict.
bool conflicting(const OverloadSignature& sig1, const OverloadSignature& sig2);
/// Decl - Base class for all declarations in Swift.
class alignas(1 << DeclAlignInBits) Decl {
class DeclBitfields {
friend class Decl;
unsigned Kind : 6;
/// \brief Whether this declaration is invalid.
unsigned Invalid : 1;
/// \brief Whether this declaration was implicitly created, e.g.,
/// an implicit constructor in a struct.
unsigned Implicit : 1;
/// \brief Whether this declaration was mapped directly from a Clang AST.
///
/// Use getClangNode() to retrieve the corresponding Clang AST.
unsigned FromClang : 1;
/// \brief Whether we've already performed early attribute validation.
/// FIXME: This is ugly.
unsigned EarlyAttrValidation : 1;
/// \brief Whether this declaration is currently being validated.
unsigned BeingValidated : 1;
/// \brief Whether we have started validating the declaration; this *isn't*
/// reset after finishing it.
unsigned ValidationStarted : 1;
/// \brief Whether this declaration was added to the surrounding
/// DeclContext of an active #if config clause.
unsigned EscapedFromIfConfig : 1;
};
enum { NumDeclBits = 13 };
static_assert(NumDeclBits <= 32, "fits in an unsigned");
class PatternBindingDeclBitfields {
friend class PatternBindingDecl;
unsigned : NumDeclBits;
/// \brief Whether this pattern binding declares static variables.
unsigned IsStatic : 1;
/// \brief Whether 'static' or 'class' was used.
unsigned StaticSpelling : 2;
/// \brief The number of pattern binding declarations.
unsigned NumPatternEntries : 16;
};
enum { NumPatternBindingDeclBits = NumDeclBits + 19 };
static_assert(NumPatternBindingDeclBits <= 32, "fits in an unsigned");
class ValueDeclBitfields {
friend class ValueDecl;
friend class MemberLookupTable;
unsigned : NumDeclBits;
unsigned AlreadyInLookupTable : 1;
/// Whether we have already checked whether this declaration is a
/// redeclaration.
unsigned 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.
unsigned IsUserAccessible : 1;
};
enum { NumValueDeclBits = NumDeclBits + 3 };
static_assert(NumValueDeclBits <= 32, "fits in an unsigned");
class AbstractStorageDeclBitfields {
friend class AbstractStorageDecl;
unsigned : NumValueDeclBits;
/// Whether we are overridden later
unsigned Overridden : 1;
/// Whether the getter is mutating.
unsigned IsGetterMutating : 1;
/// Whether the setter is mutating.
unsigned IsSetterMutating : 1;
/// The storage kind.
unsigned StorageKind : 4;
};
enum { NumAbstractStorageDeclBits = NumValueDeclBits + 7 };
static_assert(NumAbstractStorageDeclBits <= 32, "fits in an unsigned");
class VarDeclBitfields {
friend class VarDecl;
unsigned : NumAbstractStorageDeclBits;
/// \brief Whether this property is a type property (currently unfortunately
/// called 'static').
unsigned IsStatic : 1;
/// \brief The specifier associated with this variable or parameter. This
/// determines the storage semantics of the value e.g. mutability.
unsigned Specifier : 2;
/// \brief Whether this declaration was an element of a capture list.
unsigned IsCaptureList : 1;
/// \brief 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.
unsigned HasNonPatternBindingInit : 1;
/// \brief 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.
unsigned IsDebuggerVar : 1;
};
enum { NumVarDeclBits = NumAbstractStorageDeclBits + 6 };
static_assert(NumVarDeclBits <= 32, "fits in an unsigned");
class EnumElementDeclBitfields {
friend class EnumElementDecl;
unsigned : NumValueDeclBits;
/// \brief Whether or not this element directly or indirectly references
/// the enum type.
unsigned Recursiveness : 2;
/// \brief Whether or not this element has an associated value.
unsigned HasArgumentType : 1;
};
enum { NumEnumElementDeclBits = NumValueDeclBits + 3 };
static_assert(NumEnumElementDeclBits <= 32, "fits in an unsigned");
class AbstractFunctionDeclBitfields {
friend class AbstractFunctionDecl;
unsigned : NumValueDeclBits;
/// \see AbstractFunctionDecl::BodyKind
unsigned BodyKind : 3;
/// Number of curried parameter lists.
unsigned NumParameterLists : 5;
/// Whether we are overridden later.
unsigned Overridden : 1;
/// Whether the function body throws.
unsigned Throws : 1;
/// Whether this function requires a new vtable entry.
unsigned NeedsNewVTableEntry : 1;
/// Whether NeedsNewVTableEntry is valid.
unsigned HasComputedNeedsNewVTableEntry : 1;
/// The ResilienceExpansion to use for default arguments.
unsigned DefaultArgumentResilienceExpansion : 1;
};
enum { NumAbstractFunctionDeclBits = NumValueDeclBits + 13 };
static_assert(NumAbstractFunctionDeclBits <= 32, "fits in an unsigned");
class FuncDeclBitfields {
friend class FuncDecl;
unsigned : NumAbstractFunctionDeclBits;
/// Whether this function is a 'static' method.
unsigned IsStatic : 1;
/// \brief Whether 'static' or 'class' was used.
unsigned StaticSpelling : 2;
};
enum { NumFuncDeclBits = NumAbstractFunctionDeclBits + 3 };
static_assert(NumFuncDeclBits <= 32, "fits in an unsigned");
class ConstructorDeclBitfields {
friend class ConstructorDecl;
unsigned : NumAbstractFunctionDeclBits;
/// 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.
unsigned ComputedBodyInitKind : 3;
};
enum { NumConstructorDeclBits = NumAbstractFunctionDeclBits + 3 };
static_assert(NumConstructorDeclBits <= 32, "fits in an unsigned");
class TypeDeclBitfields {
friend class TypeDecl;
unsigned : NumValueDeclBits;
/// Whether we have already checked the inheritance clause.
///
/// FIXME: Is this too fine-grained?
unsigned CheckedInheritanceClause : 1;
};
enum { NumTypeDeclBits = NumValueDeclBits + 1 };
static_assert(NumTypeDeclBits <= 32, "fits in an unsigned");
class GenericTypeDeclBitfields {
friend class GenericTypeDecl;
unsigned : NumTypeDeclBits;
};
enum { NumGenericTypeDeclBits = NumTypeDeclBits };
static_assert(NumGenericTypeDeclBits <= 32, "fits in an unsigned");
class TypeAliasDeclBitfields {
friend class TypeAliasDecl;
unsigned : NumGenericTypeDeclBits;
/// Whether the typealias forwards perfectly to its underlying type.
unsigned IsCompatibilityAlias : 1;
};
enum { NumTypeAliasDeclBits = NumGenericTypeDeclBits + 1 };
static_assert(NumTypeAliasDeclBits <= 32, "fits in an unsigned");
class NominalTypeDeclBitFields {
friend class NominalTypeDecl;
unsigned : NumGenericTypeDeclBits;
/// Whether or not the nominal type decl has delayed protocol or member
/// declarations.
unsigned HasDelayedMembers : 1;
/// Whether we have already added implicitly-defined initializers
/// to this declaration.
unsigned AddedImplicitInitializers : 1;
/// Whether there is are lazily-loaded conformances for this nominal type.
unsigned HasLazyConformances : 1;
};
enum { NumNominalTypeDeclBits = NumGenericTypeDeclBits + 3 };
static_assert(NumNominalTypeDeclBits <= 32, "fits in an unsigned");
class ProtocolDeclBitfields {
friend class ProtocolDecl;
unsigned : NumNominalTypeDeclBits;
/// Whether the \c RequiresClass bit is valid.
unsigned RequiresClassValid : 1;
/// Whether this is a class-bounded protocol.
unsigned RequiresClass : 1;
/// Whether the \c ExistentialConformsToSelf bit is valid.
unsigned ExistentialConformsToSelfValid : 1;
/// Whether the existential of this protocol conforms to itself.
unsigned ExistentialConformsToSelf : 1;
/// Whether the \c ExistentialTypeSupported bit is valid.
unsigned ExistentialTypeSupportedValid : 1;
/// Whether the existential of this protocol can be represented.
unsigned ExistentialTypeSupported : 1;
/// The stage of the circularity check for this protocol.
unsigned Circularity : 2;
};
enum { NumProtocolDeclBits = NumNominalTypeDeclBits + 8 };
static_assert(NumProtocolDeclBits <= 32, "fits in an unsigned");
class ClassDeclBitfields {
friend class ClassDecl;
unsigned : NumNominalTypeDeclBits;
/// The stage of the inheritance circularity check for this class.
unsigned Circularity : 2;
/// Whether this class requires all of its instance variables to
/// have in-class initializers.
unsigned RequiresStoredPropertyInits : 1;
/// Whether this class inherits its superclass's convenience
/// initializers.
///
/// This is a value of \c StoredInheritsSuperclassInits.
unsigned InheritsSuperclassInits : 2;
/// \see ClassDecl::ForeignKind
unsigned RawForeignKind : 2;
/// Whether this class contains a destructor decl.
///
/// A fully type-checked class always contains a destructor member, even if
/// it is implicit. This bit is used during parsing and type-checking to
/// control inserting the implicit destructor.
unsigned HasDestructorDecl : 1;
};
enum { NumClassDeclBits = NumNominalTypeDeclBits + 8 };
static_assert(NumClassDeclBits <= 32, "fits in an unsigned");
class StructDeclBitfields {
friend class StructDecl;
unsigned : NumNominalTypeDeclBits;
/// True if this struct has storage for fields that aren't accessible in
/// Swift.
unsigned HasUnreferenceableStorage : 1;
};
enum { NumStructDeclBits = NumNominalTypeDeclBits + 1 };
static_assert(NumStructDeclBits <= 32, "fits in an unsigned");
class EnumDeclBitfields {
friend class EnumDecl;
unsigned : NumNominalTypeDeclBits;
/// The stage of the raw type circularity check for this class.
unsigned Circularity : 2;
/// True if the enum has cases and at least one case has associated values.
mutable unsigned HasAssociatedValues : 2;
};
enum { NumEnumDeclBits = NumNominalTypeDeclBits + 4 };
static_assert(NumEnumDeclBits <= 32, "fits in an unsigned");
class PrecedenceGroupDeclBitfields {
friend class PrecedenceGroupDecl;
unsigned : NumDeclBits;
/// The group's associativity. A value of the Associativity enum.
unsigned Associativity : 2;
/// Is this an assignment operator?
unsigned IsAssignment : 1;
};
enum { NumPrecedenceGroupDeclBits = NumDeclBits + 11 };
static_assert(NumPrecedenceGroupDeclBits <= 32, "fits in an unsigned");
class AssociatedTypeDeclBitfields {
friend class AssociatedTypeDecl;
unsigned : NumTypeDeclBits;
};
enum { NumAssociatedTypeDeclBits = NumTypeDeclBits };
static_assert(NumAssociatedTypeDeclBits <= 32, "fits in an unsigned");
class ImportDeclBitfields {
friend class ImportDecl;
unsigned : NumDeclBits;
unsigned ImportKind : 3;
};
enum { NumImportDeclBits = NumDeclBits + 3 };
static_assert(NumImportDeclBits <= 32, "fits in an unsigned");
class ExtensionDeclBitfields {
friend class ExtensionDecl;
unsigned : NumDeclBits;
/// Whether we have already checked the inheritance clause.
///
/// FIXME: Is this too fine-grained?
unsigned CheckedInheritanceClause : 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.
unsigned DefaultAndMaxAccessLevel : 3;
/// Whether there is are lazily-loaded conformances for this extension.
unsigned HasLazyConformances : 1;
};
enum { NumExtensionDeclBits = NumDeclBits + 5 };
static_assert(NumExtensionDeclBits <= 32, "fits in an unsigned");
class IfConfigDeclBitfields {
friend class IfConfigDecl;
unsigned : NumDeclBits;
/// Whether this decl is missing its closing '#endif'.
unsigned HadMissingEnd : 1;
};
enum { NumIfConfigDeclBits = NumDeclBits + 1 };
static_assert(NumIfConfigDeclBits <= 32, "fits in an unsigned");
class MissingMemberDeclBitfields {
friend class MissingMemberDecl;
unsigned : NumDeclBits;
unsigned NumberOfVTableEntries : 2;
};
enum { NumMissingMemberDeclBits = NumDeclBits + 2 };
static_assert(NumMissingMemberDeclBits <= 32, "fits in an unsigned");
protected:
union {
DeclBitfields DeclBits;
PatternBindingDeclBitfields PatternBindingDeclBits;
ValueDeclBitfields ValueDeclBits;
AbstractStorageDeclBitfields AbstractStorageDeclBits;
AbstractFunctionDeclBitfields AbstractFunctionDeclBits;
VarDeclBitfields VarDeclBits;
EnumElementDeclBitfields EnumElementDeclBits;
FuncDeclBitfields FuncDeclBits;
ConstructorDeclBitfields ConstructorDeclBits;
TypeDeclBitfields TypeDeclBits;
GenericTypeDeclBitfields GenericTypeDeclBits;
TypeAliasDeclBitfields TypeAliasDeclBits;
NominalTypeDeclBitFields NominalTypeDeclBits;
ProtocolDeclBitfields ProtocolDeclBits;
ClassDeclBitfields ClassDeclBits;
StructDeclBitfields StructDeclBits;
EnumDeclBitfields EnumDeclBits;
AssociatedTypeDeclBitfields AssociatedTypeDeclBits;
PrecedenceGroupDeclBitfields PrecedenceGroupDeclBits;
ImportDeclBitfields ImportDeclBits;
ExtensionDeclBitfields ExtensionDeclBits;
IfConfigDeclBitfields IfConfigDeclBits;
MissingMemberDeclBitfields MissingMemberDeclBits;
uint32_t OpaqueBits;
};
// FIXME: Unused padding here.
// 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;
protected:
Decl(DeclKind kind, llvm::PointerUnion<DeclContext *, ASTContext *> context)
: OpaqueBits(0), Context(context) {
DeclBits.Kind = unsigned(kind);
DeclBits.Invalid = false;
DeclBits.Implicit = false;
DeclBits.FromClang = false;
DeclBits.EarlyAttrValidation = false;
DeclBits.BeingValidated = false;
DeclBits.ValidationStarted = false;
DeclBits.EscapedFromIfConfig = false;
}
ClangNode getClangNodeImpl() const {
assert(DeclBits.FromClang);
return ClangNode::getFromOpaqueValue(
*(reinterpret_cast<void * const*>(this) - 1));
}
/// \brief Set the Clang node associated with this declaration.
void setClangNode(ClangNode Node) {
DeclBits.FromClang = true;
// Extra memory is allocated for this.
*(reinterpret_cast<void **>(this) - 1) = Node.getOpaqueValue();
}
void updateClangNode(ClangNode node) {
assert(hasClangNode());
setClangNode(node);
}
friend class ClangImporter;
DeclContext *getDeclContextForModule() const;
public:
DeclKind getKind() const { return DeclKind(DeclBits.Kind); }
/// \brief 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;
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;
/// \brief Retrieve the module in which this declaration resides.
ModuleDecl *getModuleContext() const;
/// getASTContext - Return the ASTContext that this decl lives in.
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;
SourceLoc TrailingSemiLoc;
LLVM_ATTRIBUTE_DEPRECATED(
void dump() const LLVM_ATTRIBUTE_USED,
"only for use within the debugger");
void dump(raw_ostream &OS, unsigned Indent = 0) const;
/// \brief 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;
/// \brief 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;
/// \brief 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);
/// \brief Return whether this declaration has been determined invalid.
bool isInvalid() const { return DeclBits.Invalid; }
/// \brief Mark this declaration invalid.
void setInvalid(bool isInvalid = true) { DeclBits.Invalid = isInvalid; }
/// \brief Determine whether this declaration was implicitly generated by the
/// compiler (rather than explicitly written in source code).
bool isImplicit() const { return DeclBits.Implicit; }
/// \brief Mark this declaration as implicit.
void setImplicit(bool implicit = true) { DeclBits.Implicit = implicit; }
/// Whether we have already done early attribute validation.
bool didEarlyAttrValidation() const { return DeclBits.EarlyAttrValidation; }
/// Set whether we've performed early attribute validation.
void setEarlyAttrValidation(bool validated = true) {
DeclBits.EarlyAttrValidation = validated;
}
/// Whether the declaration has a valid interface type and
/// generic signature.
bool isBeingValidated() const {
return DeclBits.BeingValidated;
}
/// Toggle whether or not the declaration is being validated.
void setIsBeingValidated(bool ibv = true) {
assert(DeclBits.BeingValidated != ibv);
DeclBits.BeingValidated = ibv;
if (ibv) {
DeclBits.ValidationStarted = true;
}
}
bool hasValidationStarted() const { return DeclBits.ValidationStarted; }
/// Manually indicate that validation has started for the declaration.
///
/// This is implied by setIsBeingValidated(true) (i.e. starting validation)
/// and so rarely needs to be called directly.
void setValidationStarted() { DeclBits.ValidationStarted = true; }
bool escapedFromIfConfig() const {
return DeclBits.EscapedFromIfConfig;
}
void setEscapedFromIfConfig(bool Escaped) {
DeclBits.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;
/// \brief Returns true if there is a Clang AST node associated
/// with self.
bool hasClangNode() const {
return DeclBits.FromClang;
}
/// \brief Retrieve the Clang AST node from which this declaration was
/// synthesized, if any.
ClangNode getClangNode() const {
if (!DeclBits.FromClang)
return ClangNode();
return getClangNodeImpl();
}
/// \brief Retrieve the Clang declaration from which this declaration was
/// synthesized, if any.
const clang::Decl *getClangDecl() const {
if (!DeclBits.FromClang)
return nullptr;
return getClangNodeImpl().getAsDecl();
}
/// \brief Retrieve the Clang macro from which this declaration was
/// synthesized, if any.
const clang::MacroInfo *getClangMacro() {
if (!DeclBits.FromClang)
return nullptr;
return getClangNodeImpl().getAsMacro();
}
bool isPrivateStdlibDecl(bool treatNonBuiltinProtocolsAsPublic = true) const;
/// Whether this declaration is weak-imported.
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;
// 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;
}
};
/// \brief 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.
};
/// \brief 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:
/// \brief 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 };
}
/// \brief 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 };
}
/// \brief 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};
}
/// \brief Determine the kind of requirement
RequirementReprKind getKind() const { return Kind; }
/// \brief Determine whether this requirement is invalid.
bool isInvalid() const { return Invalid; }
/// \brief Mark this requirement invalid.
void setInvalid() { Invalid = true; }
/// \brief 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;
}
/// \brief 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;
}
/// \brief Retrieve the location of the ':' in an explicitly-written
/// conformance requirement.
SourceLoc getColonLoc() const {
assert(getKind() == RequirementReprKind::TypeConstraint ||
getKind() == RequirementReprKind::LayoutConstraint);
return SeparatorLoc;
}
/// \brief 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;
}
/// \brief 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;
}
/// \brief Retrieve the location of the '==' in an explicitly-written
/// same-type requirement.
SourceLoc getEqualLoc() const {
assert(getKind() == RequirementReprKind::SameType);
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);
}
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(); }
/// \brief Retrieve the location of the 'where' keyword, or an invalid
/// location if 'where' was not present.
SourceLoc getWhereLoc() const { return WhereLoc; }
/// \brief 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; }
/// \brief 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 that are written within the brackets,
/// which does not include any 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);
/// \brief Retrieve the outer generic parameter list, which provides the
/// generic parameters of the context in which this generic parameter list
/// exists.
///
/// Consider the following generic class:
///
/// \code
/// class Vector<T> {
/// init<R : Range where R.Element == T>(range : R) { }
/// }
/// \endcode
///
/// The generic parameter list <T> has no outer parameters, because it is
/// the outermost generic parameter list. The generic parameter list
/// <R : Range...> for the constructor has the generic parameter list <T> as
/// its outer generic parameter list.
GenericParamList *getOuterParameters() const { return OuterParameters; }
/// \brief 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);
}
/// Retrieve the depth of this generic parameter list.
unsigned getDepth() const {
unsigned depth = 0;
for (auto gp = getOuterParameters(); gp; gp = gp->getOuterParameters())
++depth;
return 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);
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);
}
};
class GenericContext : public DeclContext {
private:
GenericParamList *GenericParams = nullptr;
/// 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 or environment of this declaration.
///
/// When this declaration stores only a signature, the generic
/// environment will be lazily loaded.
mutable llvm::PointerUnion<GenericSignature *, GenericEnvironment *>
GenericSigOrEnv;
/// Lazily populate the generic environment.
GenericEnvironment *getLazyGenericEnvironmentSlow() const;
protected:
GenericContext(DeclContextKind Kind, DeclContext *Parent)
: DeclContext(Kind, Parent) { }
public:
/// \brief Retrieve the set of parameters to a generic context, or null if
/// this context is not generic.
GenericParamList *getGenericParams() const { return GenericParams; }
void setGenericParams(GenericParamList *GenericParams);
/// \brief Determine whether this context has generic parameters
/// of its own.
bool isGeneric() const { return GenericParams != nullptr; }
/// 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.
ArrayRef<GenericTypeParamType *> getInnermostGenericParamTypes() const {
if (auto sig = getGenericSignature())
return sig->getInnermostGenericParams();
else
return { };
}
/// Retrieve the generic requirements.
ArrayRef<Requirement> getGenericRequirements() const {
if (auto sig = getGenericSignature())
return sig->getRequirements();
else
return { };
}
/// Set a lazy generic environment.
void setLazyGenericEnvironment(LazyMemberLoader *lazyLoader,
GenericSignature *genericSig,
uint64_t genericEnvData);
/// Whether this generic context has a lazily-created generic environment
/// that has not yet been constructed.
bool hasLazyGenericEnvironment() const;
/// Set the generic context of this context.
void setGenericEnvironment(GenericEnvironment *genericEnv);
};
/// 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;
public:
typedef std::pair<Identifier, SourceLoc> AccessPathElement;
private:
SourceLoc ImportLoc;
SourceLoc KindLoc;
/// The number of elements in this path.
unsigned NumPathElements;
/// 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>(), 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>(ImportDeclBits.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 getLoc() 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 Decl, public GenericContext,
public IterableDeclContext {
SourceLoc ExtensionLoc; // Location of 'extension' keyword.
SourceRange Braces;
/// The type being extended.
TypeLoc ExtendedType;
MutableArrayRef<TypeLoc> Inherited;
/// \brief 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, TypeLoc 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 (!ExtensionDeclBits.HasLazyConformances)
return { nullptr, 0 };
return takeConformanceLoaderSlow();
}
/// Slow path for \c takeConformanceLoader().
std::pair<LazyMemberLoader *, uint64_t> takeConformanceLoaderSlow();
public:
using Decl::getASTContext;
/// Create a new extension declaration.
static ExtensionDecl *create(ASTContext &ctx, SourceLoc extensionLoc,
TypeLoc extendedType,
MutableArrayRef<TypeLoc> inherited,
DeclContext *parent,
TrailingWhereClause *trailingWhereClause,
ClangNode clangNode = ClangNode());
SourceLoc getStartLoc() const { return ExtensionLoc; }
SourceLoc getLoc() const { return ExtensionLoc; }
SourceRange getSourceRange() const {
return { ExtensionLoc, Braces.End };
}
SourceRange getBraces() const { return Braces; }
void setBraces(SourceRange braces) { Braces = braces; }
/// Retrieve the type being extended.
Type getExtendedType() const { return ExtendedType.getType(); }
/// Retrieve the extended type location.
TypeLoc &getExtendedTypeLoc() { return ExtendedType; }
/// Retrieve the extended type location.
const TypeLoc &getExtendedTypeLoc() const { return ExtendedType; }
/// \brief 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; }
/// Whether we have fully checked the extension.
bool hasValidSignature() const {
return hasValidationStarted() && !isBeingValidated();
}
/// Whether we already type-checked the inheritance clause.
bool checkedInheritanceClause() const {
return ExtensionDeclBits.CheckedInheritanceClause;
}
/// Note that we have already type-checked the inheritance clause.
void setCheckedInheritanceClause(bool checked = true) {
ExtensionDeclBits.CheckedInheritanceClause = checked;
}
bool hasDefaultAccessLevel() const {
return ExtensionDeclBits.DefaultAndMaxAccessLevel != 0;
}
AccessLevel getDefaultAccessLevel() const {
assert(hasDefaultAccessLevel() && "not computed yet");
if (ExtensionDeclBits.DefaultAndMaxAccessLevel &
(1 << (static_cast<unsigned>(AccessLevel::FilePrivate) - 1)))
return AccessLevel::FilePrivate;
if (ExtensionDeclBits.DefaultAndMaxAccessLevel &
(1 << (static_cast<unsigned>(AccessLevel::Internal) - 1)))
return AccessLevel::Internal;
return AccessLevel::Public;
}
AccessLevel getMaxAccessLevel() const {
assert(hasDefaultAccessLevel() && "not computed yet");
if (ExtensionDeclBits.DefaultAndMaxAccessLevel &
(1 << (static_cast<unsigned>(AccessLevel::Public) - 1)))
return AccessLevel::Public;
if (ExtensionDeclBits.DefaultAndMaxAccessLevel &
(1 << (static_cast<unsigned>(AccessLevel::Internal) - 1)))
return AccessLevel::Internal;
return AccessLevel::FilePrivate;
}
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");
ExtensionDeclBits.DefaultAndMaxAccessLevel =
(1 << (static_cast<unsigned>(defaultAccess) - 1)) |
(1 << (static_cast<unsigned>(maxAccess) - 1));
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;
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() == DeclKind::Extension;
}
static bool classof(const DeclContext *C) {
return C->getContextKind() == DeclContextKind::ExtensionDecl;
}
static bool classof(const IterableDeclContext *C) {
return C->getIterableContextKind()
== IterableDeclContextKind::ExtensionDecl;
}
using DeclContext::operator new;
};
/// \brief 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;
}
};
/// \brief 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 {
Pattern *ThePattern;
enum class Flags {
Checked = 1 << 0,
Removed = 1 << 1
};
// When the initializer is removed we don't actually clear the pointer
// because we might need to get initializer's source range. Since the
// initializer is ASTContext-allocated it is safe.
llvm::PointerIntPair<Expr *, 2, OptionSet<Flags>> InitCheckedAndRemoved;
/// The initializer context used for this pattern binding entry.
DeclContext *InitContext = nullptr;
friend class PatternBindingInitializer;
public:
PatternBindingEntry(Pattern *P, Expr *E, DeclContext *InitContext)
: ThePattern(P), InitCheckedAndRemoved(E, {}), InitContext(InitContext) {}
Pattern *getPattern() const { return ThePattern; }
void setPattern(Pattern *P) { ThePattern = P; }
Expr *getInit() const {
return (InitCheckedAndRemoved.getInt().contains(Flags::Removed))
? nullptr : InitCheckedAndRemoved.getPointer();
}
SourceRange getOrigInitRange() const;
void setInit(Expr *E);
/// Retrieve the initializer as it was written in the source.
Expr *getInitAsWritten() const { return InitCheckedAndRemoved.getPointer(); }
bool isInitializerChecked() const {
return InitCheckedAndRemoved.getInt().contains(Flags::Checked);
}
void setInitializerChecked() {
InitCheckedAndRemoved.setInt(
InitCheckedAndRemoved.getInt() | Flags::Checked);
}
// Return the first variable initialized by this pattern.
VarDecl *getAnchoringVarDecl() const;
// Retrieve the declaration context for the initializer.
DeclContext *getInitContext() const { return InitContext; }
/// Override the initializer context.
void setInitContext(DeclContext *dc) { InitContext = dc; }
/// Retrieve the source range covered by this pattern binding.
///
/// \param omitAccessors Whether the computation should omit the accessors
/// from the source range.
SourceRange getSourceRange(bool omitAccessors = false) const;
};
/// \brief 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;
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);
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, Expr *E,
DeclContext *Parent);
static PatternBindingDecl *createDeserialized(
ASTContext &Ctx, SourceLoc StaticLoc,
StaticSpellingKind StaticSpelling,
SourceLoc VarLoc,
unsigned NumPatternEntries,
DeclContext *Parent);
SourceLoc getStartLoc() const {
return StaticLoc.isValid() ? StaticLoc : VarLoc;
}
SourceLoc getLoc() const { return VarLoc; }
SourceRange getSourceRange() const;
unsigned getNumPatternEntries() const {
return PatternBindingDeclBits.NumPatternEntries;
}
ArrayRef<PatternBindingEntry> getPatternList() const {
return const_cast<PatternBindingDecl*>(this)->getMutablePatternList();
}
Expr *getInit(unsigned i) const {
return getPatternList()[i].getInit();
}
SourceRange getOrigInitRange(unsigned i) const {
return getPatternList()[i].getOrigInitRange();
}
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);
/// 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.
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();
}
/// Does this binding declare something that requires storage?
bool hasStorage() const;
/// When the pattern binding contains only a single variable with no
/// destructuring, retrieve that variable.
VarDecl *getSingleVar() const;
bool isStatic() const { return PatternBindingDeclBits.IsStatic; }
void setStatic(bool s) { PatternBindingDeclBits.IsStatic = s; }
SourceLoc getStaticLoc() const { return StaticLoc; }
/// \returns the way 'static'/'class' was spelled in the source.
StaticSpellingKind getStaticSpelling() const {
return static_cast<StaticSpellingKind>(
PatternBindingDeclBits.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 Decl, public DeclContext {
BraceStmt *Body;
public:
TopLevelCodeDecl(DeclContext *Parent, BraceStmt *Body = nullptr)
: Decl(DeclKind::TopLevelCode, Parent),
DeclContext(DeclContextKind::TopLevelCodeDecl, Parent),
Body(Body) {}
BraceStmt *getBody() const { return Body; }
void setBody(BraceStmt *b) { Body = b; }
SourceLoc getStartLoc() const;
SourceLoc getLoc() const { return getStartLoc(); }
SourceRange getSourceRange() const;
static bool classof(const Decl *D) {
return D->getKind() == DeclKind::TopLevelCode;
}
static bool classof(const DeclContext *C) {
return C->getContextKind() == DeclContextKind::TopLevelCodeDecl;
}
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;
public:
IfConfigDecl(DeclContext *Parent, ArrayRef<IfConfigClause> Clauses,
SourceLoc EndLoc, bool HadMissingEnd)
: Decl(DeclKind::IfConfig, Parent), Clauses(Clauses), EndLoc(EndLoc)
{
IfConfigDeclBits.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; }
SourceLoc getLoc() const { return Clauses[0].Loc; }
bool hadMissingEnd() const { return IfConfigDeclBits.HadMissingEnd; }
SourceRange getSourceRange() const;
static bool classof(const Decl *D) {
return D->getKind() == DeclKind::IfConfig;
}
};
/// 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;
protected:
ValueDecl(DeclKind K,
llvm::PointerUnion<DeclContext *, ASTContext *> context,
DeclName name, SourceLoc NameLoc)
: Decl(K, context), Name(name), NameLoc(NameLoc) {
ValueDeclBits.AlreadyInLookupTable = false;
ValueDeclBits.CheckedRedeclaration = false;
ValueDeclBits.IsUserAccessible = true;
}
public:
/// \brief Return true if this is a definition of a decl, not a forward
/// declaration (e.g. of a function) that is implemented outside of the
/// swift code.
bool isDefinition() const;
/// \brief 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 ValueDeclBits.CheckedRedeclaration;
}
/// Set whether we have already checked this declaration as a
/// redeclaration.
void setCheckedRedeclaration(bool checked) {
ValueDeclBits.CheckedRedeclaration = checked;
}
void setUserAccessible(bool Accessible) {
ValueDeclBits.IsUserAccessible = Accessible;
}
bool isUserAccessible() const {
return ValueDeclBits.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() 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; }
SourceLoc getLoc() const { return NameLoc; }
bool hasAccess() const {
return TypeAndAccess.getInt().hasValue();
}
/// \see getFormalAccess
AccessLevel getFormalAccessImpl(const DeclContext *useDC) const;
bool isVersionedInternalDecl() const;
/// Returns the access level specified explicitly by the user, or provided by
/// default according to language rules.
///
/// This is the access 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.
///
/// \sa getFormalAccessScope
AccessLevel getFormalAccess(const DeclContext *useDC = nullptr,
bool respectVersionedAttr = false) const {
assert(hasAccess() && "access not computed yet");
AccessLevel result = TypeAndAccess.getInt().getValue();
if (respectVersionedAttr &&
result == AccessLevel::Internal &&
isVersionedInternalDecl()) {
assert(!useDC);
return AccessLevel::Public;
}
if (useDC && (result == AccessLevel::Internal ||
result == AccessLevel::Public))
return getFormalAccessImpl(useDC);
return result;
}
/// 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())</code>
///
/// \sa getFormalAccess
/// \sa isAccessibleFrom
AccessScope
getFormalAccessScope(const DeclContext *useDC = nullptr,
bool respectVersionedAttr = false) const;
/// 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.
bool isAccessibleFrom(const DeclContext *DC) 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);
bool hasValidSignature() const {
return hasInterfaceType() && !isBeingValidated();
}
/// 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;
/// isInstanceMember - Determine whether this value is an instance member
/// of an enum or protocol.
bool isInstanceMember() const;
/// needsCapture - Check whether referring to this decl from a nested
/// function requires capturing it.
bool needsCapture() 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;
/// Compute the overload signature for this declaration.
OverloadSignature getOverloadSignature() 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 {
return getAttrs().hasAttribute<ObjCAttr>();
}
void setIsObjC(bool Value);
/// Is this declaration marked with 'final'?
bool isFinal() const {
return getAttrs().hasAttribute<FinalAttr>();
}
/// Is this declaration marked with 'dynamic'?
bool isDynamic() const {
return getAttrs().hasAttribute<DynamicAttr>();
}
/// Returns true if this decl can be found by id-style dynamic lookup.
bool canBeAccessedByDynamicLookup() const;
/// 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.
AccessSemantics getAccessSemanticsFromContext(const DeclContext *DC) 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;
};
/// 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)
{
TypeDeclBits.CheckedInheritanceClause = false;
}
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;
/// \brief 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; }
/// Whether we already type-checked the inheritance clause.
bool checkedInheritanceClause() const {
return TypeDeclBits.CheckedInheritanceClause;
}
/// Note that we have already type-checked the inheritance clause.
void setCheckedInheritanceClause(bool checked = true) {
TypeDeclBits.CheckedInheritanceClause = checked;
}
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);
};
/// 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 TypeDecl, public GenericContext {
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) {
return C->getContextKind() == DeclContextKind::GenericTypeDecl;
}
static bool classof(const Decl *D) {
return D->getKind() >= DeclKind::First_GenericTypeDecl &&
D->getKind() <= DeclKind::Last_GenericTypeDecl;
}
};
/// TypeAliasDecl - This is a declaration of a typealias, for example:
///
/// typealias Foo = Int
///
/// TypeAliasDecl's always have 'MetatypeType' type.
///
class TypeAliasDecl : public GenericTypeDecl {
/// The location of the 'typealias' keyword
SourceLoc TypeAliasLoc;
/// The location of the equal '=' token
SourceLoc EqualLoc;
/// 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;
}
TypeLoc &getUnderlyingTypeLoc() {
return UnderlyingTy;
}
const TypeLoc &getUnderlyingTypeLoc() const {
return UnderlyingTy;
}
/// Set the underlying type, for deserialization and synthesized
/// aliases.
void setUnderlyingType(Type type);
/// For generic typealiases, return the unbound generic type.
UnboundGenericType *getUnboundGenericType() const;
bool isCompatibilityAlias() const {
return TypeAliasDeclBits.IsCompatibilityAlias;
}
void markAsCompatibilityAlias(bool newValue = true) {
TypeAliasDeclBits.IsCompatibilityAlias = newValue;
}
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) {
auto GTD = dyn_cast<GenericTypeDecl>(C);
return GTD && classof(GTD);
}
};
/// 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 {
unsigned Depth : 16;
unsigned Index : 16;
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 Depth; }
/// Set the depth of this generic type parameter.
///
/// \sa getDepth
void setDepth(unsigned depth) { Depth = depth; }
/// 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 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
///
/// Every protocol has an implicitly-created associated type 'Self' that
/// describes a type that conforms to the protocol.
class AssociatedTypeDecl : public AbstractTypeParamDecl {
/// The location of the initial keyword.
SourceLoc KeywordLoc;
/// The default definition.
TypeLoc DefaultDefinition;
/// The where clause attached to the associated type.
TrailingWhereClause *TrailingWhere;
LazyMemberLoader *Resolver = nullptr;
uint64_t ResolverContextData;
public:
AssociatedTypeDecl(DeclContext *dc, SourceLoc keywordLoc, Identifier name,
SourceLoc nameLoc, TypeLoc 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());
}
/// Retrieve the default definition type.
Type getDefaultDefinitionType() const {
return getDefaultDefinitionLoc().getType();
}
TypeLoc &getDefaultDefinitionLoc();
const TypeLoc &getDefaultDefinitionLoc() const {
return const_cast<AssociatedTypeDecl *>(this)->getDefaultDefinitionLoc();
}
/// 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;
}
/// computeType - Compute the type (and declared type) of this associated
/// type; can only be called after the alias type has been resolved.
void computeType();
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 optional types.
enum OptionalTypeKind : unsigned {
/// The type is not an optional type.
OTK_None = 0,
/// The type is Optional<T>.
OTK_Optional,
/// The type is ImplicitlyUnwrappedOptional<T>.
OTK_ImplicitlyUnwrappedOptional
};
enum { NumOptionalTypeKinds = 2 };
// 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.");
}
/// NominalTypeDecl - a declaration of a nominal type, like a struct.
class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext {
SourceRange Braces;
/// \brief The first extension of this type.
ExtensionDecl *FirstExtension = nullptr;
/// \brief The last extension of this type, used solely for efficient
/// insertion of new extensions.
ExtensionDecl *LastExtension = nullptr;
/// \brief 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 (!NominalTypeDeclBits.HasLazyConformances)
return { nullptr, 0 };
return takeConformanceLoaderSlow();
}
/// Slow path for \c takeConformanceLoader().
std::pair<LazyMemberLoader *, uint64_t> takeConformanceLoaderSlow();
/// \brief 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.
llvm::PointerIntPair<MemberLookupTable *, 1, bool> LookupTable;
/// Prepare the lookup table to make it ready for lookups.
void prepareLookupTable(bool ignoreNewExtensions);
/// 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);
/// \brief 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 DeclaredTyInContext;
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)
{
setGenericParams(GenericParams);
NominalTypeDeclBits.HasDelayedMembers = false;
NominalTypeDeclBits.AddedImplicitInitializers = false;
ExtensionGeneration = 0;
NominalTypeDeclBits.HasLazyConformances = false;
}
friend class ProtocolType;
public:
using GenericTypeDecl::getASTContext;
SourceRange getBraces() const { return Braces; }
void setBraces(SourceRange braces) { Braces = braces; }
/// \brief Does this declaration expose a fixed layout to all resilience
/// domains?
///
/// For structs, this means clients can assume the number and order of
/// stored properties will not change.
///
/// For enums, this means clients can assume the number and order of
/// cases will not change.
bool hasFixedLayout() const;
/// \brief Does this declaration expose a fixed layout to the given
/// module?
bool hasFixedLayout(ModuleDecl *M, ResilienceExpansion expansion) const;
/// \brief Returns true if this decl contains delayed value or protocol
/// declarations.
bool hasDelayedMembers() const {
return NominalTypeDeclBits.HasDelayedMembers;
}
/// \brief Mark this declaration as having delayed members or not.
void setHasDelayedMembers(bool hasDelayedMembers = true) {
NominalTypeDeclBits.HasDelayedMembers = hasDelayedMembers;
}
/// Determine whether we have already attempted to add any
/// implicitly-defined initializers to this declaration.
bool addedImplicitInitializers() const {
return NominalTypeDeclBits.AddedImplicitInitializers;
}
/// Note that we have attempted to
void setAddedImplicitInitializers() {
NominalTypeDeclBits.AddedImplicitInitializers = true;
}
/// Compute the type of this nominal 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;
/// getDeclaredTypeInContext - Retrieve the type declared by this entity, with
/// context archetypes bound if this is a generic type.
Type getDeclaredTypeInContext() const;
/// getDeclaredInterfaceType - Retrieve the type declared by this entity, with
/// generic parameters bound if this is a generic type.
Type getDeclaredInterfaceType() const;
/// \brief Add a new extension to this nominal type.
void addExtension(ExtensionDecl *extension);
/// \brief Retrieve the set of extensions of this type.
ExtensionRange getExtensions();
/// Make a member of this nominal type, or one of its extensions,
/// immediately visible in the lookup table.
///
/// A member of a nominal type or extension thereof will become
/// visible to name lookup as soon as it is added. However, if the
/// addition of a member is delayed---for example, because it's
/// being introduced in response to name lookup---this method can be
/// called to make it immediately visible.
void makeMemberVisible(ValueDecl *member);
/// 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.
///
/// \param ignoreNewExtensions Whether to avoid loading any new extension.
/// Used by the module loader to break recursion.
TinyPtrVector<ValueDecl *> lookupDirect(DeclName name,
bool ignoreNewExtensions = false);
/// 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);
/// \brief True if the type can implicitly derive a conformance for the given
/// protocol.
///
/// If true, explicit conformance checking will synthesize implicit
/// declarations for requirements of the protocol that are not satisfied by
/// the type's explicit members.
bool derivesProtocolConformance(ProtocolDecl *protocol) const;
void setConformanceLoader(LazyMemberLoader *resolver, uint64_t contextData);
/// classifyAsOptionalType - Decide whether this declaration is one
/// of the library-intrinsic Optional<T> or ImplicitlyUnwrappedOptional<T> types.
OptionalTypeKind classifyAsOptionalType() const;
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.
StoredPropertyRange getStoredProperties(bool skipInaccessible = false) const {
return StoredPropertyRange(getMembers(),
ToStoredProperty(skipInaccessible));
}
// 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) {
auto GTD = dyn_cast<GenericTypeDecl>(C);
return GTD && classof(GTD);
}
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; }
};
/// \brief 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;
struct {
/// The raw type and a bit to indicate whether the
/// raw was computed yet or not.
llvm::PointerIntPair<Type, 1, bool> RawType;
} LazySemanticInfo;
friend class IterativeTypeChecker;
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 is an enum with two cases, return the other case. Otherwise,
/// return nullptr.
EnumElementDecl *getOppositeBinaryDecl(EnumElementDecl *decl) const {
ElementRange range = getAllElements();
auto iter = range.begin();
if (iter == range.end())
return nullptr;
bool seenDecl = false;
EnumElementDecl *result = nullptr;
if (*iter == decl) {
seenDecl = true;
} else {
result = *iter;
}
++iter;
if (iter == range.end())
return nullptr;
if (seenDecl) {
assert(!result);
result = *iter;
} else {
if (decl != *iter)
return nullptr;
seenDecl = true;
}
++iter;
// If we reach this point, we saw the decl we were looking for and one other
// case. If we have any additional cases, then we do not have a binary enum.
if (iter != range.end())
return nullptr;
// This is always true since we have already returned earlier nullptr if we
// did not see the decl at all.
assert(seenDecl);
return result;
}
/// 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>(EnumDeclBits.Circularity);
}
/// Record the current stage of circularity checking.
void setCircularityCheck(CircularityCheck circularity) {
EnumDeclBits.Circularity = static_cast<unsigned>(circularity);
}
// 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) {
auto GTD = dyn_cast<GenericTypeDecl>(C);
return GTD && classof(static_cast<const Decl*>(GTD));
}
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)LazySemanticInfo.RawType.getPointer();
}
/// Retrieve the declared raw type of the enum from its inheritance clause,
/// or null if it has none.
Type getRawType() const {
return LazySemanticInfo.RawType.getPointer();
}
/// Set the raw type of the enum from its inheritance clause.
void setRawType(Type rawType) {
LazySemanticInfo.RawType.setPointerAndInt(rawType, true);
}
/// 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 the enum has cases.
bool hasCases() const {
return !getAllElements().empty();
}
/// True if the enum is marked 'indirect'.
bool isIndirect() const {
return getAttrs().hasAttribute<IndirectAttr>();
}
};
/// 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) {
auto GTD = dyn_cast<GenericTypeDecl>(C);
return GTD && classof(static_cast<const Decl*>(GTD));
}
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 StructDeclBits.HasUnreferenceableStorage;
}
void setHasUnreferenceableStorage(bool v) {
StructDeclBits.HasUnreferenceableStorage = v;
}
};
/// The kind of artificial main to generate for a class.
enum class ArtificialMainKind : uint8_t {
NSApplicationMain,
UIApplicationMain,
};
enum class ObjCClassKind : uint8_t {
/// Neither the class nor any of its superclasses are @objc.
NonObjC,
/// One of the superclasses is @objc but another superclass or the
/// class itself has generic parameters, so while it cannot be
/// directly represented in Objective-C, it has implicitly @objc
/// members.
ObjCMembers,
/// The top-level ancestor of this class is not @objc, but the
/// class itself is.
ObjCWithSwiftRoot,
/// The class is bona-fide @objc.
ObjC,
};
/// 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 type and a bit to indicate whether the
/// superclass was computed yet or not.
llvm::PointerIntPair<Type, 1, bool> Superclass;
} LazySemanticInfo;
/// Whether the class has @objc ancestry.
unsigned ObjCKind : 3;
unsigned HasMissingDesignatedInitializers : 1;
unsigned HasMissingVTableEntries : 1;
friend class IterativeTypeChecker;
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 this class has a superclass.
bool hasSuperclass() const { return (bool)getSuperclass(); }
/// Retrieve the superclass of this class, or null if there is no superclass.
Type getSuperclass() const { return LazySemanticInfo.Superclass.getPointer(); }
/// Retrieve the ClassDecl for the superclass of this class, or null if there
/// is no superclass.
ClassDecl *getSuperclassDecl() 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>(ClassDeclBits.Circularity);
}
/// Record the current stage of circularity checking.
void setCircularityCheck(CircularityCheck circularity) {
ClassDeclBits.Circularity = static_cast<unsigned>(circularity);
}
//// Whether this class requires all of its stored properties to
//// have initializers in the class definition.
bool requiresStoredPropertyInits() const {
return ClassDeclBits.RequiresStoredPropertyInits;
}
/// Set whether this class requires all of its stored properties to
/// have initializers in the class definition.
void setRequiresStoredPropertyInits(bool requiresInits) {
ClassDeclBits.RequiresStoredPropertyInits = requiresInits;
}
/// \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>(ClassDeclBits.RawForeignKind);
}
void setForeignClassKind(ForeignKind kind) {
ClassDeclBits.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) {
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) {
HasMissingVTableEntries = 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;
/// True if the class has a destructor.
///
/// Fully type-checked classes always contain destructors, but during parsing
/// or type-checking, the implicit destructor may not have been synthesized
/// yet if one was not explicitly declared.
bool hasDestructor() const { return ClassDeclBits.HasDestructorDecl; }
/// Set the 'has destructor' flag.
void setHasDestructor() { ClassDeclBits.HasDestructorDecl = 1; }
/// Retrieve the destructor for this class.
DestructorDecl *getDestructor();
/// Determine whether this class inherits the convenience initializers
/// from its superclass.
///
/// \param resolver Used to resolve the signatures of initializers, which is
/// required for name lookup.
bool inheritsSuperclassInitializers(LazyResolver *resolver);
/// Figure out if this class has any @objc ancestors, in which case it should
/// have implicitly @objc members. Note that a class with generic ancestry
/// might have implicitly @objc members, but will never itself be @objc.
ObjCClassKind checkObjCAncestry() const;
/// 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 whose Objective-C name has been
/// finalized.
void recordObjCMethod(AbstractFunctionDecl *method);
// 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) {
auto GTD = dyn_cast<GenericTypeDecl>(C);
return GTD && classof(static_cast<const Decl*>(GTD));
}
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 isObjC() && hasClangNode() && isGenericContext();
}
/// 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()
/// }
class ProtocolDecl final : public NominalTypeDecl {
SourceLoc ProtocolLoc;
/// The syntactic representation of the where clause in a protocol like
/// `protocol ... where ... { ... }`.
TrailingWhereClause *TrailingWhere;
llvm::DenseMap<ValueDecl *, Witness> DefaultWitnesses;
/// The generic signature representing exactly the new requirements introduced
/// by this protocol.
const Requirement *RequirementSignature = nullptr;
/// True if the protocol has requirements that cannot be satisfied (e.g.
/// because they could not be imported from Objective-C).
unsigned HasMissingRequirements : 1;
/// If this is a compiler-known protocol, this will be a KnownProtocolKind
/// value, plus one. Otherwise, it will be 0.
unsigned KnownProtocol : 6;
/// The number of requirements in the requirement signature.
unsigned NumRequirementsInSignature : 16;
bool requiresClassSlow();
bool existentialConformsToSelfSlow();
bool existentialTypeSupportedSlow(LazyResolver *resolver);
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.
llvm::TinyPtrVector<ProtocolDecl *> getInheritedProtocols() const;
/// Walk 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;
/// \brief 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 {
if (ProtocolDeclBits.RequiresClassValid)
return ProtocolDeclBits.RequiresClass;
return const_cast<ProtocolDecl *>(this)->requiresClassSlow();
}
/// Specify that this protocol is class-bounded, e.g., because it was
/// annotated with the 'class' keyword.
void setRequiresClass(bool requiresClass = true) {
ProtocolDeclBits.RequiresClassValid = true;
ProtocolDeclBits.RequiresClass = requiresClass;
}
/// 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 {
if (ProtocolDeclBits.ExistentialConformsToSelfValid)
return ProtocolDeclBits.ExistentialConformsToSelf;
return const_cast<ProtocolDecl *>(this)
->existentialConformsToSelfSlow();
}
/// 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(LazyResolver *resolver) const {
if (ProtocolDeclBits.ExistentialTypeSupportedValid)
return ProtocolDeclBits.ExistentialTypeSupported;
return const_cast<ProtocolDecl *>(this)
->existentialTypeSupportedSlow(resolver);
}
/// If this is known to be a compiler-known protocol, returns the kind.
/// Otherwise returns None.
///
/// Note that this is only valid after type-checking.
Optional<KnownProtocolKind> getKnownProtocolKind() const {
if (KnownProtocol == 0)
return None;
return static_cast<KnownProtocolKind>(KnownProtocol - 1);
}
/// 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;
}
/// Records that this is a compiler-known protocol.
void setKnownProtocolKind(KnownProtocolKind kind) {
assert((!getKnownProtocolKind() || *getKnownProtocolKind() == kind) &&
"can't reset known protocol kind");
KnownProtocol = static_cast<unsigned>(kind) + 1;
assert(getKnownProtocolKind() && *getKnownProtocolKind() == kind &&
"not enough bits");
}
/// Retrieve the status of circularity checking for protocol inheritance.
CircularityCheck getCircularityCheck() const {
return static_cast<CircularityCheck>(ProtocolDeclBits.Circularity);
}
/// Record the current stage of circularity checking.
void setCircularityCheck(CircularityCheck circularity) {
ProtocolDeclBits.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 HasMissingRequirements;
}
void setHasMissingRequirements(bool newValue) {
HasMissingRequirements = newValue;
}
/// 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);
/// Retrieve the name to use for this protocol when interoperating
/// with the Objective-C runtime.
StringRef getObjCRuntimeName(llvm::SmallVectorImpl<char> &buffer) const;
/// Create the implicit generic parameter list for a protocol or
/// extension thereof.
GenericParamList *createGenericParams(DeclContext *dc);
/// Create the generic parameters of this protocol if the haven't been
/// created yet.
void createGenericParamsIfMissing();
/// Retrieve the trailing where clause on this protocol, if it exists.
TrailingWhereClause *getTrailingWhereClause() const {
return TrailingWhere;
}
/// 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 {
assert(isRequirementSignatureComputed() &&
"getting requirement signature before computing it");
return llvm::makeArrayRef(RequirementSignature, NumRequirementsInSignature);
}
/// Has the requirement signature been computed yet?
bool isRequirementSignatureComputed() const {
return RequirementSignature != nullptr;
}
void computeRequirementSignature();
void setRequirementSignature(ArrayRef<Requirement> requirements);
// 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) {
auto GTD = dyn_cast<GenericTypeDecl>(C);
return GTD && classof(static_cast<const Decl*>(GTD));
}
static bool classof(const IterableDeclContext *C) {
auto NTD = dyn_cast<NominalTypeDecl>(C);
return NTD && classof(NTD);
}
};
// Note that the values of these enums line up with %select values in
// diagnostics.
enum class AccessorKind {
/// \brief This is not a property accessor.
NotAccessor = -1,
/// \brief This is a getter for a property or subscript.
IsGetter = 0,
/// \brief This is a setter for a property or subscript.
IsSetter = 1,
/// \brief This is a willSet specifier for a property.
IsWillSet = 2,
/// \brief This is a didSet specifier for a property.
IsDidSet = 3,
/// \brief This is a materializeForSet accessor for a property.
IsMaterializeForSet = 4,
/// \brief This is an address-family accessor for a property or
/// subscript. It also has an addressor kind.
IsAddressor = 5,
/// \brief This is a mutableAddress-family accessor for a property
/// or subscript. It also has an addressor kind.
IsMutableAddressor = 6,
};
/// The safety semantics of this addressor.
enum class AddressorKind : unsigned char {
/// \brief This is not an addressor.
NotAddressor,
/// \brief This is an unsafe addressor; it simply returns an address.
Unsafe,
/// \brief This is an owning addressor; it returns a Builtin.UnknownObject
/// which should be released when the caller is done with the object.
Owning,
/// \brief This is an owning addressor; it returns a Builtin.NativeObject
/// which should be released when the caller is done with the object.
NativeOwning,
/// \brief This is a pinning addressor; it returns a Builtin.NativeObject?
/// which should be unpinned when the caller is done with the object.
NativePinning,
};
/// Whether an access to storage is for reading, writing, or both.
enum class AccessKind : unsigned char {
/// The access is just to read the current value.
Read,
/// The access is just to overwrite the current value.
Write,
/// The access may require either reading or writing the current value.
ReadWrite
};
/// The way to actually evaluate an access to storage.
enum class AccessStrategy : unsigned char {
/// The decl is a VarDecl with its own backing storage; evaluate its
/// address directly.
Storage,
/// The decl is a VarDecl with storage defined by a property behavior;
/// this access may initialize or reassign the storage based on dataflow.
BehaviorStorage,
/// The decl has addressors; call the appropriate addressor for the
/// access kind. These calls are currently always direct.
Addressor,
/// Directly call the getter, setter, or materializeForSet accessor.
DirectToAccessor,
/// Indirectly call the getter, setter, or materializeForSet accessor.
DispatchToAccessor,
};
/// Information about a behavior instantiated by a storage declaration.
///
/// TODO: Accessors, composed behaviors
struct alignas(1 << 3) BehaviorRecord {
// The behavior name.
TypeRepr *ProtocolName;
// The parameter expression, if any.
Expr *Param;
Optional<NormalProtocolConformance *> Conformance = None;
// The 'value' property from the behavior protocol that provides the property
// implementation.
VarDecl *ValueDecl = nullptr;
// Storage declaration and initializer for use by definite initialization.
VarDecl *StorageDecl = nullptr;
ConcreteDeclRef InitStorageDecl = nullptr;
bool needsInitialization() const {
assert((bool)StorageDecl == (bool)InitStorageDecl
&& "DI state not consistent");
return StorageDecl != nullptr;
}
BehaviorRecord(TypeRepr *ProtocolName,
Expr *Param)
: ProtocolName(ProtocolName), Param(Param)
{}
SourceLoc getLoc() const;
};
/// AbstractStorageDecl - This is the common superclass for VarDecl and
/// SubscriptDecl, representing potentially settable memory locations.
class AbstractStorageDecl : public ValueDecl {
public:
enum StorageKindTy {
/// There are bits stored in memory for this object, and they are accessed
/// directly. This is not valid for a SubscriptDecl.
Stored,
/// This is a stored property with trivial accessors which simply get and
/// set the underlying storage. This is not valid for a SubscriptDecl.
///
/// These accessors are used for several different purposes:
/// 1) In an @objc variable, these accessors are dynamically dispatched
/// to and may be overridden.
/// 2) When a stored property satisfies a protocol requirement, these
/// accessors end up as entries in the witness table.
/// 3) When a stored property is accessed outside of the storage
/// declaration's resilience domain, when the owning type or
/// global variable is resilient.
StoredWithTrivialAccessors,
/// This is a stored property with either a didSet specifier or a
/// willSet specifier (or both). Sema synthesizes a setter which
/// calls them at the appropriate points.
StoredWithObservers,
/// There are bits stored in memory for this object, but they are
/// not allocated directly within the container; instead, there
/// are accessors which return the address of the memory. The
/// value is accessed directly through the returned address.
///
/// This is legal on both VarDecls and SubscriptDecls.
///
/// There is always at least an 'address' accessor; if the object
/// is mutable, there will also be a 'mutableAddress' accessor.
Addressed,
/// Like Addressed, this object has address accessors. Like
/// StoredWithTrivialAccessors, accessors have been synthesized
/// which simply read and write through the addresses returned by
/// the addressors.
AddressedWithTrivialAccessors,
/// Like Addressed, this object has address accessors. Like
/// StoredWithObservers, it also has either a willSet specifier or
/// a didSet specifier. Accessors have been synthesized, like
/// with StoredWithObservers but using the address returned from
/// the appropriate accessor instead.
AddressedWithObservers,
/// This is an override of an object which adds either a didSet
/// specifier or a willSet specifier (or both). Sema synthesizes
/// a setter which calls them at the appropriate points around
/// delegating to the superclass's setter.
InheritedWithObservers,
/// There is no memory associated with this decl anywhere. It is
/// accessed by calling a getter and setter. If the setter is
/// absent, then the value is only loadable, but not storable.
Computed,
/// This object was specified with non-trivial getter and
/// mutableAddress accessors. If it is accessed in a read-only
/// manner, the getter is called; otherwise, mutableAddress is
/// called.
///
/// This turns out to the be the right thing for certain core data
/// structures which, when they store a bridged object, cannot
/// return the address at which the object is stored.
ComputedWithMutableAddress,
};
private:
AbstractStorageDecl *OverriddenDecl;
struct GetSetRecord;
/// This is stored immediately before the GetSetRecord.
struct alignas(1 << 3) AddressorRecord {
FuncDecl *Address = nullptr; // User-defined address accessor
FuncDecl *MutableAddress = nullptr; // User-defined mutableAddress accessor
GetSetRecord *getGetSet() {
// Relies on not-strictly-portable ABI layout assumptions.
return reinterpret_cast<GetSetRecord*>(this+1);
}
};
void configureAddressorRecord(AddressorRecord *record,
FuncDecl *addressor, FuncDecl *mutableAddressor);
struct alignas(1 << 3) GetSetRecord {
SourceRange Braces;
FuncDecl *Get = nullptr; // User-defined getter
FuncDecl *Set = nullptr; // User-defined setter
FuncDecl *MaterializeForSet = nullptr; // optional materializeForSet accessor
AddressorRecord *getAddressors() {
// Relies on not-strictly-portable ABI layout assumptions.
return reinterpret_cast<AddressorRecord*>(this) - 1;
}
};
void configureGetSetRecord(GetSetRecord *getSetRecord,
FuncDecl *getter, FuncDecl *setter,
FuncDecl *materializeForSet);
void configureSetRecord(GetSetRecord *getSetInfo,
FuncDecl *setter,
FuncDecl *materializeForSet);
struct ObservingRecord : GetSetRecord {
FuncDecl *WillSet = nullptr; // willSet(value):
FuncDecl *DidSet = nullptr; // didSet:
};
void configureObservingRecord(ObservingRecord *record,
FuncDecl *willSet, FuncDecl *didSet);
llvm::PointerIntPair<GetSetRecord*, 3, OptionalEnum<AccessLevel>> GetSetInfo;
llvm::PointerIntPair<BehaviorRecord*, 3, OptionalEnum<AccessLevel>>
BehaviorInfo;
ObservingRecord &getDidSetInfo() const {
assert(hasObservers());
return *static_cast<ObservingRecord*>(GetSetInfo.getPointer());
}
AddressorRecord &getAddressorInfo() const {
assert(hasAddressors());
return *GetSetInfo.getPointer()->getAddressors();
}
void setStorageKind(StorageKindTy K) {
AbstractStorageDeclBits.StorageKind = unsigned(K);
}
protected:
AbstractStorageDecl(DeclKind Kind, DeclContext *DC, DeclName Name,
SourceLoc NameLoc)
: ValueDecl(Kind, DC, Name, NameLoc), OverriddenDecl(nullptr) {
AbstractStorageDeclBits.StorageKind = Stored;
AbstractStorageDeclBits.IsGetterMutating = false;
AbstractStorageDeclBits.IsSetterMutating = true;
AbstractStorageDeclBits.Overridden = false;
}
public:
/// \brief Should this declaration be treated as if annotated with transparent
/// attribute.
bool isTransparent() const;
/// \brief Determine whether this storage is a static member, if it
/// is a member. Currently only variables can be static.
inline bool isStatic() const; // defined in this header
/// \brief Determine whether this variable is computed, which means it
/// has no storage but does have a user-defined getter or setter.
///
StorageKindTy getStorageKind() const {
return (StorageKindTy) AbstractStorageDeclBits.StorageKind;
}
/// \brief Return true if this is a VarDecl that has storage associated with
/// it.
bool hasStorage() const {
switch (getStorageKind()) {
case Stored:
case StoredWithTrivialAccessors:
case StoredWithObservers:
return true;
case InheritedWithObservers:
case Computed:
case ComputedWithMutableAddress:
case Addressed:
case AddressedWithTrivialAccessors:
case AddressedWithObservers:
return false;
}
llvm_unreachable("bad storage kind");
}
/// \brief Return true if this object has a getter (and, if mutable,
/// a setter and a materializeForSet).
bool hasAccessorFunctions() const {
switch (getStorageKind()) {
case Addressed:
case Stored:
return false;
case StoredWithTrivialAccessors:
case StoredWithObservers:
case InheritedWithObservers:
case Computed:
case ComputedWithMutableAddress:
case AddressedWithTrivialAccessors:
case AddressedWithObservers:
return true;
}
llvm_unreachable("bad storage kind");
}
/// \brief Return true if this object has observing accessors.
///
/// It's generally not appropriate to use this predicate directly in
/// a condition; instead, you should be switching on the storage kind.
bool hasObservers() const {
switch (getStorageKind()) {
case Stored:
case StoredWithTrivialAccessors:
case Computed:
case ComputedWithMutableAddress:
case Addressed:
case AddressedWithTrivialAccessors:
return false;
case StoredWithObservers:
case InheritedWithObservers:
case AddressedWithObservers:
return true;
}
llvm_unreachable("bad storage kind");
}
/// \brief Return true if this object has either an addressor or a
/// mutable addressor.
///
/// It's generally not appropriate to use this predicate directly in
/// a condition; instead, you should be switching on the storage
/// kind. Only use this for diagnostic, AST exploration, or
/// assertion purposes.
bool hasAddressors() const {
switch (getStorageKind()) {
case Stored:
case StoredWithTrivialAccessors:
case StoredWithObservers:
case InheritedWithObservers:
case Computed:
return false;
case ComputedWithMutableAddress:
case Addressed:
case AddressedWithTrivialAccessors:
case AddressedWithObservers:
return true;
}
llvm_unreachable("bad storage kind");
}
/// \brief Return true if reading this storage requires the ability to
/// modify the base value.
bool isGetterMutating() const {
return AbstractStorageDeclBits.IsGetterMutating;
}
void setIsGetterMutating(bool isMutating) {
AbstractStorageDeclBits.IsGetterMutating = isMutating;
}
/// \brief Return true if modifying this storage requires the ability to
/// modify the base value.
bool isSetterMutating() const {
return AbstractStorageDeclBits.IsSetterMutating;
}
void setIsSetterMutating(bool isMutating) {
AbstractStorageDeclBits.IsSetterMutating = isMutating;
}
FuncDecl *getAccessorFunction(AccessorKind accessor) const;
/// \brief Push all of the accessor functions associated with this VarDecl
/// onto `decls`.
void getAllAccessorFunctions(SmallVectorImpl<Decl *> &decls) const;
/// \brief Turn this into a computed variable, providing a getter and setter.
void makeComputed(SourceLoc LBraceLoc, FuncDecl *Get, FuncDecl *Set,
FuncDecl *MaterializeForSet, SourceLoc RBraceLoc);
/// \brief Turn this into a computed object, providing a getter and a mutable
/// addressor.
void makeComputedWithMutableAddress(SourceLoc lbraceLoc,
FuncDecl *getter, FuncDecl *setter,
FuncDecl *materializeForSet,
FuncDecl *mutableAddressor,
SourceLoc rbraceLoc);
/// \brief Add trivial accessors to this Stored or Addressed object.
void addTrivialAccessors(FuncDecl *Get, FuncDecl *Set,
FuncDecl *MaterializeForSet);
/// \brief Turn this into a stored-with-observers var, providing the
/// didSet/willSet specifiers.
void makeStoredWithObservers(SourceLoc LBraceLoc, FuncDecl *WillSet,
FuncDecl *DidSet, SourceLoc RBraceLoc);
/// \brief Turn this into an inherited-with-observers var, providing
/// the didSet/willSet specifiers.
void makeInheritedWithObservers(SourceLoc LBraceLoc, FuncDecl *WillSet,
FuncDecl *DidSet, SourceLoc RBraceLoc);
/// \brief Turn this into an addressed var.
void makeAddressed(SourceLoc LBraceLoc, FuncDecl *Addressor,
FuncDecl *MutableAddressor,
SourceLoc RBraceLoc);
/// \brief Turn this into an addressed var with observing accessors.
void makeAddressedWithObservers(SourceLoc LBraceLoc, FuncDecl *Addressor,
FuncDecl *MutableAddressor,
FuncDecl *WillSet, FuncDecl *DidSet,
SourceLoc RBraceLoc);
/// \brief Specify the synthesized get/set functions for a
/// StoredWithObservers or AddressedWithObservers var. This is used by Sema.
void setObservingAccessors(FuncDecl *Get, FuncDecl *Set,
FuncDecl *MaterializeForSet);
/// \brief Add a setter to an existing Computed var.
///
/// This should only be used by the ClangImporter.
void setComputedSetter(FuncDecl *Set);
/// \brief Add a behavior to a property.
void addBehavior(TypeRepr *Type, Expr *Param);
/// \brief Set a materializeForSet accessor for this declaration.
///
/// This should only be used by Sema.
void setMaterializeForSetFunc(FuncDecl *materializeForSet);
/// \brief Specify the braces range without adding accessors.
///
/// This is used to record the braces range if the accessors were rejected.
void setInvalidBracesRange(SourceRange BracesRange);
SourceRange getBracesRange() const {
if (auto info = GetSetInfo.getPointer())
return info->Braces;
return SourceRange();
}
/// \brief Retrieve the getter used to access the value of this variable.
FuncDecl *getGetter() const {
if (auto info = GetSetInfo.getPointer())
return info->Get;
return nullptr;
}
/// \brief Retrieve the setter used to mutate the value of this variable.
FuncDecl *getSetter() const {
if (auto info = GetSetInfo.getPointer())
return info->Set;
return nullptr;
}
AccessLevel getSetterFormalAccess() const {
assert(hasAccess());
assert(GetSetInfo.getInt().hasValue());
return GetSetInfo.getInt().getValue();
}
void setSetterAccess(AccessLevel accessLevel) {
assert(!GetSetInfo.getInt().hasValue());
overwriteSetterAccess(accessLevel);
}
void overwriteSetterAccess(AccessLevel accessLevel);
/// \brief Retrieve the materializeForSet function, if this
/// declaration has one.
FuncDecl *getMaterializeForSetFunc() const {
if (auto info = GetSetInfo.getPointer())
return info->MaterializeForSet;
return nullptr;
}
/// \brief Return the funcdecl for the 'address' accessor if it
/// exists; this is only valid on a declaration with addressors.
FuncDecl *getAddressor() const { return getAddressorInfo().Address; }
/// \brief Return the funcdecl for the 'mutableAddress' accessors if
/// it exists; this is only valid on a declaration with addressors.
FuncDecl *getMutableAddressor() const {
return getAddressorInfo().MutableAddress;
}
/// \brief Return the appropriate addressor for the given access kind.
FuncDecl *getAddressorForAccess(AccessKind accessKind) const {
if (accessKind == AccessKind::Read)
return getAddressor();
return getMutableAddressor();
}
/// \brief Return the funcdecl for the willSet specifier if it exists, this is
/// only valid on a declaration with Observing storage.
FuncDecl *getWillSetFunc() const { return getDidSetInfo().WillSet; }
/// \brief Return the funcdecl for the didSet specifier if it exists, this is
/// only valid on a declaration with Observing storage.
FuncDecl *getDidSetFunc() const { return getDidSetInfo().DidSet; }
/// Return true if this storage can (but doesn't have to) be accessed with
/// Objective-C-compatible getters and setters.
bool hasForeignGetterAndSetter() const;
/// Return true if this storage *must* be accessed with Objective-C-compatible
/// getters and setters.
bool requiresForeignGetterAndSetter() const;
/// Given that this is an Objective-C property or subscript declaration,
/// produce its getter selector.
ObjCSelector getObjCGetterSelector(LazyResolver *resolver = nullptr,
Identifier preferredName = Identifier()) const;
/// Given that this is an Objective-C property or subscript declaration,
/// produce its setter selector.
ObjCSelector getObjCSetterSelector(LazyResolver *resolver = nullptr,
Identifier preferredName = Identifier()) const;
AbstractStorageDecl *getOverriddenDecl() const {
return OverriddenDecl;
}
void setOverriddenDecl(AbstractStorageDecl *over) {
// FIXME: Hack due to broken class circularity checking.
if (over == this) return;
OverriddenDecl = over;
over->setIsOverridden();
}
/// The declaration has been overridden in the module
///
/// Resolved during type checking
void setIsOverridden() {
AbstractStorageDeclBits.Overridden = true;
}
/// 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 AbstractStorageDeclBits.Overridden; }
/// 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.
bool isSetterAccessibleFrom(const DeclContext *DC) const;
/// Determine how this storage declaration should actually be accessed.
AccessStrategy getAccessStrategy(AccessSemantics semantics,
AccessKind accessKind) const;
/// \brief Does this declaration expose a fixed layout to all resilience
/// domains?
///
/// Roughly speaking, this means we can make assumptions about whether
/// the storage is stored or computed, and if stored, the precise access
/// pattern to be used.
bool hasFixedLayout() const;
/// \brief Does this declaration expose a fixed layout to the given
/// module?
bool hasFixedLayout(ModuleDecl *M, ResilienceExpansion expansion) const;
/// Does the storage use a behavior?
bool hasBehavior() const {
return BehaviorInfo.getPointer() != nullptr;
}
/// Does the storage use a behavior, and require definite initialization
/// analysis.
bool hasBehaviorNeedingInitialization() const {
if (auto behavior = getBehavior()) {
return behavior->needsInitialization();
}
return false;
}
/// Get the behavior info.
const BehaviorRecord *getBehavior() const {
return BehaviorInfo.getPointer();
}
BehaviorRecord *getMutableBehavior() {
return BehaviorInfo.getPointer();
}
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() >= DeclKind::First_AbstractStorageDecl &&
D->getKind() <= DeclKind::Last_AbstractStorageDecl;
}
};
/// VarDecl - 'var' and 'let' declarations.
class VarDecl : public AbstractStorageDecl {
public:
enum class Specifier : uint8_t {
// For Var Decls
Let = 0,
Var = 1,
// For Param Decls
Owned = Let,
InOut = 2,
Shared = 3,
};
protected:
llvm::PointerUnion<PatternBindingDecl*, Stmt*> ParentPattern;
VarDecl(DeclKind Kind, bool IsStatic, Specifier Sp, bool IsCaptureList,
SourceLoc NameLoc, Identifier Name, Type Ty, DeclContext *DC)
: AbstractStorageDecl(Kind, DC, Name, NameLoc)
{
VarDeclBits.IsStatic = IsStatic;
VarDeclBits.Specifier = static_cast<unsigned>(Sp);
VarDeclBits.IsCaptureList = IsCaptureList;
VarDeclBits.IsDebuggerVar = false;
VarDeclBits.HasNonPatternBindingInit = false;
setType(Ty);
}
/// This is the type specified, including location information.
TypeLoc typeLoc;
Type typeInContext;
public:
VarDecl(bool IsStatic, Specifier Sp, bool IsCaptureList, SourceLoc NameLoc,
Identifier Name, Type Ty, DeclContext *DC)
: VarDecl(DeclKind::Var, IsStatic, Sp, IsCaptureList, NameLoc, Name, Ty,
DC) {}
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;
/// \brief 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 {
return ParentPattern.dyn_cast<PatternBindingDecl *>();
}
void setParentPatternBinding(PatternBindingDecl *PBD) {
ParentPattern = 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.
Stmt *getParentPatternStmt() const {
return ParentPattern.dyn_cast<Stmt*>();
}
void setParentPatternStmt(Stmt *S) {
ParentPattern = S;
}
/// 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;
}
VarDecl *getOverriddenDecl() const {
return cast_or_null<VarDecl>(AbstractStorageDecl::getOverriddenDecl());
}
/// Determine whether this declaration is an anonymous closure parameter.
bool isAnonClosureParam() const;
/// Return the raw specifier value for this property or parameter.
Specifier getSpecifier() const {
return static_cast<Specifier>(VarDeclBits.Specifier);
}
void setSpecifier(Specifier Spec) {
VarDeclBits.Specifier = static_cast<unsigned>(Spec);
}
/// Is the type of this parameter 'inout'?
///
/// FIXME(Remove InOut): This is only valid on ParamDecls but multiple parts
/// of the compiler check ParamDecls and VarDecls along the same paths.
bool isInOut() const {
// FIXME: Re-enable this assertion and fix callers.
// assert((getKind() == DeclKind::Param) && "querying 'inout' on var decl?");
return getSpecifier() == Specifier::InOut;
}
/// Is this a type ('static') variable?
bool isStatic() const { return VarDeclBits.IsStatic; }
void setStatic(bool IsStatic) { VarDeclBits.IsStatic = IsStatic; }
/// \returns the way 'static'/'class' should be spelled for this declaration.
StaticSpellingKind getCorrectStaticSpelling() const;
/// Is this an immutable 'let' property?
bool isLet() const { return getSpecifier() == Specifier::Let; }
/// Is this an immutable 'shared' property?
bool isShared() const { return getSpecifier() == Specifier::Shared; }
/// Is this an element in a capture list?
bool isCaptureList() const { return VarDeclBits.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 VarDeclBits.HasNonPatternBindingInit;
}
void setHasNonPatternBindingInit(bool V = true) {
VarDeclBits.HasNonPatternBindingInit = V;
}
/// Is this a special debugger variable?
bool isDebuggerVar() const { return VarDeclBits.IsDebuggerVar; }
void setDebuggerVar(bool IsDebuggerVar) {
VarDeclBits.IsDebuggerVar = IsDebuggerVar;
}
/// 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;
// 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 ArgumentNameLoc;
SourceLoc SpecifierLoc;
struct StoredDefaultArgument {
Expr *DefaultArg = nullptr;
Initializer *InitContext = nullptr;
};
/// The default value, if any, along with whether this is varargs.
llvm::PointerIntPair<StoredDefaultArgument *, 1> DefaultValueAndIsVariadic;
/// 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.
bool IsTypeLocImplicit = false;
/// Information about a symbolic default argument, like #file.
DefaultArgumentKind defaultArgumentKind = DefaultArgumentKind::None;
public:
ParamDecl(VarDecl::Specifier specifier,
SourceLoc specifierLoc, SourceLoc argumentNameLoc,
Identifier argumentName, SourceLoc parameterNameLoc,
Identifier parameterName, Type ty, 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);
/// Retrieve the argument (API) name for this function parameter.
Identifier getArgumentName() const { return ArgumentName; }
/// 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; }
/// Retrieve the parameter type flags corresponding to the declaration of
/// this parameter's argument type.
ParameterTypeFlags getParameterFlags() const;
SourceLoc getSpecifierLoc() const { return SpecifierLoc; }
bool isTypeLocImplicit() const { return IsTypeLocImplicit; }
void setIsTypeLocImplicit(bool val) { IsTypeLocImplicit = val; }
bool isDefaultArgument() const {
return defaultArgumentKind != DefaultArgumentKind::None;
}
DefaultArgumentKind getDefaultArgumentKind() const {
return defaultArgumentKind;
}
void setDefaultArgumentKind(DefaultArgumentKind K) {
defaultArgumentKind = K;
}
Expr *getDefaultValue() const {
if (auto stored = DefaultValueAndIsVariadic.getPointer())
return stored->DefaultArg;
return nullptr;
}
void setDefaultValue(Expr *E);
Initializer *getDefaultArgumentInitContext() const {
if (auto stored = DefaultValueAndIsVariadic.getPointer())
return stored->InitContext;
return nullptr;
}
void setDefaultArgumentInitContext(Initializer *initContext);
/// Whether or not this parameter is varargs.
bool isVariadic() const { return DefaultValueAndIsVariadic.getInt(); }
void setVariadic(bool value = true) {DefaultValueAndIsVariadic.setInt(value);}
/// 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());
}
SourceRange getSourceRange() const;
/// Create an implicit 'self' decl for a method in the specified decl context.
/// If 'static' is true, then this is self for a static method in the type.
///
/// Note that this decl is created, but it is returned with an incorrect
/// DeclContext that needs to be set correctly. This is automatically handled
/// when a function is created with this as part of its argument list.
/// For a generic context, this also gives the parameter an unbound generic
/// type with the expectation that type-checking will fill in the context
/// generic parameters.
static ParamDecl *createUnboundSelf(SourceLoc loc, DeclContext *DC);
/// Create an implicit 'self' decl for a method in the specified decl context.
/// If 'static' is true, then this is self for a static method in the type.
///
/// Note that this decl is created, but it is returned with an incorrect
/// DeclContext that needs to be set correctly. This is automatically handled
/// when a function is created with this as part of its argument list.
static ParamDecl *createSelf(SourceLoc loc, DeclContext *DC,
bool isStatic = false,
bool isInOut = false);
// 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 {
/// Not an Objective-C subscripting kind.
None,
/// 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
};
/// \brief 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 AbstractStorageDecl, public GenericContext {
SourceLoc ArrowLoc;
ParameterList *Indices;
TypeLoc ElementTy;
public:
SubscriptDecl(DeclName Name, SourceLoc SubscriptLoc, ParameterList *Indices,
SourceLoc ArrowLoc, TypeLoc ElementTy, DeclContext *Parent,
GenericParamList *GenericParams)
: AbstractStorageDecl(DeclKind::Subscript, Parent, Name, SubscriptLoc),
GenericContext(DeclContextKind::SubscriptDecl, Parent),
ArrowLoc(ArrowLoc), Indices(nullptr), ElementTy(ElementTy) {
setIndices(Indices);
setGenericParams(GenericParams);
}
SourceLoc getSubscriptLoc() const { return getNameLoc(); }
SourceLoc getStartLoc() const { return getSubscriptLoc(); }
SourceRange getSourceRange() const;
SourceRange getSignatureSourceRange() const;
/// \brief Retrieve the indices for this subscript operation.
ParameterList *getIndices() { return Indices; }
const ParameterList *getIndices() const { return Indices; }
void setIndices(ParameterList *p);
/// Retrieve the interface type of the indices.
Type getIndicesInterfaceType() const;
/// \brief Retrieve the type of the element referenced by a subscript
/// operation.
Type getElementInterfaceType() const;
TypeLoc &getElementTypeLoc() { return ElementTy; }
const TypeLoc &getElementTypeLoc() const { return ElementTy; }
/// \brief Returns whether the result of the subscript operation can be set.
bool isSettable() const;
/// Determine the kind of Objective-C subscripting this declaration
/// implies.
ObjCSubscriptKind getObjCSubscriptKind(LazyResolver *resolver) 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) {
return DC->getContextKind() == DeclContextKind::SubscriptDecl;
}
using DeclContext::operator new;
using Decl::getASTContext;
};
/// Encodes imported-as-member status for C functions that get imported
/// as methods.
struct ImportAsMemberStatus {
// non-0 denotes import-as-member. 1 denotes no self index. n+2 denotes self
// index of n
uint8_t rawValue = 0;
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;
}
};
/// \brief Base class for function-like declarations.
class AbstractFunctionDecl : public ValueDecl, public GenericContext {
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
// This enum currently needs to fit in a 3-bit bitfield.
};
BodyKind getBodyKind() const {
return BodyKind(AbstractFunctionDeclBits.BodyKind);
}
using BodySynthesizer = void (*)(AbstractFunctionDecl *);
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() == 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;
};
CaptureInfo Captures;
/// Location of the 'throws' token.
SourceLoc ThrowsLoc;
ImportAsMemberStatus IAMStatus;
AbstractFunctionDecl(DeclKind Kind, DeclContext *Parent, DeclName Name,
SourceLoc NameLoc, bool Throws, SourceLoc ThrowsLoc,
unsigned NumParameterLists,
GenericParamList *GenericParams)
: ValueDecl(Kind, Parent, Name, NameLoc),
GenericContext(DeclContextKind::AbstractFunctionDecl, Parent),
Body(nullptr), ThrowsLoc(ThrowsLoc) {
setBodyKind(BodyKind::None);
setGenericParams(GenericParams);
AbstractFunctionDeclBits.NumParameterLists = NumParameterLists;
AbstractFunctionDeclBits.Overridden = false;
AbstractFunctionDeclBits.Throws = Throws;
AbstractFunctionDeclBits.NeedsNewVTableEntry = false;
AbstractFunctionDeclBits.HasComputedNeedsNewVTableEntry = false;
AbstractFunctionDeclBits.DefaultArgumentResilienceExpansion =
unsigned(ResilienceExpansion::Maximal);
// Verify no bitfield truncation.
assert(AbstractFunctionDeclBits.NumParameterLists == NumParameterLists);
}
void setBodyKind(BodyKind K) {
AbstractFunctionDeclBits.BodyKind = unsigned(K);
}
public:
/// 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() : "_";
}
/// \brief Should this declaration be treated as if annotated with transparent
/// attribute.
bool isTransparent() const;
// Expose our import as member status
bool isImportAsMember() const { return IAMStatus.isImportAsMember(); }
bool isImportAsInstanceMember() const { return IAMStatus.isInstance(); }
bool isImportAsStaticMember() const { return IAMStatus.isStatic(); }
uint8_t getSelfIndex() const { return IAMStatus.getSelfIndex(); }
ImportAsMemberStatus getImportAsMemberStatus() const { return IAMStatus; }
void setImportAsStaticMember() { IAMStatus.setStatic(); }
void setSelfIndex(uint8_t idx) { return IAMStatus.setSelfIndex(idx); }
public:
/// 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 AbstractFunctionDeclBits.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;
}
/// 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 {
if (canSynthesize && getBodyKind() == BodyKind::Synthesize) {
const_cast<AbstractFunctionDecl *>(this)->setBodyKind(BodyKind::None);
(*Synthesizer)(const_cast<AbstractFunctionDecl *>(this));
}
if (getBodyKind() == BodyKind::Parsed ||
getBodyKind() == BodyKind::TypeChecked) {
return Body;
}
return nullptr;
}
void setBody(BraceStmt *S, BodyKind NewBodyKind = BodyKind::Parsed) {
assert(getBodyKind() != BodyKind::Skipped &&
"cannot set a body if it was skipped");
Body = S;
setBodyKind(NewBodyKind);
}
/// \brief Note that the body was skipped for this function. Function body
/// cannot be attached after this call.
void setBodySkipped(SourceRange bodyRange) {
assert(getBodyKind() == BodyKind::None);
BodyRange = bodyRange;
setBodyKind(BodyKind::Skipped);
}
/// \brief Note that parsing for the body was delayed.
void setBodyDelayed(SourceRange bodyRange) {
assert(getBodyKind() == BodyKind::None);
BodyRange = bodyRange;
setBodyKind(BodyKind::Unparsed);
}
/// Note that parsing for the body was delayed.
void setBodySynthesizer(BodySynthesizer synthesizer) {
assert(getBodyKind() == BodyKind::None);
Synthesizer = synthesizer;
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);
}
/// If a body has been loaded, flag that it's been type-checked.
/// This is kindof a hacky operation, but it avoids some unnecessary
/// duplication of work.
void setBodyTypeCheckedIfPresent() {
if (getBodyKind() == BodyKind::Parsed)
setBodyKind(BodyKind::TypeChecked);
}
bool isBodyTypeChecked() const {
return getBodyKind() == BodyKind::TypeChecked;
}
bool isMemberwiseInitializer() const {
return getBodyKind() == BodyKind::MemberwiseInitializer;
}
void setNeedsNewVTableEntry(bool value) {
AbstractFunctionDeclBits.HasComputedNeedsNewVTableEntry = true;
AbstractFunctionDeclBits.NeedsNewVTableEntry = value;
}
bool needsNewVTableEntry() const {
if (!AbstractFunctionDeclBits.HasComputedNeedsNewVTableEntry)
const_cast<AbstractFunctionDecl *>(this)->computeNeedsNewVTableEntry();
return AbstractFunctionDeclBits.NeedsNewVTableEntry;
}
private:
void computeNeedsNewVTableEntry();
public:
/// Retrieve the source range of the function body.
SourceRange getBodySourceRange() const;
/// Retrieve the source range of the function declaration name + patterns.
SourceRange getSignatureSourceRange() const;
CaptureInfo &getCaptureInfo() { return Captures; }
const CaptureInfo &getCaptureInfo() const { return Captures; }
/// Retrieve the Objective-C selector that names this method.
ObjCSelector getObjCSelector(LazyResolver *resolver = nullptr,
DeclName preferredName = DeclName()) const;
/// Determine whether the given method would produce an Objective-C
/// instance method.
bool isObjCInstanceMethod() const;
/// Determine the default argument kind and type for the given argument index
/// in this declaration, which must be a function or constructor.
///
/// \param Index The index of the argument for which we are querying the
/// default argument.
///
/// \returns the default argument kind and, if there is a default argument,
/// the type of the corresponding parameter.
std::pair<DefaultArgumentKind, Type> getDefaultArg(unsigned Index) const;
/// Determine whether the name of an argument is an API name by default
/// depending on the function context.
bool argumentNameIsAPIByDefault() const;
/// \brief Returns the "natural" number of argument clauses taken by this
/// function. This value is one for free-standing functions, and two for
/// methods.
unsigned getNumParameterLists() const {
return AbstractFunctionDeclBits.NumParameterLists;
}
/// \brief Returns the parameter pattern(s) for the function definition that
/// determine the parameter names bound in the function body.
///
/// The number of "top-level" elements in this pattern will match the number
/// of argument names in the compound name of the function or constructor.
MutableArrayRef<ParameterList *> getParameterLists();
ArrayRef<const ParameterList *> getParameterLists() const {
auto paramLists =
const_cast<AbstractFunctionDecl *>(this)->getParameterLists();
return ArrayRef<const ParameterList *>(paramLists.data(),paramLists.size());
}
ParameterList *getParameterList(unsigned i) {
return getParameterLists()[i];
}
const ParameterList *getParameterList(unsigned i) const {
return getParameterLists()[i];
}
/// \brief This method returns the implicit 'self' decl.
///
/// Note that some functions don't have an implicit 'self' decl, for example,
/// free functions. In this case nullptr is returned.
const ParamDecl *getImplicitSelfDecl() const {
return const_cast<AbstractFunctionDecl*>(this)->getImplicitSelfDecl();
}
ParamDecl *getImplicitSelfDecl();
/// Retrieve the declaration that this method overrides, if any.
AbstractFunctionDecl *getOverriddenDecl() const;
/// Returns true if a function declaration overrides a given
/// method from its direct or indirect superclass.
bool isOverridingDecl(const AbstractFunctionDecl *method) const;
/// 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 AbstractFunctionDeclBits.Overridden; }
/// The declaration has been overridden in the module
///
/// Resolved during type checking
void setIsOverridden() { AbstractFunctionDeclBits.Overridden = true; }
/// The ResilienceExpansion for default arguments.
///
/// In Swift 4 mode, default argument expressions are serialized, and must
/// obey the restrictions imposed upon inlineable function bodies.
ResilienceExpansion getDefaultArgumentResilienceExpansion() const {
return ResilienceExpansion(
AbstractFunctionDeclBits.DefaultArgumentResilienceExpansion);
}
/// Set the ResilienceExpansion for default arguments.
void setDefaultArgumentResilienceExpansion(ResilienceExpansion expansion) {
AbstractFunctionDeclBits.DefaultArgumentResilienceExpansion =
unsigned(expansion);
}
/// 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) {
return DC->getContextKind() == DeclContextKind::AbstractFunctionDecl;
}
/// True if the declaration is forced to be statically dispatched.
bool hasForcedStaticDispatch() const;
/// Get the interface type of this decl and remove the Self context.
Type getMethodInterfaceType() const;
using DeclContext::operator new;
using Decl::getASTContext;
};
class OperatorDecl;
/// Note: These align with '%select's in diagnostics.
enum class SelfAccessKind : uint8_t {
NonMutating = 0,
Mutating = 1,
__Consuming = 2,
};
/// FuncDecl - 'func' declaration.
class FuncDecl final : public AbstractFunctionDecl,
private llvm::TrailingObjects<FuncDecl, ParameterList *> {
friend class AbstractFunctionDecl;
friend TrailingObjects;
SourceLoc StaticLoc; // Location of the 'static' token or invalid.
SourceLoc FuncLoc; // Location of the 'func' token.
SourceLoc AccessorKeywordLoc; // Location of the accessor keyword, e.g. 'set'.
TypeLoc FnRetType;
/// Whether we are statically dispatched even if overridable
unsigned ForcedStaticDispatch : 1;
/// Whether this function has a dynamic Self return type.
unsigned HasDynamicSelf : 1;
/// Backing bits for 'self' access kind.
unsigned SelfAccess : 2;
/// \brief If this FuncDecl is an accessor for a property, this indicates
/// which property and what kind of accessor.
llvm::PointerIntPair<AbstractStorageDecl*, 3, AccessorKind> AccessorDecl;
llvm::PointerUnion<FuncDecl *, BehaviorRecord *>
OverriddenOrBehaviorParamDecl;
llvm::PointerIntPair<OperatorDecl *, 3,
AddressorKind> OperatorAndAddressorKind;
FuncDecl(SourceLoc StaticLoc, StaticSpellingKind StaticSpelling,
SourceLoc FuncLoc,
DeclName Name, SourceLoc NameLoc,
bool Throws, SourceLoc ThrowsLoc,
SourceLoc AccessorKeywordLoc,
unsigned NumParameterLists,
GenericParamList *GenericParams, DeclContext *Parent)
: AbstractFunctionDecl(DeclKind::Func, Parent,
Name, NameLoc,
Throws, ThrowsLoc,
NumParameterLists, GenericParams),
StaticLoc(StaticLoc), FuncLoc(FuncLoc),
AccessorKeywordLoc(AccessorKeywordLoc),
OverriddenOrBehaviorParamDecl(),
OperatorAndAddressorKind(nullptr, AddressorKind::NotAddressor) {
FuncDeclBits.IsStatic =
StaticLoc.isValid() || StaticSpelling != StaticSpellingKind::None;
FuncDeclBits.StaticSpelling = static_cast<unsigned>(StaticSpelling);
assert(NumParameterLists > 0 && "Must have at least an empty tuple arg");
HasDynamicSelf = false;
ForcedStaticDispatch = false;
SelfAccess = static_cast<unsigned>(SelfAccessKind::NonMutating);
}
static FuncDecl *createImpl(ASTContext &Context, SourceLoc StaticLoc,
StaticSpellingKind StaticSpelling,
SourceLoc FuncLoc,
DeclName Name, SourceLoc NameLoc,
bool Throws, SourceLoc ThrowsLoc,
SourceLoc AccessorKeywordLoc,
GenericParamList *GenericParams,
unsigned NumParameterLists,
DeclContext *Parent,
ClangNode ClangN);
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,
SourceLoc AccessorKeywordLoc,
GenericParamList *GenericParams,
unsigned NumParameterLists,
DeclContext *Parent);
static FuncDecl *create(ASTContext &Context, SourceLoc StaticLoc,
StaticSpellingKind StaticSpelling,
SourceLoc FuncLoc,
DeclName Name, SourceLoc NameLoc,
bool Throws, SourceLoc ThrowsLoc,
SourceLoc AccessorKeywordLoc,
GenericParamList *GenericParams,
ArrayRef<ParameterList *> ParameterLists,
TypeLoc FnRetType, DeclContext *Parent,
ClangNode ClangN = ClangNode());
Identifier getName() const { return getFullName().getBaseIdentifier(); }
bool isStatic() const {
return FuncDeclBits.IsStatic;
}
/// \returns the way 'static'/'class' was spelled in the source.
StaticSpellingKind getStaticSpelling() const {
return static_cast<StaticSpellingKind>(FuncDeclBits.StaticSpelling);
}
/// \returns the way 'static'/'class' should be spelled for this declaration.
StaticSpellingKind getCorrectStaticSpelling() const;
void setStatic(bool IsStatic = true) {
FuncDeclBits.IsStatic = IsStatic;
}
bool isMutating() const {
return getSelfAccessKind() == SelfAccessKind::Mutating;
}
bool isNonMutating() const {
return getSelfAccessKind() == SelfAccessKind::NonMutating;
}
bool isConsuming() const {
return getSelfAccessKind() == SelfAccessKind::__Consuming;
}
TypeLoc getReturnTypeLoc() const {
return FnRetType;
}
SelfAccessKind getSelfAccessKind() const {
return static_cast<SelfAccessKind>(SelfAccess);
}
void setSelfAccessKind(SelfAccessKind mod) {
SelfAccess = static_cast<unsigned>(mod);
}
/// \brief Returns the parameter lists(s) for the function definition.
///
/// The number of "top-level" elements will match the number of argument names
/// in the compound name of the function or constructor.
MutableArrayRef<ParameterList *> getParameterLists() {
return {getTrailingObjects<ParameterList *>(), getNumParameterLists()};
}
ArrayRef<const ParameterList *> getParameterLists() const {
return {getTrailingObjects<ParameterList *>(), getNumParameterLists()};
}
ParameterList *getParameterList(unsigned i) {
return getParameterLists()[i];
}
const ParameterList *getParameterList(unsigned i) const {
return getParameterLists()[i];
}
/// \returns true if this is non-mutating due to applying a 'mutating'
/// attribute. For example a "mutating set" accessor.
bool isExplicitNonMutating() const;
void setDeserializedSignature(ArrayRef<ParameterList *> ParameterLists,
TypeLoc FnRetType);
SourceLoc getStaticLoc() const { return StaticLoc; }
SourceLoc getFuncLoc() const { return FuncLoc; }
SourceLoc getAccessorKeywordLoc() const {return AccessorKeywordLoc; }
SourceLoc getStartLoc() const {
return StaticLoc.isValid() && !isAccessor() ? 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;
/// makeAccessor - Note that this function is an accessor for the given
/// VarDecl or SubscriptDecl.
void makeAccessor(AbstractStorageDecl *D, AccessorKind Kind) {
assert(Kind != AccessorKind::NotAccessor && "Must specify an accessor kind");
AccessorDecl.setPointerAndInt(D, Kind);
}
/// Set the addressor kind of this address or mutableAddress declaration.
void setAddressorKind(AddressorKind kind) {
assert(kind != AddressorKind::NotAddressor);
OperatorAndAddressorKind.setInt(kind);
}
AbstractStorageDecl *getAccessorStorageDecl() const {
return AccessorDecl.getPointer();
}
AccessorKind getAccessorKind() const {
if (AccessorDecl.getPointer() == nullptr)
return AccessorKind::NotAccessor;
return AccessorDecl.getInt();
}
AddressorKind getAddressorKind() const {
return OperatorAndAddressorKind.getInt();
}
bool isGetter() const { return getAccessorKind() == AccessorKind::IsGetter; }
bool isSetter() const { return getAccessorKind() == AccessorKind::IsSetter; }
/// isGetterOrSetter - Determine whether this is a getter or a setter vs.
/// a normal function.
bool isGetterOrSetter() const { return isGetter() || isSetter(); }
bool isObservingAccessor() const {
return getAccessorKind() == AccessorKind::IsDidSet ||
getAccessorKind() == AccessorKind::IsWillSet;
}
bool isAccessor() const {
return getAccessorKind() != AccessorKind::NotAccessor;
}
/// Determine whether this function has a dynamic \c Self return
/// type.
bool hasDynamicSelf() const { return HasDynamicSelf; }
/// Set whether this function has a dynamic \c Self return or not.
void setDynamicSelf(bool hasDynamicSelf) {
HasDynamicSelf = hasDynamicSelf;
}
void getLocalCaptures(SmallVectorImpl<CapturedValue> &Result) const {
return getCaptureInfo().getLocalCaptures(Result);
}
/// Get the supertype method this method overrides, if any.
FuncDecl *getOverriddenDecl() const {
return OverriddenOrBehaviorParamDecl.dyn_cast<FuncDecl *>();
}
void setOverriddenDecl(FuncDecl *over) {
// FIXME: Hack due to broken class circularity checking.
if (over == this) return;
// A function cannot be an override if it is also a derived global decl
// (since derived decls are at global scope).
assert((!OverriddenOrBehaviorParamDecl
|| OverriddenOrBehaviorParamDecl.get<FuncDecl*>() == over)
&& "function can only be one of override, derived, or behavior param");
OverriddenOrBehaviorParamDecl = over;
over->setIsOverridden();
}
/// Get the property behavior this function serves as a parameter for, if
/// any.
BehaviorRecord *getParamBehavior() const {
return OverriddenOrBehaviorParamDecl
.dyn_cast<BehaviorRecord *>();
}
void setParamBehavior(BehaviorRecord *behavior) {
// Behavior param blocks cannot be overrides or derived.
assert((!OverriddenOrBehaviorParamDecl
|| OverriddenOrBehaviorParamDecl.is<BehaviorRecord *>())
&& "function can only be one of override, derived, or behavior param");
OverriddenOrBehaviorParamDecl = behavior;
}
OperatorDecl *getOperatorDecl() const {
return OperatorAndAddressorKind.getPointer();
}
void setOperatorDecl(OperatorDecl *o) {
assert(isOperator() && "can't set an OperatorDecl for a non-operator");
OperatorAndAddressorKind.setPointer(o);
}
/// Returns true if the function is forced to be statically dispatched.
bool hasForcedStaticDispatch() const {
return ForcedStaticDispatch;
}
void setForcedStaticDispatch(bool flag) {
ForcedStaticDispatch = flag;
}
static bool classof(const Decl *D) { return D->getKind() == DeclKind::Func; }
static bool classof(const AbstractFunctionDecl *D) {
return classof(static_cast<const Decl*>(D));
}
static bool classof(const DeclContext *DC) {
if (auto fn = dyn_cast<AbstractFunctionDecl>(DC))
return classof(fn);
return false;
}
/// True if the function is a defer body.
bool isDeferBody() const;
/// Perform basic checking to determine whether the @IBAction attribute can
/// be applied to this function.
bool isPotentialIBActionTarget() const;
};
/// \brief 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;
SourceLoc CaseLoc;
/// The number of tail-allocated element pointers.
unsigned NumElements;
EnumCaseDecl(SourceLoc CaseLoc,
ArrayRef<EnumElementDecl *> Elements,
DeclContext *DC)
: Decl(DeclKind::EnumCase, DC),
CaseLoc(CaseLoc), NumElements(Elements.size())
{
std::uninitialized_copy(Elements.begin(), Elements.end(),
getTrailingObjects<EnumElementDecl *>());
}
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 *>(), NumElements};
}
SourceLoc getLoc() const {
return CaseLoc;
}
SourceRange getSourceRange() const;
static bool classof(const Decl *D) {
return D->getKind() == DeclKind::EnumCase;
}
};
/// \brief 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 ValueDecl {
/// 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.
TypeLoc ArgumentType;
SourceLoc EqualsLoc;
/// The raw value literal for the enum element, or null.
LiteralExpr *RawValueExpr;
/// The type-checked raw value expression.
Expr *TypeCheckedRawValueExpr = nullptr;
public:
EnumElementDecl(SourceLoc IdentifierLoc, Identifier Name,
TypeLoc ArgumentType,
bool HasArgumentType,
SourceLoc EqualsLoc,
LiteralExpr *RawValueExpr,
DeclContext *DC)
: ValueDecl(DeclKind::EnumElement, DC, Name, IdentifierLoc),
ArgumentType(ArgumentType),
EqualsLoc(EqualsLoc),
RawValueExpr(RawValueExpr)
{
EnumElementDeclBits.Recursiveness =
static_cast<unsigned>(ElementRecursiveness::NotRecursive);
EnumElementDeclBits.HasArgumentType = HasArgumentType;
}
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() : "_";
}
/// \returns false if there was an error during the computation rendering the
/// EnumElementDecl invalid, true otherwise.
bool computeType();
Type getArgumentInterfaceType() const;
TypeLoc &getArgumentTypeLoc() { return ArgumentType; }
const TypeLoc &getArgumentTypeLoc() const { return ArgumentType; }
bool hasRawValueExpr() const { return RawValueExpr; }
LiteralExpr *getRawValueExpr() const { return RawValueExpr; }
void setRawValueExpr(LiteralExpr *e) { RawValueExpr = e; }
Expr *getTypeCheckedRawValueExpr() const {
return TypeCheckedRawValueExpr;
}
void setTypeCheckedRawValueExpr(Expr *e) {
TypeCheckedRawValueExpr = 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;
ElementRecursiveness getRecursiveness() const {
return
static_cast<ElementRecursiveness>(EnumElementDeclBits.Recursiveness);
}
void setRecursiveness(ElementRecursiveness recursiveness) {
EnumElementDeclBits.Recursiveness = static_cast<unsigned>(recursiveness);
}
bool hasAssociatedValues() const {
return EnumElementDeclBits.HasArgumentType;
}
static bool classof(const Decl *D) {
return D->getKind() == DeclKind::EnumElement;
}
/// True if the case is marked 'indirect'.
bool isIndirect() const {
return getAttrs().hasAttribute<IndirectAttr>();
}
};
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 kind of initializer we have.
unsigned InitKind : 2;
/// The failability of this initializer, which is an OptionalTypeKind.
unsigned Failability : 2;
/// 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.
unsigned HasStubImplementation : 1;
/// The location of the '!' or '?' for a failable initializer.
SourceLoc FailabilityLoc;
ParameterList *ParameterLists[2];
/// 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;
/// The constructor this overrides, which only makes sense when
/// both the overriding and the overridden constructors are abstract.
ConstructorDecl *OverriddenDecl = nullptr;
public:
ConstructorDecl(DeclName Name, SourceLoc ConstructorLoc,
OptionalTypeKind Failability, SourceLoc FailabilityLoc,
bool Throws, SourceLoc ThrowsLoc,
ParamDecl *SelfParam, ParameterList *BodyParams,
GenericParamList *GenericParams,
DeclContext *Parent);
Identifier getName() const { return getFullName().getBaseIdentifier(); }
void setParameterLists(ParamDecl *selfParam, ParameterList *bodyParams);
SourceLoc getConstructorLoc() const { return getNameLoc(); }
SourceLoc getStartLoc() const { return getConstructorLoc(); }
SourceRange getSourceRange() const;
/// getArgumentInterfaceType - get the interface type of the argument tuple
Type getArgumentInterfaceType() const;
/// \brief Get the interface type of the constructed object.
Type getResultInterfaceType() const;
/// Get the interface type of the initializing constructor.
Type getInitializerInterfaceType();
void setInitializerInterfaceType(Type t);
/// 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; }
MutableArrayRef<ParameterList *> getParameterLists() {
return { ParameterLists, 2 };
}
ArrayRef<const ParameterList *> getParameterLists() const {
return AbstractFunctionDecl::getParameterLists();
}
ParameterList *getParameterList(unsigned i) {
return getParameterLists()[i];
}
const ParameterList *getParameterList(unsigned i) const {
return getParameterLists()[i];
}
/// Returns the normal parameters to the initializer, not including self.
ParameterList *getParameters() { return ParameterLists[1]; }
/// Returns the normal parameters to the initializer, not including self.
const ParameterList *getParameters() const { return ParameterLists[1]; }
/// 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 {
return static_cast<CtorInitializerKind>(InitKind);
}
/// Set whether this is a convenience initializer.
void setInitKind(CtorInitializerKind kind) {
InitKind = static_cast<unsigned>(kind);
}
/// 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 the failability of the initializer.
OptionalTypeKind getFailability() const {
return static_cast<OptionalTypeKind>(Failability);
}
/// 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 HasStubImplementation;
}
/// Set whether the implementation of this method is a stub that
/// traps at runtime.
void setStubImplementation(bool stub) {
HasStubImplementation = stub;
}
ConstructorDecl *getOverriddenDecl() const { return OverriddenDecl; }
void setOverriddenDecl(ConstructorDecl *over) {
// FIXME: Hack due to broken class circularity checking.
if (over == this) return;
OverriddenDecl = over;
over->setIsOverridden();
}
/// 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 fn = dyn_cast<AbstractFunctionDecl>(DC))
return classof(fn);
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 {
ParameterList *SelfParameter;
public:
DestructorDecl(SourceLoc DestructorLoc, ParamDecl *selfDecl,
DeclContext *Parent);
void setSelfDecl(ParamDecl *selfDecl);
MutableArrayRef<ParameterList *> getParameterLists() {
return { &SelfParameter, 1 };
}
ArrayRef<const ParameterList *> getParameterLists() const {
return { &SelfParameter, 1 };
}
SourceLoc getDestructorLoc() const { return getNameLoc(); }
SourceLoc getStartLoc() const { return getDestructorLoc(); }
SourceRange getSourceRange() 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 fn = dyn_cast<AbstractFunctionDecl>(DC))
return classof(fn);
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);
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);
SourceLoc getLoc() const { return NameLoc; }
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(PrecedenceGroupDeclBits.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 PrecedenceGroupDeclBits.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;
public:
OperatorDecl(DeclKind kind,
DeclContext *DC,
SourceLoc OperatorLoc,
Identifier Name,
SourceLoc NameLoc)
: Decl(kind, DC),
OperatorLoc(OperatorLoc), NameLoc(NameLoc),
name(Name) {}
SourceLoc getLoc() const { return NameLoc; }
SourceLoc getOperatorLoc() const { return OperatorLoc; }
SourceLoc getNameLoc() const { return NameLoc; }
Identifier getName() const { return name; }
static bool classof(const Decl *D) {
return D->getKind() >= DeclKind::First_OperatorDecl
&& D->getKind() <= DeclKind::Last_OperatorDecl;
}
};
/// Declares the behavior of an infix operator. For example:
///
/// \code
/// infix operator /+/ : AdditivePrecedence
/// \endcode
class InfixOperatorDecl : public OperatorDecl {
SourceLoc ColonLoc, PrecedenceGroupNameLoc;
Identifier PrecedenceGroupName;
PrecedenceGroupDecl *PrecedenceGroup = nullptr;
public:
InfixOperatorDecl(DeclContext *DC,
SourceLoc operatorLoc,
Identifier name,
SourceLoc nameLoc,
SourceLoc colonLoc,
Identifier precedenceGroupName,
SourceLoc precedenceGroupNameLoc)
: OperatorDecl(DeclKind::InfixOperator, DC, operatorLoc, name, nameLoc),
ColonLoc(colonLoc), PrecedenceGroupNameLoc(precedenceGroupNameLoc),
PrecedenceGroupName(precedenceGroupName) {
}
SourceLoc getEndLoc() const {
if (PrecedenceGroupName.empty())
return getNameLoc();
return PrecedenceGroupNameLoc;
}
SourceRange getSourceRange() const {
return { getOperatorLoc(), getEndLoc() };
}
SourceLoc getColonLoc() const { return ColonLoc; }
SourceLoc getPrecedenceGroupNameLoc() const { return PrecedenceGroupNameLoc; }
Identifier getPrecedenceGroupName() const { return PrecedenceGroupName; }
PrecedenceGroupDecl *getPrecedenceGroup() const { return PrecedenceGroup; }
void setPrecedenceGroup(PrecedenceGroupDecl *PGD) {
PrecedenceGroup = PGD;
}
/// 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)
: OperatorDecl(DeclKind::PrefixOperator, DC, OperatorLoc, Name, NameLoc) {}
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)
: OperatorDecl(DeclKind::PostfixOperator, DC, OperatorLoc, Name, NameLoc) {}
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)
: Decl(DeclKind::MissingMember, DC), Name(name) {
MissingMemberDeclBits.NumberOfVTableEntries = vtableEntries;
assert(getNumberOfVTableEntries() == vtableEntries && "not enough bits");
setImplicit();
}
public:
static MissingMemberDecl *
forMethod(ASTContext &ctx, DeclContext *DC, DeclName name,
bool hasNormalVTableEntry) {
assert(!name || name.isCompoundName());
return new (ctx) MissingMemberDecl(DC, name, hasNormalVTableEntry);
}
static MissingMemberDecl *
forInitializer(ASTContext &ctx, DeclContext *DC, DeclName name,
bool hasNormalVTableEntry,
bool hasAllocatingVTableEntry) {
unsigned entries = hasNormalVTableEntry + hasAllocatingVTableEntry;
return new (ctx) MissingMemberDecl(DC, name, entries);
}
DeclName getFullName() const {
return Name;
}
unsigned getNumberOfVTableEntries() const {
return MissingMemberDeclBits.NumberOfVTableEntries;
}
SourceLoc getLoc() const {
return SourceLoc();
}
SourceRange getSourceRange() const {
return SourceRange();
}
static bool classof(const Decl *D) {
return D->getKind() == DeclKind::MissingMember;
}
};
inline bool ValueDecl::isSettable(const DeclContext *UseDC,
const DeclRefExpr *base) const {
if (auto vd = dyn_cast<VarDecl>(this)) {
return vd->isSettable(UseDC, base);
} else if (auto sd = dyn_cast<SubscriptDecl>(this)) {
return sd->isSettable();
} else
return false;
}
inline Optional<VarDecl *>
NominalTypeDecl::ToStoredProperty::operator()(Decl *decl) const {
if (auto var = dyn_cast<VarDecl>(decl)) {
if (!var->isStatic() && var->hasStorage() &&
(!skipUserInaccessible || var->isUserAccessible()))
return var;
}
return None;
}
inline void
AbstractStorageDecl::overwriteSetterAccess(AccessLevel accessLevel) {
GetSetInfo.setInt(accessLevel);
if (auto setter = getSetter())
setter->overwriteAccess(accessLevel);
if (auto materializeForSet = getMaterializeForSetFunc())
materializeForSet->overwriteAccess(accessLevel);
}
inline bool AbstractStorageDecl::isStatic() const {
if (auto var = dyn_cast<VarDecl>(this)) {
return var->isStatic();
}
// Currently, subscripts are never static.
return false;
}
inline MutableArrayRef<ParameterList *>
AbstractFunctionDecl::getParameterLists() {
switch (getKind()) {
default: llvm_unreachable("Unknown AbstractFunctionDecl!");
case DeclKind::Constructor:
return cast<ConstructorDecl>(this)->getParameterLists();
case DeclKind::Destructor:
return cast<DestructorDecl>(this)->getParameterLists();
case DeclKind::Func:
return cast<FuncDecl>(this)->getParameterLists();
}
}
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 Decl::isPotentiallyOverridable() const {
if (isa<VarDecl>(this) ||
isa<SubscriptDecl>(this) ||
isa<FuncDecl>(this)) {
return getDeclContext()->getAsClassOrClassExtensionContext();
} else {
return false;
}
}
inline GenericParamKey::GenericParamKey(const GenericTypeParamDecl *d)
: Depth(d->getDepth()), Index(d->getIndex()) { }
} // end namespace swift
#endif