Weaken the type-matching rules for methods that return aggregates when

complaining about mismatches in the global method pool.

llvm-svn: 133123
This commit is contained in:
John McCall 2011-06-16 01:15:19 +00:00
parent b00e8c0cad
commit 54507ab83c
2 changed files with 53 additions and 2 deletions

View File

@ -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<VectorType>(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<RecordType>(lt) || !isa<RecordType>(rt)) return false;
RecordDecl *left = cast<RecordType>(lt)->getDecl();
RecordDecl *right = cast<RecordType>(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<CXXRecordDecl>(left) && !cast<CXXRecordDecl>(left)->isPOD()) ||
(isa<CXXRecordDecl>(right) && !cast<CXXRecordDecl>(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<p1,p2> in type comparisons

View File

@ -55,3 +55,19 @@ void f5(id a0, Abstract *a1) {
void f6(id<A> 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}}
}