summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp40
-rw-r--r--lldb/test/lang/objcxx/objcxx-ivar-vector/TestIvarVector.py4
-rw-r--r--lldb/test/lang/objcxx/objcxx-ivar-vector/main.mm33
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];
+ }
+}
OpenPOWER on IntegriCloud