Support for IRGen of synthesize bitfield ivars in

objc-nonfragile-abi2 (radar 7824380).

llvm-svn: 111823
This commit is contained in:
Fariborz Jahanian 2010-08-23 18:51:39 +00:00
parent 99e9d6ffbf
commit bf9294fb65
8 changed files with 102 additions and 10 deletions

View File

@ -1269,6 +1269,10 @@ public:
/// that are common to binary operators (C99 6.3.1.8, C++ [expr]p9)
/// and returns the result type of that conversion.
QualType UsualArithmeticConversionsType(QualType lhs, QualType rhs);
void ResetObjCLayout(const ObjCContainerDecl *CD) {
ObjCLayouts[CD] = 0;
}
//===--------------------------------------------------------------------===//
// Integer Predicates
@ -1409,7 +1413,7 @@ private:
const ASTRecordLayout &getObjCLayout(const ObjCInterfaceDecl *D,
const ObjCImplementationDecl *Impl);
private:
/// \brief A set of deallocations that should be performed when the
/// ASTContext is destroyed.

View File

@ -919,6 +919,9 @@ class ObjCCategoryDecl : public ObjCContainerDecl {
/// FIXME: this should not be a singly-linked list. Move storage elsewhere.
ObjCCategoryDecl *NextClassCategory;
/// true of class extension has at least one bitfield ivar.
bool HasSynthBitfield : 1;
/// \brief The location of the '@' in '@interface'
SourceLocation AtLoc;
@ -929,8 +932,8 @@ class ObjCCategoryDecl : public ObjCContainerDecl {
SourceLocation ClassNameLoc, SourceLocation CategoryNameLoc,
IdentifierInfo *Id)
: ObjCContainerDecl(ObjCCategory, DC, ClassNameLoc, Id),
ClassInterface(0), NextClassCategory(0), AtLoc(AtLoc),
CategoryNameLoc(CategoryNameLoc) {
ClassInterface(0), NextClassCategory(0), HasSynthBitfield(false),
AtLoc(AtLoc), CategoryNameLoc(CategoryNameLoc) {
}
public:
@ -982,6 +985,9 @@ public:
bool IsClassExtension() const { return getIdentifier() == 0; }
const ObjCCategoryDecl *getNextClassExtension() const;
bool hasSynthBitfield() const { return HasSynthBitfield; }
void setHasSynthBitfield (bool val) { HasSynthBitfield = val; }
typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator;
ivar_iterator ivar_begin() const {
return ivar_iterator(decls_begin());
@ -1154,11 +1160,15 @@ class ObjCImplementationDecl : public ObjCImplDecl {
CXXBaseOrMemberInitializer **IvarInitializers;
unsigned NumIvarInitializers;
/// true of class extension has at least one bitfield ivar.
bool HasSynthBitfield : 1;
ObjCImplementationDecl(DeclContext *DC, SourceLocation L,
ObjCInterfaceDecl *classInterface,
ObjCInterfaceDecl *superDecl)
: ObjCImplDecl(ObjCImplementation, DC, L, classInterface),
SuperClass(superDecl), IvarInitializers(0), NumIvarInitializers(0) {}
SuperClass(superDecl), IvarInitializers(0), NumIvarInitializers(0),
HasSynthBitfield(false) {}
public:
static ObjCImplementationDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
@ -1196,6 +1206,9 @@ public:
void setIvarInitializers(ASTContext &C,
CXXBaseOrMemberInitializer ** initializers,
unsigned numInitializers);
bool hasSynthBitfield() const { return HasSynthBitfield; }
void setHasSynthBitfield (bool val) { HasSynthBitfield = val; }
/// getIdentifier - Get the identifier that names the class
/// interface associated with this implementation.

View File

@ -604,10 +604,17 @@ ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC,
// decl contexts, the previously built IvarList must be rebuilt.
ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(DC);
if (!ID) {
if (ObjCImplementationDecl *IM = dyn_cast<ObjCImplementationDecl>(DC))
if (ObjCImplementationDecl *IM = dyn_cast<ObjCImplementationDecl>(DC)) {
ID = IM->getClassInterface();
else
ID = (cast<ObjCCategoryDecl>(DC))->getClassInterface();
if (BW)
IM->setHasSynthBitfield(true);
}
else {
ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(DC);
ID = CD->getClassInterface();
if (BW)
CD->setHasSynthBitfield(true);
}
}
ID->setIvarList(0);
}

View File

@ -1940,9 +1940,16 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
// Forward declarations, no (immediate) code generation.
case Decl::ObjCClass:
case Decl::ObjCForwardProtocol:
case Decl::ObjCCategory:
case Decl::ObjCInterface:
break;
case Decl::ObjCCategory: {
ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D);
if (CD->IsClassExtension() && CD->hasSynthBitfield())
Context.ResetObjCLayout(CD->getClassInterface());
break;
}
case Decl::ObjCProtocol:
Runtime->GenerateProtocol(cast<ObjCProtocolDecl>(D));
@ -1956,6 +1963,8 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
case Decl::ObjCImplementation: {
ObjCImplementationDecl *OMD = cast<ObjCImplementationDecl>(D);
if (Features.ObjCNonFragileABI2 && OMD->hasSynthBitfield())
Context.ResetObjCLayout(OMD->getClassInterface());
EmitObjCPropertyImplementations(OMD);
EmitObjCIvarInitializations(OMD);
Runtime->GenerateClass(OMD);

View File

@ -6349,9 +6349,13 @@ Decl *Sema::ActOnIvar(Scope *S,
ObjCContainerDecl *EnclosingContext;
if (ObjCImplementationDecl *IMPDecl =
dyn_cast<ObjCImplementationDecl>(EnclosingDecl)) {
if (!LangOpts.ObjCNonFragileABI2) {
// Case of ivar declared in an implementation. Context is that of its class.
EnclosingContext = IMPDecl->getClassInterface();
assert(EnclosingContext && "Implementation has no class interface!");
EnclosingContext = IMPDecl->getClassInterface();
assert(EnclosingContext && "Implementation has no class interface!");
}
else
EnclosingContext = EnclosingDecl;
} else {
if (ObjCCategoryDecl *CDecl =
dyn_cast<ObjCCategoryDecl>(EnclosingDecl)) {

View File

@ -476,6 +476,7 @@ void ASTDeclReader::VisitObjCCategoryDecl(ObjCCategoryDecl *CD) {
CD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(),
*Reader.getContext());
CD->setNextClassCategory(cast_or_null<ObjCCategoryDecl>(Reader.GetDecl(Record[Idx++])));
CD->setHasSynthBitfield(Record[Idx++]);
CD->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
CD->setCategoryNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
@ -524,6 +525,7 @@ void ASTDeclReader::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
cast_or_null<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++])));
llvm::tie(D->IvarInitializers, D->NumIvarInitializers)
= Reader.ReadCXXBaseOrMemberInitializers(Cursor, Record, Idx);
D->setHasSynthBitfield(Record[Idx++]);
}

View File

@ -428,6 +428,7 @@ void ASTDeclWriter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
PL != PLEnd; ++PL)
Writer.AddSourceLocation(*PL, Record);
Writer.AddDeclRef(D->getNextClassCategory(), Record);
Record.push_back(D->hasSynthBitfield());
Writer.AddSourceLocation(D->getAtLoc(), Record);
Writer.AddSourceLocation(D->getCategoryNameLoc(), Record);
Code = serialization::DECL_OBJC_CATEGORY;
@ -473,6 +474,7 @@ void ASTDeclWriter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
Writer.AddDeclRef(D->getSuperClass(), Record);
Writer.AddCXXBaseOrMemberInitializers(D->IvarInitializers,
D->NumIvarInitializers, Record);
Record.push_back(D->hasSynthBitfield());
Code = serialization::DECL_OBJC_IMPLEMENTATION;
}

View File

@ -0,0 +1,51 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi2 -emit-llvm -o %t %s
// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi2 -emit-llvm -o %t %s
// rdar: // 7824380
@interface Super {
int ivar_super_a : 5;
}
@end
@interface A : Super {
@public
int ivar_a : 5;
}
@end
int f0(A *a) {
return a->ivar_a;
}
@interface A () {
@public
int ivar_ext_a : 5;
int ivar_ext_b : 5;
}@end
int f1(A *a) {
return a->ivar_ext_a + a->ivar_a;
}
@interface A () {
@public
int ivar_ext2_a : 5;
int ivar_ext2_b : 5;
}@end
int f2(A* a) {
return a->ivar_ext2_a + a->ivar_ext_a + a->ivar_a;
}
@implementation A {
@public
int ivar_b : 5;
int ivar_c : 5;
int ivar_d : 5;
}
@end
int f3(A *a) {
return a->ivar_d + a->ivar_ext2_a + a->ivar_ext_a + a->ivar_a;
}