aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Sema/Action.h3
-rw-r--r--include/clang/Sema/Sema.h3
-rw-r--r--lib/Parse/ParseObjc.cpp3
-rw-r--r--lib/Sema/SemaDecl.cpp42
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,