From: Fariborz Jahanian Date: Tue, 28 Feb 2012 22:45:07 +0000 (+0000) Subject: Modern objective-c translator. rewriting ivars of aggregate type. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=15f87771cae0c31da45c05b34841d0a2ca70bc87;p=clang Modern objective-c translator. rewriting ivars of aggregate type. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@151662 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Rewrite/RewriteModernObjC.cpp b/lib/Rewrite/RewriteModernObjC.cpp index a2dbf9f437..db1f5ff471 100644 --- a/lib/Rewrite/RewriteModernObjC.cpp +++ b/lib/Rewrite/RewriteModernObjC.cpp @@ -108,6 +108,7 @@ namespace { llvm::SmallPtrSet ObjCSynthesizedStructs; llvm::SmallPtrSet ObjCSynthesizedProtocols; llvm::SmallPtrSet ObjCWrittenInterfaces; + llvm::SmallPtrSet TagsDefinedInIvarDecls; SmallVector ObjCInterfacesSeen; SmallVector Stmts; SmallVector ObjCBcLabelNo; @@ -333,6 +334,8 @@ namespace { void RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl, std::string &Result); + void RewriteObjCFieldDecl(FieldDecl *fieldDecl, std::string &Result); + void RewriteIvarOffsetSymbols(ObjCInterfaceDecl *CDecl, std::string &Result); @@ -3165,6 +3168,78 @@ bool RewriteModernObjC::BufferContainsPPDirectives(const char *startBuf, 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(); + + if (Type->isRecordType()) { + RecordDecl *RD = Type->getAs()->getDecl(); + if (RD->isCompleteDefinition()) { + if (RD->isStruct()) + Result += "\n\tstruct "; + else if (RD->isUnion()) + 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; + } + TagsDefinedInIvarDecls.insert(RD); + Result += " {\n"; + for (RecordDecl::field_iterator i = RD->field_begin(), + e = RD->field_end(); i != e; ++i) { + FieldDecl *FD = *i; + RewriteObjCFieldDecl(FD, Result); + } + Result += "\t} "; + Result += Name; Result += ";\n"; + return; + } + } + else if (Type->isEnumeralType()) { + EnumDecl *ED = Type->getAs()->getDecl(); + if (ED->isCompleteDefinition()) { + Result += "\n\tenum "; + Result += ED->getName(); + if (TagsDefinedInIvarDecls.count(ED)) { + // This enum is already defined. Do not write its definition again. + Result += " "; Result += Name; Result += ";\n"; + return; + } + TagsDefinedInIvarDecls.insert(ED); + + Result += " {\n"; + for (EnumDecl::enumerator_iterator EC = ED->enumerator_begin(), + ECEnd = ED->enumerator_end(); EC != ECEnd; ++EC) { + Result += "\t"; Result += EC->getName(); Result += " = "; + llvm::APSInt Val = EC->getInitVal(); + Result += Val.toString(10); + Result += ",\n"; + } + Result += "\t} "; + Result += Name; Result += ";\n"; + return; + } + } + + Result += "\t"; + convertObjCTypeToCStyleType(Type); + + Type.getAsStringInternal(Name, Context->getPrintingPolicy()); + Result += Name; + if (fieldDecl->isBitField()) { + Result += " : "; Result += utostr(fieldDecl->getBitWidthValue(*Context)); + } + Result += ";\n"; +} + /// RewriteObjCInternalStruct - Rewrite one internal struct corresponding to /// an objective-c class with ivars. void RewriteModernObjC::RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl, @@ -3205,22 +3280,10 @@ void RewriteModernObjC::RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl, Result += "_IMPL "; Result += RCDecl->getNameAsString(); Result += "_IVARS;\n"; } - - for (unsigned i = 0, e = IVars.size(); i < e; i++) { - ObjCIvarDecl *IvarDecl = IVars[i]; - QualType Type = IvarDecl->getType(); - std::string Name = IvarDecl->getNameAsString(); + TagsDefinedInIvarDecls.clear(); + for (unsigned i = 0, e = IVars.size(); i < e; i++) + RewriteObjCFieldDecl(IVars[i], Result); - Result += "\t"; - convertObjCTypeToCStyleType(Type); - - Type.getAsStringInternal(Name, Context->getPrintingPolicy()); - Result += Name; - if (IvarDecl->isBitField()) { - Result += " : "; Result += utostr(IvarDecl->getBitWidthValue(*Context)); - } - Result += ";\n"; - } Result += "};\n"; endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts); ReplaceText(LocStart, endBuf-startBuf, Result); diff --git a/test/Rewriter/rewrite-modern-ivars-1.mm b/test/Rewriter/rewrite-modern-ivars-1.mm new file mode 100644 index 0000000000..376d300c7e --- /dev/null +++ b/test/Rewriter/rewrite-modern-ivars-1.mm @@ -0,0 +1,89 @@ +// 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 NSCheapMutableString { +@private + struct S s0; + union { + char *fat; + unsigned char *thin; + } contents; + + struct { + unsigned int isFat:1; + unsigned int freeWhenDone:1; + unsigned int refs:30; + } flags; + + struct S { + int iS1; + double dS1; + } others; + + union U { + int iU1; + double dU1; + } u_others; + + enum { + One, Two + } E1; + + enum e { + Yes = 1, + No = 0 + } BoOl; + + struct S s1; + + enum e E2; + + union { + char *fat; + unsigned char *thin; + } Last_contents; + + struct { + unsigned int isFat:1; + unsigned int freeWhenDone:1; + unsigned int refs:30; + } Last_flags; +} +@end + +@interface III { +@private + struct S s0; + + union { + char *fat; + unsigned char *thin; + } contents; + + struct { + unsigned int isFat:1; + unsigned int freeWhenDone:1; + unsigned int refs:30; + } flags; + + enum { + One1 = 1000, Two1, Three1 + } E1; + + struct S s1; + + enum e E2; + + union { + char *fat; + unsigned char *thin; + } Last_contents; + + struct { + unsigned int isFat:1; + unsigned int freeWhenDone:1; + unsigned int refs:30; + } Last_flags; +} +@end +