diff options
-rw-r--r-- | include/clang/Sema/Action.h | 3 | ||||
-rw-r--r-- | include/clang/Sema/Sema.h | 3 | ||||
-rw-r--r-- | lib/Parse/ParseObjc.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 42 |
4 files changed, 49 insertions, 2 deletions
diff --git a/include/clang/Sema/Action.h b/include/clang/Sema/Action.h index 611d2f42f2..542ac3b8dc 100644 --- a/include/clang/Sema/Action.h +++ b/include/clang/Sema/Action.h @@ -722,6 +722,9 @@ public: return 0; } + virtual void ActOnLastBitfield(SourceLocation DeclStart, Decl *IntfDecl, + llvm::SmallVectorImpl<Decl *> &AllIvarDecls) {} + virtual void ActOnFields(Scope* S, SourceLocation RecLoc, Decl *TagDecl, Decl **Fields, unsigned NumFields, SourceLocation LBrac, SourceLocation RBrac, diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 41abdb4bfa..6ec01572b9 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -1022,7 +1022,8 @@ public: bool CheckNontrivialField(FieldDecl *FD); void DiagnoseNontrivial(const RecordType* Record, CXXSpecialMember mem); CXXSpecialMember getSpecialMember(const CXXMethodDecl *MD); - + virtual void ActOnLastBitfield(SourceLocation DeclStart, Decl *IntfDecl, + llvm::SmallVectorImpl<Decl *> &AllIvarDecls); virtual Decl *ActOnIvar(Scope *S, SourceLocation DeclStart, Decl *IntfDecl, Declarator &D, ExprTy *BitfieldWidth, diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index aafe9996d4..822d96b7c8 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -1097,7 +1097,7 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl, return Field; } } Callback(*this, interfaceDecl, visibility, AllIvarDecls); - + // Parse all the comma separated declarators. DeclSpec DS; ParseStructDeclaration(DS, Callback); @@ -1111,6 +1111,7 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl, } } SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc); + Actions.ActOnLastBitfield(RBraceLoc, interfaceDecl, AllIvarDecls); // Call ActOnFields() even if we don't have any decls. This is useful // for code rewriting tools that need to be aware of the empty list. Actions.ActOnFields(getCurScope(), atLoc, interfaceDecl, diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index f08092f922..e9a2b3cd72 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -6399,6 +6399,48 @@ Decl *Sema::ActOnIvar(Scope *S, return NewID; } +/// ActOnLastBitfield - This routine handles synthesized bitfields rules for +/// class and class extensions. For every class @interface and class +/// extension @interface, if the last ivar is a bitfield of any type, +/// then add an implicit `char :0` ivar to the end of that interface. +void Sema::ActOnLastBitfield(SourceLocation DeclLoc, Decl *EnclosingDecl, + llvm::SmallVectorImpl<Decl *> &AllIvarDecls) { + if (!LangOpts.ObjCNonFragileABI2 || AllIvarDecls.empty()) + return; + + Decl *ivarDecl = AllIvarDecls[AllIvarDecls.size()-1]; + ObjCIvarDecl *Ivar = cast<ObjCIvarDecl>(ivarDecl); + + if (!Ivar->isBitField()) + return; + uint64_t BitFieldSize = + Ivar->getBitWidth()->EvaluateAsInt(Context).getZExtValue(); + if (BitFieldSize == 0) + return; + ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(EnclosingDecl); + if (!ID) { + if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(EnclosingDecl)) { + if (!CD->IsClassExtension()) + return; + } + // No need to add this to end of @implementation. + else + return; + } + // All conditions are met. Add a new bitfield to the tail end of ivars. + llvm::APInt Zero(Context.getTypeSize(Context.CharTy), 0); + Expr * BW = + new (Context) IntegerLiteral(Zero, Context.CharTy, DeclLoc); + + Ivar = ObjCIvarDecl::Create(Context, cast<ObjCContainerDecl>(EnclosingDecl), + DeclLoc, 0, + Context.CharTy, + Context.CreateTypeSourceInfo(Context.CharTy), + ObjCIvarDecl::Private, BW, + true); + AllIvarDecls.push_back(Ivar); +} + void Sema::ActOnFields(Scope* S, SourceLocation RecLoc, Decl *EnclosingDecl, Decl **Fields, unsigned NumFields, |