Author: sivachandra
Date: Wed Oct  7 17:11:52 2015
New Revision: 249629

URL: http://llvm.org/viewvc/llvm-project?rev=249629&view=rev
Log:
[DWARFASTParserClang] Strengthen incomplete type handling.

Summary: This change fixes pr24916. As associated test has been added.

Reviewers: clayborg

Subscribers: zturner, lldb-commits

Differential Revision: http://reviews.llvm.org/D13224

Added:
    lldb/trunk/test/lang/cpp/limit-debug-info/
    lldb/trunk/test/lang/cpp/limit-debug-info/Makefile
    lldb/trunk/test/lang/cpp/limit-debug-info/TestWithLimitDebugInfo.py
    lldb/trunk/test/lang/cpp/limit-debug-info/base.cpp
    lldb/trunk/test/lang/cpp/limit-debug-info/base.h
    lldb/trunk/test/lang/cpp/limit-debug-info/derived.cpp
    lldb/trunk/test/lang/cpp/limit-debug-info/derived.h
    lldb/trunk/test/lang/cpp/limit-debug-info/main.cpp
Modified:
    lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
    lldb/trunk/test/make/Makefile.rules

Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp?rev=249629&r1=249628&r2=249629&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp 
(original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp Wed Oct  
7 17:11:52 2015
@@ -615,6 +615,10 @@ DWARFASTParserClang::ParseTypeFromDWARF
                             // so lets use it and cache the fact that we found
                             // a complete type for this die
                             dwarf->GetDIEToType()[die.GetDIE()] = 
type_sp.get();
+                            clang::DeclContext *defn_decl_ctx = 
GetCachedClangDeclContextForDIE(
+                                
dwarf->DebugInfo()->GetDIE(DIERef(type_sp->GetID())));
+                            if (defn_decl_ctx)
+                                LinkDeclContextToDIE(defn_decl_ctx, die);
                             return type_sp;
                         }
                     }
@@ -1101,8 +1105,11 @@ DWARFASTParserClang::ParseTypeFromDWARF
                                 Type *class_type = dwarf->ResolveType 
