From d96b35bc6becf8db00d140c11e3d0e53f27567a1 Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Fri, 17 Oct 2008 16:17:37 +0000 Subject: [PATCH] More Obj-C type encoding improvements. - Encode unions and bit-fields correctly. - Accept option to name record fields (used for NeXT runtime). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@57685 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/ASTContext.h | 10 ++++--- lib/AST/ASTContext.cpp | 49 +++++++++++++++++++++------------- lib/CodeGen/CGObjCMac.cpp | 3 ++- 3 files changed, 40 insertions(+), 22 deletions(-) diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index b071255c57..e0ffcf4c92 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -273,9 +273,12 @@ public: //// This gets the struct used to keep track of fast enumerations. QualType getObjCFastEnumerationStateType(); - // Return the ObjC type encoding for a given type. + /// getObjCEncodingForType - Emit the ObjC type encoding for the + /// given type into \arg S. If \arg NameFields is specified then + /// record field names are also encoded. void getObjCEncodingForType(QualType t, std::string &S, - llvm::SmallVector &RT) const; + llvm::SmallVector &RT, + bool NameFields=false) const; // Put the string version of type qualifiers into S. void getObjCEncodingForTypeQualifier(Decl::ObjCDeclQualifier QT, @@ -478,7 +481,8 @@ private: void getObjCEncodingForTypeImpl(QualType t, std::string &S, bool ExpandPointedToStructures, bool ExpandStructures, - llvm::SmallVector &RT) const; + llvm::SmallVector &RT, + bool NameFields) const; }; diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 578b0ddfb3..292d5a9482 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -1594,26 +1594,20 @@ void ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD, } void ASTContext::getObjCEncodingForType(QualType T, std::string& S, - llvm::SmallVector &ERType) const { + llvm::SmallVector &ERType, + bool NameFields) const { // We follow the behavior of gcc, expanding structures which are // directly pointed to, and expanding embedded structures. Note that // these rules are sufficient to prevent recursive encoding of the // same type. - getObjCEncodingForTypeImpl(T, S, true, true, ERType); + getObjCEncodingForTypeImpl(T, S, true, true, ERType, NameFields); } void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, bool ExpandPointedToStructures, bool ExpandStructures, - llvm::SmallVector &ERType) const { - // FIXME: This currently doesn't encode: - // @ An object (whether statically typed or typed id) - // # A class object (Class) - // : A method selector (SEL) - // {name=type...} A structure - // (name=type...) A union - // bnum A bit field of num bits - + llvm::SmallVector &ERType, + bool NameFields) const { if (const BuiltinType *BT = T->getAsBuiltinType()) { char encoding; switch (BT->getKind()) { @@ -1643,7 +1637,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, // Treat id same as 'id' for encoding purposes. return getObjCEncodingForTypeImpl(getObjCIdType(), S, ExpandPointedToStructures, - ExpandStructures, ERType); + ExpandStructures, ERType, NameFields); } else if (const PointerType *PT = T->getAsPointerType()) { QualType PointeeTy = PT->getPointeeType(); @@ -1669,7 +1663,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, S += '^'; getObjCEncodingForTypeImpl(PT->getPointeeType(), S, - false, ExpandPointedToStructures, ERType); + false, ExpandPointedToStructures, + ERType, NameFields); } else if (const ArrayType *AT = // Ignore type qualifiers etc. dyn_cast(T->getCanonicalTypeInternal())) { @@ -1681,13 +1676,13 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, assert(0 && "Unhandled array type!"); getObjCEncodingForTypeImpl(AT->getElementType(), S, - false, ExpandStructures, ERType); + false, ExpandStructures, ERType, NameFields); S += ']'; } else if (T->getAsFunctionType()) { S += '?'; } else if (const RecordType *RTy = T->getAsRecordType()) { RecordDecl *RDecl = RTy->getDecl(); - S += '{'; + S += RDecl->isUnion() ? '(' : '{'; // Anonymous structures print as '?' if (const IdentifierInfo *II = RDecl->getIdentifier()) { S += II->getName(); @@ -1704,13 +1699,31 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, ERType.push_back(RTy); S += '='; for (int i = 0; i < RDecl->getNumMembers(); i++) { - FieldDecl *field = RDecl->getMember(i); - getObjCEncodingForTypeImpl(field->getType(), S, false, true, ERType); + FieldDecl *FD = RDecl->getMember(i); + if (NameFields) { + S += '"'; + S += FD->getName(); + S += '"'; + } + + // Special case bit-fields. + if (const Expr *E = FD->getBitWidth()) { + // FIXME: Fix constness. + ASTContext *Ctx = const_cast(this); + unsigned N = E->getIntegerConstantExprValue(*Ctx).getZExtValue(); + // FIXME: Obj-C is losing information about the type size + // here. Investigate if this is a problem. + S += 'b'; + S += llvm::utostr(N); + } else { + getObjCEncodingForTypeImpl(FD->getType(), S, false, true, + ERType, NameFields); + } } assert(ERType.back() == RTy && "Record Type stack mismatch."); ERType.pop_back(); } - S += '}'; + S += RDecl->isUnion() ? ')' : '}'; } else if (T->isEnumeralType()) { S += 'i'; } else if (T->isBlockPointerType()) { diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 682515180d..2b1ffc0d8e 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -1271,7 +1271,8 @@ llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID, llvm::SmallVector EncodingRecordTypes; Ivar[0] = GetMethodVarName(V->getIdentifier()); CGM.getContext().getObjCEncodingForType(V->getType(), TypeStr, - EncodingRecordTypes); + EncodingRecordTypes, + true); Ivar[1] = GetMethodVarType(TypeStr); Ivar[2] = llvm::ConstantInt::get(ObjCTypes.IntTy, Offset); Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarTy, -- 2.40.0