Modified the expression parser's class wrapper to

support reporting "this" as a templated class.  The
expression parser wraps expressions in C++ methods
as methods with the signature

$__lldb_class::$__lldb_expr(...)

and previously responded to clang's queries about
$__lldb_class with the type of *this.  This didn't
work if *this was a ClassTemplateSpecializationDecl
because ClassTemplateSpecializationDecls can't be
the result of simple name queries.

Instead what we do now is respond that $__lldb_class
is a typedef and that the target of the typedef is
the (potentially templated) type of *this.  That is
much more robust.

Thanks to John McCall for key insights.

<rdar://problem/10987183>

llvm-svn: 174153
This commit is contained in:
Sean Callanan 2013-02-01 06:55:48 +00:00
parent 1d584029ae
commit fa4fab77d4
4 changed files with 86 additions and 36 deletions

View File

@ -1017,16 +1017,23 @@ private:
///
/// @param[in] type
/// The type that needs to be created.
///
/// @param[in] add_method
/// True if a method with signature void $__lldb_expr(void*)
/// should be added to the C++ class type passed in
//------------------------------------------------------------------
void
AddOneType (NameSearchContext &context,
TypeFromUser &type,
unsigned int current_id,
bool add_method);
unsigned int current_id);
//------------------------------------------------------------------
/// Copy a C++ class type into the parser's AST context and add a
/// member function declaration to it for the expression.
///
/// @param[in] type
/// The type that needs to be created.
//------------------------------------------------------------------
TypeFromParser
CopyClassType(TypeFromUser &type,
unsigned int current_id);
//------------------------------------------------------------------
/// Actually do the task of materializing or dematerializing the struct.

View File

@ -2650,7 +2650,6 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
if (method_decl)
{
clang::CXXRecordDecl *class_decl = method_decl->getParent();
QualType class_qual_type(class_decl->getTypeForDecl(), 0);
@ -2664,7 +2663,28 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
log->Printf(" CEDM::FEVD[%u] Adding type for $__lldb_class: %s", current_id, ast_dumper.GetCString());
}
AddOneType(context, class_user_type, current_id, true);
TypeFromParser class_type = CopyClassType(class_user_type, current_id);
if (!class_type.IsValid())
return;
TypeSourceInfo *type_source_info = m_ast_context->CreateTypeSourceInfo(QualType::getFromOpaquePtr(class_type.GetOpaqueQualType()));
if (!type_source_info)
return;
TypedefDecl *typedef_decl = TypedefDecl::Create(*m_ast_context,
m_ast_context->getTranslationUnitDecl(),
SourceLocation(),
SourceLocation(),
context.m_decl_name.getAsIdentifierInfo(),
type_source_info);
if (!typedef_decl)
return;
context.AddNamedDecl(typedef_decl);
if (method_decl->isInstance())
{
@ -2715,7 +2735,7 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
TypeFromUser class_user_type (class_type.getAsOpaquePtr(),
this_type->GetClangAST());
AddOneType(context, class_user_type, current_id, false);
AddOneType(context, class_user_type, current_id);
TypeFromUser this_user_type(this_type->GetClangFullType(),
@ -2774,7 +2794,7 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
log->Printf(" FEVD[%u] Adding type for $__lldb_objc_class: %s", current_id, ast_dumper.GetCString());
}
AddOneType(context, class_user_type, current_id, false);
AddOneType(context, class_user_type, current_id);
if (method_decl->isInstanceMethod())
{
@ -2841,7 +2861,7 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
TypeFromUser class_user_type (class_type.getAsOpaquePtr(),
self_type->GetClangAST());
AddOneType(context, class_user_type, current_id, false);
AddOneType(context, class_user_type, current_id);
TypeFromUser self_user_type(self_type->GetClangFullType(),
self_type->GetClangAST());
@ -3605,28 +3625,26 @@ ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context,
}
}
void
ClangExpressionDeclMap::AddOneType(NameSearchContext &context,
TypeFromUser &ut,
unsigned int current_id,
bool add_method)
TypeFromParser
ClangExpressionDeclMap::CopyClassType(TypeFromUser &ut,
unsigned int current_id)
{
ASTContext *parser_ast_context = m_ast_context;
ASTContext *user_ast_context = ut.GetASTContext();
void *copied_type = GuardedCopyType(parser_ast_context, user_ast_context, ut.GetOpaqueQualType());
if (!copied_type)
{
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
if (log)
log->Printf("ClangExpressionDeclMap::AddOneType - Couldn't import the type");
return;
if (log)
log->Printf("ClangExpressionDeclMap::CopyClassType - Couldn't import the type");
return TypeFromParser();
}
if (add_method && ClangASTContext::IsAggregateType(copied_type) && ClangASTContext::GetCompleteType (parser_ast_context, copied_type))
if (ClangASTContext::IsAggregateType(copied_type) && ClangASTContext::GetCompleteType (parser_ast_context, copied_type))
{
void *args[1];
@ -3659,5 +3677,28 @@ ClangExpressionDeclMap::AddOneType(NameSearchContext &context,
is_artificial);
}
return TypeFromParser(copied_type, parser_ast_context);
}
void
ClangExpressionDeclMap::AddOneType(NameSearchContext &context,
TypeFromUser &ut,
unsigned int current_id)
{
ASTContext *parser_ast_context = m_ast_context;
ASTContext *user_ast_context = ut.GetASTContext();
void *copied_type = GuardedCopyType(parser_ast_context, user_ast_context, ut.GetOpaqueQualType());
if (!copied_type)
{
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
if (log)
log->Printf("ClangExpressionDeclMap::AddOneType - Couldn't import the type");
return;
}
context.AddTypeDecl(copied_type);
}

View File

@ -1309,8 +1309,8 @@ ClangASTContext::CreateClassTemplateDecl (DeclContext *decl_ctx,
// With templated classes, we say that a class is templated with
// specializations, but that the bare class has no functions.
template_cxx_decl->startDefinition();
template_cxx_decl->completeDefinition();
//template_cxx_decl->startDefinition();
//template_cxx_decl->completeDefinition();
class_template_decl = ClassTemplateDecl::Create (*ast,
decl_ctx, // What decl context do we use here? TU? The actual decl context?
@ -1356,6 +1356,8 @@ ClangASTContext::CreateClassTemplateSpecializationDecl (DeclContext *decl_ctx,
template_param_infos.args.size(),
NULL);
class_template_specialization_decl->setSpecializationKind(TSK_ExplicitSpecialization);
return class_template_specialization_decl;
}

View File

@ -9,45 +9,45 @@
#include <stdio.h>
class A
template <class T> class A
{
public:
void accessMember(int a);
int accessMemberConst() const;
void accessMember(T a);
T accessMemberConst() const;
static int accessStaticMember();
void accessMemberInline(int a) __attribute__ ((always_inline))
void accessMemberInline(T a) __attribute__ ((always_inline))
{
m_a = a; // breakpoint 4
}
int m_a;
T m_a;
static int s_a;
};
int A::s_a = 5;
template <class T> int A<T>::s_a = 5;
void A::accessMember(int a)
template <class T> void A<T>::accessMember(T a)
{
m_a = a; // breakpoint 1
}
int A::accessMemberConst() const
template <class T> T A<T>::accessMemberConst() const
{
return m_a; // breakpoint 2
}
int A::accessStaticMember()
template <class T> int A<T>::accessStaticMember()
{
return s_a; // breakpoint 3
}
int main()
{
A my_a;
A<int> my_a;
my_a.accessMember(3);
my_a.accessMemberConst();
A::accessStaticMember();
A<int>::accessStaticMember();
my_a.accessMemberInline(5);
}