From: John McCall Date: Thu, 16 Jun 2011 01:15:19 +0000 (+0000) Subject: Weaken the type-matching rules for methods that return aggregates when X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0f4c4c4445b194db6a086ea91ec8e7af963a456c;p=clang Weaken the type-matching rules for methods that return aggregates when complaining about mismatches in the global method pool. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@133123 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 563de6fd15..b54e2425b2 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -1652,6 +1652,10 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc, return CDecl; } +static bool tryMatchRecordTypes(ASTContext &Context, + Sema::MethodMatchStrategy strategy, + const Type *left, const Type *right); + static bool matchTypes(ASTContext &Context, Sema::MethodMatchStrategy strategy, QualType leftQT, QualType rightQT) { const Type *left = @@ -1681,10 +1685,11 @@ static bool matchTypes(ASTContext &Context, Sema::MethodMatchStrategy strategy, if (isa(right)) return false; // - references should only match references of identical type - // - structs, unions, and Objective-C objects must match exactly + // - structs, unions, and Objective-C objects must match more-or-less + // exactly // - everything else should be a scalar if (!left->isScalarType() || !right->isScalarType()) - return false; + return tryMatchRecordTypes(Context, strategy, left, right); // Make scalars agree in kind, except count bools as chars. Type::ScalarTypeKind leftSK = left->getScalarTypeKind(); @@ -1698,6 +1703,36 @@ static bool matchTypes(ASTContext &Context, Sema::MethodMatchStrategy strategy, return (leftSK == rightSK); } +static bool tryMatchRecordTypes(ASTContext &Context, + Sema::MethodMatchStrategy strategy, + const Type *lt, const Type *rt) { + assert(lt && rt && lt != rt); + + if (!isa(lt) || !isa(rt)) return false; + RecordDecl *left = cast(lt)->getDecl(); + RecordDecl *right = cast(rt)->getDecl(); + + // Require union-hood to match. + if (left->isUnion() != right->isUnion()) return false; + + // Require an exact match if either is non-POD. + if ((isa(left) && !cast(left)->isPOD()) || + (isa(right) && !cast(right)->isPOD())) + return false; + + // Require size and alignment to match. + if (Context.getTypeInfo(lt) != Context.getTypeInfo(rt)) return false; + + // Require fields to match. + RecordDecl::field_iterator li = left->field_begin(), le = left->field_end(); + RecordDecl::field_iterator ri = right->field_begin(), re = right->field_end(); + for (; li != le && ri != re; ++li, ++ri) { + if (!matchTypes(Context, strategy, li->getType(), ri->getType())) + return false; + } + return (li == le && ri == re); +} + /// MatchTwoMethodDeclarations - Checks that two methods have matching type and /// returns true, or false, accordingly. /// TODO: Handle protocol list; such as id in type comparisons diff --git a/test/SemaObjC/method-lookup-3.m b/test/SemaObjC/method-lookup-3.m index 882b3d1d21..b3d9c46484 100644 --- a/test/SemaObjC/method-lookup-3.m +++ b/test/SemaObjC/method-lookup-3.m @@ -55,3 +55,19 @@ void f5(id a0, Abstract *a1) { void f6(id a0) { Abstract *l = [a0 x]; } + +struct test3a { int x, y; }; +struct test3b { unsigned x, y; }; +@interface Test3A - (struct test3a) test3; @end +@interface Test3B - (struct test3b) test3; @end +void test3(id x) { + (void) [x test3]; +} + +struct test4a { int x, y; }; +struct test4b { float x, y; }; +@interface Test4A - (struct test4a) test4; @end //expected-note{{using}} +@interface Test4B - (struct test4b) test4; @end //expected-note{{also found}} +void test4(id x) { + (void) [x test4]; //expected-warning {{multiple methods named 'test4' found}} +}