diff options
author | John McCall <rjmccall@apple.com> | 2011-06-16 01:15:19 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2011-06-16 01:15:19 +0000 |
commit | 0f4c4c4445b194db6a086ea91ec8e7af963a456c (patch) | |
tree | 3ff1a114163cc7e4e415420f06217b6f1555b4f3 /lib/Sema/SemaDeclObjC.cpp | |
parent | f0b60d6a945b907f890e0bbc2aa02b5aa2bc62e3 (diff) |
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
Diffstat (limited to 'lib/Sema/SemaDeclObjC.cpp')
-rw-r--r-- | lib/Sema/SemaDeclObjC.cpp | 39 |
1 files changed, 37 insertions, 2 deletions
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<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 |