mirror of https://github.com/microsoft/clang.git
objective-C modern translator. Fix up the translated
metadata to handle ivar bitfields. This is wip. // rdar://13138459 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@174573 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
4a19052fe9
commit
cd3b036dbd
|
@ -133,6 +133,7 @@ namespace {
|
|||
|
||||
SmallVector<DeclRefExpr *, 32> BlockDeclRefs;
|
||||
|
||||
|
||||
// Block related declarations.
|
||||
SmallVector<ValueDecl *, 8> BlockByCopyDecls;
|
||||
llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDeclsPtrSet;
|
||||
|
@ -146,6 +147,13 @@ 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;
|
||||
|
||||
// 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.
|
||||
|
@ -340,6 +348,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);
|
||||
|
||||
|
@ -800,11 +822,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();
|
||||
|
@ -852,6 +879,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;
|
||||
}
|
||||
|
@ -3882,6 +3913,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,
|
||||
|
@ -3915,7 +4066,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";
|
||||
|
@ -3926,8 +4089,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);
|
||||
|
@ -3946,9 +4119,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\")) ";
|
||||
|
@ -3959,7 +4141,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 += ";";
|
||||
}
|
||||
}
|
||||
|
@ -6052,19 +6239,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.
|
||||
|
@ -6741,21 +6925,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());
|
||||
|
@ -6771,22 +6975,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";
|
||||
|
@ -7511,7 +7728,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);
|
||||
|
||||
|
@ -7535,6 +7755,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();
|
||||
|
@ -7587,8 +7809,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);
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fms-extensions -rewrite-objc %s -o %t-modern-rw.cpp
|
||||
// RUN: %clang_cc1 -fsyntax-only -Wno-address-of-temporary -D"Class=void*" -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-modern-rw.cpp
|
||||
// rdar://13138459
|
||||
|
||||
// -Did="void*" -DSEL="void *" -DClass="void*"
|
||||
@interface NSMutableArray {
|
||||
id isa;
|
||||
}
|
||||
@end
|
||||
|
||||
typedef unsigned char BOOL;
|
||||
typedef unsigned long NSUInteger;
|
||||
|
||||
__attribute__((visibility("hidden")))
|
||||
@interface __NSArrayM : NSMutableArray {
|
||||
NSUInteger _used;
|
||||
NSUInteger _doHardRetain:1;
|
||||
NSUInteger _doWeakAccess:1;
|
||||
#if __LP64__
|
||||
NSUInteger _size:62;
|
||||
#else
|
||||
NSUInteger _size:30;
|
||||
#endif
|
||||
NSUInteger _hasObjects:1;
|
||||
NSUInteger _hasStrongReferences:1;
|
||||
#if __LP64__
|
||||
NSUInteger _offset:62;
|
||||
#else
|
||||
NSUInteger _offset:30;
|
||||
#endif
|
||||
unsigned long _mutations;
|
||||
id *_list;
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
id __CFAllocateObject2();
|
||||
BOOL objc_collectingEnabled();
|
||||
|
||||
@implementation __NSArrayM
|
||||
+ (id)__new:(const id [])objects :(NSUInteger)count :(BOOL)hasObjects :(BOOL)hasStrong :(BOOL)transferRetain {
|
||||
__NSArrayM *newArray = (__NSArrayM *)__CFAllocateObject2();
|
||||
newArray->_size = count;
|
||||
newArray->_mutations = 1;
|
||||
newArray->_doHardRetain = (hasObjects && hasStrong);
|
||||
newArray->_doWeakAccess = (objc_collectingEnabled() && !hasStrong);
|
||||
newArray->_hasObjects = hasObjects;
|
||||
newArray->_hasStrongReferences = hasStrong;
|
||||
newArray->_list = 0;
|
||||
return *newArray->_list;
|
||||
}
|
||||
@end
|
|
@ -1,5 +1,6 @@
|
|||
// RUN: %clang_cc1 -E %s -o %t.mm
|
||||
// RUN: %clang_cc1 -x objective-c++ -fblocks -fms-extensions -rewrite-objc %t.mm -o - | FileCheck %s
|
||||
// rdar://13138459
|
||||
|
||||
@interface Foo {
|
||||
@private
|
||||
|
@ -13,11 +14,14 @@
|
|||
@implementation Foo
|
||||
@end
|
||||
|
||||
// CHECK: struct Foo__T_1 {
|
||||
// CHECK-NEXT: int : 1;
|
||||
// CHECK-NEXT: int third : 1;
|
||||
// CHECK-NEXT: int : 1;
|
||||
// CHECK-NEXT: int fifth : 1;
|
||||
// CHECK-NEXT: char : 0;
|
||||
// CHECK-NEXT: } ;
|
||||
// CHECK: struct Foo_IMPL {
|
||||
// CHECK-NEXT: int first;
|
||||
// CHECK-NEXT: int : 1;
|
||||
// CHECK-NEXT: int third : 1;
|
||||
// CHECK-NEXT: int : 1;
|
||||
// CHECK-NEXT: int fifth : 1;
|
||||
// CHECK-NEXT: char : 0;
|
||||
// CHECK-NEXT: int first;
|
||||
// CHECK-NEXT: struct Foo__T_1 Foo__GRBF_1;
|
||||
// CHECK-NEXT: };
|
||||
|
|
Loading…
Reference in New Issue