forked from OSchip/llvm-project
Add clang support for IBOutletCollection.
llvm-svn: 104135
This commit is contained in:
parent
52e37becf6
commit
26bde774df
|
@ -810,7 +810,8 @@ enum CXCursorKind {
|
|||
|
||||
CXCursor_IBActionAttr = 401,
|
||||
CXCursor_IBOutletAttr = 402,
|
||||
CXCursor_LastAttr = CXCursor_IBOutletAttr,
|
||||
CXCursor_IBOutletCollectionAttr = 403,
|
||||
CXCursor_LastAttr = CXCursor_IBOutletCollectionAttr,
|
||||
|
||||
/* Preprocessing */
|
||||
CXCursor_PreprocessingDirective = 500,
|
||||
|
|
|
@ -23,9 +23,10 @@ using llvm::dyn_cast;
|
|||
|
||||
namespace clang {
|
||||
class ASTContext;
|
||||
class IdentifierInfo;
|
||||
class ObjCInterfaceDecl;
|
||||
}
|
||||
|
||||
|
||||
// Defined in ASTContext.h
|
||||
void *operator new(size_t Bytes, clang::ASTContext &C,
|
||||
size_t Alignment = 16) throw ();
|
||||
|
@ -63,6 +64,7 @@ public:
|
|||
GNUInline,
|
||||
Hiding,
|
||||
IBOutletKind, // Clang-specific. Use "Kind" suffix to not conflict w/ macro.
|
||||
IBOutletCollectionKind, // Clang-specific.
|
||||
IBActionKind, // Clang-specific. Use "Kind" suffix to not conflict w/ macro.
|
||||
Malloc,
|
||||
NoDebug,
|
||||
|
@ -318,6 +320,23 @@ public:
|
|||
static bool classof(const IBOutletAttr *A) { return true; }
|
||||
};
|
||||
|
||||
class IBOutletCollectionAttr : public Attr {
|
||||
const ObjCInterfaceDecl *D;
|
||||
public:
|
||||
IBOutletCollectionAttr(const ObjCInterfaceDecl *d = 0)
|
||||
: Attr(IBOutletCollectionKind), D(d) {}
|
||||
|
||||
const ObjCInterfaceDecl *getClass() const { return D; }
|
||||
|
||||
virtual Attr *clone(ASTContext &C) const;
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Attr *A) {
|
||||
return A->getKind() == IBOutletCollectionKind;
|
||||
}
|
||||
static bool classof(const IBOutletCollectionAttr *A) { return true; }
|
||||
};
|
||||
|
||||
class IBActionAttr : public Attr {
|
||||
public:
|
||||
IBActionAttr() : Attr(IBActionKind) {}
|
||||
|
|
|
@ -957,8 +957,7 @@ def err_attribute_regparm_invalid_number : Error<
|
|||
|
||||
// Clang-Specific Attributes
|
||||
def err_attribute_iboutlet : Error<
|
||||
"iboutlet attribute can only be applied to instance variables or "
|
||||
"properties">;
|
||||
"%0 attribute can only be applied to instance variables or properties">;
|
||||
def err_attribute_ibaction: Error<
|
||||
"ibaction attribute can only be applied to Objective-C instance methods">;
|
||||
def err_attribute_overloadable_not_function : Error<
|
||||
|
|
|
@ -55,6 +55,7 @@ public:
|
|||
enum Kind { // Please keep this list alphabetized.
|
||||
AT_IBAction, // Clang-specific.
|
||||
AT_IBOutlet, // Clang-specific.
|
||||
AT_IBOutletCollection, // Clang-specific.
|
||||
AT_address_space,
|
||||
AT_alias,
|
||||
AT_aligned,
|
||||
|
|
|
@ -143,6 +143,10 @@ Attr *IBOutletAttr::clone(ASTContext &C) const {
|
|||
return ::new (C) IBOutletAttr;
|
||||
}
|
||||
|
||||
Attr *IBOutletCollectionAttr::clone(ASTContext &C) const {
|
||||
return ::new (C) IBOutletCollectionAttr(D);
|
||||
}
|
||||
|
||||
Attr *IBActionAttr::clone(ASTContext &C) const {
|
||||
return ::new (C) IBActionAttr;
|
||||
}
|
||||
|
|
|
@ -115,7 +115,8 @@ void clang::CheckObjCDealloc(const ObjCImplementationDecl* D,
|
|||
QualType T = ID->getType();
|
||||
|
||||
if (!T->isObjCObjectPointerType() ||
|
||||
ID->getAttr<IBOutletAttr>()) // Skip IBOutlets.
|
||||
ID->getAttr<IBOutletAttr>() || // Skip IBOutlets.
|
||||
ID->getAttr<IBOutletCollectionAttr>()) // Skip IBOutletCollections.
|
||||
continue;
|
||||
|
||||
containsPointerIvar = true;
|
||||
|
|
|
@ -114,7 +114,8 @@ void clang::CheckObjCUnusedIvar(const ObjCImplementationDecl *D,
|
|||
// (b) explicitly marked unused
|
||||
// (c) are iboutlets
|
||||
if (ID->getAccessControl() != ObjCIvarDecl::Private ||
|
||||
ID->getAttr<UnusedAttr>() || ID->getAttr<IBOutletAttr>())
|
||||
ID->getAttr<UnusedAttr>() || ID->getAttr<IBOutletAttr>() ||
|
||||
ID->getAttr<IBOutletCollectionAttr>())
|
||||
continue;
|
||||
|
||||
M[ID] = Unused;
|
||||
|
|
|
@ -726,6 +726,13 @@ Attr *PCHReader::ReadAttributes() {
|
|||
New = ::new (*Context) IBOutletAttr();
|
||||
break;
|
||||
|
||||
case Attr::IBOutletCollectionKind: {
|
||||
ObjCInterfaceDecl *D =
|
||||
cast_or_null<ObjCInterfaceDecl>(GetDecl(Record[Idx++]));
|
||||
New = ::new (*Context) IBOutletCollectionAttr(D);
|
||||
break;
|
||||
}
|
||||
|
||||
SIMPLE_ATTR(Malloc);
|
||||
SIMPLE_ATTR(NoDebug);
|
||||
SIMPLE_ATTR(NoInline);
|
||||
|
|
|
@ -1917,6 +1917,12 @@ void PCHWriter::WriteAttributeRecord(const Attr *Attr) {
|
|||
case Attr::NoThrow:
|
||||
break;
|
||||
|
||||
case Attr::IBOutletCollectionKind: {
|
||||
const IBOutletCollectionAttr *ICA = cast<IBOutletCollectionAttr>(Attr);
|
||||
AddDeclRef(ICA->getClass(), Record);
|
||||
break;
|
||||
}
|
||||
|
||||
case Attr::NonNull: {
|
||||
const NonNullAttr *NonNull = cast<NonNullAttr>(Attr);
|
||||
Record.push_back(NonNull->size());
|
||||
|
|
|
@ -84,6 +84,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
|
|||
.Case("fastcall", AT_fastcall)
|
||||
.Case("ibaction", AT_IBAction)
|
||||
.Case("iboutlet", AT_IBOutlet)
|
||||
.Case("iboutletcollection", AT_IBOutletCollection)
|
||||
.Case("noreturn", AT_noreturn)
|
||||
.Case("noinline", AT_noinline)
|
||||
.Case("override", AT_override)
|
||||
|
|
|
@ -259,6 +259,26 @@ static void HandleIBOutlet(Decl *d, const AttributeList &Attr, Sema &S) {
|
|||
S.Diag(Attr.getLoc(), diag::err_attribute_iboutlet) << Attr.getName();
|
||||
}
|
||||
|
||||
static void HandleIBOutletCollection(Decl *d, const AttributeList &Attr,
|
||||
Sema &S) {
|
||||
|
||||
// The iboutletcollection attribute can have zero or one arguments.
|
||||
if (Attr.getNumArgs() > 1) {
|
||||
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
|
||||
return;
|
||||
}
|
||||
|
||||
// The IBOutletCollection attributes only apply to instance variables of
|
||||
// Objective-C classes.
|
||||
if (!(isa<ObjCIvarDecl>(d) || isa<ObjCPropertyDecl>(d))) {
|
||||
S.Diag(Attr.getLoc(), diag::err_attribute_iboutlet) << Attr.getName();
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME: Eventually accept the type argument.
|
||||
d->addAttr(::new (S.Context) IBOutletCollectionAttr());
|
||||
}
|
||||
|
||||
static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||
// GCC ignores the nonnull attribute on K&R style function prototypes, so we
|
||||
// ignore it as well
|
||||
|
@ -1884,7 +1904,9 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D,
|
|||
return;
|
||||
switch (Attr.getKind()) {
|
||||
case AttributeList::AT_IBAction: HandleIBAction(D, Attr, S); break;
|
||||
case AttributeList::AT_IBOutlet: HandleIBOutlet(D, Attr, S); break;
|
||||
case AttributeList::AT_IBOutlet: HandleIBOutlet(D, Attr, S); break;
|
||||
case AttributeList::AT_IBOutletCollection:
|
||||
HandleIBOutletCollection(D, Attr, S); break;
|
||||
case AttributeList::AT_address_space:
|
||||
case AttributeList::AT_objc_gc:
|
||||
case AttributeList::AT_vector_size:
|
||||
|
|
|
@ -54,6 +54,18 @@ int main (int argc, const char * argv[]) {
|
|||
main(someEnum, (const char **)bee);
|
||||
}
|
||||
|
||||
// Test attribute traversal.
|
||||
#define IBOutlet __attribute__((iboutlet))
|
||||
#define IBOutletCollection(ClassName) __attribute__((iboutletcollection))
|
||||
#define IBAction void)__attribute__((ibaction)
|
||||
|
||||
@interface TestAttributes {
|
||||
IBOutlet char * anOutlet;
|
||||
IBOutletCollection(id) id anOutletCollection;
|
||||
}
|
||||
- (IBAction) actionMethod:(id)arg;
|
||||
@end
|
||||
|
||||
// CHECK: c-index-api-loadTU-test.m:4:12: ObjCInterfaceDecl=Foo:4:12 Extent=[4:1 - 12:5]
|
||||
// CHECK: c-index-api-loadTU-test.m:6:32: ObjCIvarDecl=myoutlet:6:32 (Definition) Extent=[6:32 - 6:40]
|
||||
// CHECK: <invalid loc>:0:0: attribute(iboutlet)=
|
||||
|
@ -123,4 +135,14 @@ int main (int argc, const char * argv[]) {
|
|||
// CHECK: c-index-api-loadTU-test.m:54:8: DeclRefExpr=someEnum:43:3 Extent=[54:8 - 54:16]
|
||||
// CHECK: c-index-api-loadTU-test.m:54:18: UnexposedExpr=bee:47:8 Extent=[54:18 - 54:36]
|
||||
// CHECK: c-index-api-loadTU-test.m:54:33: DeclRefExpr=bee:47:8 Extent=[54:33 - 54:36]
|
||||
// CHECK: c-index-api-loadTU-test.m:62:12: ObjCInterfaceDecl=TestAttributes:62:12 Extent=[62:1 - 67:5]
|
||||
// CHECK: c-index-api-loadTU-test.m:63:19: ObjCIvarDecl=anOutlet:63:19 (Definition) Extent=[63:19 - 63:27]
|
||||
// CHECK: <invalid loc>:0:0: attribute(iboutlet)=
|
||||
// CHECK: c-index-api-loadTU-test.m:64:29: ObjCIvarDecl=anOutletCollection:64:29 (Definition) Extent=[64:29 - 64:47]
|
||||
// CHECK: <invalid loc>:0:0: attribute(iboutletcollection)=
|
||||
// CHECK: c-index-api-loadTU-test.m:64:26: TypeRef=id:0:0 Extent=[64:26 - 64:28]
|
||||
// CHECK: c-index-api-loadTU-test.m:66:1: ObjCInstanceMethodDecl=actionMethod::66:1 Extent=[66:1 - 66:35]
|
||||
// CHECK: <invalid loc>:0:0: attribute(ibaction)=
|
||||
// CHECK: c-index-api-loadTU-test.m:66:31: ParmDecl=arg:66:31 (Definition) Extent=[66:28 - 66:34]
|
||||
// CHECK: c-index-api-loadTU-test.m:66:28: TypeRef=id:0:0 Extent=[66:28 - 66:30]
|
||||
|
||||
|
|
|
@ -1726,6 +1726,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
|
|||
return createCXString("attribute(ibaction)");
|
||||
case CXCursor_IBOutletAttr:
|
||||
return createCXString("attribute(iboutlet)");
|
||||
case CXCursor_IBOutletCollectionAttr:
|
||||
return createCXString("attribute(iboutletcollection)");
|
||||
case CXCursor_PreprocessingDirective:
|
||||
return createCXString("preprocessing directive");
|
||||
case CXCursor_MacroDefinition:
|
||||
|
|
|
@ -80,6 +80,7 @@ static CXCursorKind GetCursorKind(const Attr *A) {
|
|||
default: break;
|
||||
case Attr::IBActionKind: return CXCursor_IBActionAttr;
|
||||
case Attr::IBOutletKind: return CXCursor_IBOutletAttr;
|
||||
case Attr::IBOutletCollectionKind: return CXCursor_IBOutletCollectionAttr;
|
||||
}
|
||||
|
||||
return CXCursor_UnexposedAttr;
|
||||
|
|
Loading…
Reference in New Issue