aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2009-02-23 22:00:08 +0000
committerChris Lattner <sabre@nondot.org>2009-02-23 22:00:08 +0000
commit1829a6db2ec19e08061f0bb2f4c52a8e5e4efaf0 (patch)
tree5e6ec0f846885aefd6f18f3dbdaa9bc6e38c8c47
parent60ff8ce5b2fda9c2a510f15d8b8504d0fc8c8e2f (diff)
fix rdar://6611778, a redefinition of an interface was causing an
assertion when the ivars and method list was reset into the existing interface. To fix this, mark decls as invalid when they are redefined, and don't insert ivars/methods into invalid decls. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65340 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/SemaDecl.cpp15
-rw-r--r--lib/Sema/SemaDeclObjC.cpp5
-rw-r--r--test/Sema/anonymous-struct-union.c3
-rw-r--r--test/Sema/nested-redef.c3
-rw-r--r--test/SemaObjC/interface-1.m10
-rw-r--r--test/SemaObjC/ivar-sem-check-1.m3
6 files changed, 29 insertions, 10 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 4ec2dc6968..1786b6372b 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -3665,12 +3665,20 @@ void Sema::ActOnFields(Scope* S,
AttributeList *Attr) {
Decl *EnclosingDecl = static_cast<Decl*>(RecDecl);
assert(EnclosingDecl && "missing record or interface decl");
- RecordDecl *Record = dyn_cast<RecordDecl>(EnclosingDecl);
+
+ // If the decl this is being inserted into is invalid, then it may be a
+ // redeclaration or some other bogus case. Don't try to add fields to it.
+ if (EnclosingDecl->isInvalidDecl()) {
+ // FIXME: Deallocate fields?
+ return;
+ }
+
// Verify that all the fields are okay.
unsigned NumNamedMembers = 0;
llvm::SmallVector<FieldDecl*, 32> RecFields;
+ RecordDecl *Record = dyn_cast<RecordDecl>(EnclosingDecl);
for (unsigned i = 0; i != NumFields; ++i) {
FieldDecl *FD = cast_or_null<FieldDecl>(static_cast<Decl*>(Fields[i]));
assert(FD && "missing field decl");
@@ -3782,9 +3790,8 @@ void Sema::ActOnFields(Scope* S,
}
}
}
- }
- else if (ObjCImplementationDecl *IMPDecl =
- dyn_cast<ObjCImplementationDecl>(EnclosingDecl)) {
+ } else if (ObjCImplementationDecl *IMPDecl =
+ dyn_cast<ObjCImplementationDecl>(EnclosingDecl)) {
assert(IMPDecl && "ActOnFields - missing ObjCImplementationDecl");
IMPDecl->setIVarList(ClsFields, RecFields.size(), Context);
CheckImplementationIvars(IMPDecl, ClsFields, RecFields.size(), RBrac);
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 660f745228..b3644a5ab9 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -78,6 +78,7 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
if (IDecl) {
// Class already seen. Is it a forward declaration?
if (!IDecl->isForwardDecl()) {
+ IDecl->setInvalidDecl();
Diag(AtInterfaceLoc, diag::err_duplicate_class_def)<<IDecl->getDeclName();
Diag(IDecl->getLocation(), diag::note_previous_definition);
@@ -225,6 +226,7 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc,
if (PDecl) {
// Protocol already seen. Better be a forward protocol declaration
if (!PDecl->isForwardDecl()) {
+ PDecl->setInvalidDecl();
Diag(ProtocolLoc, diag::err_duplicate_protocol_def) << ProtocolName;
Diag(PDecl->getLocation(), diag::note_previous_definition);
// Just return the protocol we already had.
@@ -555,8 +557,7 @@ Sema::DeclTy *Sema::ActOnStartClassImplementation(
if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {
Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName;
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
- }
- else {
+ } else {
// Is there an interface declaration of this class; if not, warn!
IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
if (!IDecl)
diff --git a/test/Sema/anonymous-struct-union.c b/test/Sema/anonymous-struct-union.c
index 72790c9abb..b288f6278a 100644
--- a/test/Sema/anonymous-struct-union.c
+++ b/test/Sema/anonymous-struct-union.c
@@ -47,8 +47,7 @@ struct Redecl {
};
int z; // expected-error{{duplicate member 'z'}}
- void zz(); // expected-error{{duplicate member 'zz'}} \
- // expected-error{{field 'zz' declared as a function}}
+ void zz(); // expected-error{{duplicate member 'zz'}}
};
union { // expected-error{{anonymous unions must be struct or union members}}
diff --git a/test/Sema/nested-redef.c b/test/Sema/nested-redef.c
index 83cd420967..b0b12805e6 100644
--- a/test/Sema/nested-redef.c
+++ b/test/Sema/nested-redef.c
@@ -1,6 +1,7 @@
// RUN: clang -fsyntax-only -verify %s
struct X { // expected-note{{previous definition is here}}
- struct X { } x; // expected-error{{nested redefinition of 'X'}}
+ struct X { } x; // expected-error{{nested redefinition of 'X'}} \
+ expected-error {{field has incomplete type}}
};
struct Y { };
diff --git a/test/SemaObjC/interface-1.m b/test/SemaObjC/interface-1.m
index ea77050505..b974b39a3a 100644
--- a/test/SemaObjC/interface-1.m
+++ b/test/SemaObjC/interface-1.m
@@ -25,3 +25,13 @@ void test2() {
++c;
}
+
+// rdar://6611778
+@interface FOO // expected-note {{previous definition is here}}
+- (void)method;
+@end
+
+@interface FOO // expected-error {{duplicate interface definition for class 'FOO'}}
+- (void)method2;
+@end
+
diff --git a/test/SemaObjC/ivar-sem-check-1.m b/test/SemaObjC/ivar-sem-check-1.m
index 1ec4e57ce8..1833a0f457 100644
--- a/test/SemaObjC/ivar-sem-check-1.m
+++ b/test/SemaObjC/ivar-sem-check-1.m
@@ -9,7 +9,8 @@ typedef int FOO();
int arr[]; // expected-error {{field has incomplete type}}
struct S IC; // expected-error {{field has incomplete type}}
struct T { // expected-note {{previous definition is here}}
- struct T {} X; // expected-error {{nested redefinition of 'T'}}
+ struct T {} X; // expected-error {{nested redefinition of 'T'}} \
+ expected-error {{field has incomplete type}}
}YYY;
FOO BADFUNC; // expected-error {{field 'BADFUNC' declared as a function}}
int kaka; // expected-note {{previous declaration is here}}