aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/DeclObjC.h43
-rw-r--r--lib/Frontend/PCHReaderDecl.cpp1
-rw-r--r--lib/Frontend/PCHWriterDecl.cpp1
-rw-r--r--lib/Sema/Sema.h8
-rw-r--r--lib/Sema/SemaDeclCXX.cpp41
-rw-r--r--lib/Sema/SemaDeclObjC.cpp47
6 files changed, 111 insertions, 30 deletions
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h
index 18bb607d79..e34ec9ffcd 100644
--- a/include/clang/AST/DeclObjC.h
+++ b/include/clang/AST/DeclObjC.h
@@ -29,6 +29,7 @@ class ObjCProtocolDecl;
class ObjCCategoryDecl;
class ObjCPropertyDecl;
class ObjCPropertyImplDecl;
+class CXXBaseOrMemberInitializer;
class ObjCListBase {
void operator=(const ObjCListBase &); // DO NOT IMPLEMENT
@@ -1152,18 +1153,54 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
class ObjCImplementationDecl : public ObjCImplDecl {
/// Implementation Class's super class.
ObjCInterfaceDecl *SuperClass;
-
+ /// Support for ivar initialization.
+ /// IvarInitializers - The arguments used to initialize the ivars
+ CXXBaseOrMemberInitializer **IvarInitializers;
+ unsigned NumIvarInitializers;
+
ObjCImplementationDecl(DeclContext *DC, SourceLocation L,
ObjCInterfaceDecl *classInterface,
ObjCInterfaceDecl *superDecl)
: ObjCImplDecl(ObjCImplementation, DC, L, classInterface),
- SuperClass(superDecl){}
+ SuperClass(superDecl), IvarInitializers(0), NumIvarInitializers(0) {}
public:
static ObjCImplementationDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
ObjCInterfaceDecl *classInterface,
ObjCInterfaceDecl *superDecl);
-
+
+ /// init_iterator - Iterates through the ivar initializer list.
+ typedef CXXBaseOrMemberInitializer **init_iterator;
+
+ /// init_const_iterator - Iterates through the ivar initializer list.
+ typedef CXXBaseOrMemberInitializer * const * init_const_iterator;
+
+ /// init_begin() - Retrieve an iterator to the first initializer.
+ init_iterator init_begin() { return IvarInitializers; }
+ /// begin() - Retrieve an iterator to the first initializer.
+ init_const_iterator init_begin() const { return IvarInitializers; }
+
+ /// init_end() - Retrieve an iterator past the last initializer.
+ init_iterator init_end() {
+ return IvarInitializers + NumIvarInitializers;
+ }
+ /// end() - Retrieve an iterator past the last initializer.
+ init_const_iterator init_end() const {
+ return IvarInitializers + NumIvarInitializers;
+ }
+ /// getNumArgs - Number of ivars which must be initialized.
+ unsigned getNumIvarInitializers() const {
+ return NumIvarInitializers;
+ }
+
+ void setNumIvarInitializers(unsigned numNumIvarInitializers) {
+ NumIvarInitializers = numNumIvarInitializers;
+ }
+
+ void setIvarInitializers(ASTContext &C,
+ CXXBaseOrMemberInitializer ** initializers,
+ unsigned numInitializers);
+
/// getIdentifier - Get the identifier that names the class
/// interface associated with this implementation.
IdentifierInfo *getIdentifier() const {
diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp
index 53647badff..c215a5abba 100644
--- a/lib/Frontend/PCHReaderDecl.cpp
+++ b/lib/Frontend/PCHReaderDecl.cpp
@@ -383,6 +383,7 @@ void PCHDeclReader::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
VisitObjCImplDecl(D);
D->setSuperClass(
cast_or_null<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++])));
+ // FIXME. Add reading of IvarInitializers and NumIvarInitializers.
}
diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp
index 6b4ba67904..c3831628eb 100644
--- a/lib/Frontend/PCHWriterDecl.cpp
+++ b/lib/Frontend/PCHWriterDecl.cpp
@@ -361,6 +361,7 @@ void PCHDeclWriter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
void PCHDeclWriter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
VisitObjCImplDecl(D);
Writer.AddDeclRef(D->getSuperClass(), Record);
+ // FIXME add writing of IvarInitializers and NumIvarInitializers.
Code = pch::DECL_OBJC_IMPLEMENTATION;
}
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index f22c1ad852..fb65862fe4 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -1592,10 +1592,9 @@ public:
void AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method);
/// CollectIvarsToConstructOrDestruct - Collect those ivars which require
- /// construction (construct=true) or destruction (construct=false)
+ /// initialization.
void CollectIvarsToConstructOrDestruct(const ObjCInterfaceDecl *OI,
- llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars,
- bool construct=true);
+ llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars);
//===--------------------------------------------------------------------===//
// Statement Parsing Callbacks: SemaStmt.cpp.
public:
@@ -2510,6 +2509,9 @@ public:
bool SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
CXXBaseOrMemberInitializer **Initializers,
unsigned NumInitializers, bool AnyErrors);
+
+ void SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation);
+
/// MarkBaseAndMemberDestructorsReferenced - Given a record decl,
/// mark all the non-trivial destructors of its members and bases as
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index f6ff40010c..854f204ab0 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -5699,3 +5699,44 @@ void Sema::MarkVirtualMembersReferenced(SourceLocation Loc,
MarkVirtualMembersReferenced(Loc, Base);
}
}
+
+/// SetIvarInitializers - This routine builds initialization ASTs for the
+/// Objective-C implementation whose ivars need be initialized.
+void Sema::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) {
+ if (!getLangOptions().CPlusPlus)
+ return;
+ if (const ObjCInterfaceDecl *OID = ObjCImplementation->getClassInterface()) {
+ llvm::SmallVector<ObjCIvarDecl*, 8> ivars;
+ CollectIvarsToConstructOrDestruct(OID, ivars);
+ if (ivars.empty())
+ return;
+ llvm::SmallVector<CXXBaseOrMemberInitializer*, 32> AllToInit;
+ for (unsigned i = 0; i < ivars.size(); i++) {
+ FieldDecl *Field = ivars[i];
+ CXXBaseOrMemberInitializer *Member;
+ InitializedEntity InitEntity = InitializedEntity::InitializeMember(Field);
+ InitializationKind InitKind =
+ InitializationKind::CreateDefault(ObjCImplementation->getLocation());
+
+ InitializationSequence InitSeq(*this, InitEntity, InitKind, 0, 0);
+ Sema::OwningExprResult MemberInit =
+ InitSeq.Perform(*this, InitEntity, InitKind,
+ Sema::MultiExprArg(*this, 0, 0));
+ MemberInit = MaybeCreateCXXExprWithTemporaries(move(MemberInit));
+ // Note, MemberInit could actually come back empty if no initialization
+ // is required (e.g., because it would call a trivial default constructor)
+ if (!MemberInit.get() || MemberInit.isInvalid())
+ continue;
+
+ Member =
+ new (Context) CXXBaseOrMemberInitializer(Context,
+ Field, SourceLocation(),
+ SourceLocation(),
+ MemberInit.takeAs<Expr>(),
+ SourceLocation());
+ AllToInit.push_back(Member);
+ }
+ ObjCImplementation->setIvarInitializers(Context,
+ AllToInit.data(), AllToInit.size());
+ }
+}
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 1324e05b6d..8032030cf0 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -1441,6 +1441,7 @@ void Sema::ActOnAtEnd(SourceRange AtEnd,
IDecl = IDecl->getSuperClass();
}
}
+ SetIvarInitializers(IC);
} else if (ObjCCategoryImplDecl* CatImplClass =
dyn_cast<ObjCCategoryImplDecl>(ClassDecl)) {
CatImplClass->setAtEndRange(AtEnd);
@@ -1800,23 +1801,15 @@ Sema::DeclPtrTy Sema::ActOnObjCExceptionDecl(Scope *S, Declarator &D) {
}
/// CollectIvarsToConstructOrDestruct - Collect those ivars which require
-/// construction (construct=true) or destruction (construct=false)
-///
+/// initialization.
void Sema::CollectIvarsToConstructOrDestruct(const ObjCInterfaceDecl *OI,
- llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars,
- bool construct) {
- if (!getLangOptions().CPlusPlus)
- return;
+ llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) {
for (ObjCInterfaceDecl::ivar_iterator I = OI->ivar_begin(),
E = OI->ivar_end(); I != E; ++I) {
ObjCIvarDecl *Iv = (*I);
QualType QT = Context.getBaseElementType(Iv->getType());
- if (const RecordType *RT = QT->getAs<RecordType>()) {
- if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()))
- if (construct && !RD->hasTrivialConstructor() ||
- !construct && !RD->hasTrivialDestructor())
- Ivars.push_back(*I);
- }
+ if (isa<RecordType>(QT))
+ Ivars.push_back(*I);
}
// Find ivars to construct/destruct in class extension.
@@ -1825,12 +1818,8 @@ void Sema::CollectIvarsToConstructOrDestruct(const ObjCInterfaceDecl *OI,
E = CDecl->ivar_end(); I != E; ++I) {
ObjCIvarDecl *Iv = (*I);
QualType QT = Context.getBaseElementType(Iv->getType());
- if (const RecordType *RT = QT->getAs<RecordType>()) {
- if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()))
- if (construct && !RD->hasTrivialConstructor() ||
- !construct && !RD->hasTrivialDestructor())
- Ivars.push_back(*I);
- }
+ if (isa<RecordType>(QT))
+ Ivars.push_back(*I);
}
}
@@ -1841,12 +1830,22 @@ void Sema::CollectIvarsToConstructOrDestruct(const ObjCInterfaceDecl *OI,
E = ImplDecl->ivar_end(); I != E; ++I) {
ObjCIvarDecl *Iv = (*I);
QualType QT = Context.getBaseElementType(Iv->getType());
- if (const RecordType *RT = QT->getAs<RecordType>()) {
- if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()))
- if (construct && !RD->hasTrivialConstructor() ||
- !construct && !RD->hasTrivialDestructor())
- Ivars.push_back(*I);
- }
+ if (isa<RecordType>(QT))
+ Ivars.push_back(*I);
}
}
}
+
+void ObjCImplementationDecl::setIvarInitializers(ASTContext &C,
+ CXXBaseOrMemberInitializer ** initializers,
+ unsigned numInitializers) {
+ if (numInitializers > 0) {
+ NumIvarInitializers = numInitializers;
+ CXXBaseOrMemberInitializer **ivarInitializers =
+ new (C) CXXBaseOrMemberInitializer*[NumIvarInitializers];
+ memcpy(ivarInitializers, initializers,
+ numInitializers * sizeof(CXXBaseOrMemberInitializer*));
+ IvarInitializers = ivarInitializers;
+ }
+}
+