[Lldb-commits] [lldb] r151868 - in /lldb/trunk: include/lldb/Symbol/ClangASTContext.h source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp source/Symbol/ClangASTContext.cpp test/lang/c/anonymous/ test/lang/c/anonymous/Makefile test/lang/c/anonymous/TestAnonymous.py test/lang/c/anonymous/main.c

Sean Callanan scallanan at apple.com
Thu Mar 1 17:03:45 PST 2012


Author: spyffe
Date: Thu Mar  1 19:03:45 2012
New Revision: 151868

URL: http://llvm.org/viewvc/llvm-project?rev=151868&view=rev
Log:
Improved the type's handling of anonymous structs,
so that the expression parser can look up members
of anonymous structs correctly.  This meant creating
all the proper IndirectFieldDecls in each Record
after it has been completely populated with members.

Added:
    lldb/trunk/test/lang/c/anonymous/
    lldb/trunk/test/lang/c/anonymous/Makefile
    lldb/trunk/test/lang/c/anonymous/TestAnonymous.py
    lldb/trunk/test/lang/c/anonymous/main.c
Modified:
    lldb/trunk/include/lldb/Symbol/ClangASTContext.h
    lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
    lldb/trunk/source/Symbol/ClangASTContext.cpp

Modified: lldb/trunk/include/lldb/Symbol/ClangASTContext.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/ClangASTContext.h?rev=151868&r1=151867&r2=151868&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/ClangASTContext.h (original)
+++ lldb/trunk/include/lldb/Symbol/ClangASTContext.h Thu Mar  1 19:03:45 2012
@@ -282,6 +282,17 @@
                                                       bitfield_bit_size);
     }
     
+    static void
+    BuildIndirectFields (clang::ASTContext *ast,
+                         lldb::clang_type_t record_qual_type);
+    
+    void
+    BuildIndirectFields (lldb::clang_type_t record_qual_type)
+    {
+        ClangASTContext::BuildIndirectFields(getASTContext(),
+                                             record_qual_type);
+    }
+    
     static clang::CXXMethodDecl *
     AddMethodToCXXRecordType (clang::ASTContext *ast,
                               lldb::clang_type_t record_opaque_type,

Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp?rev=151868&r1=151867&r2=151868&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp Thu Mar  1 19:03:45 2012
@@ -2067,6 +2067,9 @@
                     }
                 }
             }
+            
+            ast.BuildIndirectFields (clang_type);
+            
             ast.CompleteTagDeclarationDefinition (clang_type);
             
             if (!layout_info.field_offsets.empty())

Modified: lldb/trunk/source/Symbol/ClangASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangASTContext.cpp?rev=151868&r1=151867&r2=151868&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/ClangASTContext.cpp (original)
+++ lldb/trunk/source/Symbol/ClangASTContext.cpp Thu Mar  1 19:03:45 2012
@@ -1943,6 +1943,9 @@
                                                   bit_width,  // BitWidth
                                                   false,      // Mutable
                                                   false);     // HasInit
+            
+            if (!name)
+                field->setImplicit();
 
             field->setAccess (ConvertAccessTypeToAccessSpecifier (access));
 
@@ -1974,6 +1977,131 @@
     return field;
 }
 
