[cfe-commits] r42191 - in /cfe/trunk: AST/Decl.cpp Parse/MinimalAction.cpp Parse/ParseObjc.cpp Sema/Sema.h Sema/SemaDecl.cpp include/clang/AST/ASTContext.h include/clang/AST/Decl.h include/clang/Basic/DiagnosticKinds.def include/clang/Parse/Action.h test/Sema/protocol-test-2.m

Fariborz Jahanian fjahanian at apple.com
Fri Sep 21 08:40:54 PDT 2007


Author: fjahanian
Date: Fri Sep 21 10:40:54 2007
New Revision: 42191

URL: http://llvm.org/viewvc/llvm-project?rev=42191&view=rev
Log:
This patch instantiates objects for forward protocols and in general handles use of 
protocols referenced in @protocol declarations.

Added:
    cfe/trunk/test/Sema/protocol-test-2.m
Modified:
    cfe/trunk/AST/Decl.cpp
    cfe/trunk/Parse/MinimalAction.cpp
    cfe/trunk/Parse/ParseObjc.cpp
    cfe/trunk/Sema/Sema.h
    cfe/trunk/Sema/SemaDecl.cpp
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/include/clang/Basic/DiagnosticKinds.def
    cfe/trunk/include/clang/Parse/Action.h

Modified: cfe/trunk/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/AST/Decl.cpp?rev=42191&r1=42190&r2=42191&view=diff

==============================================================================
--- cfe/trunk/AST/Decl.cpp (original)
+++ cfe/trunk/AST/Decl.cpp Fri Sep 21 10:40:54 2007
@@ -29,6 +29,7 @@
 static unsigned nClassDecls = 0;
 static unsigned nMethodDecls = 0;
 static unsigned nProtocolDecls = 0;
+static unsigned nForwardProtocolDecls = 0;
 static unsigned nCategoryDecls = 0;
 static unsigned nIvarDecls = 0;
 
@@ -59,6 +60,8 @@
     return "ObjcProtoMethod";
   case ObjcProtocol:
     return "ObjcProtocol";
+  case ObjcForwardProtocol:
+    return "ObjcForwardProtocol"; 
   case Struct:
     return "Struct";
   case Union:
@@ -122,6 +125,9 @@
   fprintf(stderr, "    %d protocol decls, %d each (%d bytes)\n", 
 	  nProtocolDecls, (int)sizeof(ObjcProtocolDecl),
 	  int(nProtocolDecls*sizeof(ObjcProtocolDecl)));
+  fprintf(stderr, "    %d forward protocol decls, %d each (%d bytes)\n", 
+	  nForwardProtocolDecls, (int)sizeof(ObjcForwardProtocolDecl),
+	  int(nForwardProtocolDecls*sizeof(ObjcForwardProtocolDecl)));
   fprintf(stderr, "    %d category decls, %d each (%d bytes)\n", 
 	  nCategoryDecls, (int)sizeof(ObjcCategoryDecl),
 	  int(nCategoryDecls*sizeof(ObjcCategoryDecl)));
@@ -178,6 +184,9 @@
     case ObjcProtocol:
       nProtocolDecls++;
       break;
+    case ObjcForwardProtocol:
+      nForwardProtocolDecls++;
+      break;
     case ObjcCategory:
      nCategoryDecls++;
      break;

Modified: cfe/trunk/Parse/MinimalAction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Parse/MinimalAction.cpp?rev=42191&r1=42190&r2=42191&view=diff

==============================================================================
--- cfe/trunk/Parse/MinimalAction.cpp (original)
+++ cfe/trunk/Parse/MinimalAction.cpp Fri Sep 21 10:40:54 2007
@@ -109,6 +109,23 @@
   return 0;
 }
 
+/// ObjcForwardProtocolDeclaration - 
+/// Scope will always be top level file scope. 
+Action::DeclTy *
+MinimalAction::ObjcForwardProtocolDeclaration(Scope *S, SourceLocation AtClassLoc,
+                 IdentifierInfo **IdentList, unsigned NumElts) {
+  for (unsigned i = 0; i != NumElts; ++i) {
+    TypeNameInfo *TI =
+    new TypeNameInfo(1, IdentList[i]->getFETokenInfo<TypeNameInfo>());
+    
+    IdentList[i]->setFETokenInfo(TI);
+    
+    // Remember that this needs to be removed when the scope is popped.
+    S->AddDecl(IdentList[i]);
+  }
+  return 0;
+}
+
 /// PopScope - When a scope is popped, if any typedefs are now out-of-scope,
 /// they are removed from the IdentifierInfo::FETokenInfo field.
 void MinimalAction::PopScope(SourceLocation Loc, Scope *S) {

Modified: cfe/trunk/Parse/ParseObjc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Parse/ParseObjc.cpp?rev=42191&r1=42190&r2=42191&view=diff

==============================================================================
--- cfe/trunk/Parse/ParseObjc.cpp (original)
+++ cfe/trunk/Parse/ParseObjc.cpp Fri Sep 21 10:40:54 2007
@@ -713,13 +713,13 @@
   IdentifierInfo *protocolName = Tok.getIdentifierInfo();
   SourceLocation nameLoc = ConsumeToken();
   
-  if (Tok.getKind() == tok::semi) { // forward declaration.
+  llvm::SmallVector<IdentifierInfo *, 8> ProtocolRefs;
+  if (Tok.getKind() == tok::semi) { // forward declaration of one protocol.
     ConsumeToken();
-    return 0; // FIXME: add protocolName
+    ProtocolRefs.push_back(protocolName);
   }
   if (Tok.getKind() == tok::comma) { // list of forward declarations.
     // Parse the list of forward declarations.
-    llvm::SmallVector<IdentifierInfo *, 8> ProtocolRefs;
     ProtocolRefs.push_back(protocolName);
     
     while (1) {
@@ -738,10 +738,12 @@
     // Consume the ';'.
     if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@protocol"))
       return 0;
-    return 0; // FIXME
   }
+  if (ProtocolRefs.size() > 0)
+    return Actions.ObjcForwardProtocolDeclaration(CurScope, AtLoc,
+                                                  &ProtocolRefs[0], 
+                                                  ProtocolRefs.size());
   // Last, and definitely not least, parse a protocol declaration.
-  llvm::SmallVector<IdentifierInfo *, 8> ProtocolRefs;
   if (Tok.getKind() == tok::less) {
     if (ParseObjCProtocolReferences(ProtocolRefs))
       return 0;

Modified: cfe/trunk/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/Sema.h?rev=42191&r1=42190&r2=42191&view=diff

==============================================================================
--- cfe/trunk/Sema/Sema.h (original)
+++ cfe/trunk/Sema/Sema.h Fri Sep 21 10:40:54 2007
@@ -370,6 +370,11 @@
   virtual DeclTy *ObjcClassDeclaration(Scope *S, SourceLocation AtClassLoc,
                                        IdentifierInfo **IdentList,
                                        unsigned NumElts);
+  
+  virtual DeclTy *ObjcForwardProtocolDeclaration(Scope *S, 
+                                                 SourceLocation AtProtocolLoc,
+                                                 IdentifierInfo **IdentList,
+                                                 unsigned NumElts);
 
   virtual void ObjcAddMethodsToClass(DeclTy *ClassDecl, 
 				     DeclTy **allMethods, unsigned allNum);

Modified: cfe/trunk/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaDecl.cpp?rev=42191&r1=42190&r2=42191&view=diff

==============================================================================
--- cfe/trunk/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/Sema/SemaDecl.cpp Fri Sep 21 10:40:54 2007
@@ -905,16 +905,66 @@
                 IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc,
                 IdentifierInfo **ProtoRefNames, unsigned NumProtoRefs) {
   assert(ProtocolName && "Missing protocol identifier");
-  ObjcProtocolDecl *PDecl;
-
-  PDecl = new ObjcProtocolDecl(AtProtoInterfaceLoc, ProtocolName);
+  ObjcProtocolDecl *PDecl = Context.getObjCProtocolDecl(ProtocolName);
+  if (PDecl) {
+    // Protocol already seen. Better be a forward protocol declaration
+    if (!PDecl->getIsForwardProtoDecl())
+      Diag(ProtocolLoc, diag::err_duplicate_protocol_def, 
+           ProtocolName->getName());
+    else {
+      PDecl->setIsForwardProtoDecl(false);
+      PDecl->AllocReferencedProtocols(NumProtoRefs);
+    }
+  }
+  else {
+    PDecl = new ObjcProtocolDecl(AtProtoInterfaceLoc, NumProtoRefs, 
+                                 ProtocolName);
+    PDecl->setIsForwardProtoDecl(false);
+    // Chain & install the protocol decl into the identifier.
+    PDecl->setNext(ProtocolName->getFETokenInfo<ScopedDecl>());
+    ProtocolName->setFETokenInfo(PDecl);
+    Context.setObjCProtocolDecl(ProtocolName, PDecl);
+  }    
+  
+  /// Check then save referenced protocols
+  for (unsigned int i = 0; i != NumProtoRefs; i++) {
+    ObjcProtocolDecl* RefPDecl = Context.getObjCProtocolDecl(ProtoRefNames[i]);
+    if (!RefPDecl || RefPDecl->getIsForwardProtoDecl())
+      Diag(ProtocolLoc, diag::err_undef_protocolref,
+	   ProtoRefNames[i]->getName(),
+           ProtocolName->getName());
+    PDecl->setReferencedProtocols((int)i, RefPDecl);
+  }
 
-  // Chain & install the protocol decl into the identifier.
-  PDecl->setNext(ProtocolName->getFETokenInfo<ScopedDecl>());
-  ProtocolName->setFETokenInfo(PDecl);
   return PDecl;
 }
 
+/// ObjcForwardProtocolDeclaration - 
+/// Scope will always be top level file scope. 
+Action::DeclTy *
+Sema::ObjcForwardProtocolDeclaration(Scope *S, SourceLocation AtProtocolLoc,
+        IdentifierInfo **IdentList, unsigned NumElts) {
+  ObjcForwardProtocolDecl *FDecl = new ObjcForwardProtocolDecl(AtProtocolLoc, 
+                                                               NumElts);
+  
+  for (unsigned i = 0; i != NumElts; ++i) {
+    ObjcProtocolDecl *PDecl;
+    PDecl = Context.getObjCProtocolDecl(IdentList[i]);
+    if (!PDecl)  {// Already seen?
+      PDecl = new ObjcProtocolDecl(SourceLocation(), 0, IdentList[i], true);
+      // Chain & install the protocol decl into the identifier.
+      PDecl->setNext(IdentList[i]->getFETokenInfo<ScopedDecl>());
+      IdentList[i]->setFETokenInfo(PDecl);
+      Context.setObjCProtocolDecl(IdentList[i], PDecl);
+    }
+    // Remember that this needs to be removed when the scope is popped.
+    S->AddDecl(IdentList[i]);
+    
+    FDecl->setForwardProtocolDecl((int)i, PDecl);
+  }
+  return FDecl;
+}
+
 Sema::DeclTy *Sema::ObjcStartCatInterface(SourceLocation AtInterfaceLoc,
                       IdentifierInfo *ClassName, SourceLocation ClassLoc,
                       IdentifierInfo *CategoryName, SourceLocation CategoryLoc,

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=42191&r1=42190&r2=42191&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Fri Sep 21 10:40:54 2007
@@ -38,6 +38,7 @@
   llvm::FoldingSet<FunctionTypeProto> FunctionTypeProtos;
   llvm::DenseMap<const RecordDecl*, const RecordLayout*> RecordLayoutInfo;
   llvm::DenseMap<const IdentifierInfo*, ObjcInterfaceDecl*> ClassNameInfo;
+  llvm::DenseMap<const IdentifierInfo*, ObjcProtocolDecl*> ProtocolNameInfo;
   RecordDecl *CFConstantStringTypeDecl;
 public:
   
@@ -165,6 +166,12 @@
                             ObjcInterfaceDecl* InterfaceDecl)
   { ClassNameInfo[ClassName] = InterfaceDecl; }
   
+  ObjcProtocolDecl* getObjCProtocolDecl(const IdentifierInfo* ProtocolName) 
+  { return ProtocolNameInfo[ProtocolName]; }
+  void setObjCProtocolDecl(const IdentifierInfo* ProtocolName,
+                            ObjcProtocolDecl* ProtocolDecl)
+  { ProtocolNameInfo[ProtocolName] = ProtocolDecl; }
+  
   //===--------------------------------------------------------------------===//
   //                            Type Operators
   //===--------------------------------------------------------------------===//

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=42191&r1=42190&r2=42191&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Fri Sep 21 10:40:54 2007
@@ -38,7 +38,7 @@
     Function, BlockVariable, FileVariable, ParmVariable, EnumConstant,
     // Concrete sub-classes of TypeDecl
     Typedef, Struct, Union, Class, Enum, ObjcInterface, ObjcClass, ObjcMethod,
-    ObjcProtoMethod, ObjcProtocol, ObjcCategory,
+    ObjcProtoMethod, ObjcProtocol, ObjcForwardProtocol, ObjcCategory,
     // Concrete sub-class of Decl
     Field, ObjcIvar
   };
@@ -680,6 +680,10 @@
 };
 
 class ObjcProtocolDecl : public TypeDecl {
+  /// referenced protocols
+  ObjcProtocolDecl **ReferencedProtocols;  // Null if none
+  int NumReferencedProtocols;  // -1 if none
+  
   /// protocol instance methods
   ObjcMethodDecl **ProtoInsMethods;  // Null if not defined
   int NumProtoInsMethods;  // -1 if not defined
@@ -690,20 +694,62 @@
 
   bool isForwardProtoDecl; // declared with @protocol.
 public:
-  ObjcProtocolDecl(SourceLocation L, IdentifierInfo *Id, bool FD = false)
+  ObjcProtocolDecl(SourceLocation L, unsigned numRefProtos,
+                   IdentifierInfo *Id, bool FD = false)
     : TypeDecl(ObjcProtocol, L, Id, 0), 
+      ReferencedProtocols(0), NumReferencedProtocols(-1),
       ProtoInsMethods(0), NumProtoInsMethods(-1), 
       ProtoClsMethods(0), NumProtoClsMethods(-1),
-      isForwardProtoDecl(FD) { }
-
+      isForwardProtoDecl(FD) {
+        AllocReferencedProtocols(numRefProtos);
+      }
+  void AllocReferencedProtocols(unsigned numRefProtos) {
+    if (numRefProtos) {
+      ReferencedProtocols = new ObjcProtocolDecl*[numRefProtos];
+      memset(ReferencedProtocols, '\0', 
+             numRefProtos*sizeof(ObjcProtocolDecl*));
+      NumReferencedProtocols = numRefProtos;
+    }    
+  }
   void ObjcAddProtoMethods(ObjcMethodDecl **insMethods, unsigned numInsMembers,
                            ObjcMethodDecl **clsMethods, unsigned numClsMembers);
+  
+  void setReferencedProtocols(int idx, ObjcProtocolDecl *OID) {
+    assert((idx < NumReferencedProtocols) && "index out of range");
+    ReferencedProtocols[idx] = OID;
+  }
+  
+  
+  bool getIsForwardProtoDecl() const { return isForwardProtoDecl; }
+  void setIsForwardProtoDecl(bool val) { isForwardProtoDecl = val; }
 
   static bool classof(const Decl *D) {
     return D->getKind() == ObjcProtocol;
   }
   static bool classof(const ObjcProtocolDecl *D) { return true; }
 };
+  
+class ObjcForwardProtocolDecl : public TypeDecl {
+    ObjcProtocolDecl **ForwardProtocolDecls;   // Null if not defined.
+    int NumForwardProtocolDecls;               // -1 if not defined.
+  public:
+    ObjcForwardProtocolDecl(SourceLocation L, unsigned nElts)
+    : TypeDecl(ObjcForwardProtocol, L, 0, 0) { 
+      if (nElts) {
+        ForwardProtocolDecls = new ObjcProtocolDecl*[nElts];
+        memset(ForwardProtocolDecls, '\0', nElts*sizeof(ObjcProtocolDecl*));
+        NumForwardProtocolDecls = nElts;
+      }
+    }
+    void setForwardProtocolDecl(int idx, ObjcProtocolDecl *OID) {
+      assert((idx < NumForwardProtocolDecls) && "index out of range");
+      ForwardProtocolDecls[idx] = OID;
+    }
+    static bool classof(const Decl *D) {
+      return D->getKind() == ObjcForwardProtocol;
+    }
+    static bool classof(const ObjcForwardProtocolDecl *D) { return true; }
+};
 
 class ObjcCategoryDecl : public ScopedDecl {
   /// category instance methods

Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=42191&r1=42190&r2=42191&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Fri Sep 21 10:40:54 2007
@@ -412,7 +412,10 @@
      "cannot find interface declaration for '%0', superclass of '%1'")
 DIAG(err_duplicate_class_def, ERROR,
      "duplicate interface declaration for class '%0'")
-
+DIAG(err_undef_protocolref, ERROR,
+     "cannot find protocol definition for '%0', referenced by '%1'")
+DIAG(err_duplicate_protocol_def, ERROR,
+     "duplicate protocol declaration of '%0'")
 
 //===----------------------------------------------------------------------===//
 // Semantic Analysis

Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=42191&r1=42190&r2=42191&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Fri Sep 21 10:40:54 2007
@@ -502,6 +502,14 @@
                                        unsigned NumElts) {
     return 0;
   }
