Added template support when parsing DWARF into types. We can now use STL

classes in the expression parser.

llvm-svn: 142717
This commit is contained in:
Greg Clayton 2011-10-22 03:33:13 +00:00
parent 33ba99566f
commit f0705c8b90
7 changed files with 405 additions and 32 deletions

View File

@ -31,6 +31,8 @@ namespace clang
class AddrLabelExpr;
class AnalyzerOptions;
class BinaryOperator;
class ClassTemplateDecl;
class ClassTemplateSpecializationDecl;
class CodeGenOptions;
class CodeGenerator;
class CompilerInstance;

View File

@ -19,6 +19,8 @@
// Other libraries and framework includes
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallVector.h"
#include "clang/AST/TemplateBase.h"
// Project includes
#include "lldb/lldb-enumerations.h"
@ -55,7 +57,7 @@ public:
typedef void (*CompleteTagDeclCallback)(void *baton, clang::TagDecl *);
typedef void (*CompleteObjCInterfaceDeclCallback)(void *baton, clang::ObjCInterfaceDecl *);
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
@ -300,6 +302,44 @@ public:
is_explicit);
}
class TemplateParameterInfos
{
public:
bool
IsValid() const
{
if (args.empty())
return false;
return args.size() == names.size();
}
size_t
GetSize () const
{
if (IsValid())
return args.size();
return 0;
}
llvm::SmallVector<const char *, 8> names;
llvm::SmallVector<clang::TemplateArgument, 8> args;
};
clang::ClassTemplateDecl *
CreateClassTemplateDecl (clang::DeclContext *decl_ctx,
const char *class_name,
int kind,
const TemplateParameterInfos &infos);
clang::ClassTemplateSpecializationDecl *
CreateClassTemplateSpecializationDecl (clang::DeclContext *decl_ctx,
clang::ClassTemplateDecl *class_template_decl,
int kind,
const TemplateParameterInfos &infos);
lldb::clang_type_t
CreateClassTemplateSpecializationType (clang::ClassTemplateSpecializationDecl *class_template_specialization_decl);
static clang::DeclContext *
GetAsDeclContext (clang::CXXMethodDecl *cxx_method_decl);

View File

@ -224,16 +224,41 @@ IRForTarget::GetFunctionAddress (llvm::Function *fun,
{
if (!m_decl_map->GetFunctionInfo (fun_decl, fun_value_ptr, fun_addr))
{
fun_value_ptr = NULL;
if (!m_decl_map->GetFunctionAddress (name, fun_addr))
lldb_private::ConstString alternate_mangling_const_str;
bool found_it = m_decl_map->GetFunctionAddress (name, fun_addr);
if (!found_it)
{
// Check for an alternate mangling for "std::basic_string<char>"
// that is part of the itanium C++ name mangling scheme
const char *name_cstr = name.GetCString();
if (strncmp(name_cstr, "_ZNKSbIcE", strlen("_ZNKSbIcE")) == 0)
{
std::string alternate_mangling("_ZNKSs");
alternate_mangling.append (name_cstr + strlen("_ZNKSbIcE"));
alternate_mangling_const_str.SetCString(alternate_mangling.c_str());
found_it = m_decl_map->GetFunctionAddress (alternate_mangling_const_str, fun_addr);
}
}
if (!found_it)
{
fun_value_ptr = NULL;
if (log)
log->Printf("Function \"%s\" had no address", name.GetCString());
{
if (alternate_mangling_const_str)
log->Printf("Function \"%s\" (alternate name \"%s\") has no address", name.GetCString(), alternate_mangling_const_str.GetCString());
else
log->Printf("Function \"%s\" had no address", name.GetCString());
}
if (m_error_stream)
m_error_stream->Printf("Error [IRForTarget]: Call to a function '%s' that is not present in the target\n", name.GetCString());
{
if (alternate_mangling_const_str)
m_error_stream->Printf("error: call to a function '%s' (alternate name '%s') that is not present in the target\n", name.GetCString(), alternate_mangling_const_str.GetCString());
else
m_error_stream->Printf("error: call to a function '%s' that is not present in the target\n", name.GetCString());
}
return false;
}
}

View File

@ -1133,6 +1133,128 @@ SymbolFileDWARF::ParseFunctionBlocks
return blocks_added;
}
bool
SymbolFileDWARF::ParseTemplateParameterInfos (DWARFCompileUnit* dwarf_cu,
const DWARFDebugInfoEntry *parent_die,
ClangASTContext::TemplateParameterInfos &template_param_infos)
{
if (parent_die == NULL)
return NULL;
const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize());
Args template_parameter_names;
for (const DWARFDebugInfoEntry *die = parent_die->GetFirstChild();
die != NULL;
die = die->GetSibling())
{
const dw_tag_t tag = die->Tag();
switch (tag)
{
case DW_TAG_template_type_parameter:
case DW_TAG_template_value_parameter:
{
DWARFDebugInfoEntry::Attributes attributes;
const size_t num_attributes = die->GetAttributes (this,
dwarf_cu,
fixed_form_sizes,
attributes);
const char *name = NULL;
Type *lldb_type = NULL;
clang_type_t clang_type = NULL;
uint64_t uval64 = 0;
bool uval64_valid = false;
if (num_attributes > 0)
{
DWARFFormValue form_value;
for (size_t i=0; i<num_attributes; ++i)
{
const dw_attr_t attr = attributes.AttributeAtIndex(i);
switch (attr)
{
case DW_AT_name:
if (attributes.ExtractFormValueAtIndex(this, i, form_value))
name = form_value.AsCString(&get_debug_str_data());
break;
case DW_AT_type:
if (attributes.ExtractFormValueAtIndex(this, i, form_value))
{
const dw_offset_t type_die_offset = form_value.Reference(dwarf_cu);
lldb_type = ResolveTypeUID(type_die_offset);
if (lldb_type)
clang_type = lldb_type->GetClangForwardType();
}
break;
case DW_AT_const_value:
if (attributes.ExtractFormValueAtIndex(this, i, form_value))
{
uval64_valid = true;
uval64 = form_value.Unsigned();
}
break;
default:
break;
}
}
if (name && lldb_type && clang_type)
{
bool is_signed = false;
template_param_infos.names.push_back(name);
clang::QualType clang_qual_type (clang::QualType::getFromOpaquePtr (clang_type));
if (tag == DW_TAG_template_value_parameter && ClangASTContext::IsIntegerType (clang_type, is_signed) && uval64_valid)
{
llvm::APInt apint (lldb_type->GetByteSize() * 8, uval64, is_signed);
template_param_infos.args.push_back (clang::TemplateArgument (llvm::APSInt(apint), clang_qual_type));
}
else
{
template_param_infos.args.push_back (clang::TemplateArgument (clang_qual_type));
}
}
else
{
return false;
}
}
}
break;
default:
break;
}
}
if (template_param_infos.args.empty())
return false;
return template_param_infos.args.size() == template_param_infos.names.size();
}
clang::ClassTemplateDecl *
SymbolFileDWARF::ParseClassTemplateDecl (clang::DeclContext *decl_ctx,
const char *parent_name,
int tag_decl_kind,
const ClangASTContext::TemplateParameterInfos &template_param_infos)
{
if (template_param_infos.IsValid())
{
std::string template_basename(parent_name);
template_basename.erase (template_basename.find('<'));
ClangASTContext &ast = GetClangASTContext();
return ast.CreateClassTemplateDecl (decl_ctx,
template_basename.c_str(),
tag_decl_kind,
template_param_infos);
}
return NULL;
}
size_t
SymbolFileDWARF::ParseChildMembers
(
@ -2342,16 +2464,16 @@ SymbolFileDWARF::FunctionDieMatchesPartialName (const DWARFDebugInfoEntry* die,
if (name_type_mask == eFunctionNameTypeMethod
|| name_type_mask == eFunctionNameTypeBase)
{
clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIEOffset(die->GetOffset());
if (!containing_decl_ctx)
return false;
bool is_cxx_method = (containing_decl_ctx->getDeclKind() == clang::Decl::CXXRecord);
if (!is_cxx_method && name_type_mask == eFunctionNameTypeMethod)
return false;
if (is_cxx_method && name_type_mask == eFunctionNameTypeBase)
return false;
clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIEOffset(die->GetOffset());
if (!containing_decl_ctx)
return false;
bool is_cxx_method = DeclKindIsCXXClass(containing_decl_ctx->getDeclKind());
if (!is_cxx_method && name_type_mask == eFunctionNameTypeMethod)
return false;
if (is_cxx_method && name_type_mask == eFunctionNameTypeBase)
return false;
}
// Now we need to check whether the name we got back for this type matches the extra specifications
@ -2989,7 +3111,7 @@ SymbolFileDWARF::ParseChildParameters (const SymbolContext& sc,
// Ugly, but that
if (arg_idx == 0)
{
if (containing_decl_ctx->getDeclKind() == clang::Decl::CXXRecord)
if (DeclKindIsCXXClass(containing_decl_ctx->getDeclKind()))
{
// Often times compilers omit the "this" name for the
// specification DIEs, so we can't rely upon the name
@ -3900,11 +4022,34 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
clang_type = m_forward_decl_die_to_clang_type.lookup (die);
if (clang_type == NULL)
{
clang_type_was_created = true;
clang_type = ast.CreateRecordType (type_name_cstr,
tag_decl_kind,
GetClangDeclContextContainingDIE (dwarf_cu, die, NULL),
class_language);
clang::DeclContext *decl_ctx = GetClangDeclContextContainingDIE (dwarf_cu, die, NULL);
if (type_name_cstr && strchr (type_name_cstr, '<'))
{
ClangASTContext::TemplateParameterInfos template_param_infos;
if (ParseTemplateParameterInfos (dwarf_cu, die, template_param_infos))
{
clang::ClassTemplateDecl *class_template_decl = ParseClassTemplateDecl (decl_ctx,
type_name_cstr,
tag_decl_kind,
template_param_infos);
clang::ClassTemplateSpecializationDecl *class_specialization_decl = ast.CreateClassTemplateSpecializationDecl (decl_ctx,
class_template_decl,
tag_decl_kind,
template_param_infos);
clang_type = ast.CreateClassTemplateSpecializationType (class_specialization_decl);
clang_type_was_created = true;
}
}
if (!clang_type_was_created)
{
clang_type_was_created = true;
clang_type = ast.CreateRecordType (type_name_cstr,
tag_decl_kind,
decl_ctx,
class_language);
}
}
// Store a forward declaration to this class type in case any
@ -4167,7 +4312,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIE (dwarf_cu, die, &decl_ctx_die);
const clang::Decl::Kind containing_decl_kind = containing_decl_ctx->getDeclKind();
const bool is_cxx_method = containing_decl_kind == clang::Decl::CXXRecord;
const bool is_cxx_method = DeclKindIsCXXClass (containing_decl_kind);
// Start off static. This will be set to false in ParseChildParameters(...)
// if we find a "this" paramters as the first parameter
if (is_cxx_method)

View File

@ -28,6 +28,7 @@
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Flags.h"
#include "lldb/Core/UniqueCStringMap.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/SymbolContext.h"
@ -58,7 +59,7 @@ class SymbolFileDWARFDebugMap;
class SymbolFileDWARF : public lldb_private::SymbolFile, public lldb_private::UserID
{
public:
friend class SymbolFileDWARFDebugMap;
friend class SymbolFileDWARFDebugMap;
//------------------------------------------------------------------
// Static Functions
@ -426,6 +427,32 @@ protected:
return GetID() | die_offset;
}
static bool
DeclKindIsCXXClass (clang::Decl::Kind decl_kind)
{
switch (decl_kind)
{
case clang::Decl::CXXRecord:
case clang::Decl::ClassTemplateSpecialization:
return true;
default:
break;
}
return false;
}
bool
ParseTemplateParameterInfos (DWARFCompileUnit* dwarf_cu,
const DWARFDebugInfoEntry *parent_die,
lldb_private::ClangASTContext::TemplateParameterInfos &template_param_infos);
clang::ClassTemplateDecl *
ParseClassTemplateDecl (clang::DeclContext *decl_ctx,
const char *parent_name,
int tag_decl_kind,
const lldb_private::ClangASTContext::TemplateParameterInfos &template_param_infos);
void
ReportError (const char *format, ...) __attribute__ ((format (printf, 2, 3)));
void

View File

@ -36,6 +36,7 @@
#include "clang/AST/ASTImporter.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/Type.h"
#include "clang/Basic/Builtins.h"
@ -58,6 +59,8 @@
#include "lldb/Core/dwarf.h"
#include "lldb/Core/Flags.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/RegularExpression.h"
#include "lldb/Expression/ASTDumper.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
@ -1085,16 +1088,138 @@ ClangASTContext::CreateRecordType (const char *name, int kind, DeclContext *decl
// the CXXRecordDecl class since we often don't know from debug information
// if something is struct or a class, so we default to always use the more
// complete definition just in case.
CXXRecordDecl *decl = CXXRecordDecl::Create(*ast,
(TagDecl::TagKind)kind,
decl_ctx,
SourceLocation(),
SourceLocation(),
name && name[0] ? &ast->Idents.get(name) : NULL);
CXXRecordDecl *decl = CXXRecordDecl::Create (*ast,
(TagDecl::TagKind)kind,
decl_ctx,
SourceLocation(),
SourceLocation(),
name && name[0] ? &ast->Idents.get(name) : NULL);
return ast->getTagDeclType(decl).getAsOpaquePtr();
}
ClassTemplateDecl *
ClangASTContext::CreateClassTemplateDecl (DeclContext *decl_ctx,
const char *class_name,
int kind,
const TemplateParameterInfos &template_param_infos)
{
ASTContext *ast = getASTContext();
ClassTemplateDecl *class_template_decl = NULL;
if (decl_ctx == NULL)
decl_ctx = ast->getTranslationUnitDecl();
IdentifierInfo &identifier_info = ast->Idents.get(class_name);
DeclarationName decl_name (&identifier_info);
clang::DeclContext::lookup_result result = decl_ctx->lookup(decl_name);
for (clang::DeclContext::lookup_iterator pos = result.first, end = result.second; pos != end; ++pos)
{
class_template_decl = dyn_cast<clang::ClassTemplateDecl>(*pos);
if (class_template_decl)
return class_template_decl;
}
llvm::SmallVector<NamedDecl *, 8> template_param_decls;
const bool parameter_pack = false;
const bool is_typename = false;
const unsigned depth = 0;
const size_t num_template_params = template_param_infos.GetSize();
for (size_t i=0; i<num_template_params; ++i)
{
const char *name = template_param_infos.names[i];
if (template_param_infos.args[i].getAsIntegral())
{
template_param_decls.push_back (NonTypeTemplateParmDecl::Create (*ast,
ast->getTranslationUnitDecl(), // Is this the right decl context?, SourceLocation StartLoc,
SourceLocation(),
SourceLocation(),
depth,
i,
&ast->Idents.get(name),
template_param_infos.args[i].getAsType(),
parameter_pack,
NULL));
}
else
{
template_param_decls.push_back (TemplateTypeParmDecl::Create (*ast,
ast->getTranslationUnitDecl(), // Is this the right decl context?
SourceLocation(),
SourceLocation(),
depth,
i,
&ast->Idents.get(name),
is_typename,
parameter_pack));
}
}
TemplateParameterList *template_param_list = TemplateParameterList::Create (*ast,
SourceLocation(),
SourceLocation(),
&template_param_decls.front(),
template_param_decls.size(),
SourceLocation());
CXXRecordDecl *template_cxx_decl = CXXRecordDecl::Create (*ast,
(TagDecl::TagKind)kind,
decl_ctx, // What decl context do we use here? TU? The actual decl context?
SourceLocation(),
SourceLocation(),
&identifier_info);
class_template_decl = ClassTemplateDecl::Create (*ast,
decl_ctx, // What decl context do we use here? TU? The actual decl context?
SourceLocation(),
decl_name,
template_param_list,
template_cxx_decl,
NULL);
if (class_template_decl)
decl_ctx->addDecl (class_template_decl);
return class_template_decl;
}
ClassTemplateSpecializationDecl *
ClangASTContext::CreateClassTemplateSpecializationDecl (DeclContext *decl_ctx,
ClassTemplateDecl *class_template_decl,
int kind,
const TemplateParameterInfos &template_param_infos)
{
ASTContext *ast = getASTContext();
ClassTemplateSpecializationDecl *class_template_specialization_decl = ClassTemplateSpecializationDecl::Create (*ast,
(TagDecl::TagKind)kind,
decl_ctx,
SourceLocation(),
SourceLocation(),
class_template_decl,
&template_param_infos.args.front(),
template_param_infos.args.size(),
NULL);
return class_template_specialization_decl;
}
lldb::clang_type_t
ClangASTContext::CreateClassTemplateSpecializationType (ClassTemplateSpecializationDecl *class_template_specialization_decl)
{
if (class_template_specialization_decl)
{
ASTContext *ast = getASTContext();
if (ast)
return ast->getTagDeclType(class_template_specialization_decl).getAsOpaquePtr();
}
return NULL;
}
bool
ClangASTContext::SetHasExternalStorage (clang_type_t clang_type, bool has_extern)
{
@ -2842,6 +2967,8 @@ ClangASTContext::GetNumPointeeChildren (clang_type_t clang_type)
case clang::BuiltinType::ObjCClass:
case clang::BuiltinType::ObjCSel:
case clang::BuiltinType::BoundMember:
case clang::BuiltinType::Half:
case clang::BuiltinType::ARCUnbridgedCast:
return 1;
}
break;
@ -4615,6 +4742,8 @@ ClangASTContext::IsPossibleDynamicType (clang::ASTContext *ast, clang_type_t cla
case clang::BuiltinType::ObjCClass:
case clang::BuiltinType::ObjCSel:
case clang::BuiltinType::BoundMember:
case clang::BuiltinType::Half:
case clang::BuiltinType::ARCUnbridgedCast:
break;
}
break;
@ -4748,6 +4877,8 @@ ClangASTContext::IsPossibleCPlusPlusDynamicType (clang::ASTContext *ast, clang_t
case clang::BuiltinType::ObjCClass:
case clang::BuiltinType::ObjCSel:
case clang::BuiltinType::BoundMember:
case clang::BuiltinType::Half:
case clang::BuiltinType::ARCUnbridgedCast:
break;
}
break;

View File

@ -569,7 +569,10 @@ ClangASTType::GetFormat (clang_type_t clang_type)
case clang::BuiltinType::Dependent:
case clang::BuiltinType::ObjCId:
case clang::BuiltinType::ObjCClass:
case clang::BuiltinType::ObjCSel: return lldb::eFormatHex;
case clang::BuiltinType::ObjCSel:
case clang::BuiltinType::Half:
case clang::BuiltinType::ARCUnbridgedCast:
return lldb::eFormatHex;
}
break;
case clang::Type::ObjCObjectPointer: return lldb::eFormatHex;