]> granicus.if.org Git - clang/commitdiff
fix rdar://6611778, a redefinition of an interface was causing an
authorChris Lattner <sabre@nondot.org>
Mon, 23 Feb 2009 22:00:08 +0000 (22:00 +0000)
committerChris Lattner <sabre@nondot.org>
Mon, 23 Feb 2009 22:00:08 +0000 (22:00 +0000)
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

lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclObjC.cpp
test/Sema/anonymous-struct-union.c
test/Sema/nested-redef.c
test/SemaObjC/interface-1.m
test/SemaObjC/ivar-sem-check-1.m

index 4ec2dc6968b5004c7bfb3fa51b6886c31c25a2f2..1786b6372b0859209db9abc550b60ac93b587386 100644 (file)
@@ -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);
index 660f745228b8252f31fc1d5ff9a29c0565d06e3e..b3644a5ab9c0e7d9c9843f0a6ef9d579e6aefcc8 100644 (file)
@@ -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)
index 72790c9abb400f9783e3df154ece0ec03cd6d866..b288f6278a36df3b29f059672b3aa036834bdb88 100644 (file)
@@ -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}}
index 83cd4209675c586b3166cae910a00204471e8b0e..b0b12805e6819849ac4d5bfe4907db2479d21b33 100644 (file)
@@ -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 { };
index ea77050505480562942eda61e77d86850574b0ed..b974b39a3a8b59c64957d3170274257890eb16d4 100644 (file)
@@ -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
+
index 1ec4e57ce84efb7ca0d95a428ad37ffe503fe11d..1833a0f457b2cd6445895a17a079cf7c73fd6889 100644 (file)
@@ -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}}