]> granicus.if.org Git - clang/commitdiff
Switch initialization of the protocol list for an interface decl to use
authorChris Lattner <sabre@nondot.org>
Mon, 21 Jul 2008 07:06:49 +0000 (07:06 +0000)
committerChris Lattner <sabre@nondot.org>
Mon, 21 Jul 2008 07:06:49 +0000 (07:06 +0000)
the standard "set these as the list of protocols" interface instead of a
strange "set this as the size and then set each one to the value" interface.
The problem with the later is that it a) is completely different from
everything else, b) is awkward, and c) doesn't handle the case when a
referenced protocol is invalid: it set it to null.

This meant that all clients downstream would have to handle null protocols
in the protocol list, and empirically they didn't.  Fix this by not setting
invalid protocols in the referenced protocol list, fixing the crash on
test/Sema/objc-interface-1.m

While I'm at it, clean up some locations so that we produce:

t.m:1:25: error: cannot find interface declaration for 'NSObject', superclass of 'NSWhatever'
@interface NSWhatever : NSObject <NSCopying>
~~~~~~~~~~~~~~~~~~~~~   ^

instead of:

t.m:1:1: error: cannot find interface declaration for 'NSObject', superclass of 'NSWhatever'
@interface NSWhatever : NSObject <NSCopying>
^

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@53846 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/DeclObjC.h
lib/AST/DeclObjC.cpp
lib/Sema/Sema.cpp
lib/Sema/SemaDeclObjC.cpp
test/Sema/objc-interface-1.m [new file with mode: 0644]

