Fixed a case where we might end up trying to parse a type in the DWARF parser for a method whose class isn't currently in the process of completing itself. Currently, methods of a class, must be parsed when the class type that contains the method is asked to complete itself through the clang::ExternalASTSource virtual functions. Now we "do the right thing" by checking if the class is being defined, and if so we parse it, else we tell the class to complete itself so everything happens correctly.

llvm-svn: 141908
This commit is contained in:
Greg Clayton 2011-10-13 23:13:20 +00:00
parent 0084615924
commit 20568dd981
4 changed files with 74 additions and 26 deletions

View File

@ -721,6 +721,9 @@ public:
static bool
IsCXXClassType (lldb::clang_type_t clang_type);
static bool
IsBeingDefined (lldb::clang_type_t clang_type);
static bool
IsObjCClassType (lldb::clang_type_t clang_type);

View File

@ -658,11 +658,6 @@ public:
target,
variable_list,
valobj_list));
// matches = target->GetImages().FindGlobalVariables (ConstString(arg),
// true,
// UINT32_MAX,
// variable_list);
matches = variable_list.GetSize();
}

View File

@ -34,6 +34,8 @@
#include "lldb/Core/Timer.h"
#include "lldb/Core/Value.h"
#include "lldb/Host/Host.h"
#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/ClangExternalASTSourceCallbacks.h"
#include "lldb/Symbol/CompileUnit.h"
@ -4275,32 +4277,67 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
clang_type_t class_opaque_type = class_type->GetClangForwardType();
if (ClangASTContext::IsCXXClassType (class_opaque_type))
{
// 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())
if (ClangASTContext::IsBeingDefined (class_opaque_type))
{
// We have a C++ member function with no children (this pointer!)
// and clang will get mad if we try and make a function that isn't
// well formed in the DWARF, so we will just skip it...
type_handled = true;
// 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!)
// and clang will get mad if we try and make a function that isn't
// well formed in the DWARF, so we will just skip it...
type_handled = true;
}
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.8x from %s/%s",
type_name_cstr,
class_type->GetName().GetCString(),
die->GetOffset(),
m_obj_file->GetFileSpec().GetDirectory().GetCString(),
m_obj_file->GetFileSpec().GetFilename().GetCString());
cxx_method_decl = ast.AddMethodToCXXRecordType (class_opaque_type,
type_name_cstr,
clang_type,
accessibility,
is_virtual,
is_static,
is_inline,
is_explicit);
LinkDeclContextToDIE(ClangASTContext::GetAsDeclContext(cxx_method_decl), die);
type_handled = cxx_method_decl != NULL;
}
}
else
{
clang::CXXMethodDecl *cxx_method_decl;
cxx_method_decl = ast.AddMethodToCXXRecordType (class_opaque_type,
type_name_cstr,
clang_type,
accessibility,
is_virtual,
is_static,
is_inline,
is_explicit);
LinkDeclContextToDIE(ClangASTContext::GetAsDeclContext(cxx_method_decl), die);
// We were asked to parse the type for a method in a class, yet the
// class hasn't been asked to complete itself through the
// clang::ExternalASTSource protocol, so we need to just have the
// class complete itself and do things the right way, then our
// DIE should then have an entry in the m_die_to_type map. First
// we need to modify the m_die_to_type so it doesn't think we are
// trying to parse this DIE anymore...
m_die_to_type[die] = NULL;
// Now we get the full type to force our class type to complete itself
// using the clang::ExternalASTSource protocol which will parse all
// base classes and all methods (including the method for this DIE).
class_type->GetClangFullType();
type_handled = cxx_method_decl != NULL;
// The type for this DIE should have been filled in the function call above
type_ptr = m_die_to_type[die];
if (type_ptr)
{
type_sp = type_list->FindType(type_ptr->GetID());
break;
}
}
}
}

View File

@ -4998,6 +4998,19 @@ ClangASTContext::IsCXXClassType (clang_type_t clang_type)
return false;
}
bool
ClangASTContext::IsBeingDefined (lldb::clang_type_t clang_type)
{
if (clang_type)
{
QualType qual_type (QualType::getFromOpaquePtr(clang_type));
const clang::TagType *tag_type = dyn_cast<clang::TagType>(qual_type);
if (tag_type)
return tag_type->isBeingDefined();
}
return false;
}
bool
ClangASTContext::IsObjCClassType (clang_type_t clang_type)
{