[Lldb-commits] [lldb] r221651 - Fixed two issues in the type encoding parser:

Sean Callanan scallanan at apple.com
Mon Nov 10 16:50:10 PST 2014


Author: spyffe
Date: Mon Nov 10 18:50:10 2014
New Revision: 221651

URL: http://llvm.org/viewvc/llvm-project?rev=221651&view=rev
Log:
Fixed two issues in the type encoding parser:

- A correctness issue: with assertions disabled,
  ReadQuotedString would misbehave; and

- A performance issue: BuildType used a long
  chain of if()s; I changed that to two switch
  statements.  That also makes the code much
  nicer to step through when debugging it.

Modified:
    lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp

Modified: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp?rev=221651&r1=221650&r2=221651&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp Mon Nov 10 18:50:10 2014
@@ -43,7 +43,8 @@ AppleObjCTypeEncodingParser::ReadQuotedS
     StreamString buffer;
     while (type.HasAtLeast(1) && type.Peek() != '"')
         buffer.Printf("%c",type.Next());
-    assert(type.Next() == '"');
+    StringLexer::Character next = type.Next();
+    assert (next == '"');
     return buffer.GetString();
 }
 
@@ -198,7 +199,7 @@ AppleObjCTypeEncodingParser::BuildObjCOb
             {
             default:
                 // roll back
-                type.PutBack(name.length() + 1);
+                type.PutBack(name.length() + 2); // undo our consumption of the string and of the quotes
                 name.clear();
                 break;
             case '}':
@@ -258,85 +259,78 @@ AppleObjCTypeEncodingParser::BuildType (
     if (!type.HasAtLeast(1))
         return clang::QualType();
     
-    if (type.NextIf('c'))
+    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;
-    if (type.NextIf('i'))
+    case 'i':
         return ast_ctx.IntTy;
-    if (type.NextIf('s'))
+    case 's':
         return ast_ctx.ShortTy;
-    if (type.NextIf('l'))
-    {
-        ClangASTContext *lldb_ctx = ClangASTContext::GetASTContext(&ast_ctx);
-        if (!lldb_ctx)
-            return clang::QualType();
-        return lldb_ctx->GetIntTypeFromBitSize(32, true).GetQualType();
-    }
-    if (type.NextIf('q'))
+    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;
-    if (type.NextIf('C'))
+    case 'C':
         return ast_ctx.UnsignedCharTy;
-    if (type.NextIf('I'))
+    case 'I':
         return ast_ctx.UnsignedIntTy;
-    if (type.NextIf('S'))
+    case 'S':
         return ast_ctx.UnsignedShortTy;
-    if (type.NextIf('L'))
-    {
-        ClangASTContext *lldb_ctx = ClangASTContext::GetASTContext(&ast_ctx);
-        if (!lldb_ctx)
-            return clang::QualType();
-        return lldb_ctx->GetIntTypeFromBitSize(32, false).GetQualType();
-    }
-    if (type.NextIf('Q'))
+    case 'L':
+        return ast_ctx.getIntTypeForBitwidth(32, false);
+        // see note for 'l'
+    case 'Q':
         return ast_ctx.UnsignedLongLongTy;
-    if (type.NextIf('f'))
+    case 'f':
         return ast_ctx.FloatTy;
-    if (type.NextIf('d'))
+    case 'd':
         return ast_ctx.DoubleTy;
-    if (type.NextIf('B'))
+    case 'B':
         return ast_ctx.BoolTy;
-    if (type.NextIf('v'))
+    case 'v':
         return ast_ctx.VoidTy;
-    if (type.NextIf('*'))
+    case '*':
         return ast_ctx.getPointerType(ast_ctx.CharTy);
-    if (type.NextIf('#'))
+    case '#':
         return ast_ctx.getObjCClassType();
-    if (type.NextIf(':'))
+    case ':':
         return ast_ctx.getObjCSelType();
-    
-    if (type.NextIf('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();
-    }
-    
-    if (type.NextIf('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);
-    }
-    
-    if (type.NextIf('^'))
-    {
-        if (!for_expression && type.NextIf('?'))
+    case 'b':
         {
-            // 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;
+            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();
         }
-        else
+    case 'r':
         {
             clang::QualType target_type = BuildType(ast_ctx, type, for_expression);
             if (target_type.isNull())
@@ -344,26 +338,32 @@ AppleObjCTypeEncodingParser::BuildType (
             else if (target_type == ast_ctx.UnknownAnyTy)
                 return ast_ctx.UnknownAnyTy;
             else
-                return ast_ctx.getPointerType(target_type);
+                return ast_ctx.getConstType(target_type);
         }
-    }
-    
-    if (type.NextIf('?'))
+    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();
-    
-    if (type.Peek() == '{')
-        return BuildStruct(ast_ctx, type, for_expression);
-    
-    if (type.Peek() == '[')
-        return BuildArray(ast_ctx, type, for_expression);
-    
-    if (type.Peek() == '(')
-        return BuildUnion(ast_ctx, type, for_expression);
-    
-    if (type.Peek() == '@')
-        return BuildObjCObjectPointerType(ast_ctx, type, for_expression);
-    
-    return clang::QualType();
+    }
 }
 
 ClangASTType





More information about the lldb-commits mailing list