index 89499f65a7068deca3b2793e886f9a27ce534179..8c8325fb671635a89bbc94eafb76edc3368641b5 100644 (file)
@@ -257,10 +257,8 @@ class ObjCInterfaceDecl : public NamedDecl, public DeclContext {
   SourceLocation EndLoc; // marks the '>', '}', or identifier.
   SourceLocation AtEndLoc; // marks the end of the entire interface.
 
-  ObjCInterfaceDecl(SourceLocation atLoc,
-                    unsigned numRefProtos,
-                    IdentifierInfo *Id, SourceLocation CLoc,
-                    bool FD, bool isInternal)
+  ObjCInterfaceDecl(SourceLocation atLoc, IdentifierInfo *Id,
+                    SourceLocation CLoc, bool FD, bool isInternal)
     : NamedDecl(ObjCInterface, atLoc, Id), DeclContext(ObjCInterface),
       TypeForDecl(0), SuperClass(0),
       ReferencedProtocols(0), NumReferencedProtocols(0), Ivars(0), 
@@ -270,7 +268,6 @@ class ObjCInterfaceDecl : public NamedDecl, public DeclContext {
       CategoryList(0), PropertyDecl(0), NumPropertyDecl(0),
       ForwardDecl(FD), InternalInterface(isInternal),
       ClassLoc(CLoc) {
-        AllocIntfRefProtocols(numRefProtos);
       }
   
   virtual ~ObjCInterfaceDecl();
@@ -282,22 +279,11 @@ public:
 
   static ObjCInterfaceDecl *Create(ASTContext &C,
                                    SourceLocation atLoc,
-                                   unsigned numRefProtos, 
                                    IdentifierInfo *Id, 
                                    SourceLocation ClassLoc = SourceLocation(),
                                    bool ForwardDecl = false,
                                    bool isInternal = false);
   
-  // This is necessary when converting a forward declaration to a definition.
-  void AllocIntfRefProtocols(unsigned numRefProtos) {
-    if (numRefProtos) {
-      ReferencedProtocols = new ObjCProtocolDecl*[numRefProtos];
-      memset(ReferencedProtocols, '\0',
-             numRefProtos*sizeof(ObjCProtocolDecl*));
-      NumReferencedProtocols = numRefProtos;
-    }
-  }
-  
   ObjCProtocolDecl **getReferencedProtocols() const { 
     return ReferencedProtocols; 
   }
@@ -333,7 +319,12 @@ public:
   classmeth_iterator classmeth_end() const {
     return ClassMethods+NumClassMethods;
   }
+
   
+  /// addReferencedProtocols - Set the list of protocols that this interface
+  /// implements.
+  void addReferencedProtocols(ObjCProtocolDecl **OID, unsigned numRefProtos);
+   
   void addInstanceVariablesToClass(ObjCIvarDecl **ivars, unsigned numIvars,
                                    SourceLocation RBracLoc);
 
@@ -358,11 +349,6 @@ public:
   bool isForwardDecl() const { return ForwardDecl; }
   void setForwardDecl(bool val) { ForwardDecl = val; }
   
-  void setIntfRefProtocols(unsigned idx, ObjCProtocolDecl *OID) {
-    assert((idx < NumReferencedProtocols) && "index out of range");
-    ReferencedProtocols[idx] = OID;
-  }
-  
   ObjCInterfaceDecl *getSuperClass() const { return SuperClass; }
   void setSuperClass(ObjCInterfaceDecl * superCls) { SuperClass = superCls; }
   
index ef3b2d74fb9b10546cd9a419886ba704393c43fc..a1011b830e10c5e3eb8b543f33f62ae69bcd652c 100644 (file)
@@ -52,13 +52,11 @@ void ObjCMethodDecl::Destroy(ASTContext& C) {
 
 ObjCInterfaceDecl *ObjCInterfaceDecl::Create(ASTContext &C,
                                              SourceLocation atLoc,
-                                             unsigned numRefProtos,
                                              IdentifierInfo *Id, 
                                              SourceLocation ClassLoc,
                                              bool ForwardDecl, bool isInternal){
   void *Mem = C.getAllocator().Allocate<ObjCInterfaceDecl>();
-  return new (Mem) ObjCInterfaceDecl(atLoc, numRefProtos,
-                                     Id, ClassLoc, ForwardDecl,
+  return new (Mem) ObjCInterfaceDecl(atLoc, Id, ClassLoc, ForwardDecl,
                                      isInternal);
 }
 
@@ -282,6 +280,18 @@ ObjCIvarDecl *
   return 0;
 }
 
+/// addReferencedProtocols - Set the list of protocols that this interface
+/// implements.
+void ObjCInterfaceDecl::addReferencedProtocols(ObjCProtocolDecl **OID, 
+                                               unsigned numRefProtos) {
+  assert(NumReferencedProtocols == 0 && "refproto already set!");
+  NumReferencedProtocols = numRefProtos;
+  if (numRefProtos) {
+    ReferencedProtocols = new ObjCProtocolDecl*[numRefProtos];
+    memcpy(ReferencedProtocols, OID, numRefProtos*sizeof(ObjCProtocolDecl*));
+  }
+}
+
 /// ObjCAddInstanceVariablesToClass - Inserts instance variables
 /// into ObjCInterfaceDecl's fields.
 ///
index 61a8948e4d76409a53b73469c417a035712f3139..32c769b64d98f61f9af2ce11abc893dd793b4f25 100644 (file)
@@ -53,7 +53,8 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
   if (!PP.getLangOptions().ObjC1) return;
   
   // Synthesize "typedef struct objc_selector *SEL;"
-  RecordDecl *SelTag = RecordDecl::Create(Context, TagDecl::TK_struct, CurContext,
+  RecordDecl *SelTag = RecordDecl::Create(Context, TagDecl::TK_struct,
+                                          CurContext,
                                           SourceLocation(), 
                                           &Context.Idents.get("objc_selector"),
                                           0);
@@ -82,7 +83,7 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
   Context.setObjCClassType(ClassTypedef);
   // Synthesize "@class Protocol;
   ObjCInterfaceDecl *ProtocolDecl =
-    ObjCInterfaceDecl::Create(Context, SourceLocation(), 0, 
+    ObjCInterfaceDecl::Create(Context, SourceLocation(),
                               &Context.Idents.get("Protocol"), 
                               SourceLocation(), true);
   Context.setObjCProtoType(Context.getObjCInterfaceType(ProtocolDecl));
index 5b6bd104a90b9aebee38e37dacfa3fc3beaead58..2f12a6ffdad8c4f48077e3f39635ed7febe99401 100644 (file)
@@ -92,11 +92,9 @@ Sema::DeclTy *Sema::ActOnStartClassInterface(
     else {
       IDecl->setLocation(AtInterfaceLoc);
       IDecl->setForwardDecl(false);
-      IDecl->AllocIntfRefProtocols(NumProtocols);
     }
-  }
-  else {
-    IDecl = ObjCInterfaceDecl::Create(Context, AtInterfaceLoc, NumProtocols,
+  } else {
+    IDecl = ObjCInterfaceDecl::Create(Context, AtInterfaceLoc,
                                       ClassName, ClassLoc);
   
     ObjCInterfaceDecls[ClassName] = IDecl;
@@ -118,10 +116,10 @@ Sema::DeclTy *Sema::ActOnStartClassInterface(
       SuperClassEntry = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); 
                               
       if (!SuperClassEntry || SuperClassEntry->isForwardDecl()) {
-        Diag(AtInterfaceLoc, diag::err_undef_superclass, 
+        Diag(SuperLoc, diag::err_undef_superclass, 
              SuperClassEntry ? SuperClassEntry->getName() 
                              : SuperName->getName(),
-             ClassName->getName()); 
+             ClassName->getName(), SourceRange(AtInterfaceLoc, ClassLoc));
       }
     }
     IDecl->setSuperClass(SuperClassEntry);
@@ -133,14 +131,18 @@ Sema::DeclTy *Sema::ActOnStartClassInterface(
   
   /// Check then save referenced protocols
   if (NumProtocols) {
+    llvm::SmallVector<ObjCProtocolDecl*, 8> RefProtos;
     for (unsigned int i = 0; i != NumProtocols; i++) {
       ObjCProtocolDecl* RefPDecl = ObjCProtocols[ProtocolNames[i]];
       if (!RefPDecl || RefPDecl->isForwardDecl())
-        Diag(ClassLoc, diag::warn_undef_protocolref,
+        Diag(EndProtoLoc, diag::warn_undef_protocolref,
              ProtocolNames[i]->getName(),
              ClassName->getName());
-      IDecl->setIntfRefProtocols(i, RefPDecl);
+      else
+        RefProtos.push_back(RefPDecl);
     }
+    if (!RefProtos.empty())
+      IDecl->addReferencedProtocols(&RefProtos[0], RefProtos.size());
     IDecl->setLocEnd(EndProtoLoc);
   }
   return IDecl;
@@ -350,26 +352,23 @@ void
 Sema::MergeProtocolPropertiesIntoClass(ObjCInterfaceDecl *IDecl,
                                        DeclTy *MergeItsProtocols) {
   Decl *ClassDecl = static_cast<Decl *>(MergeItsProtocols);
-  if (ObjCInterfaceDecl *MDecl = 
-      dyn_cast<ObjCInterfaceDecl>(ClassDecl)) {
+  if (ObjCInterfaceDecl *MDecl = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) {
     for (ObjCInterfaceDecl::protocol_iterator P = MDecl->protocol_begin(),
          E = MDecl->protocol_end(); P != E; ++P)
-      MergeOneProtocolPropertiesIntoClass(IDecl, (*P));
       // Merge properties of class (*P) into IDECL's
-      ;
+      MergeOneProtocolPropertiesIntoClass(IDecl, *P);
+    
     // Go thru the list of protocols for this class and recursively merge
     // their properties into this class as well.
     for (ObjCInterfaceDecl::protocol_iterator P = IDecl->protocol_begin(),
          E = IDecl->protocol_end(); P != E; ++P)
-      MergeProtocolPropertiesIntoClass(IDecl, (*P));
-  }
-  else if (ObjCProtocolDecl *MDecl = 
-           dyn_cast<ObjCProtocolDecl>(ClassDecl))
+      MergeProtocolPropertiesIntoClass(IDecl, *P);
+  } else {
+    ObjCProtocolDecl *MDecl = cast<ObjCProtocolDecl>(ClassDecl);
     for (ObjCProtocolDecl::protocol_iterator P = MDecl->protocol_begin(),
          E = MDecl->protocol_end(); P != E; ++P)
       MergeOneProtocolPropertiesIntoClass(IDecl, (*P));
-  else
-    assert(false && "MergeProtocolPropertiesIntoClass - bad object kind");
+  }
 }
 
 /// ActOnForwardProtocolDeclaration - 
@@ -509,7 +508,7 @@ Sema::DeclTy *Sema::ActOnStartClassImplementation(
   if (!IDecl) {
     // Legacy case of @implementation with no corresponding @interface.
     // Build, chain & install the interface decl into the identifier.
-    IDecl = ObjCInterfaceDecl::Create(Context, AtClassImplLoc, 0, ClassName, 
+    IDecl = ObjCInterfaceDecl::Create(Context, AtClassImplLoc, ClassName, 
                                       ClassLoc, false, true);
     ObjCInterfaceDecls[ClassName] = IDecl;
     IDecl->setSuperClass(SDecl);
@@ -726,7 +725,7 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
     }
     ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); 
     if (!IDecl) {  // Not already seen?  Make a forward decl.
-      IDecl = ObjCInterfaceDecl::Create(Context, AtClassLoc, 0, IdentList[i],
+      IDecl = ObjCInterfaceDecl::Create(Context, AtClassLoc, IdentList[i],
                                         SourceLocation(), true);
       ObjCInterfaceDecls[IdentList[i]] = IDecl;
 
diff --git a/test/Sema/objc-interface-1.m b/test/Sema/objc-interface-1.m
new file mode 100644 (file)
index 0000000..0e02542
--- /dev/null
@@ -0,0 +1,8 @@
+// RUN: clang %s -fsyntax-only -verify
+// rdar://5957506
+
+@interface NSWhatever :
+NSObject     // expected-error {{cannot find interface declaration for 'NSObject'}}
+<NSCopying>  // expected-error {{cannot find protocol definition for 'NSCopying'}}
+@end
+