mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
626 lines
22 KiB
C++
626 lines
22 KiB
C++
//===--- ClangImporterRequests.h - Clang Importer Requests ------*- C++ -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2021 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 clang-importer requests.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
#ifndef SWIFT_CLANG_IMPORTER_REQUESTS_H
|
|
#define SWIFT_CLANG_IMPORTER_REQUESTS_H
|
|
|
|
#include "swift/AST/ASTTypeIDs.h"
|
|
#include "swift/AST/EvaluatorDependencies.h"
|
|
#include "swift/AST/Identifier.h"
|
|
#include "swift/AST/NameLookup.h"
|
|
#include "swift/AST/SimpleRequest.h"
|
|
#include "swift/Basic/Statistic.h"
|
|
#include "swift/ClangImporter/ClangImporter.h"
|
|
#include "clang/AST/Type.h"
|
|
#include "clang/Basic/Specifiers.h"
|
|
#include "llvm/ADT/Hashing.h"
|
|
#include "llvm/ADT/TinyPtrVector.h"
|
|
|
|
namespace swift {
|
|
class Decl;
|
|
class DeclName;
|
|
class EnumDecl;
|
|
enum class ExplicitSafety;
|
|
|
|
/// The input type for a clang direct lookup request.
|
|
struct ClangDirectLookupDescriptor final {
|
|
Decl *decl;
|
|
const clang::Decl *clangDecl;
|
|
DeclName name;
|
|
|
|
ClangDirectLookupDescriptor(Decl *decl, const clang::Decl *clangDecl,
|
|
DeclName name)
|
|
: decl(decl), clangDecl(clangDecl), name(name) {}
|
|
|
|
friend llvm::hash_code hash_value(const ClangDirectLookupDescriptor &desc) {
|
|
return llvm::hash_combine(desc.name, desc.decl, desc.clangDecl);
|
|
}
|
|
|
|
friend bool operator==(const ClangDirectLookupDescriptor &lhs,
|
|
const ClangDirectLookupDescriptor &rhs) {
|
|
return lhs.name == rhs.name && lhs.decl == rhs.decl &&
|
|
lhs.clangDecl == rhs.clangDecl;
|
|
}
|
|
|
|
friend bool operator!=(const ClangDirectLookupDescriptor &lhs,
|
|
const ClangDirectLookupDescriptor &rhs) {
|
|
return !(lhs == rhs);
|
|
}
|
|
};
|
|
|
|
void simple_display(llvm::raw_ostream &out,
|
|
const ClangDirectLookupDescriptor &desc);
|
|
SourceLoc extractNearestSourceLoc(const ClangDirectLookupDescriptor &desc);
|
|
|
|
/// This matches SwiftLookupTable::SingleEntry;
|
|
using SingleEntry = llvm::PointerUnion<clang::NamedDecl *, clang::MacroInfo *,
|
|
clang::ModuleMacro *>;
|
|
/// Uses the appropriate SwiftLookupTable to find a set of clang decls given
|
|
/// their name.
|
|
class ClangDirectLookupRequest
|
|
: public SimpleRequest<ClangDirectLookupRequest,
|
|
SmallVector<SingleEntry, 4>(
|
|
ClangDirectLookupDescriptor),
|
|
RequestFlags::Uncached> {
|
|
public:
|
|
using SimpleRequest::SimpleRequest;
|
|
|
|
private:
|
|
friend SimpleRequest;
|
|
|
|
// Evaluation.
|
|
SmallVector<SingleEntry, 4> evaluate(Evaluator &evaluator,
|
|
ClangDirectLookupDescriptor desc) const;
|
|
};
|
|
|
|
/// The input type for a namespace member lookup request.
|
|
struct CXXNamespaceMemberLookupDescriptor final {
|
|
EnumDecl *namespaceDecl;
|
|
DeclName name;
|
|
|
|
CXXNamespaceMemberLookupDescriptor(EnumDecl *namespaceDecl, DeclName name)
|
|
: namespaceDecl(namespaceDecl), name(name) {
|
|
assert(isa<clang::NamespaceDecl>(namespaceDecl->getClangDecl()));
|
|
}
|
|
|
|
friend llvm::hash_code
|
|
hash_value(const CXXNamespaceMemberLookupDescriptor &desc) {
|
|
return llvm::hash_combine(desc.name, desc.namespaceDecl);
|
|
}
|
|
|
|
friend bool operator==(const CXXNamespaceMemberLookupDescriptor &lhs,
|
|
const CXXNamespaceMemberLookupDescriptor &rhs) {
|
|
return lhs.name == rhs.name && lhs.namespaceDecl == rhs.namespaceDecl;
|
|
}
|
|
|
|
friend bool operator!=(const CXXNamespaceMemberLookupDescriptor &lhs,
|
|
const CXXNamespaceMemberLookupDescriptor &rhs) {
|
|
return !(lhs == rhs);
|
|
}
|
|
};
|
|
|
|
void simple_display(llvm::raw_ostream &out,
|
|
const CXXNamespaceMemberLookupDescriptor &desc);
|
|
SourceLoc
|
|
extractNearestSourceLoc(const CXXNamespaceMemberLookupDescriptor &desc);
|
|
|
|
/// Uses ClangDirectLookup to find a named member inside of the given namespace.
|
|
class CXXNamespaceMemberLookup
|
|
: public SimpleRequest<CXXNamespaceMemberLookup,
|
|
TinyPtrVector<ValueDecl *>(
|
|
CXXNamespaceMemberLookupDescriptor),
|
|
RequestFlags::Uncached> {
|
|
public:
|
|
using SimpleRequest::SimpleRequest;
|
|
|
|
private:
|
|
friend SimpleRequest;
|
|
|
|
// Evaluation.
|
|
TinyPtrVector<ValueDecl *>
|
|
evaluate(Evaluator &evaluator, CXXNamespaceMemberLookupDescriptor desc) const;
|
|
};
|
|
|
|
/// The input type for a record member lookup request.
|
|
///
|
|
/// These lookups may be requested recursively in the case of inheritance,
|
|
/// for which we separately keep track of the derived class where we started
|
|
/// looking (startDecl) and the access level for the current inheritance.
|
|
struct ClangRecordMemberLookupDescriptor final {
|
|
NominalTypeDecl *recordDecl; // Where we are currently looking
|
|
NominalTypeDecl *inheritingDecl; // Where we started looking from
|
|
DeclName name; // What we are looking for
|
|
ClangInheritanceInfo inheritance;
|
|
|
|
ClangRecordMemberLookupDescriptor(NominalTypeDecl *recordDecl, DeclName name)
|
|
: recordDecl(recordDecl), inheritingDecl(recordDecl), name(name),
|
|
inheritance() {
|
|
assert(isa<clang::RecordDecl>(recordDecl->getClangDecl()));
|
|
}
|
|
|
|
friend llvm::hash_code
|
|
hash_value(const ClangRecordMemberLookupDescriptor &desc) {
|
|
return llvm::hash_combine(desc.name, desc.recordDecl, desc.inheritingDecl,
|
|
desc.inheritance);
|
|
}
|
|
|
|
friend bool operator==(const ClangRecordMemberLookupDescriptor &lhs,
|
|
const ClangRecordMemberLookupDescriptor &rhs) {
|
|
return lhs.name == rhs.name && lhs.recordDecl == rhs.recordDecl &&
|
|
lhs.inheritingDecl == rhs.inheritingDecl &&
|
|
lhs.inheritance == rhs.inheritance;
|
|
}
|
|
|
|
friend bool operator!=(const ClangRecordMemberLookupDescriptor &lhs,
|
|
const ClangRecordMemberLookupDescriptor &rhs) {
|
|
return !(lhs == rhs);
|
|
}
|
|
|
|
private:
|
|
friend class ClangRecordMemberLookup;
|
|
|
|
// This private constructor should only be used in ClangRecordMemberLookup,
|
|
// for recursively traversing base classes that inheritingDecl inherites from.
|
|
ClangRecordMemberLookupDescriptor(NominalTypeDecl *recordDecl, DeclName name,
|
|
NominalTypeDecl *inheritingDecl,
|
|
ClangInheritanceInfo inheritance)
|
|
: recordDecl(recordDecl), inheritingDecl(inheritingDecl), name(name),
|
|
inheritance(inheritance) {
|
|
assert(isa<clang::RecordDecl>(recordDecl->getClangDecl()));
|
|
assert(isa<clang::CXXRecordDecl>(inheritingDecl->getClangDecl()));
|
|
assert(inheritance.isInheriting() &&
|
|
"recursive calls should indicate inheritance");
|
|
assert(recordDecl != inheritingDecl &&
|
|
"recursive calls should lookup elsewhere");
|
|
}
|
|
};
|
|
|
|
void simple_display(llvm::raw_ostream &out,
|
|
const ClangRecordMemberLookupDescriptor &desc);
|
|
SourceLoc
|
|
extractNearestSourceLoc(const ClangRecordMemberLookupDescriptor &desc);
|
|
|
|
/// Uses ClangDirectLookup to find a named member inside of the given record.
|
|
class ClangRecordMemberLookup
|
|
: public SimpleRequest<ClangRecordMemberLookup,
|
|
TinyPtrVector<ValueDecl *>(
|
|
ClangRecordMemberLookupDescriptor),
|
|
RequestFlags::Uncached> {
|
|
public:
|
|
using SimpleRequest::SimpleRequest;
|
|
|
|
private:
|
|
friend SimpleRequest;
|
|
|
|
// Evaluation.
|
|
TinyPtrVector<ValueDecl *>
|
|
evaluate(Evaluator &evaluator, ClangRecordMemberLookupDescriptor desc) const;
|
|
};
|
|
|
|
/// The input type for a clang category lookup request.
|
|
struct ClangCategoryLookupDescriptor final {
|
|
const ClassDecl *classDecl;
|
|
Identifier categoryName;
|
|
|
|
ClangCategoryLookupDescriptor(const ClassDecl *classDecl,
|
|
Identifier categoryName)
|
|
: classDecl(classDecl), categoryName(categoryName) {}
|
|
|
|
friend llvm::hash_code hash_value(const ClangCategoryLookupDescriptor &desc) {
|
|
return llvm::hash_combine(desc.classDecl, desc.categoryName);
|
|
}
|
|
|
|
friend bool operator==(const ClangCategoryLookupDescriptor &lhs,
|
|
const ClangCategoryLookupDescriptor &rhs) {
|
|
return lhs.classDecl == rhs.classDecl
|
|
&& lhs.categoryName == rhs.categoryName;
|
|
}
|
|
|
|
friend bool operator!=(const ClangCategoryLookupDescriptor &lhs,
|
|
const ClangCategoryLookupDescriptor &rhs) {
|
|
return !(lhs == rhs);
|
|
}
|
|
};
|
|
|
|
void simple_display(llvm::raw_ostream &out,
|
|
const ClangCategoryLookupDescriptor &desc);
|
|
SourceLoc extractNearestSourceLoc(const ClangCategoryLookupDescriptor &desc);
|
|
|
|
/// Given a Swift class, find the imported Swift decl(s) representing the
|
|
/// \c \@interface with the given category name. An empty \c categoryName
|
|
/// represents the main interface for the class.
|
|
///
|
|
/// That is, this request will return one of:
|
|
///
|
|
/// \li a single \c swift::ExtensionDecl backed by a \c clang::ObjCCategoryDecl
|
|
/// \li a \c swift::ClassDecl backed by a \c clang::ObjCInterfaceDecl, plus
|
|
/// zero or more \c swift::ExtensionDecl s backed by
|
|
/// \c clang::ObjCCategoryDecl s (representing ObjC class extensions).
|
|
/// \li an empty list if the class is not imported from Clang or it does not
|
|
/// have a category by that name.
|
|
class ClangCategoryLookupRequest
|
|
: public SimpleRequest<ClangCategoryLookupRequest,
|
|
TinyPtrVector<Decl *>(ClangCategoryLookupDescriptor),
|
|
RequestFlags::Uncached> {
|
|
public:
|
|
using SimpleRequest::SimpleRequest;
|
|
|
|
private:
|
|
friend SimpleRequest;
|
|
|
|
// Evaluation.
|
|
TinyPtrVector<Decl *> evaluate(Evaluator &evaluator,
|
|
ClangCategoryLookupDescriptor desc) const;
|
|
};
|
|
|
|
/// Links an \c \@_objcImplementation decl to the imported declaration(s) that
|
|
/// it implements.
|
|
///
|
|
/// There is usually a 1:1 correspondence between interfaces and
|
|
/// implementations, except that a class's main implementation implements
|
|
/// both its main interface and any class extension interfaces. In this
|
|
/// situation, the main class is always the first decl in \c interfaceDecls.
|
|
struct ObjCInterfaceAndImplementation final {
|
|
llvm::TinyPtrVector<Decl *> interfaceDecls;
|
|
Decl *implementationDecl;
|
|
|
|
ObjCInterfaceAndImplementation(llvm::TinyPtrVector<Decl *> interfaceDecls,
|
|
Decl *implementationDecl)
|
|
: interfaceDecls(interfaceDecls), implementationDecl(implementationDecl)
|
|
{
|
|
assert(!interfaceDecls.empty() && implementationDecl &&
|
|
"interface and implementation are both non-null");
|
|
}
|
|
|
|
ObjCInterfaceAndImplementation()
|
|
: interfaceDecls(), implementationDecl(nullptr) {}
|
|
|
|
bool empty() const {
|
|
return interfaceDecls.empty();
|
|
}
|
|
|
|
friend llvm::hash_code
|
|
hash_value(const ObjCInterfaceAndImplementation &pair) {
|
|
return hash_combine(llvm::hash_combine_range(pair.interfaceDecls.begin(),
|
|
pair.interfaceDecls.end()),
|
|
pair.implementationDecl);
|
|
}
|
|
|
|
friend bool operator==(const ObjCInterfaceAndImplementation &lhs,
|
|
const ObjCInterfaceAndImplementation &rhs) {
|
|
return lhs.interfaceDecls == rhs.interfaceDecls
|
|
&& lhs.implementationDecl == rhs.implementationDecl;
|
|
}
|
|
|
|
friend bool operator!=(const ObjCInterfaceAndImplementation &lhs,
|
|
const ObjCInterfaceAndImplementation &rhs) {
|
|
return !(lhs == rhs);
|
|
}
|
|
};
|
|
|
|
void simple_display(llvm::raw_ostream &out,
|
|
const ObjCInterfaceAndImplementation &desc);
|
|
SourceLoc extractNearestSourceLoc(const ObjCInterfaceAndImplementation &desc);
|
|
|
|
/// Given a \c Decl , determine if it is an implementation with separate
|
|
/// interfaces imported from ObjC (or vice versa) and if so, return all of the
|
|
/// declarations involved in this relationship. Otherwise return an empty value.
|
|
///
|
|
/// We perform this lookup in both directions using a single request because
|
|
/// we want to cache the relationship on both sides to avoid duplicating work.
|
|
class ObjCInterfaceAndImplementationRequest
|
|
: public SimpleRequest<ObjCInterfaceAndImplementationRequest,
|
|
ObjCInterfaceAndImplementation(Decl *),
|
|
RequestFlags::SeparatelyCached> {
|
|
public:
|
|
using SimpleRequest::SimpleRequest;
|
|
|
|
private:
|
|
friend SimpleRequest;
|
|
|
|
// Evaluation.
|
|
ObjCInterfaceAndImplementation
|
|
evaluate(Evaluator &evaluator, Decl *decl) const;
|
|
|
|
public:
|
|
// Separate caching.
|
|
bool isCached() const { return true; }
|
|
std::optional<ObjCInterfaceAndImplementation> getCachedResult() const;
|
|
void cacheResult(ObjCInterfaceAndImplementation value) const;
|
|
};
|
|
|
|
enum class CxxRecordSemanticsKind {
|
|
Trivial,
|
|
Owned,
|
|
MoveOnly,
|
|
Reference,
|
|
Iterator,
|
|
// A record that is either not copyable/movable or not destructible.
|
|
MissingLifetimeOperation,
|
|
// A record that has no copy and no move operations
|
|
UnavailableConstructors,
|
|
// A C++ record that represents a Swift class type exposed to C++ from Swift.
|
|
SwiftClassType
|
|
};
|
|
|
|
struct CxxRecordSemanticsDescriptor final {
|
|
const clang::RecordDecl *decl;
|
|
ASTContext &ctx;
|
|
ClangImporter::Implementation *importerImpl;
|
|
|
|
/// Whether to emit warnings for missing destructor or copy constructor
|
|
/// whenever the classification of the type assumes that they exist (e.g. for
|
|
/// a value type).
|
|
bool shouldDiagnoseLifetimeOperations;
|
|
|
|
CxxRecordSemanticsDescriptor(const clang::RecordDecl *decl, ASTContext &ctx,
|
|
ClangImporter::Implementation *importerImpl,
|
|
bool shouldDiagnoseLifetimeOperations = true)
|
|
: decl(decl), ctx(ctx), importerImpl(importerImpl),
|
|
shouldDiagnoseLifetimeOperations(shouldDiagnoseLifetimeOperations) {}
|
|
|
|
friend llvm::hash_code hash_value(const CxxRecordSemanticsDescriptor &desc) {
|
|
return llvm::hash_combine(desc.decl);
|
|
}
|
|
|
|
friend bool operator==(const CxxRecordSemanticsDescriptor &lhs,
|
|
const CxxRecordSemanticsDescriptor &rhs) {
|
|
return lhs.decl == rhs.decl;
|
|
}
|
|
|
|
friend bool operator!=(const CxxRecordSemanticsDescriptor &lhs,
|
|
const CxxRecordSemanticsDescriptor &rhs) {
|
|
return !(lhs == rhs);
|
|
}
|
|
};
|
|
|
|
void simple_display(llvm::raw_ostream &out, CxxRecordSemanticsDescriptor desc);
|
|
SourceLoc extractNearestSourceLoc(CxxRecordSemanticsDescriptor desc);
|
|
|
|
/// What pattern does this C++ API fit? Uses attributes such as
|
|
/// import_owned and import_reference to determine the pattern.
|
|
///
|
|
/// Do not evaluate this request before importing has started. For example, it
|
|
/// is OK to invoke this request when importing a decl, but it is not OK to
|
|
/// evaluate this request when importing names. This is because when importing
|
|
/// names, Clang sema has not yet defined implicit special members, so the
|
|
/// results will be flakey/incorrect.
|
|
class CxxRecordSemantics
|
|
: public SimpleRequest<CxxRecordSemantics,
|
|
CxxRecordSemanticsKind(CxxRecordSemanticsDescriptor),
|
|
RequestFlags::Uncached> {
|
|
public:
|
|
using SimpleRequest::SimpleRequest;
|
|
|
|
// Source location
|
|
SourceLoc getNearestLoc() const { return SourceLoc(); };
|
|
|
|
private:
|
|
friend SimpleRequest;
|
|
|
|
// Evaluation.
|
|
CxxRecordSemanticsKind evaluate(Evaluator &evaluator,
|
|
CxxRecordSemanticsDescriptor) const;
|
|
};
|
|
|
|
/// Does this C++ record represent a Swift type.
|
|
class CxxRecordAsSwiftType
|
|
: public SimpleRequest<CxxRecordAsSwiftType,
|
|
ValueDecl *(CxxRecordSemanticsDescriptor),
|
|
RequestFlags::Uncached> {
|
|
public:
|
|
using SimpleRequest::SimpleRequest;
|
|
|
|
// Source location
|
|
SourceLoc getNearestLoc() const { return SourceLoc(); };
|
|
|
|
private:
|
|
friend SimpleRequest;
|
|
|
|
ValueDecl *evaluate(Evaluator &evaluator, CxxRecordSemanticsDescriptor) const;
|
|
};
|
|
|
|
struct SafeUseOfCxxDeclDescriptor final {
|
|
const clang::Decl *decl;
|
|
|
|
SafeUseOfCxxDeclDescriptor(const clang::Decl *decl) : decl(decl) {}
|
|
|
|
friend llvm::hash_code hash_value(const SafeUseOfCxxDeclDescriptor &desc) {
|
|
return llvm::hash_combine(desc.decl);
|
|
}
|
|
|
|
friend bool operator==(const SafeUseOfCxxDeclDescriptor &lhs,
|
|
const SafeUseOfCxxDeclDescriptor &rhs) {
|
|
return lhs.decl == rhs.decl;
|
|
}
|
|
|
|
friend bool operator!=(const SafeUseOfCxxDeclDescriptor &lhs,
|
|
const SafeUseOfCxxDeclDescriptor &rhs) {
|
|
return !(lhs == rhs);
|
|
}
|
|
};
|
|
|
|
void simple_display(llvm::raw_ostream &out, SafeUseOfCxxDeclDescriptor desc);
|
|
SourceLoc extractNearestSourceLoc(SafeUseOfCxxDeclDescriptor desc);
|
|
|
|
class IsSafeUseOfCxxDecl
|
|
: public SimpleRequest<IsSafeUseOfCxxDecl, bool(SafeUseOfCxxDeclDescriptor),
|
|
RequestFlags::Uncached> {
|
|
public:
|
|
using SimpleRequest::SimpleRequest;
|
|
|
|
// Source location
|
|
SourceLoc getNearestLoc() const { return SourceLoc(); };
|
|
|
|
private:
|
|
friend SimpleRequest;
|
|
|
|
// Evaluation.
|
|
bool evaluate(Evaluator &evaluator, SafeUseOfCxxDeclDescriptor desc) const;
|
|
};
|
|
|
|
enum class CustomRefCountingOperationKind { retain, release };
|
|
|
|
struct CustomRefCountingOperationDescriptor final {
|
|
const ClassDecl *decl;
|
|
CustomRefCountingOperationKind kind;
|
|
|
|
CustomRefCountingOperationDescriptor(const ClassDecl *decl,
|
|
CustomRefCountingOperationKind kind)
|
|
: decl(decl), kind(kind) {}
|
|
|
|
friend llvm::hash_code
|
|
hash_value(const CustomRefCountingOperationDescriptor &desc) {
|
|
return llvm::hash_combine(desc.decl, desc.kind);
|
|
}
|
|
|
|
friend bool operator==(const CustomRefCountingOperationDescriptor &lhs,
|
|
const CustomRefCountingOperationDescriptor &rhs) {
|
|
return lhs.decl == rhs.decl && lhs.kind == rhs.kind;
|
|
}
|
|
|
|
friend bool operator!=(const CustomRefCountingOperationDescriptor &lhs,
|
|
const CustomRefCountingOperationDescriptor &rhs) {
|
|
return !(lhs == rhs);
|
|
}
|
|
};
|
|
|
|
void simple_display(llvm::raw_ostream &out,
|
|
CustomRefCountingOperationDescriptor desc);
|
|
SourceLoc extractNearestSourceLoc(CustomRefCountingOperationDescriptor desc);
|
|
|
|
struct CustomRefCountingOperationResult {
|
|
enum CustomRefCountingOperationResultKind {
|
|
noAttribute,
|
|
tooManyAttributes,
|
|
immortal,
|
|
notFound,
|
|
tooManyFound,
|
|
foundOperation
|
|
};
|
|
|
|
CustomRefCountingOperationResultKind kind;
|
|
ValueDecl *operation;
|
|
std::string name;
|
|
};
|
|
|
|
class CustomRefCountingOperation
|
|
: public SimpleRequest<CustomRefCountingOperation,
|
|
CustomRefCountingOperationResult(
|
|
CustomRefCountingOperationDescriptor),
|
|
RequestFlags::Cached> {
|
|
public:
|
|
using SimpleRequest::SimpleRequest;
|
|
|
|
// Caching
|
|
bool isCached() const { return true; }
|
|
|
|
// Source location
|
|
SourceLoc getNearestLoc() const { return SourceLoc(); };
|
|
|
|
private:
|
|
friend SimpleRequest;
|
|
|
|
// Evaluation.
|
|
CustomRefCountingOperationResult
|
|
evaluate(Evaluator &evaluator,
|
|
CustomRefCountingOperationDescriptor desc) const;
|
|
};
|
|
|
|
enum class CxxEscapability { Escapable, NonEscapable, Unknown };
|
|
|
|
struct EscapabilityLookupDescriptor final {
|
|
const clang::Type *type;
|
|
ClangImporter::Implementation *impl;
|
|
bool annotationOnly = true;
|
|
|
|
friend llvm::hash_code hash_value(const EscapabilityLookupDescriptor &desc) {
|
|
return llvm::hash_combine(desc.type);
|
|
}
|
|
|
|
friend bool operator==(const EscapabilityLookupDescriptor &lhs,
|
|
const EscapabilityLookupDescriptor &rhs) {
|
|
return lhs.type == rhs.type && lhs.annotationOnly == rhs.annotationOnly;
|
|
}
|
|
|
|
friend bool operator!=(const EscapabilityLookupDescriptor &lhs,
|
|
const EscapabilityLookupDescriptor &rhs) {
|
|
return !(lhs == rhs);
|
|
}
|
|
};
|
|
|
|
class ClangTypeEscapability
|
|
: public SimpleRequest<ClangTypeEscapability,
|
|
CxxEscapability(EscapabilityLookupDescriptor),
|
|
RequestFlags::Cached> {
|
|
public:
|
|
using SimpleRequest::SimpleRequest;
|
|
|
|
bool isCached() const { return true; }
|
|
|
|
private:
|
|
friend SimpleRequest;
|
|
|
|
CxxEscapability evaluate(Evaluator &evaluator,
|
|
EscapabilityLookupDescriptor desc) const;
|
|
};
|
|
|
|
void simple_display(llvm::raw_ostream &out, EscapabilityLookupDescriptor desc);
|
|
SourceLoc extractNearestSourceLoc(EscapabilityLookupDescriptor desc);
|
|
|
|
/// Determine the safety of the given Clang declaration.
|
|
class ClangDeclExplicitSafety
|
|
: public SimpleRequest<ClangDeclExplicitSafety,
|
|
ExplicitSafety(SafeUseOfCxxDeclDescriptor),
|
|
RequestFlags::Cached> {
|
|
public:
|
|
using SimpleRequest::SimpleRequest;
|
|
|
|
// Source location
|
|
SourceLoc getNearestLoc() const { return SourceLoc(); };
|
|
bool isCached() const;
|
|
|
|
private:
|
|
friend SimpleRequest;
|
|
|
|
// Evaluation.
|
|
ExplicitSafety evaluate(Evaluator &evaluator, SafeUseOfCxxDeclDescriptor desc) const;
|
|
};
|
|
|
|
#define SWIFT_TYPEID_ZONE ClangImporter
|
|
#define SWIFT_TYPEID_HEADER "swift/ClangImporter/ClangImporterTypeIDZone.def"
|
|
#include "swift/Basic/DefineTypeIDZone.h"
|
|
#undef SWIFT_TYPEID_ZONE
|
|
#undef SWIFT_TYPEID_HEADER
|
|
|
|
// Set up reporting of evaluated requests.
|
|
template<typename Request>
|
|
void reportEvaluatedRequest(UnifiedStatsReporter &stats,
|
|
const Request &request);
|
|
|
|
#define SWIFT_REQUEST(Zone, RequestType, Sig, Caching, LocOptions) \
|
|
template <> \
|
|
inline void reportEvaluatedRequest(UnifiedStatsReporter &stats, \
|
|
const RequestType &request) { \
|
|
++stats.getFrontendCounters().RequestType; \
|
|
}
|
|
#include "swift/ClangImporter/ClangImporterTypeIDZone.def"
|
|
#undef SWIFT_REQUEST
|
|
|
|
} // end namespace swift
|
|
|
|
#endif // SWIFT_CLANG_IMPORTER_REQUESTS_H
|
|
|