]> granicus.if.org Git - clang/commitdiff
Semantics of @protocol attributes.
authorFariborz Jahanian <fjahanian@apple.com>
Wed, 17 Dec 2008 01:07:27 +0000 (01:07 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Wed, 17 Dec 2008 01:07:27 +0000 (01:07 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@61114 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Attr.h
include/clang/Basic/DiagnosticKinds.def
include/clang/Parse/Action.h
include/clang/Parse/AttributeList.h
lib/Parse/AttributeList.cpp
lib/Parse/ParseObjc.cpp
lib/Sema/Sema.h
lib/Sema/SemaDeclAttr.cpp
lib/Sema/SemaDeclObjC.cpp
test/SemaObjC/protocol-atttribute-1.m [new file with mode: 0644]

index 0a9ceb0666d62024c13a71af9bba5d884f795166..51f1e192af8b7b35154970636aee4e1baa59aa82 100644 (file)
@@ -45,6 +45,7 @@ public:
     Packed,
     StdCall,
     TransparentUnion,
+    Unavailable,
     Unused,    
     Visibility,
     Weak,
@@ -65,6 +66,10 @@ public:
   }
 
   Kind getKind() const { return AttrKind; }
+  
+  bool hasKind(Kind kind) const {
+    return AttrKind == kind;
+  }
 
   Attr *getNext() { return Next; }
   const Attr *getNext() const { return Next; }
@@ -219,6 +224,16 @@ public:
   static bool classof(const DeprecatedAttr *A) { return true; }
 };
 
+class UnavailableAttr : public Attr {
+public:
+  UnavailableAttr() : Attr(Unavailable) {}
+
+  // Implement isa/cast/dyncast/etc.
+
+  static bool classof(const Attr *A) { return A->getKind() == Unavailable; }
+  static bool classof(const UnavailableAttr *A) { return true; }
+};
+
 class UnusedAttr : public Attr {
 public:
   UnusedAttr() : Attr(Unused) {}
index c900a230733a9832f807c2dfd15851765ba2a5db..b379ab2f02025a63d416773277048921d6a9acae 100644 (file)
@@ -974,6 +974,8 @@ DIAG(err_undeclared_use, ERROR,
      "use of undeclared '%0'")
 DIAG(warn_deprecated, WARNING,
      "%0 is deprecated")
+DIAG(warn_unavailable, WARNING,
+     "%0 is unavailable")
 DIAG(err_redefinition, ERROR,
      "redefinition of %0")
 DIAG(err_static_non_static, ERROR,
index a0d8d085d840b5cc140ebcb9f8c1d5a63975dc4f..2822538564a4411e9fd94ed036edda67e21a0c35 100644 (file)
@@ -1072,7 +1072,8 @@ public:
   virtual DeclTy *ActOnForwardProtocolDeclaration(
     SourceLocation AtProtocolLoc,
     const IdentifierLocPair*IdentList,
-    unsigned NumElts) {
+    unsigned NumElts,
+    AttributeList *AttrList) {
     return 0;
   }
   
index 9c73aa013e008360984931b98a49bc171c3565e5..d3e546204c92bd862b260848f60a654be45b233b 100644 (file)
@@ -66,6 +66,7 @@ public:
     AT_pure,
     AT_stdcall,
     AT_transparent_union,
+    AT_unavailable,
     AT_unused,
     AT_vector_size,
     AT_visibility,
index 342c87f1fe25572094392c2907aa80daaf9cd442..0a418bb9cc19a06228674d0b4bcd629e8da98b89 100644 (file)
@@ -94,6 +94,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
   case 11:
     if (!memcmp(Str, "vector_size", 11)) return AT_vector_size;
     if (!memcmp(Str, "constructor", 11)) return AT_constructor;
+    if (!memcmp(Str, "unavailable", 11)) return AT_unavailable;
     break;
   case 13:
     if (!memcmp(Str, "address_space", 13)) return AT_address_space;
index 5f2ebad6dbce9de545d8eeb355cd9b7836289637..e70d2024c760524818877c649c20d58133a21e5c 100644 (file)
@@ -936,7 +936,8 @@ Parser::DeclTy *Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
   if (Tok.is(tok::semi)) { // forward declaration of one protocol.
     IdentifierLocPair ProtoInfo(protocolName, nameLoc);
     ConsumeToken();
-    return Actions.ActOnForwardProtocolDeclaration(AtLoc, &ProtoInfo, 1);
+    return Actions.ActOnForwardProtocolDeclaration(AtLoc, &ProtoInfo, 1, 
+                                                   attrList);
   }
   
   if (Tok.is(tok::comma)) { // list of forward declarations.
@@ -964,7 +965,8 @@ Parser::DeclTy *Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
     
     return Actions.ActOnForwardProtocolDeclaration(AtLoc,
                                                    &ProtocolRefs[0], 
-                                                   ProtocolRefs.size());
+                                                   ProtocolRefs.size(),
+                                                   attrList);
   }
   
   // Last, and definitely not least, parse a protocol declaration.
index 89d9ebb583c2c8ce8a32b318ffd32a2e5f613c2f..66230314c0fbe722bac377006e3ed01b2206a672 100644 (file)
@@ -1063,7 +1063,8 @@ public:
   
   virtual DeclTy *ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc,
                                             const IdentifierLocPair *IdentList,
-                                                  unsigned NumElts);
+                                                  unsigned NumElts,
+                                                  AttributeList *attrList);
   
   virtual void FindProtocolDeclaration(bool WarnOnDeclarations,
                                        const IdentifierLocPair *ProtocolId,
index 5c2b49472b1e3799922039aa752d8f2aee6cc705..dbeedb10c6a675bb77d2b74aac9e9dd60da4154e 100644 (file)
@@ -501,6 +501,16 @@ static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
   d->addAttr(new DeprecatedAttr());
 }
 
