From e4498c6d66a8f472cba29b6158a2e86dfc60d0ef Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Wed, 28 Apr 2010 16:11:27 +0000 Subject: [PATCH] More of Sema to implement initialization of ivar of c++ object types. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@102500 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/DeclObjC.h | 43 ++++++++++++++++++++++++++++--- lib/Frontend/PCHReaderDecl.cpp | 1 + lib/Frontend/PCHWriterDecl.cpp | 1 + lib/Sema/Sema.h | 8 +++--- lib/Sema/SemaDeclCXX.cpp | 41 +++++++++++++++++++++++++++++ lib/Sema/SemaDeclObjC.cpp | 47 +++++++++++++++++----------------- 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(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 &Ivars, - bool construct=true); + llvm::SmallVectorImpl &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 ivars; + CollectIvarsToConstructOrDestruct(OID, ivars); + if (ivars.empty()) + return; + llvm::SmallVector 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(), + 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(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 &Ivars, - bool construct) { - if (!getLangOptions().CPlusPlus) - return; + llvm::SmallVectorImpl &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()) { - if (const CXXRecordDecl *RD = dyn_cast(RT->getDecl())) - if (construct && !RD->hasTrivialConstructor() || - !construct && !RD->hasTrivialDestructor()) - Ivars.push_back(*I); - } + if (isa(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()) { - if (const CXXRecordDecl *RD = dyn_cast(RT->getDecl())) - if (construct && !RD->hasTrivialConstructor() || - !construct && !RD->hasTrivialDestructor()) - Ivars.push_back(*I); - } + if (isa(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()) { - if (const CXXRecordDecl *RD = dyn_cast(RT->getDecl())) - if (construct && !RD->hasTrivialConstructor() || - !construct && !RD->hasTrivialDestructor()) - Ivars.push_back(*I); - } + if (isa(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; + } +} + -- 2.40.0