diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2008-01-22 22:44:46 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2008-01-22 22:44:46 +0000 |
commit | 7d6b46d9a9d75dea8ef9f6973dd50633c1f37963 (patch) | |
tree | 6cb0465d2f3e2303372075864c872f087fdcebdf | |
parent | 655398244fc839638fe1a3e0a27a15d5a6d7e0d8 (diff) |
Problem with ObjC's type-encoding of nested structs causing infinit recursion.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@46260 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | AST/ASTContext.cpp | 32 | ||||
-rw-r--r-- | CodeGen/CGExprScalar.cpp | 5 | ||||
-rw-r--r-- | Driver/RewriteTest.cpp | 10 | ||||
-rw-r--r-- | include/clang/AST/ASTContext.h | 5 | ||||
-rw-r--r-- | test/Sema/objc-encoding-bug-1.m | 19 |
5 files changed, 55 insertions, 16 deletions
diff --git a/AST/ASTContext.cpp b/AST/ASTContext.cpp index 28c2329058..242a684b0a 100644 --- a/AST/ASTContext.cpp +++ b/AST/ASTContext.cpp @@ -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()) { diff --git a/CodeGen/CGExprScalar.cpp b/CodeGen/CGExprScalar.cpp index 410284a7b8..8ec1a83318 100644 --- a/CodeGen/CGExprScalar.cpp +++ b/CodeGen/CGExprScalar.cpp @@ -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, diff --git a/Driver/RewriteTest.cpp b/Driver/RewriteTest.cpp index c1243b91ed..eca9349fb6 100644 --- a/Driver/RewriteTest.cpp +++ b/Driver/RewriteTest.cpp @@ -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); diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index be185c38ac..1e5a255b91 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -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, diff --git a/test/Sema/objc-encoding-bug-1.m b/test/Sema/objc-encoding-bug-1.m new file mode 100644 index 0000000000..ecf7d81314 --- /dev/null +++ b/test/Sema/objc-encoding-bug-1.m @@ -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 + |