mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Record Objective-C method lookup tables in Swift modules.
Include a mapping from Objective-C selectors to the @objc methods that
produce Objective-c methods with those selectors. Use this to lazily
populate the Objective-C method lookup tables in each class. This makes
@objc override checking work across Swift modules, which is part of
rdar://problem/18391046.
Note that we use a single, unified selector table, both because it is
simpler and because it makes global queries ("is there any method with
the given selector?") easier.
Swift SVN r23214
This commit is contained in:
@@ -530,6 +530,31 @@ public:
|
||||
/// one.
|
||||
void loadExtensions(NominalTypeDecl *nominal, unsigned previousGeneration);
|
||||
|
||||
/// \brief Load the methods within the given class that that produce
|
||||
/// Objective-C class or instance methods with the given selector.
|
||||
///
|
||||
/// \param classDecl The class in which we are searching for @objc methods.
|
||||
/// The search only considers this class and its extensions; not any
|
||||
/// superclasses.
|
||||
///
|
||||
/// \param selector The selector to search for.
|
||||
///
|
||||
/// \param isInstanceMethod Whether we are looking for an instance method
|
||||
/// (vs. a class method).
|
||||
///
|
||||
/// \param previousGeneration The previous generation with which this
|
||||
/// callback was invoked. The list of methods will already contain all of
|
||||
/// the results from generations up and and including \c previousGeneration.
|
||||
///
|
||||
/// \param methods The list of @objc methods in this class that have this
|
||||
/// selector and are instance/class methods as requested. This list will be
|
||||
/// extended with any methods found in subsequent generations.
|
||||
void loadObjCMethods(ClassDecl *classDecl,
|
||||
ObjCSelector selector,
|
||||
bool isInstanceMethod,
|
||||
unsigned previousGeneration,
|
||||
llvm::TinyPtrVector<AbstractFunctionDecl *> &methods);
|
||||
|
||||
/// \brief Retrieve the Clang module loader for this ASTContext.
|
||||
///
|
||||
/// If there is no Clang module loader, returns a null pointer.
|
||||
|
||||
@@ -2996,8 +2996,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class ObjCMethodLookupTable;
|
||||
|
||||
/// ClassDecl - This is the declaration of a class, for example:
|
||||
///
|
||||
/// class Complex { var R : Double, I : Double }
|
||||
@@ -3005,6 +3003,8 @@ class ObjCMethodLookupTable;
|
||||
/// The type of the decl itself is a MetatypeType; use getDeclaredType()
|
||||
/// to get the declared type ("Complex" in the above example).
|
||||
class ClassDecl : public NominalTypeDecl {
|
||||
class ObjCMethodLookupTable;
|
||||
|
||||
SourceLoc ClassLoc;
|
||||
Type Superclass;
|
||||
ObjCMethodLookupTable *ObjCMethodLookup = nullptr;
|
||||
|
||||
@@ -441,12 +441,35 @@ public:
|
||||
LLVM_ATTRIBUTE_DEPRECATED(void dump() const,
|
||||
"only for use within the debugger");
|
||||
|
||||
/// Compare two Objective-C selectors, producing -1 if \c *this comes before
|
||||
/// \c other, 1 if \c *this comes after \c other, and 0 if they are equal.
|
||||
int compare(ObjCSelector other) const {
|
||||
return Storage.compare(other.Storage);
|
||||
}
|
||||
|
||||
friend bool operator==(ObjCSelector lhs, ObjCSelector rhs) {
|
||||
return lhs.getOpaqueValue() == rhs.getOpaqueValue();
|
||||
}
|
||||
|
||||
friend bool operator!=(ObjCSelector lhs, ObjCSelector rhs) {
|
||||
return lhs.getOpaqueValue() != rhs.getOpaqueValue();
|
||||
}
|
||||
|
||||
friend bool operator<(ObjCSelector lhs, ObjCSelector rhs) {
|
||||
return lhs.compare(rhs) < 0;
|
||||
}
|
||||
|
||||
friend bool operator<=(ObjCSelector lhs, ObjCSelector rhs) {
|
||||
return lhs.compare(lhs) <= 0;
|
||||
}
|
||||
|
||||
friend bool operator>(ObjCSelector lhs, ObjCSelector rhs) {
|
||||
return lhs.compare(lhs) > 0;
|
||||
}
|
||||
|
||||
friend bool operator>=(ObjCSelector lhs, ObjCSelector rhs) {
|
||||
return lhs.compare(lhs) >= 0;
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace swift
|
||||
|
||||
@@ -20,9 +20,12 @@
|
||||
#include "swift/AST/Identifier.h"
|
||||
#include "swift/Basic/LLVM.h"
|
||||
#include "swift/Basic/SourceLoc.h"
|
||||
#include "llvm/ADT/TinyPtrVector.h"
|
||||
|
||||
namespace swift {
|
||||
|
||||
class AbstractFunctionDecl;
|
||||
class ClassDecl;
|
||||
class Module;
|
||||
class NominalTypeDecl;
|
||||
|
||||
@@ -76,6 +79,32 @@ public:
|
||||
virtual void loadExtensions(NominalTypeDecl *nominal,
|
||||
unsigned previousGeneration) { }
|
||||
|
||||
/// \brief Load the methods within the given class that that produce
|
||||
/// Objective-C class or instance methods with the given selector.
|
||||
///
|
||||
/// \param classDecl The class in which we are searching for @objc methods.
|
||||
/// The search only considers this class and its extensions; not any
|
||||
/// superclasses.
|
||||
///
|
||||
/// \param selector The selector to search for.
|
||||
///
|
||||
/// \param isInstanceMethod Whether we are looking for an instance method
|
||||
/// (vs. a class method).
|
||||
///
|
||||
/// \param previousGeneration The previous generation with which this
|
||||
/// callback was invoked. The list of methods will already contain all of
|
||||
/// the results from generations up and and including \c previousGeneration.
|
||||
///
|
||||
/// \param methods The list of @objc methods in this class that have this
|
||||
/// selector and are instance/class methods as requested. This list will be
|
||||
/// extended with any methods found in subsequent generations.
|
||||
virtual void loadObjCMethods(
|
||||
ClassDecl *classDecl,
|
||||
ObjCSelector selector,
|
||||
bool isInstanceMethod,
|
||||
unsigned previousGeneration,
|
||||
llvm::TinyPtrVector<AbstractFunctionDecl *> &methods) { }
|
||||
|
||||
/// \brief Verify all modules loaded by this loader.
|
||||
virtual void verifyAllModules() { }
|
||||
};
|
||||
|
||||
@@ -252,6 +252,12 @@ private:
|
||||
std::unique_ptr<SerializedDeclTable> ClassMembersByName;
|
||||
std::unique_ptr<SerializedDeclTable> OperatorMethodDecls;
|
||||
|
||||
class ObjCMethodTableInfo;
|
||||
using SerializedObjCMethodTable =
|
||||
llvm::OnDiskIterableChainedHashTable<ObjCMethodTableInfo>;
|
||||
|
||||
std::unique_ptr<SerializedObjCMethodTable> ObjCMethods;
|
||||
|
||||
llvm::DenseMap<const ValueDecl *, Identifier> PrivateDiscriminatorsByValue;
|
||||
|
||||
TinyPtrVector<Decl *> ImportDecls;
|
||||
@@ -323,6 +329,11 @@ private:
|
||||
std::unique_ptr<SerializedDeclTable>
|
||||
readDeclTable(ArrayRef<uint64_t> fields, StringRef blobData);
|
||||
|
||||
/// Read an on-disk Objective-C method table stored in
|
||||
/// index_block::ObjCMethodTableLayout format.
|
||||
std::unique_ptr<ModuleFile::SerializedObjCMethodTable>
|
||||
readObjCMethodTable(ArrayRef<uint64_t> fields, StringRef blobData);
|
||||
|
||||
/// Reads the index block, which contains global tables.
|
||||
///
|
||||
/// Returns false if there was an error.
|
||||
@@ -450,6 +461,25 @@ public:
|
||||
/// Note that this may cause other decls to load as well.
|
||||
void loadExtensions(NominalTypeDecl *nominal);
|
||||
|
||||
/// \brief Load the methods within the given class that that produce
|
||||
/// Objective-C class or instance methods with the given selector.
|
||||
///
|
||||
/// \param classDecl The class in which we are searching for @objc methods.
|
||||
/// The search only considers this class and its extensions; not any
|
||||
/// superclasses.
|
||||
///
|
||||
/// \param selector The selector to search for.
|
||||
///
|
||||
/// \param isInstanceMethod Whether we are looking for an instance method
|
||||
/// (vs. a class method).
|
||||
///
|
||||
/// \param methods The list of @objc methods in this class that have this
|
||||
/// selector and are instance/class methods as requested.
|
||||
void loadObjCMethods(ClassDecl *classDecl,
|
||||
ObjCSelector selector,
|
||||
bool isInstanceMethod,
|
||||
llvm::TinyPtrVector<AbstractFunctionDecl *> &methods);
|
||||
|
||||
/// Reports all class members in the module to the given consumer.
|
||||
///
|
||||
/// This is intended for use with id-style lookup and code completion.
|
||||
|
||||
@@ -51,7 +51,7 @@ const uint16_t VERSION_MAJOR = 0;
|
||||
/// To ensure that two separate changes don't silently get merged into one
|
||||
/// in source control, you should also update the comment to briefly
|
||||
/// describe what change you made.
|
||||
const uint16_t VERSION_MINOR = 158; // Last change: objc decl attribute
|
||||
const uint16_t VERSION_MINOR = 159; // Last change: objc method3 table
|
||||
|
||||
using DeclID = Fixnum<31>;
|
||||
using DeclIDField = BCFixed<31>;
|
||||
@@ -328,7 +328,7 @@ enum BlockID {
|
||||
/// The comment block, which contains documentation comments.
|
||||
///
|
||||
/// \sa comment_block
|
||||
COMMENT_BLOCK_ID,
|
||||
COMMENT_BLOCK_ID
|
||||
};
|
||||
|
||||
/// The record types within the control block.
|
||||
@@ -1210,7 +1210,12 @@ namespace index_block {
|
||||
OPERATORS,
|
||||
EXTENSIONS,
|
||||
CLASS_MEMBERS,
|
||||
OPERATOR_METHODS
|
||||
OPERATOR_METHODS,
|
||||
|
||||
/// The Objective-C method index, which contains a mapping from
|
||||
/// Objective-C selectors to the methods/initializers/properties/etc. that
|
||||
/// produce Objective-C methods.
|
||||
OBJC_METHODS,
|
||||
};
|
||||
|
||||
using OffsetsLayout = BCGenericRecordLayout<
|
||||
@@ -1223,6 +1228,12 @@ namespace index_block {
|
||||
BCVBR<16>, // table offset within the blob (see below)
|
||||
BCBlob // map from identifier strings to decl kinds / decl IDs
|
||||
>;
|
||||
|
||||
using ObjCMethodTableLayout = BCRecordLayout<
|
||||
OBJC_METHODS, // record ID
|
||||
BCVBR<16>, // table offset within the blob (see below)
|
||||
BCBlob // map from Objective-C selectors to methods with that selector
|
||||
>;
|
||||
}
|
||||
|
||||
/// \sa COMMENT_BLOCK_ID
|
||||
|
||||
@@ -113,6 +113,13 @@ public:
|
||||
virtual void loadExtensions(NominalTypeDecl *nominal,
|
||||
unsigned previousGeneration) override;
|
||||
|
||||
virtual void loadObjCMethods(
|
||||
ClassDecl *classDecl,
|
||||
ObjCSelector selector,
|
||||
bool isInstanceMethod,
|
||||
unsigned previousGeneration,
|
||||
llvm::TinyPtrVector<AbstractFunctionDecl *> &methods);
|
||||
|
||||
/// Returns true if the data looks like it contains a serialized AST.
|
||||
static bool isSerializedAST(StringRef data);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user