Author: gclayton
Date: Tue Feb 9 16:36:24 2016
New Revision: 260308
URL: http://llvm.org/viewvc/llvm-project?rev=260308&view=rev
Log:
Fixed many issues that were causing differing type definition issues to show up
when parsing expressions.
1) Turns out we weren't correctly uniquing types for C++. We would search our
repository for "lldb_private::Process", but yet store just "Process" in the
unique type map. Now we store things correctly and correctly unique types.
2) SymbolFileDWARF::CompleteType() can be called at any time in order to
complete a C++ or Objective C class. All public inquiries into the SymbolFile
go through SymbolVendor, and SymbolVendor correctly takes the module lock
before it call the SymbolFile API call, but when we let CompilerType objects
out in the wild, they can complete themselves at any time from the expression
parser, so the ValueObjects or (SBValue objects in the public API), and many
more places. So we now take the module lock when completing a type to avoid two
threads being in the SymbolFileDWARF at the same time.
3) If a class has a template member function like:
class A
{
<template T>
void Foo(T t);
};
The DWARF will _only_ contain a DW_TAG_subprogram for "Foo" if anyone
specialized it. This would cause a class definition for A inside a.cpp that
used a "int" and "float" overload to look like:
class A
{
void Foo(int t);
void Foo(double t);
};
And a version from b.cpp that used a "float" overload to look like:
class A
{
void Foo(float t);
};
And a version from c.cpp that use no overloads to look like:
class A
{
};
Then in an expression if you have two variables, one name "a" from a.cpp in
liba.dylib, and one named "b" from b.cpp in libb.dylib, you will get
conflicting definitions for "A" and your expression will fail. This all stems
from the fact that DWARF _only_ emits template specializations, not generic
definitions, and they are only emitted if they are used. There are two
solutions to this:
a) When ever you run into ANY class, you must say "just because this class
doesn't have templatized member functions, it doesn't mean that any other
instances might not have any, so when ever I run into ANY class, I must parse
all compile units and parse all instances of class "A" just in case it has
member functions that are templatized.". That is really bad because it means
you always pull in ALL DWARF that contains most likely exact duplicate
definitions of the class "A" and you bloat the memory that the SymbolFileDWARF
plug-in uses in LLDB (since you pull in all DIEs from all compile units that
contain a "A" definition) uses for little value most of the time.
b) Modify DWARF to emit generic template member function definitions so
that you know from looking at any instance of class "A" wether it has template
member functions or not. In order to do this, we would have to have the ability
to correctly parse a member function template, but there is a compiler bug:
<rdar://problem/24515533> [PR 26553] C++ Debug info should reference
DW_TAG_template_type_parameter
This bugs means that not all of the info needed to correctly make a
template member function is in the DWARF. The main source of the problem is if
we have DWARF for a template instantiation for "int" like: "void
A::Foo<int>(T)" the DWARF comes out as "void A::Foo<int>(int)" (it doesn't
mention type "T", it resolves the type to the specialized type to "int"). But
if you actually have your function defined as "<template T> void Foo(int t)"
and you only use T for local variables inside the function call, we can't
correctly make the function prototype up in the clang::ASTContext.
So the best we can do for now we just omit all member functions that are
templatized from the class definition so that "A" never has any template member
functions. This means all defintions of "A" look like:
class A
{
};
And our expressions will work. You won't be able to call template member
fucntions in expressions (not a regression, we weren't able to do this before)
and if you are stopped in a templatized member function, we won't know that are
are in a method of class "A". All things we should fix, but we need
<rdar://problem/24515533> fixed first, followed by:
<rdar://problem/24515624> Classes should always include a template
subprogram definition, even when no template member functions are used
before we can do anything about it in LLDB.
This bug mainly fixed the following Apple radar:
<rdar://problem/24483905>
Modified:
lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
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=260308&r1=260307&r2=260308&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
(original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp Tue Feb
9 16:36:24 2016
@@ -555,43 +555,32 @@ DWARFASTParserClang::ParseTypeFromDWARF
// and clang isn't good and sharing the stack space for
variables in different blocks.
std::unique_ptr<UniqueDWARFASTType>
unique_ast_entry_ap(new UniqueDWARFASTType());
+ ConstString unique_typename(type_name_const_str);
+ Declaration unique_decl(decl);
+
if (type_name_const_str)
{
LanguageType die_language = die.GetLanguage();
- bool handled = false;
if (Language::LanguageIsCPlusPlus(die_language))
{
+ // For C++, we rely solely upon the one definition
rule that says only
+ // one thing can exist at a given decl context. We
ignore the file and
+ // line that things are declared on.
std::string qualified_name;
if (die.GetQualifiedName(qualified_name))
- {
- handled = true;
- ConstString
const_qualified_name(qualified_name);
- if
(dwarf->GetUniqueDWARFASTTypeMap().Find(const_qualified_name, die,
Declaration(),
-
byte_size_valid ? byte_size : -1,
-
*unique_ast_entry_ap))
- {
- type_sp = unique_ast_entry_ap->m_type_sp;
- if (type_sp)
- {
- dwarf->GetDIEToType()[die.GetDIE()] =
type_sp.get();
- return type_sp;
- }
- }
- }
+ unique_typename = ConstString(qualified_name);
+ unique_decl.Clear();
}
- if (!handled)
+ if
(dwarf->GetUniqueDWARFASTTypeMap().Find(unique_typename, die, unique_decl,
+
byte_size_valid ? byte_size : -1,
+
*unique_ast_entry_ap))
{
- if
(dwarf->GetUniqueDWARFASTTypeMap().Find(type_name_const_str, die, decl,
-
byte_size_valid ? byte_size : -1,
-
*unique_ast_entry_ap))
+ type_sp = unique_ast_entry_ap->m_type_sp;
+ if (type_sp)
{
- type_sp = unique_ast_entry_ap->m_type_sp;
- if (type_sp)
- {
- dwarf->GetDIEToType()[die.GetDIE()] =
type_sp.get();
- return type_sp;
- }
+ dwarf->GetDIEToType()[die.GetDIE()] =
type_sp.get();
+ return type_sp;
}
}
}
@@ -822,9 +811,9 @@ DWARFASTParserClang::ParseTypeFromDWARF
// and over in the ASTContext for our module
unique_ast_entry_ap->m_type_sp = type_sp;
unique_ast_entry_ap->m_die = die;
- unique_ast_entry_ap->m_declaration = decl;
+ unique_ast_entry_ap->m_declaration = unique_decl;
unique_ast_entry_ap->m_byte_size = byte_size;
- dwarf->GetUniqueDWARFASTTypeMap().Insert
(type_name_const_str,
+ dwarf->GetUniqueDWARFASTTypeMap().Insert (unique_typename,
*unique_ast_entry_ap);
if (is_forward_declaration && die.HasChildren())
@@ -1069,6 +1058,7 @@ DWARFASTParserClang::ParseTypeFromDWARF
bool is_virtual = false;
bool is_explicit = false;
bool is_artificial = false;
+ bool has_template_params = false;
DWARFFormValue specification_die_form;
DWARFFormValue abstract_origin_die_form;
dw_offset_t object_pointer_die_offset = DW_INVALID_OFFSET;
@@ -1193,11 +1183,13 @@ DWARFASTParserClang::ParseTypeFromDWARF
clang::DeclContext *containing_decl_ctx =
GetClangDeclContextContainingDIE (die, &decl_ctx_die);
const clang::Decl::Kind containing_decl_kind =
containing_decl_ctx->getDeclKind();
- const bool is_cxx_method = DeclKindIsCXXClass
(containing_decl_kind);
+ bool is_cxx_method = DeclKindIsCXXClass
(containing_decl_kind);
// Start off static. This will be set to false in
ParseChildParameters(...)
// if we find a "this" parameters as the first parameter
if (is_cxx_method)
+ {
is_static = true;
+ }
if (die.HasChildren())
{
@@ -1208,11 +1200,26 @@ DWARFASTParserClang::ParseTypeFromDWARF
skip_artificial,
is_static,
is_variadic,
+ has_template_params,
function_param_types,
function_param_decls,
type_quals);
}
+ bool ignore_containing_context = false;
+ // Check for templatized class member functions. If we had
any DW_TAG_template_type_parameter
+ // or DW_TAG_template_value_parameter the
DW_TAG_subprogram DIE, then we can't let this become
+ // a method in a class. Why? Because templatized functions
are only emitted if one of the
+ // templatized methods is used in the current compile unit
and we will end up with classes
+ // that may or may not include these member functions and
this means one class won't match another
+ // class definition and it affects our ability to use a
class in the clang expression parser. So
+ // for the greater good, we currently must not allow any
template member functions in a class definition.
+// if (is_cxx_method && has_template_params)
+// {
+// ignore_containing_context = true;
+// is_cxx_method = false;
+// }
+
// clang_type will get the function prototype clang type
after this call
clang_type = m_ast.CreateFunctionType (return_clang_type,
function_param_types.data(),
@@ -1220,7 +1227,6 @@ DWARFASTParserClang::ParseTypeFromDWARF
is_variadic,
type_quals);
- bool ignore_containing_context = false;
if (type_name_cstr)
{
@@ -1980,6 +1986,10 @@ DWARFASTParserClang::CompleteTypeFromDWA
lldb_private::Type *type,
CompilerType &clang_type)
{
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+
+ lldb_private::Mutex::Locker
locker(dwarf->GetObjectFile()->GetModule()->GetMutex());
+
// Disable external storage for this type so we don't get anymore
// clang::ExternalASTSource queries for this type.
m_ast.SetHasExternalStorage (clang_type.GetOpaqueQualType(), false);
@@ -1989,8 +1999,6 @@ DWARFASTParserClang::CompleteTypeFromDWA
const dw_tag_t tag = die.Tag();
- SymbolFileDWARF *dwarf = die.GetDWARF();
-
Log *log = nullptr; //
(LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO|DWARF_LOG_TYPE_COMPLETION));
if (log)
dwarf->GetObjectFile()->GetModule()->LogMessageVerboseBacktrace (log,
@@ -2507,6 +2515,7 @@ DWARFASTParserClang::ParseFunctionFromDW
// never mangled.
bool is_static = false;
bool is_variadic = false;
+ bool has_template_params = false;
unsigned type_quals = 0;
std::vector<CompilerType> param_types;
std::vector<clang::ParmVarDecl*> param_decls;
@@ -2523,6 +2532,7 @@ DWARFASTParserClang::ParseFunctionFromDW
true,
is_static,
is_variadic,
+ has_template_params,
param_types,
param_decls,
type_quals);
@@ -3189,6 +3199,7 @@ DWARFASTParserClang::ParseChildParameter
bool skip_artificial,
bool &is_static,
bool &is_variadic,
+ bool &has_template_params,
std::vector<CompilerType>&
function_param_types,
std::vector<clang::ParmVarDecl*>&
function_param_decls,
unsigned &type_quals)
@@ -3347,6 +3358,7 @@ DWARFASTParserClang::ParseChildParameter
// in SymbolFileDWARF::ParseType() so this was removed. If we
ever need
// the template params back, we can add them back.
// ParseTemplateDIE (dwarf_cu, die, template_param_infos);
+ has_template_params = true;
break;
default:
Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
URL:
http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h?rev=260308&r1=260307&r2=260308&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h Tue Feb 9
16:36:24 2016
@@ -133,6 +133,7 @@ protected:
bool skip_artificial,
bool &is_static,
bool &is_variadic,
+ bool &has_template_params,
std::vector<lldb_private::CompilerType>&
function_args,
std::vector<clang::ParmVarDecl*>&
function_param_decls,
unsigned &type_quals);
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=260308&r1=260307&r2=260308&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp Tue Feb 9
16:36:24 2016
@@ -1623,6 +1623,8 @@ SymbolFileDWARF::HasForwardDeclForClangT
bool
SymbolFileDWARF::CompleteType (CompilerType &compiler_type)
{
+ lldb_private::Mutex::Locker
locker(GetObjectFile()->GetModule()->GetMutex());
+
TypeSystem *type_system = compiler_type.GetTypeSystem();
if (type_system)
{
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits