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
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 4ec2dc6..1786b63 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -3665,12 +3665,20 @@
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 @@
}
}
}
- }
- 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 660f745..b3644a5 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -78,6 +78,7 @@
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 @@
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 @@
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 72790c9..b288f62 100644
--- a/test/Sema/anonymous-struct-union.c
+++ b/test/Sema/anonymous-struct-union.c
@@ -47,8 +47,7 @@
};
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 83cd420..b0b1280 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 ea77050..b974b39 100644
--- a/test/SemaObjC/interface-1.m
+++ b/test/SemaObjC/interface-1.m
@@ -25,3 +25,13 @@
++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 1ec4e57..1833a0f 100644
--- a/test/SemaObjC/ivar-sem-check-1.m
+++ b/test/SemaObjC/ivar-sem-check-1.m
@@ -9,7 +9,8 @@
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}}