Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
161 changes: 143 additions & 18 deletions include/swift/SIL/AbstractionPattern.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@ namespace llvm {
}

namespace clang {
class ValueDecl;
class CXXMethodDecl;
class ObjCMethodDecl;
class Type;
class ValueDecl;
}

namespace swift {
Expand Down Expand Up @@ -178,6 +179,15 @@ class AbstractionPattern {
/// type. ObjCMethod is valid. OtherData is an encoded foreign
/// error index.
ObjCMethodType,
/// The uncurried imported type of a C++ method. OrigType is valid and is a
/// function type. CXXMethod is valid.
CXXMethodType,
/// The curried imported type of a C++ method. OrigType is valid and is a
/// function type. CXXMethod is valid.
CurriedCXXMethodType,
/// The partially-applied curried imported type of a C++ method. OrigType is
/// valid and is a function type. CXXMethod is valid.
PartialCurriedCXXMethodType,
};

class EncodedForeignErrorInfo {
Expand Down Expand Up @@ -234,6 +244,7 @@ class AbstractionPattern {
union {
const clang::Type *ClangType;
const clang::ObjCMethodDecl *ObjCMethod;
const clang::CXXMethodDecl *CXXMethod;
const AbstractionPattern *OrigTupleElements;
};
CanGenericSignature GenericSig;
Expand Down Expand Up @@ -266,6 +277,18 @@ class AbstractionPattern {
}
}

bool hasStoredCXXMethod() const {
switch (getKind()) {
case Kind::CXXMethodType:
case Kind::CurriedCXXMethodType:
case Kind::PartialCurriedCXXMethodType:
return true;

default:
return false;
}
}

bool hasStoredObjCMethod() const {
switch (getKind()) {
case Kind::CurriedObjCMethodType:
Expand Down Expand Up @@ -327,6 +350,12 @@ class AbstractionPattern {
OtherData = memberStatus.getRawValue();
}

void initCXXMethod(CanGenericSignature signature, CanType origType,
const clang::CXXMethodDecl *method, Kind kind) {
initSwiftType(signature, origType, kind);
CXXMethod = method;
}

AbstractionPattern() {}
explicit AbstractionPattern(Kind kind) : TheKind(unsigned(kind)) {}

Expand Down Expand Up @@ -354,17 +383,29 @@ class AbstractionPattern {
}

bool hasGenericSignature() const {
return (getKind() == Kind::Type ||
getKind() == Kind::Discard ||
hasStoredClangType() ||
hasStoredObjCMethod());
switch (getKind()) {
case Kind::Type:
case Kind::Discard:
case Kind::ClangType:
case Kind::CFunctionAsMethodType:
case Kind::CurriedCFunctionAsMethodType:
case Kind::PartialCurriedCFunctionAsMethodType:
case Kind::CurriedObjCMethodType:
case Kind::PartialCurriedObjCMethodType:
case Kind::ObjCMethodType:
case Kind::CXXMethodType:
case Kind::CurriedCXXMethodType:
case Kind::PartialCurriedCXXMethodType:
return true;
case Kind::Invalid:
case Kind::Opaque:
case Kind::Tuple:
return false;
}
}

CanGenericSignature getGenericSignature() const {
assert(getKind() == Kind::Type ||
getKind() == Kind::Discard ||
hasStoredClangType() ||
hasStoredObjCMethod());
assert(hasGenericSignature());
return CanGenericSignature(GenericSig);
}

Expand Down Expand Up @@ -418,6 +459,41 @@ class AbstractionPattern {
getCurriedCFunctionAsMethod(CanType origType,
const AbstractFunctionDecl *function);

/// Return an abstraction pattern for the curried type of a C++ method.
static AbstractionPattern
getCurriedCXXMethod(CanType origType, const AbstractFunctionDecl *function);

/// Return an abstraction pattern for the uncurried type of a C++ method.
///
/// For example, if the original function is:
/// void Refrigerator::SetTemperature(RefrigeratorCompartment compartment,
/// Temperature temperature);
/// then the uncurried type is:
/// ((RefrigeratorCompartment, Temperature), Refrigerator) -> ()
static AbstractionPattern getCXXMethod(CanType origType,
const clang::CXXMethodDecl *method) {
assert(isa<AnyFunctionType>(origType));
AbstractionPattern pattern;
pattern.initCXXMethod(nullptr, origType, method, Kind::CXXMethodType);
return pattern;
}

/// Return an abstraction pattern for the curried type of a C++ method.
///
/// For example, if the original function is:
/// void Refrigerator::SetTemperature(RefrigeratorCompartment compartment,
/// Temperature temperature);
/// then the curried type:
/// (Refrigerator) -> (Compartment, Temperature) -> ()
static AbstractionPattern
getCurriedCXXMethod(CanType origType, const clang::CXXMethodDecl *method) {
assert(isa<AnyFunctionType>(origType));
AbstractionPattern pattern;
pattern.initCXXMethod(nullptr, origType, method,
Kind::CurriedCXXMethodType);
return pattern;
}

/// For a C-function-as-method pattern,
/// get the index of the C function parameter that was imported as the
/// `self` parameter of the imported method, or None if this is a static
Expand Down Expand Up @@ -497,6 +573,24 @@ class AbstractionPattern {
return pattern;
}

/// Return an abstraction pattern for the partially-applied curried
/// type of an C++ method.
///
/// For example, if the original function is:
/// void Refrigerator::SetTemperature(RefrigeratorCompartment compartment,
/// Temperature temperature);
/// then the partially-applied curried type is:
/// (Compartment, Temperature) -> ()
static AbstractionPattern
getPartialCurriedCXXMethod(CanGenericSignature signature, CanType origType,
const clang::CXXMethodDecl *method) {
assert(isa<AnyFunctionType>(origType));
AbstractionPattern pattern;
pattern.initCXXMethod(signature, origType, method,
Kind::PartialCurriedCXXMethodType);
return pattern;
}

public:
/// Return an abstraction pattern for the type of an Objective-C method.
static AbstractionPattern
Expand All @@ -520,18 +614,13 @@ class AbstractionPattern {
/// current Objective-C method.
AbstractionPattern getObjCMethodSelfPattern(CanType paramType) const;

/// Return a pattern corresponding to the formal parameters of the
/// current Objective-C method.
AbstractionPattern getObjCMethodFormalParamPattern(CanType paramType) const;

/// Return a pattern corresponding to the 'self' parameter of the
/// current C function imported as a method.
AbstractionPattern getCFunctionAsMethodSelfPattern(CanType paramType) const;

/// Return a pattern corresponding to the formal parameters of the
/// current C function imported as a method.
AbstractionPattern getCFunctionAsMethodFormalParamPattern(CanType paramType)
const;

/// Return a pattern corresponding to the 'self' parameter of the
/// current C++ method.
AbstractionPattern getCXXMethodSelfPattern(CanType paramType) const;

public:
/// Return an abstraction pattern with an added level of optionality.
Expand Down Expand Up @@ -606,6 +695,9 @@ class AbstractionPattern {
case Kind::CFunctionAsMethodType:
case Kind::CurriedCFunctionAsMethodType:
case Kind::PartialCurriedCFunctionAsMethodType:
case Kind::CXXMethodType:
case Kind::CurriedCXXMethodType:
case Kind::PartialCurriedCXXMethodType:
case Kind::Type:
case Kind::Discard:
return OrigType;
Expand Down Expand Up @@ -637,6 +729,9 @@ class AbstractionPattern {
case Kind::CFunctionAsMethodType:
case Kind::CurriedCFunctionAsMethodType:
case Kind::PartialCurriedCFunctionAsMethodType:
case Kind::CXXMethodType:
case Kind::CurriedCXXMethodType:
case Kind::PartialCurriedCXXMethodType:
case Kind::Type:
case Kind::Discard:
assert(signature || !type->hasTypeParameter());
Expand Down Expand Up @@ -669,6 +764,9 @@ class AbstractionPattern {
case Kind::CFunctionAsMethodType:
case Kind::CurriedCFunctionAsMethodType:
case Kind::PartialCurriedCFunctionAsMethodType:
case Kind::CXXMethodType:
case Kind::CurriedCXXMethodType:
case Kind::PartialCurriedCXXMethodType:
return true;
}
llvm_unreachable("bad kind");
Expand Down Expand Up @@ -702,6 +800,18 @@ class AbstractionPattern {
return ObjCMethod;
}

/// Return whether this abstraction pattern represents a C++ method.
/// If so, it is legal to call getCXXMethod().
bool isCXXMethod() const {
return (getKind() == Kind::CXXMethodType ||
getKind() == Kind::CurriedCXXMethodType);
}

const clang::CXXMethodDecl *getCXXMethod() const {
assert(hasStoredCXXMethod());
return CXXMethod;
}

EncodedForeignErrorInfo getEncodedForeignErrorInfo() const {
assert(hasStoredForeignErrorInfo());
return EncodedForeignErrorInfo::fromOpaqueValue(OtherData);
Expand All @@ -721,6 +831,9 @@ class AbstractionPattern {
case Kind::CFunctionAsMethodType:
case Kind::CurriedCFunctionAsMethodType:
case Kind::PartialCurriedCFunctionAsMethodType:
case Kind::CXXMethodType:
case Kind::CurriedCXXMethodType:
case Kind::PartialCurriedCXXMethodType:
return false;
case Kind::PartialCurriedObjCMethodType:
case Kind::CurriedObjCMethodType:
Expand Down Expand Up @@ -749,6 +862,9 @@ class AbstractionPattern {
case Kind::CFunctionAsMethodType:
case Kind::CurriedCFunctionAsMethodType:
case Kind::PartialCurriedCFunctionAsMethodType:
case Kind::CXXMethodType:
case Kind::CurriedCXXMethodType:
case Kind::PartialCurriedCXXMethodType:
case Kind::Type:
case Kind::Discard:
return dyn_cast<TYPE>(getType());
Expand All @@ -774,6 +890,9 @@ class AbstractionPattern {
case Kind::CFunctionAsMethodType:
case Kind::CurriedCFunctionAsMethodType:
case Kind::PartialCurriedCFunctionAsMethodType:
case Kind::CXXMethodType:
case Kind::CurriedCXXMethodType:
case Kind::PartialCurriedCXXMethodType:
// We assume that the Clang type might provide additional structure.
return false;
case Kind::Type:
Expand All @@ -798,6 +917,9 @@ class AbstractionPattern {
case Kind::CurriedCFunctionAsMethodType:
case Kind::PartialCurriedCFunctionAsMethodType:
case Kind::ObjCMethodType:
case Kind::CXXMethodType:
case Kind::CurriedCXXMethodType:
case Kind::PartialCurriedCXXMethodType:
return false;
case Kind::Tuple:
return true;
Expand All @@ -820,6 +942,9 @@ class AbstractionPattern {
case Kind::CurriedCFunctionAsMethodType:
case Kind::PartialCurriedCFunctionAsMethodType:
case Kind::ObjCMethodType:
case Kind::CXXMethodType:
case Kind::CurriedCXXMethodType:
case Kind::PartialCurriedCXXMethodType:
llvm_unreachable("pattern is not a tuple");
case Kind::Tuple:
return getNumTupleElements_Stored();
Expand Down
27 changes: 24 additions & 3 deletions lib/ClangImporter/ImportDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3251,6 +3251,7 @@ namespace {

// Import each of the members.
SmallVector<VarDecl *, 4> members;
SmallVector<FuncDecl *, 4> methods;
SmallVector<ConstructorDecl *, 4> ctors;

// FIXME: Import anonymous union fields and support field access when
Expand Down Expand Up @@ -3315,6 +3316,10 @@ namespace {
continue;
}

if (auto MD = dyn_cast<FuncDecl>(member)) {
methods.push_back(MD);
continue;
}
auto VD = cast<VarDecl>(member);

if (isa<clang::IndirectFieldDecl>(nd) || decl->isUnion()) {
Expand Down Expand Up @@ -3392,11 +3397,15 @@ namespace {
for (auto member : members) {
result->addMember(member);
}

for (auto ctor : ctors) {
result->addMember(ctor);
}

for (auto method : methods) {
result->addMember(method);
}

result->setHasUnreferenceableStorage(hasUnreferenceableStorage);

return result;
Expand Down Expand Up @@ -3691,6 +3700,19 @@ namespace {
/*throws*/ false,
dc, decl);

if (auto *mdecl = dyn_cast<clang::CXXMethodDecl>(decl)) {
if (!mdecl->isStatic()) {
// Workaround until proper const support is handled: Force
// everything to be mutating. This implicitly makes the parameter
// indirect.
result->setSelfAccessKind(SelfAccessKind::Mutating);
// "self" is the first argument.
result->setSelfIndex(0);
} else {
result->setStatic();
result->setImportAsStaticMember();
}
}
result->computeType();
result->setValidationToChecked();
result->setIsObjC(false);
Expand Down Expand Up @@ -3732,8 +3754,7 @@ namespace {
}

Decl *VisitCXXMethodDecl(const clang::CXXMethodDecl *decl) {
// FIXME: Import C++ member functions as methods.
return nullptr;
return VisitFunctionDecl(decl);
}

Decl *VisitFieldDecl(const clang::FieldDecl *decl) {
Expand Down
Loading