+static clang::AccessSpecifier UnifyAccessSpecifiers (clang::AccessSpecifier lhs,
+                                                     clang::AccessSpecifier rhs)
+{
+    clang::AccessSpecifier ret = lhs;
+    
+    // Make the access equal to the stricter of the field and the nested field's access
+    switch (ret)
+    {
+        case clang::AS_none:
+            break;
+        case clang::AS_private:
+            break;
+        case clang::AS_protected:
+            if (rhs == AS_private)
+                ret = AS_private;
+            break;
+        case clang::AS_public:
+            ret = rhs;
+            break;
+    }
+    
+    return ret;
+}
+
+void
+ClangASTContext::BuildIndirectFields (clang::ASTContext *ast,
+                                      lldb::clang_type_t record_clang_type)
+{
+    QualType record_qual_type(QualType::getFromOpaquePtr(record_clang_type));
+
+    const RecordType *record_type = record_qual_type->getAs<RecordType>();
+    
+    if (!record_type)
+        return;
+    
+    RecordDecl *record_decl = record_type->getDecl();
+    
+    if (!record_decl)
+        return;
+    
+    typedef llvm::SmallVector <IndirectFieldDecl *, 1> IndirectFieldVector;
+    
+    IndirectFieldVector indirect_fields;
+    
+    for (RecordDecl::field_iterator fi = record_decl->field_begin(), fe = record_decl->field_end();
+         fi != fe;
+         ++fi)
+    {
+        if (fi->isAnonymousStructOrUnion())
+        {
+            QualType field_qual_type = fi->getType();
+            
+            const RecordType *field_record_type = field_qual_type->getAs<RecordType>();
+            
+            if (!field_record_type)
+                continue;
+            
+            RecordDecl *field_record_decl = field_record_type->getDecl();
+            
+            if (!field_record_decl)
+                continue;
+            
+            for (RecordDecl::decl_iterator di = field_record_decl->decls_begin(), de = field_record_decl->decls_end();
+                 di != de;
+                 ++di)
+            {
+                if (FieldDecl *nested_field_decl = dyn_cast<FieldDecl>(*di))
+                {
+                    NamedDecl **chain = new (*ast) NamedDecl*[2];
+                    chain[0] = *fi;
+                    chain[1] = nested_field_decl;
+                    IndirectFieldDecl *indirect_field = IndirectFieldDecl::Create(*ast,
+                                                                                  record_decl,
+                                                                                  SourceLocation(),
+                                                                                  nested_field_decl->getIdentifier(),
+                                                                                  nested_field_decl->getType(),
+                                                                                  chain,
+                                                                                  2);
+                    
+                    indirect_field->setAccess(UnifyAccessSpecifiers(fi->getAccess(),
+                                                                    nested_field_decl->getAccess()));
+                    
+                    indirect_fields.push_back(indirect_field);
+                }
+                else if (IndirectFieldDecl *nested_indirect_field_decl = dyn_cast<IndirectFieldDecl>(*di))
+                {
+                    int nested_chain_size = nested_indirect_field_decl->getChainingSize();
+                    NamedDecl **chain = new (*ast) NamedDecl*[nested_chain_size + 1];
+                    chain[0] = *fi;
+                    
+                    int chain_index = 1;
+                    for (IndirectFieldDecl::chain_iterator nci = nested_indirect_field_decl->chain_begin(),
+                         nce = nested_indirect_field_decl->chain_end();
+                         nci < nce;
+                         ++nci)
+                    {
+                        chain[chain_index] = *nci;
+                        chain_index++;
+                    }
+                    
+                    IndirectFieldDecl *indirect_field = IndirectFieldDecl::Create(*ast,
+                                                                                  record_decl,
+                                                                                  SourceLocation(),
+                                                                                  nested_indirect_field_decl->getIdentifier(),
+                                                                                  nested_indirect_field_decl->getType(),
+                                                                                  chain,
+                                                                                  nested_chain_size + 1);
+                                        
+                    indirect_field->setAccess(UnifyAccessSpecifiers(fi->getAccess(),
+                                                                    nested_indirect_field_decl->getAccess()));
+                    
+                    indirect_fields.push_back(indirect_field);
+                }
+            }
+        }
+    }
+    
+    for (IndirectFieldVector::iterator ifi = indirect_fields.begin(), ife = indirect_fields.end();
+         ifi < ife;
+         ++ifi)
+    {
+        record_decl->addDecl(*ifi);
+    }
+}
+
 bool
 ClangASTContext::FieldIsBitfield (FieldDecl* field, uint32_t& bitfield_bit_size)
 {

Added: lldb/trunk/test/lang/c/anonymous/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/c/anonymous/Makefile?rev=151868&view=auto
==============================================================================
--- lldb/trunk/test/lang/c/anonymous/Makefile (added)
+++ lldb/trunk/test/lang/c/anonymous/Makefile Thu Mar  1 19:03:45 2012
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+
+C_SOURCES := main.c
+
+include $(LEVEL)/Makefile.rules

Added: lldb/trunk/test/lang/c/anonymous/TestAnonymous.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/c/anonymous/TestAnonymous.py?rev=151868&view=auto
==============================================================================
--- lldb/trunk/test/lang/c/anonymous/TestAnonymous.py (added)
+++ lldb/trunk/test/lang/c/anonymous/TestAnonymous.py Thu Mar  1 19:03:45 2012
@@ -0,0 +1,59 @@
+"""Test that anonymous structs/unions are transparent to member access"""
+
+import os, time
+import unittest2
+import lldb
+from lldbtest import *
+
+class AnonymousTestCase(TestBase):
+
+    mydir = os.path.join("lang", "c", "anonymous")
+
+    def test_expr_with_dsym(self):
+        self.buildDsym()
+        self.expr()
+
+    def test_expr_with_dwarf(self):
+        self.buildDwarf()
+        self.expr()
+
+    def setUp(self):
+        # Call super's setUp().
+        TestBase.setUp(self)
+        # Find the line number to break inside main().
+        self.line = line_number('main.c', '// Set breakpoint 0 here.')
+
+    def common_setup(self):
+        exe = os.path.join(os.getcwd(), "a.out")
+        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
+
+        # Break inside the foo function which takes a bar_ptr argument.
+        self.expect("breakpoint set -f main.c -l %d" % self.line, BREAKPOINT_CREATED,
+            startstr = "Breakpoint created")
+
+        self.runCmd("run", RUN_SUCCEEDED)
+
+        # The stop reason of the thread should be breakpoint.
+        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
+            substrs = ['stopped',
+                       'stop reason = breakpoint'])
+
+        # The breakpoint should have a hit count of 1.
+        self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE,
+            substrs = [' resolved, hit count = 1'])
+
+    def expr(self):
+        self.common_setup()
+
+        # This should display correctly.
+        self.expect("expression c->foo.d", VARIABLES_DISPLAYED_CORRECTLY,
+            substrs = ["= 4"])
+            
+        self.expect("expression c->b", VARIABLES_DISPLAYED_CORRECTLY,
+            substrs = ["= 2"])
+
+if __name__ == '__main__':
+    import atexit
+    lldb.SBDebugger.Initialize()
+    atexit.register(lambda: lldb.SBDebugger.Terminate())
+    unittest2.main()

Added: lldb/trunk/test/lang/c/anonymous/main.c
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/c/anonymous/main.c?rev=151868&view=auto
==============================================================================
--- lldb/trunk/test/lang/c/anonymous/main.c (added)
+++ lldb/trunk/test/lang/c/anonymous/main.c Thu Mar  1 19:03:45 2012
@@ -0,0 +1,28 @@
+#include <stdio.h>
+
+struct container {
+  struct {
+    struct {
+      int a;
+      int b;
+    };
+    struct {
+      int c;
+      int d;
+    } foo;
+  };
+};
+
+int processor (struct container *c)
+{
+  return c->foo.d + c->b; // Set breakpoint 0 here.
+}
+
+int main()
+{
+  struct container c = { 0, 2, 0, 4 };
+  
+  printf("%d\n", processor(&c));
+
+  return 0;
+}





More information about the lldb-commits mailing list