diff options
Diffstat (limited to 'lib/Rewrite/Frontend/RewriteModernObjC.cpp')
-rw-r--r-- | lib/Rewrite/Frontend/RewriteModernObjC.cpp | 568 |
1 files changed, 410 insertions, 158 deletions
diff --git a/lib/Rewrite/Frontend/RewriteModernObjC.cpp b/lib/Rewrite/Frontend/RewriteModernObjC.cpp index 4b56b37..0e59b11 100644 --- a/lib/Rewrite/Frontend/RewriteModernObjC.cpp +++ b/lib/Rewrite/Frontend/RewriteModernObjC.cpp @@ -12,20 +12,23 @@ //===----------------------------------------------------------------------===// #include "clang/Rewrite/Frontend/ASTConsumers.h" -#include "clang/Rewrite/Core/Rewriter.h" #include "clang/AST/AST.h" #include "clang/AST/ASTConsumer.h" +#include "clang/AST/Attr.h" #include "clang/AST/ParentMap.h" -#include "clang/Basic/SourceManager.h" -#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/CharInfo.h" #include "clang/Basic/Diagnostic.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Basic/TargetInfo.h" #include "clang/Lex/Lexer.h" +#include "clang/Rewrite/Core/Rewriter.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/OwningPtr.h" -#include "llvm/ADT/DenseSet.h" using namespace clang; using llvm::utostr; @@ -115,7 +118,7 @@ namespace { SmallVector<ObjCInterfaceDecl*, 8> DefinedNonLazyClasses; /// DefinedNonLazyCategories - List of defined "non-lazy" categories. - llvm::SmallVector<ObjCCategoryDecl*, 8> DefinedNonLazyCategories; + SmallVector<ObjCCategoryDecl *, 8> DefinedNonLazyCategories; SmallVector<Stmt *, 32> Stmts; SmallVector<int, 8> ObjCBcLabelNo; @@ -131,6 +134,7 @@ namespace { SmallVector<DeclRefExpr *, 32> BlockDeclRefs; + // Block related declarations. SmallVector<ValueDecl *, 8> BlockByCopyDecls; llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDeclsPtrSet; @@ -144,6 +148,14 @@ namespace { llvm::DenseMap<ObjCInterfaceDecl *, llvm::SmallPtrSet<ObjCIvarDecl *, 8> > ReferencedIvars; + // ivar bitfield grouping containers + llvm::DenseSet<const ObjCInterfaceDecl *> ObjCInterefaceHasBitfieldGroups; + llvm::DenseMap<const ObjCIvarDecl* , unsigned> IvarGroupNumber; + // This container maps an <class, group number for ivar> tuple to the type + // of the struct where the bitfield belongs. + llvm::DenseMap<std::pair<const ObjCInterfaceDecl*, unsigned>, QualType> GroupRecordType; + SmallVector<FunctionDecl*, 32> FunctionDefinitionsSeen; + // This maps an original source AST to it's rewritten form. This allows // us to avoid rewriting the same node twice (which is very uncommon). // This is needed to support some of the exotic property rewriting. @@ -152,6 +164,7 @@ namespace { // Needed for header files being rewritten bool IsHeader; bool SilenceRewriteMacroWarning; + bool GenerateLineInfo; bool objc_impl_method; bool DisableReplaceStmt; @@ -193,6 +206,18 @@ namespace { } } + if (FunctionDecl *FDecl = dyn_cast<FunctionDecl>(*I)) { + // Under modern abi, we cannot translate body of the function + // yet until all class extensions and its implementation is seen. + // This is because they may introduce new bitfields which must go + // into their grouping struct. + if (FDecl->isThisDeclarationADefinition() && + // Not c functions defined inside an objc container. + !FDecl->isTopLevelDeclInObjCContainer()) { + FunctionDefinitionsSeen.push_back(FDecl); + break; + } + } HandleTopLevelSingleDecl(*I); } return true; @@ -201,7 +226,7 @@ namespace { void HandleDeclInMainFile(Decl *D); RewriteModernObjC(std::string inFile, raw_ostream *OS, DiagnosticsEngine &D, const LangOptions &LOpts, - bool silenceMacroWarn); + bool silenceMacroWarn, bool LineInfo); ~RewriteModernObjC() {} @@ -282,7 +307,7 @@ namespace { void ConvertSourceLocationToLineDirective(SourceLocation Loc, std::string &LineString); void RewriteForwardClassDecl(DeclGroupRef D); - void RewriteForwardClassDecl(const llvm::SmallVector<Decl*, 8> &DG); + void RewriteForwardClassDecl(const SmallVector<Decl *, 8> &DG); void RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl, const std::string &typedefString); void RewriteImplementations(); @@ -300,7 +325,7 @@ namespace { void RewriteCategoryDecl(ObjCCategoryDecl *Dcl); void RewriteProtocolDecl(ObjCProtocolDecl *Dcl); void RewriteForwardProtocolDecl(DeclGroupRef D); - void RewriteForwardProtocolDecl(const llvm::SmallVector<Decl*, 8> &DG); + void RewriteForwardProtocolDecl(const SmallVector<Decl *, 8> &DG); void RewriteMethodDeclaration(ObjCMethodDecl *Method); void RewriteProperty(ObjCPropertyDecl *prop); void RewriteFunctionDecl(FunctionDecl *FD); @@ -338,6 +363,20 @@ namespace { void RewriteImplicitCastObjCExpr(CastExpr *IE); void RewriteLinkageSpec(LinkageSpecDecl *LSD); + // Computes ivar bitfield group no. + unsigned ObjCIvarBitfieldGroupNo(ObjCIvarDecl *IV); + // Names field decl. for ivar bitfield group. + void ObjCIvarBitfieldGroupDecl(ObjCIvarDecl *IV, std::string &Result); + // Names struct type for ivar bitfield group. + void ObjCIvarBitfieldGroupType(ObjCIvarDecl *IV, std::string &Result); + // Names symbol for ivar bitfield group field offset. + void ObjCIvarBitfieldGroupOffset(ObjCIvarDecl *IV, std::string &Result); + // Given an ivar bitfield, it builds (or finds) its group record type. + QualType GetGroupRecordTypeForObjCIvarBitfield(ObjCIvarDecl *IV); + QualType SynthesizeBitfieldGroupStructType( + ObjCIvarDecl *IV, + SmallVectorImpl<ObjCIvarDecl *> &IVars); + // Block rewriting. void RewriteBlocksInFunctionProtoType(QualType funcType, NamedDecl *D); @@ -533,14 +572,13 @@ namespace { } QualType getSimpleFunctionType(QualType result, - const QualType *args, - unsigned numArgs, + ArrayRef<QualType> args, bool variadic = false) { if (result == Context->getObjCInstanceType()) result = Context->getObjCIdType(); FunctionProtoType::ExtProtoInfo fpi; fpi.Variadic = variadic; - return Context->getFunctionType(result, args, numArgs, fpi); + return Context->getFunctionType(result, args, fpi); } // Helper function: create a CStyleCastExpr with trivial type source info. @@ -596,9 +634,10 @@ static bool IsHeaderFile(const std::string &Filename) { RewriteModernObjC::RewriteModernObjC(std::string inFile, raw_ostream* OS, DiagnosticsEngine &D, const LangOptions &LOpts, - bool silenceMacroWarn) + bool silenceMacroWarn, + bool LineInfo) : Diags(D), LangOpts(LOpts), InFileName(inFile), OutFile(OS), - SilenceRewriteMacroWarning(silenceMacroWarn) { + SilenceRewriteMacroWarning(silenceMacroWarn), GenerateLineInfo(LineInfo) { IsHeader = IsHeaderFile(inFile); RewriteFailedDiag = Diags.getCustomDiagID(DiagnosticsEngine::Warning, "rewriting sub-expression within a macro (may not be correct)"); @@ -617,8 +656,10 @@ ASTConsumer *clang::CreateModernObjCRewriter(const std::string& InFile, raw_ostream* OS, DiagnosticsEngine &Diags, const LangOptions &LOpts, - bool SilenceRewriteMacroWarning) { - return new RewriteModernObjC(InFile, OS, Diags, LOpts, SilenceRewriteMacroWarning); + bool SilenceRewriteMacroWarning, + bool LineInfo) { + return new RewriteModernObjC(InFile, OS, Diags, LOpts, + SilenceRewriteMacroWarning, LineInfo); } void RewriteModernObjC::InitializeCommon(ASTContext &context) { @@ -798,11 +839,16 @@ RewriteModernObjC::getIvarAccessString(ObjCIvarDecl *D) { // Build name of symbol holding ivar offset. std::string IvarOffsetName; - WriteInternalIvarName(ClassDecl, D, IvarOffsetName); + if (D->isBitField()) + ObjCIvarBitfieldGroupOffset(D, IvarOffsetName); + else + WriteInternalIvarName(ClassDecl, D, IvarOffsetName); std::string S = "(*("; QualType IvarT = D->getType(); + if (D->isBitField()) + IvarT = GetGroupRecordTypeForObjCIvarBitfield(D); if (!isa<TypedefType>(IvarT) && IvarT->isRecordType()) { RecordDecl *RD = IvarT->getAs<RecordType>()->getDecl(); @@ -850,6 +896,10 @@ RewriteModernObjC::getIvarAccessString(ObjCIvarDecl *D) { S += "((char *)self + "; S += IvarOffsetName; S += "))"; + if (D->isBitField()) { + S += "."; + S += D->getNameAsString(); + } ReferencedIvars[const_cast<ObjCInterfaceDecl *>(ClassDecl)].insert(D); return S; } @@ -889,9 +939,8 @@ void RewriteModernObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID, // Generate the 'getter' function. ObjCPropertyDecl *PD = PID->getPropertyDecl(); ObjCIvarDecl *OID = PID->getPropertyIvarDecl(); + assert(IMD && OID && "Synthesized ivars must be attached to @implementation"); - if (!OID) - return; unsigned Attributes = PD->getPropertyAttributes(); if (mustSynthesizeSetterGetterMethod(IMD, PD, true /*getter*/)) { bool GenGetProperty = !(Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) && @@ -993,7 +1042,7 @@ void RewriteModernObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID, static void RewriteOneForwardClassDecl(ObjCInterfaceDecl *ForwardDecl, std::string &typedefString) { - typedefString += "#ifndef _REWRITER_typedef_"; + typedefString += "\n#ifndef _REWRITER_typedef_"; typedefString += ForwardDecl->getNameAsString(); typedefString += "\n"; typedefString += "#define _REWRITER_typedef_"; @@ -1026,7 +1075,7 @@ void RewriteModernObjC::RewriteForwardClassDecl(DeclGroupRef D) { // as a comment. typedefString += "// @class "; typedefString += ForwardDecl->getNameAsString(); - typedefString += ";\n"; + typedefString += ";"; } RewriteOneForwardClassDecl(ForwardDecl, typedefString); } @@ -1035,14 +1084,14 @@ void RewriteModernObjC::RewriteForwardClassDecl(DeclGroupRef D) { } void RewriteModernObjC::RewriteForwardClassDecl( - const llvm::SmallVector<Decl*, 8> &D) { + const SmallVector<Decl *, 8> &D) { std::string typedefString; for (unsigned i = 0; i < D.size(); i++) { ObjCInterfaceDecl *ForwardDecl = cast<ObjCInterfaceDecl>(D[i]); if (i == 0) { typedefString += "// @class "; typedefString += ForwardDecl->getNameAsString(); - typedefString += ";\n"; + typedefString += ";"; } RewriteOneForwardClassDecl(ForwardDecl, typedefString); } @@ -1100,7 +1149,7 @@ void RewriteModernObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) { // Lastly, comment out the @end. ReplaceText(CatDecl->getAtEndRange().getBegin(), - strlen("@end"), "/* @end */"); + strlen("@end"), "/* @end */\n"); } void RewriteModernObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) { @@ -1125,7 +1174,7 @@ void RewriteModernObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) { // Lastly, comment out the @end. SourceLocation LocEnd = PDecl->getAtEndRange().getBegin(); - ReplaceText(LocEnd, strlen("@end"), "/* @end */"); + ReplaceText(LocEnd, strlen("@end"), "/* @end */\n"); // Must comment out @optional/@required const char *startBuf = SM->getCharacterData(LocStart); @@ -1153,7 +1202,7 @@ void RewriteModernObjC::RewriteForwardProtocolDecl(DeclGroupRef D) { } void -RewriteModernObjC::RewriteForwardProtocolDecl(const llvm::SmallVector<Decl*, 8> &DG) { +RewriteModernObjC::RewriteForwardProtocolDecl(const SmallVector<Decl *, 8> &DG) { SourceLocation LocStart = DG[0]->getLocStart(); if (LocStart.isInvalid()) llvm_unreachable("Invalid SourceLocation"); @@ -1393,7 +1442,7 @@ void RewriteModernObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) { // Lastly, comment out the @end. ReplaceText(ClassDecl->getAtEndRange().getBegin(), strlen("@end"), - "/* @end */"); + "/* @end */\n"); } } @@ -1608,7 +1657,7 @@ Stmt *RewriteModernObjC::RewriteBreakStmt(BreakStmt *S) { void RewriteModernObjC::ConvertSourceLocationToLineDirective( SourceLocation Loc, std::string &LineString) { - if (Loc.isFileID()) { + if (Loc.isFileID() && GenerateLineInfo) { LineString += "\n#line "; PresumedLoc PLoc = SM->getPresumedLoc(Loc); LineString += utostr(PLoc.getLine()); @@ -2042,7 +2091,9 @@ Stmt *RewriteModernObjC::RewriteObjCThrowStmt(ObjCAtThrowStmt *S) { assert((*wBuf == 'w') && "@throw: can't find 'w'"); ReplaceText(startLoc, wBuf-startBuf+1, buf); - const char *semiBuf = strchr(startBuf, ';'); + SourceLocation endLoc = S->getLocEnd(); + const char *endBuf = SM->getCharacterData(endLoc); + const char *semiBuf = strchr(endBuf, ';'); assert((*semiBuf == ';') && "@throw: can't find ';'"); SourceLocation semiLoc = startLoc.getLocWithOffset(semiBuf-startBuf); if (S->getThrowExpr()) @@ -2208,6 +2259,10 @@ void RewriteModernObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) { Loc = FD->getLocation(); Type = FD->getType(); } + else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(Dcl)) { + Loc = TD->getLocation(); + Type = TD->getUnderlyingType(); + } else return; @@ -2305,13 +2360,12 @@ void RewriteModernObjC::SynthSelGetUidFunctionDecl() { SmallVector<QualType, 16> ArgTys; ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst())); QualType getFuncType = - getSimpleFunctionType(Context->getObjCSelType(), &ArgTys[0], ArgTys.size()); + getSimpleFunctionType(Context->getObjCSelType(), ArgTys); SelGetUidFunctionDecl = FunctionDecl::Create(*Context, TUDecl, - SourceLocation(), - SourceLocation(), - SelGetUidIdent, getFuncType, 0, - SC_Extern, - SC_None, false); + SourceLocation(), + SourceLocation(), + SelGetUidIdent, getFuncType, 0, + SC_Extern); } void RewriteModernObjC::RewriteFunctionDecl(FunctionDecl *FD) { @@ -2404,13 +2458,12 @@ void RewriteModernObjC::SynthSuperContructorFunctionDecl() { ArgTys.push_back(argT); ArgTys.push_back(argT); QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), - &ArgTys[0], ArgTys.size()); + ArgTys); SuperContructorFunctionDecl = FunctionDecl::Create(*Context, TUDecl, - SourceLocation(), - SourceLocation(), - msgSendIdent, msgSendType, 0, - SC_Extern, - SC_None, false); + SourceLocation(), + SourceLocation(), + msgSendIdent, msgSendType, + 0, SC_Extern); } // SynthMsgSendFunctionDecl - id objc_msgSend(id self, SEL op, ...); @@ -2424,14 +2477,12 @@ void RewriteModernObjC::SynthMsgSendFunctionDecl() { assert(!argT.isNull() && "Can't find 'SEL' type"); ArgTys.push_back(argT); QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), - &ArgTys[0], ArgTys.size(), - true /*isVariadic*/); + ArgTys, /*isVariadic=*/true); MsgSendFunctionDecl = FunctionDecl::Create(*Context, TUDecl, - SourceLocation(), - SourceLocation(), - msgSendIdent, msgSendType, 0, - SC_Extern, - SC_None, false); + SourceLocation(), + SourceLocation(), + msgSendIdent, msgSendType, 0, + SC_Extern); } // SynthMsgSendSuperFunctionDecl - id objc_msgSendSuper(void); @@ -2440,14 +2491,12 @@ void RewriteModernObjC::SynthMsgSendSuperFunctionDecl() { SmallVector<QualType, 2> ArgTys; ArgTys.push_back(Context->VoidTy); QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), - &ArgTys[0], 1, - true /*isVariadic*/); + ArgTys, /*isVariadic=*/true); MsgSendSuperFunctionDecl = FunctionDecl::Create(*Context, TUDecl, - SourceLocation(), - SourceLocation(), - msgSendIdent, msgSendType, 0, - SC_Extern, - SC_None, false); + SourceLocation(), + SourceLocation(), + msgSendIdent, msgSendType, 0, + SC_Extern); } // SynthMsgSendStretFunctionDecl - id objc_msgSend_stret(id self, SEL op, ...); @@ -2461,14 +2510,12 @@ void RewriteModernObjC::SynthMsgSendStretFunctionDecl() { assert(!argT.isNull() && "Can't find 'SEL' type"); ArgTys.push_back(argT); QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), - &ArgTys[0], ArgTys.size(), - true /*isVariadic*/); + ArgTys, /*isVariadic=*/true); MsgSendStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, - SourceLocation(), - SourceLocation(), - msgSendIdent, msgSendType, 0, - SC_Extern, - SC_None, false); + SourceLocation(), + SourceLocation(), + msgSendIdent, msgSendType, 0, + SC_Extern); } // SynthMsgSendSuperStretFunctionDecl - @@ -2479,14 +2526,13 @@ void RewriteModernObjC::SynthMsgSendSuperStretFunctionDecl() { SmallVector<QualType, 2> ArgTys; ArgTys.push_back(Context->VoidTy); QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), - &ArgTys[0], 1, - true /*isVariadic*/); + ArgTys, /*isVariadic=*/true); MsgSendSuperStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), SourceLocation(), - msgSendIdent, msgSendType, 0, - SC_Extern, - SC_None, false); + msgSendIdent, + msgSendType, 0, + SC_Extern); } // SynthMsgSendFpretFunctionDecl - double objc_msgSend_fpret(id self, SEL op, ...); @@ -2500,14 +2546,12 @@ void RewriteModernObjC::SynthMsgSendFpretFunctionDecl() { assert(!argT.isNull() && "Can't find 'SEL' type"); ArgTys.push_back(argT); QualType msgSendType = getSimpleFunctionType(Context->DoubleTy, - &ArgTys[0], ArgTys.size(), - true /*isVariadic*/); + ArgTys, /*isVariadic=*/true); MsgSendFpretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, - SourceLocation(), - SourceLocation(), - msgSendIdent, msgSendType, 0, - SC_Extern, - SC_None, false); + SourceLocation(), + SourceLocation(), + msgSendIdent, msgSendType, 0, + SC_Extern); } // SynthGetClassFunctionDecl - Class objc_getClass(const char *name); @@ -2516,13 +2560,12 @@ void RewriteModernObjC::SynthGetClassFunctionDecl() { SmallVector<QualType, 16> ArgTys; ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst())); QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(), - &ArgTys[0], ArgTys.size()); + ArgTys); GetClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl, - SourceLocation(), - SourceLocation(), - getClassIdent, getClassType, 0, - SC_Extern, - SC_None, false); + SourceLocation(), + SourceLocation(), + getClassIdent, getClassType, 0, + SC_Extern); } // SynthGetSuperClassFunctionDecl - Class class_getSuperclass(Class cls); @@ -2532,15 +2575,13 @@ void RewriteModernObjC::SynthGetSuperClassFunctionDecl() { SmallVector<QualType, 16> ArgTys; ArgTys.push_back(Context->getObjCClassType()); QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(), - &ArgTys[0], ArgTys.size()); + ArgTys); GetSuperClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), SourceLocation(), getSuperClassIdent, getClassType, 0, - SC_Extern, - SC_None, - false); + SC_Extern); } // SynthGetMetaClassFunctionDecl - Class objc_getMetaClass(const char *name); @@ -2549,13 +2590,12 @@ void RewriteModernObjC::SynthGetMetaClassFunctionDecl() { SmallVector<QualType, 16> ArgTys; ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst())); QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(), - &ArgTys[0], ArgTys.size()); + ArgTys); GetMetaClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl, - SourceLocation(), - SourceLocation(), - getClassIdent, getClassType, 0, - SC_Extern, - SC_None, false); + SourceLocation(), + SourceLocation(), + getClassIdent, getClassType, + 0, SC_Extern); } Stmt *RewriteModernObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) { @@ -2568,7 +2608,7 @@ Stmt *RewriteModernObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) { for (i=0; i < tmpName.length(); i++) { char c = tmpName.at(i); // replace any non alphanumeric characters with '_'. - if (!isalpha(c) && (c < '0' || c > '9')) + if (!isAlphanumeric(c)) tmpName[i] = '_'; } S += tmpName; @@ -2588,7 +2628,7 @@ Stmt *RewriteModernObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) { VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(), SourceLocation(), &Context->Idents.get(S), - strType, 0, SC_Static, SC_None); + strType, 0, SC_Static); DeclRefExpr *DRE = new (Context) DeclRefExpr(NewVD, false, strType, VK_LValue, SourceLocation()); Expr *Unop = new (Context) UnaryOperator(DRE, UO_AddrOf, @@ -2697,8 +2737,7 @@ Stmt *RewriteModernObjC::RewriteObjCBoxedExpr(ObjCBoxedExpr *Exp) { // Now do the "normal" pointer to function cast. QualType castType = - getSimpleFunctionType(returnType, &ArgTypes[0], ArgTypes.size(), - BoxingMethod->isVariadic()); + getSimpleFunctionType(returnType, ArgTypes, BoxingMethod->isVariadic()); castType = Context->getPointerType(castType); cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast, cast); @@ -2731,7 +2770,7 @@ Stmt *RewriteModernObjC::RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp) { // Build the expression: __NSContainer_literal(int, ...).arr QualType IntQT = Context->IntTy; QualType NSArrayFType = - getSimpleFunctionType(Context->VoidTy, &IntQT, 1, true); + getSimpleFunctionType(Context->VoidTy, IntQT, true); std::string NSArrayFName("__NSContainer_literal"); FunctionDecl *NSArrayFD = SynthBlockInitFunctionDecl(NSArrayFName); DeclRefExpr *NSArrayDRE = @@ -2835,8 +2874,7 @@ Stmt *RewriteModernObjC::RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp) { // Now do the "normal" pointer to function cast. QualType castType = - getSimpleFunctionType(returnType, &ArgTypes[0], ArgTypes.size(), - ArrayMethod->isVariadic()); + getSimpleFunctionType(returnType, ArgTypes, ArrayMethod->isVariadic()); castType = Context->getPointerType(castType); cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast, cast); @@ -2869,7 +2907,7 @@ Stmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral // Build the expression: __NSContainer_literal(int, ...).arr QualType IntQT = Context->IntTy; QualType NSDictFType = - getSimpleFunctionType(Context->VoidTy, &IntQT, 1, true); + getSimpleFunctionType(Context->VoidTy, IntQT, true); std::string NSDictFName("__NSContainer_literal"); FunctionDecl *NSDictFD = SynthBlockInitFunctionDecl(NSDictFName); DeclRefExpr *NSDictDRE = @@ -3009,8 +3047,7 @@ Stmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral // Now do the "normal" pointer to function cast. QualType castType = - getSimpleFunctionType(returnType, &ArgTypes[0], ArgTypes.size(), - DictMethod->isVariadic()); + getSimpleFunctionType(returnType, ArgTypes, DictMethod->isVariadic()); castType = Context->getPointerType(castType); cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast, cast); @@ -3102,7 +3139,7 @@ static SourceLocation getFunctionSourceLocation (RewriteModernObjC &R, if (!LSD->getRBraceLoc().isValid()) return LSD->getExternLoc(); } - if (FD->getStorageClassAsWritten() != SC_None) + if (FD->getStorageClass() != SC_None) R.RewriteBlockLiteralFunctionDecl(FD); return FD->getTypeSpecStartLoc(); } @@ -3111,7 +3148,7 @@ void RewriteModernObjC::RewriteLineDirective(const Decl *D) { SourceLocation Location = D->getLocation(); - if (Location.isFileID()) { + if (Location.isFileID() && GenerateLineInfo) { std::string LineString("\n#line "); PresumedLoc PLoc = SM->getPresumedLoc(Location); LineString += utostr(PLoc.getLine()); @@ -3152,8 +3189,9 @@ Expr *RewriteModernObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFla SmallVectorImpl<Expr*> &MsgExprs, ObjCMethodDecl *Method) { // Now do the "normal" pointer to function cast. - QualType castType = getSimpleFunctionType(returnType, &ArgTypes[0], ArgTypes.size(), - Method ? Method->isVariadic() : false); + QualType castType = getSimpleFunctionType(returnType, ArgTypes, + Method ? Method->isVariadic() + : false); castType = Context->getPointerType(castType); // build type for containing the objc_msgSend_stret object. @@ -3211,8 +3249,8 @@ Expr *RewriteModernObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFla // AST for __Stretn(receiver, args).s; IdentifierInfo *ID = &Context->Idents.get(name); FunctionDecl *FD = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), - SourceLocation(), ID, castType, 0, SC_Extern, - SC_None, false, false); + SourceLocation(), ID, castType, 0, + SC_Extern, false, false); DeclRefExpr *DRE = new (Context) DeclRefExpr(FD, false, castType, VK_RValue, SourceLocation()); CallExpr *STCE = new (Context) CallExpr(*Context, DRE, MsgExprs, @@ -3592,10 +3630,10 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp, CK_BitCast, DRE); // Now do the "normal" pointer to function cast. + // If we don't have a method decl, force a variadic cast. + const ObjCMethodDecl *MD = Exp->getMethodDecl(); QualType castType = - getSimpleFunctionType(returnType, &ArgTypes[0], ArgTypes.size(), - // If we don't have a method decl, force a variadic cast. - Exp->getMethodDecl() ? Exp->getMethodDecl()->isVariadic() : true); + getSimpleFunctionType(returnType, ArgTypes, MD ? MD->isVariadic() : true); castType = Context->getPointerType(castType); cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast, cast); @@ -3685,7 +3723,7 @@ Stmt *RewriteModernObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) { IdentifierInfo *ID = &Context->Idents.get(Name); VarDecl *VD = VarDecl::Create(*Context, TUDecl, SourceLocation(), SourceLocation(), ID, getProtocolType(), 0, - SC_Extern, SC_None); + SC_Extern); DeclRefExpr *DRE = new (Context) DeclRefExpr(VD, false, getProtocolType(), VK_LValue, SourceLocation()); Expr *DerefExpr = new (Context) UnaryOperator(DRE, UO_AddrOf, @@ -3840,16 +3878,16 @@ void RewriteModernObjC::RewriteObjCFieldDecl(FieldDecl *fieldDecl, Result += " : "; Result += utostr(fieldDecl->getBitWidthValue(*Context)); } else if (EleboratedType && Type->isArrayType()) { - CanQualType CType = Context->getCanonicalType(Type); - while (isa<ArrayType>(CType)) { - if (const ConstantArrayType *CAT = Context->getAsConstantArrayType(CType)) { + const ArrayType *AT = Context->getAsArrayType(Type); + do { + if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) { Result += "["; llvm::APInt Dim = CAT->getSize(); Result += utostr(Dim.getZExtValue()); Result += "]"; } - CType = CType->getAs<ArrayType>()->getElementType(); - } + AT = Context->getAsArrayType(AT->getElementType()); + } while (AT); } Result += ";\n"; @@ -3890,6 +3928,126 @@ void RewriteModernObjC::RewriteLocallyDefinedNamedAggregates(FieldDecl *fieldDec } +unsigned RewriteModernObjC::ObjCIvarBitfieldGroupNo(ObjCIvarDecl *IV) { + const ObjCInterfaceDecl *CDecl = IV->getContainingInterface(); + if (ObjCInterefaceHasBitfieldGroups.count(CDecl)) { + return IvarGroupNumber[IV]; + } + unsigned GroupNo = 0; + SmallVector<const ObjCIvarDecl *, 8> IVars; + for (const ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin(); + IVD; IVD = IVD->getNextIvar()) + IVars.push_back(IVD); + + for (unsigned i = 0, e = IVars.size(); i < e; i++) + if (IVars[i]->isBitField()) { + IvarGroupNumber[IVars[i++]] = ++GroupNo; + while (i < e && IVars[i]->isBitField()) + IvarGroupNumber[IVars[i++]] = GroupNo; + if (i < e) + --i; + } + + ObjCInterefaceHasBitfieldGroups.insert(CDecl); + return IvarGroupNumber[IV]; +} + +QualType RewriteModernObjC::SynthesizeBitfieldGroupStructType( + ObjCIvarDecl *IV, + SmallVectorImpl<ObjCIvarDecl *> &IVars) { + std::string StructTagName; + ObjCIvarBitfieldGroupType(IV, StructTagName); + RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, + Context->getTranslationUnitDecl(), + SourceLocation(), SourceLocation(), + &Context->Idents.get(StructTagName)); + for (unsigned i=0, e = IVars.size(); i < e; i++) { + ObjCIvarDecl *Ivar = IVars[i]; + RD->addDecl(FieldDecl::Create(*Context, RD, SourceLocation(), SourceLocation(), + &Context->Idents.get(Ivar->getName()), + Ivar->getType(), + 0, /*Expr *BW */Ivar->getBitWidth(), false, + ICIS_NoInit)); + } + RD->completeDefinition(); + return Context->getTagDeclType(RD); +} + +QualType RewriteModernObjC::GetGroupRecordTypeForObjCIvarBitfield(ObjCIvarDecl *IV) { + const ObjCInterfaceDecl *CDecl = IV->getContainingInterface(); + unsigned GroupNo = ObjCIvarBitfieldGroupNo(IV); + std::pair<const ObjCInterfaceDecl*, unsigned> tuple = std::make_pair(CDecl, GroupNo); + if (GroupRecordType.count(tuple)) + return GroupRecordType[tuple]; + + SmallVector<ObjCIvarDecl *, 8> IVars; + for (const ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin(); + IVD; IVD = IVD->getNextIvar()) { + if (IVD->isBitField()) + IVars.push_back(const_cast<ObjCIvarDecl *>(IVD)); + else { + if (!IVars.empty()) { + unsigned GroupNo = ObjCIvarBitfieldGroupNo(IVars[0]); + // Generate the struct type for this group of bitfield ivars. + GroupRecordType[std::make_pair(CDecl, GroupNo)] = + SynthesizeBitfieldGroupStructType(IVars[0], IVars); + IVars.clear(); + } + } + } + if (!IVars.empty()) { + // Do the last one. + unsigned GroupNo = ObjCIvarBitfieldGroupNo(IVars[0]); + GroupRecordType[std::make_pair(CDecl, GroupNo)] = + SynthesizeBitfieldGroupStructType(IVars[0], IVars); + } + QualType RetQT = GroupRecordType[tuple]; + assert(!RetQT.isNull() && "GetGroupRecordTypeForObjCIvarBitfield struct type is NULL"); + + return RetQT; +} + +/// ObjCIvarBitfieldGroupDecl - Names field decl. for ivar bitfield group. +/// Name would be: classname__GRBF_n where n is the group number for this ivar. +void RewriteModernObjC::ObjCIvarBitfieldGroupDecl(ObjCIvarDecl *IV, + std::string &Result) { + const ObjCInterfaceDecl *CDecl = IV->getContainingInterface(); + Result += CDecl->getName(); + Result += "__GRBF_"; + unsigned GroupNo = ObjCIvarBitfieldGroupNo(IV); + Result += utostr(GroupNo); + return; +} + +/// ObjCIvarBitfieldGroupType - Names struct type for ivar bitfield group. +/// Name of the struct would be: classname__T_n where n is the group number for +/// this ivar. +void RewriteModernObjC::ObjCIvarBitfieldGroupType(ObjCIvarDecl *IV, + std::string &Result) { + const ObjCInterfaceDecl *CDecl = IV->getContainingInterface(); + Result += CDecl->getName(); + Result += "__T_"; + unsigned GroupNo = ObjCIvarBitfieldGroupNo(IV); + Result += utostr(GroupNo); + return; +} + +/// ObjCIvarBitfieldGroupOffset - Names symbol for ivar bitfield group field offset. +/// Name would be: OBJC_IVAR_$_classname__GRBF_n where n is the group number for +/// this ivar. +void RewriteModernObjC::ObjCIvarBitfieldGroupOffset(ObjCIvarDecl *IV, + std::string &Result) { + Result += "OBJC_IVAR_$_"; + ObjCIvarBitfieldGroupDecl(IV, Result); +} + +#define SKIP_BITFIELDS(IX, ENDIX, VEC) { \ + while ((IX < ENDIX) && VEC[IX]->isBitField()) \ + ++IX; \ + if (IX < ENDIX) \ + --IX; \ +} + /// RewriteObjCInternalStruct - Rewrite one internal struct corresponding to /// an objective-c class with ivars. void RewriteModernObjC::RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl, @@ -3923,7 +4081,19 @@ void RewriteModernObjC::RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl, // struct/unions in objective-c classes. for (unsigned i = 0, e = IVars.size(); i < e; i++) RewriteLocallyDefinedNamedAggregates(IVars[i], Result); - + + // Insert named structs which are syntheized to group ivar bitfields + // to outer scope as well. + for (unsigned i = 0, e = IVars.size(); i < e; i++) + if (IVars[i]->isBitField()) { + ObjCIvarDecl *IV = IVars[i]; + QualType QT = GetGroupRecordTypeForObjCIvarBitfield(IV); + RewriteObjCFieldDeclType(QT, Result); + Result += ";"; + // skip over ivar bitfields in this group. + SKIP_BITFIELDS(i , e, IVars); + } + Result += "\nstruct "; Result += CDecl->getNameAsString(); Result += "_IMPL {\n"; @@ -3934,8 +4104,18 @@ void RewriteModernObjC::RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl, Result += "_IVARS;\n"; } - for (unsigned i = 0, e = IVars.size(); i < e; i++) - RewriteObjCFieldDecl(IVars[i], Result); + for (unsigned i = 0, e = IVars.size(); i < e; i++) { + if (IVars[i]->isBitField()) { + ObjCIvarDecl *IV = IVars[i]; + Result += "\tstruct "; + ObjCIvarBitfieldGroupType(IV, Result); Result += " "; + ObjCIvarBitfieldGroupDecl(IV, Result); Result += ";\n"; + // skip over ivar bitfields in this group. + SKIP_BITFIELDS(i , e, IVars); + } + else + RewriteObjCFieldDecl(IVars[i], Result); + } Result += "};\n"; endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts); @@ -3954,9 +4134,18 @@ void RewriteModernObjC::RewriteIvarOffsetSymbols(ObjCInterfaceDecl *CDecl, llvm::SmallPtrSet<ObjCIvarDecl *, 8> Ivars = ReferencedIvars[CDecl]; if (Ivars.empty()) return; + + llvm::DenseSet<std::pair<const ObjCInterfaceDecl*, unsigned> > GroupSymbolOutput; for (llvm::SmallPtrSet<ObjCIvarDecl *, 8>::iterator i = Ivars.begin(), e = Ivars.end(); i != e; i++) { ObjCIvarDecl *IvarDecl = (*i); + const ObjCInterfaceDecl *IDecl = IvarDecl->getContainingInterface(); + unsigned GroupNo = 0; + if (IvarDecl->isBitField()) { + GroupNo = ObjCIvarBitfieldGroupNo(IvarDecl); + if (GroupSymbolOutput.count(std::make_pair(IDecl, GroupNo))) + continue; + } Result += "\n"; if (LangOpts.MicrosoftExt) Result += "__declspec(allocate(\".objc_ivar$B\")) "; @@ -3967,7 +4156,12 @@ void RewriteModernObjC::RewriteIvarOffsetSymbols(ObjCInterfaceDecl *CDecl, Result += "__declspec(dllimport) "; Result += "unsigned long "; - WriteInternalIvarName(CDecl, IvarDecl, Result); + if (IvarDecl->isBitField()) { + ObjCIvarBitfieldGroupOffset(IvarDecl, Result); + GroupSymbolOutput.insert(std::make_pair(IDecl, GroupNo)); + } + else + WriteInternalIvarName(CDecl, IvarDecl, Result); Result += ";"; } } @@ -4545,7 +4739,7 @@ QualType RewriteModernObjC::convertFunctionTypeOfBlocks(const FunctionType *FT) } QualType FuncType; if (modified) - FuncType = getSimpleFunctionType(Res, &ArgTypes[0], ArgTypes.size()); + FuncType = getSimpleFunctionType(Res, ArgTypes); else FuncType = QualType(FT, 0); return FuncType; } @@ -4612,8 +4806,7 @@ Stmt *RewriteModernObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp } } // Now do the pointer to function cast. - QualType PtrToFuncCastType - = getSimpleFunctionType(Exp->getType(), &ArgTypes[0], ArgTypes.size()); + QualType PtrToFuncCastType = getSimpleFunctionType(Exp->getType(), ArgTypes); PtrToFuncCastType = Context->getPointerType(PtrToFuncCastType); @@ -5053,7 +5246,7 @@ void RewriteModernObjC::RewriteByRefVar(VarDecl *ND, bool firstDecl, // Add void *__Block_byref_id_object_copy; // void *__Block_byref_id_object_dispose; if needed. QualType Ty = ND->getType(); - bool HasCopyAndDispose = Context->BlockRequiresCopying(Ty); + bool HasCopyAndDispose = Context->BlockRequiresCopying(Ty, ND); if (HasCopyAndDispose) { ByrefType += " void (*__Block_byref_id_object_copy)(void*, void*);\n"; ByrefType += " void (*__Block_byref_id_object_dispose)(void*);\n"; @@ -5089,7 +5282,7 @@ void RewriteModernObjC::RewriteByRefVar(VarDecl *ND, bool firstDecl, flag |= BLOCK_FIELD_IS_OBJECT; std::string HF = SynthesizeByrefCopyDestroyHelper(ND, flag); if (!HF.empty()) - InsertText(FunLocStart, HF); + Preamble += HF; } // struct __Block_byref_ND ND = @@ -5210,7 +5403,7 @@ FunctionDecl *RewriteModernObjC::SynthBlockInitFunctionDecl(StringRef name) { QualType FType = Context->getFunctionNoProtoType(Context->VoidPtrTy); return FunctionDecl::Create(*Context, TUDecl, SourceLocation(), SourceLocation(), ID, FType, 0, SC_Extern, - SC_None, false, false); + false, false); } Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp, @@ -5311,7 +5504,7 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp, SourceLocation(), SourceLocation(), &Context->Idents.get(DescData.c_str()), Context->VoidPtrTy, 0, - SC_Static, SC_None); + SC_Static); UnaryOperator *DescRefExpr = new (Context) UnaryOperator(new (Context) DeclRefExpr(NewVD, false, Context->VoidPtrTy, @@ -5464,6 +5657,8 @@ Stmt *RewriteModernObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { } else if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) { return RewriteObjCIvarRefExpr(IvarRefExpr); } + else if (isa<OpaqueValueExpr>(S)) + S = cast<OpaqueValueExpr>(S)->getSourceExpr(); SourceRange OrigStmtRange = S->getSourceRange(); @@ -5805,6 +6000,8 @@ void RewriteModernObjC::HandleDeclInMainFile(Decl *D) { RewriteBlockPointerDecl(TD); else if (TD->getUnderlyingType()->isFunctionPointerType()) CheckFunctionPointerDecl(TD->getUnderlyingType(), TD); + else + RewriteObjCQualifiedInterfaceTypes(TD); } break; } @@ -5844,6 +6041,14 @@ void RewriteModernObjC::HandleTranslationUnit(ASTContext &C) { RewriteInclude(); + for (unsigned i = 0, e = FunctionDefinitionsSeen.size(); i < e; i++) { + // translation of function bodies were postponed untill all class and + // their extensions and implementations are seen. This is because, we + // cannot build grouping structs for bitfields untill they are all seen. + FunctionDecl *FDecl = FunctionDefinitionsSeen[i]; + HandleTopLevelSingleDecl(FDecl); + } + // Here's a great place to add any extra declarations that may be needed. // Write out meta data for each @protocol(<expr>). for (llvm::SmallPtrSet<ObjCProtocolDecl *,8>::iterator I = ProtocolExprDecls.begin(), @@ -5865,7 +6070,7 @@ void RewriteModernObjC::HandleTranslationUnit(ASTContext &C) { // private ivars. RewriteInterfaceDecl(CDecl); } - + // Get the buffer corresponding to MainFileID. If we haven't changed it, then // we are done. if (const RewriteBuffer *RewriteBuf = @@ -6060,19 +6265,16 @@ void RewriteModernObjC::Initialize(ASTContext &context) { /// ivar offset. void RewriteModernObjC::RewriteIvarOffsetComputation(ObjCIvarDecl *ivar, std::string &Result) { - if (ivar->isBitField()) { - // FIXME: The hack below doesn't work for bitfields. For now, we simply - // place all bitfields at offset 0. - Result += "0"; - } else { - Result += "__OFFSETOFIVAR__(struct "; - Result += ivar->getContainingInterface()->getNameAsString(); - if (LangOpts.MicrosoftExt) - Result += "_IMPL"; - Result += ", "; + Result += "__OFFSETOFIVAR__(struct "; + Result += ivar->getContainingInterface()->getNameAsString(); + if (LangOpts.MicrosoftExt) + Result += "_IMPL"; + Result += ", "; + if (ivar->isBitField()) + ObjCIvarBitfieldGroupDecl(ivar, Result); + else Result += ivar->getNameAsString(); - Result += ")"; - } + Result += ")"; } /// WriteModernMetadataDeclarations - Writes out metadata declarations for modern ABI. @@ -6749,21 +6951,41 @@ static void Write_IvarOffsetVar(RewriteModernObjC &RewriteObj, Result += "extern \"C\" unsigned long int "; else Result += "extern \"C\" __declspec(dllexport) unsigned long int "; - WriteInternalIvarName(CDecl, IvarDecl, Result); + if (Ivars[i]->isBitField()) + RewriteObj.ObjCIvarBitfieldGroupOffset(IvarDecl, Result); + else + WriteInternalIvarName(CDecl, IvarDecl, Result); Result += " __attribute__ ((used, section (\"__DATA,__objc_ivar\")))"; Result += " = "; RewriteObj.RewriteIvarOffsetComputation(IvarDecl, Result); Result += ";\n"; + if (Ivars[i]->isBitField()) { + // skip over rest of the ivar bitfields. + SKIP_BITFIELDS(i , e, Ivars); + } } } static void Write__ivar_list_t_initializer(RewriteModernObjC &RewriteObj, ASTContext *Context, std::string &Result, - ArrayRef<ObjCIvarDecl *> Ivars, + ArrayRef<ObjCIvarDecl *> OriginalIvars, StringRef VarName, ObjCInterfaceDecl *CDecl) { - if (Ivars.size() > 0) { - Write_IvarOffsetVar(RewriteObj, Context, Result, Ivars, CDecl); + if (OriginalIvars.size() > 0) { + Write_IvarOffsetVar(RewriteObj, Context, Result, OriginalIvars, CDecl); + SmallVector<ObjCIvarDecl *, 8> Ivars; + // strip off all but the first ivar bitfield from each group of ivars. + // Such ivars in the ivar list table will be replaced by their grouping struct + // 'ivar'. + for (unsigned i = 0, e = OriginalIvars.size(); i < e; i++) { + if (OriginalIvars[i]->isBitField()) { + Ivars.push_back(OriginalIvars[i]); + // skip over rest of the ivar bitfields. + SKIP_BITFIELDS(i , e, OriginalIvars); + } + else + Ivars.push_back(OriginalIvars[i]); + } Result += "\nstatic "; Write__ivar_list_t_TypeDecl(Result, Ivars.size()); @@ -6779,22 +7001,35 @@ static void Write__ivar_list_t_initializer(RewriteModernObjC &RewriteObj, else Result += "\t {"; Result += "(unsigned long int *)&"; - WriteInternalIvarName(CDecl, IvarDecl, Result); + if (Ivars[i]->isBitField()) + RewriteObj.ObjCIvarBitfieldGroupOffset(IvarDecl, Result); + else + WriteInternalIvarName(CDecl, IvarDecl, Result); Result += ", "; - Result += "\""; Result += IvarDecl->getName(); Result += "\", "; + Result += "\""; + if (Ivars[i]->isBitField()) + RewriteObj.ObjCIvarBitfieldGroupDecl(Ivars[i], Result); + else + Result += IvarDecl->getName(); + Result += "\", "; + + QualType IVQT = IvarDecl->getType(); + if (IvarDecl->isBitField()) + IVQT = RewriteObj.GetGroupRecordTypeForObjCIvarBitfield(IvarDecl); + std::string IvarTypeString, QuoteIvarTypeString; - Context->getObjCEncodingForType(IvarDecl->getType(), IvarTypeString, + Context->getObjCEncodingForType(IVQT, IvarTypeString, IvarDecl); RewriteObj.QuoteDoublequotes(IvarTypeString, QuoteIvarTypeString); Result += "\""; Result += QuoteIvarTypeString; Result += "\", "; // FIXME. this alignment represents the host alignment and need be changed to // represent the target alignment. - unsigned Align = Context->getTypeAlign(IvarDecl->getType())/8; + unsigned Align = Context->getTypeAlign(IVQT)/8; Align = llvm::Log2_32(Align); Result += llvm::utostr(Align); Result += ", "; - CharUnits Size = Context->getTypeSizeInChars(IvarDecl->getType()); + CharUnits Size = Context->getTypeSizeInChars(IVQT); Result += llvm::utostr(Size.getQuantity()); if (i == e-1) Result += "}}\n"; @@ -7306,11 +7541,8 @@ void RewriteModernObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl, WriteModernMetadataDeclarations(Context, Result); ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface(); // Find category declaration for this implementation. - ObjCCategoryDecl *CDecl=0; - for (CDecl = ClassDecl->getCategoryList(); CDecl; - CDecl = CDecl->getNextClassCategory()) - if (CDecl->getIdentifier() == IDecl->getIdentifier()) - break; + ObjCCategoryDecl *CDecl + = ClassDecl->FindCategoryDeclaration(IDecl->getIdentifier()); std::string FullCategoryName = ClassDecl->getNameAsString(); FullCategoryName += "_$_"; @@ -7522,7 +7754,10 @@ Stmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) { // Build name of symbol holding ivar offset. std::string IvarOffsetName; - WriteInternalIvarName(clsDeclared, D, IvarOffsetName); + if (D->isBitField()) + ObjCIvarBitfieldGroupOffset(D, IvarOffsetName); + else + WriteInternalIvarName(clsDeclared, D, IvarOffsetName); ReferencedIvars[clsDeclared].insert(D); @@ -7533,7 +7768,7 @@ Stmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) { BaseExpr); VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(), SourceLocation(), &Context->Idents.get(IvarOffsetName), - Context->UnsignedLongTy, 0, SC_Extern, SC_None); + Context->UnsignedLongTy, 0, SC_Extern); DeclRefExpr *DRE = new (Context) DeclRefExpr(NewVD, false, Context->UnsignedLongTy, VK_LValue, SourceLocation()); @@ -7546,6 +7781,8 @@ Stmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) { SourceLocation(), addExpr); QualType IvarT = D->getType(); + if (D->isBitField()) + IvarT = GetGroupRecordTypeForObjCIvarBitfield(D); if (!isa<TypedefType>(IvarT) && IvarT->isRecordType()) { RecordDecl *RD = IvarT->getAs<RecordType>()->getDecl(); @@ -7598,8 +7835,23 @@ Stmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) { PE = new (Context) ParenExpr(OldRange.getBegin(), OldRange.getEnd(), Exp); + + if (D->isBitField()) { + FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(), + SourceLocation(), + &Context->Idents.get(D->getNameAsString()), + D->getType(), 0, + /*BitWidth=*/D->getBitWidth(), + /*Mutable=*/true, + ICIS_NoInit); + MemberExpr *ME = new (Context) MemberExpr(PE, /*isArrow*/false, FD, SourceLocation(), + FD->getType(), VK_LValue, + OK_Ordinary); + Replacement = ME; - Replacement = PE; + } + else + Replacement = PE; } ReplaceStmtWithRange(IV, Replacement, OldRange); |