From 2f041d0b12aa87f3345e5fb2e38fefba30c5bff3 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Thu, 29 Sep 2011 07:02:25 +0000 Subject: [PATCH] Like IBOutletCollection, it only makes sense to apply the IBOutlet annotation to Objective-C object types. Fixes . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@140778 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Analysis/ProgramPoint.h | 4 +- include/clang/Basic/DiagnosticSemaKinds.td | 10 ++-- lib/Sema/SemaDeclAttr.cpp | 56 ++++++++++++---------- test/Index/c-index-api-loadTU-test.m | 4 +- test/SemaObjC/iboutletcollection-attr.m | 5 +- 5 files changed, 44 insertions(+), 35 deletions(-) diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h index d0c6e71576..8f2b55c9a9 100644 --- a/include/clang/Analysis/ProgramPoint.h +++ b/include/clang/Analysis/ProgramPoint.h @@ -114,7 +114,9 @@ class BlockEntrance : public ProgramPoint { public: BlockEntrance(const CFGBlock *B, const LocationContext *L, const ProgramPointTag *tag = 0) - : ProgramPoint(B, BlockEntranceKind, L, tag) {} + : ProgramPoint(B, BlockEntranceKind, L, tag) { + assert(B && "BlockEntrance requires non-null block"); + } const CFGBlock *getBlock() const { return reinterpret_cast(getData1()); diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index d517c6aa35..6ef027441b 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1205,11 +1205,6 @@ def err_attribute_too_many_arguments : Error< "attribute takes no more than %0 argument%s0">; def err_attribute_too_few_arguments : Error< "attribute takes at least %0 argument%s0">; -def err_iboutletcollection_type : Error< - "invalid type %0 as argument of iboutletcollection attribute">; -def err_iboutletcollection_object_type : Error< - "%select{ivar|property}1 with iboutletcollection attribute must " - "have object type (invalid %0)">; def err_attribute_missing_parameter_name : Error< "attribute requires unquoted parameter">; def err_attribute_invalid_vector_type : Error<"invalid vector element type %0">; @@ -1558,6 +1553,11 @@ def warn_attribute_iboutlet : Warning< "%0 attribute can only be applied to instance variables or properties">; def warn_attribute_ibaction: Warning< "ibaction attribute can only be applied to Objective-C instance methods">; +def err_iboutletcollection_type : Error< + "invalid type %0 as argument of iboutletcollection attribute">; +def err_iboutlet_object_type : Error< + "%select{ivar|property}2 with %0 attribute must " + "be an object type (invalid %1)">; def err_attribute_overloadable_not_function : Error< "'overloadable' attribute can only be applied to a function">; def err_attribute_overloadable_missing : Error< diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 6e0dc8f4a9..435507f9d7 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -753,19 +753,41 @@ static void handleIBAction(Sema &S, Decl *D, const AttributeList &Attr) { S.Diag(Attr.getLoc(), diag::warn_attribute_ibaction) << Attr.getName(); } +static bool checkIBOutletCommon(Sema &S, Decl *D, const AttributeList &Attr) { + // The IBOutlet/IBOutletCollection attributes only apply to instance + // variables or properties of Objective-C classes. The outlet must also + // have an object reference type. + if (const ObjCIvarDecl *VD = dyn_cast(D)) { + if (!VD->getType()->getAs()) { + S.Diag(Attr.getLoc(), diag::err_iboutlet_object_type) + << Attr.getName() << VD->getType() << 0; + return false; + } + } + else if (const ObjCPropertyDecl *PD = dyn_cast(D)) { + if (!PD->getType()->getAs()) { + S.Diag(Attr.getLoc(), diag::err_iboutlet_object_type) + << Attr.getName() << PD->getType() << 1; + return false; + } + } + else { + S.Diag(Attr.getLoc(), diag::warn_attribute_iboutlet) << Attr.getName(); + return false; + } + + return true; +} + static void handleIBOutlet(Sema &S, Decl *D, const AttributeList &Attr) { // check the attribute arguments. if (!checkAttributeNumArgs(S, Attr, 0)) return; - - // The IBOutlet attributes only apply to instance variables of - // Objective-C classes. - if (isa(D) || isa(D)) { - D->addAttr(::new (S.Context) IBOutletAttr(Attr.getRange(), S.Context)); + + if (!checkIBOutletCommon(S, D, Attr)) return; - } - S.Diag(Attr.getLoc(), diag::warn_attribute_iboutlet) << Attr.getName(); + D->addAttr(::new (S.Context) IBOutletAttr(Attr.getRange(), S.Context)); } static void handleIBOutletCollection(Sema &S, Decl *D, @@ -777,25 +799,9 @@ static void handleIBOutletCollection(Sema &S, Decl *D, return; } - // The IBOutletCollection attributes only apply to instance variables of - // Objective-C classes. - if (!(isa(D) || isa(D))) { - S.Diag(Attr.getLoc(), diag::warn_attribute_iboutlet) << Attr.getName(); + if (!checkIBOutletCommon(S, D, Attr)) return; - } - if (const ValueDecl *VD = dyn_cast(D)) - if (!VD->getType()->getAs()) { - S.Diag(Attr.getLoc(), diag::err_iboutletcollection_object_type) - << VD->getType() << 0; - return; - } - if (const ObjCPropertyDecl *PD = dyn_cast(D)) - if (!PD->getType()->getAs()) { - S.Diag(Attr.getLoc(), diag::err_iboutletcollection_object_type) - << PD->getType() << 1; - return; - } - + IdentifierInfo *II = Attr.getParameterName(); if (!II) II = &S.Context.Idents.get("id"); diff --git a/test/Index/c-index-api-loadTU-test.m b/test/Index/c-index-api-loadTU-test.m index 2f74455a2b..1bca7058c8 100644 --- a/test/Index/c-index-api-loadTU-test.m +++ b/test/Index/c-index-api-loadTU-test.m @@ -60,7 +60,7 @@ int main (int argc, const char * argv[]) { #define IBAction void)__attribute__((ibaction) @interface TestAttributes { - IBOutlet char * anOutlet; + IBOutlet id anOutlet; IBOutletCollection(id) id anOutletCollection; } - (IBAction) actionMethod:(id)arg; @@ -140,7 +140,7 @@ struct X0 {}; // CHECK: c-index-api-loadTU-test.m:54:18: UnexposedExpr= 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=[58:18 - 63:27] +// CHECK: c-index-api-loadTU-test.m:63:15: ObjCIvarDecl=anOutlet:63:15 (Definition) Extent=[58:18 - 63:23] // CHECK: :0:0: attribute(iboutlet)= // CHECK: c-index-api-loadTU-test.m:64:29: ObjCIvarDecl=anOutletCollection:64:29 (Definition) Extent=[59:39 - 64:47] // CHECK: :0:0: attribute(iboutletcollection)= [IBOutletCollection=ObjCObjectPointer] diff --git a/test/SemaObjC/iboutletcollection-attr.m b/test/SemaObjC/iboutletcollection-attr.m index 5c82c8308a..6bfe313895 100644 --- a/test/SemaObjC/iboutletcollection-attr.m +++ b/test/SemaObjC/iboutletcollection-attr.m @@ -19,12 +19,13 @@ typedef void *PV; __attribute__((iboutletcollection(I, 1))) id ivar1; // expected-error {{attribute takes one argument}} __attribute__((iboutletcollection(B))) id ivar2; // expected-error {{invalid type 'B' as argument of iboutletcollection attribute}} __attribute__((iboutletcollection(PV))) id ivar3; // expected-error {{invalid type 'PV' as argument of iboutletcollection attribute}} - __attribute__((iboutletcollection(PV))) void *ivar4; // expected-error {{ivar with iboutletcollection attribute must have object type (invalid 'void *')}} + __attribute__((iboutletcollection(PV))) void *ivar4; // expected-error {{ivar with 'iboutletcollection' attribute must be an object type (invalid 'void *')}} __attribute__((iboutletcollection(int))) id ivar5; // expected-error {{type argument of iboutletcollection attribute cannot be a builtin type}} + __attribute__((iboutlet)) int ivar6; // expected-error {{ivar with 'iboutlet' attribute must be an object type}} } @property (nonatomic, retain) __attribute__((iboutletcollection(I,2,3))) id prop1; // expected-error {{attribute takes one argument}} @property (nonatomic, retain) __attribute__((iboutletcollection(B))) id prop2; // expected-error {{invalid type 'B' as argument of iboutletcollection attribute}} -@property __attribute__((iboutletcollection(BAD))) int prop3; // expected-error {{property with iboutletcollection attribute must have object type (invalid 'int')}} +@property __attribute__((iboutletcollection(BAD))) int prop3; // expected-error {{property with 'iboutletcollection' attribute must be an object type (invalid 'int')}} @end -- 2.40.0