Merge pull request #13939 from davezarzycki/declnode_declctxt_cleanup
diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index bfdd042..6747434 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -58,6 +58,7 @@
class LiteralExpr;
class BraceStmt;
class DeclAttributes;
+ class GenericContext;
class GenericSignature;
class GenericTypeParamDecl;
class GenericTypeParamType;
@@ -847,6 +848,9 @@
return getClangNodeImpl().getAsMacro();
}
+ /// \brief Return the GenericContext if the Decl has one.
+ const GenericContext *getAsGenericContext() const;
+
bool isPrivateStdlibDecl(bool treatNonBuiltinProtocolsAsPublic = true) const;
/// Whether this declaration is weak-imported.
@@ -6200,6 +6204,9 @@
Identifier getName() const { return name; }
static bool classof(const Decl *D) {
+ // Workaround: http://llvm.org/PR35906
+ if (DeclKind::Last_Decl == DeclKind::Last_OperatorDecl)
+ return D->getKind() >= DeclKind::First_OperatorDecl;
return D->getKind() >= DeclKind::First_OperatorDecl
&& D->getKind() <= DeclKind::Last_OperatorDecl;
}
@@ -6480,6 +6487,41 @@
inline GenericParamKey::GenericParamKey(const GenericTypeParamDecl *d)
: Depth(d->getDepth()), Index(d->getIndex()) { }
+inline const GenericContext *Decl::getAsGenericContext() const {
+ switch (getKind()) {
+ default: return nullptr;
+#define DECL(Id, Parent) // See previous line
+#define GENERIC_DECL(Id, Parent) \
+ case DeclKind::Id: \
+ return static_cast<const Id##Decl*>(this);
+#include "swift/AST/DeclNodes.def"
+ }
+}
+
+inline bool DeclContext::classof(const Decl *D) {
+ switch (D->getKind()) { //
+ default: return false;
+#define DECL(ID, PARENT) // See previous line
+#define CONTEXT_DECL(ID, PARENT) \
+ case DeclKind::ID: return true;
+#include "swift/AST/DeclNodes.def"
+ }
+}
+
+inline DeclContext *DeclContext::castDeclToDeclContext(const Decl *D) {
+ // XXX -- ModuleDecl is not defined in Decl.h, but because DeclContexts
+ // preface decls in memory, any DeclContext type will due.
+ const DeclContext *DC = static_cast<const ExtensionDecl*>(D);
+ switch (D->getKind()) {
+ default: llvm_unreachable("Not a DeclContext");
+#define DECL(ID, PARENT) // See previous line
+#define CONTEXT_DECL(ID, PARENT) \
+ case DeclKind::ID:
+#include "swift/AST/DeclNodes.def"
+ return const_cast<DeclContext *>(DC);
+ }
+}
+
} // end namespace swift
#endif
diff --git a/include/swift/AST/DeclContext.h b/include/swift/AST/DeclContext.h
index 688bf93..9c2c3bd 100644
--- a/include/swift/AST/DeclContext.h
+++ b/include/swift/AST/DeclContext.h
@@ -208,6 +208,7 @@
template<class A, class B, class C>
friend struct ::llvm::cast_convert_val;
+ // See swift/AST/Decl.h
static DeclContext *castDeclToDeclContext(const Decl *D);
/// If this DeclContext is a GenericType declaration or an
@@ -235,6 +236,7 @@
llvm_unreachable("Unhandled DeclContextKind");
}
+public:
Decl *getAsDeclOrDeclExtensionContext() {
return ParentAndKind.getInt() == ASTHierarchy::Decl ?
reinterpret_cast<Decl*>(this + 1) : nullptr;
@@ -243,7 +245,6 @@
return const_cast<DeclContext*>(this)->getAsDeclOrDeclExtensionContext();
}
-public:
DeclContext(DeclContextKind Kind, DeclContext *Parent)
: ParentAndKind(Parent, getASTHierarchyFromKind(Kind)) {
if (Kind != DeclContextKind::Module)
@@ -554,7 +555,7 @@
void *operator new(size_t Bytes, ASTContext &C,
unsigned Alignment = alignof(DeclContext));
- // Some Decls are DeclContexts, but not all.
+ // Some Decls are DeclContexts, but not all. See swift/AST/Decl.h
static bool classof(const Decl *D);
};
diff --git a/include/swift/AST/DeclNodes.def b/include/swift/AST/DeclNodes.def
index a22de9b..6ebbc98 100644
--- a/include/swift/AST/DeclNodes.def
+++ b/include/swift/AST/DeclNodes.def
@@ -38,25 +38,68 @@
#define CONTEXT_DECL(Id, Parent) DECL(Id, Parent)
#endif
-/// VALUE_DECL(Id, Parent)
-/// Used for subclasses of ValueDecl. The default behavior is to do
-/// the same as for Decl.
-#ifndef VALUE_DECL
-#define VALUE_DECL(Id, Parent) DECL(Id, Parent)
+/// ITERABLE_NONGENERIC_DECL(Id, Parent)
+/// Used for Decls that are also IterableDeclContexts and DeclContexts. The
+/// default behavior is to do the same as for CONTEXT_DECL. This combination
+/// does not exist at the moment.
+#ifndef ITERABLE_NONGENERIC_DECL
+#ifdef ITERABLE_DECL
+#define ITERABLE_NONGENERIC_DECL(Id, Parent) ITERABLE_DECL(Id, Parent)
+#else
+#define ITERABLE_NONGENERIC_DECL(Id, Parent) CONTEXT_DECL(Id, Parent)
+#endif
+#endif
+
+/// GENERIC_DECL(Id, Parent)
+/// Used for Decls that are also GenericContexts. The default behavior is to
+/// do the same as for CONTEXT_DECL.
+#ifndef GENERIC_DECL
+#define GENERIC_DECL(Id, Parent) CONTEXT_DECL(Id, Parent)
+#endif
+
+/// ITERABLE_GENERIC_DECL(Id, Parent)
+/// Used for Decls that are also IterableDeclContexts and GenericContexts. The
+/// default behavior is to do the same as for GENERIC_DECL.
+#ifndef ITERABLE_GENERIC_DECL
+#ifdef ITERABLE_DECL
+#define ITERABLE_GENERIC_DECL(Id, Parent) ITERABLE_DECL(Id, Parent)
+#else
+#define ITERABLE_GENERIC_DECL(Id, Parent) GENERIC_DECL(Id, Parent)
+#endif
#endif
/// CONTEXT_VALUE_DECL(Id, Parent)
/// Used for subclasses of ValueDecl that are also DeclContexts. The default
-/// behavior is to do the same as for ValueDecl.
+/// behavior is to do the same as for CONTEXT_DECL.
#ifndef CONTEXT_VALUE_DECL
+#ifdef VALUE_DECL
#define CONTEXT_VALUE_DECL(Id, Parent) VALUE_DECL(Id, Parent)
+#else
+#define CONTEXT_VALUE_DECL(Id, Parent) CONTEXT_DECL(Id, Parent)
+#endif
#endif
-/// FUNCTION_DECL(Id, Parent)
-/// Used for subclasses of AbstractFunctionDecl. The default behavior is to do
-/// the same as for CONTEXT_VALUE_DECL.
-#ifndef FUNCTION_DECL
-#define FUNCTION_DECL(Id, Parent) CONTEXT_VALUE_DECL(Id, Parent)
+/// GENERIC_VALUE_DECL(Id, Parent)
+/// Used for subclasses of ValueDecl that are also GenericContexts. The
+/// default behavior is to do the same as for GENERIC_DECL.
+#ifndef GENERIC_VALUE_DECL
+#ifdef VALUE_DECL
+#define GENERIC_VALUE_DECL(Id, Parent) VALUE_DECL(Id, Parent)
+#else
+#define GENERIC_VALUE_DECL(Id, Parent) GENERIC_DECL(Id, Parent)
+#endif
+#endif
+
+/// ITERABLE_GENERIC_VALUE_DECL(Id, Parent)
+/// Used for subclasses of ValueDecl that are also IterableDeclContexts and
+/// GenericContexts. The default behavior is to do the same as for
+/// ITERABLE_GENERIC_DECL.
+#ifndef ITERABLE_GENERIC_VALUE_DECL
+#ifdef VALUE_DECL
+#define ITERABLE_GENERIC_VALUE_DECL(Id, Parent) VALUE_DECL(Id, Parent)
+#else
+#define ITERABLE_GENERIC_VALUE_DECL(Id, Parent) ITERABLE_GENERIC_DECL(Id,Parent)
+#endif
#endif
/// OPERATOR_DECL(Id, Parent)
@@ -68,16 +111,16 @@
/// NOMINAL_TYPE_DECL(Id, Parent)
/// Used for subclasses of NominalTypeDecl. The default behavior is
-/// to do the same as for CONTEXT_VALUE_DECL.
+/// to do the same as for ITERABLE_GENERIC_VALUE_DECL.
#ifndef NOMINAL_TYPE_DECL
-#define NOMINAL_TYPE_DECL(Id, Parent) CONTEXT_VALUE_DECL(Id, Parent)
+#define NOMINAL_TYPE_DECL(Id, Parent) ITERABLE_GENERIC_VALUE_DECL(Id, Parent)
#endif
-/// EXTENSION_DECL(Id, Parent)
-/// Used for subclasses of ExtensionDecl. The default behavior is
-/// to do the same as for CONTEXT_DECL.
-#ifndef EXTENSION_DECL
-#define EXTENSION_DECL(Id, Parent) CONTEXT_DECL(Id, Parent)
+/// VALUE_DECL(Id, Parent)
+/// Used for subclasses of ValueDecl. The default behavior is to do
+/// the same as for Decl.
+#ifndef VALUE_DECL
+#define VALUE_DECL(Id, Parent) DECL(Id, Parent)
#endif
/// A convenience for determining the range of declarations. These will always
@@ -90,14 +133,48 @@
#define LAST_DECL(Id)
#endif
-DECL(Import, Decl)
-EXTENSION_DECL(Extension, Decl)
-DECL(PatternBinding, Decl)
-DECL(EnumCase, Decl)
+// NOTE: For performance, maximize the numer of [important] abstract Decls
+// where "First_XYZDecl" == 0 to improve isa/dyn_cast code gen.
+
+ABSTRACT_DECL(Value, Decl)
+ ABSTRACT_DECL(Type, ValueDecl)
+ ABSTRACT_DECL(GenericType, TypeDecl)
+ ABSTRACT_DECL(NominalType, GenericTypeDecl)
+ NOMINAL_TYPE_DECL(Enum, NominalTypeDecl)
+ NOMINAL_TYPE_DECL(Struct, NominalTypeDecl)
+ NOMINAL_TYPE_DECL(Class, NominalTypeDecl)
+ NOMINAL_TYPE_DECL(Protocol, NominalTypeDecl)
+ DECL_RANGE(NominalType, Enum, Protocol)
+ GENERIC_VALUE_DECL(TypeAlias, GenericTypeDecl)
+ DECL_RANGE(GenericType, Enum, TypeAlias)
+ ABSTRACT_DECL(AbstractTypeParam, TypeDecl)
+ VALUE_DECL(GenericTypeParam, AbstractTypeParamDecl)
+ VALUE_DECL(AssociatedType, AbstractTypeParamDecl)
+ DECL_RANGE(AbstractTypeParam, GenericTypeParam, AssociatedType)
+ CONTEXT_VALUE_DECL(Module, TypeDecl)
+ DECL_RANGE(Type, Enum, Module)
+ ABSTRACT_DECL(AbstractStorage, ValueDecl)
+ VALUE_DECL(Var, AbstractStorageDecl)
+ VALUE_DECL(Param, VarDecl)
+ GENERIC_VALUE_DECL(Subscript, AbstractStorageDecl)
+ DECL_RANGE(AbstractStorage, Var, Subscript)
+ ABSTRACT_DECL(AbstractFunction, ValueDecl)
+ GENERIC_VALUE_DECL(Constructor, AbstractFunctionDecl)
+ GENERIC_VALUE_DECL(Destructor, AbstractFunctionDecl)
+ GENERIC_VALUE_DECL(Func, AbstractFunctionDecl)
+ GENERIC_VALUE_DECL(Accessor, FuncDecl)
+ DECL_RANGE(AbstractFunction, Constructor, Accessor)
+ VALUE_DECL(EnumElement, ValueDecl)
+ DECL_RANGE(Value, Enum, EnumElement)
+
+ITERABLE_GENERIC_DECL(Extension, Decl)
CONTEXT_DECL(TopLevelCode, Decl)
+DECL(Import, Decl)
DECL(IfConfig, Decl)
DECL(PrecedenceGroup, Decl)
DECL(MissingMember, Decl)
+DECL(PatternBinding, Decl)
+DECL(EnumCase, Decl)
ABSTRACT_DECL(Operator, Decl)
OPERATOR_DECL(InfixOperator, OperatorDecl)
@@ -105,45 +182,19 @@
OPERATOR_DECL(PostfixOperator, OperatorDecl)
DECL_RANGE(Operator, InfixOperator, PostfixOperator)
-ABSTRACT_DECL(Value, Decl)
- ABSTRACT_DECL(Type, ValueDecl)
- ABSTRACT_DECL(AbstractTypeParam, TypeDecl)
- VALUE_DECL(GenericTypeParam, AbstractTypeParamDecl)
- VALUE_DECL(AssociatedType, AbstractTypeParamDecl)
- DECL_RANGE(AbstractTypeParam, GenericTypeParam, AssociatedType)
- ABSTRACT_DECL(GenericType, TypeDecl)
- CONTEXT_VALUE_DECL(TypeAlias, GenericTypeDecl)
- ABSTRACT_DECL(NominalType, GenericTypeDecl)
- NOMINAL_TYPE_DECL(Enum, NominalTypeDecl)
- NOMINAL_TYPE_DECL(Struct, NominalTypeDecl)
- NOMINAL_TYPE_DECL(Class, NominalTypeDecl)
- NOMINAL_TYPE_DECL(Protocol, NominalTypeDecl)
- DECL_RANGE(NominalType, Enum, Protocol)
- DECL_RANGE(GenericType, TypeAlias, Protocol)
- CONTEXT_VALUE_DECL(Module, TypeDecl)
- DECL_RANGE(Type, GenericTypeParam, Module)
- ABSTRACT_DECL(AbstractStorage, ValueDecl)
- VALUE_DECL(Var, AbstractStorageDecl)
- VALUE_DECL(Param, VarDecl)
- CONTEXT_VALUE_DECL(Subscript, AbstractStorageDecl)
- DECL_RANGE(AbstractStorage, Var, Subscript)
- ABSTRACT_DECL(AbstractFunction, ValueDecl)
- FUNCTION_DECL(Constructor, AbstractFunctionDecl)
- FUNCTION_DECL(Destructor, AbstractFunctionDecl)
- FUNCTION_DECL(Func, AbstractFunctionDecl)
- FUNCTION_DECL(Accessor, FuncDecl)
- DECL_RANGE(AbstractFunction, Constructor, Accessor)
- VALUE_DECL(EnumElement, ValueDecl)
- DECL_RANGE(Value, GenericTypeParam, EnumElement)
-LAST_DECL(EnumElement)
+LAST_DECL(PostfixOperator)
#undef NOMINAL_TYPE_DECL
+#undef CONTEXT_DECL
+#undef ITERABLE_NONGENERIC_DECL
+#undef GENERIC_DECL
+#undef ITERABLE_GENERIC_DECL
+#undef ITERABLE_DECL
+#undef CONTEXT_VALUE_DECL
+#undef GENERIC_VALUE_DECL
+#undef ITERABLE_GENERIC_VALUE_DECL
#undef VALUE_DECL
#undef DECL_RANGE
#undef ABSTRACT_DECL
-#undef FUNCTION_DECL
-#undef CONTEXT_DECL
-#undef CONTEXT_VALUE_DECL
-#undef EXTENSION_DECL
#undef DECL
#undef LAST_DECL
diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h
index f6bb709..6fa679e 100644
--- a/include/swift/AST/Types.h
+++ b/include/swift/AST/Types.h
@@ -1506,6 +1506,7 @@
}
static bool classof(const TypeBase *T) {
+ // Workaround: http://llvm.org/PR35906
if (TypeKind::Last_Type == TypeKind::Last_SugarType)
return T->getKind() >= TypeKind::First_SugarType;
return T->getKind() >= TypeKind::First_SugarType &&
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index b1b6b58..dd6cca7 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -309,13 +309,6 @@
return getDeclContext();
}
-DeclContext *Decl::getDeclContextForModule() const {
- if (auto module = dyn_cast<ModuleDecl>(this))
- return const_cast<ModuleDecl *>(module);
-
- return nullptr;
-}
-
void Decl::setDeclContext(DeclContext *DC) {
Context = DC;
}
diff --git a/lib/AST/DeclContext.cpp b/lib/AST/DeclContext.cpp
index 6f3b54e..703cc30 100644
--- a/lib/AST/DeclContext.cpp
+++ b/lib/AST/DeclContext.cpp
@@ -153,135 +153,52 @@
}
GenericParamList *DeclContext::getGenericParamsOfContext() const {
- for (const DeclContext *dc = this; ; dc = dc->getParent()) {
- switch (dc->getContextKind()) {
- case DeclContextKind::Module:
- case DeclContextKind::FileUnit:
- case DeclContextKind::TopLevelCodeDecl:
- return nullptr;
-
- case DeclContextKind::SerializedLocal:
- case DeclContextKind::Initializer:
- case DeclContextKind::AbstractClosureExpr:
- // Closures and initializers can't themselves be generic, but they
- // can occur in generic contexts.
- continue;
-
- case DeclContextKind::SubscriptDecl:
- if (auto GP = cast<SubscriptDecl>(dc)->getGenericParams())
- return GP;
- continue;
-
- case DeclContextKind::AbstractFunctionDecl:
- if (auto GP = cast<AbstractFunctionDecl>(dc)->getGenericParams())
- return GP;
- continue;
-
- case DeclContextKind::GenericTypeDecl:
- if (auto GP = cast<GenericTypeDecl>(dc)->getGenericParams())
- return GP;
- continue;
-
- case DeclContextKind::ExtensionDecl:
- // Extensions do not capture outer generic parameters.
- return cast<ExtensionDecl>(dc)->getGenericParams();
+ auto dc = this;
+ do {
+ if (auto decl = dc->getAsDeclOrDeclExtensionContext()) {
+ if (auto GC = decl->getAsGenericContext()) {
+ auto GP = GC->getGenericParams();
+ // Extensions do not capture outer generic parameters.
+ if (GP != nullptr || isa<ExtensionDecl>(decl))
+ return GP;
+ }
}
- llvm_unreachable("bad DeclContextKind");
- }
- llvm_unreachable("unknown parent");
+ } while ((dc = dc->getParent()));
+
+ return nullptr;
}
GenericSignature *DeclContext::getGenericSignatureOfContext() const {
- for (const DeclContext *dc = this; ; dc = dc->getParent()) {
- switch (dc->getContextKind()) {
- case DeclContextKind::Module:
- case DeclContextKind::FileUnit:
- case DeclContextKind::TopLevelCodeDecl:
- return nullptr;
+ auto dc = this;
+ do {
+ if (auto decl = dc->getAsDeclOrDeclExtensionContext())
+ if (auto GC = decl->getAsGenericContext())
+ return GC->getGenericSignature();
+ } while ((dc = dc->getParent()));
- case DeclContextKind::Initializer:
- case DeclContextKind::SerializedLocal:
- case DeclContextKind::AbstractClosureExpr:
- // Closures and initializers can't themselves be generic, but they
- // can occur in generic contexts.
- continue;
-
- case DeclContextKind::SubscriptDecl:
- return cast<SubscriptDecl>(dc)->getGenericSignature();
-
- case DeclContextKind::AbstractFunctionDecl:
- return cast<AbstractFunctionDecl>(dc)->getGenericSignature();
-
- case DeclContextKind::GenericTypeDecl:
- return cast<GenericTypeDecl>(dc)->getGenericSignature();
-
- case DeclContextKind::ExtensionDecl:
- return cast<ExtensionDecl>(dc)->getGenericSignature();
- }
- llvm_unreachable("bad DeclContextKind");
- }
+ return nullptr;
}
GenericEnvironment *DeclContext::getGenericEnvironmentOfContext() const {
- for (const DeclContext *dc = this; ; dc = dc->getParent()) {
- switch (dc->getContextKind()) {
- case DeclContextKind::Module:
- case DeclContextKind::FileUnit:
- case DeclContextKind::TopLevelCodeDecl:
- return nullptr;
+ auto dc = this;
+ do {
+ if (auto decl = dc->getAsDeclOrDeclExtensionContext())
+ if (auto GC = decl->getAsGenericContext())
+ return GC->getGenericEnvironment();
+ } while ((dc = dc->getParent()));
- case DeclContextKind::Initializer:
- case DeclContextKind::SerializedLocal:
- case DeclContextKind::AbstractClosureExpr:
- // Closures and initializers can't themselves be generic, but they
- // can occur in generic contexts.
- continue;
-
- case DeclContextKind::SubscriptDecl:
- return cast<SubscriptDecl>(dc)->getGenericEnvironment();
-
- case DeclContextKind::AbstractFunctionDecl:
- return cast<AbstractFunctionDecl>(dc)->getGenericEnvironment();
-
- case DeclContextKind::GenericTypeDecl:
- return cast<GenericTypeDecl>(dc)->getGenericEnvironment();
-
- case DeclContextKind::ExtensionDecl:
- return cast<ExtensionDecl>(dc)->getGenericEnvironment();
- }
- llvm_unreachable("bad DeclContextKind");
- }
+ return nullptr;
}
bool DeclContext::contextHasLazyGenericEnvironment() const {
- for (const DeclContext *dc = this; ; dc = dc->getParent()) {
- switch (dc->getContextKind()) {
- case DeclContextKind::Module:
- case DeclContextKind::FileUnit:
- case DeclContextKind::TopLevelCodeDecl:
- return false;
+ auto dc = this;
+ do {
+ if (auto decl = dc->getAsDeclOrDeclExtensionContext())
+ if (auto GC = decl->getAsGenericContext())
+ return GC->hasLazyGenericEnvironment();
+ } while ((dc = dc->getParent()));
- case DeclContextKind::Initializer:
- case DeclContextKind::SerializedLocal:
- case DeclContextKind::AbstractClosureExpr:
- // Closures and initializers can't themselves be generic, but they
- // can occur in generic contexts.
- continue;
-
- case DeclContextKind::SubscriptDecl:
- return cast<SubscriptDecl>(dc)->hasLazyGenericEnvironment();
-
- case DeclContextKind::AbstractFunctionDecl:
- return cast<AbstractFunctionDecl>(dc)->hasLazyGenericEnvironment();
-
- case DeclContextKind::GenericTypeDecl:
- return cast<GenericTypeDecl>(dc)->hasLazyGenericEnvironment();
-
- case DeclContextKind::ExtensionDecl:
- return cast<ExtensionDecl>(dc)->hasLazyGenericEnvironment();
- }
- llvm_unreachable("bad DeclContextKind");
- }
+ return false;
}
Type DeclContext::mapTypeIntoContext(Type type) const {
@@ -298,76 +215,40 @@
}
AbstractFunctionDecl *DeclContext::getInnermostMethodContext() {
- DeclContext *result = this;
- while (true) {
- switch (result->getContextKind()) {
- case DeclContextKind::AbstractClosureExpr:
- case DeclContextKind::Initializer:
- case DeclContextKind::SerializedLocal:
- // Look through closures, initial values.
- result = result->getParent();
- continue;
-
- case DeclContextKind::AbstractFunctionDecl: {
- // If this function is a method, we found our result.
- auto func = dyn_cast<AbstractFunctionDecl>(result);
+ auto dc = this;
+ do {
+ if (auto decl = dc->getAsDeclOrDeclExtensionContext()) {
+ auto func = dyn_cast<AbstractFunctionDecl>(decl);
+ // If we found a non-func decl, we're done.
+ if (func == nullptr)
+ return nullptr;
if (func->getDeclContext()->isTypeContext())
return func;
-
- // This function isn't a method; look through it.
- result = func->getDeclContext();
- continue;
}
+ } while ((dc = dc->getParent()));
- case DeclContextKind::ExtensionDecl:
- case DeclContextKind::FileUnit:
- case DeclContextKind::Module:
- case DeclContextKind::GenericTypeDecl:
- case DeclContextKind::TopLevelCodeDecl:
- case DeclContextKind::SubscriptDecl:
- // Not in a method context.
- return nullptr;
- }
- }
+ return nullptr;
}
bool DeclContext::isTypeContext() const {
- return isa<NominalTypeDecl>(this) ||
- getContextKind() == DeclContextKind::ExtensionDecl;
+ if (auto decl = getAsDeclOrDeclExtensionContext())
+ return isa<NominalTypeDecl>(decl) || isa<ExtensionDecl>(decl);
+ return false;
}
DeclContext *DeclContext::getInnermostTypeContext() {
- DeclContext *Result = this;
- while (true) {
- switch (Result->getContextKind()) {
- case DeclContextKind::AbstractClosureExpr:
- case DeclContextKind::Initializer:
- case DeclContextKind::TopLevelCodeDecl:
- case DeclContextKind::AbstractFunctionDecl:
- case DeclContextKind::SubscriptDecl:
- case DeclContextKind::SerializedLocal:
- Result = Result->getParent();
- continue;
+ auto dc = this;
+ do {
+ if (auto decl = dc->getAsDeclOrDeclExtensionContext())
+ if (isa<NominalTypeDecl>(decl) || isa<ExtensionDecl>(decl))
+ return dc;
+ } while ((dc = dc->getParent()));
- case DeclContextKind::Module:
- case DeclContextKind::FileUnit:
- return nullptr;
-
- case DeclContextKind::GenericTypeDecl:
- if (isa<TypeAliasDecl>(Result)) {
- Result = Result->getParent();
- continue;
- }
- return Result;
-
- case DeclContextKind::ExtensionDecl:
- return Result;
- }
- }
+ return nullptr;
}
Decl *DeclContext::getInnermostDeclarationDeclContext() {
- DeclContext *DC = this;
+ auto DC = this;
do {
if (auto decl = DC->getAsDeclOrDeclExtensionContext())
return isa<ModuleDecl>(decl) ? nullptr : decl;
@@ -674,32 +555,6 @@
return ctx.SourceMgr.getLineAndColumn(loc).first;
}
-bool DeclContext::classof(const Decl *D) {
- switch (D->getKind()) { //
-#define DECL(ID, PARENT) case DeclKind::ID: return false;
-#define CONTEXT_DECL(ID, PARENT) case DeclKind::ID: return true;
-#define CONTEXT_VALUE_DECL(ID, PARENT) case DeclKind::ID: return true;
-#include "swift/AST/DeclNodes.def"
- }
-
- llvm_unreachable("Unhandled DeclKind in switch.");
-}
-
-DeclContext *DeclContext::castDeclToDeclContext(const Decl *D) {
- switch (D->getKind()) {
-#define DECL(ID, PARENT) \
- case DeclKind::ID: llvm_unreachable("not a decl context");
-#define CONTEXT_DECL(ID, PARENT) \
- case DeclKind::ID: \
- return const_cast<DeclContext *>( \
- static_cast<const DeclContext*>(cast<ID##Decl>(D)));
-#define CONTEXT_VALUE_DECL(ID, PARENT) CONTEXT_DECL(ID, PARENT)
-#include "swift/AST/DeclNodes.def"
- }
-
- llvm_unreachable("Unhandled DeclKind in switch.");
-}
-
unsigned DeclContext::printContext(raw_ostream &OS, unsigned indent) const {
unsigned Depth = 0;
if (auto *P = getParent())
@@ -957,32 +812,25 @@
bool IterableDeclContext::classof(const Decl *D) {
switch (D->getKind()) {
-#define DECL(ID, PARENT) case DeclKind::ID: return false;
-#define NOMINAL_TYPE_DECL(ID, PARENT) case DeclKind::ID: return true;
-#define EXTENSION_DECL(ID, PARENT) case DeclKind::ID: return true;
+ default: return false;
+#define DECL(ID, PARENT) // See previous line
+#define ITERABLE_DECL(ID, PARENT) \
+ case DeclKind::ID: return true;
#include "swift/AST/DeclNodes.def"
}
-
- llvm_unreachable("Unhandled DeclKind in switch.");
}
IterableDeclContext *
IterableDeclContext::castDeclToIterableDeclContext(const Decl *D) {
switch (D->getKind()) {
-#define DECL(ID, PARENT) \
- case DeclKind::ID: llvm_unreachable("not a decl context");
-#define NOMINAL_TYPE_DECL(ID, PARENT) \
- case DeclKind::ID: \
- return const_cast<IterableDeclContext *>( \
- static_cast<const IterableDeclContext*>(cast<ID##Decl>(D)));
-#define EXTENSION_DECL(ID, PARENT) \
+ default: llvm_unreachable("Decl is not a IterableDeclContext.");
+#define DECL(ID, PARENT) // See previous line
+#define ITERABLE_DECL(ID, PARENT) \
case DeclKind::ID: \
return const_cast<IterableDeclContext *>( \
static_cast<const IterableDeclContext*>(cast<ID##Decl>(D)));
#include "swift/AST/DeclNodes.def"
}
-
- llvm_unreachable("Unhandled DeclKind in switch.");
}
/// Return the DeclContext to compare when checking private access in
@@ -1076,6 +924,13 @@
return false;
}
+DeclContext *Decl::getDeclContextForModule() const {
+ if (auto module = dyn_cast<ModuleDecl>(this))
+ return const_cast<ModuleDecl *>(module);
+
+ return nullptr;
+}
+
DeclContextKind DeclContext::getContextKind() const {
switch (ParentAndKind.getInt()) {
case ASTHierarchy::Expr:
diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp
index bd943a8..dc1f80e 100644
--- a/lib/AST/Module.cpp
+++ b/lib/AST/Module.cpp
@@ -406,31 +406,11 @@
size_t oldSize = results.size();
bool alreadyInPrivateContext = false;
- switch (container->getContextKind()) {
- case DeclContextKind::SerializedLocal:
- case DeclContextKind::AbstractClosureExpr:
- case DeclContextKind::Initializer:
- case DeclContextKind::TopLevelCodeDecl:
- case DeclContextKind::AbstractFunctionDecl:
- case DeclContextKind::SubscriptDecl:
- llvm_unreachable("This context does not support lookup.");
+ auto containerDecl = container->getAsDeclOrDeclExtensionContext();
+ // If FileUnit, then use FileUnit::lookupValue instead.
+ assert(containerDecl != nullptr && "This context does not support lookup.");
- case DeclContextKind::FileUnit:
- llvm_unreachable("Use FileUnit::lookupValue instead.");
-
- case DeclContextKind::ExtensionDecl:
- llvm_unreachable("Use ExtensionDecl::lookupDirect instead.");
-
- case DeclContextKind::Module: {
- assert(container == this);
- this->lookupValue({}, name, NLKind::QualifiedLookup, results);
- break;
- }
-
- case DeclContextKind::GenericTypeDecl: {
- auto nominal = dyn_cast<NominalTypeDecl>(container);
- if (!nominal) break;
-
+ if (auto nominal = dyn_cast<NominalTypeDecl>(containerDecl)) {
auto lookupResults = nominal->lookupDirect(name);
// Filter out declarations from other modules.
@@ -443,9 +423,12 @@
auto AS = nominal->getFormalAccessScope();
if (AS.isPrivate() || AS.isFileScope())
alreadyInPrivateContext = true;
-
- break;
- }
+ } else if (isa<ModuleDecl>(containerDecl)) {
+ assert(container == this);
+ this->lookupValue({}, name, NLKind::QualifiedLookup, results);
+ } else if (!isa<GenericTypeDecl>(containerDecl)) {
+ // If ExtensionDecl, then use ExtensionDecl::lookupDirect instead.
+ llvm_unreachable("This context does not support lookup.");
}
// Filter by private-discriminator, or filter out private decls if there isn't
diff --git a/test/IDE/Inputs/foo_swift_module.printed.comments.txt b/test/IDE/Inputs/foo_swift_module.printed.comments.txt
index c5013e9..57da84b 100644
--- a/test/IDE/Inputs/foo_swift_module.printed.comments.txt
+++ b/test/IDE/Inputs/foo_swift_module.printed.comments.txt
@@ -1,16 +1,5 @@
import SwiftOnoneSupport
-precedencegroup High {
- associativity: left
- higherThan: BitwiseShiftPrecedence
-}
-
-infix operator %%% : High
-
-postfix operator =->
-
-postfix operator =>
-
func %%% (lhs: Int, rhs: Int) -> Int
postfix func =-> (lhs: Int) -> Int
@@ -64,3 +53,14 @@
func visibleImport()
+precedencegroup High {
+ associativity: left
+ higherThan: BitwiseShiftPrecedence
+}
+
+infix operator %%% : High
+
+postfix operator =->
+
+postfix operator =>
+
diff --git a/test/Serialization/Recovery/typedefs.swift b/test/Serialization/Recovery/typedefs.swift
index 42e4d36..3e03146 100644
--- a/test/Serialization/Recovery/typedefs.swift
+++ b/test/Serialization/Recovery/typedefs.swift
@@ -91,29 +91,6 @@
prefix operator ***
-// CHECK-LABEL: extension WrappedInt : WrappedProto {
-// CHECK-NEXT: func wrappedMethod()
-// CHECK-NEXT: prefix static func *** (x: WrappedInt)
-// CHECK-NEXT: }
-// CHECK-RECOVERY-NEGATIVE-NOT: extension WrappedInt
-extension WrappedInt: WrappedProto {
- public func wrappedMethod() {}
- public static prefix func ***(x: WrappedInt) {}
-}
-// CHECK-LABEL: extension Int32 : UnwrappedProto {
-// CHECK-NEXT: func unwrappedMethod()
-// CHECK-NEXT: prefix static func *** (x: UnwrappedInt)
-// CHECK-NEXT: }
-// CHECK-RECOVERY-LABEL: extension Int32 : UnwrappedProto {
-// CHECK-RECOVERY-NEXT: func unwrappedMethod()
-// CHECK-RECOVERY-NEXT: prefix static func *** (x: Int32)
-// CHECK-RECOVERY-NEXT: }
-// CHECK-RECOVERY-NEGATIVE-NOT: extension UnwrappedInt
-extension UnwrappedInt: UnwrappedProto {
- public func unwrappedMethod() {}
- public static prefix func ***(x: UnwrappedInt) {}
-}
-
// CHECK-LABEL: class User {
// CHECK-RECOVERY-LABEL: class User {
open class User {
@@ -397,4 +374,28 @@
public typealias ConstrainedWrapped<T: HasAssoc> = T where T.Assoc == WrappedInt
public typealias ConstrainedUnwrapped<T: HasAssoc> = T where T.Assoc == UnwrappedInt
+// CHECK-LABEL: extension Int32 : UnwrappedProto {
+// CHECK-NEXT: func unwrappedMethod()
+// CHECK-NEXT: prefix static func *** (x: UnwrappedInt)
+// CHECK-NEXT: }
+// CHECK-RECOVERY-LABEL: extension Int32 : UnwrappedProto {
+// CHECK-RECOVERY-NEXT: func unwrappedMethod()
+// CHECK-RECOVERY-NEXT: prefix static func *** (x: Int32)
+// CHECK-RECOVERY-NEXT: }
+// CHECK-RECOVERY-NEGATIVE-NOT: extension UnwrappedInt
+extension UnwrappedInt: UnwrappedProto {
+ public func unwrappedMethod() {}
+ public static prefix func ***(x: UnwrappedInt) {}
+}
+
+// CHECK-LABEL: extension WrappedInt : WrappedProto {
+// CHECK-NEXT: func wrappedMethod()
+// CHECK-NEXT: prefix static func *** (x: WrappedInt)
+// CHECK-NEXT: }
+// CHECK-RECOVERY-NEGATIVE-NOT: extension WrappedInt
+extension WrappedInt: WrappedProto {
+ public func wrappedMethod() {}
+ public static prefix func ***(x: WrappedInt) {}
+}
+
#endif // TEST
diff --git a/test/Serialization/extension-of-typealias.swift b/test/Serialization/extension-of-typealias.swift
index 2b49bf0..265e87a 100644
--- a/test/Serialization/extension-of-typealias.swift
+++ b/test/Serialization/extension-of-typealias.swift
@@ -10,6 +10,9 @@
public typealias Zahl = Int
+// CHECK: typealias List
+// CHECK: typealias Zahl
+
// CHECK-LABEL: extension Int {
extension Zahl {
// CHECK-NEXT: addedMember()
@@ -30,9 +33,6 @@
public func addedMemberInt() {}
} // CHECK-NEXT: {{^}$}}
-// CHECK: typealias List
-// CHECK: typealias Zahl
-
#else
import Library