This commit completes the rearchitecting of ClangASTSource

to allow variables in the persistent variable store to know
how to complete themselves from debug information.  That
fixes a variety of bugs during dematerialization of 
expression results and also makes persistent variable and
result variables ($foo, $4, ...) more useful.

I have also added logging improvements that make it much
easier to figure out how types are moving from place to 
place, and made some checking a little more aggressive.

The commit includes patches to Clang which are currently being
integrated into Clang proper; once these fixes are in Clang
top-of-tree, these patches will be removed.  The patches don't
fix API; rather, they fix some internal bugs in Clang's 
ASTImporter that were exposed when LLDB was moving types from
place to place multiple times.

llvm-svn: 144969
This commit is contained in:
Sean Callanan 2011-11-18 03:28:09 +00:00
parent 1ec141d0f9
commit 00f43622e1
8 changed files with 261 additions and 51 deletions

View File

@ -129,6 +129,12 @@ private:
decl = rhs.decl;
}
void operator= (const DeclOrigin &rhs)
{
ctx = rhs.ctx;
decl = rhs.decl;
}
bool
Valid ()
{

View File

@ -156,7 +156,7 @@ else
do_command ("cd '$SRCROOT' && svn co --quiet --revision $llvm_revision http://llvm.org/svn/llvm-project/llvm/trunk llvm", "checking out llvm from repository", 1);
print "Checking out clang sources from revision $clang_revision...\n";
do_command ("cd '$llvm_srcroot/tools' && svn co --quiet --revision $clang_revision http://llvm.org/svn/llvm-project/cfe/trunk clang", "checking out clang from repository", 1);
print "Applying any local patches to LLVM...";
print "Applying any local patches to LLVM/Clang...";
my @llvm_patches = bsd_glob("$ENV{SRCROOT}/scripts/llvm.*.diff");
@ -164,6 +164,13 @@ else
{
do_command ("cd '$llvm_srcroot' && patch -p0 < $patch");
}
my @clang_patches = bsd_glob("$ENV{SRCROOT}/scripts/clang.*.diff");
foreach my $patch (@clang_patches)
{
do_command ("cd '$llvm_srcroot/tools/clang' && patch -p0 < $patch");
}
print "Removing the llvm/test and llvm/tools/clang/test directories...\n";
do_command ("cd '$llvm_srcroot' && rm -rf test && rm -rf tools/clang/test ", "removing test directories", 1);

View File

@ -0,0 +1,78 @@
Index: include/clang/AST/DeclBase.h
===================================================================
--- include/clang/AST/DeclBase.h (revision 144573)
+++ include/clang/AST/DeclBase.h (working copy)
@@ -807,6 +807,12 @@
/// storage that contains additional declarations that are visible
/// in this context.
mutable unsigned ExternalVisibleStorage : 1;
+
+ /// \brief True if this declaration context is currently having
+ /// declarations added from its external lexical storage. This flag
+ /// is intended to prevent One Definition Rule checking as the
+ /// declarations are imported.
+ mutable unsigned IsBeingCompletedFromLexicalStorage : 1;
/// \brief Pointer to the data structure used to lookup declarations
/// within this context (or a DependentStoredDeclsMap if this is a
@@ -834,8 +840,8 @@
DeclContext(Decl::Kind K)
: DeclKind(K), ExternalLexicalStorage(false),
- ExternalVisibleStorage(false), LookupPtr(0), FirstDecl(0),
- LastDecl(0) { }
+ ExternalVisibleStorage(false), IsBeingCompletedFromLexicalStorage(false),
+ LookupPtr(0), FirstDecl(0), LastDecl(0) { }
public:
~DeclContext();
@@ -1339,6 +1345,14 @@
ExternalVisibleStorage = ES;
}
+ bool isBeingCompletedFromLexicalStorage() const {
+ return IsBeingCompletedFromLexicalStorage;
+ }
+
+ void setIsBeingCompletedFromLexicalStorage(bool IBC) const {
+ IsBeingCompletedFromLexicalStorage = IBC;
+ }
+
/// \brief Determine whether the given declaration is stored in the list of
/// declarations lexically within this context.
bool isDeclInLexicalTraversal(const Decl *D) const {
Index: lib/AST/Decl.cpp
===================================================================
--- lib/AST/Decl.cpp (revision 144573)
+++ lib/AST/Decl.cpp (working copy)
@@ -2405,8 +2405,14 @@
ExternalASTSource::Deserializing TheFields(Source);
SmallVector<Decl*, 64> Decls;
- LoadedFieldsFromExternalStorage = true;
- switch (Source->FindExternalLexicalDeclsBy<FieldDecl>(this, Decls)) {
+ LoadedFieldsFromExternalStorage = true;
+
+ setIsBeingCompletedFromLexicalStorage(true);
+ ExternalLoadResult LoadResult =
+ Source->FindExternalLexicalDeclsBy<FieldDecl>(this, Decls);
+ setIsBeingCompletedFromLexicalStorage(false);
+
+ switch (LoadResult) {
case ELR_Success:
break;
Index: lib/AST/ASTImporter.cpp
===================================================================
--- lib/AST/ASTImporter.cpp (revision 144573)
+++ lib/AST/ASTImporter.cpp (working copy)
@@ -2290,7 +2290,8 @@
if (RecordDecl *FoundRecord = dyn_cast<RecordDecl>(Found)) {
if (RecordDecl *FoundDef = FoundRecord->getDefinition()) {
- if (!D->isCompleteDefinition() || IsStructuralMatch(D, FoundDef)) {
+ if (FoundDef->isBeingCompletedFromLexicalStorage() ||
+ !D->isCompleteDefinition() || IsStructuralMatch(D, FoundDef)) {
// The record types structurally match, or the "from" translation
// unit only had a forward declaration anyway; call it the same
// function.

View File

@ -0,0 +1,28 @@
Index: lib/AST/ASTImporter.cpp
===================================================================
--- lib/AST/ASTImporter.cpp (revision 144573)
+++ lib/AST/ASTImporter.cpp (working copy)
@@ -100,6 +100,7 @@
bool IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToRecord);
bool IsStructuralMatch(ClassTemplateDecl *From, ClassTemplateDecl *To);
Decl *VisitDecl(Decl *D);
+ Decl *VisitTranslationUnitDecl(TranslationUnitDecl *D);
Decl *VisitNamespaceDecl(NamespaceDecl *D);
Decl *VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias);
Decl *VisitTypedefDecl(TypedefDecl *D);
@@ -2030,6 +2031,15 @@
return 0;
}
+Decl *ASTNodeImporter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
+ TranslationUnitDecl *ToD =
+ Importer.getToContext().getTranslationUnitDecl();
+
+ Importer.Imported(D, ToD);
+
+ return ToD;
+}
+
Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) {
// Import the major distinguishing characteristics of this namespace.
DeclContext *DC, *LexicalDC;

View File

@ -135,7 +135,7 @@ ClangASTSource::CompleteType (TagDecl *tag_decl)
if (log)
{
log->Printf(" [CompleteTagDecl] Completing a TagDecl named %s", tag_decl->getName().str().c_str());
log->Printf(" [CompleteTagDecl] on (ASTContext*)%p Completing a TagDecl named %s", m_ast_context, tag_decl->getName().str().c_str());
log->Printf(" [CTD] Before:");
ASTDumper dumper((Decl*)tag_decl);
dumper.ToLog(log, " [CTD] ");
@ -158,7 +158,7 @@ ClangASTSource::CompleteType (clang::ObjCInterfaceDecl *interface_decl)
if (log)
{
log->Printf(" [CompleteObjCInterfaceDecl] Completing an ObjCInterfaceDecl named %s", interface_decl->getName().str().c_str());
log->Printf(" [CompleteObjCInterfaceDecl] on (ASTContext*)%p Completing an ObjCInterfaceDecl named %s", m_ast_context, interface_decl->getName().str().c_str());
log->Printf(" [COID] Before:");
ASTDumper dumper((Decl*)interface_decl);
dumper.ToLog(log, " [COID] ");
@ -192,19 +192,24 @@ ClangASTSource::FindExternalLexicalDecls (const DeclContext *decl_context,
if (log)
{
if (const NamedDecl *context_named_decl = dyn_cast<NamedDecl>(context_decl))
log->Printf("FindExternalLexicalDecls[%u] in '%s' (a %s) with %s predicate",
log->Printf("FindExternalLexicalDecls[%u] on (ASTContext*)%p in '%s' (%sDecl*)%p with %s predicate",
current_id,
m_ast_context,
context_named_decl->getNameAsString().c_str(),
context_decl->getDeclKindName(),
context_decl->getDeclKindName(),
context_decl,
(predicate ? "non-null" : "null"));
else if(context_decl)
log->Printf("FindExternalLexicalDecls[%u] in a %s with %s predicate",
log->Printf("FindExternalLexicalDecls[%u] on (ASTContext*)%p in (%sDecl*)%p with %s predicate",
current_id,
m_ast_context,
context_decl->getDeclKindName(),
context_decl,
(predicate ? "non-null" : "null"));
else
log->Printf("FindExternalLexicalDecls[%u] in a NULL context with %s predicate",
log->Printf("FindExternalLexicalDecls[%u] on (ASTContext*)%p in a NULL context with %s predicate",
current_id,
m_ast_context,
(predicate ? "non-null" : "null"));
}
@ -274,11 +279,11 @@ ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context)
if (log)
{
if (!context.m_decl_context)
log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] for '%s' in a NULL DeclContext", current_id, name.GetCString());
log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on (ASTContext*)%p for '%s' in a NULL DeclContext", current_id, m_ast_context, name.GetCString());
else if (const NamedDecl *context_named_decl = dyn_cast<NamedDecl>(context.m_decl_context))
log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] for '%s' in '%s'", current_id, name.GetCString(), context_named_decl->getNameAsString().c_str());
log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on (ASTContext*)%p for '%s' in '%s'", current_id, m_ast_context, name.GetCString(), context_named_decl->getNameAsString().c_str());
else
log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] for '%s' in a '%s'", current_id, name.GetCString(), context.m_decl_context->getDeclKindName());
log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on (ASTContext*)%p for '%s' in a '%s'", current_id, m_ast_context, name.GetCString(), context.m_decl_context->getDeclKindName());
}
context.m_namespace_map.reset(new ClangASTImporter::NamespaceMap);
@ -511,8 +516,9 @@ ClangASTSource::FindObjCMethodDecls (NameSearchContext &context)
ConstString selector_name(ss.GetData());
if (log)
log->Printf("ClangASTSource::FindObjCMethodDecls[%d] for selector [%s %s]",
current_id,
log->Printf("ClangASTSource::FindObjCMethodDecls[%d] on (ASTContext*)%p for selector [%s %s]",
current_id,
m_ast_context,
interface_decl->getNameAsString().c_str(),
selector_name.AsCString());
@ -603,8 +609,9 @@ ClangASTSource::FindObjCPropertyDecls (NameSearchContext &context)
ObjCPropertyDecl *property_decl = orig_iface_decl->FindPropertyDeclaration(&orig_ast_ctx->Idents.get(property_name));
if (log)
log->Printf("ClangASTSource::FindObjCPropertyDecls[%d] for property '%s.%s'",
log->Printf("ClangASTSource::FindObjCPropertyDecls[%d] on (ASTContext*)%p for property '%s.%s'",
current_id,
m_ast_context,
iface_decl->getNameAsString().c_str(),
property_name_str.c_str());
@ -643,13 +650,15 @@ ClangASTSource::CompleteNamespaceMap (ClangASTImporter::NamespaceMapSP &namespac
if (log)
{
if (parent_map && parent_map->size())
log->Printf("CompleteNamespaceMap[%u] Searching for namespace %s in namespace %s",
log->Printf("CompleteNamespaceMap[%u] on (ASTContext*)%p Searching for namespace %s in namespace %s",
current_id,
m_ast_context,
name.GetCString(),
parent_map->begin()->second.GetNamespaceDecl()->getDeclName().getAsString().c_str());
else
log->Printf("CompleteNamespaceMap[%u] Searching for namespace %s",
log->Printf("CompleteNamespaceMap[%u] on (ASTContext*)%p Searching for namespace %s",
current_id,
m_ast_context,
name.GetCString());
}

View File

@ -196,9 +196,9 @@ ClangExpressionDeclMap::BuildIntegerVariable (const ConstString &name,
ASTContext *context(target->GetScratchClangASTContext()->getASTContext());
TypeFromUser user_type(ClangASTContext::CopyType(context,
type.GetASTContext(),
type.GetOpaqueQualType()),
TypeFromUser user_type(m_ast_importer->CopyType(context,
type.GetASTContext(),
type.GetOpaqueQualType()),
context);
if (!m_parser_vars->m_persistent_vars->CreatePersistentVariable (exe_ctx->GetBestExecutionContextScope (),
@ -285,9 +285,9 @@ ClangExpressionDeclMap::BuildCastVariable (const ConstString &name,
if (!var_sp)
return ClangExpressionVariableSP();
TypeFromUser user_type(ClangASTContext::CopyType(context,
type.GetASTContext(),
type.GetOpaqueQualType()),
TypeFromUser user_type(m_ast_importer->CopyType(context,
type.GetASTContext(),
type.GetOpaqueQualType()),
context);
TypeFromUser var_type = var_sp->GetTypeFromUser();
@ -424,10 +424,17 @@ ClangExpressionDeclMap::AddPersistentVariable
ASTContext *context(target->GetScratchClangASTContext()->getASTContext());
TypeFromUser user_type(ClangASTContext::CopyType(context,
parser_type.GetASTContext(),
parser_type.GetOpaqueQualType()),
TypeFromUser user_type(m_ast_importer->CopyType(context,
parser_type.GetASTContext(),
parser_type.GetOpaqueQualType()),
context);
if (!user_type.GetOpaqueQualType())
{
if (log)
log->Printf("Persistent variable's type wasn't copied successfully");
return false;
}
if (!m_parser_vars->m_target_info.IsValid())
return false;
@ -499,7 +506,7 @@ ClangExpressionDeclMap::AddValueToStruct
return false;
if (log)
log->Printf("Adding value for decl %p [%s - %s] to the structure",
log->Printf("Adding value for (NamedDecl*)%p [%s - %s] to the structure",
decl,
name.GetCString(),
var_sp->GetName().GetCString());
@ -936,8 +943,15 @@ ClangExpressionDeclMap::ReadTarget (uint8_t *data,
return err.Success();
}
case Value::eValueTypeHostAddress:
memcpy (data, (const void *)value.GetScalar().ULongLong(), length);
{
void *host_addr = (void*)value.GetScalar().ULongLong();
if (!host_addr)
return false;
memcpy (data, host_addr, length);
return true;
}
case Value::eValueTypeScalar:
return false;
}
@ -1370,12 +1384,16 @@ ClangExpressionDeclMap::DoMaterialize
log->PutCString("Allocating memory for materialized argument struct");
lldb::addr_t mem = process->AllocateMemory(m_struct_vars->m_struct_alignment + m_struct_vars->m_struct_size,
lldb::ePermissionsReadable | lldb::ePermissionsWritable,
err);
lldb::ePermissionsReadable | lldb::ePermissionsWritable,
err);
if (mem == LLDB_INVALID_ADDRESS)
{
err.SetErrorStringWithFormat("Couldn't allocate 0x%llx bytes for materialized argument struct",
(unsigned long long)(m_struct_vars->m_struct_alignment + m_struct_vars->m_struct_size));
return false;
}
m_material_vars->m_allocated_area = mem;
}
@ -1400,8 +1418,11 @@ ClangExpressionDeclMap::DoMaterialize
RegisterContext *reg_ctx = exe_ctx.GetRegisterContext();
if (!reg_ctx)
{
err.SetErrorString("Couldn't get register context");
return false;
}
if (!DoMaterializeOneRegister (dematerialize,
exe_ctx,
*reg_ctx,
@ -1413,7 +1434,10 @@ ClangExpressionDeclMap::DoMaterialize
else
{
if (!member_sp->m_jit_vars.get())
{
err.SetErrorString("Variable being materialized doesn't have necessary state");
return false;
}
if (!DoMaterializeOneVariable (dematerialize,
exe_ctx,
@ -1485,7 +1509,10 @@ ClangExpressionDeclMap::DoMaterializeOnePersistentVariable
uint8_t *pvar_data = var_sp->GetValueBytes();
if (pvar_data == NULL)
{
err.SetErrorString("Persistent variable being materialized contains no data");
return false;
}
Error error;
Process *process = exe_ctx.GetProcessPtr();
@ -1689,7 +1716,10 @@ ClangExpressionDeclMap::DoMaterializeOneVariable
StackFrame *frame = exe_ctx.GetFramePtr();
if (!frame || !process || !target || !m_parser_vars.get() || !expr_var->m_parser_vars.get())
{
err.SetErrorString("Necessary state for variable materialization isn't present");
return false;
}
// Vital information about the value
@ -2200,7 +2230,7 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context)
ClangASTImporter::NamespaceMapSP namespace_map = m_ast_importer->GetNamespaceMap(namespace_context);
if (log && log->GetVerbose())
log->Printf(" CEDM::FEVD[%u] Inspecting namespace map %p (%d entries)",
log->Printf(" CEDM::FEVD[%u] Inspecting (NamespaceMap*)%p (%d entries)",
current_id,
namespace_map.get(),
(int)namespace_map->size());
@ -2873,7 +2903,7 @@ ClangExpressionDeclMap::ResolveUnknownTypes()
QualType var_type = var_decl->getType();
TypeFromParser parser_type(var_type.getAsOpaquePtr(), &var_decl->getASTContext());
lldb::clang_type_t copied_type = ClangASTContext::CopyType(scratch_ast_context, &var_decl->getASTContext(), var_type.getAsOpaquePtr());
lldb::clang_type_t copied_type = m_ast_importer->CopyType(scratch_ast_context, &var_decl->getASTContext(), var_type.getAsOpaquePtr());
TypeFromUser user_type(copied_type, scratch_ast_context);

View File

@ -647,12 +647,25 @@ IRForTarget::CreateResultVariable (llvm::Function &llvm_function)
clang::QualType element_qual_type = pointer_pointertype->getPointeeType();
m_result_type = lldb_private::TypeFromParser(element_qual_type.getAsOpaquePtr(),
&result_decl->getASTContext());
&result_decl->getASTContext());
}
else
{
m_result_type = lldb_private::TypeFromParser(result_var->getType().getAsOpaquePtr(),
&result_decl->getASTContext());
&result_decl->getASTContext());
}
if (m_result_type.GetClangTypeBitWidth() == 0)
{
lldb_private::StreamString type_desc_stream;
m_result_type.DumpTypeDescription(&type_desc_stream);
if (log)
log->Printf("Result type has size 0");
if (m_error_stream)
m_error_stream->Printf("Internal error [IRForTarget]: Result type '%s' has invalid size\n",
type_desc_stream.GetData());
}
if (log)
@ -660,13 +673,15 @@ IRForTarget::CreateResultVariable (llvm::Function &llvm_function)
lldb_private::StreamString type_desc_stream;
m_result_type.DumpTypeDescription(&type_desc_stream);
log->Printf("Result decl type: \"%s\"", type_desc_stream.GetString().c_str());
log->Printf("Result decl type: \"%s\"", type_desc_stream.GetData());
}
m_result_name = m_decl_map->GetPersistentResultName();
if (log)
log->Printf("Creating a new result global: \"%s\"", m_result_name.GetCString());
log->Printf("Creating a new result global: \"%s\" with size 0x%x",
m_result_name.GetCString(),
m_result_type.GetClangTypeBitWidth() / 8);
// Construct a new result global and set up its metadata
@ -755,11 +770,12 @@ IRForTarget::CreateResultVariable (llvm::Function &llvm_function)
}
if (!m_const_result)
m_decl_map->AddPersistentVariable(result_decl,
m_result_name,
m_result_type,
true,
m_result_is_pointer);
if (!m_decl_map->AddPersistentVariable(result_decl,
m_result_name,
m_result_type,
true,
m_result_is_pointer))
return false;
result_global->eraseFromParent();

View File

@ -193,7 +193,26 @@ clang::Decl
*ClangASTImporter::Minion::Imported (clang::Decl *from, clang::Decl *to)
{
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
if (log)
{
if (NamedDecl *from_named_decl = dyn_cast<clang::NamedDecl>(from))
{
log->Printf(" [ClangASTImporter] Imported (%sDecl*)%p, named %s (from (Decl*)%p)",
from->getDeclKindName(),
to,
from_named_decl->getName().str().c_str(),
from);
}
else
{
log->Printf(" [ClangASTImporter] Imported (%sDecl*)%p (from (Decl*)%p)",
from->getDeclKindName(),
to,
from);
}
}
ASTContextMetadataSP to_context_md = m_master.GetContextMetadata(&to->getASTContext());
ASTContextMetadataSP from_context_md = m_master.MaybeGetContextMetadata(m_source_ctx);
@ -204,7 +223,22 @@ clang::Decl
OriginMap::iterator origin_iter = origins.find(from);
if (origin_iter != origins.end())
{
to_context_md->m_origins[to] = origin_iter->second;
if (log)
log->Printf(" [ClangASTImporter] Propagated origin (Decl*)%p/(ASTContext*)%p from (ASTContext*)%p to (ASTContext*)%p",
origin_iter->second.decl,
origin_iter->second.ctx,
&from->getASTContext(),
&to->getASTContext());
}
else
{
if (log)
log->Printf(" [ClangASTImporter] Decl has no origin information in (ASTContext*)%p",
&from->getASTContext());
}
if (clang::NamespaceDecl *to_namespace = dyn_cast<clang::NamespaceDecl>(to))
{
@ -221,6 +255,12 @@ clang::Decl
else
{
to_context_md->m_origins[to] = DeclOrigin (m_source_ctx, from);
if (log)
log->Printf(" [ClangASTImporter] Sourced origin (Decl*)%p/(ASTContext*)%p into (ASTContext*)%p",
from,
m_source_ctx,
&to->getASTContext());
}
if (TagDecl *from_tag_decl = dyn_cast<TagDecl>(from))
@ -230,14 +270,13 @@ clang::Decl
to_tag_decl->setHasExternalLexicalStorage();
if (log)
log->Printf(" [ClangASTImporter] Imported %p, a %s named %s%s%s [%s->%s]",
to,
((clang::Decl*)from_tag_decl)->getDeclKindName(),
from_tag_decl->getName().str().c_str(),
log->Printf(" [ClangASTImporter] To is a TagDecl - attributes %s%s [%s->%s]",
(to_tag_decl->hasExternalLexicalStorage() ? " Lexical" : ""),
(to_tag_decl->hasExternalVisibleStorage() ? " Visible" : ""),
(from_tag_decl->isCompleteDefinition() ? "complete" : "incomplete"),
(to_tag_decl->isCompleteDefinition() ? "complete" : "incomplete"));
to_tag_decl = NULL;
}
if (isa<NamespaceDecl>(from))
@ -249,7 +288,7 @@ clang::Decl
to_namespace_decl->setHasExternalVisibleStorage();
}
if (ObjCInterfaceDecl *from_interface_decl = dyn_cast<ObjCInterfaceDecl>(from))
if (isa<ObjCInterfaceDecl>(from))
{
ObjCInterfaceDecl *to_interface_decl = dyn_cast<ObjCInterfaceDecl>(to);
@ -262,10 +301,7 @@ clang::Decl
to_interface_decl->setExternallyCompleted();
if (log)
log->Printf(" [ClangASTImporter] Imported %p, a %s named %s%s%s%s",
to,
((clang::Decl*)from_interface_decl)->getDeclKindName(),
from_interface_decl->getName().str().c_str(),
log->Printf(" [ClangASTImporter] To is an ObjCInterfaceDecl - attributes %s%s%s",
(to_interface_decl->hasExternalLexicalStorage() ? " Lexical" : ""),
(to_interface_decl->hasExternalVisibleStorage() ? " Visible" : ""),
(to_interface_decl->isForwardDecl() ? " Forward" : ""));