forked from OSchip/llvm-project
Problem with ObjC's type-encoding of nested structs causing infinit recursion.
llvm-svn: 46260
This commit is contained in:
parent
db449040aa
commit
0a71ad2e07
|
@ -984,7 +984,7 @@ void ASTContext::getObjCEncodingForMethodDecl(ObjCMethodDecl *Decl,
|
|||
// Encode type qualifer, 'in', 'inout', etc. for the return type.
|
||||
getObjCEncodingForTypeQualifier(Decl->getObjCDeclQualifier(), S);
|
||||
// Encode result type.
|
||||
getObjCEncodingForType(Decl->getResultType(), S);
|
||||
getObjCEncodingForType(Decl->getResultType(), S, EncodingRecordTypes);
|
||||
// Compute size of all parameters.
|
||||
// Start with computing size of a pointer in number of bytes.
|
||||
// FIXME: There might(should) be a better way of doing this computation!
|
||||
|
@ -1012,13 +1012,14 @@ void ASTContext::getObjCEncodingForMethodDecl(ObjCMethodDecl *Decl,
|
|||
// 'in', 'inout', etc.
|
||||
getObjCEncodingForTypeQualifier(
|
||||
Decl->getParamDecl(i)->getObjCDeclQualifier(), S);
|
||||
getObjCEncodingForType(PType, S);
|
||||
getObjCEncodingForType(PType, S, EncodingRecordTypes);
|
||||
S += llvm::utostr(ParmOffset);
|
||||
ParmOffset += getObjCEncodingTypeSize(PType);
|
||||
}
|
||||
}
|
||||
|
||||
void ASTContext::getObjCEncodingForType(QualType T, std::string& S) const
|
||||
void ASTContext::getObjCEncodingForType(QualType T, std::string& S,
|
||||
llvm::SmallVector<const RecordType *, 8> &ERType) const
|
||||
{
|
||||
// FIXME: This currently doesn't encode:
|
||||
// @ An object (whether statically typed or typed id)
|
||||
|
@ -1086,7 +1087,7 @@ void ASTContext::getObjCEncodingForType(QualType T, std::string& S) const
|
|||
}
|
||||
else if (T->isObjCQualifiedIdType()) {
|
||||
// Treat id<P...> same as 'id' for encoding purposes.
|
||||
return getObjCEncodingForType(getObjCIdType(), S);
|
||||
return getObjCEncodingForType(getObjCIdType(), S, ERType);
|
||||
|
||||
}
|
||||
else if (const PointerType *PT = T->getAsPointerType()) {
|
||||
|
@ -1112,7 +1113,7 @@ void ASTContext::getObjCEncodingForType(QualType T, std::string& S) const
|
|||
}
|
||||
|
||||
S += '^';
|
||||
getObjCEncodingForType(PT->getPointeeType(), S);
|
||||
getObjCEncodingForType(PT->getPointeeType(), S, ERType);
|
||||
} else if (const ArrayType *AT = T->getAsArrayType()) {
|
||||
S += '[';
|
||||
|
||||
|
@ -1121,7 +1122,7 @@ void ASTContext::getObjCEncodingForType(QualType T, std::string& S) const
|
|||
else
|
||||
assert(0 && "Unhandled array type!");
|
||||
|
||||
getObjCEncodingForType(AT->getElementType(), S);
|
||||
getObjCEncodingForType(AT->getElementType(), S, ERType);
|
||||
S += ']';
|
||||
} else if (T->getAsFunctionType()) {
|
||||
S += '?';
|
||||
|
@ -1129,10 +1130,21 @@ void ASTContext::getObjCEncodingForType(QualType T, std::string& S) const
|
|||
RecordDecl *RDecl= RTy->getDecl();
|
||||
S += '{';
|
||||
S += RDecl->getName();
|
||||
S += '=';
|
||||
for (int i = 0; i < RDecl->getNumMembers(); i++) {
|
||||
FieldDecl *field = RDecl->getMember(i);
|
||||
getObjCEncodingForType(field->getType(), S);
|
||||
bool found = false;
|
||||
for (unsigned i = 0, e = ERType.size(); i != e; ++i)
|
||||
if (ERType[i] == RTy) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if (!found) {
|
||||
ERType.push_back(RTy);
|
||||
S += '=';
|
||||
for (int i = 0; i < RDecl->getNumMembers(); i++) {
|
||||
FieldDecl *field = RDecl->getMember(i);
|
||||
getObjCEncodingForType(field->getType(), S, ERType);
|
||||
}
|
||||
assert(ERType.back() == RTy && "Record Type stack mismatch.");
|
||||
ERType.pop_back();
|
||||
}
|
||||
S += '}';
|
||||
} else if (T->isEnumeralType()) {
|
||||
|
|
|
@ -1005,8 +1005,9 @@ Value *ScalarExprEmitter::VisitVAArgExpr(VAArgExpr *VE) {
|
|||
|
||||
Value *ScalarExprEmitter::VisitObjCEncodeExpr(const ObjCEncodeExpr *E) {
|
||||
std::string str;
|
||||
|
||||
CGF.getContext().getObjCEncodingForType(E->getEncodedType(), str);
|
||||
llvm::SmallVector<const RecordType *, 8> EncodingRecordTypes;
|
||||
CGF.getContext().getObjCEncodingForType(E->getEncodedType(), str,
|
||||
EncodingRecordTypes);
|
||||
|
||||
llvm::Constant *C = llvm::ConstantArray::get(str);
|
||||
C = new llvm::GlobalVariable(C->getType(), true,
|
||||
|
|
|
@ -42,6 +42,7 @@ namespace {
|
|||
llvm::DenseMap<ObjCMethodDecl*, std::string> MethodInternalNames;
|
||||
llvm::SmallVector<Stmt *, 32> Stmts;
|
||||
llvm::SmallVector<int, 8> ObjCBcLabelNo;
|
||||
llvm::SmallVector<const RecordType *, 8> EncodingRecordTypes;
|
||||
|
||||
FunctionDecl *MsgSendFunctionDecl;
|
||||
FunctionDecl *MsgSendSuperFunctionDecl;
|
||||
|
@ -1226,7 +1227,8 @@ Stmt *RewriteTest::RewriteAtEncode(ObjCEncodeExpr *Exp) {
|
|||
// Create a new string expression.
|
||||
QualType StrType = Context->getPointerType(Context->CharTy);
|
||||
std::string StrEncoding;
|
||||
Context->getObjCEncodingForType(Exp->getEncodedType(), StrEncoding);
|
||||
Context->getObjCEncodingForType(Exp->getEncodedType(), StrEncoding,
|
||||
EncodingRecordTypes);
|
||||
Expr *Replacement = new StringLiteral(StrEncoding.c_str(),
|
||||
StrEncoding.length(), false, StrType,
|
||||
SourceLocation(), SourceLocation());
|
||||
|
@ -2516,7 +2518,8 @@ void RewriteTest::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
|
|||
Result += (*IVI)->getName();
|
||||
Result += "\", \"";
|
||||
std::string StrEncoding;
|
||||
Context->getObjCEncodingForType((*IVI)->getType(), StrEncoding);
|
||||
Context->getObjCEncodingForType((*IVI)->getType(), StrEncoding,
|
||||
EncodingRecordTypes);
|
||||
Result += StrEncoding;
|
||||
Result += "\", ";
|
||||
SynthesizeIvarOffsetComputation(IDecl, *IVI, Result);
|
||||
|
@ -2526,7 +2529,8 @@ void RewriteTest::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
|
|||
Result += (*IVI)->getName();
|
||||
Result += "\", \"";
|
||||
std::string StrEncoding;
|
||||
Context->getObjCEncodingForType((*IVI)->getType(), StrEncoding);
|
||||
Context->getObjCEncodingForType((*IVI)->getType(), StrEncoding,
|
||||
EncodingRecordTypes);
|
||||
Result += StrEncoding;
|
||||
Result += "\", ";
|
||||
SynthesizeIvarOffsetComputation(IDecl, (*IVI), Result);
|
||||
|
|
|
@ -46,6 +46,8 @@ class ASTContext {
|
|||
/// ASTRecordLayouts - A cache mapping from RecordDecls to ASTRecordLayouts.
|
||||
/// This is lazily created. This is intentionally not serialized.
|
||||
llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*> ASTRecordLayouts;
|
||||
|
||||
llvm::SmallVector<const RecordType *, 8> EncodingRecordTypes;
|
||||
|
||||
/// BuiltinVaListType - built-in va list type.
|
||||
/// This is initially null and set by Sema::LazilyCreateBuiltin when
|
||||
|
@ -204,7 +206,8 @@ public:
|
|||
}
|
||||
|
||||
// Return the ObjC type encoding for a given type.
|
||||
void getObjCEncodingForType(QualType t, std::string &S) const;
|
||||
void getObjCEncodingForType(QualType t, std::string &S,
|
||||
llvm::SmallVector<const RecordType *, 8> &RT) const;
|
||||
|
||||
// Put the string version of type qualifiers into S.
|
||||
void getObjCEncodingForTypeQualifier(Decl::ObjCDeclQualifier QT,
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
// RUN: clang -rewrite-test %s | clang
|
||||
|
||||
typedef struct NSMethodFrameArgInfo {
|
||||
struct NSMethodFrameArgInfo *subInfo;
|
||||
struct NSMethodFrameArgInfo *an;
|
||||
} NSMethodFrameArgInfo;
|
||||
|
||||
@interface NSMethodSignature
|
||||
- (NSMethodFrameArgInfo *)_argInfo;
|
||||
@end
|
||||
|
||||
@implementation NSMethodSignature
|
||||
|
||||
- (NSMethodFrameArgInfo *)_argInfo{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@end
|
||||
|
Loading…
Reference in New Issue