зеркало из https://github.com/microsoft/clang-1.git
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
This commit is contained in:
Родитель
1c0cfd4599
Коммит
43822eaedd
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -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!");
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче