Skip to content

Commit 765d338

Browse files
authored
Merge pull request #26047 from pschuh/cpp-2
Add importing cxx function decls and the basic requisite AbstractionPattern support.
2 parents 1a211e6 + 4a5dae5 commit 765d338

File tree

6 files changed

+338
-26
lines changed

6 files changed

+338
-26
lines changed

include/swift/SIL/AbstractionPattern.h

Lines changed: 143 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,10 @@ namespace llvm {
2626
}
2727

2828
namespace clang {
29-
class ValueDecl;
29+
class CXXMethodDecl;
3030
class ObjCMethodDecl;
3131
class Type;
32+
class ValueDecl;
3233
}
3334

3435
namespace swift {
@@ -178,6 +179,15 @@ class AbstractionPattern {
178179
/// type. ObjCMethod is valid. OtherData is an encoded foreign
179180
/// error index.
180181
ObjCMethodType,
182+
/// The uncurried imported type of a C++ method. OrigType is valid and is a
183+
/// function type. CXXMethod is valid.
184+
CXXMethodType,
185+
/// The curried imported type of a C++ method. OrigType is valid and is a
186+
/// function type. CXXMethod is valid.
187+
CurriedCXXMethodType,
188+
/// The partially-applied curried imported type of a C++ method. OrigType is
189+
/// valid and is a function type. CXXMethod is valid.
190+
PartialCurriedCXXMethodType,
181191
};
182192

183193
class EncodedForeignErrorInfo {
@@ -234,6 +244,7 @@ class AbstractionPattern {
234244
union {
235245
const clang::Type *ClangType;
236246
const clang::ObjCMethodDecl *ObjCMethod;
247+
const clang::CXXMethodDecl *CXXMethod;
237248
const AbstractionPattern *OrigTupleElements;
238249
};
239250
CanGenericSignature GenericSig;
@@ -266,6 +277,18 @@ class AbstractionPattern {
266277
}
267278
}
268279

280+
bool hasStoredCXXMethod() const {
281+
switch (getKind()) {
282+
case Kind::CXXMethodType:
283+
case Kind::CurriedCXXMethodType:
284+
case Kind::PartialCurriedCXXMethodType:
285+
return true;
286+
287+
default:
288+
return false;
289+
}
290+
}
291+
269292
bool hasStoredObjCMethod() const {
270293
switch (getKind()) {
271294
case Kind::CurriedObjCMethodType:
@@ -327,6 +350,12 @@ class AbstractionPattern {
327350
OtherData = memberStatus.getRawValue();
328351
}
329352

353+
void initCXXMethod(CanGenericSignature signature, CanType origType,
354+
const clang::CXXMethodDecl *method, Kind kind) {
355+
initSwiftType(signature, origType, kind);
356+
CXXMethod = method;
357+
}
358+
330359
AbstractionPattern() {}
331360
explicit AbstractionPattern(Kind kind) : TheKind(unsigned(kind)) {}
332361

@@ -354,17 +383,29 @@ class AbstractionPattern {
354383
}
355384

356385
bool hasGenericSignature() const {
357-
return (getKind() == Kind::Type ||
358-
getKind() == Kind::Discard ||
359-
hasStoredClangType() ||
360-
hasStoredObjCMethod());
386+
switch (getKind()) {
387+
case Kind::Type:
388+
case Kind::Discard:
389+
case Kind::ClangType:
390+
case Kind::CFunctionAsMethodType:
391+
case Kind::CurriedCFunctionAsMethodType:
392+
case Kind::PartialCurriedCFunctionAsMethodType:
393+
case Kind::CurriedObjCMethodType:
394+
case Kind::PartialCurriedObjCMethodType:
395+
case Kind::ObjCMethodType:
396+
case Kind::CXXMethodType:
397+
case Kind::CurriedCXXMethodType:
398+
case Kind::PartialCurriedCXXMethodType:
399+
return true;
400+
case Kind::Invalid:
401+
case Kind::Opaque:
402+
case Kind::Tuple:
403+
return false;
404+
}
361405
}
362406

363407
CanGenericSignature getGenericSignature() const {
364-
assert(getKind() == Kind::Type ||
365-
getKind() == Kind::Discard ||
366-
hasStoredClangType() ||
367-
hasStoredObjCMethod());
408+
assert(hasGenericSignature());
368409
return CanGenericSignature(GenericSig);
369410
}
370411

@@ -418,6 +459,41 @@ class AbstractionPattern {
418459
getCurriedCFunctionAsMethod(CanType origType,
419460
const AbstractFunctionDecl *function);
420461

462+
/// Return an abstraction pattern for the curried type of a C++ method.
463+
static AbstractionPattern
464+
getCurriedCXXMethod(CanType origType, const AbstractFunctionDecl *function);
465+
466+
/// Return an abstraction pattern for the uncurried type of a C++ method.
467+
///
468+
/// For example, if the original function is:
469+
/// void Refrigerator::SetTemperature(RefrigeratorCompartment compartment,
470+
/// Temperature temperature);
471+
/// then the uncurried type is:
472+
/// ((RefrigeratorCompartment, Temperature), Refrigerator) -> ()
473+
static AbstractionPattern getCXXMethod(CanType origType,
474+
const clang::CXXMethodDecl *method) {
475+
assert(isa<AnyFunctionType>(origType));
476+
AbstractionPattern pattern;
477+
pattern.initCXXMethod(nullptr, origType, method, Kind::CXXMethodType);
478+
return pattern;
479+
}
480+
481+
/// Return an abstraction pattern for the curried type of a C++ method.
482+
///
483+
/// For example, if the original function is:
484+
/// void Refrigerator::SetTemperature(RefrigeratorCompartment compartment,
485+
/// Temperature temperature);
486+
/// then the curried type:
487+
/// (Refrigerator) -> (Compartment, Temperature) -> ()
488+
static AbstractionPattern
489+
getCurriedCXXMethod(CanType origType, const clang::CXXMethodDecl *method) {
490+
assert(isa<AnyFunctionType>(origType));
491+
AbstractionPattern pattern;
492+
pattern.initCXXMethod(nullptr, origType, method,
493+
Kind::CurriedCXXMethodType);
494+
return pattern;
495+
}
496+
421497
/// For a C-function-as-method pattern,
422498
/// get the index of the C function parameter that was imported as the
423499
/// `self` parameter of the imported method, or None if this is a static
@@ -497,6 +573,24 @@ class AbstractionPattern {
497573
return pattern;
498574
}
499575

576+
/// Return an abstraction pattern for the partially-applied curried
577+
/// type of an C++ method.
578+
///
579+
/// For example, if the original function is:
580+
/// void Refrigerator::SetTemperature(RefrigeratorCompartment compartment,
581+
/// Temperature temperature);
582+
/// then the partially-applied curried type is:
583+
/// (Compartment, Temperature) -> ()
584+
static AbstractionPattern
585+
getPartialCurriedCXXMethod(CanGenericSignature signature, CanType origType,
586+
const clang::CXXMethodDecl *method) {
587+
assert(isa<AnyFunctionType>(origType));
588+
AbstractionPattern pattern;
589+
pattern.initCXXMethod(signature, origType, method,
590+
Kind::PartialCurriedCXXMethodType);
591+
return pattern;
592+
}
593+
500594
public:
501595
/// Return an abstraction pattern for the type of an Objective-C method.
502596
static AbstractionPattern
@@ -520,18 +614,13 @@ class AbstractionPattern {
520614
/// current Objective-C method.
521615
AbstractionPattern getObjCMethodSelfPattern(CanType paramType) const;
522616

523-
/// Return a pattern corresponding to the formal parameters of the
524-
/// current Objective-C method.
525-
AbstractionPattern getObjCMethodFormalParamPattern(CanType paramType) const;
526-
527617
/// Return a pattern corresponding to the 'self' parameter of the
528618
/// current C function imported as a method.
529619
AbstractionPattern getCFunctionAsMethodSelfPattern(CanType paramType) const;
530-
531-
/// Return a pattern corresponding to the formal parameters of the
532-
/// current C function imported as a method.
533-
AbstractionPattern getCFunctionAsMethodFormalParamPattern(CanType paramType)
534-
const;
620+
621+
/// Return a pattern corresponding to the 'self' parameter of the
622+
/// current C++ method.
623+
AbstractionPattern getCXXMethodSelfPattern(CanType paramType) const;
535624

536625
public:
537626
/// Return an abstraction pattern with an added level of optionality.
@@ -606,6 +695,9 @@ class AbstractionPattern {
606695
case Kind::CFunctionAsMethodType:
607696
case Kind::CurriedCFunctionAsMethodType:
608697
case Kind::PartialCurriedCFunctionAsMethodType:
698+
case Kind::CXXMethodType:
699+
case Kind::CurriedCXXMethodType:
700+
case Kind::PartialCurriedCXXMethodType:
609701
case Kind::Type:
610702
case Kind::Discard:
611703
return OrigType;
@@ -637,6 +729,9 @@ class AbstractionPattern {
637729
case Kind::CFunctionAsMethodType:
638730
case Kind::CurriedCFunctionAsMethodType:
639731
case Kind::PartialCurriedCFunctionAsMethodType:
732+
case Kind::CXXMethodType:
733+
case Kind::CurriedCXXMethodType:
734+
case Kind::PartialCurriedCXXMethodType:
640735
case Kind::Type:
641736
case Kind::Discard:
642737
assert(signature || !type->hasTypeParameter());
@@ -669,6 +764,9 @@ class AbstractionPattern {
669764
case Kind::CFunctionAsMethodType:
670765
case Kind::CurriedCFunctionAsMethodType:
671766
case Kind::PartialCurriedCFunctionAsMethodType:
767+
case Kind::CXXMethodType:
768+
case Kind::CurriedCXXMethodType:
769+
case Kind::PartialCurriedCXXMethodType:
672770
return true;
673771
}
674772
llvm_unreachable("bad kind");
@@ -702,6 +800,18 @@ class AbstractionPattern {
702800
return ObjCMethod;
703801
}
704802

803+
/// Return whether this abstraction pattern represents a C++ method.
804+
/// If so, it is legal to call getCXXMethod().
805+
bool isCXXMethod() const {
806+
return (getKind() == Kind::CXXMethodType ||
807+
getKind() == Kind::CurriedCXXMethodType);
808+
}
809+
810+
const clang::CXXMethodDecl *getCXXMethod() const {
811+
assert(hasStoredCXXMethod());
812+
return CXXMethod;
813+
}
814+
705815
EncodedForeignErrorInfo getEncodedForeignErrorInfo() const {
706816
assert(hasStoredForeignErrorInfo());
707817
return EncodedForeignErrorInfo::fromOpaqueValue(OtherData);
@@ -721,6 +831,9 @@ class AbstractionPattern {
721831
case Kind::CFunctionAsMethodType:
722832
case Kind::CurriedCFunctionAsMethodType:
723833
case Kind::PartialCurriedCFunctionAsMethodType:
834+
case Kind::CXXMethodType:
835+
case Kind::CurriedCXXMethodType:
836+
case Kind::PartialCurriedCXXMethodType:
724837
return false;
725838
case Kind::PartialCurriedObjCMethodType:
726839
case Kind::CurriedObjCMethodType:
@@ -749,6 +862,9 @@ class AbstractionPattern {
749862
case Kind::CFunctionAsMethodType:
750863
case Kind::CurriedCFunctionAsMethodType:
751864
case Kind::PartialCurriedCFunctionAsMethodType:
865+
case Kind::CXXMethodType:
866+
case Kind::CurriedCXXMethodType:
867+
case Kind::PartialCurriedCXXMethodType:
752868
case Kind::Type:
753869
case Kind::Discard:
754870
return dyn_cast<TYPE>(getType());
@@ -774,6 +890,9 @@ class AbstractionPattern {
774890
case Kind::CFunctionAsMethodType:
775891
case Kind::CurriedCFunctionAsMethodType:
776892
case Kind::PartialCurriedCFunctionAsMethodType:
893+
case Kind::CXXMethodType:
894+
case Kind::CurriedCXXMethodType:
895+
case Kind::PartialCurriedCXXMethodType:
777896
// We assume that the Clang type might provide additional structure.
778897
return false;
779898
case Kind::Type:
@@ -798,6 +917,9 @@ class AbstractionPattern {
798917
case Kind::CurriedCFunctionAsMethodType:
799918
case Kind::PartialCurriedCFunctionAsMethodType:
800919
case Kind::ObjCMethodType:
920+
case Kind::CXXMethodType:
921+
case Kind::CurriedCXXMethodType:
922+
case Kind::PartialCurriedCXXMethodType:
801923
return false;
802924
case Kind::Tuple:
803925
return true;
@@ -820,6 +942,9 @@ class AbstractionPattern {
820942
case Kind::CurriedCFunctionAsMethodType:
821943
case Kind::PartialCurriedCFunctionAsMethodType:
822944
case Kind::ObjCMethodType:
945+
case Kind::CXXMethodType:
946+
case Kind::CurriedCXXMethodType:
947+
case Kind::PartialCurriedCXXMethodType:
823948
llvm_unreachable("pattern is not a tuple");
824949
case Kind::Tuple:
825950
return getNumTupleElements_Stored();

lib/ClangImporter/ImportDecl.cpp

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3242,6 +3242,7 @@ namespace {
32423242

32433243
// Import each of the members.
32443244
SmallVector<VarDecl *, 4> members;
3245+
SmallVector<FuncDecl *, 4> methods;
32453246
SmallVector<ConstructorDecl *, 4> ctors;
32463247

32473248
// FIXME: Import anonymous union fields and support field access when
@@ -3306,6 +3307,10 @@ namespace {
33063307
continue;
33073308
}
33083309

3310+
if (auto MD = dyn_cast<FuncDecl>(member)) {
3311+
methods.push_back(MD);
3312+
continue;
3313+
}
33093314
auto VD = cast<VarDecl>(member);
33103315

33113316
if (isa<clang::IndirectFieldDecl>(nd) || decl->isUnion()) {
@@ -3383,11 +3388,15 @@ namespace {
33833388
for (auto member : members) {
33843389
result->addMember(member);
33853390
}
3386-
3391+
33873392
for (auto ctor : ctors) {
33883393
result->addMember(ctor);
33893394
}
33903395

3396+
for (auto method : methods) {
3397+
result->addMember(method);
3398+
}
3399+
33913400
result->setHasUnreferenceableStorage(hasUnreferenceableStorage);
33923401

33933402
return result;
@@ -3682,6 +3691,19 @@ namespace {
36823691
/*throws*/ false,
36833692
dc, decl);
36843693

3694+
if (auto *mdecl = dyn_cast<clang::CXXMethodDecl>(decl)) {
3695+
if (!mdecl->isStatic()) {
3696+
// Workaround until proper const support is handled: Force
3697+
// everything to be mutating. This implicitly makes the parameter
3698+
// indirect.
3699+
result->setSelfAccessKind(SelfAccessKind::Mutating);
3700+
// "self" is the first argument.
3701+
result->setSelfIndex(0);
3702+
} else {
3703+
result->setStatic();
3704+
result->setImportAsStaticMember();
3705+
}
3706+
}
36853707
result->computeType();
36863708
result->setValidationToChecked();
36873709
result->setIsObjC(false);
@@ -3723,8 +3745,7 @@ namespace {
37233745
}
37243746

37253747
Decl *VisitCXXMethodDecl(const clang::CXXMethodDecl *decl) {
3726-
// FIXME: Import C++ member functions as methods.
3727-
return nullptr;
3748+
return VisitFunctionDecl(decl);
37283749
}
37293750

37303751
Decl *VisitFieldDecl(const clang::FieldDecl *decl) {

0 commit comments

Comments
 (0)