(decl_ctx_die);
                                 if (class_type)
                                 {
+                                    bool alternate_defn = false;
                                     if (class_type->GetID() != 
decl_ctx_die.GetID())
                                     {
+                                        alternate_defn = true;
+
                                         // We uniqued the parent class of this 
function to another class
                                         // so we now need to associate all 
dies under "decl_ctx_die" to
                                         // DIEs in the DIE for "class_type"...
@@ -1193,13 +1200,8 @@ DWARFASTParserClang::ParseTypeFromDWARF
                                         CompilerType class_opaque_type = 
class_type->GetForwardCompilerType ();
                                         if 
(ClangASTContext::IsCXXClassType(class_opaque_type))
                                         {
-                                            if 
(class_opaque_type.IsBeingDefined ())
+                                            if 
(class_opaque_type.IsBeingDefined () || alternate_defn)
                                             {
-                                                // Neither GCC 4.2 nor clang++ 
currently set a valid accessibility
-                                                // in the DWARF for C++ 
methods... Default to public for now...
-                                                if (accessibility == 
eAccessNone)
-                                                    accessibility = 
eAccessPublic;
-
                                                 if (!is_static && 
!die.HasChildren())
                                                 {
                                                     // We have a C++ member 
function with no children (this pointer!)
@@ -1209,52 +1211,87 @@ DWARFASTParserClang::ParseTypeFromDWARF
                                                 }
                                                 else
                                                 {
-                                                    clang::CXXMethodDecl 
*cxx_method_decl;
-                                                    // REMOVE THE CRASH 
DESCRIPTION BELOW
-                                                    
Host::SetCrashDescriptionWithFormat ("SymbolFileDWARF::ParseType() is adding a 
method %s to class %s in DIE 0x%8.8" PRIx64 " from %s",
-                                                                               
          type_name_cstr,
-                                                                               
          class_type->GetName().GetCString(),
-                                                                               
          die.GetID(),
-                                                                               
          dwarf->GetObjectFile()->GetFileSpec().GetPath().c_str());
-
-                                                    const bool is_attr_used = 
false;
-
-                                                    cxx_method_decl = 
m_ast.AddMethodToCXXRecordType (class_opaque_type.GetOpaqueQualType(),
-                                                                               
                       type_name_cstr,
-                                                                               
                       clang_type,
-                                                                               
                       accessibility,
-                                                                               
                       is_virtual,
-                                                                               
                       is_static,
-                                                                               
                       is_inline,
-                                                                               
                       is_explicit,
-                                                                               
                       is_attr_used,
-                                                                               
                       is_artificial);
-
-                                                    type_handled = 
cxx_method_decl != NULL;
-
-                                                    if (type_handled)
+                                                    bool add_method = true;
+                                                    if (alternate_defn)
                                                     {
-                                                        
LinkDeclContextToDIE(ClangASTContext::GetAsDeclContext(cxx_method_decl), die);
-
-                                                        
Host::SetCrashDescription (NULL);
-
-
-                                                        ClangASTMetadata 
metadata;
-                                                        
metadata.SetUserID(die.GetID());
-
-                                                        if 
(!object_pointer_name.empty())
+                                                        // If an alternate 
definition for the class exists, then add the method only if an
+                                                        // equivalent is not 
already present.
+                                                        clang::CXXRecordDecl 
*record_decl = m_ast.GetAsCXXRecordDecl(class_opaque_type.GetOpaqueQualType());
+                                                        if (record_decl)
                                                         {
-                                                            
metadata.SetObjectPtrName(object_pointer_name.c_str());
-                                                            if (log)
-                                                                log->Printf 
("Setting object pointer name: %s on method object %p.\n",
-                                                                             
object_pointer_name.c_str(),
-                                                                             
static_cast<void*>(cxx_method_decl));
+                                                            for (auto 
method_iter = record_decl->method_begin();
+                                                                 method_iter 
!= record_decl->method_end();
+                                                                 method_iter++)
+                                                            {
+                                                                
clang::CXXMethodDecl *method_decl = *method_iter;
+                                                                if 
(method_decl->getNameInfo().getAsString() == std::string(type_name_cstr))
+                                                                {
+                                                                    if 
(method_decl->getType() == ClangASTContext::GetQualType(clang_type))
+                                                                    {
+                                                                        
add_method = false;
+                                                                        
LinkDeclContextToDIE(ClangASTContext::GetAsDeclContext(method_decl), die);
+                                                                        
type_handled = true;
+
+                                                                        break;
+                                                                    }
+                                                                }
+                                                            }
                                                         }
-                                                        m_ast.SetMetadata 
(cxx_method_decl, metadata);
                                                     }
-                                                    else
+
+                                                    if (add_method)
                                                     {
-                                                        
ignore_containing_context = true;
+                                                        // REMOVE THE CRASH 
DESCRIPTION BELOW
+                                                        
Host::SetCrashDescriptionWithFormat ("SymbolFileDWARF::ParseType() is adding a 
method %s to class %s in DIE 0x%8.8" PRIx64 " from %s",
+                                                                               
              type_name_cstr,
+                                                                               
              class_type->GetName().GetCString(),
+                                                                               
              die.GetID(),
+                                                                               
              dwarf->GetObjectFile()->GetFileSpec().GetPath().c_str());
+    
+                                                        const bool 
is_attr_used = false;
+                                                        // Neither GCC 4.2 nor 
clang++ currently set a valid accessibility
+                                                        // in the DWARF for 
C++ methods... Default to public for now...
+                                                        if (accessibility == 
eAccessNone)
+                                                            accessibility = 
eAccessPublic;
+    
+                                                        clang::CXXMethodDecl 
*cxx_method_decl;
+                                                        cxx_method_decl = 
m_ast.AddMethodToCXXRecordType (class_opaque_type.GetOpaqueQualType(),
+                                                                               
                           type_name_cstr,
+                                                                               
                           clang_type,
+                                                                               
                           accessibility,
+                                                                               
                           is_virtual,
+                                                                               
                           is_static,
+                                                                               
                           is_inline,
+                                                                               
                           is_explicit,
+                                                                               
                           is_attr_used,
+                                                                               
                           is_artificial);
+    
+                                                        type_handled = 
cxx_method_decl != NULL;
+    
+                                                        if (type_handled)
+                                                        {
+                                                            
LinkDeclContextToDIE(ClangASTContext::GetAsDeclContext(cxx_method_decl), die);
+    
+                                                            
Host::SetCrashDescription (NULL);
+    
+    
+                                                            ClangASTMetadata 
metadata;
+                                                            
metadata.SetUserID(die.GetID());
+    
+                                                            if 
(!object_pointer_name.empty())
+                                                            {
+                                                                
metadata.SetObjectPtrName(object_pointer_name.c_str());
+                                                                if (log)
+                                                                    
log->Printf ("Setting object pointer name: %s on method object %p.\n",
+                                                                               
  object_pointer_name.c_str(),
+                                                                               
  static_cast<void*>(cxx_method_decl));
+                                                            }
+                                                            m_ast.SetMetadata 
(cxx_method_decl, metadata);
+                                                        }
+                                                        else
+                                                        {
+                                                            
ignore_containing_context = true;
+                                                        }
                                                     }
                                                 }
                                             }

Added: lldb/trunk/test/lang/cpp/limit-debug-info/Makefile
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/cpp/limit-debug-info/Makefile?rev=249629&view=auto
==============================================================================
--- lldb/trunk/test/lang/cpp/limit-debug-info/Makefile (added)
+++ lldb/trunk/test/lang/cpp/limit-debug-info/Makefile Wed Oct  7 17:11:52 2015
@@ -0,0 +1,7 @@
+LEVEL = ../../../make
+
+CXX_SOURCES = main.cpp derived.cpp base.cpp
+
+CFLAGS_EXTRAS += $(LIMIT_DEBUG_INFO_FLAGS)
+
+include $(LEVEL)/Makefile.rules

Added: lldb/trunk/test/lang/cpp/limit-debug-info/TestWithLimitDebugInfo.py
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/cpp/limit-debug-info/TestWithLimitDebugInfo.py?rev=249629&view=auto
==============================================================================
--- lldb/trunk/test/lang/cpp/limit-debug-info/TestWithLimitDebugInfo.py (added)
+++ lldb/trunk/test/lang/cpp/limit-debug-info/TestWithLimitDebugInfo.py Wed Oct 
 7 17:11:52 2015
@@ -0,0 +1,48 @@
+import lldb
+from lldbtest import *
+import lldbutil
+
+class TestWithLimitDebugInfo(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    @dwarf_test
+    def test_with_dwarf(self):
+        self.buildDwarf()
+
+        cwd = os.getcwd()
+
+        src_file = os.path.join(cwd, "main.cpp")
+        src_file_spec = lldb.SBFileSpec(src_file)
+        self.assertTrue(src_file_spec.IsValid(), "breakpoint file")
+
+        # Get the path of the executable
+        exe_path  = os.path.join(cwd, 'a.out')
+
+        # Load the executable
+        target = self.dbg.CreateTarget(exe_path)
+        self.assertTrue(target.IsValid(), VALID_TARGET)
+
+        # Break on main function
+        breakpoint = target.BreakpointCreateBySourceRegex("break here", 
src_file_spec)
+        self.assertTrue(breakpoint.IsValid() and breakpoint.GetNumLocations() 
>= 1, VALID_BREAKPOINT)
+
+        # Launch the process
+        process = target.LaunchSimple(None, None, 
self.get_process_working_directory())
+        self.assertTrue(process.IsValid(), PROCESS_IS_VALID)
+
+        # Get the thread of the process
+        self.assertTrue(process.GetState() == lldb.eStateStopped, 
PROCESS_STOPPED)
+        thread = lldbutil.get_stopped_thread(process, 
lldb.eStopReasonBreakpoint)
+        thread.StepInto()
+
+        # Get frame for current thread
+        frame = thread.GetSelectedFrame()
+
+        v1 = frame.EvaluateExpression("1")
+        self.assertTrue(v1.IsValid(), "'expr 1' results in a valid SBValue 
object")
+        self.assertTrue(v1.GetError().Success(), "'expr 1' succeeds without an 
error.")
+
+        v2 = frame.EvaluateExpression("this")
+        self.assertTrue(v2.IsValid(), "'expr this' results in a valid SBValue 
object")
+        self.assertTrue(v2.GetError().Success(), "'expr this' succeeds without 
an error.")

Added: lldb/trunk/test/lang/cpp/limit-debug-info/base.cpp
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/cpp/limit-debug-info/base.cpp?rev=249629&view=auto
==============================================================================
--- lldb/trunk/test/lang/cpp/limit-debug-info/base.cpp (added)
+++ lldb/trunk/test/lang/cpp/limit-debug-info/base.cpp Wed Oct  7 17:11:52 2015
@@ -0,0 +1,6 @@
+#include "base.h"
+
+void FooNS::bar() {
+    x = 54321;
+}
+

Added: lldb/trunk/test/lang/cpp/limit-debug-info/base.h
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/cpp/limit-debug-info/base.h?rev=249629&view=auto
==============================================================================
--- lldb/trunk/test/lang/cpp/limit-debug-info/base.h (added)
+++ lldb/trunk/test/lang/cpp/limit-debug-info/base.h Wed Oct  7 17:11:52 2015
@@ -0,0 +1,10 @@
+class FooNS
+{
+public:
+    virtual void bar();
+    virtual char baz() = 0;
+
+protected:
+    int x;
+};
+

Added: lldb/trunk/test/lang/cpp/limit-debug-info/derived.cpp
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/cpp/limit-debug-info/derived.cpp?rev=249629&view=auto
==============================================================================
--- lldb/trunk/test/lang/cpp/limit-debug-info/derived.cpp (added)
+++ lldb/trunk/test/lang/cpp/limit-debug-info/derived.cpp Wed Oct  7 17:11:52 
2015
@@ -0,0 +1,6 @@
+#include "derived.h"
+
+char Foo::baz() {
+    return (char)(x&0xff);
+}
+

Added: lldb/trunk/test/lang/cpp/limit-debug-info/derived.h
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/cpp/limit-debug-info/derived.h?rev=249629&view=auto
==============================================================================
--- lldb/trunk/test/lang/cpp/limit-debug-info/derived.h (added)
+++ lldb/trunk/test/lang/cpp/limit-debug-info/derived.h Wed Oct  7 17:11:52 2015
@@ -0,0 +1,13 @@
+#include "base.h"
+
+class Foo : public FooNS
+{
+public:
+    Foo() {
+        a = 12345;
+    }
+
+    char baz() override;
+    int a;
+};
+

Added: lldb/trunk/test/lang/cpp/limit-debug-info/main.cpp
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/cpp/limit-debug-info/main.cpp?rev=249629&view=auto
==============================================================================
--- lldb/trunk/test/lang/cpp/limit-debug-info/main.cpp (added)
+++ lldb/trunk/test/lang/cpp/limit-debug-info/main.cpp Wed Oct  7 17:11:52 2015
@@ -0,0 +1,7 @@
+#include "derived.h"
+
+int main() {
+    Foo f; // break here
+    f.bar();
+    return f.baz();
+}

Modified: lldb/trunk/test/make/Makefile.rules
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/test/make/Makefile.rules?rev=249629&r1=249628&r2=249629&view=diff
==============================================================================
--- lldb/trunk/test/make/Makefile.rules (original)
+++ lldb/trunk/test/make/Makefile.rules Wed Oct  7 17:11:52 2015
@@ -170,6 +170,11 @@ else
        endif
 endif
 
+LIMIT_DEBUG_INFO_FLAGS =
+ifneq (,$(findstring clang,$(CC)))
+   LIMIT_DEBUG_INFO_FLAGS += -flimit-debug-info
+endif
+
 CFLAGS ?= -g -O0 -fno-builtin
 ifeq "$(OS)" "Darwin"
        CFLAGS += $(ARCHFLAG) $(ARCH) $(FRAMEWORK_INCLUDES) $(CFLAGS_EXTRAS) 
-I$(LLDB_BASE_DIR)include


_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to