r244193 - [ObjC] Circular containers: add support of subclasses
AlexDenisov
1101.debian at gmail.com
Wed Aug 5 21:54:27 PDT 2015
Hi, Hans.
The patch fixes crash reported by Argyrios.
Might be a candidate for release_37.
--
AlexDenisov
Software Engineer, http://lowlevelbits.org
> On 06 Aug 2015, at 06:51, Alex Denisov <1101.debian at gmail.com> wrote:
>
> Author: alexdenisov
> Date: Wed Aug 5 23:51:14 2015
> New Revision: 244193
>
> URL: http://llvm.org/viewvc/llvm-project?rev=244193&view=rev
> Log:
> [ObjC] Circular containers: add support of subclasses
>
>
> Modified:
> cfe/trunk/include/clang/AST/NSAPI.h
> cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> cfe/trunk/include/clang/Sema/Sema.h
> cfe/trunk/lib/AST/NSAPI.cpp
> cfe/trunk/lib/Sema/SemaChecking.cpp
> cfe/trunk/test/SemaObjC/circular-container.m
>
> Modified: cfe/trunk/include/clang/AST/NSAPI.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/NSAPI.h?rev=244193&r1=244192&r2=244193&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/NSAPI.h (original)
> +++ cfe/trunk/include/clang/AST/NSAPI.h Wed Aug 5 23:51:14 2015
> @@ -16,6 +16,7 @@
>
> namespace clang {
> class ASTContext;
> + class ObjCInterfaceDecl;
> class QualType;
> class Expr;
>
> @@ -35,11 +36,10 @@ public:
> ClassId_NSMutableDictionary,
> ClassId_NSNumber,
> ClassId_NSMutableSet,
> - ClassId_NSCountedSet,
> ClassId_NSMutableOrderedSet,
> ClassId_NSValue
> };
> - static const unsigned NumClassIds = 11;
> + static const unsigned NumClassIds = 10;
>
> enum NSStringMethodKind {
> NSStr_stringWithString,
> @@ -220,6 +220,10 @@ public:
> /// \brief Returns \c true if \p Id is currently defined as a macro.
> bool isMacroDefined(StringRef Id) const;
>
> + /// \brief Returns \c true if \p InterfaceDecl is subclass of \p NSClassKind
> + bool isSubclassOfNSClass(ObjCInterfaceDecl *InterfaceDecl,
> + NSClassIdKindKind NSClassKind) const;
> +
> private:
> bool isObjCTypedef(QualType T, StringRef name, IdentifierInfo *&II) const;
> bool isObjCEnumerator(const Expr *E,
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=244193&r1=244192&r2=244193&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Aug 5 23:51:14 2015
> @@ -5370,7 +5370,7 @@ def err_objc_object_catch : Error<
> def err_incomplete_type_objc_at_encode : Error<
> "'@encode' of incomplete type %0">;
> def warn_objc_circular_container : Warning<
> - "adding '%0' to '%0' might cause circular dependency in container">,
> + "adding '%0' to '%1' might cause circular dependency in container">,
> InGroup<DiagGroup<"objc-circular-container">>;
> def note_objc_circular_container_declared_here : Note<"'%0' declared here">;
>
>
> Modified: cfe/trunk/include/clang/Sema/Sema.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=244193&r1=244192&r2=244193&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Sema/Sema.h (original)
> +++ cfe/trunk/include/clang/Sema/Sema.h Wed Aug 5 23:51:14 2015
> @@ -729,27 +729,12 @@ public:
> /// \brief The declaration of the Objective-C NSArray class.
> ObjCInterfaceDecl *NSArrayDecl;
>
> - /// \brief Pointer to NSMutableArray type (NSMutableArray *).
> - QualType NSMutableArrayPointer;
> -
> /// \brief The declaration of the arrayWithObjects:count: method.
> ObjCMethodDecl *ArrayWithObjectsMethod;
>
> /// \brief The declaration of the Objective-C NSDictionary class.
> ObjCInterfaceDecl *NSDictionaryDecl;
>
> - /// \brief Pointer to NSMutableDictionary type (NSMutableDictionary *).
> - QualType NSMutableDictionaryPointer;
> -
> - /// \brief Pointer to NSMutableSet type (NSMutableSet *).
> - QualType NSMutableSetPointer;
> -
> - /// \brief Pointer to NSCountedSet type (NSCountedSet *).
> - QualType NSCountedSetPointer;
> -
> - /// \brief Pointer to NSMutableOrderedSet type (NSMutableOrderedSet *).
> - QualType NSMutableOrderedSetPointer;
> -
> /// \brief The declaration of the dictionaryWithObjects:forKeys:count: method.
> ObjCMethodDecl *DictionaryWithObjectsMethod;
>
>
> Modified: cfe/trunk/lib/AST/NSAPI.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/NSAPI.cpp?rev=244193&r1=244192&r2=244193&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/NSAPI.cpp (original)
> +++ cfe/trunk/lib/AST/NSAPI.cpp Wed Aug 5 23:51:14 2015
> @@ -9,6 +9,7 @@
>
> #include "clang/AST/NSAPI.h"
> #include "clang/AST/ASTContext.h"
> +#include "clang/AST/DeclObjC.h"
> #include "clang/AST/Expr.h"
> #include "llvm/ADT/StringSwitch.h"
>
> @@ -29,7 +30,6 @@ IdentifierInfo *NSAPI::getNSClassId(NSCl
> "NSMutableDictionary",
> "NSNumber",
> "NSMutableSet",
> - "NSCountedSet",
> "NSMutableOrderedSet",
> "NSValue"
> };
> @@ -511,6 +511,26 @@ bool NSAPI::isMacroDefined(StringRef Id)
> return Ctx.Idents.get(Id).hasMacroDefinition();
> }
>
> +bool NSAPI::isSubclassOfNSClass(ObjCInterfaceDecl *InterfaceDecl,
> + NSClassIdKindKind NSClassKind) const {
> + if (!InterfaceDecl) {
> + return false;
> + }
> +
> + IdentifierInfo *NSClassID = getNSClassId(NSClassKind);
> +
> + bool IsSubclass = false;
> + do {
> + IsSubclass = NSClassID == InterfaceDecl->getIdentifier();
> +
> + if (IsSubclass) {
> + break;
> + }
> + } while ((InterfaceDecl = InterfaceDecl->getSuperClass()));
> +
> + return IsSubclass;
> +}
> +
> bool NSAPI::isObjCTypedef(QualType T,
> StringRef name, IdentifierInfo *&II) const {
> if (!Ctx.getLangOpts().ObjC1)
>
> Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=244193&r1=244192&r2=244193&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaChecking.cpp Wed Aug 5 23:51:14 2015
> @@ -8727,23 +8727,10 @@ static bool isSetterLikeSelector(Selecto
>
> static Optional<int> GetNSMutableArrayArgumentIndex(Sema &S,
> ObjCMessageExpr *Message) {
> - if (S.NSMutableArrayPointer.isNull()) {
> - IdentifierInfo *NSMutableArrayId =
> - S.NSAPIObj->getNSClassId(NSAPI::ClassId_NSMutableArray);
> - NamedDecl *IF = S.LookupSingleName(S.TUScope, NSMutableArrayId,
> - Message->getLocStart(),
> - Sema::LookupOrdinaryName);
> - ObjCInterfaceDecl *InterfaceDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
> - if (!InterfaceDecl) {
> - return None;
> - }
> - QualType NSMutableArrayObject =
> - S.Context.getObjCInterfaceType(InterfaceDecl);
> - S.NSMutableArrayPointer =
> - S.Context.getObjCObjectPointerType(NSMutableArrayObject);
> - }
> -
> - if (S.NSMutableArrayPointer != Message->getReceiverType()) {
> + bool IsMutableArray = S.NSAPIObj->isSubclassOfNSClass(
> + Message->getReceiverInterface(),
> + NSAPI::ClassId_NSMutableArray);
> + if (!IsMutableArray) {
> return None;
> }
>
> @@ -8775,24 +8762,10 @@ static Optional<int> GetNSMutableArrayAr
> static
> Optional<int> GetNSMutableDictionaryArgumentIndex(Sema &S,
> ObjCMessageExpr *Message) {
> -
> - if (S.NSMutableDictionaryPointer.isNull()) {
> - IdentifierInfo *NSMutableDictionaryId =
> - S.NSAPIObj->getNSClassId(NSAPI::ClassId_NSMutableDictionary);
> - NamedDecl *IF = S.LookupSingleName(S.TUScope, NSMutableDictionaryId,
> - Message->getLocStart(),
> - Sema::LookupOrdinaryName);
> - ObjCInterfaceDecl *InterfaceDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
> - if (!InterfaceDecl) {
> - return None;
> - }
> - QualType NSMutableDictionaryObject =
> - S.Context.getObjCInterfaceType(InterfaceDecl);
> - S.NSMutableDictionaryPointer =
> - S.Context.getObjCObjectPointerType(NSMutableDictionaryObject);
> - }
> -
> - if (S.NSMutableDictionaryPointer != Message->getReceiverType()) {
> + bool IsMutableDictionary = S.NSAPIObj->isSubclassOfNSClass(
> + Message->getReceiverInterface(),
> + NSAPI::ClassId_NSMutableDictionary);
> + if (!IsMutableDictionary) {
> return None;
> }
>
> @@ -8820,63 +8793,14 @@ Optional<int> GetNSMutableDictionaryArgu
> }
>
> static Optional<int> GetNSSetArgumentIndex(Sema &S, ObjCMessageExpr *Message) {
> -
> - ObjCInterfaceDecl *InterfaceDecl;
> - if (S.NSMutableSetPointer.isNull()) {
> - IdentifierInfo *NSMutableSetId =
> - S.NSAPIObj->getNSClassId(NSAPI::ClassId_NSMutableSet);
> - NamedDecl *IF = S.LookupSingleName(S.TUScope, NSMutableSetId,
> - Message->getLocStart(),
> - Sema::LookupOrdinaryName);
> - InterfaceDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
> - if (InterfaceDecl) {
> - QualType NSMutableSetObject =
> - S.Context.getObjCInterfaceType(InterfaceDecl);
> - S.NSMutableSetPointer =
> - S.Context.getObjCObjectPointerType(NSMutableSetObject);
> - }
> - }
> -
> - if (S.NSCountedSetPointer.isNull()) {
> - IdentifierInfo *NSCountedSetId =
> - S.NSAPIObj->getNSClassId(NSAPI::ClassId_NSCountedSet);
> - NamedDecl *IF = S.LookupSingleName(S.TUScope, NSCountedSetId,
> - Message->getLocStart(),
> - Sema::LookupOrdinaryName);
> - InterfaceDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
> - if (InterfaceDecl) {
> - QualType NSCountedSetObject =
> - S.Context.getObjCInterfaceType(InterfaceDecl);
> - S.NSCountedSetPointer =
> - S.Context.getObjCObjectPointerType(NSCountedSetObject);
> - }
> - }
> -
> - if (S.NSMutableOrderedSetPointer.isNull()) {
> - IdentifierInfo *NSOrderedSetId =
> - S.NSAPIObj->getNSClassId(NSAPI::ClassId_NSMutableOrderedSet);
> - NamedDecl *IF = S.LookupSingleName(S.TUScope, NSOrderedSetId,
> - Message->getLocStart(),
> - Sema::LookupOrdinaryName);
> - InterfaceDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
> - if (InterfaceDecl) {
> - QualType NSOrderedSetObject =
> - S.Context.getObjCInterfaceType(InterfaceDecl);
> - S.NSMutableOrderedSetPointer =
> - S.Context.getObjCObjectPointerType(NSOrderedSetObject);
> - }
> - }
> -
> - QualType ReceiverType = Message->getReceiverType();
> -
> - bool IsMutableSet = !S.NSMutableSetPointer.isNull() &&
> - ReceiverType == S.NSMutableSetPointer;
> - bool IsMutableOrderedSet = !S.NSMutableOrderedSetPointer.isNull() &&
> - ReceiverType == S.NSMutableOrderedSetPointer;
> - bool IsCountedSet = !S.NSCountedSetPointer.isNull() &&
> - ReceiverType == S.NSCountedSetPointer;
> -
> - if (!IsMutableSet && !IsMutableOrderedSet && !IsCountedSet) {
> + bool IsMutableSet = S.NSAPIObj->isSubclassOfNSClass(
> + Message->getReceiverInterface(),
> + NSAPI::ClassId_NSMutableSet);
> +
> + bool IsMutableOrderedSet = S.NSAPIObj->isSubclassOfNSClass(
> + Message->getReceiverInterface(),
> + NSAPI::ClassId_NSMutableOrderedSet);
> + if (!IsMutableSet && !IsMutableOrderedSet) {
> return None;
> }
>
> @@ -8917,38 +8841,51 @@ void Sema::CheckObjCCircularContainer(Ob
>
> int ArgIndex = *ArgOpt;
>
> - Expr *Receiver = Message->getInstanceReceiver()->IgnoreImpCasts();
> - if (OpaqueValueExpr *OE = dyn_cast<OpaqueValueExpr>(Receiver)) {
> - Receiver = OE->getSourceExpr()->IgnoreImpCasts();
> - }
> -
> Expr *Arg = Message->getArg(ArgIndex)->IgnoreImpCasts();
> if (OpaqueValueExpr *OE = dyn_cast<OpaqueValueExpr>(Arg)) {
> Arg = OE->getSourceExpr()->IgnoreImpCasts();
> }
>
> - if (DeclRefExpr *ReceiverRE = dyn_cast<DeclRefExpr>(Receiver)) {
> + if (Message->getReceiverKind() == ObjCMessageExpr::SuperInstance) {
> if (DeclRefExpr *ArgRE = dyn_cast<DeclRefExpr>(Arg)) {
> - if (ReceiverRE->getDecl() == ArgRE->getDecl()) {
> - ValueDecl *Decl = ReceiverRE->getDecl();
> + if (ArgRE->isObjCSelfExpr()) {
> Diag(Message->getSourceRange().getBegin(),
> diag::warn_objc_circular_container)
> - << Decl->getName();
> - Diag(Decl->getLocation(),
> - diag::note_objc_circular_container_declared_here)
> - << Decl->getName();
> + << ArgRE->getDecl()->getName() << StringRef("super");
> }
> }
> - } else if (ObjCIvarRefExpr *IvarRE = dyn_cast<ObjCIvarRefExpr>(Receiver)) {
> - if (ObjCIvarRefExpr *IvarArgRE = dyn_cast<ObjCIvarRefExpr>(Arg)) {
> - if (IvarRE->getDecl() == IvarArgRE->getDecl()) {
> - ObjCIvarDecl *Decl = IvarRE->getDecl();
> - Diag(Message->getSourceRange().getBegin(),
> - diag::warn_objc_circular_container)
> - << Decl->getName();
> - Diag(Decl->getLocation(),
> - diag::note_objc_circular_container_declared_here)
> - << Decl->getName();
> + } else {
> + Expr *Receiver = Message->getInstanceReceiver()->IgnoreImpCasts();
> +
> + if (OpaqueValueExpr *OE = dyn_cast<OpaqueValueExpr>(Receiver)) {
> + Receiver = OE->getSourceExpr()->IgnoreImpCasts();
> + }
> +
> + if (DeclRefExpr *ReceiverRE = dyn_cast<DeclRefExpr>(Receiver)) {
> + if (DeclRefExpr *ArgRE = dyn_cast<DeclRefExpr>(Arg)) {
> + if (ReceiverRE->getDecl() == ArgRE->getDecl()) {
> + ValueDecl *Decl = ReceiverRE->getDecl();
> + Diag(Message->getSourceRange().getBegin(),
> + diag::warn_objc_circular_container)
> + << Decl->getName() << Decl->getName();
> + if (!ArgRE->isObjCSelfExpr()) {
> + Diag(Decl->getLocation(),
> + diag::note_objc_circular_container_declared_here)
> + << Decl->getName();
> + }
> + }
> + }
> + } else if (ObjCIvarRefExpr *IvarRE = dyn_cast<ObjCIvarRefExpr>(Receiver)) {
> + if (ObjCIvarRefExpr *IvarArgRE = dyn_cast<ObjCIvarRefExpr>(Arg)) {
> + if (IvarRE->getDecl() == IvarArgRE->getDecl()) {
> + ObjCIvarDecl *Decl = IvarRE->getDecl();
> + Diag(Message->getSourceRange().getBegin(),
> + diag::warn_objc_circular_container)
> + << Decl->getName() << Decl->getName();
> + Diag(Decl->getLocation(),
> + diag::note_objc_circular_container_declared_here)
> + << Decl->getName();
> + }
> }
> }
> }
>
> Modified: cfe/trunk/test/SemaObjC/circular-container.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/circular-container.m?rev=244193&r1=244192&r2=244193&view=diff
> ==============================================================================
> --- cfe/trunk/test/SemaObjC/circular-container.m (original)
> +++ cfe/trunk/test/SemaObjC/circular-container.m Wed Aug 5 23:51:14 2015
> @@ -144,3 +144,64 @@ void checkNSMutableOrderedSet() {
> [s replaceObjectAtIndex:0 withObject:s]; // expected-warning {{adding 's' to 's' might cause circular dependency in container}}
> }
>
> +// Test subclassing
> +
> + at interface FootableSet : NSMutableSet
> + at end
> +
> + at implementation FootableSet
> +- (void)meth {
> + [super addObject:self]; // expected-warning {{adding 'self' to 'super' might cause circular dependency in container}}
> + [super addObject:nil]; // no-warning
> + [self addObject:self]; // expected-warning {{adding 'self' to 'self' might cause circular dependency in container}}
> +}
> + at end
> +
> + at interface FootableArray : NSMutableArray
> + at end
> +
> + at implementation FootableArray
> +- (void)meth {
> + [super addObject:self]; // expected-warning {{adding 'self' to 'super' might cause circular dependency in container}}
> + [super addObject:nil]; // no-warning
> + [self addObject:self]; // expected-warning {{adding 'self' to 'self' might cause circular dependency in container}}
> +}
> + at end
> +
> + at interface FootableDictionary : NSMutableDictionary
> + at end
> +
> + at implementation FootableDictionary
> +- (void)meth {
> + [super setObject:self forKey:@"key"]; // expected-warning {{adding 'self' to 'super' might cause circular dependency in container}}
> + [super setObject:nil forKey:@"key"]; // no-warning
> + [self setObject:self forKey:@"key"]; // expected-warning {{adding 'self' to 'self' might cause circular dependency in container}}
> +}
> + at end
> +
> +
> +void subclassingNSMutableArray() {
> + FootableArray *a = nil; // expected-note 5 {{'a' declared here}} 5
> +
> + [a addObject:a]; // expected-warning {{adding 'a' to 'a' might cause circular dependency in container}}
> + [a insertObject:a atIndex:0]; // expected-warning {{adding 'a' to 'a' might cause circular dependency in container}}
> + [a replaceObjectAtIndex:0 withObject:a]; // expected-warning {{adding 'a' to 'a' might cause circular dependency in container}}
> + [a setObject:a atIndexedSubscript:0]; // expected-warning {{adding 'a' to 'a' might cause circular dependency in container}}
> + a[0] = a; // expected-warning {{adding 'a' to 'a' might cause circular dependency in container}}
> +}
> +
> +void subclassingNSMutableDictionary() {
> + FootableDictionary *d = nil; // expected-note 4 {{'d' declared here}}
> +
> + [d setObject:d forKey:@"key"]; // expected-warning {{adding 'd' to 'd' might cause circular dependency in container}}
> + [d setObject:d forKeyedSubscript:@"key"]; // expected-warning {{adding 'd' to 'd' might cause circular dependency in container}}
> + [d setValue:d forKey:@"key"]; // expected-warning {{adding 'd' to 'd' might cause circular dependency in container}}
> + d[@"key"] = d; // expected-warning {{adding 'd' to 'd' might cause circular dependency in container}}
> +}
> +
> +void subclassingNSMutableSet() {
> + FootableSet *s = nil; // expected-note {{'s' declared here}}
> +
> + [s addObject:s]; // expected-warning {{adding 's' to 's' might cause circular dependency in container}}
> +}
> +
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 496 bytes
Desc: Message signed with OpenPGP using GPGMail
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20150806/89024de5/attachment-0001.sig>
More information about the cfe-commits
mailing list