forked from OSchip/llvm-project
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:
parent
1d584029ae
commit
fa4fab77d4
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue