aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Naroff <snaroff@apple.com>2009-03-03 14:49:36 +0000
committerSteve Naroff <snaroff@apple.com>2009-03-03 14:49:36 +0000
commitca33129bb28b05938c3e6c9f8a66165b5cceb4dd (patch)
treeccc64a297d056a97f4308211f9b7e1b2cba2e284
parent0258eeeac5ecbc67b6a09e3497f3d593db01903b (diff)
Fix <rdar://problem/6497608> clang does not catch ivar type mismatches in @implementation.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65948 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.def2
-rw-r--r--lib/Sema/SemaDeclObjC.cpp20
-rw-r--r--test/SemaObjC/class-bitfield.m20
3 files changed, 37 insertions, 5 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.def b/include/clang/Basic/DiagnosticSemaKinds.def
index 042b155479..83fe15ebf8 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.def
+++ b/include/clang/Basic/DiagnosticSemaKinds.def
@@ -156,6 +156,8 @@ DIAG(err_dup_implementation_class, ERROR,
"reimplementation of class %0")
DIAG(err_conflicting_ivar_type, ERROR,
"instance variable %0 has conflicting type: %1 vs %2")
+DIAG(err_conflicting_ivar_bitwidth, ERROR,
+ "instance variable %0 has conflicting bitfield width")
DIAG(err_conflicting_ivar_name, ERROR,
"conflicting instance variable names: %0 vs %1")
DIAG(err_inconsistant_ivar_count, ERROR,
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 59b6e93971..19a2a636db 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "Sema.h"
+#include "clang/AST/Expr.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/Parse/DeclSpec.h"
@@ -688,20 +689,29 @@ void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl,
ObjCIvarDecl* ClsIvar = *IVI;
assert (ImplIvar && "missing implementation ivar");
assert (ClsIvar && "missing class ivar");
+
+ // First, make sure the types match.
if (Context.getCanonicalType(ImplIvar->getType()) !=
Context.getCanonicalType(ClsIvar->getType())) {
Diag(ImplIvar->getLocation(), diag::err_conflicting_ivar_type)
<< ImplIvar->getIdentifier()
<< ImplIvar->getType() << ClsIvar->getType();
Diag(ClsIvar->getLocation(), diag::note_previous_definition);
- }
- // TODO: Two mismatched (unequal width) Ivar bitfields should be diagnosed
- // as error.
- else if (ImplIvar->getIdentifier() != ClsIvar->getIdentifier()) {
+ } else if (ImplIvar->isBitField() && ClsIvar->isBitField()) {
+ Expr *ImplBitWidth = ImplIvar->getBitWidth();
+ Expr *ClsBitWidth = ClsIvar->getBitWidth();
+ if (ImplBitWidth->getIntegerConstantExprValue(Context).getZExtValue() !=
+ ClsBitWidth->getIntegerConstantExprValue(Context).getZExtValue()) {
+ Diag(ImplBitWidth->getLocStart(), diag::err_conflicting_ivar_bitwidth)
+ << ImplIvar->getIdentifier();
+ Diag(ClsBitWidth->getLocStart(), diag::note_previous_definition);
+ }
+ }
+ // Make sure the names are identical.
+ if (ImplIvar->getIdentifier() != ClsIvar->getIdentifier()) {
Diag(ImplIvar->getLocation(), diag::err_conflicting_ivar_name)
<< ImplIvar->getIdentifier() << ClsIvar->getIdentifier();
Diag(ClsIvar->getLocation(), diag::note_previous_definition);
- return;
}
--numIvars;
}
diff --git a/test/SemaObjC/class-bitfield.m b/test/SemaObjC/class-bitfield.m
index 713a898fa0..a67927f3be 100644
--- a/test/SemaObjC/class-bitfield.m
+++ b/test/SemaObjC/class-bitfield.m
@@ -15,3 +15,23 @@
}
@end
+@interface Base {
+ int i;
+}
+@end
+
+@interface WithBitfields: Base {
+ void *isa; // expected-note {{previous definition is here}}
+ unsigned a: 5;
+ signed b: 4;
+ int c: 5; // expected-note {{previous definition is here}}
+}
+@end
+
+@implementation WithBitfields {
+ char *isa; // expected-error {{instance variable 'isa' has conflicting type: 'char *' vs 'void *'}}
+ unsigned a: 5;
+ signed b: 4;
+ int c: 3; // expected-error {{instance variable 'c' has conflicting bitfield width}}
+}
+@end