aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDeclObjC.cpp
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2011-06-16 01:15:19 +0000
committerJohn McCall <rjmccall@apple.com>2011-06-16 01:15:19 +0000
commit0f4c4c4445b194db6a086ea91ec8e7af963a456c (patch)
tree3ff1a114163cc7e4e415420f06217b6f1555b4f3 /lib/Sema/SemaDeclObjC.cpp
parentf0b60d6a945b907f890e0bbc2aa02b5aa2bc62e3 (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.cpp39
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