diff options
3 files changed, 77 insertions, 0 deletions
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp index 9445fa56189..06e2333d5c5 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp @@ -43,6 +43,7 @@ AppleObjCTypeEncodingParser::ReadQuotedString(lldb_utility::StringLexer& type)      StreamString buffer;      while (type.HasAtLeast(1) && type.Peek() != '"')          buffer.Printf("%c",type.Next()); +    assert(type.Next() == '"');      return buffer.GetString();  } @@ -173,7 +174,46 @@ AppleObjCTypeEncodingParser::BuildObjCObjectPointerType (clang::ASTContext &ast_      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() + 1); +                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())      { diff --git a/lldb/test/lang/objcxx/objcxx-ivar-vector/TestIvarVector.py b/lldb/test/lang/objcxx/objcxx-ivar-vector/TestIvarVector.py new file mode 100644 index 00000000000..356979f0248 --- /dev/null +++ b/lldb/test/lang/objcxx/objcxx-ivar-vector/TestIvarVector.py @@ -0,0 +1,4 @@ +import lldbinline +import lldbtest + +lldbinline.MakeInlineTest(__file__, globals(), [lldbtest.skipIfFreeBSD,lldbtest.skipIfLinux,lldbtest.skipIfWindows]) diff --git a/lldb/test/lang/objcxx/objcxx-ivar-vector/main.mm b/lldb/test/lang/objcxx/objcxx-ivar-vector/main.mm new file mode 100644 index 00000000000..36eda1da2ac --- /dev/null +++ b/lldb/test/lang/objcxx/objcxx-ivar-vector/main.mm @@ -0,0 +1,33 @@ +#import <Foundation/Foundation.h> + +#include <vector> + +@interface MyElement : NSObject { +} +@end + +@interface MyClass : NSObject { +  std::vector<MyElement *> elements; +}; + +-(void)doSomething; + +@end + +@implementation MyClass + +-(void)doSomething +{ +  NSLog(@"Hello"); //% self.expect("expression -- elements", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["vector", "MyElement"]); +} + +@end + +int main () +{ +  @autoreleasepool +  { +    MyClass *c = [MyClass alloc]; +    [c doSomething]; +  } +}  | 

