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_IBActionAttr = 401,
|
||||||
CXCursor_IBOutletAttr = 402,
|
CXCursor_IBOutletAttr = 402,
|
||||||
CXCursor_LastAttr = CXCursor_IBOutletAttr,
|
CXCursor_IBOutletCollectionAttr = 403,
|
||||||
|
CXCursor_LastAttr = CXCursor_IBOutletCollectionAttr,
|
||||||
|
|
||||||
/* Preprocessing */
|
/* Preprocessing */
|
||||||
CXCursor_PreprocessingDirective = 500,
|
CXCursor_PreprocessingDirective = 500,
|
||||||
|
|
|
@ -23,9 +23,10 @@ using llvm::dyn_cast;
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
class ASTContext;
|
class ASTContext;
|
||||||
|
class IdentifierInfo;
|
||||||
|
class ObjCInterfaceDecl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Defined in ASTContext.h
|
// Defined in ASTContext.h
|
||||||
void *operator new(size_t Bytes, clang::ASTContext &C,
|
void *operator new(size_t Bytes, clang::ASTContext &C,
|
||||||
size_t Alignment = 16) throw ();
|
size_t Alignment = 16) throw ();
|
||||||
|
@ -63,6 +64,7 @@ public:
|
||||||
GNUInline,
|
GNUInline,
|
||||||
Hiding,
|
Hiding,
|
||||||
IBOutletKind, // Clang-specific. Use "Kind" suffix to not conflict w/ macro.
|
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.
|
IBActionKind, // Clang-specific. Use "Kind" suffix to not conflict w/ macro.
|
||||||
Malloc,
|
Malloc,
|
||||||
NoDebug,
|
NoDebug,
|
||||||
|
@ -318,6 +320,23 @@ public:
|
||||||
static bool classof(const IBOutletAttr *A) { return true; }
|
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 {
|
class IBActionAttr : public Attr {
|
||||||
public:
|
public:
|
||||||
IBActionAttr() : Attr(IBActionKind) {}
|
IBActionAttr() : Attr(IBActionKind) {}
|
||||||
|
|
|
@ -957,8 +957,7 @@ def err_attribute_regparm_invalid_number : Error<
|
||||||
|
|
||||||
// Clang-Specific Attributes
|
// Clang-Specific Attributes
|
||||||
def err_attribute_iboutlet : Error<
|
def err_attribute_iboutlet : Error<
|
||||||
"iboutlet attribute can only be applied to instance variables or "
|
"%0 attribute can only be applied to instance variables or properties">;
|
||||||
"properties">;
|
|
||||||
def err_attribute_ibaction: Error<
|
def err_attribute_ibaction: Error<
|
||||||
"ibaction attribute can only be applied to Objective-C instance methods">;
|
"ibaction attribute can only be applied to Objective-C instance methods">;
|
||||||
def err_attribute_overloadable_not_function : Error<
|
def err_attribute_overloadable_not_function : Error<
|
||||||
|
|
|
@ -55,6 +55,7 @@ public:
|
||||||
enum Kind { // Please keep this list alphabetized.
|
enum Kind { // Please keep this list alphabetized.
|
||||||
AT_IBAction, // Clang-specific.
|
AT_IBAction, // Clang-specific.
|
||||||
AT_IBOutlet, // Clang-specific.
|
AT_IBOutlet, // Clang-specific.
|
||||||
|
AT_IBOutletCollection, // Clang-specific.
|
||||||
AT_address_space,
|
AT_address_space,
|
||||||
AT_alias,
|
AT_alias,
|
||||||
AT_aligned,
|
AT_aligned,
|
||||||
|
|
|
@ -143,6 +143,10 @@ Attr *IBOutletAttr::clone(ASTContext &C) const {
|
||||||
return ::new (C) IBOutletAttr;
|
return ::new (C) IBOutletAttr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Attr *IBOutletCollectionAttr::clone(ASTContext &C) const {
|
||||||
|
return ::new (C) IBOutletCollectionAttr(D);
|
||||||
|
}
|
||||||
|
|
||||||
Attr *IBActionAttr::clone(ASTContext &C) const {
|
Attr *IBActionAttr::clone(ASTContext &C) const {
|
||||||
return ::new (C) IBActionAttr;
|
return ::new (C) IBActionAttr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,7 +115,8 @@ void clang::CheckObjCDealloc(const ObjCImplementationDecl* D,
|
||||||
QualType T = ID->getType();
|
QualType T = ID->getType();
|
||||||
|
|
||||||
if (!T->isObjCObjectPointerType() ||
|
if (!T->isObjCObjectPointerType() ||
|
||||||
ID->getAttr<IBOutletAttr>()) // Skip IBOutlets.
|
ID->getAttr<IBOutletAttr>() || // Skip IBOutlets.
|
||||||
|
ID->getAttr<IBOutletCollectionAttr>()) // Skip IBOutletCollections.
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
containsPointerIvar = true;
|
containsPointerIvar = true;
|
||||||
|
|
|
@ -114,7 +114,8 @@ void clang::CheckObjCUnusedIvar(const ObjCImplementationDecl *D,
|
||||||
// (b) explicitly marked unused
|
// (b) explicitly marked unused
|
||||||
// (c) are iboutlets
|
// (c) are iboutlets
|
||||||
if (ID->getAccessControl() != ObjCIvarDecl::Private ||
|
if (ID->getAccessControl() != ObjCIvarDecl::Private ||
|
||||||
ID->getAttr<UnusedAttr>() || ID->getAttr<IBOutletAttr>())
|
ID->getAttr<UnusedAttr>() || ID->getAttr<IBOutletAttr>() ||
|
||||||
|
ID->getAttr<IBOutletCollectionAttr>())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
M[ID] = Unused;
|
M[ID] = Unused;
|
||||||
|
|
|
@ -726,6 +726,13 @@ Attr *PCHReader::ReadAttributes() {
|
||||||
New = ::new (*Context) IBOutletAttr();
|
New = ::new (*Context) IBOutletAttr();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case Attr::IBOutletCollectionKind: {
|
||||||
|
ObjCInterfaceDecl *D =
|
||||||
|
cast_or_null<ObjCInterfaceDecl>(GetDecl(Record[Idx++]));
|
||||||
|
New = ::new (*Context) IBOutletCollectionAttr(D);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
SIMPLE_ATTR(Malloc);
|
SIMPLE_ATTR(Malloc);
|
||||||
SIMPLE_ATTR(NoDebug);
|
SIMPLE_ATTR(NoDebug);
|
||||||
SIMPLE_ATTR(NoInline);
|
SIMPLE_ATTR(NoInline);
|
||||||
|
|
|
@ -1917,6 +1917,12 @@ void PCHWriter::WriteAttributeRecord(const Attr *Attr) {
|
||||||
case Attr::NoThrow:
|
case Attr::NoThrow:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case Attr::IBOutletCollectionKind: {
|
||||||
|
const IBOutletCollectionAttr *ICA = cast<IBOutletCollectionAttr>(Attr);
|
||||||
|
AddDeclRef(ICA->getClass(), Record);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case Attr::NonNull: {
|
case Attr::NonNull: {
|
||||||
const NonNullAttr *NonNull = cast<NonNullAttr>(Attr);
|
const NonNullAttr *NonNull = cast<NonNullAttr>(Attr);
|
||||||
Record.push_back(NonNull->size());
|
Record.push_back(NonNull->size());
|
||||||
|
|
|
@ -84,6 +84,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
|
||||||
.Case("fastcall", AT_fastcall)
|
.Case("fastcall", AT_fastcall)
|
||||||
.Case("ibaction", AT_IBAction)
|
.Case("ibaction", AT_IBAction)
|
||||||
.Case("iboutlet", AT_IBOutlet)
|
.Case("iboutlet", AT_IBOutlet)
|
||||||
|
.Case("iboutletcollection", AT_IBOutletCollection)
|
||||||
.Case("noreturn", AT_noreturn)
|
.Case("noreturn", AT_noreturn)
|
||||||
.Case("noinline", AT_noinline)
|
.Case("noinline", AT_noinline)
|
||||||
.Case("override", AT_override)
|
.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();
|
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) {
|
static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
// GCC ignores the nonnull attribute on K&R style function prototypes, so we
|
// GCC ignores the nonnull attribute on K&R style function prototypes, so we
|
||||||
// ignore it as well
|
// ignore it as well
|
||||||
|
@ -1884,7 +1904,9 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D,
|
||||||
return;
|
return;
|
||||||
switch (Attr.getKind()) {
|
switch (Attr.getKind()) {
|
||||||
case AttributeList::AT_IBAction: HandleIBAction(D, Attr, S); break;
|
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_address_space:
|
||||||
case AttributeList::AT_objc_gc:
|
case AttributeList::AT_objc_gc:
|
||||||
case AttributeList::AT_vector_size:
|
case AttributeList::AT_vector_size:
|
||||||
|
|
|
@ -54,6 +54,18 @@ int main (int argc, const char * argv[]) {
|
||||||
main(someEnum, (const char **)bee);
|
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: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: 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)=
|
// 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: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: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: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)");
|
return createCXString("attribute(ibaction)");
|
||||||
case CXCursor_IBOutletAttr:
|
case CXCursor_IBOutletAttr:
|
||||||
return createCXString("attribute(iboutlet)");
|
return createCXString("attribute(iboutlet)");
|
||||||
|
case CXCursor_IBOutletCollectionAttr:
|
||||||
|
return createCXString("attribute(iboutletcollection)");
|
||||||
case CXCursor_PreprocessingDirective:
|
case CXCursor_PreprocessingDirective:
|
||||||
return createCXString("preprocessing directive");
|
return createCXString("preprocessing directive");
|
||||||
case CXCursor_MacroDefinition:
|
case CXCursor_MacroDefinition:
|
||||||
|
|
|
@ -80,6 +80,7 @@ static CXCursorKind GetCursorKind(const Attr *A) {
|
||||||
default: break;
|
default: break;
|
||||||
case Attr::IBActionKind: return CXCursor_IBActionAttr;
|
case Attr::IBActionKind: return CXCursor_IBActionAttr;
|
||||||
case Attr::IBOutletKind: return CXCursor_IBOutletAttr;
|
case Attr::IBOutletKind: return CXCursor_IBOutletAttr;
|
||||||
|
case Attr::IBOutletCollectionKind: return CXCursor_IBOutletCollectionAttr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return CXCursor_UnexposedAttr;
|
return CXCursor_UnexposedAttr;
|
||||||
|
|
Loading…
Reference in New Issue