diff options
author | Steve Naroff <snaroff@apple.com> | 2009-03-03 14:49:36 +0000 |
---|---|---|
committer | Steve Naroff <snaroff@apple.com> | 2009-03-03 14:49:36 +0000 |
commit | ca33129bb28b05938c3e6c9f8a66165b5cceb4dd (patch) | |
tree | ccc64a297d056a97f4308211f9b7e1b2cba2e284 | |
parent | 0258eeeac5ecbc67b6a09e3497f3d593db01903b (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.def | 2 | ||||
-rw-r--r-- | lib/Sema/SemaDeclObjC.cpp | 20 | ||||
-rw-r--r-- | test/SemaObjC/class-bitfield.m | 20 |
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 |