diff options
author | Daniel Dunbar <daniel@zuster.org> | 2008-10-17 16:17:37 +0000 |
---|---|---|
committer | Daniel Dunbar <daniel@zuster.org> | 2008-10-17 16:17:37 +0000 |
commit | d96b35bc6becf8db00d140c11e3d0e53f27567a1 (patch) | |
tree | 0bd124ea4cf5ee89e1d1f72e9caadcf6cf999f17 | |
parent | 66031a5594bc9a7dc0dc5137c3e7955f835e4639 (diff) |
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
-rw-r--r-- | include/clang/AST/ASTContext.h | 10 | ||||
-rw-r--r-- | lib/AST/ASTContext.cpp | 49 | ||||
-rw-r--r-- | 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<const RecordType*,8> &RT) const; + llvm::SmallVector<const RecordType*,8> &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<const RecordType*,8> &RT) const; + llvm::SmallVector<const RecordType*,8> &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<const RecordType*,8> &ERType) const { + llvm::SmallVector<const RecordType*,8> &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<const RecordType*,8> &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<const RecordType*,8> &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<P...> 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<ArrayType>(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<ASTContext*>(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<const RecordType *, 8> 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, |