[ClangImporter] Don't put method redeclarations in a member list.

Previously we'd try to put the same method into the list of members multiple
times--once for each redeclaration in the @interface. This led to an
assertion failure.

Checking the canonical decl isn't super cheap, but the ObjCMethodDecl
redeclaration infrastructure seems to be fairly broken. We can revisit this
later.

There's also a test for what happens when categories get involved. I'm not
convinced this is correct behavior, either, and will file an additional bug
to look into that at some point.

rdar://problem/19039485

Swift SVN r24129
This commit is contained in:
Jordan Rose
2014-12-23 22:43:30 +00:00
parent 9b009af3be
commit e21abcf405
8 changed files with 88 additions and 7 deletions

View File

@@ -3848,7 +3848,7 @@ namespace {
for (auto m = decl->decls_begin(), mEnd = decl->decls_end();
m != mEnd; ++m) {
auto nd = dyn_cast<clang::NamedDecl>(*m);
if (!nd)
if (!nd || nd != nd->getCanonicalDecl())
continue;
auto member = Impl.importDecl(nd);
@@ -3865,11 +3865,6 @@ namespace {
continue;
}
// If this member is a method that is a getter or setter for a property
// that was imported, don't add it to the list of members so it won't
// be found by name lookup. This eliminates the ambiguity between
// property names and getter names (by choosing to only have a
// variable).
if (auto objcMethod = dyn_cast<clang::ObjCMethodDecl>(nd)) {
// If there is a special declaration associated with this member,
// add it now.
@@ -3906,6 +3901,11 @@ namespace {
// Import explicit properties as instance properties, not as separate
// getter and setter methods.
if (!Impl.isAccessibilityDecl(objcMethod)) {
// If this member is a method that is a getter or setter for a
// propertythat was imported, don't add it to the list of members
// so it won't be found by name lookup. This eliminates the
// ambiguity between property names and getter names (by choosing
// to only have a variable).
if (objcMethod->isPropertyAccessor()) {
auto prop = objcMethod->findPropertyDecl(/*checkOverrides=*/false);
assert(prop);

View File

@@ -92,3 +92,10 @@ __weak id globalWeakVar;
@interface DeprecatedFactoryMethod
+ (instancetype)deprecatedFactoryMethod __attribute__((deprecated("use something newer")));
@end
@interface RepeatedMembers : NSObject
- (void)repeatedMethod;
- (void)anotherMethod;
- (void)repeatedMethod __attribute__((deprecated("use something newer")));
@end

View File

@@ -455,3 +455,7 @@ func testFactoryMethodAvailability() {
let _ = DeprecatedFactoryMethod() // expected-error{{'init()' is unavailable: use something newer}}
}
func testRepeatedMembers(obj: RepeatedMembers) {
obj.repeatedMethod()
}

View File

@@ -254,3 +254,17 @@ class <loc>FooClassDerived</loc> : <ref:Class>FooClassBase</ref>, <ref:Protocol>
<decl:TypeAlias>typealias <loc>FooCFTypeRef</loc> = <ref:Class>FooCFType</ref></decl>
<decl:Func>@availability(*, unavailable, message="Core Foundation objects are automatically memory managed")
func <loc>FooCFTypeRelease(_: <ref:Class>FooCFType</ref>!)</loc></decl>
<decl:Class>class <loc>FooRepeatedMembers</loc> : <ref:Class>FooClassBase</ref> {
<decl:Func>func <loc>repeatedMethod()</loc></decl>
<decl:Func>func <loc>anotherMethod()</loc></decl>
<decl:Constructor><loc>init!()</loc></decl>
<decl:Constructor>convenience <loc>init!(float f: <ref:Struct>Float</ref>)</loc></decl>
}</decl>
<decl:Extension>extension <ref:Class><loc>FooRepeatedMembers</ref></loc> {
<decl:Var>var <loc>repeatedPropertyInCategory</loc>: <ref:Struct>Int32</ref></decl>
<decl:Func>func <loc>repeatedMethodInCategory()</loc></decl>
<decl:Var>var <loc>repeatedPropertyFromCategory</loc>: <ref:Struct>Int32</ref></decl>
<decl:Func>func <loc>repeatedMethodFromCategory()</loc></decl>
}</decl>
<decl:Extension>extension <ref:Class><loc>FooRepeatedMembers</ref></loc> {
}</decl>

View File

@@ -260,4 +260,27 @@ struct _InternalStruct {
typedef struct __FooCFType *FooCFTypeRef;
void FooCFTypeRelease(FooCFTypeRef);
@interface FooRepeatedMembers : FooClassBase
- (void)repeatedMethod;
- (void)anotherMethod;
- (void)repeatedMethod;
@property int repeatedPropertyInCategory;
- (void)repeatedMethodInCategory;
@end
@interface FooRepeatedMembers (Category)
@property int repeatedPropertyInCategory;
- (void)repeatedMethodInCategory;
@property int repeatedPropertyFromCategory;
- (void)repeatedMethodFromCategory;
@end
@interface FooRepeatedMembers (AnotherCategory)
@property int repeatedPropertyFromCategory;
- (void)repeatedMethodFromCategory;
@end
#endif /* ! __FOO_H__ */

View File

@@ -254,6 +254,20 @@ class FooUnavailableMembers : FooClassBase {
typealias FooCFTypeRef = FooCFType
@availability(*, unavailable, message="Core Foundation objects are automatically memory managed")
func FooCFTypeRelease(_: FooCFType!)
class FooRepeatedMembers : FooClassBase {
func repeatedMethod()
func anotherMethod()
init!()
convenience init!(float f: Float)
}
extension FooRepeatedMembers {
var repeatedPropertyInCategory: Int32
func repeatedMethodInCategory()
var repeatedPropertyFromCategory: Int32
func repeatedMethodFromCategory()
}
extension FooRepeatedMembers {
}
func fooSubFunc1(a: Int32) -> Int32
struct FooSubEnum1 {
init(_ value: UInt32)

View File

@@ -308,3 +308,21 @@ class FooUnavailableMembers : FooClassBase {
typealias FooCFTypeRef = FooCFType
@availability(*, unavailable, message="Core Foundation objects are automatically memory managed")
func FooCFTypeRelease(_: FooCFType!)
class FooRepeatedMembers : FooClassBase {
func repeatedMethod()
func anotherMethod()
init!()
convenience init!(float f: Float)
}
extension FooRepeatedMembers {
var repeatedPropertyInCategory: Int32
func repeatedMethodInCategory()
var repeatedPropertyFromCategory: Int32
func repeatedMethodFromCategory()
}
extension FooRepeatedMembers {
}

View File

@@ -144,7 +144,7 @@ func testCompleteModuleQualifiedFoo2() {
Foo#^CLANG_QUAL_FOO_2^#
// If the number of results below changes, then you need to add a result to the
// list below.
// CLANG_QUAL_FOO_2: Begin completions, 61 items
// CLANG_QUAL_FOO_2: Begin completions, 62 items
// CLANG_QUAL_FOO_2-DAG: Decl[Class]/OtherModule: .FooClassBase[#FooClassBase#]{{$}}
// CLANG_QUAL_FOO_2-DAG: Decl[Class]/OtherModule: .FooClassDerived[#FooClassDerived#]{{$}}
// CLANG_QUAL_FOO_2-DAG: Decl[Class]/OtherModule: .ClassWithInternalProt[#ClassWithInternalProt#]{{$}}
@@ -206,6 +206,7 @@ func testCompleteModuleQualifiedFoo2() {
// CLANG_QUAL_FOO_2-DAG: Decl[Class]/OtherModule: .FooUnavailableMembers[#FooUnavailableMembers#]
// CLANG_QUAL_FOO_2-DAG: Decl[TypeAlias]/OtherModule: .FooTypedef1[#Int32#]{{$}}
// CLANG_QUAL_FOO_2-DAG: Decl[TypeAlias]/OtherModule: .FooCFTypeRef[#FooCFType#]{{$}}
// CLANG_QUAL_FOO_2-DAG: Decl[Class]/OtherModule: .FooRepeatedMembers[#FooRepeatedMembers#]{{$}}
// CLANG_QUAL_FOO_2: End completions
}