diff --git a/clang/lib/Rewrite/RewriteModernObjC.cpp b/clang/lib/Rewrite/RewriteModernObjC.cpp index 66069766bb5f..410e68908d1f 100644 --- a/clang/lib/Rewrite/RewriteModernObjC.cpp +++ b/clang/lib/Rewrite/RewriteModernObjC.cpp @@ -3523,6 +3523,11 @@ bool RewriteModernObjC::IsTagDefinedInsideClass(ObjCContainerDecl *IDecl, /// It handles elaborated types, as well as enum types in the process. bool RewriteModernObjC::RewriteObjCFieldDeclType(QualType &Type, std::string &Result) { + if (isa(Type)) { + Result += "\t"; + return false; + } + if (Type->isArrayType()) { QualType ElemTy = Context->getBaseElementType(Type); return RewriteObjCFieldDeclType(ElemTy, Result); @@ -3618,6 +3623,8 @@ void RewriteModernObjC::RewriteObjCFieldDecl(FieldDecl *fieldDecl, void RewriteModernObjC::RewriteLocallyDefinedNamedAggregates(FieldDecl *fieldDecl, std::string &Result) { QualType Type = fieldDecl->getType(); + if (isa(Type)) + return; if (Type->isArrayType()) Type = Context->getBaseElementType(Type); ObjCContainerDecl *IDecl = @@ -7308,12 +7315,17 @@ Stmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) { addExpr); QualType IvarT = D->getType(); - if (IvarT->isRecordType()) { + if (!isa(IvarT) && IvarT->isRecordType()) { RecordDecl *RD = IvarT->getAs()->getDecl(); RD = RD->getDefinition(); if (RD && !RD->getDeclName().getAsIdentifierInfo()) { // decltype(((Foo_IMPL*)0)->bar) * - std::string RecName = iFaceDecl->getDecl()->getName(); + ObjCContainerDecl *CDecl = + dyn_cast(D->getDeclContext()); + // ivar in class extensions requires special treatment. + if (ObjCCategoryDecl *CatDecl = dyn_cast(CDecl)) + CDecl = CatDecl->getClassInterface(); + std::string RecName = CDecl->getName(); RecName += "_IMPL"; RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, SourceLocation(), SourceLocation(), diff --git a/clang/test/Rewriter/rewrite-modern-struct-ivar-1.mm b/clang/test/Rewriter/rewrite-modern-struct-ivar-1.mm new file mode 100644 index 000000000000..a17fe3f85675 --- /dev/null +++ b/clang/test/Rewriter/rewrite-modern-struct-ivar-1.mm @@ -0,0 +1,48 @@ +// RUN: %clang_cc1 -fblocks -rewrite-objc -fms-extensions %s -o %t-rw.cpp +// RUN: %clang_cc1 -Werror -fsyntax-only -Wno-address-of-temporary -Wno-c++11-narrowing -std=c++11 -D"Class=void*" -D"id=void*" -D"SEL=void*" -U__declspec -D"__declspec(X)=" %t-rw.cpp +// rdar://11323187 + +typedef unsigned long NSUInteger; + +typedef struct _NSRange { + NSUInteger location; + NSUInteger length; +} NSRange; + +typedef struct { + NSUInteger _capacity; + NSRange _ranges[0]; +} _NSRangeInfo; + +@interface Foo{ + @protected + struct _bar { + int x:1; + int y:1; + } bar; + union { + struct { + NSRange _range; + } _singleRange; + struct { + void * _data; + void *_reserved; + } _multipleRanges; + } _internal; +} +@end +@implementation Foo +- (void)x:(Foo *)other { + bar.x = 0; + bar.y = 1; + self->_internal._singleRange._range = (( other ->bar.x) ? &( other ->_internal._singleRange._range) : ((NSRange *)(&(((_NSRangeInfo *)( other ->_internal._multipleRanges._data))->_ranges))))[0]; +} +@end +@interface FooS : Foo +@end +@implementation FooS +- (void)y { + + NSUInteger asdf = (( self ->bar.x) ? 1 : ((_NSRangeInfo *)( self ->_internal._multipleRanges._data))->_capacity ); +} +@end