+  
+  virtual DeclTy *ObjcForwardProtocolDeclaration(Scope *S, 
+                                                 SourceLocation AtProtocolLoc,
+                                                 IdentifierInfo **IdentList,
+                                                 unsigned NumElts) {
+    return 0;
+  }
+  
   virtual void ObjCStartCategoryInterface() { // FIXME
     return;
   }
@@ -548,6 +556,11 @@
                                        IdentifierInfo **IdentList,
                                        unsigned NumElts);
   
+  virtual DeclTy *ObjcForwardProtocolDeclaration(Scope *S, 
+                                                 SourceLocation AtProtocolLoc,
+                                                 IdentifierInfo **IdentList,
+                                                 unsigned NumElts);
+   
   virtual DeclTy *ObjcStartClassInterface(SourceLocation AtInterafceLoc,
                     IdentifierInfo *ClassName, SourceLocation ClassLoc,
                     IdentifierInfo *SuperName, SourceLocation SuperLoc,

Added: cfe/trunk/test/Sema/protocol-test-2.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/protocol-test-2.m?rev=42191&view=auto

==============================================================================
--- cfe/trunk/test/Sema/protocol-test-2.m (added)
+++ cfe/trunk/test/Sema/protocol-test-2.m Fri Sep 21 10:40:54 2007
@@ -0,0 +1,29 @@
+ at interface INTF1 @end
+
+ at protocol p1,p2,p3;
+
+ at protocol p1;
+
+ at protocol PROTO1
+- (INTF1<p1>*) meth;
+ at end
+
+ at protocol PROTO2<p1> // expected-error {{cannot find protocol definition for 'p1', referenced by 'PROTO2'}}
+ at end
+
+ at protocol p1 @end
+
+ at protocol PROTO<p1>
+ at end
+
+ at protocol PROTO<p1>	// expected-error {{duplicate protocol declaration of 'PROTO'}}
+ at end
+
+ at protocol PROTO3<p1, p1>
+ at end
+
+ at protocol p2 <p1>
+ at end
+
+ at protocol PROTO4 <p1, p2, PROTO, PROTO3, p3> // expected-error {{cannot find protocol definition for 'p3', referenced by 'PROTO4'}}
+ at end





More information about the cfe-commits mailing list