mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[cxx-interop] Adding swift_name attributes to virtual methods overrides
This commit is contained in:
@@ -73,6 +73,11 @@ GROUPED_WARNING(inconsistent_swift_name, ClangDeclarationImport, none,
|
||||
(bool, StringRef, StringRef, DeclName, StringRef, DeclName,
|
||||
StringRef))
|
||||
|
||||
WARNING(swift_name_attr_ignored, none,
|
||||
"ignoring swift_name attribute %0; swift_name attributes have no "
|
||||
"effect on method overrides",
|
||||
(DeclName))
|
||||
|
||||
GROUPED_WARNING(swift_name_circular_context_import, ClangDeclarationImport, none,
|
||||
"cycle detected while resolving '%0' in swift_name attribute for '%1'",
|
||||
(StringRef, StringRef))
|
||||
|
||||
@@ -6336,11 +6336,9 @@ TinyPtrVector<ValueDecl *> ClangRecordMemberLookup::evaluate(
|
||||
// Capture the arity of already found members in the
|
||||
// current record, to avoid adding ambiguous members
|
||||
// from base classes.
|
||||
const auto getArity =
|
||||
ClangImporter::Implementation::getImportedBaseMemberDeclArity;
|
||||
llvm::SmallSet<size_t, 4> foundNameArities;
|
||||
llvm::SmallSet<DeclName, 4> foundMethodNames;
|
||||
for (const auto *valueDecl : result)
|
||||
foundNameArities.insert(getArity(valueDecl));
|
||||
foundMethodNames.insert(valueDecl->getName());
|
||||
|
||||
for (auto base : cxxRecord->bases()) {
|
||||
if (skipIfNonPublic && base.getAccessSpecifier() != clang::AS_public)
|
||||
@@ -6374,9 +6372,9 @@ TinyPtrVector<ValueDecl *> ClangRecordMemberLookup::evaluate(
|
||||
{});
|
||||
|
||||
for (auto foundInBase : baseResults) {
|
||||
// Do not add duplicate entry with the same arity,
|
||||
// Do not add duplicate entry with the same DeclName,
|
||||
// as that would cause an ambiguous lookup.
|
||||
if (foundNameArities.count(getArity(foundInBase)))
|
||||
if (foundMethodNames.count(foundInBase->getName()))
|
||||
continue;
|
||||
|
||||
collector.add(foundInBase);
|
||||
@@ -7671,6 +7669,7 @@ ValueDecl *ClangImporter::Implementation::importBaseMemberDecl(
|
||||
auto known = clonedBaseMembers.find(key);
|
||||
if (known == clonedBaseMembers.end()) {
|
||||
ValueDecl *cloned = cloneBaseMemberDecl(decl, newContext, inheritance);
|
||||
handleAmbiguousSwiftName(cloned);
|
||||
known = clonedBaseMembers.insert({key, cloned}).first;
|
||||
clonedMembers.insert(std::make_pair(cloned, decl));
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
#include "swift/ClangImporter/ClangImporterRequests.h"
|
||||
#include "swift/ClangImporter/ClangModule.h"
|
||||
#include "swift/Parse/Lexer.h"
|
||||
#include "swift/Parse/ParseDeclName.h"
|
||||
#include "swift/Strings.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/Attr.h"
|
||||
@@ -4424,7 +4425,43 @@ namespace {
|
||||
// Create a thunk that will perform dynamic dispatch.
|
||||
// TODO: we don't have to import the actual `method` in this case,
|
||||
// we can just synthesize a thunk and import that instead.
|
||||
auto result = synthesizer.makeVirtualMethod(decl);
|
||||
|
||||
FuncDecl *result;
|
||||
if (decl->size_overridden_methods() > 0) {
|
||||
if (auto swiftNameAttr = decl->getAttr<clang::SwiftNameAttr>()) {
|
||||
auto parsedDeclName = parseDeclName(swiftNameAttr->getName());
|
||||
auto swiftDeclName =
|
||||
parsedDeclName.formDeclName(method->getASTContext());
|
||||
ImportedName importedName;
|
||||
std::tie(importedName, std::ignore) = importFullName(decl);
|
||||
|
||||
result = synthesizer.makeVirtualMethod(decl);
|
||||
|
||||
if (swiftDeclName != importedName.getDeclName()) {
|
||||
Impl.diagnose(HeaderLoc(swiftNameAttr->getLoc()),
|
||||
diag::swift_name_attr_ignored, swiftDeclName);
|
||||
|
||||
Impl.markUnavailable(
|
||||
result, (llvm::Twine("ignoring swift_name '") +
|
||||
swiftNameAttr->getName() + "' in '" +
|
||||
decl->getParent()->getName() +
|
||||
"'; swift_name attributes have no effect "
|
||||
"on method overrides")
|
||||
.str());
|
||||
}
|
||||
} else {
|
||||
// If there's no swift_name attribute, we don't import this method.
|
||||
// This is because if the overridden method was renamed and
|
||||
// this one is not, we want to use the overridden method's name.
|
||||
// This is reasonable because `makeVirtualMethod` returns
|
||||
// a thunk that will perform dynamic dispatch, and consequently
|
||||
// the correct instance of the method will get executed.
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
result = synthesizer.makeVirtualMethod(decl);
|
||||
}
|
||||
|
||||
if (result) {
|
||||
return result;
|
||||
} else {
|
||||
@@ -10367,6 +10404,22 @@ ValueDecl *ClangImporter::Implementation::createUnavailableDecl(
|
||||
return var;
|
||||
}
|
||||
|
||||
void ClangImporter::Implementation::handleAmbiguousSwiftName(ValueDecl *decl) {
|
||||
if (!decl || decl->isUnavailable())
|
||||
return;
|
||||
|
||||
auto *cxxRecordDecl = dyn_cast<clang::CXXRecordDecl>(
|
||||
decl->getDeclContext()->getAsDecl()->getClangDecl());
|
||||
|
||||
if (!cxxRecordDecl)
|
||||
return;
|
||||
|
||||
if (findUnavailableMethod(cxxRecordDecl, decl->getName())) {
|
||||
markUnavailable(decl,
|
||||
"overrides multiple C++ methods with different Swift names");
|
||||
}
|
||||
}
|
||||
|
||||
// Force the members of the entire inheritance hierarchy to be loaded and
|
||||
// deserialized before loading the members of this class. This allows the
|
||||
// decl members table to be warmed up and enables the correct identification of
|
||||
|
||||
@@ -1706,6 +1706,12 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
|
||||
}
|
||||
}
|
||||
|
||||
// `swift_name` attribute is not supported in virtual methods overrides
|
||||
if (auto method = dyn_cast<clang::CXXMethodDecl>(D)) {
|
||||
if (method->isVirtual() && method->size_overridden_methods() > 0)
|
||||
skipCustomName = true;
|
||||
}
|
||||
|
||||
if (!skipCustomName) {
|
||||
result.info.hasCustomName = true;
|
||||
result.declName = parsedName.formDeclName(
|
||||
@@ -2315,6 +2321,42 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
|
||||
newName = baseName.substr(StringRef("__synthesizedVirtualCall_").size());
|
||||
baseName = newName;
|
||||
}
|
||||
if (method->isVirtual()) {
|
||||
// The name should be imported from the base method
|
||||
if (method->size_overridden_methods() > 0) {
|
||||
DeclName overriddenName;
|
||||
bool foundDivergentMethod = false;
|
||||
for (auto overriddenMethod : method->overridden_methods()) {
|
||||
ImportedName importedName =
|
||||
importName(overriddenMethod, version, givenName);
|
||||
if (!overriddenName) {
|
||||
overriddenName = importedName.getDeclName();
|
||||
} else if (overriddenName.compare(importedName.getDeclName())) {
|
||||
importerImpl->insertUnavailableMethod(method->getParent(),
|
||||
importedName.getDeclName());
|
||||
foundDivergentMethod = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (foundDivergentMethod) {
|
||||
// The method we want to mark as unavailable will be generated
|
||||
// lazily, when we clone the methods from base classes to the derived
|
||||
// class method->getParent().
|
||||
// Since we don't have the actual method here, we store this
|
||||
// information to be accessed when we generate the actual method.
|
||||
importerImpl->insertUnavailableMethod(method->getParent(),
|
||||
overriddenName);
|
||||
return ImportedName();
|
||||
}
|
||||
|
||||
baseName = overriddenName.getBaseIdentifier().str();
|
||||
// Also inherit argument names from base method
|
||||
argumentNames.clear();
|
||||
llvm::for_each(overriddenName.getArgumentNames(), [&](Identifier arg) {
|
||||
argumentNames.push_back(arg.str());
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// swift_newtype-ed declarations may have common words with the type name
|
||||
|
||||
@@ -694,6 +694,14 @@ private:
|
||||
// Map all cloned methods back to the original member
|
||||
llvm::DenseMap<ValueDecl *, ValueDecl *> clonedMembers;
|
||||
|
||||
// Keep track of methods that are unavailale in each class.
|
||||
// We need this set because these methods will be imported lazily. We don't
|
||||
// have the corresponding Swift method when the availability check is
|
||||
// performed, so instead we store the information in this set and then, when
|
||||
// the method is finally generated, we check if it's present here
|
||||
llvm::DenseSet<std::pair<const clang::CXXRecordDecl *, DeclName>>
|
||||
unavailableMethods;
|
||||
|
||||
public:
|
||||
llvm::DenseMap<const clang::ParmVarDecl*, FuncDecl*> defaultArgGenerators;
|
||||
|
||||
@@ -722,6 +730,18 @@ public:
|
||||
return getNameImporter().getEnumKind(decl);
|
||||
}
|
||||
|
||||
bool findUnavailableMethod(const clang::CXXRecordDecl *classDecl,
|
||||
DeclName name) {
|
||||
return unavailableMethods.contains({classDecl, name});
|
||||
}
|
||||
|
||||
void insertUnavailableMethod(const clang::CXXRecordDecl *classDecl,
|
||||
DeclName name) {
|
||||
unavailableMethods.insert({classDecl, name});
|
||||
}
|
||||
|
||||
void handleAmbiguousSwiftName(ValueDecl *decl);
|
||||
|
||||
private:
|
||||
/// A mapping from imported declarations to their "alternate" declarations,
|
||||
/// for cases where a single Clang declaration is imported to two
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "swift/Basic/STLExtras.h"
|
||||
#include "swift/Basic/Version.h"
|
||||
#include "swift/ClangImporter/ClangImporter.h"
|
||||
#include "swift/Parse/ParseDeclName.h"
|
||||
#include "clang/AST/DeclCXX.h"
|
||||
#include "clang/AST/DeclObjC.h"
|
||||
#include "clang/Lex/MacroInfo.h"
|
||||
@@ -1945,6 +1946,15 @@ void importer::addEntryToLookupTable(SwiftLookupTable &table,
|
||||
named, importedName.getEffectiveContext());
|
||||
}
|
||||
|
||||
if (auto swiftNameAttr = named->getAttr<clang::SwiftNameAttr>()) {
|
||||
auto parsedDeclName = parseDeclName(swiftNameAttr->getName());
|
||||
auto swiftDeclName =
|
||||
parsedDeclName.formDeclName(nameImporter.getContext());
|
||||
if (importedName.getDeclName() != swiftDeclName)
|
||||
table.addEntry(swiftDeclName, named,
|
||||
importedName.getEffectiveContext());
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
if (failed) {
|
||||
|
||||
@@ -41,19 +41,19 @@ import ImportAsMember
|
||||
// CHECK-NEXT: TU: __swift
|
||||
// CHECK-NEXT: adding:
|
||||
// CHECK-NEXT: SNSomeStruct: SNAdding
|
||||
// CHECK-NEXT: blue:
|
||||
// CHECK: blue:
|
||||
// CHECK-NEXT: SNColorChoice: SNColorBlue
|
||||
// CHECK-NEXT: defaultValue:
|
||||
// CHECK-NEXT: SNSomeStruct: SNSomeStructGetDefault, SNSomeStructSetDefault
|
||||
// CHECK-NEXT: defaultX:
|
||||
// CHECK: defaultX:
|
||||
// CHECK-NEXT: SNSomeStruct: DefaultXValue
|
||||
// CHECK-NEXT: foo:
|
||||
// CHECK: foo:
|
||||
// CHECK-NEXT: SNSomeStruct: SNSomeStructGetFoo, SNSomeStructSetFoo
|
||||
// CHECK-NEXT: green:
|
||||
// CHECK: green:
|
||||
// CHECK-NEXT: SNColorChoice: SNColorGreen
|
||||
// CHECK-NEXT: init:
|
||||
// CHECK-NEXT: SNSomeStruct: SNCreate
|
||||
// CHECK-NEXT: makeSomeStruct:
|
||||
// CHECK: makeSomeStruct:
|
||||
// CHECK-NEXT: TU: SNMakeSomeStruct, SNMakeSomeStructForX
|
||||
// CHECK-NEXT: x:
|
||||
// CHECK-NEXT: SNSomeStruct: X
|
||||
|
||||
@@ -139,3 +139,138 @@ inline const Immortal *_Nonnull castToImmortal(
|
||||
const DerivedFromImmortal *_Nonnull immortal) {
|
||||
return static_cast<const Immortal *>(immortal);
|
||||
}
|
||||
|
||||
// A1
|
||||
// / \
|
||||
// B1 B2
|
||||
// / \
|
||||
// C1 C2
|
||||
|
||||
struct IMMORTAL_FRT A1 {
|
||||
virtual int virtualMethod() const { return 111; }
|
||||
|
||||
__attribute__((swift_name("swiftFooRename()")))
|
||||
virtual int fooRename() const { return 112; }
|
||||
|
||||
__attribute__((swift_name("swiftBarRename()")))
|
||||
virtual int barRename() const { return 113; }
|
||||
|
||||
__attribute__((swift_name("swiftParamsRename(a1:)")))
|
||||
virtual int paramsRename(int i) const { return i; }
|
||||
|
||||
static A1 *_Nonnull create() { return new A1(); }
|
||||
};
|
||||
|
||||
struct B1 : A1 {
|
||||
__attribute__((swift_name("swiftVirtualMethod()")))
|
||||
virtual int virtualMethod() const override { return 211; }
|
||||
|
||||
virtual int fooRename() const override { return 212; }
|
||||
|
||||
__attribute__((swift_name("B1BarRename()")))
|
||||
virtual int barRename() const override { return 213; }
|
||||
|
||||
__attribute__((swift_name("swiftParamsRename(b1:)")))
|
||||
virtual int paramsRename(int i) const override { return i; }
|
||||
|
||||
static B1 *_Nonnull create() { return new B1(); }
|
||||
};
|
||||
|
||||
struct B2 : A1 {
|
||||
int virtualMethod() const { return 221; }
|
||||
|
||||
int fooRename() const { return 222; }
|
||||
|
||||
__attribute__((swift_name("B2BarRename()"))) int barRename() const {
|
||||
return 223;
|
||||
}
|
||||
|
||||
static B2 *_Nonnull create() { return new B2(); }
|
||||
};
|
||||
|
||||
struct C1 : B1 {
|
||||
__attribute__((swift_name("swiftFooRename()")))
|
||||
virtual int fooRename() const override { return 312; }
|
||||
|
||||
__attribute__((swift_name("swiftBarRename()")))
|
||||
virtual int barRename() const override { return 313; }
|
||||
|
||||
virtual int paramsRename(int i) const override { return i; }
|
||||
|
||||
static C1 *_Nonnull create() { return new C1(); }
|
||||
};
|
||||
|
||||
struct C2 : B1 {
|
||||
__attribute__((swift_name("swiftVirtualMethod()")))
|
||||
virtual int virtualMethod() const override { return 321; }
|
||||
|
||||
__attribute__((swift_name("C2FooRename()")))
|
||||
virtual int fooRename() const override { return 322; }
|
||||
|
||||
__attribute__((swift_name("B1BarRename()")))
|
||||
virtual int barRename() const override { return 323; }
|
||||
|
||||
__attribute__((swift_name("swiftParamsRename(b1:)")))
|
||||
virtual int paramsRename(int i) const override { return i; }
|
||||
|
||||
static C2 *_Nonnull create() { return new C2(); }
|
||||
};
|
||||
|
||||
struct IMMORTAL_FRT A2 {
|
||||
__attribute__((swift_name("swiftVirtualMethod()")))
|
||||
virtual int virtualMethod() const { return 121; }
|
||||
|
||||
__attribute__((swift_name("swiftFooRename()")))
|
||||
virtual int fooRename() const { return 122; }
|
||||
|
||||
__attribute__((swift_name("A2BarRename()")))
|
||||
virtual int barRename() const { return 123; }
|
||||
|
||||
__attribute__((swift_name("swiftParamsRename(a2:)"))) virtual int
|
||||
paramsRename(int i) const {
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
static A2 *_Nonnull create() { return new A2(); }
|
||||
};
|
||||
|
||||
// A1 A2
|
||||
// \ /
|
||||
// D1
|
||||
|
||||
struct D1 : A1, A2 {
|
||||
static D1 *_Nonnull create() { return new D1(); }
|
||||
};
|
||||
|
||||
// A1 A2
|
||||
// \ /
|
||||
// B1 /
|
||||
// \ /
|
||||
// D2
|
||||
|
||||
struct D2 : B1, A2 {
|
||||
__attribute__((swift_name("swiftVirtualMethod()")))
|
||||
virtual int virtualMethod() const override { return 411; }
|
||||
|
||||
virtual int fooRename() const override { return 412; }
|
||||
|
||||
virtual int barRename() const override { return 413; }
|
||||
|
||||
virtual int paramsRename(int i) const override { return i; }
|
||||
};
|
||||
|
||||
// A1
|
||||
// / \
|
||||
// / \
|
||||
// B1 B2
|
||||
// |\ /|
|
||||
// | \ / |
|
||||
// | D3 |
|
||||
// C1 |
|
||||
// \ |
|
||||
// \ /
|
||||
// D4
|
||||
|
||||
struct D3 : B1, B2 {};
|
||||
|
||||
struct D4 : C1, B2 {};
|
||||
|
||||
@@ -15,3 +15,123 @@
|
||||
// CHECK-NEXT: final func virtualMethod(_: HasDestructor)
|
||||
// CHECK-NEXT: final func swiftVirtualRename()
|
||||
// CHECK: }
|
||||
|
||||
// CHECK: class A1 {
|
||||
// CHECK: final func virtualMethod() -> Int32
|
||||
// CHECK: final func swiftFooRename() -> Int32
|
||||
// CHECK: final func swiftBarRename() -> Int32
|
||||
// CHECK: final func swiftParamsRename(a1 i: Int32) -> Int32
|
||||
// CHECK: }
|
||||
|
||||
// CHECK: class B1 {
|
||||
// CHECK: @available(*, unavailable, message: "ignoring{{.*}}")
|
||||
// CHECK: final func swiftVirtualMethod() -> Int32
|
||||
// CHECK: @available(*, unavailable, message: "ignoring{{.*}}")
|
||||
// CHECK: final func B1BarRename() -> Int32
|
||||
// CHECK: @available(*, unavailable, message: "ignoring{{.*}}")
|
||||
// CHECK: final func swiftParamsRename(b1 i: Int32) -> Int32
|
||||
// CHECK: final func virtualMethod() -> Int32
|
||||
// CHECK: final func swiftFooRename() -> Int32
|
||||
// CHECK: final func swiftBarRename() -> Int32
|
||||
// CHECK: final func swiftParamsRename(a1 i: Int32) -> Int32
|
||||
// CHECK: }
|
||||
|
||||
// CHECK: class B2 {
|
||||
// CHECK: @available(*, unavailable, message: "ignoring{{.*}}")
|
||||
// CHECK: final func B2BarRename() -> Int32
|
||||
// CHECK: final func virtualMethod() -> Int32
|
||||
// CHECK: final func swiftFooRename() -> Int32
|
||||
// CHECK: final func swiftBarRename() -> Int32
|
||||
// CHECK: final func swiftParamsRename(a1 i: Int32) -> Int32
|
||||
// CHECK: }
|
||||
|
||||
// CHECK: class C1 {
|
||||
// CHECK: final func swiftFooRename() -> Int32
|
||||
// CHECK: final func swiftBarRename() -> Int32
|
||||
// CHECK: @available(*, unavailable, message: "ignoring{{.*}}")
|
||||
// CHECK: final func swiftVirtualMethod() -> Int32
|
||||
// CHECK: @available(*, unavailable, message: "ignoring{{.*}}")
|
||||
// CHECK: final func B1BarRename() -> Int32
|
||||
// CHECK: @available(*, unavailable, message: "ignoring{{.*}}")
|
||||
// CHECK: final func swiftParamsRename(b1 i: Int32) -> Int32
|
||||
// CHECK: final func virtualMethod() -> Int32
|
||||
// CHECK: final func swiftParamsRename(a1 i: Int32) -> Int32
|
||||
// CHECK: }
|
||||
|
||||
// CHECK: class C2 {
|
||||
// CHECK: @available(*, unavailable, message: "ignoring{{.*}}")
|
||||
// CHECK: final func swiftVirtualMethod() -> Int32
|
||||
// CHECK: @available(*, unavailable, message: "ignoring{{.*}}")
|
||||
// CHECK: final func C2FooRename() -> Int32
|
||||
// CHECK: @available(*, unavailable, message: "ignoring{{.*}}")
|
||||
// CHECK: final func B1BarRename() -> Int32
|
||||
// CHECK: @available(*, unavailable, message: "ignoring{{.*}}")
|
||||
// CHECK: final func swiftParamsRename(b1 i: Int32) -> Int32
|
||||
// CHECK: final func virtualMethod() -> Int32
|
||||
// CHECK: final func swiftFooRename() -> Int32
|
||||
// CHECK: final func swiftBarRename() -> Int32
|
||||
// CHECK: final func swiftParamsRename(a1 i: Int32) -> Int32
|
||||
// CHECK: }
|
||||
|
||||
// CHECK: class A2 {
|
||||
// CHECK: final func swiftVirtualMethod() -> Int32
|
||||
// CHECK: final func swiftFooRename() -> Int32
|
||||
// CHECK: final func A2BarRename() -> Int32
|
||||
// CHECK: final func swiftParamsRename(a2 i: Int32) -> Int32
|
||||
// CHECK: }
|
||||
|
||||
// CHECK: class D1 {
|
||||
// CHECK: final func virtualMethod() -> Int32
|
||||
// CHECK: final func swiftFooRename() -> Int32
|
||||
// CHECK: final func swiftBarRename() -> Int32
|
||||
// CHECK: final func swiftParamsRename(a1 i: Int32) -> Int32
|
||||
// CHECK: final func swiftVirtualMethod() -> Int32
|
||||
// CHECK: final func A2BarRename() -> Int32
|
||||
// CHECK: final func swiftParamsRename(a2 i: Int32) -> Int32
|
||||
// CHECK: }
|
||||
|
||||
// CHECK: class D2 {
|
||||
// CHECK: @available(*, unavailable, message: "ignoring{{.*}}")
|
||||
// CHECK: final func swiftVirtualMethod() -> Int32
|
||||
// CHECK: @available(*, unavailable, message: "ignoring{{.*}}")
|
||||
// CHECK: final func B1BarRename() -> Int32
|
||||
// CHECK: @available(*, unavailable, message: "ignoring{{.*}}")
|
||||
// CHECK: final func swiftParamsRename(b1 i: Int32) -> Int32
|
||||
// CHECK: @available(*, unavailable, message: "overrides{{.*}}")
|
||||
// CHECK: final func virtualMethod() -> Int32
|
||||
// CHECK: final func swiftFooRename() -> Int32
|
||||
// CHECK: @available(*, unavailable, message: "overrides{{.*}}")
|
||||
// CHECK: final func swiftBarRename() -> Int32
|
||||
// CHECK: @available(*, unavailable, message: "overrides{{.*}}")
|
||||
// CHECK: final func swiftParamsRename(a1 i: Int32) -> Int32
|
||||
// CHECK: @available(*, unavailable, message: "overrides{{.*}}")
|
||||
// CHECK: final func A2BarRename() -> Int32
|
||||
// CHECK: @available(*, unavailable, message: "overrides{{.*}}")
|
||||
// CHECK: final func swiftParamsRename(a2 i: Int32) -> Int32
|
||||
// CHECK: }
|
||||
|
||||
// CHECK: struct D3 {
|
||||
// CHECK: @available(*, unavailable, message: "ignoring{{.*}}")
|
||||
// CHECK: final func swiftVirtualMethod() -> Int32
|
||||
// CHECK: @available(*, unavailable, message: "ignoring{{.*}}")
|
||||
// CHECK: final func B1BarRename() -> Int32
|
||||
// CHECK: @available(*, unavailable, message: "ignoring{{.*}}")
|
||||
// CHECK: final func swiftParamsRename(b1 i: Int32) -> Int32
|
||||
// CHECK: final func virtualMethod() -> Int32
|
||||
// CHECK: final func swiftFooRename() -> Int32
|
||||
// CHECK: final func swiftBarRename() -> Int32
|
||||
// CHECK: final func swiftParamsRename(a1 i: Int32) -> Int32
|
||||
// CHECK: }
|
||||
|
||||
// CHECK: struct D4 {
|
||||
// CHECK: final func swiftFooRename() -> Int32
|
||||
// CHECK: final func swiftBarRename() -> Int32
|
||||
// CHECK: @available(*, unavailable, message: "ignoring{{.*}}")
|
||||
// CHECK: final func swiftVirtualMethod() -> Int32
|
||||
// CHECK: @available(*, unavailable, message: "ignoring{{.*}}")
|
||||
// CHECK: final func B1BarRename() -> Int32
|
||||
// CHECK: @available(*, unavailable, message: "ignoring{{.*}}")
|
||||
// CHECK: final func swiftParamsRename(b1 i: Int32) -> Int32
|
||||
// CHECK: final func virtualMethod() -> Int32
|
||||
// CHECK: final func swiftParamsRename(a1 i: Int32) -> Int32
|
||||
// CHECK: }
|
||||
|
||||
@@ -32,3 +32,94 @@ func callsRenamedVirtualMethodsInFRT(_ i: Immortal2) {
|
||||
i.virtualRename() // expected-error {{value of type 'Immortal2' has no member 'virtualRename'}}
|
||||
i.swiftVirtualRename()
|
||||
}
|
||||
|
||||
@available(SwiftStdlib 5.8, *)
|
||||
func callsOverridesOfRenamedVirtualMethods(
|
||||
_ a1: A1, _ a2: A2, _ b1: B1, _ b2: B2, _ c1: C1, _ c2: C2, _ d1: D1, _ d2: D2, _ d3: D3, _ d4: D4
|
||||
) {
|
||||
a1.virtualMethod()
|
||||
a1.fooRename() // expected-error {{value of type 'A1' has no member 'fooRename'}}
|
||||
a1.swiftFooRename()
|
||||
a1.swiftParamsRename(a1: 42)
|
||||
|
||||
b1.virtualMethod()
|
||||
b1.swiftVirtualMethod() // expected-error {{'swiftVirtualMethod()' is unavailable: ignoring swift_name 'swiftVirtualMethod()' in 'B1'; swift_name attributes have no effect on method overrides}}
|
||||
b1.fooRename() // expected-error {{value of type 'B1' has no member 'fooRename'}}
|
||||
b1.swiftFooRename()
|
||||
b1.barRename() // expected-error {{value of type 'B1' has no member 'barRename'}}
|
||||
b1.swiftBarRename()
|
||||
b1.B1BarRename() // expected-error {{'B1BarRename()' is unavailable: ignoring swift_name 'B1BarRename()' in 'B1'; swift_name attributes have no effect on method overrides}}
|
||||
b1.swiftParamsRename(a1: 42)
|
||||
b1.swiftParamsRename(b1: 42) // expected-error {{'swiftParamsRename(b1:)' is unavailable: ignoring swift_name 'swiftParamsRename(b1:)' in 'B1'; swift_name attributes have no effect on method overrides}}
|
||||
|
||||
b2.virtualMethod()
|
||||
b2.fooRename() // expected-error {{value of type 'B2' has no member 'fooRename'; did you mean 'swiftFooRename'?}}
|
||||
b2.swiftFooRename()
|
||||
b2.B2BarRename() // expected-error {{'B2BarRename()' is unavailable: ignoring swift_name 'B2BarRename()' in 'B2'; swift_name attributes have no effect on method overrides}}
|
||||
b2.swiftParamsRename(a1: 42)
|
||||
|
||||
c1.virtualMethod()
|
||||
c1.swiftVirtualMethod() // expected-error {{'swiftVirtualMethod()' is unavailable: ignoring swift_name 'swiftVirtualMethod()' in 'B1'; swift_name attributes have no effect on method overrides}}
|
||||
c1.fooRename() // expected-error {{value of type 'C1' has no member 'fooRename'}}
|
||||
c1.swiftFooRename()
|
||||
c1.barRename() // expected-error {{value of type 'C1' has no member 'barRename'}}
|
||||
c1.swiftBarRename()
|
||||
c1.B1BarRename() // expected-error {{'B1BarRename()' is unavailable: ignoring swift_name 'B1BarRename()' in 'B1'; swift_name attributes have no effect on method overrides}}
|
||||
c1.paramsRename(42) // expected-error {{value of type 'C1' has no member 'paramsRename'}}
|
||||
c1.swiftParamsRename(42) // expected-error {{missing argument label 'a1:' in call}}
|
||||
c1.swiftParamsRename(a1: 42)
|
||||
|
||||
c2.virtualMethod()
|
||||
c2.swiftVirtualMethod() // expected-error {{'swiftVirtualMethod()' is unavailable: ignoring swift_name 'swiftVirtualMethod()' in 'C2'; swift_name attributes have no effect on method overrides}}
|
||||
c2.fooRename() // expected-error {{value of type 'C2' has no member 'fooRename'}}
|
||||
c2.swiftFooRename()
|
||||
c2.C2FooRename() // expected-error {{'C2FooRename()' is unavailable: ignoring swift_name 'C2FooRename()' in 'C2'; swift_name attributes have no effect on method overrides}}
|
||||
c2.barRename() // expected-error {{value of type 'C2' has no member 'barRename'}}
|
||||
c2.swiftBarRename()
|
||||
c2.B1BarRename() // expected-error {{'B1BarRename()' is unavailable: ignoring swift_name 'B1BarRename()' in 'C2'; swift_name attributes have no effect on method overrides}}
|
||||
c2.paramsRename(42) // expected-error {{value of type 'C2' has no member 'paramsRename'}}
|
||||
c2.swiftParamsRename(a1: 42)
|
||||
c2.swiftParamsRename(b1: 42) // expected-error {{'swiftParamsRename(b1:)' is unavailable: ignoring swift_name 'swiftParamsRename(b1:)' in 'C2'; swift_name attributes have no effect on method overrides}}
|
||||
|
||||
d1.virtualMethod()
|
||||
d1.swiftVirtualMethod()
|
||||
d1.fooRename() // expected-error {{value of type 'D1' has no member 'fooRename'}}
|
||||
d1.swiftFooRename() // expected-error {{ambiguous use of 'swiftFooRename()'}}
|
||||
d1.barRename() // expected-error {{value of type 'D1' has no member 'barRename'}}
|
||||
d1.swiftBarRename()
|
||||
d1.A2BarRename()
|
||||
d1.swiftParamsRename(a1: 42)
|
||||
d1.swiftParamsRename(a2: 42)
|
||||
|
||||
d2.virtualMethod() // expected-error {{'virtualMethod()' is unavailable: overrides multiple C++ methods with different Swift names}}
|
||||
d2.swiftVirtualMethod() // expected-error {{ambiguous use of 'swiftVirtualMethod()'}}
|
||||
d2.fooRename() // expected-error {{value of type 'D2' has no member 'fooRename'}}
|
||||
d2.swiftFooRename() // expected-error {{ambiguous use of 'swiftFooRename()'}}
|
||||
d2.barRename() // expected-error {{value of type 'D2' has no member 'barRename'}}
|
||||
d2.swiftBarRename() // expected-error {{'swiftBarRename()' is unavailable: overrides multiple C++ methods with different Swift names}}
|
||||
d2.A2BarRename() // expected-error {{'A2BarRename()' is unavailable: overrides multiple C++ methods with different Swift names}}
|
||||
d2.swiftParamsRename(a1: 42) // expected-error {{'swiftParamsRename(a1:)' is unavailable: overrides multiple C++ methods with different Swift names}}
|
||||
d2.swiftParamsRename(a2: 42) // expected-error {{'swiftParamsRename(a2:)' is unavailable: overrides multiple C++ methods with different Swift names}}
|
||||
d2.swiftParamsRename(b1: 42) // expected-error {{'swiftParamsRename(b1:)' is unavailable: ignoring swift_name 'swiftParamsRename(b1:)' in 'B1'; swift_name attributes have no effect on method overrides}}
|
||||
|
||||
d3.virtualMethod()
|
||||
d3.swiftVirtualMethod() // expected-error {{'swiftVirtualMethod()' is unavailable: ignoring swift_name 'swiftVirtualMethod()' in 'B1'; swift_name attributes have no effect on method overrides}}
|
||||
d3.fooRename() // expected-error {{value of type 'D3' has no member 'fooRename'}}
|
||||
d3.swiftFooRename()
|
||||
d3.barRename() // expected-error {{value of type 'D3' has no member 'barRename'}}
|
||||
d3.swiftBarRename()
|
||||
d3.B1BarRename() // expected-error {{'B1BarRename()' is unavailable: ignoring swift_name 'B1BarRename()' in 'B1'; swift_name attributes have no effect on method overrides}}
|
||||
d3.swiftParamsRename(a1: 42)
|
||||
d3.swiftParamsRename(b1: 42) // expected-error {{'swiftParamsRename(b1:)' is unavailable: ignoring swift_name 'swiftParamsRename(b1:)' in 'B1'; swift_name attributes have no effect on method overrides}}
|
||||
|
||||
d4.virtualMethod()
|
||||
d4.swiftVirtualMethod() // expected-error {{'swiftVirtualMethod()' is unavailable: ignoring swift_name 'swiftVirtualMethod()' in 'B1'; swift_name attributes have no effect on method overrides}}
|
||||
d4.fooRename() // expected-error {{value of type 'D4' has no member 'fooRename'}}
|
||||
d4.swiftFooRename() // expected-error {{ambiguous use of 'swiftFooRename()'}}
|
||||
d4.barRename() // expected-error {{value of type 'D4' has no member 'barRename'}}
|
||||
d4.swiftBarRename() // expected-error {{ambiguous use of 'swiftBarRename()'}}
|
||||
d4.B1BarRename() // expected-error {{'B1BarRename()' is unavailable: ignoring swift_name 'B1BarRename()' in 'B1'; swift_name attributes have no effect on method overrides}}
|
||||
d4.paramsRename(42) // expected-error {{value of type 'D4' has no member 'paramsRename'}}
|
||||
d4.swiftParamsRename(42) // expected-error {{missing argument label 'a1:' in call}}
|
||||
d4.swiftParamsRename(a1: 42)
|
||||
}
|
||||
|
||||
@@ -111,6 +111,50 @@ if #available(SwiftStdlib 5.8, *) {
|
||||
func f(immortalClass: Immortal2) {
|
||||
immortalClass.swiftVirtualRename()
|
||||
}
|
||||
|
||||
let a1 = A1.create()
|
||||
expectEqual(a1.virtualMethod(), 111)
|
||||
expectEqual(a1.swiftFooRename(), 112)
|
||||
expectEqual(a1.swiftBarRename(), 113)
|
||||
expectEqual(a1.swiftParamsRename(a1: 42), 42)
|
||||
|
||||
let b1 = B1.create()
|
||||
expectEqual(b1.virtualMethod(), 211)
|
||||
expectEqual(b1.swiftFooRename(), 212)
|
||||
expectEqual(b1.swiftBarRename(), 213)
|
||||
expectEqual(b1.swiftParamsRename(a1: 42), 42)
|
||||
|
||||
let b2 = B2.create()
|
||||
expectEqual(b2.virtualMethod(), 221)
|
||||
expectEqual(b2.swiftFooRename(), 222)
|
||||
expectEqual(b2.swiftBarRename(), 223)
|
||||
|
||||
let c1 = C1.create()
|
||||
expectEqual(c1.virtualMethod(), 211)
|
||||
expectEqual(c1.swiftFooRename(), 312)
|
||||
expectEqual(c1.swiftBarRename(), 313)
|
||||
expectEqual(c1.swiftParamsRename(a1: 42), 42)
|
||||
|
||||
let c2 = C2.create()
|
||||
expectEqual(c2.virtualMethod(), 321)
|
||||
expectEqual(c2.swiftFooRename(), 322)
|
||||
expectEqual(c2.swiftBarRename(), 323)
|
||||
expectEqual(c2.swiftParamsRename(a1: 42), 42)
|
||||
|
||||
let a2 = A2.create()
|
||||
expectEqual(a2.swiftVirtualMethod(), 121)
|
||||
expectEqual(a2.swiftFooRename(), 122)
|
||||
expectEqual(a2.A2BarRename(), 123)
|
||||
expectEqual(a2.swiftParamsRename(a2: 42), 43)
|
||||
|
||||
let d1 = D1.create()
|
||||
expectEqual(d1.virtualMethod(), 111)
|
||||
expectEqual(d1.swiftBarRename(), 113)
|
||||
expectEqual(d1.swiftParamsRename(a1: 42), 42)
|
||||
// FIXME the method calls below return incorrect values
|
||||
expectEqual(d1.swiftVirtualMethod(), 111) // should be 121
|
||||
expectEqual(d1.A2BarRename(), 113) // should be 123
|
||||
expectEqual(d1.swiftParamsRename(a2: 42), 42) // should be 43
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user