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.deb...@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 > + > +@interface FootableSet : NSMutableSet > +@end > + > +@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}} > +} > +@end > + > +@interface FootableArray : NSMutableArray > +@end > + > +@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}} > +} > +@end > + > +@interface FootableDictionary : NSMutableDictionary > +@end > + > +@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}} > +} > +@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@lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
signature.asc
Description: Message signed with OpenPGP using GPGMail
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits