From bc1c877fe28fb6a825f0b226a0a2da99e713ea03 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Wed, 17 Dec 2008 01:07:27 +0000 Subject: [PATCH] Semantics of @protocol attributes. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@61114 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Attr.h | 15 ++++++++ include/clang/Basic/DiagnosticKinds.def | 2 + include/clang/Parse/Action.h | 3 +- include/clang/Parse/AttributeList.h | 1 + lib/Parse/AttributeList.cpp | 1 + lib/Parse/ParseObjc.cpp | 6 ++- lib/Sema/Sema.h | 3 +- lib/Sema/SemaDeclAttr.cpp | 11 ++++++ lib/Sema/SemaDeclObjC.cpp | 17 +++++++-- test/SemaObjC/protocol-atttribute-1.m | 49 +++++++++++++++++++++++++ 10 files changed, 101 insertions(+), 7 deletions(-) create mode 100644 test/SemaObjC/protocol-atttribute-1.m diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index 0a9ceb0666..51f1e192af 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -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) {} diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def index c900a23073..b379ab2f02 100644 --- a/include/clang/Basic/DiagnosticKinds.def +++ b/include/clang/Basic/DiagnosticKinds.def @@ -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, diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index a0d8d085d8..2822538564 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -1072,7 +1072,8 @@ public: virtual DeclTy *ActOnForwardProtocolDeclaration( SourceLocation AtProtocolLoc, const IdentifierLocPair*IdentList, - unsigned NumElts) { + unsigned NumElts, + AttributeList *AttrList) { return 0; } diff --git a/include/clang/Parse/AttributeList.h b/include/clang/Parse/AttributeList.h index 9c73aa013e..d3e546204c 100644 --- a/include/clang/Parse/AttributeList.h +++ b/include/clang/Parse/AttributeList.h @@ -66,6 +66,7 @@ public: AT_pure, AT_stdcall, AT_transparent_union, + AT_unavailable, AT_unused, AT_vector_size, AT_visibility, diff --git a/lib/Parse/AttributeList.cpp b/lib/Parse/AttributeList.cpp index 342c87f1fe..0a418bb9cc 100644 --- a/lib/Parse/AttributeList.cpp +++ b/lib/Parse/AttributeList.cpp @@ -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; diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index 5f2ebad6db..e70d2024c7 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -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. diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 89d9ebb583..66230314c0 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -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, diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 5c2b49472b..dbeedb10c6 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -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; diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 25d1334ab5..b9a63fda26 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -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 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 index 0000000000..658c72c69f --- /dev/null +++ b/test/SemaObjC/protocol-atttribute-1.m @@ -0,0 +1,49 @@ +// RUN: clang -fsyntax-only -verify %s + +__attribute ((unavailable)) +@protocol FwProto; + +Class cFw = 0; // expected-warning {{'FwProto' is unavailable}} + + +__attribute ((deprecated)) @protocol MyProto1 +@end + +@protocol Proto2 // expected-warning {{'MyProto1' is deprecated}} ++method2; +@end + + +@interface MyClass1 // expected-warning {{'MyProto1' is deprecated}} +{ + Class isa; +} +@end + +@interface Derived : MyClass1 // expected-warning {{'MyProto1' is deprecated}} +{ + id ivar; // expected-warning {{'MyProto1' is deprecated}} +} +@end + +@interface MyClass1 (Category) // expected-warning {{'MyProto1' is deprecated}} +@end + + + +Class clsP1 = 0; // expected-warning {{'MyProto1' is deprecated}} + +@protocol FwProto @end + +@interface MyClass2 // expected-warning {{'FwProto' is unavailable}} +@end + +__attribute ((unavailable)) __attribute ((deprecated)) @protocol XProto; + +id idX = 0; // expected-warning {{'XProto' is unavailable}} expected-warning {{'XProto' is deprecated}} + +int main () +{ + MyClass1 *p1; // expected-warning {{'MyProto1' is deprecated}} +} + -- 2.40.0