diff --git a/clang/lib/Rewrite/RewriteModernObjC.cpp b/clang/lib/Rewrite/RewriteModernObjC.cpp index fdaf44dd3300..111de2e49587 100644 --- a/clang/lib/Rewrite/RewriteModernObjC.cpp +++ b/clang/lib/Rewrite/RewriteModernObjC.cpp @@ -336,6 +336,8 @@ namespace { void RewriteObjCFieldDecl(FieldDecl *fieldDecl, std::string &Result); + bool RewriteObjCFieldDeclType(QualType &Type, std::string &Result); + void RewriteIvarOffsetSymbols(ObjCInterfaceDecl *CDecl, std::string &Result); @@ -3168,14 +3170,15 @@ bool RewriteModernObjC::BufferContainsPPDirectives(const char *startBuf, return false; } -/// RewriteObjCFieldDecl - This routine rewrites a field into the buffer. +/// RewriteObjCFieldDeclType - This routine rewrites a type into the buffer. /// It handles elaborated types, as well as enum types in the process. -void RewriteModernObjC::RewriteObjCFieldDecl(FieldDecl *fieldDecl, - std::string &Result) { - QualType Type = fieldDecl->getType(); - std::string Name = fieldDecl->getNameAsString(); - - if (Type->isRecordType()) { +bool RewriteModernObjC::RewriteObjCFieldDeclType(QualType &Type, + std::string &Result) { + if (Type->isArrayType()) { + QualType ElemTy = Context->getBaseElementType(Type); + return RewriteObjCFieldDeclType(ElemTy, Result); + } + else if (Type->isRecordType()) { RecordDecl *RD = Type->getAs()->getDecl(); if (RD->isCompleteDefinition()) { if (RD->isStruct()) @@ -3184,23 +3187,22 @@ void RewriteModernObjC::RewriteObjCFieldDecl(FieldDecl *fieldDecl, Result += "\n\tunion "; else assert(false && "class not allowed as an ivar type"); - + Result += RD->getName(); if (TagsDefinedInIvarDecls.count(RD)) { // This struct is already defined. Do not write its definition again. - Result += " "; Result += Name; Result += ";\n"; - return; + Result += " "; + return true; } TagsDefinedInIvarDecls.insert(RD); Result += " {\n"; for (RecordDecl::field_iterator i = RD->field_begin(), - e = RD->field_end(); i != e; ++i) { + e = RD->field_end(); i != e; ++i) { FieldDecl *FD = *i; RewriteObjCFieldDecl(FD, Result); } Result += "\t} "; - Result += Name; Result += ";\n"; - return; + return true; } } else if (Type->isEnumeralType()) { @@ -3210,8 +3212,8 @@ void RewriteModernObjC::RewriteObjCFieldDecl(FieldDecl *fieldDecl, Result += ED->getName(); if (TagsDefinedInIvarDecls.count(ED)) { // This enum is already defined. Do not write its definition again. - Result += " "; Result += Name; Result += ";\n"; - return; + Result += " "; + return true; } TagsDefinedInIvarDecls.insert(ED); @@ -3224,19 +3226,43 @@ void RewriteModernObjC::RewriteObjCFieldDecl(FieldDecl *fieldDecl, Result += ",\n"; } Result += "\t} "; - Result += Name; Result += ";\n"; - return; + return true; } } Result += "\t"; convertObjCTypeToCStyleType(Type); + return false; +} + + +/// RewriteObjCFieldDecl - This routine rewrites a field into the buffer. +/// It handles elaborated types, as well as enum types in the process. +void RewriteModernObjC::RewriteObjCFieldDecl(FieldDecl *fieldDecl, + std::string &Result) { + QualType Type = fieldDecl->getType(); + std::string Name = fieldDecl->getNameAsString(); - Type.getAsStringInternal(Name, Context->getPrintingPolicy()); + bool EleboratedType = RewriteObjCFieldDeclType(Type, Result); + if (!EleboratedType) + Type.getAsStringInternal(Name, Context->getPrintingPolicy()); Result += Name; if (fieldDecl->isBitField()) { Result += " : "; Result += utostr(fieldDecl->getBitWidthValue(*Context)); } + else if (EleboratedType && Type->isArrayType()) { + CanQualType CType = Context->getCanonicalType(Type); + while (isa(CType)) { + if (const ConstantArrayType *CAT = Context->getAsConstantArrayType(CType)) { + Result += "["; + llvm::APInt Dim = CAT->getSize(); + Result += utostr(Dim.getZExtValue()); + Result += "]"; + } + CType = CType->getAs()->getElementType(); + } + } + Result += ";\n"; } diff --git a/clang/test/Rewriter/rewrite-modern-ivars-2.mm b/clang/test/Rewriter/rewrite-modern-ivars-2.mm new file mode 100644 index 000000000000..ead8e8f548a5 --- /dev/null +++ b/clang/test/Rewriter/rewrite-modern-ivars-2.mm @@ -0,0 +1,73 @@ +// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp +// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -D"Class=void*" -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp + +@interface B @end + +@interface A { + struct s0 { + int f0; + int f1; + } f0; + id f1; +__weak B *f2; + int f3 : 5; + struct s1 { + int *f0; + int *f1; + } f4[2][1]; +} +@end + +@interface C : A +@property int p3; +@end + +@implementation C +@synthesize p3 = _p3; +@end + +@interface A() +@property int p0; +@property (assign) __strong id p1; +@property (assign) __weak id p2; +@end + +// FIXME: Check layout for this class, once it is clear what the right +// answer is. +@implementation A +@synthesize p0 = _p0; +@synthesize p1 = _p1; +@synthesize p2 = _p2; +@end + +@interface D : A +@property int p3; +@end + +// FIXME: Check layout for this class, once it is clear what the right +// answer is. +@implementation D +@synthesize p3 = _p3; +@end + +typedef unsigned short UInt16; + + +typedef signed char BOOL; +typedef unsigned int FSCatalogInfoBitmap; + +@interface NSFileLocationComponent { + @private + + id _specifierOrStandardizedPath; + BOOL _carbonCatalogInfoAndNameAreValid; + FSCatalogInfoBitmap _carbonCatalogInfoMask; + id _name; + id _containerComponent; + id _presentableName; + id _iconAsAttributedString; +} +@end + +@implementation NSFileLocationComponent @end +