+static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }
+  
+  d->addAttr(new UnavailableAttr());
+}
+
 static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) {
   // check the attribute arguments.
   if (Attr.getNumArgs() != 1) {
@@ -1126,6 +1136,7 @@ static void ProcessDeclAttribute(Decl *D, const AttributeList &Attr, Sema &S) {
   case AttributeList::AT_nothrow:     HandleNothrowAttr   (D, Attr, S); break;
   case AttributeList::AT_packed:      HandlePackedAttr    (D, Attr, S); break;
   case AttributeList::AT_stdcall:     HandleStdCallAttr   (D, Attr, S); break;
+  case AttributeList::AT_unavailable: HandleUnavailableAttr(D, Attr, S); break;
   case AttributeList::AT_unused:      HandleUnusedAttr    (D, Attr, S); break;
   case AttributeList::AT_vector_size: HandleVectorSizeAttr(D, Attr, S); break;
   case AttributeList::AT_visibility:  HandleVisibilityAttr(D, Attr, S); break;
index 25d1334ab56aa8a71a588a9bfb1d37e28722051b..b9a63fda260f294b1c6955b8e1715442d1d72a41 100644 (file)
@@ -207,7 +207,8 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc,
     PDecl->setForwardDecl(false);
     ObjCProtocols[ProtocolName] = PDecl;
   }
-  
+  if (AttrList)
+    ProcessDeclAttributeList(PDecl, AttrList);
   if (NumProtoRefs) {
     /// Check then save referenced protocols.
     PDecl->addReferencedProtocols((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs);
@@ -233,6 +234,14 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations,
         << ProtocolId[i].first;
       continue;
     }
+    for (const Attr *attr = PDecl->getAttrs(); attr; attr = attr->getNext()) {
+      if (attr->hasKind(Attr::Unavailable))
+        Diag(ProtocolId[i].second, diag::warn_unavailable) << 
+          PDecl->getDeclName();
+      if (attr->hasKind(Attr::Deprecated))
+        Diag(ProtocolId[i].second, diag::warn_deprecated) << 
+          PDecl->getDeclName();
+    }
 
     // If this is a forward declaration and we are supposed to warn in this
     // case, do it.
@@ -417,7 +426,8 @@ Sema::MergeProtocolPropertiesIntoClass(Decl *CDecl,
 Action::DeclTy *
 Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc,
                                       const IdentifierLocPair *IdentList,
-                                      unsigned NumElts) {
+                                      unsigned NumElts,
+                                      AttributeList *attrList) {
   llvm::SmallVector<ObjCProtocolDecl*, 32> Protocols;
   
   for (unsigned i = 0; i != NumElts; ++i) {
@@ -425,7 +435,8 @@ Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc,
     ObjCProtocolDecl *&PDecl = ObjCProtocols[Ident];
     if (PDecl == 0) // Not already seen?
       PDecl = ObjCProtocolDecl::Create(Context, IdentList[i].second, Ident);
-    
+    if (attrList)
+      ProcessDeclAttributeList(PDecl, attrList);
     Protocols.push_back(PDecl);
   }
   
diff --git a/test/SemaObjC/protocol-atttribute-1.m b/test/SemaObjC/protocol-atttribute-1.m
new file mode 100644 (file)
index 0000000..658c72c
--- /dev/null
@@ -0,0 +1,49 @@
+// RUN: clang -fsyntax-only -verify %s
+
+__attribute ((unavailable))
+@protocol FwProto;
+
+Class <FwProto> cFw = 0;  // expected-warning {{'FwProto' is unavailable}}
+
+
+__attribute ((deprecated)) @protocol MyProto1
+@end
+
+@protocol Proto2  <MyProto1>  // expected-warning {{'MyProto1' is deprecated}}
++method2;
+@end
+
+
+@interface MyClass1 <MyProto1>  // expected-warning {{'MyProto1' is deprecated}}
+{
+  Class isa;
+}
+@end
+
+@interface Derived : MyClass1 <MyProto1>  // expected-warning {{'MyProto1' is deprecated}}
+{
+       id <MyProto1> ivar;  // expected-warning {{'MyProto1' is deprecated}}
+}
+@end
+
+@interface MyClass1 (Category) <MyProto1, Proto2>  // expected-warning {{'MyProto1' is deprecated}}
+@end
+
+
+
+Class <MyProto1> clsP1 = 0;  // expected-warning {{'MyProto1' is deprecated}}
+
+@protocol FwProto @end
+
+@interface MyClass2 <FwProto> // expected-warning {{'FwProto' is unavailable}}
+@end
+
+__attribute ((unavailable)) __attribute ((deprecated)) @protocol XProto;
+
+id <XProto> idX = 0; // expected-warning {{'XProto' is unavailable}} expected-warning {{'XProto' is deprecated}}
+
+int main ()
+{
+       MyClass1 <MyProto1> *p1;  // expected-warning {{'MyProto1' is deprecated}}
+}
+