aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2008-12-19 23:34:38 +0000
committerFariborz Jahanian <fjahanian@apple.com>2008-12-19 23:34:38 +0000
commit43822eaeddeaa419b90f23c68af6b23c46788a58 (patch)
tree7f62cc3113d296a3758e41073e3a5916eff8a922
parent1c0cfd4599e816cfd7a8f348286bf0ad79652ffc (diff)
More encoding support. This time for
@encode of classes and bitfields. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@61268 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/ASTContext.h4
-rw-r--r--lib/AST/ASTContext.cpp100
-rw-r--r--lib/CodeGen/CGObjCMac.cpp2
-rw-r--r--test/CodeGenObjC/encode-test.m40
4 files changed, 104 insertions, 42 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 2c7b6fdf41..4a1992a914 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -299,7 +299,7 @@ public:
/// given type into \arg S. If \arg NameFields is specified then
/// record field names are also encoded.
void getObjCEncodingForType(QualType t, std::string &S,
- bool NameFields=false) const;
+ FieldDecl *Field=NULL) const;
// Put the string version of type qualifiers into S.
void getObjCEncodingForTypeQualifier(Decl::ObjCDeclQualifier QT,
@@ -542,7 +542,7 @@ private:
void getObjCEncodingForTypeImpl(QualType t, std::string &S,
bool ExpandPointedToStructures,
bool ExpandStructures,
- bool NameFields) const;
+ FieldDecl *Field) const;
};
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index a91679e594..c50a021028 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -1734,48 +1734,58 @@ void ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD,
}
void ASTContext::getObjCEncodingForType(QualType T, std::string& S,
- bool NameFields) const {
+ FieldDecl *Field) 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, NameFields);
+ getObjCEncodingForTypeImpl(T, S, true, true, Field);
}
void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
bool ExpandPointedToStructures,
bool ExpandStructures,
- bool NameFields) const {
+ FieldDecl *FD) const {
if (const BuiltinType *BT = T->getAsBuiltinType()) {
- char encoding;
- switch (BT->getKind()) {
- default: assert(0 && "Unhandled builtin type kind");
- case BuiltinType::Void: encoding = 'v'; break;
- case BuiltinType::Bool: encoding = 'B'; break;
- case BuiltinType::Char_U:
- case BuiltinType::UChar: encoding = 'C'; break;
- case BuiltinType::UShort: encoding = 'S'; break;
- case BuiltinType::UInt: encoding = 'I'; break;
- case BuiltinType::ULong: encoding = 'L'; break;
- case BuiltinType::ULongLong: encoding = 'Q'; break;
- case BuiltinType::Char_S:
- case BuiltinType::SChar: encoding = 'c'; break;
- case BuiltinType::Short: encoding = 's'; break;
- case BuiltinType::Int: encoding = 'i'; break;
- case BuiltinType::Long: encoding = 'l'; break;
- case BuiltinType::LongLong: encoding = 'q'; break;
- case BuiltinType::Float: encoding = 'f'; break;
- case BuiltinType::Double: encoding = 'd'; break;
- case BuiltinType::LongDouble: encoding = 'd'; break;
+ if (FD && FD->isBitField()) {
+ const Expr *E = FD->getBitWidth();
+ assert(E && "bitfield width not there - getObjCEncodingForTypeImpl");
+ ASTContext *Ctx = const_cast<ASTContext*>(this);
+ unsigned N = E->getIntegerConstantExprValue(*Ctx).getZExtValue();
+ S += 'b';
+ S += llvm::utostr(N);
}
+ else {
+ char encoding;
+ switch (BT->getKind()) {
+ default: assert(0 && "Unhandled builtin type kind");
+ case BuiltinType::Void: encoding = 'v'; break;
+ case BuiltinType::Bool: encoding = 'B'; break;
+ case BuiltinType::Char_U:
+ case BuiltinType::UChar: encoding = 'C'; break;
+ case BuiltinType::UShort: encoding = 'S'; break;
+ case BuiltinType::UInt: encoding = 'I'; break;
+ case BuiltinType::ULong: encoding = 'L'; break;
+ case BuiltinType::ULongLong: encoding = 'Q'; break;
+ case BuiltinType::Char_S:
+ case BuiltinType::SChar: encoding = 'c'; break;
+ case BuiltinType::Short: encoding = 's'; break;
+ case BuiltinType::Int: encoding = 'i'; break;
+ case BuiltinType::Long: encoding = 'l'; break;
+ case BuiltinType::LongLong: encoding = 'q'; break;
+ case BuiltinType::Float: encoding = 'f'; break;
+ case BuiltinType::Double: encoding = 'd'; break;
+ case BuiltinType::LongDouble: encoding = 'd'; break;
+ }
- S += encoding;
+ S += encoding;
+ }
}
else if (T->isObjCQualifiedIdType()) {
// Treat id<P...> same as 'id' for encoding purposes.
return getObjCEncodingForTypeImpl(getObjCIdType(), S,
ExpandPointedToStructures,
- ExpandStructures, NameFields);
+ ExpandStructures, FD);
}
else if (const PointerType *PT = T->getAsPointerType()) {
QualType PointeeTy = PT->getPointeeType();
@@ -1810,7 +1820,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
S += '^';
getObjCEncodingForTypeImpl(PT->getPointeeType(), S,
false, ExpandPointedToStructures,
- false);
+ NULL);
} else if (const ArrayType *AT =
// Ignore type qualifiers etc.
dyn_cast<ArrayType>(T->getCanonicalTypeInternal())) {
@@ -1822,7 +1832,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
assert(0 && "Unhandled array type!");
getObjCEncodingForTypeImpl(AT->getElementType(), S,
- false, ExpandStructures, NameFields);
+ false, ExpandStructures, FD);
S += ']';
} else if (T->getAsFunctionType()) {
S += '?';
@@ -1840,24 +1850,19 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
for (RecordDecl::field_iterator Field = RDecl->field_begin(),
FieldEnd = RDecl->field_end();
Field != FieldEnd; ++Field) {
- if (NameFields) {
+ if (FD) {
S += '"';
S += Field->getNameAsString();
S += '"';
}
// Special case bit-fields.
- if (const Expr *E = Field->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);
+ if (Field->isBitField()) {
+ getObjCEncodingForTypeImpl(Field->getType(), S, false, true,
+ (*Field));
} else {
getObjCEncodingForTypeImpl(Field->getType(), S, false, true,
- NameFields);
+ FD);
}
}
}
@@ -1866,7 +1871,26 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
S += 'i';
} else if (T->isBlockPointerType()) {
S += '^'; // This type string is the same as general pointers.
- } else
+ } else if (T->isObjCInterfaceType()) {
+ // @encode(class_name)
+ ObjCInterfaceDecl *OI = T->getAsObjCInterfaceType()->getDecl();
+ S += '{';
+ const IdentifierInfo *II = OI->getIdentifier();
+ S += II->getName();
+ S += '=';
+ std::vector<FieldDecl*> RecFields;
+ CollectObjCIvars(OI, RecFields);
+ for (unsigned int i = 0; i != RecFields.size(); i++) {
+ if (RecFields[i]->isBitField())
+ getObjCEncodingForTypeImpl(RecFields[i]->getType(), S, false, true,
+ RecFields[i]);
+ else
+ getObjCEncodingForTypeImpl(RecFields[i]->getType(), S, false, true,
+ FD);
+ }
+ S += '}';
+ }
+ else
assert(0 && "@encode for type not implemented!");
}
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp
index 33dfff1030..dd722458aa 100644
--- a/lib/CodeGen/CGObjCMac.cpp
+++ b/lib/CodeGen/CGObjCMac.cpp
@@ -1336,7 +1336,7 @@ llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
Layout->getElementOffset(CGM.getTypes().getLLVMFieldNo(Field));
std::string TypeStr;
Ivar[0] = GetMethodVarName(V->getIdentifier());
- CGM.getContext().getObjCEncodingForType(V->getType(), TypeStr, true);
+ CGM.getContext().getObjCEncodingForType(V->getType(), TypeStr, Field);
Ivar[1] = GetMethodVarType(TypeStr);
Ivar[2] = llvm::ConstantInt::get(ObjCTypes.IntTy, Offset);
Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarTy, Ivar));
diff --git a/test/CodeGenObjC/encode-test.m b/test/CodeGenObjC/encode-test.m
index f5b6b92071..982faf03ba 100644
--- a/test/CodeGenObjC/encode-test.m
+++ b/test/CodeGenObjC/encode-test.m
@@ -1,5 +1,6 @@
// RUN: clang -fnext-runtime -emit-llvm -o %t %s &&
-// RUN: grep -e "\^{Innermost=CC}" %t | count 1
+// RUN: grep -e "\^{Innermost=CC}" %t | count 1 &&
+// RUN: grep -e "{Derived=#ib32b8b3b8sb16b8b8b2b8ccb6}" %t | count 1
@class Int1;
@@ -15,3 +16,40 @@ struct Innermost {
@implementation Int1
@end
+
+@interface Base
+{
+ struct objc_class *isa;
+ int full;
+ int full2: 32;
+ int _refs: 8;
+ int field2: 3;
+ unsigned f3: 8;
+ short cc;
+ unsigned g: 16;
+ int r2: 8;
+ int r3: 8;
+ int r4: 2;
+ int r5: 8;
+ char c;
+}
+@end
+
+@interface Derived: Base
+{
+ char d;
+ int _field3: 6;
+}
+@end
+
+@implementation Base
+@end
+
+@implementation Derived
+@end
+
+int main()
+{
+ const char *en = @encode(Derived);
+}
+