mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
After recent changes, this asserts on all decls that are not VarDecls, so we can just enforce that statically now. Interestingly, this turns up some dead code which would have asserted immediately if called. Also, replace AnyFunctionRef::getType() with AnyFunctionRef::getInterfaceType(), since the old AnyFunctionRef::getType() would just assert when called on a Decl.
195 lines
6.2 KiB
C++
195 lines
6.2 KiB
C++
//===--- AnyFunctionRef.h - A Universal Function Reference ------*- C++ -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2016 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SWIFT_AST_ANY_FUNCTION_REF_H
|
|
#define SWIFT_AST_ANY_FUNCTION_REF_H
|
|
|
|
#include "swift/Basic/LLVM.h"
|
|
#include "swift/AST/ArchetypeBuilder.h"
|
|
#include "swift/AST/Decl.h"
|
|
#include "swift/AST/Expr.h"
|
|
#include "swift/AST/Types.h"
|
|
#include "llvm/ADT/DenseMap.h"
|
|
#include "llvm/ADT/PointerUnion.h"
|
|
|
|
namespace swift {
|
|
class CaptureInfo;
|
|
|
|
/// \brief A universal function reference -- can wrap all AST nodes that
|
|
/// represent functions and exposes a common interface to them.
|
|
class AnyFunctionRef {
|
|
PointerUnion<AbstractFunctionDecl *, AbstractClosureExpr *> TheFunction;
|
|
|
|
friend struct llvm::DenseMapInfo<AnyFunctionRef>;
|
|
|
|
AnyFunctionRef(decltype(TheFunction) TheFunction)
|
|
: TheFunction(TheFunction) {}
|
|
|
|
public:
|
|
AnyFunctionRef(AbstractFunctionDecl *AFD) : TheFunction(AFD) {
|
|
assert(AFD && "should have a function");
|
|
}
|
|
AnyFunctionRef(AbstractClosureExpr *ACE) : TheFunction(ACE) {
|
|
assert(ACE && "should have a closure");
|
|
}
|
|
|
|
/// Construct an AnyFunctionRef from a decl context that's known to
|
|
/// be some sort of function.
|
|
static AnyFunctionRef fromFunctionDeclContext(DeclContext *dc) {
|
|
if (auto fn = dyn_cast<AbstractFunctionDecl>(dc)) {
|
|
return fn;
|
|
} else {
|
|
return cast<AbstractClosureExpr>(dc);
|
|
}
|
|
}
|
|
|
|
CaptureInfo &getCaptureInfo() const {
|
|
if (auto *AFD = TheFunction.dyn_cast<AbstractFunctionDecl *>())
|
|
return AFD->getCaptureInfo();
|
|
return TheFunction.get<AbstractClosureExpr *>()->getCaptureInfo();
|
|
}
|
|
|
|
void getLocalCaptures(SmallVectorImpl<CapturedValue> &Result) const {
|
|
getCaptureInfo().getLocalCaptures(Result);
|
|
}
|
|
|
|
ArrayRef<ParameterList *> getParameterLists() const {
|
|
if (auto *AFD = TheFunction.dyn_cast<AbstractFunctionDecl *>())
|
|
return AFD->getParameterLists();
|
|
return TheFunction.get<AbstractClosureExpr *>()->getParameterLists();
|
|
}
|
|
|
|
bool hasType() const {
|
|
if (auto *AFD = TheFunction.dyn_cast<AbstractFunctionDecl *>())
|
|
return AFD->hasInterfaceType();
|
|
return !TheFunction.get<AbstractClosureExpr *>()->getType().isNull();
|
|
}
|
|
|
|
Type getType() const {
|
|
if (auto *AFD = TheFunction.dyn_cast<AbstractFunctionDecl *>())
|
|
return AFD->getInterfaceType();
|
|
return TheFunction.get<AbstractClosureExpr *>()->getType();
|
|
}
|
|
|
|
Type getBodyResultType() const {
|
|
if (auto *AFD = TheFunction.dyn_cast<AbstractFunctionDecl *>()) {
|
|
if (auto *FD = dyn_cast<FuncDecl>(AFD))
|
|
return ArchetypeBuilder::mapTypeIntoContext(
|
|
FD, FD->getResultInterfaceType());
|
|
return TupleType::getEmpty(AFD->getASTContext());
|
|
}
|
|
return TheFunction.get<AbstractClosureExpr *>()->getResultType();
|
|
}
|
|
|
|
BraceStmt *getBody() const {
|
|
if (auto *AFD = TheFunction.dyn_cast<AbstractFunctionDecl *>())
|
|
return AFD->getBody();
|
|
auto *ACE = TheFunction.get<AbstractClosureExpr *>();
|
|
if (auto *CE = dyn_cast<ClosureExpr>(ACE))
|
|
return CE->getBody();
|
|
return cast<AutoClosureExpr>(ACE)->getBody();
|
|
}
|
|
|
|
DeclContext *getAsDeclContext() const {
|
|
if (auto *AFD = TheFunction.dyn_cast<AbstractFunctionDecl *>())
|
|
return AFD;
|
|
return TheFunction.get<AbstractClosureExpr *>();
|
|
}
|
|
|
|
AbstractFunctionDecl *getAbstractFunctionDecl() const {
|
|
return TheFunction.dyn_cast<AbstractFunctionDecl*>();
|
|
}
|
|
|
|
AbstractClosureExpr *getAbstractClosureExpr() const {
|
|
return TheFunction.dyn_cast<AbstractClosureExpr*>();
|
|
}
|
|
|
|
/// Return true if this closure is passed as an argument to a function and is
|
|
/// known not to escape from that function. In this case, captures can be
|
|
/// more efficient.
|
|
bool isKnownNoEscape() const {
|
|
if (auto afd = TheFunction.dyn_cast<AbstractFunctionDecl *>()) {
|
|
// As a hack, assume defer bodies are noescape.
|
|
if (auto fd = dyn_cast<FuncDecl>(afd))
|
|
return fd->isDeferBody();
|
|
return false;
|
|
}
|
|
|
|
|
|
auto *CE = TheFunction.get<AbstractClosureExpr *>();
|
|
if (!CE->getType() || CE->getType()->hasError())
|
|
return false;
|
|
return CE->getType()->castTo<FunctionType>()->isNoEscape();
|
|
}
|
|
|
|
bool isObjC() const {
|
|
if (auto afd = TheFunction.dyn_cast<AbstractFunctionDecl *>()) {
|
|
return afd->isObjC();
|
|
}
|
|
if (TheFunction.dyn_cast<AbstractClosureExpr *>()) {
|
|
// Closures are never @objc.
|
|
return false;
|
|
}
|
|
llvm_unreachable("unexpected AnyFunctionRef representation");
|
|
}
|
|
|
|
SourceLoc getLoc() const {
|
|
if (auto afd = TheFunction.dyn_cast<AbstractFunctionDecl *>()) {
|
|
return afd->getLoc();
|
|
}
|
|
if (auto ce = TheFunction.dyn_cast<AbstractClosureExpr *>()) {
|
|
return ce->getLoc();
|
|
}
|
|
llvm_unreachable("unexpected AnyFunctionRef representation");
|
|
}
|
|
|
|
LLVM_ATTRIBUTE_DEPRECATED(void dump() const LLVM_ATTRIBUTE_USED,
|
|
"only for use within the debugger") {
|
|
if (auto afd = TheFunction.dyn_cast<AbstractFunctionDecl *>()) {
|
|
return afd->dump();
|
|
}
|
|
if (auto ce = TheFunction.dyn_cast<AbstractClosureExpr *>()) {
|
|
return ce->dump();
|
|
}
|
|
llvm_unreachable("unexpected AnyFunctionRef representation");
|
|
}
|
|
};
|
|
|
|
} // namespace swift
|
|
|
|
namespace llvm {
|
|
|
|
template<>
|
|
struct DenseMapInfo<swift::AnyFunctionRef> {
|
|
using PointerUnion = decltype(swift::AnyFunctionRef::TheFunction);
|
|
using PointerUnionTraits = DenseMapInfo<PointerUnion>;
|
|
using AnyFunctionRef = swift::AnyFunctionRef;
|
|
|
|
static inline AnyFunctionRef getEmptyKey() {
|
|
return AnyFunctionRef(PointerUnionTraits::getEmptyKey());
|
|
}
|
|
static inline AnyFunctionRef getTombstoneKey() {
|
|
return AnyFunctionRef(PointerUnionTraits::getTombstoneKey());
|
|
}
|
|
static inline unsigned getHashValue(AnyFunctionRef ref) {
|
|
return PointerUnionTraits::getHashValue(ref.TheFunction);
|
|
}
|
|
static bool isEqual(AnyFunctionRef a, AnyFunctionRef b) {
|
|
return a.TheFunction == b.TheFunction;
|
|
}
|
|
};
|
|
|
|
}
|
|
|
|
#endif // LLVM_SWIFT_AST_ANY_FUNCTION_REF_H
|
|
|