/// 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
const ASTRecordLayout &getObjCLayout(const ObjCInterfaceDecl *D,
const ObjCImplementationDecl *Impl);
-
+
private:
/// \brief A set of deallocations that should be performed when the
/// ASTContext is destroyed.
/// 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;
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:
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());
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,
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.
// 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);
}
// 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));
case Decl::ObjCImplementation: {
ObjCImplementationDecl *OMD = cast<ObjCImplementationDecl>(D);
+ if (Features.ObjCNonFragileABI2 && OMD->hasSynthBitfield())
+ Context.ResetObjCLayout(OMD->getClassInterface());
EmitObjCPropertyImplementations(OMD);
EmitObjCIvarInitializations(OMD);
Runtime->GenerateClass(OMD);
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)) {
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++]));
}
cast_or_null<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++])));
llvm::tie(D->IvarInitializers, D->NumIvarInitializers)
= Reader.ReadCXXBaseOrMemberInitializers(Cursor, Record, Idx);
+ D->setHasSynthBitfield(Record[Idx++]);
}
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;
Writer.AddDeclRef(D->getSuperClass(), Record);
Writer.AddCXXBaseOrMemberInitializers(D->IvarInitializers,
D->NumIvarInitializers, Record);
+ Record.push_back(D->hasSynthBitfield());
Code = serialization::DECL_OBJC_IMPLEMENTATION;
}
--- /dev/null
+// 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;
+}
+