diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:26:05 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:26:05 +0000 |
commit | 14f1b3e8826ce43b978db93a62d1166055db5394 (patch) | |
tree | 0a00ad8d3498783fe0193f3b656bca17c4c8697d /source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp | |
parent | 4ee8c119c71a06dcad1e0fecc8c675e480e59337 (diff) | |
download | src-14f1b3e8826ce43b978db93a62d1166055db5394.tar.gz src-14f1b3e8826ce43b978db93a62d1166055db5394.zip |
Vendor import of lldb trunk r290819:vendor/lldb/lldb-trunk-r290819
Notes
Notes:
svn path=/vendor/lldb/dist/; revision=311128
svn path=/vendor/lldb/lldb-trunk-r290819/; revision=311129; tag=vendor/lldb/lldb-trunk-r290819
Diffstat (limited to 'source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp')
-rw-r--r-- | source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp | 659 |
1 files changed, 328 insertions, 331 deletions
diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp index d4adc094bc1b..316115b0dcb1 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp @@ -21,379 +21,376 @@ using namespace lldb_private; using namespace lldb_utility; -AppleObjCTypeEncodingParser::AppleObjCTypeEncodingParser (ObjCLanguageRuntime& runtime) : - ObjCLanguageRuntime::EncodingToType(), - m_runtime(runtime) -{ - if (!m_scratch_ast_ctx_ap) - m_scratch_ast_ctx_ap.reset(new ClangASTContext(runtime.GetProcess()->GetTarget().GetArchitecture().GetTriple().str().c_str())); +AppleObjCTypeEncodingParser::AppleObjCTypeEncodingParser( + ObjCLanguageRuntime &runtime) + : ObjCLanguageRuntime::EncodingToType(), m_runtime(runtime) { + if (!m_scratch_ast_ctx_ap) + m_scratch_ast_ctx_ap.reset(new ClangASTContext(runtime.GetProcess() + ->GetTarget() + .GetArchitecture() + .GetTriple() + .str() + .c_str())); } std::string -AppleObjCTypeEncodingParser::ReadStructName(lldb_utility::StringLexer& type) -{ - StreamString buffer; - while (type.HasAtLeast(1) && type.Peek() != '=') - buffer.Printf("%c",type.Next()); - return buffer.GetString(); +AppleObjCTypeEncodingParser::ReadStructName(lldb_utility::StringLexer &type) { + StreamString buffer; + while (type.HasAtLeast(1) && type.Peek() != '=') + buffer.Printf("%c", type.Next()); + return buffer.GetString(); } std::string -AppleObjCTypeEncodingParser::ReadQuotedString(lldb_utility::StringLexer& type) -{ - StreamString buffer; - while (type.HasAtLeast(1) && type.Peek() != '"') - buffer.Printf("%c",type.Next()); - StringLexer::Character next = type.Next(); - UNUSED_IF_ASSERT_DISABLED(next); - assert (next == '"'); - return buffer.GetString(); +AppleObjCTypeEncodingParser::ReadQuotedString(lldb_utility::StringLexer &type) { + StreamString buffer; + while (type.HasAtLeast(1) && type.Peek() != '"') + buffer.Printf("%c", type.Next()); + StringLexer::Character next = type.Next(); + UNUSED_IF_ASSERT_DISABLED(next); + assert(next == '"'); + return buffer.GetString(); } uint32_t -AppleObjCTypeEncodingParser::ReadNumber (lldb_utility::StringLexer& type) -{ - uint32_t total = 0; - while (type.HasAtLeast(1) && isdigit(type.Peek())) - total = 10*total + (type.Next() - '0'); - return total; +AppleObjCTypeEncodingParser::ReadNumber(lldb_utility::StringLexer &type) { + uint32_t total = 0; + while (type.HasAtLeast(1) && isdigit(type.Peek())) + total = 10 * total + (type.Next() - '0'); + return total; } -// as an extension to the published grammar recent runtimes emit structs like this: +// as an extension to the published grammar recent runtimes emit structs like +// this: // "{CGRect=\"origin\"{CGPoint=\"x\"d\"y\"d}\"size\"{CGSize=\"width\"d\"height\"d}}" -AppleObjCTypeEncodingParser::StructElement::StructElement() : -name(""), -type(clang::QualType()), -bitfield(0) -{} +AppleObjCTypeEncodingParser::StructElement::StructElement() + : name(""), type(clang::QualType()), bitfield(0) {} AppleObjCTypeEncodingParser::StructElement -AppleObjCTypeEncodingParser::ReadStructElement (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool for_expression) -{ - StructElement retval; - if (type.NextIf('"')) - retval.name = ReadQuotedString(type); - if (!type.NextIf('"')) - return retval; - uint32_t bitfield_size = 0; - retval.type = BuildType(ast_ctx, type, for_expression, &bitfield_size); - retval.bitfield = bitfield_size; +AppleObjCTypeEncodingParser::ReadStructElement(clang::ASTContext &ast_ctx, + lldb_utility::StringLexer &type, + bool for_expression) { + StructElement retval; + if (type.NextIf('"')) + retval.name = ReadQuotedString(type); + if (!type.NextIf('"')) return retval; + uint32_t bitfield_size = 0; + retval.type = BuildType(ast_ctx, type, for_expression, &bitfield_size); + retval.bitfield = bitfield_size; + return retval; } clang::QualType -AppleObjCTypeEncodingParser::BuildStruct (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool for_expression) -{ - return BuildAggregate(ast_ctx, type, for_expression, '{', '}', clang::TTK_Struct); +AppleObjCTypeEncodingParser::BuildStruct(clang::ASTContext &ast_ctx, + lldb_utility::StringLexer &type, + bool for_expression) { + return BuildAggregate(ast_ctx, type, for_expression, '{', '}', + clang::TTK_Struct); } clang::QualType -AppleObjCTypeEncodingParser::BuildUnion (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool for_expression) -{ - return BuildAggregate(ast_ctx, type, for_expression, '(', ')', clang::TTK_Union); +AppleObjCTypeEncodingParser::BuildUnion(clang::ASTContext &ast_ctx, + lldb_utility::StringLexer &type, + bool for_expression) { + return BuildAggregate(ast_ctx, type, for_expression, '(', ')', + clang::TTK_Union); } -clang::QualType -AppleObjCTypeEncodingParser::BuildAggregate (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool for_expression, char opener, char closer, uint32_t kind) -{ - if (!type.NextIf(opener)) - return clang::QualType(); - std::string name(ReadStructName(type)); - - // We do not handle templated classes/structs at the moment. - // If the name has a < in it, we are going to abandon this. - // We're still obliged to parse it, so we just set a flag that - // means "Don't actually build anything." - - const bool is_templated = name.find('<') != std::string::npos; - - if (!type.NextIf('=')) - return clang::QualType(); - bool in_union = true; - std::vector<StructElement> elements; - while (in_union && type.HasAtLeast(1)) - { - if (type.NextIf(closer)) - { - in_union = false; - break; - } - else - { - auto element = ReadStructElement(ast_ctx, type, for_expression); - if (element.type.isNull()) - break; - else - elements.push_back(element); - } +clang::QualType AppleObjCTypeEncodingParser::BuildAggregate( + clang::ASTContext &ast_ctx, lldb_utility::StringLexer &type, + bool for_expression, char opener, char closer, uint32_t kind) { + if (!type.NextIf(opener)) + return clang::QualType(); + std::string name(ReadStructName(type)); + + // We do not handle templated classes/structs at the moment. + // If the name has a < in it, we are going to abandon this. + // We're still obliged to parse it, so we just set a flag that + // means "Don't actually build anything." + + const bool is_templated = name.find('<') != std::string::npos; + + if (!type.NextIf('=')) + return clang::QualType(); + bool in_union = true; + std::vector<StructElement> elements; + while (in_union && type.HasAtLeast(1)) { + if (type.NextIf(closer)) { + in_union = false; + break; + } else { + auto element = ReadStructElement(ast_ctx, type, for_expression); + if (element.type.isNull()) + break; + else + elements.push_back(element); } - if (in_union) - return clang::QualType(); - - if (is_templated) - return clang::QualType(); // This is where we bail out. Sorry! - - ClangASTContext *lldb_ctx = ClangASTContext::GetASTContext(&ast_ctx); - if (!lldb_ctx) - return clang::QualType(); - CompilerType union_type(lldb_ctx->CreateRecordType(nullptr, lldb::eAccessPublic, name.c_str(), kind, lldb::eLanguageTypeC)); - if (union_type) - { - ClangASTContext::StartTagDeclarationDefinition(union_type); - - unsigned int count = 0; - for (auto element: elements) - { - if (element.name.empty()) - { - StreamString elem_name; - elem_name.Printf("__unnamed_%u",count); - element.name = std::string(elem_name.GetData()); - } - ClangASTContext::AddFieldToRecordType(union_type, element.name.c_str(), CompilerType(&ast_ctx, element.type), lldb::eAccessPublic, element.bitfield); - ++count; - } - ClangASTContext::CompleteTagDeclarationDefinition(union_type); + } + if (in_union) + return clang::QualType(); + + if (is_templated) + return clang::QualType(); // This is where we bail out. Sorry! + + ClangASTContext *lldb_ctx = ClangASTContext::GetASTContext(&ast_ctx); + if (!lldb_ctx) + return clang::QualType(); + CompilerType union_type(lldb_ctx->CreateRecordType( + nullptr, lldb::eAccessPublic, name.c_str(), kind, lldb::eLanguageTypeC)); + if (union_type) { + ClangASTContext::StartTagDeclarationDefinition(union_type); + + unsigned int count = 0; + for (auto element : elements) { + if (element.name.empty()) { + StreamString elem_name; + elem_name.Printf("__unnamed_%u", count); + element.name = elem_name.GetString(); + } + ClangASTContext::AddFieldToRecordType( + union_type, element.name.c_str(), + CompilerType(&ast_ctx, element.type), lldb::eAccessPublic, + element.bitfield); + ++count; } - return ClangUtil::GetQualType(union_type); + ClangASTContext::CompleteTagDeclarationDefinition(union_type); + } + return ClangUtil::GetQualType(union_type); } clang::QualType -AppleObjCTypeEncodingParser::BuildArray (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool for_expression) -{ - if (!type.NextIf('[')) - return clang::QualType(); - uint32_t size = ReadNumber(type); - clang::QualType element_type(BuildType(ast_ctx, type, for_expression)); - if (!type.NextIf(']')) - return clang::QualType(); - ClangASTContext *lldb_ctx = ClangASTContext::GetASTContext(&ast_ctx); - if (!lldb_ctx) - return clang::QualType(); - CompilerType array_type(lldb_ctx->CreateArrayType(CompilerType(&ast_ctx, element_type), size, false)); - return ClangUtil::GetQualType(array_type); +AppleObjCTypeEncodingParser::BuildArray(clang::ASTContext &ast_ctx, + lldb_utility::StringLexer &type, + bool for_expression) { + if (!type.NextIf('[')) + return clang::QualType(); + uint32_t size = ReadNumber(type); + clang::QualType element_type(BuildType(ast_ctx, type, for_expression)); + if (!type.NextIf(']')) + return clang::QualType(); + ClangASTContext *lldb_ctx = ClangASTContext::GetASTContext(&ast_ctx); + if (!lldb_ctx) + return clang::QualType(); + CompilerType array_type(lldb_ctx->CreateArrayType( + CompilerType(&ast_ctx, element_type), size, false)); + return ClangUtil::GetQualType(array_type); } // the runtime can emit these in the form of @"SomeType", giving more specifics -// this would be interesting for expression parser interop, but since we actually try -// to avoid exposing the ivar info to the expression evaluator, consume but ignore the type info -// and always return an 'id'; if anything, dynamic typing will resolve things for us anyway -clang::QualType -AppleObjCTypeEncodingParser::BuildObjCObjectPointerType (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool for_expression) -{ - if (!type.NextIf('@')) - return clang::QualType(); - - std::string name; - - if (type.NextIf('"')) - { - // We have to be careful here. We're used to seeing - // @"NSString" - // but in records it is possible that the string following an @ is the name of the next field and @ means "id". - // This is the case if anything unquoted except for "}", the end of the type, or another name follows the quoted string. - // - // E.g. - // - @"NSString"@ means "id, followed by a field named NSString of type id" - // - @"NSString"} means "a pointer to NSString and the end of the struct" - // - @"NSString""nextField" means "a pointer to NSString and a field named nextField" - // - @"NSString" followed by the end of the string means "a pointer to NSString" - // - // As a result, the rule is: If we see @ followed by a quoted string, we peek. - // - If we see }, ), ], the end of the string, or a quote ("), the quoted string is a class name. - // - If we see anything else, the quoted string is a field name and we push it back onto type. - - name = ReadQuotedString(type); - - if (type.HasAtLeast(1)) - { - switch (type.Peek()) - { - default: - // roll back - type.PutBack(name.length() + 2); // undo our consumption of the string and of the quotes - name.clear(); - break; - case '}': - case ')': - case ']': - case '"': - // the quoted string is a class name – see the rule - break; - } - } - else - { - // the quoted string is a class name – see the rule - } +// this would be interesting for expression parser interop, but since we +// actually try +// to avoid exposing the ivar info to the expression evaluator, consume but +// ignore the type info +// and always return an 'id'; if anything, dynamic typing will resolve things +// for us anyway +clang::QualType AppleObjCTypeEncodingParser::BuildObjCObjectPointerType( + clang::ASTContext &ast_ctx, lldb_utility::StringLexer &type, + bool for_expression) { + if (!type.NextIf('@')) + return clang::QualType(); + + std::string name; + + if (type.NextIf('"')) { + // We have to be careful here. We're used to seeing + // @"NSString" + // but in records it is possible that the string following an @ is the name + // of the next field and @ means "id". + // This is the case if anything unquoted except for "}", the end of the + // type, or another name follows the quoted string. + // + // E.g. + // - @"NSString"@ means "id, followed by a field named NSString of type id" + // - @"NSString"} means "a pointer to NSString and the end of the struct" + // - @"NSString""nextField" means "a pointer to NSString and a field named + // nextField" + // - @"NSString" followed by the end of the string means "a pointer to + // NSString" + // + // As a result, the rule is: If we see @ followed by a quoted string, we + // peek. + // - If we see }, ), ], the end of the string, or a quote ("), the quoted + // string is a class name. + // - If we see anything else, the quoted string is a field name and we push + // it back onto type. + + name = ReadQuotedString(type); + + if (type.HasAtLeast(1)) { + switch (type.Peek()) { + default: + // roll back + type.PutBack(name.length() + + 2); // undo our consumption of the string and of the quotes + name.clear(); + break; + case '}': + case ')': + case ']': + case '"': + // the quoted string is a class name – see the rule + break; + } + } else { + // the quoted string is a class name – see the rule + } + } + + if (for_expression && !name.empty()) { + size_t less_than_pos = name.find('<'); + + if (less_than_pos != std::string::npos) { + if (less_than_pos == 0) + return ast_ctx.getObjCIdType(); + else + name.erase(less_than_pos); } - - if (for_expression && !name.empty()) - { - size_t less_than_pos = name.find('<'); - - if (less_than_pos != std::string::npos) - { - if (less_than_pos == 0) - return ast_ctx.getObjCIdType(); - else - name.erase(less_than_pos); - } - - DeclVendor *decl_vendor = m_runtime.GetDeclVendor(); - - assert (decl_vendor); // how are we parsing type encodings for expressions if a type vendor isn't in play? - - const bool append = false; - const uint32_t max_matches = 1; - std::vector<clang::NamedDecl *> decls; - - uint32_t num_types = decl_vendor->FindDecls(ConstString(name), - append, - max_matches, - decls); - - // The user can forward-declare something that has no definition. The runtime doesn't prohibit this at all. - // This is a rare and very weird case. We keep this assert in debug builds so we catch other weird cases. + + DeclVendor *decl_vendor = m_runtime.GetDeclVendor(); + if (!decl_vendor) + return clang::QualType(); + + const bool append = false; + const uint32_t max_matches = 1; + std::vector<clang::NamedDecl *> decls; + + uint32_t num_types = + decl_vendor->FindDecls(ConstString(name), append, max_matches, decls); + +// The user can forward-declare something that has no definition. The runtime +// doesn't prohibit this at all. +// This is a rare and very weird case. We keep this assert in debug builds so +// we catch other weird cases. #ifdef LLDB_CONFIGURATION_DEBUG - assert(num_types); + assert(num_types); #else - if (!num_types) - return ast_ctx.getObjCIdType(); + if (!num_types) + return ast_ctx.getObjCIdType(); #endif - return ClangUtil::GetQualType(ClangASTContext::GetTypeForDecl(decls[0]).GetPointerType()); - } - else - { - // We're going to resolve this dynamically anyway, so just smile and wave. - return ast_ctx.getObjCIdType(); - } + return ClangUtil::GetQualType( + ClangASTContext::GetTypeForDecl(decls[0]).GetPointerType()); + } else { + // We're going to resolve this dynamically anyway, so just smile and wave. + return ast_ctx.getObjCIdType(); + } } clang::QualType -AppleObjCTypeEncodingParser::BuildType (clang::ASTContext &ast_ctx, StringLexer& type, bool for_expression, uint32_t *bitfield_bit_size) -{ - if (!type.HasAtLeast(1)) - return clang::QualType(); - - switch (type.Peek()) - { - default: - break; - case '{': - return BuildStruct(ast_ctx, type, for_expression); - case '[': - return BuildArray(ast_ctx, type, for_expression); - case '(': - return BuildUnion(ast_ctx, type, for_expression); - case '@': - return BuildObjCObjectPointerType(ast_ctx, type, for_expression); - } - - switch (type.Next()) - { - default: - type.PutBack(1); +AppleObjCTypeEncodingParser::BuildType(clang::ASTContext &ast_ctx, + StringLexer &type, bool for_expression, + uint32_t *bitfield_bit_size) { + if (!type.HasAtLeast(1)) + return clang::QualType(); + + switch (type.Peek()) { + default: + break; + case '{': + return BuildStruct(ast_ctx, type, for_expression); + case '[': + return BuildArray(ast_ctx, type, for_expression); + case '(': + return BuildUnion(ast_ctx, type, for_expression); + case '@': + return BuildObjCObjectPointerType(ast_ctx, type, for_expression); + } + + switch (type.Next()) { + default: + type.PutBack(1); + return clang::QualType(); + case 'c': + return ast_ctx.CharTy; + case 'i': + return ast_ctx.IntTy; + case 's': + return ast_ctx.ShortTy; + case 'l': + return ast_ctx.getIntTypeForBitwidth(32, true); + // this used to be done like this: + // ClangASTContext *lldb_ctx = ClangASTContext::GetASTContext(&ast_ctx); + // if (!lldb_ctx) + // return clang::QualType(); + // return lldb_ctx->GetIntTypeFromBitSize(32, true).GetQualType(); + // which uses one of the constants if one is available, but we don't think all + // this work is necessary. + case 'q': + return ast_ctx.LongLongTy; + case 'C': + return ast_ctx.UnsignedCharTy; + case 'I': + return ast_ctx.UnsignedIntTy; + case 'S': + return ast_ctx.UnsignedShortTy; + case 'L': + return ast_ctx.getIntTypeForBitwidth(32, false); + // see note for 'l' + case 'Q': + return ast_ctx.UnsignedLongLongTy; + case 'f': + return ast_ctx.FloatTy; + case 'd': + return ast_ctx.DoubleTy; + case 'B': + return ast_ctx.BoolTy; + case 'v': + return ast_ctx.VoidTy; + case '*': + return ast_ctx.getPointerType(ast_ctx.CharTy); + case '#': + return ast_ctx.getObjCClassType(); + case ':': + return ast_ctx.getObjCSelType(); + case 'b': { + uint32_t size = ReadNumber(type); + if (bitfield_bit_size) { + *bitfield_bit_size = size; + return ast_ctx.UnsignedIntTy; // FIXME: the spec is fairly vague here. + } else + return clang::QualType(); + } + case 'r': { + clang::QualType target_type = BuildType(ast_ctx, type, for_expression); + if (target_type.isNull()) + return clang::QualType(); + else if (target_type == ast_ctx.UnknownAnyTy) + return ast_ctx.UnknownAnyTy; + else + return ast_ctx.getConstType(target_type); + } + case '^': { + if (!for_expression && type.NextIf('?')) { + // if we are not supporting the concept of unknownAny, but what is being + // created here is an unknownAny*, then + // we can just get away with a void* + // this is theoretically wrong (in the same sense as 'theoretically + // nothing exists') but is way better than outright failure + // in many practical cases + return ast_ctx.VoidPtrTy; + } else { + clang::QualType target_type = BuildType(ast_ctx, type, for_expression); + if (target_type.isNull()) return clang::QualType(); - case 'c': - return ast_ctx.CharTy; - case 'i': - return ast_ctx.IntTy; - case 's': - return ast_ctx.ShortTy; - case 'l': - return ast_ctx.getIntTypeForBitwidth(32, true); - // this used to be done like this: - // ClangASTContext *lldb_ctx = ClangASTContext::GetASTContext(&ast_ctx); - // if (!lldb_ctx) - // return clang::QualType(); - // return lldb_ctx->GetIntTypeFromBitSize(32, true).GetQualType(); - // which uses one of the constants if one is available, but we don't think all this work is necessary. - case 'q': - return ast_ctx.LongLongTy; - case 'C': - return ast_ctx.UnsignedCharTy; - case 'I': - return ast_ctx.UnsignedIntTy; - case 'S': - return ast_ctx.UnsignedShortTy; - case 'L': - return ast_ctx.getIntTypeForBitwidth(32, false); - // see note for 'l' - case 'Q': - return ast_ctx.UnsignedLongLongTy; - case 'f': - return ast_ctx.FloatTy; - case 'd': - return ast_ctx.DoubleTy; - case 'B': - return ast_ctx.BoolTy; - case 'v': - return ast_ctx.VoidTy; - case '*': - return ast_ctx.getPointerType(ast_ctx.CharTy); - case '#': - return ast_ctx.getObjCClassType(); - case ':': - return ast_ctx.getObjCSelType(); - case 'b': - { - uint32_t size = ReadNumber(type); - if (bitfield_bit_size) - { - *bitfield_bit_size = size; - return ast_ctx.UnsignedIntTy; // FIXME: the spec is fairly vague here. - } - else - return clang::QualType(); - } - case 'r': - { - clang::QualType target_type = BuildType(ast_ctx, type, for_expression); - if (target_type.isNull()) - return clang::QualType(); - else if (target_type == ast_ctx.UnknownAnyTy) - return ast_ctx.UnknownAnyTy; - else - return ast_ctx.getConstType(target_type); - } - case '^': - { - if (!for_expression && type.NextIf('?')) - { - // if we are not supporting the concept of unknownAny, but what is being created here is an unknownAny*, then - // we can just get away with a void* - // this is theoretically wrong (in the same sense as 'theoretically nothing exists') but is way better than outright failure - // in many practical cases - return ast_ctx.VoidPtrTy; - } - else - { - clang::QualType target_type = BuildType(ast_ctx, type, for_expression); - if (target_type.isNull()) - return clang::QualType(); - else if (target_type == ast_ctx.UnknownAnyTy) - return ast_ctx.UnknownAnyTy; - else - return ast_ctx.getPointerType(target_type); - } - } - case '?': - return for_expression ? ast_ctx.UnknownAnyTy : clang::QualType(); + else if (target_type == ast_ctx.UnknownAnyTy) + return ast_ctx.UnknownAnyTy; + else + return ast_ctx.getPointerType(target_type); } + } + case '?': + return for_expression ? ast_ctx.UnknownAnyTy : clang::QualType(); + } } -CompilerType -AppleObjCTypeEncodingParser::RealizeType (clang::ASTContext &ast_ctx, const char* name, bool for_expression) -{ - if (name && name[0]) - { - StringLexer lexer(name); - clang::QualType qual_type = BuildType(ast_ctx, lexer, for_expression); - return CompilerType(&ast_ctx, qual_type); - } - return CompilerType(); +CompilerType AppleObjCTypeEncodingParser::RealizeType( + clang::ASTContext &ast_ctx, const char *name, bool for_expression) { + if (name && name[0]) { + StringLexer lexer(name); + clang::QualType qual_type = BuildType(ast_ctx, lexer, for_expression); + return CompilerType(&ast_ctx, qual_type); + } + return CompilerType(); } - |