Preserve the owning module information from DWARF in the synthesized AST

Types that came from a Clang module are nested in DW_TAG_module tags
in DWARF. This patch recreates the Clang module hierarchy in LLDB and
1;95;0csets the owning module information accordingly. My primary motivation
is to facilitate looking up per-module APINotes for individual
declarations, but this likely also has other applications.

This reapplies the previously reverted commit, but without support for
ClassTemplateSpecializations, which I'm going to look into separately.

rdar://problem/59634380

Differential Revision: https://reviews.llvm.org/D75488
This commit is contained in:
Adrian Prantl 2020-03-04 09:30:12 -08:00
parent 680082a408
commit 143d507c9f
25 changed files with 594 additions and 168 deletions

View File

@ -242,8 +242,10 @@ public:
/// Create a typedef to this type using "name" as the name of the typedef this
/// type is valid and the type system supports typedefs, else return an
/// invalid type.
/// \param payload The typesystem-specific \p lldb::Type payload.
CompilerType CreateTypedef(const char *name,
const CompilerDeclContext &decl_ctx) const;
const CompilerDeclContext &decl_ctx,
uint32_t payload) const;
/// If the current object represents a typedef type, get the underlying type
CompilerType GetTypedefedType() const;

View File

@ -259,9 +259,12 @@ public:
virtual CompilerType AddRestrictModifier(lldb::opaque_compiler_type_t type);
/// \param opaque_payload The m_payload field of Type, which may
/// carry TypeSystem-specific extra information.
virtual CompilerType CreateTypedef(lldb::opaque_compiler_type_t type,
const char *name,
const CompilerDeclContext &decl_ctx);
const CompilerDeclContext &decl_ctx,
uint32_t opaque_payload);
// Exploring the type

View File

@ -18,6 +18,7 @@
#include "Plugins/ExpressionParser/Clang/ClangASTImporter.h"
#include "Plugins/ExpressionParser/Clang/ClangASTMetadata.h"
#include "Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.h"
#include "Plugins/ExpressionParser/Clang/ClangUtil.h"
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
@ -1003,6 +1004,21 @@ static void MaybeCompleteReturnType(ClangASTImporter &importer,
importer.CompleteTagDecl(rd);
}
/// Recreate a module with its parents in \p to_source and return its id.
static OptionalClangModuleID
RemapModule(OptionalClangModuleID from_id,
ClangExternalASTSourceCallbacks &from_source,
ClangExternalASTSourceCallbacks &to_source) {
if (!from_id.HasValue())
return {};
clang::Module *module = from_source.getModule(from_id.GetValue());
OptionalClangModuleID parent = RemapModule(
from_source.GetIDForModule(module->Parent), from_source, to_source);
TypeSystemClang &to_ts = to_source.GetTypeSystem();
return to_ts.GetOrCreateClangModule(module->Name, parent, module->IsFramework,
module->IsExplicit);
}
void ClangASTImporter::ASTImporterDelegate::Imported(clang::Decl *from,
clang::Decl *to) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
@ -1012,6 +1028,20 @@ void ClangASTImporter::ASTImporterDelegate::Imported(clang::Decl *from,
if (m_decls_to_ignore.find(to) != m_decls_to_ignore.end())
return clang::ASTImporter::Imported(from, to);
// Transfer module ownership information.
auto *from_source = llvm::dyn_cast_or_null<ClangExternalASTSourceCallbacks>(
getFromContext().getExternalSource());
// Can also be a ClangASTSourceProxy.
auto *to_source = llvm::dyn_cast_or_null<ClangExternalASTSourceCallbacks>(
getToContext().getExternalSource());
if (from_source && to_source) {
OptionalClangModuleID from_id(from->getOwningModuleID());
OptionalClangModuleID to_id =
RemapModule(from_id, *from_source, *to_source);
TypeSystemClang &to_ts = to_source->GetTypeSystem();
to_ts.SetOwningModule(to, to_id);
}
lldb::user_id_t user_id = LLDB_INVALID_UID;
ClangASTMetadata *metadata = m_master.GetDeclMetadata(from);
if (metadata)

View File

@ -993,7 +993,7 @@ void ClangExpressionDeclMap::LookupLocalVarNamespace(
clang::NamespaceDecl *namespace_decl =
m_clang_ast_context->GetUniqueNamespaceDeclaration(
g_lldb_local_vars_namespace_cstr, nullptr);
g_lldb_local_vars_namespace_cstr, nullptr, OptionalClangModuleID());
if (!namespace_decl)
return;

View File

@ -13,6 +13,8 @@
using namespace lldb_private;
char ClangExternalASTSourceCallbacks::ID;
void ClangExternalASTSourceCallbacks::CompleteType(clang::TagDecl *tag_decl) {
m_ast.CompleteTagDecl(tag_decl);
}
@ -43,3 +45,29 @@ void ClangExternalASTSourceCallbacks::FindExternalLexicalDecls(
CompleteType(tag_decl);
}
}
OptionalClangModuleID
ClangExternalASTSourceCallbacks::RegisterModule(clang::Module *module) {
m_modules.push_back(module);
unsigned id = m_modules.size();
m_ids.insert({module, id});
return OptionalClangModuleID(id);
}
llvm::Optional<clang::ASTSourceDescriptor>
ClangExternalASTSourceCallbacks::getSourceDescriptor(unsigned id) {
if (clang::Module *module = getModule(id))
return {*module};
return {};
}
clang::Module *ClangExternalASTSourceCallbacks::getModule(unsigned id) {
if (id && id <= m_modules.size())
return m_modules[id - 1];
return nullptr;
}
OptionalClangModuleID
ClangExternalASTSourceCallbacks::GetIDForModule(clang::Module *module) {
return OptionalClangModuleID(m_ids[module]);
}

View File

@ -10,14 +10,19 @@
#define LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGEXTERNALASTSOURCECALLBACKS_H
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/Basic/Module.h"
namespace lldb_private {
class TypeSystemClang;
class ClangExternalASTSourceCallbacks : public clang::ExternalASTSource {
/// LLVM RTTI support.
static char ID;
public:
/// LLVM RTTI support.
bool isA(const void *ClassID) const override { return ClassID == &ID; }
static bool classof(const clang::ExternalASTSource *s) { return s->isA(&ID); }
ClangExternalASTSourceCallbacks(TypeSystemClang &ast) : m_ast(ast) {}
void FindExternalLexicalDecls(
@ -37,8 +42,20 @@ public:
llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
&VirtualBaseOffsets) override;
TypeSystemClang &GetTypeSystem() const { return m_ast; }
/// Module-related methods.
/// \{
llvm::Optional<clang::ASTSourceDescriptor>
getSourceDescriptor(unsigned ID) override;
clang::Module *getModule(unsigned ID) override;
OptionalClangModuleID RegisterModule(clang::Module *module);
OptionalClangModuleID GetIDForModule(clang::Module *module);
/// \}
private:
TypeSystemClang &m_ast;
std::vector<clang::Module *> m_modules;
llvm::DenseMap<clang::Module *, unsigned> m_ids;
};
} // namespace lldb_private

View File

@ -76,8 +76,9 @@ static CompilerType GetLLDBNSPairType(TargetSP target_sp) {
if (!compiler_type) {
compiler_type = target_ast_context->CreateRecordType(
nullptr, lldb::eAccessPublic, g___lldb_autogen_nspair.GetCString(),
clang::TTK_Struct, lldb::eLanguageTypeC);
nullptr, OptionalClangModuleID(), lldb::eAccessPublic,
g___lldb_autogen_nspair.GetCString(), clang::TTK_Struct,
lldb::eLanguageTypeC);
if (compiler_type) {
TypeSystemClang::StartTagDeclarationDefinition(compiler_type);

View File

@ -124,7 +124,8 @@ clang::QualType AppleObjCTypeEncodingParser::BuildAggregate(
return clang::QualType(); // This is where we bail out. Sorry!
CompilerType union_type(ast_ctx.CreateRecordType(
nullptr, lldb::eAccessPublic, name, kind, lldb::eLanguageTypeC));
nullptr, OptionalClangModuleID(), lldb::eAccessPublic, name, kind,
lldb::eLanguageTypeC));
if (union_type) {
TypeSystemClang::StartTagDeclarationDefinition(union_type);

View File

@ -212,14 +212,15 @@ TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc,
TypeSP type_sp(new Type(
die.GetID(), dwarf, pcm_type_sp->GetName(), pcm_type_sp->GetByteSize(),
nullptr, LLDB_INVALID_UID, Type::eEncodingInvalid,
&pcm_type_sp->GetDeclaration(), type, Type::ResolveState::Forward));
&pcm_type_sp->GetDeclaration(), type, Type::ResolveState::Forward,
TypePayloadClang(GetOwningClangModule(die))));
dwarf->GetTypeList().Insert(type_sp);
dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
clang::TagDecl *tag_decl = TypeSystemClang::GetAsTagDecl(type);
if (tag_decl)
if (tag_decl) {
LinkDeclContextToDIE(tag_decl, die);
else {
} else {
clang::DeclContext *defn_decl_ctx = GetCachedClangDeclContextForDIE(die);
if (defn_decl_ctx)
LinkDeclContextToDIE(defn_decl_ctx, die);
@ -708,7 +709,7 @@ DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc,
type_sp = std::make_shared<Type>(
die.GetID(), dwarf, attrs.name, attrs.byte_size, nullptr,
dwarf->GetUID(attrs.type.Reference()), encoding_data_type, &attrs.decl,
clang_type, resolve_state);
clang_type, resolve_state, TypePayloadClang(GetOwningClangModule(die)));
dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
return type_sp;
@ -790,7 +791,8 @@ TypeSP DWARFASTParserClang::ParseEnum(const SymbolContext &sc,
clang_type = m_ast.CreateEnumerationType(
attrs.name.GetCString(), GetClangDeclContextContainingDIE(die, nullptr),
attrs.decl, enumerator_clang_type, attrs.is_scoped_enum);
GetOwningClangModule(die), attrs.decl, enumerator_clang_type,
attrs.is_scoped_enum);
} else {
enumerator_clang_type = m_ast.GetEnumerationIntegerType(clang_type);
}
@ -800,7 +802,8 @@ TypeSP DWARFASTParserClang::ParseEnum(const SymbolContext &sc,
type_sp = std::make_shared<Type>(
die.GetID(), dwarf, attrs.name, attrs.byte_size, nullptr,
dwarf->GetUID(attrs.type.Reference()), Type::eEncodingIsUID, &attrs.decl,
clang_type, Type::ResolveState::Forward);
clang_type, Type::ResolveState::Forward,
TypePayloadClang(GetOwningClangModule(die)));
if (TypeSystemClang::StartTagDeclarationDefinition(clang_type)) {
if (die.HasChildren()) {
@ -1184,7 +1187,8 @@ TypeSP DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die,
function_decl = m_ast.CreateFunctionDeclaration(
ignore_containing_context ? m_ast.GetTranslationUnitDecl()
: containing_decl_ctx,
name, clang_type, attrs.storage, attrs.is_inline);
GetOwningClangModule(die), name, clang_type, attrs.storage,
attrs.is_inline);
if (has_template_params) {
TypeSystemClang::TemplateParameterInfos template_param_infos;
@ -1192,12 +1196,12 @@ TypeSP DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die,
template_function_decl = m_ast.CreateFunctionDeclaration(
ignore_containing_context ? m_ast.GetTranslationUnitDecl()
: containing_decl_ctx,
name, clang_type, attrs.storage, attrs.is_inline);
GetOwningClangModule(die), attrs.name.GetCString(), clang_type,
attrs.storage, attrs.is_inline);
clang::FunctionTemplateDecl *func_template_decl =
m_ast.CreateFunctionTemplateDecl(containing_decl_ctx,
template_function_decl, name,
template_param_infos);
m_ast.CreateFunctionTemplateDecl(
containing_decl_ctx, GetOwningClangModule(die),
template_function_decl, name, template_param_infos);
m_ast.CreateFunctionTemplateSpecializationInfo(
template_function_decl, func_template_decl, template_param_infos);
}
@ -1594,9 +1598,9 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
TypeSystemClang::TemplateParameterInfos template_param_infos;
if (ParseTemplateParameterInfos(die, template_param_infos)) {
clang::ClassTemplateDecl *class_template_decl =
m_ast.ParseClassTemplateDecl(decl_ctx, attrs.accessibility,
attrs.name.GetCString(), tag_decl_kind,
template_param_infos);
m_ast.ParseClassTemplateDecl(
decl_ctx, GetOwningClangModule(die), attrs.accessibility,
attrs.name.GetCString(), tag_decl_kind, template_param_infos);
if (!class_template_decl) {
if (log) {
dwarf->GetObjectFile()->GetModule()->LogMessage(
@ -1611,8 +1615,8 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
clang::ClassTemplateSpecializationDecl *class_specialization_decl =
m_ast.CreateClassTemplateSpecializationDecl(
decl_ctx, class_template_decl, tag_decl_kind,
template_param_infos);
decl_ctx, GetOwningClangModule(die), class_template_decl,
tag_decl_kind, template_param_infos);
clang_type = m_ast.CreateClassTemplateSpecializationType(
class_specialization_decl);
clang_type_was_created = true;
@ -1625,8 +1629,9 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
if (!clang_type_was_created) {
clang_type_was_created = true;
clang_type = m_ast.CreateRecordType(
decl_ctx, attrs.accessibility, attrs.name.GetCString(), tag_decl_kind,
attrs.class_language, &metadata, attrs.exports_symbols);
decl_ctx, GetOwningClangModule(die), attrs.accessibility,
attrs.name.GetCString(), tag_decl_kind, attrs.class_language,
&metadata, attrs.exports_symbols);
}
}
@ -1638,7 +1643,7 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
die.GetID(), dwarf, attrs.name, attrs.byte_size, nullptr,
LLDB_INVALID_UID, Type::eEncodingIsUID, &attrs.decl, clang_type,
Type::ResolveState::Forward,
TypePayloadClang(attrs.is_complete_objc_class));
TypePayloadClang(OptionalClangModuleID(), attrs.is_complete_objc_class));
// Add our type to the unique type map so we don't end up creating many
// copies of the same type over and over in the ASTContext for our
@ -3082,9 +3087,9 @@ size_t DWARFASTParserClang::ParseChildParameters(
function_param_types.push_back(type->GetForwardCompilerType());
clang::ParmVarDecl *param_var_decl =
m_ast.CreateParameterDeclaration(containing_decl_ctx, name,
type->GetForwardCompilerType(),
storage);
m_ast.CreateParameterDeclaration(
containing_decl_ctx, GetOwningClangModule(die), name,
type->GetForwardCompilerType(), storage);
assert(param_var_decl);
function_param_decls.push_back(param_var_decl);
@ -3282,7 +3287,7 @@ clang::Decl *DWARFASTParserClang::GetClangDeclForDIE(const DWARFDIE &die) {
TypeSystemClang::DeclContextGetAsDeclContext(
dwarf->GetDeclContextContainingUID(die.GetID()));
decl = m_ast.CreateVariableDeclaration(
decl_context, name,
decl_context, GetOwningClangModule(die), name,
ClangUtil::GetQualType(type->GetForwardCompilerType()));
}
break;
@ -3299,8 +3304,8 @@ clang::Decl *DWARFASTParserClang::GetClangDeclForDIE(const DWARFDIE &die) {
if (clang::NamedDecl *clang_imported_decl =
llvm::dyn_cast<clang::NamedDecl>(
(clang::Decl *)imported_decl.GetOpaqueDecl()))
decl =
m_ast.CreateUsingDeclaration(decl_context, clang_imported_decl);
decl = m_ast.CreateUsingDeclaration(
decl_context, OptionalClangModuleID(), clang_imported_decl);
}
}
break;
@ -3319,7 +3324,8 @@ clang::Decl *DWARFASTParserClang::GetClangDeclForDIE(const DWARFDIE &die) {
if (clang::NamespaceDecl *ns_decl =
TypeSystemClang::DeclContextGetAsNamespaceDecl(
imported_decl_ctx))
decl = m_ast.CreateUsingDirectiveDeclaration(decl_context, ns_decl);
decl = m_ast.CreateUsingDirectiveDeclaration(
decl_context, OptionalClangModuleID(), ns_decl);
}
}
break;
@ -3377,6 +3383,32 @@ DWARFASTParserClang::GetClangDeclContextForDIE(const DWARFDIE &die) {
return nullptr;
}
OptionalClangModuleID
DWARFASTParserClang::GetOwningClangModule(const DWARFDIE &die) {
if (!die.IsValid())
return {};
for (DWARFDIE parent = die.GetParent(); parent.IsValid();
parent = parent.GetParent()) {
const dw_tag_t tag = parent.Tag();
if (tag == DW_TAG_module) {
DWARFDIE module_die = parent;
auto it = m_die_to_module.find(module_die.GetDIE());
if (it != m_die_to_module.end())
return it->second;
const char *name = module_die.GetAttributeValueAsString(DW_AT_name, 0);
if (!name)
return {};
OptionalClangModuleID id =
m_ast.GetOrCreateClangModule(name, GetOwningClangModule(module_die));
m_die_to_module.insert({module_die.GetDIE(), id});
return id;
}
}
return {};
}
static bool IsSubroutine(const DWARFDIE &die) {
switch (die.Tag()) {
case DW_TAG_subprogram:
@ -3449,7 +3481,8 @@ clang::BlockDecl *DWARFASTParserClang::ResolveBlockDIE(const DWARFDIE &die) {
DWARFDIE decl_context_die;
clang::DeclContext *decl_context =
GetClangDeclContextContainingDIE(die, &decl_context_die);
decl = m_ast.CreateBlockDeclaration(decl_context);
decl =
m_ast.CreateBlockDeclaration(decl_context, GetOwningClangModule(die));
if (decl)
LinkDeclContextToDIE((clang::DeclContext *)decl, die);
@ -3477,7 +3510,8 @@ DWARFASTParserClang::ResolveNamespaceDIE(const DWARFDIE &die) {
die.GetAttributeValueAsUnsigned(DW_AT_export_symbols, 0) != 0;
namespace_decl = m_ast.GetUniqueNamespaceDeclaration(
namespace_name, containing_decl_ctx, is_inline);
namespace_name, containing_decl_ctx, GetOwningClangModule(die),
is_inline);
Log *log =
nullptr; // (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO));
if (log) {

View File

@ -78,6 +78,9 @@ protected:
DIEToDeclContextMap;
typedef std::multimap<const clang::DeclContext *, const DWARFDIE>
DeclContextToDIEMap;
typedef llvm::DenseMap<const DWARFDebugInfoEntry *,
lldb_private::OptionalClangModuleID>
DIEToModuleMap;
typedef llvm::DenseMap<const DWARFDebugInfoEntry *, clang::Decl *>
DIEToDeclMap;
typedef llvm::DenseMap<const clang::Decl *, DIEPointerSet> DeclToDIEMap;
@ -87,6 +90,7 @@ protected:
DeclToDIEMap m_decl_to_die;
DIEToDeclContextMap m_die_to_decl_ctx;
DeclContextToDIEMap m_decl_ctx_to_die;
DIEToModuleMap m_die_to_module;
std::unique_ptr<lldb_private::ClangASTImporter> m_clang_ast_importer_up;
/// @}
@ -140,6 +144,7 @@ protected:
clang::DeclContext *GetClangDeclContextContainingDIE(const DWARFDIE &die,
DWARFDIE *decl_ctx_die);
lldb_private::OptionalClangModuleID GetOwningClangModule(const DWARFDIE &die);
bool CopyUniqueClassMethodTypes(const DWARFDIE &src_class_die,
const DWARFDIE &dst_class_die,

View File

@ -776,8 +776,9 @@ clang::QualType PdbAstBuilder::CreateRecordType(PdbTypeSymId id,
metadata.SetUserID(toOpaqueUid(id));
metadata.SetIsDynamicCXXType(false);
CompilerType ct = m_clang.CreateRecordType(
context, access, uname, ttk, lldb::eLanguageTypeC_plus_plus, &metadata);
CompilerType ct =
m_clang.CreateRecordType(context, OptionalClangModuleID(), access, uname,
ttk, lldb::eLanguageTypeC_plus_plus, &metadata);
lldbassert(ct.IsValid());
@ -804,7 +805,8 @@ clang::NamespaceDecl *
PdbAstBuilder::GetOrCreateNamespaceDecl(const char *name,
clang::DeclContext &context) {
return m_clang.GetUniqueNamespaceDeclaration(
IsAnonymousNamespaceName(name) ? nullptr : name, &context);
IsAnonymousNamespaceName(name) ? nullptr : name, &context,
OptionalClangModuleID());
}
clang::BlockDecl *
@ -814,7 +816,8 @@ PdbAstBuilder::GetOrCreateBlockDecl(PdbCompilandSymId block_id) {
clang::DeclContext *scope = GetParentDeclContext(block_id);
clang::BlockDecl *block_decl = m_clang.CreateBlockDeclaration(scope);
clang::BlockDecl *block_decl =
m_clang.CreateBlockDeclaration(scope, OptionalClangModuleID());
m_uid_to_decl.insert({toOpaqueUid(block_id), block_decl});
DeclStatus status;
@ -831,7 +834,7 @@ clang::VarDecl *PdbAstBuilder::CreateVariableDecl(PdbSymUid uid, CVSymbol sym,
clang::QualType qt = GetOrCreateType(var_info.type);
clang::VarDecl *var_decl = m_clang.CreateVariableDeclaration(
&scope, var_info.name.str().c_str(), qt);
&scope, OptionalClangModuleID(), var_info.name.str().c_str(), qt);
m_uid_to_decl[toOpaqueUid(uid)] = var_decl;
DeclStatus status;
@ -879,7 +882,7 @@ PdbAstBuilder::GetOrCreateTypedefDecl(PdbGlobalSymId id) {
std::string uname = std::string(DropNameScope(udt.Name));
CompilerType ct = m_clang.CreateTypedefType(ToCompilerType(qt), uname.c_str(),
ToCompilerDeclContext(*scope));
ToCompilerDeclContext(*scope), 0);
clang::TypedefNameDecl *tnd = m_clang.GetAsTypedefDecl(ct);
DeclStatus status;
status.resolved = true;
@ -1012,7 +1015,8 @@ PdbAstBuilder::GetOrCreateFunctionDecl(PdbCompilandSymId func_id) {
proc_name.consume_front("::");
clang::FunctionDecl *function_decl = m_clang.CreateFunctionDeclaration(
parent, proc_name.str().c_str(), func_ct, storage, false);
parent, OptionalClangModuleID(), proc_name.str().c_str(), func_ct,
storage, false);
lldbassert(m_uid_to_decl.count(toOpaqueUid(func_id)) == 0);
m_uid_to_decl[toOpaqueUid(func_id)] = function_decl;
@ -1080,8 +1084,8 @@ void PdbAstBuilder::CreateFunctionParameters(PdbCompilandSymId func_id,
CompilerType param_type_ct = m_clang.GetType(qt);
clang::ParmVarDecl *param = m_clang.CreateParameterDeclaration(
&function_decl, param_name.str().c_str(), param_type_ct,
clang::SC_None, true);
&function_decl, OptionalClangModuleID(), param_name.str().c_str(),
param_type_ct, clang::SC_None, true);
lldbassert(m_uid_to_decl.count(toOpaqueUid(param_uid)) == 0);
m_uid_to_decl[toOpaqueUid(param_uid)] = param;
@ -1102,8 +1106,8 @@ clang::QualType PdbAstBuilder::CreateEnumType(PdbTypeSymId id,
Declaration declaration;
CompilerType enum_ct = m_clang.CreateEnumerationType(
uname.c_str(), decl_context, declaration, ToCompilerType(underlying_type),
er.isScoped());
uname.c_str(), decl_context, OptionalClangModuleID(), declaration,
ToCompilerType(underlying_type), er.isScoped());
TypeSystemClang::StartTagDeclarationDefinition(enum_ct);
TypeSystemClang::SetHasExternalStorage(enum_ct.GetOpaqueQualType(), true);

View File

@ -409,9 +409,9 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
metadata.SetUserID(type.getSymIndexId());
metadata.SetIsDynamicCXXType(false);
clang_type =
m_ast.CreateRecordType(decl_context, access, name, tag_type_kind,
lldb::eLanguageTypeC_plus_plus, &metadata);
clang_type = m_ast.CreateRecordType(
decl_context, OptionalClangModuleID(), access, name, tag_type_kind,
lldb::eLanguageTypeC_plus_plus, &metadata);
assert(clang_type.IsValid());
auto record_decl =
@ -497,7 +497,8 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
// Class). Set it false for now.
bool isScoped = false;
ast_enum = m_ast.CreateEnumerationType(name.c_str(), decl_context, decl,
ast_enum = m_ast.CreateEnumerationType(name.c_str(), decl_context,
OptionalClangModuleID(), decl,
builtin_type, isScoped);
auto enum_decl = TypeSystemClang::GetAsEnumDecl(ast_enum);
@ -550,7 +551,7 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
CompilerType target_ast_type = target_type->GetFullCompilerType();
ast_typedef = m_ast.CreateTypedefType(
target_ast_type, name.c_str(), m_ast.CreateDeclContext(decl_ctx));
target_ast_type, name.c_str(), m_ast.CreateDeclContext(decl_ctx), 0);
if (!ast_typedef)
return nullptr;
@ -901,7 +902,7 @@ PDBASTParser::GetDeclForSymbol(const llvm::pdb::PDBSymbol &symbol) {
return nullptr;
decl = m_ast.CreateVariableDeclaration(
decl_context, name.c_str(),
decl_context, OptionalClangModuleID(), name.c_str(),
ClangUtil::GetQualType(type->GetLayoutCompilerType()));
}
@ -927,8 +928,8 @@ PDBASTParser::GetDeclForSymbol(const llvm::pdb::PDBSymbol &symbol) {
: clang::StorageClass::SC_None;
auto decl = m_ast.CreateFunctionDeclaration(
decl_context, name.c_str(), type->GetForwardCompilerType(), storage,
func->hasInlineAttribute());
decl_context, OptionalClangModuleID(), name.c_str(),
type->GetForwardCompilerType(), storage, func->hasInlineAttribute());
std::vector<clang::ParmVarDecl *> params;
if (std::unique_ptr<PDBSymbolTypeFunctionSig> sig = func->getSignature()) {
@ -941,8 +942,8 @@ PDBASTParser::GetDeclForSymbol(const llvm::pdb::PDBSymbol &symbol) {
continue;
clang::ParmVarDecl *param = m_ast.CreateParameterDeclaration(
decl, nullptr, arg_type->GetForwardCompilerType(),
clang::SC_None, true);
decl, OptionalClangModuleID(), nullptr,
arg_type->GetForwardCompilerType(), clang::SC_None, true);
if (param)
params.push_back(param);
}
@ -1056,8 +1057,8 @@ clang::DeclContext *PDBASTParser::GetDeclContextContainingSymbol(
IsAnonymousNamespaceName(namespace_name) ? nullptr
: namespace_name.data();
clang::NamespaceDecl *namespace_decl =
m_ast.GetUniqueNamespaceDeclaration(namespace_name_c_str,
curr_context);
m_ast.GetUniqueNamespaceDeclaration(
namespace_name_c_str, curr_context, OptionalClangModuleID());
m_parent_to_namespaces[curr_context].insert(namespace_decl);
m_namespaces.insert(namespace_decl);

View File

@ -419,8 +419,9 @@ void SystemRuntimeMacOSX::ReadLibdispatchTSDIndexes() {
CompilerType uint16 =
ast_ctx->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 16);
CompilerType dispatch_tsd_indexes_s = ast_ctx->CreateRecordType(
nullptr, lldb::eAccessPublic, "__lldb_dispatch_tsd_indexes_s",
clang::TTK_Struct, lldb::eLanguageTypeC);
nullptr, OptionalClangModuleID(), lldb::eAccessPublic,
"__lldb_dispatch_tsd_indexes_s", clang::TTK_Struct,
lldb::eLanguageTypeC);
TypeSystemClang::StartTagDeclarationDefinition(dispatch_tsd_indexes_s);
TypeSystemClang::AddFieldToRecordType(dispatch_tsd_indexes_s,

View File

@ -34,6 +34,9 @@
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Frontend/FrontendOptions.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/ModuleMap.h"
#include "clang/Sema/Sema.h"
#include "llvm/Support/Signals.h"
@ -316,10 +319,33 @@ static ClangASTMap &GetASTMap() {
return *g_map_ptr;
}
TypePayloadClang::TypePayloadClang(bool is_complete_objc_class) {
TypePayloadClang::TypePayloadClang(OptionalClangModuleID owning_module,
bool is_complete_objc_class)
: m_payload(owning_module.GetValue()) {
SetIsCompleteObjCClass(is_complete_objc_class);
}
void TypePayloadClang::SetOwningModule(OptionalClangModuleID id) {
assert(id.GetValue() < ObjCClassBit);
bool is_complete = IsCompleteObjCClass();
m_payload = id.GetValue();
SetIsCompleteObjCClass(is_complete);
}
static void SetMemberOwningModule(clang::Decl *member,
const clang::Decl *parent) {
if (!member || !parent)
return;
OptionalClangModuleID id(parent->getOwningModuleID());
if (!id.HasValue())
return;
member->setFromASTFile();
member->setOwningModuleID(id.GetValue());
member->setModuleOwnershipKind(clang::Decl::ModuleOwnershipKind::Visible);
}
char TypeSystemClang::ID;
bool TypeSystemClang::IsOperator(llvm::StringRef name,
@ -505,6 +531,10 @@ static void ParseLangArgs(LangOptions &Opts, InputKind IK, const char *triple) {
//
// FIXME: This is affected by other options (-fno-inline).
Opts.NoInlineDefine = !Opt;
// This is needed to allocate the extra space for the owning module
// on each decl.
Opts.ModulesLocalVisibility = 1;
}
TypeSystemClang::TypeSystemClang(llvm::StringRef name,
@ -1186,12 +1216,60 @@ CompilerType TypeSystemClang::GetTypeForDecl(ObjCInterfaceDecl *decl) {
#pragma mark Structure, Unions, Classes
CompilerType TypeSystemClang::CreateRecordType(DeclContext *decl_ctx,
AccessType access_type,
llvm::StringRef name, int kind,
LanguageType language,
ClangASTMetadata *metadata,
bool exports_symbols) {
void TypeSystemClang::SetOwningModule(clang::Decl *decl,
OptionalClangModuleID owning_module) {
if (!decl || !owning_module.HasValue())
return;
decl->setFromASTFile();
decl->setOwningModuleID(owning_module.GetValue());
decl->setModuleOwnershipKind(clang::Decl::ModuleOwnershipKind::Visible);
if (auto *decl_ctx = llvm::dyn_cast<clang::DeclContext>(decl)) {
decl_ctx->setHasExternalVisibleStorage();
if (auto *ns = llvm::dyn_cast<NamespaceDecl>(decl_ctx))
ns->getPrimaryContext()->setMustBuildLookupTable();
}
}
OptionalClangModuleID
TypeSystemClang::GetOrCreateClangModule(llvm::StringRef name,
OptionalClangModuleID parent,
bool is_framework, bool is_explicit) {
// Get the external AST source which holds the modules.
auto *ast_source = llvm::dyn_cast_or_null<ClangExternalASTSourceCallbacks>(
getASTContext().getExternalSource());
assert(ast_source && "external ast source was lost");
if (!ast_source)
return {};
// Lazily initialize the module map.
if (!m_header_search_up) {
auto HSOpts = std::make_shared<clang::HeaderSearchOptions>();
m_header_search_up = std::make_unique<clang::HeaderSearch>(
HSOpts, *m_source_manager_up, *m_diagnostics_engine_up,
*m_language_options_up, m_target_info_up.get());
m_module_map_up = std::make_unique<clang::ModuleMap>(
*m_source_manager_up, *m_diagnostics_engine_up, *m_language_options_up,
m_target_info_up.get(), *m_header_search_up);
}
// Get or create the module context.
bool created;
clang::Module *module;
auto parent_desc = ast_source->getSourceDescriptor(parent.GetValue());
std::tie(module, created) = m_module_map_up->findOrCreateModule(
name, parent_desc ? parent_desc->getModuleOrNull() : nullptr,
is_framework, is_explicit);
if (!created)
return ast_source->GetIDForModule(module);
return ast_source->RegisterModule(module);
}
CompilerType TypeSystemClang::CreateRecordType(
clang::DeclContext *decl_ctx, OptionalClangModuleID owning_module,
AccessType access_type, llvm::StringRef name, int kind,
LanguageType language, ClangASTMetadata *metadata, bool exports_symbols) {
ASTContext &ast = getASTContext();
if (decl_ctx == nullptr)
@ -1201,7 +1279,8 @@ CompilerType TypeSystemClang::CreateRecordType(DeclContext *decl_ctx,
language == eLanguageTypeObjC_plus_plus) {
bool isForwardDecl = true;
bool isInternal = false;
return CreateObjCClass(name, decl_ctx, isForwardDecl, isInternal, metadata);
return CreateObjCClass(name, decl_ctx, owning_module, isForwardDecl,
isInternal, metadata);
}
// NOTE: Eventually CXXRecordDecl will be merged back into RecordDecl and
@ -1216,6 +1295,7 @@ CompilerType TypeSystemClang::CreateRecordType(DeclContext *decl_ctx,
decl->setDeclContext(decl_ctx);
if (has_name)
decl->setDeclName(&ast.Idents.get(name));
SetOwningModule(decl, owning_module);
if (!has_name) {
// In C++ a lambda is also represented as an unnamed class. This is
@ -1327,13 +1407,13 @@ static TemplateParameterList *CreateTemplateParameterList(
}
clang::FunctionTemplateDecl *TypeSystemClang::CreateFunctionTemplateDecl(
clang::DeclContext *decl_ctx, clang::FunctionDecl *func_decl,
const char *name, const TemplateParameterInfos &template_param_infos) {
clang::DeclContext *decl_ctx, OptionalClangModuleID owning_module,
clang::FunctionDecl *func_decl, const char *name,
const TemplateParameterInfos &template_param_infos) {
// /// Create a function template node.
ASTContext &ast = getASTContext();
llvm::SmallVector<NamedDecl *, 8> template_param_decls;
TemplateParameterList *template_param_list = CreateTemplateParameterList(
ast, template_param_infos, template_param_decls);
FunctionTemplateDecl *func_tmpl_decl =
@ -1342,6 +1422,7 @@ clang::FunctionTemplateDecl *TypeSystemClang::CreateFunctionTemplateDecl(
func_tmpl_decl->setLocation(func_decl->getLocation());
func_tmpl_decl->setDeclName(func_decl->getDeclName());
func_tmpl_decl->init(func_decl, template_param_list);
SetOwningModule(func_tmpl_decl, owning_module);
for (size_t i = 0, template_param_decl_count = template_param_decls.size();
i < template_param_decl_count; ++i) {
@ -1368,8 +1449,9 @@ void TypeSystemClang::CreateFunctionTemplateSpecializationInfo(
}
ClassTemplateDecl *TypeSystemClang::CreateClassTemplateDecl(
DeclContext *decl_ctx, lldb::AccessType access_type, const char *class_name,
int kind, const TemplateParameterInfos &template_param_infos) {
DeclContext *decl_ctx, OptionalClangModuleID owning_module,
lldb::AccessType access_type, const char *class_name, int kind,
const TemplateParameterInfos &template_param_infos) {
ASTContext &ast = getASTContext();
ClassTemplateDecl *class_template_decl = nullptr;
@ -1397,6 +1479,7 @@ ClassTemplateDecl *TypeSystemClang::CreateClassTemplateDecl(
// What decl context do we use here? TU? The actual decl context?
template_cxx_decl->setDeclContext(decl_ctx);
template_cxx_decl->setDeclName(decl_name);
SetOwningModule(template_cxx_decl, owning_module);
for (size_t i = 0, template_param_decl_count = template_param_decls.size();
i < template_param_decl_count; ++i) {
@ -1414,6 +1497,7 @@ ClassTemplateDecl *TypeSystemClang::CreateClassTemplateDecl(
class_template_decl->setDeclName(decl_name);
class_template_decl->init(template_cxx_decl, template_param_list);
template_cxx_decl->setDescribedClassTemplate(class_template_decl);
SetOwningModule(class_template_decl, owning_module);
if (class_template_decl) {
if (access_type != eAccessNone)
@ -1453,7 +1537,8 @@ TypeSystemClang::CreateTemplateTemplateParmDecl(const char *template_name) {
ClassTemplateSpecializationDecl *
TypeSystemClang::CreateClassTemplateSpecializationDecl(
DeclContext *decl_ctx, ClassTemplateDecl *class_template_decl, int kind,
DeclContext *decl_ctx, OptionalClangModuleID owning_module,
ClassTemplateDecl *class_template_decl, int kind,
const TemplateParameterInfos &template_param_infos) {
ASTContext &ast = getASTContext();
llvm::SmallVector<clang::TemplateArgument, 2> args(
@ -1476,6 +1561,16 @@ TypeSystemClang::CreateClassTemplateSpecializationDecl(
ast.getTypeDeclType(class_template_specialization_decl, nullptr);
class_template_specialization_decl->setDeclName(
class_template_decl->getDeclName());
// FIXME: Turning this on breaks the libcxx data formatter tests.
// SetOwningModule marks the Decl as external, which prevents a
// LookupPtr from being built. Template instantiations can also not
// be found by ExternalASTSource::FindExternalVisibleDeclsByName(),
// nor can we lazily build a LookupPtr later, because template
// specializations are supposed to be hidden so
// makeDeclVisibleInContextWithFlags() is a noop, as well.
//
// SetOwningModule(class_template_specialization_decl, owning_module);
decl_ctx->addDecl(class_template_specialization_decl);
class_template_specialization_decl->setSpecializationKind(
TSK_ExplicitSpecialization);
@ -1594,14 +1689,13 @@ bool TypeSystemClang::RecordHasFields(const RecordDecl *record_decl) {
#pragma mark Objective-C Classes
CompilerType TypeSystemClang::CreateObjCClass(llvm::StringRef name,
DeclContext *decl_ctx,
bool isForwardDecl,
bool isInternal,
ClangASTMetadata *metadata) {
CompilerType TypeSystemClang::CreateObjCClass(
llvm::StringRef name, clang::DeclContext *decl_ctx,
OptionalClangModuleID owning_module, bool isForwardDecl, bool isInternal,
ClangASTMetadata *metadata) {
ASTContext &ast = getASTContext();
assert(!name.empty());
if (decl_ctx == nullptr)
if (!decl_ctx)
decl_ctx = ast.getTranslationUnitDecl();
ObjCInterfaceDecl *decl = ObjCInterfaceDecl::CreateDeserialized(ast, 0);
@ -1609,6 +1703,7 @@ CompilerType TypeSystemClang::CreateObjCClass(llvm::StringRef name,
decl->setDeclName(&ast.Idents.get(name));
/*isForwardDecl,*/
decl->setImplicit(isInternal);
SetOwningModule(decl, owning_module);
if (decl && metadata)
SetMetadata(decl, *metadata);
@ -1646,11 +1741,12 @@ TypeSystemClang::GetNumBaseClasses(const CXXRecordDecl *cxx_record_decl,
#pragma mark Namespace Declarations
NamespaceDecl *TypeSystemClang::GetUniqueNamespaceDeclaration(
const char *name, clang::DeclContext *decl_ctx, bool is_inline) {
const char *name, clang::DeclContext *decl_ctx,
OptionalClangModuleID owning_module, bool is_inline) {
NamespaceDecl *namespace_decl = nullptr;
ASTContext &ast = getASTContext();
TranslationUnitDecl *translation_unit_decl = ast.getTranslationUnitDecl();
if (decl_ctx == nullptr)
if (!decl_ctx)
decl_ctx = translation_unit_decl;
if (name) {
@ -1699,17 +1795,23 @@ NamespaceDecl *TypeSystemClang::GetUniqueNamespaceDeclaration(
}
}
}
// Note: namespaces can span multiple modules, so perhaps this isn't a good
// idea.
SetOwningModule(namespace_decl, owning_module);
VerifyDecl(namespace_decl);
return namespace_decl;
}
clang::BlockDecl *
TypeSystemClang::CreateBlockDeclaration(clang::DeclContext *ctx) {
TypeSystemClang::CreateBlockDeclaration(clang::DeclContext *ctx,
OptionalClangModuleID owning_module) {
if (ctx) {
clang::BlockDecl *decl =
clang::BlockDecl::CreateDeserialized(getASTContext(), 0);
decl->setDeclContext(ctx);
ctx->addDecl(decl);
SetOwningModule(decl, owning_module);
return decl;
}
return nullptr;
@ -1733,7 +1835,8 @@ clang::DeclContext *FindLCABetweenDecls(clang::DeclContext *left,
}
clang::UsingDirectiveDecl *TypeSystemClang::CreateUsingDirectiveDeclaration(
clang::DeclContext *decl_ctx, clang::NamespaceDecl *ns_decl) {
clang::DeclContext *decl_ctx, OptionalClangModuleID owning_module,
clang::NamespaceDecl *ns_decl) {
if (decl_ctx && ns_decl) {
auto *translation_unit = getASTContext().getTranslationUnitDecl();
clang::UsingDirectiveDecl *using_decl = clang::UsingDirectiveDecl::Create(
@ -1743,6 +1846,7 @@ clang::UsingDirectiveDecl *TypeSystemClang::CreateUsingDirectiveDeclaration(
FindLCABetweenDecls(decl_ctx, ns_decl,
translation_unit));
decl_ctx->addDecl(using_decl);
SetOwningModule(using_decl, owning_module);
return using_decl;
}
return nullptr;
@ -1750,14 +1854,17 @@ clang::UsingDirectiveDecl *TypeSystemClang::CreateUsingDirectiveDeclaration(
clang::UsingDecl *
TypeSystemClang::CreateUsingDeclaration(clang::DeclContext *current_decl_ctx,
OptionalClangModuleID owning_module,
clang::NamedDecl *target) {
if (current_decl_ctx != nullptr && target != nullptr) {
if (current_decl_ctx && target) {
clang::UsingDecl *using_decl = clang::UsingDecl::Create(
getASTContext(), current_decl_ctx, clang::SourceLocation(),
clang::NestedNameSpecifierLoc(), clang::DeclarationNameInfo(), false);
SetOwningModule(using_decl, owning_module);
clang::UsingShadowDecl *shadow_decl = clang::UsingShadowDecl::Create(
getASTContext(), current_decl_ctx, clang::SourceLocation(), using_decl,
target);
SetOwningModule(shadow_decl, owning_module);
using_decl->addShadowDecl(shadow_decl);
current_decl_ctx->addDecl(using_decl);
return using_decl;
@ -1766,7 +1873,8 @@ TypeSystemClang::CreateUsingDeclaration(clang::DeclContext *current_decl_ctx,
}
clang::VarDecl *TypeSystemClang::CreateVariableDeclaration(
clang::DeclContext *decl_context, const char *name, clang::QualType type) {
clang::DeclContext *decl_context, OptionalClangModuleID owning_module,
const char *name, clang::QualType type) {
if (decl_context) {
clang::VarDecl *var_decl =
clang::VarDecl::CreateDeserialized(getASTContext(), 0);
@ -1774,6 +1882,7 @@ clang::VarDecl *TypeSystemClang::CreateVariableDeclaration(
if (name && name[0])
var_decl->setDeclName(&getASTContext().Idents.getOwn(name));
var_decl->setType(type);
SetOwningModule(var_decl, owning_module);
var_decl->setAccess(clang::AS_public);
decl_context->addDecl(var_decl);
return var_decl;
@ -1885,11 +1994,12 @@ TypeSystemClang::GetDeclarationName(const char *name,
}
FunctionDecl *TypeSystemClang::CreateFunctionDeclaration(
DeclContext *decl_ctx, const char *name,
const CompilerType &function_clang_type, int storage, bool is_inline) {
clang::DeclContext *decl_ctx, OptionalClangModuleID owning_module,
const char *name, const CompilerType &function_clang_type, int storage,
bool is_inline) {
FunctionDecl *func_decl = nullptr;
ASTContext &ast = getASTContext();
if (decl_ctx == nullptr)
if (!decl_ctx)
decl_ctx = ast.getTranslationUnitDecl();
const bool hasWrittenPrototype = true;
@ -1906,6 +2016,7 @@ FunctionDecl *TypeSystemClang::CreateFunctionDeclaration(
func_decl->setHasWrittenPrototype(hasWrittenPrototype);
func_decl->setConstexprKind(isConstexprSpecified ? CSK_constexpr
: CSK_unspecified);
SetOwningModule(func_decl, owning_module);
if (func_decl)
decl_ctx->addDecl(func_decl);
@ -1954,8 +2065,9 @@ TypeSystemClang::CreateFunctionType(const CompilerType &result_type,
}
ParmVarDecl *TypeSystemClang::CreateParameterDeclaration(
clang::DeclContext *decl_ctx, const char *name,
const CompilerType &param_type, int storage, bool add_decl) {
clang::DeclContext *decl_ctx, OptionalClangModuleID owning_module,
const char *name, const CompilerType &param_type, int storage,
bool add_decl) {
ASTContext &ast = getASTContext();
auto *decl = ParmVarDecl::CreateDeserialized(ast, 0);
decl->setDeclContext(decl_ctx);
@ -1963,6 +2075,7 @@ ParmVarDecl *TypeSystemClang::CreateParameterDeclaration(
decl->setDeclName(&ast.Idents.get(name));
decl->setType(ClangUtil::GetQualType(param_type));
decl->setStorageClass(static_cast<clang::StorageClass>(storage));
SetOwningModule(decl, owning_module);
if (add_decl)
decl_ctx->addDecl(decl);
@ -2024,8 +2137,9 @@ CompilerType TypeSystemClang::CreateStructForIdentifier(
return type;
}
type = CreateRecordType(nullptr, lldb::eAccessPublic, type_name.GetCString(),
clang::TTK_Struct, lldb::eLanguageTypeC);
type = CreateRecordType(nullptr, OptionalClangModuleID(), lldb::eAccessPublic,
type_name.GetCString(), clang::TTK_Struct,
lldb::eLanguageTypeC);
StartTagDeclarationDefinition(type);
for (const auto &field : type_fields)
AddFieldToRecordType(type, field.first, field.second, lldb::eAccessPublic,
@ -2050,11 +2164,10 @@ CompilerType TypeSystemClang::GetOrCreateStructForIdentifier(
#pragma mark Enumeration Types
CompilerType
TypeSystemClang::CreateEnumerationType(const char *name, DeclContext *decl_ctx,
const Declaration &decl,
const CompilerType &integer_clang_type,
bool is_scoped) {
CompilerType TypeSystemClang::CreateEnumerationType(
const char *name, clang::DeclContext *decl_ctx,
OptionalClangModuleID owning_module, const Declaration &decl,
const CompilerType &integer_clang_type, bool is_scoped) {
// TODO: Do something intelligent with the Declaration object passed in
// like maybe filling in the SourceLocation with it...
ASTContext &ast = getASTContext();
@ -2068,6 +2181,7 @@ TypeSystemClang::CreateEnumerationType(const char *name, DeclContext *decl_ctx,
enum_decl->setScoped(is_scoped);
enum_decl->setScopedUsingClassTag(is_scoped);
enum_decl->setFixed(false);
SetOwningModule(enum_decl, owning_module);
if (enum_decl) {
if (decl_ctx)
decl_ctx->addDecl(enum_decl);
@ -4254,7 +4368,7 @@ TypeSystemClang::GetNonReferenceType(lldb::opaque_compiler_type_t type) {
CompilerType TypeSystemClang::CreateTypedefType(
const CompilerType &type, const char *typedef_name,
const CompilerDeclContext &compiler_decl_ctx) {
const CompilerDeclContext &compiler_decl_ctx, uint32_t payload) {
if (type && typedef_name && typedef_name[0]) {
TypeSystemClang *ast =
llvm::dyn_cast<TypeSystemClang>(type.GetTypeSystem());
@ -4265,7 +4379,7 @@ CompilerType TypeSystemClang::CreateTypedefType(
clang::DeclContext *decl_ctx =
TypeSystemClang::DeclContextGetAsDeclContext(compiler_decl_ctx);
if (decl_ctx == nullptr)
if (!decl_ctx)
decl_ctx = ast->getASTContext().getTranslationUnitDecl();
clang::TypedefDecl *decl =
@ -4274,6 +4388,7 @@ CompilerType TypeSystemClang::CreateTypedefType(
decl->setDeclName(&clang_ast.Idents.get(typedef_name));
decl->setTypeSourceInfo(clang_ast.getTrivialTypeSourceInfo(qual_type));
SetOwningModule(decl, TypePayloadClang(payload).GetOwningModule());
decl->setAccess(clang::AS_public); // TODO respect proper access specifier
decl_ctx->addDecl(decl);
@ -4362,24 +4477,23 @@ TypeSystemClang::AddRestrictModifier(lldb::opaque_compiler_type_t type) {
return CompilerType();
}
CompilerType
TypeSystemClang::CreateTypedef(lldb::opaque_compiler_type_t type,
const char *typedef_name,
const CompilerDeclContext &compiler_decl_ctx) {
CompilerType TypeSystemClang::CreateTypedef(
lldb::opaque_compiler_type_t type, const char *typedef_name,
const CompilerDeclContext &compiler_decl_ctx, uint32_t payload) {
if (type) {
clang::ASTContext &clang_ast = getASTContext();
clang::QualType qual_type(GetQualType(type));
clang::DeclContext *decl_ctx =
TypeSystemClang::DeclContextGetAsDeclContext(compiler_decl_ctx);
if (decl_ctx == nullptr)
if (!decl_ctx)
decl_ctx = getASTContext().getTranslationUnitDecl();
clang::TypedefDecl *decl =
clang::TypedefDecl::CreateDeserialized(clang_ast, 0);
decl->setDeclContext(decl_ctx);
decl->setDeclName(&clang_ast.Idents.get(typedef_name));
decl->setTypeSourceInfo(clang_ast.getTrivialTypeSourceInfo(qual_type));
clang::TypedefDecl *decl = clang::TypedefDecl::Create(
clang_ast, decl_ctx, clang::SourceLocation(), clang::SourceLocation(),
&clang_ast.Idents.get(typedef_name),
clang_ast.getTrivialTypeSourceInfo(qual_type));
SetOwningModule(decl, TypePayloadClang(payload).GetOwningModule());
clang::TagDecl *tdecl = nullptr;
if (!qual_type.isNull()) {
@ -6923,6 +7037,7 @@ clang::FieldDecl *TypeSystemClang::AddFieldToRecordType(
field->setType(ClangUtil::GetQualType(field_clang_type));
if (bit_width)
field->setBitWidth(bit_width);
SetMemberOwningModule(field, record_decl);
if (name.empty()) {
// Determine whether this field corresponds to an anonymous struct or
@ -6964,6 +7079,7 @@ clang::FieldDecl *TypeSystemClang::AddFieldToRecordType(
ivar->setBitWidth(bit_width);
ivar->setSynthesize(is_synthesized);
field = ivar;
SetMemberOwningModule(field, class_interface_decl);
if (field) {
class_interface_decl->addDecl(field);
@ -7025,6 +7141,7 @@ void TypeSystemClang::BuildIndirectFields(const CompilerType &type) {
ast->getASTContext(), record_decl, clang::SourceLocation(),
nested_field_decl->getIdentifier(),
nested_field_decl->getType(), {chain, 2});
SetMemberOwningModule(indirect_field, record_decl);
indirect_field->setImplicit();
@ -7055,6 +7172,7 @@ void TypeSystemClang::BuildIndirectFields(const CompilerType &type) {
nested_indirect_field_decl->getIdentifier(),
nested_indirect_field_decl->getType(),
{chain, nested_chain_size + 1});
SetMemberOwningModule(indirect_field, record_decl);
indirect_field->setImplicit();
@ -7121,6 +7239,7 @@ clang::VarDecl *TypeSystemClang::AddVariableToRecordType(
var_decl->setDeclName(ident);
var_decl->setType(ClangUtil::GetQualType(var_type));
var_decl->setStorageClass(clang::SC_Static);
SetMemberOwningModule(var_decl, record_decl);
if (!var_decl)
return nullptr;
@ -7256,6 +7375,7 @@ clang::CXXMethodDecl *TypeSystemClang::AddMethodToCXXRecordType(
cxx_method_decl->setConstexprKind(CSK_unspecified);
}
}
SetMemberOwningModule(cxx_method_decl, cxx_record_decl);
clang::AccessSpecifier access_specifier =
TypeSystemClang::ConvertAccessTypeToAccessSpecifier(access);
@ -7430,6 +7550,7 @@ bool TypeSystemClang::AddObjCClassProperty(
? ivar_decl->getType()
: ClangUtil::GetQualType(property_clang_type),
prop_type_source);
SetMemberOwningModule(property_decl, class_interface_decl);
if (!property_decl)
return false;
@ -7521,6 +7642,7 @@ bool TypeSystemClang::AddObjCClassProperty(
getter->setDefined(isDefined);
getter->setDeclImplementation(impControl);
getter->setRelatedResultType(HasRelatedResultType);
SetMemberOwningModule(getter, class_interface_decl);
if (getter) {
if (metadata)
@ -7562,6 +7684,7 @@ bool TypeSystemClang::AddObjCClassProperty(
setter->setDefined(isDefined);
setter->setDeclImplementation(impControl);
setter->setRelatedResultType(HasRelatedResultType);
SetMemberOwningModule(setter, class_interface_decl);
if (setter) {
if (metadata)
@ -7690,6 +7813,7 @@ clang::ObjCMethodDecl *TypeSystemClang::AddMethodToObjCObjectType(
objc_method_decl->setDefined(isDefined);
objc_method_decl->setDeclImplementation(impControl);
objc_method_decl->setRelatedResultType(HasRelatedResultType);
SetMemberOwningModule(objc_method_decl, class_interface_decl);
if (objc_method_decl == nullptr)
return nullptr;
@ -7920,6 +8044,7 @@ clang::EnumConstantDecl *TypeSystemClang::AddEnumerationValueToEnumerationType(
enumerator_decl->setDeclName(&getASTContext().Idents.get(name));
enumerator_decl->setType(clang::QualType(enutype, 0));
enumerator_decl->setInitVal(value);
SetMemberOwningModule(enumerator_decl, enutype->getDecl());
if (!enumerator_decl)
return nullptr;
@ -8814,14 +8939,14 @@ void TypeSystemClang::DumpTypeName(const CompilerType &type) {
}
clang::ClassTemplateDecl *TypeSystemClang::ParseClassTemplateDecl(
clang::DeclContext *decl_ctx, lldb::AccessType access_type,
const char *parent_name, int tag_decl_kind,
clang::DeclContext *decl_ctx, OptionalClangModuleID owning_module,
lldb::AccessType access_type, const char *parent_name, int tag_decl_kind,
const TypeSystemClang::TemplateParameterInfos &template_param_infos) {
if (template_param_infos.IsValid()) {
std::string template_basename(parent_name);
template_basename.erase(template_basename.find('<'));
return CreateClassTemplateDecl(decl_ctx, access_type,
return CreateClassTemplateDecl(decl_ctx, owning_module, access_type,
template_basename.c_str(), tag_decl_kind,
template_param_infos);
}

View File

@ -53,13 +53,30 @@ class ClangASTMetadata;
class ClangASTSource;
class Declaration;
/// A Clang module ID.
class OptionalClangModuleID {
unsigned m_id = 0;
public:
OptionalClangModuleID() = default;
explicit OptionalClangModuleID(unsigned id) : m_id(id) {}
bool HasValue() const { return m_id != 0; }
unsigned GetValue() const { return m_id; }
};
/// The implementation of lldb::Type's m_payload field for TypeSystemClang.
class TypePayloadClang {
/// Layout: bit 31 ... IsCompleteObjCClass.
/// The Layout is as follows:
/// \verbatim
/// bit 0..30 ... Owning Module ID.
/// bit 31 ...... IsCompleteObjCClass.
/// \endverbatim
Type::Payload m_payload = 0;
public:
TypePayloadClang() = default;
explicit TypePayloadClang(bool is_complete_objc_class);
explicit TypePayloadClang(OptionalClangModuleID owning_module,
bool is_complete_objc_class = false);
explicit TypePayloadClang(uint32_t opaque_payload) : m_payload(opaque_payload) {}
operator Type::Payload() { return m_payload; }
@ -69,6 +86,11 @@ public:
m_payload = is_complete_objc_class ? Flags(m_payload).Set(ObjCClassBit)
: Flags(m_payload).Clear(ObjCClassBit);
}
OptionalClangModuleID GetOwningModule() {
return OptionalClangModuleID(Flags(m_payload).Clear(ObjCClassBit));
}
void SetOwningModule(OptionalClangModuleID id);
/// \}
};
/// A TypeSystem implementation based on Clang.
@ -293,7 +315,14 @@ public:
static uint32_t GetNumBaseClasses(const clang::CXXRecordDecl *cxx_record_decl,
bool omit_empty_base_classes);
/// Synthesize a clang::Module and return its ID or a default-constructed ID.
OptionalClangModuleID GetOrCreateClangModule(llvm::StringRef name,
OptionalClangModuleID parent,
bool is_framework = false,
bool is_explicit = false);
CompilerType CreateRecordType(clang::DeclContext *decl_ctx,
OptionalClangModuleID owning_module,
lldb::AccessType access_type,
llvm::StringRef name, int kind,
lldb::LanguageType language,
@ -319,6 +348,7 @@ public:
clang::FunctionTemplateDecl *
CreateFunctionTemplateDecl(clang::DeclContext *decl_ctx,
OptionalClangModuleID owning_module,
clang::FunctionDecl *func_decl, const char *name,
const TemplateParameterInfos &infos);
@ -328,6 +358,7 @@ public:
clang::ClassTemplateDecl *
CreateClassTemplateDecl(clang::DeclContext *decl_ctx,
OptionalClangModuleID owning_module,
lldb::AccessType access_type, const char *class_name,
int kind, const TemplateParameterInfos &infos);
@ -335,7 +366,7 @@ public:
CreateTemplateTemplateParmDecl(const char *template_name);
clang::ClassTemplateSpecializationDecl *CreateClassTemplateSpecializationDecl(
clang::DeclContext *decl_ctx,
clang::DeclContext *decl_ctx, OptionalClangModuleID owning_module,
clang::ClassTemplateDecl *class_template_decl, int kind,
const TemplateParameterInfos &infos);
@ -355,8 +386,9 @@ public:
static bool RecordHasFields(const clang::RecordDecl *record_decl);
CompilerType CreateObjCClass(llvm::StringRef name,
clang::DeclContext *decl_ctx, bool isForwardDecl,
bool isInternal,
clang::DeclContext *decl_ctx,
OptionalClangModuleID owning_module,
bool isForwardDecl, bool isInternal,
ClangASTMetadata *metadata = nullptr);
bool SetTagTypeKind(clang::QualType type, int kind) const;
@ -373,14 +405,16 @@ public:
clang::NamespaceDecl *
GetUniqueNamespaceDeclaration(const char *name, clang::DeclContext *decl_ctx,
OptionalClangModuleID owning_module,
bool is_inline = false);
// Function Types
clang::FunctionDecl *
CreateFunctionDeclaration(clang::DeclContext *decl_ctx, const char *name,
const CompilerType &function_Type, int storage,
bool is_inline);
CreateFunctionDeclaration(clang::DeclContext *decl_ctx,
OptionalClangModuleID owning_module,
const char *name, const CompilerType &function_Type,
int storage, bool is_inline);
CompilerType CreateFunctionType(const CompilerType &result_type,
const CompilerType *args, unsigned num_args,
@ -394,11 +428,11 @@ public:
type_quals, clang::CC_C);
}
clang::ParmVarDecl *CreateParameterDeclaration(clang::DeclContext *decl_ctx,
const char *name,
const CompilerType &param_type,
int storage,
bool add_decl=false);
clang::ParmVarDecl *
CreateParameterDeclaration(clang::DeclContext *decl_ctx,
OptionalClangModuleID owning_module,
const char *name, const CompilerType &param_type,
int storage, bool add_decl = false);
void SetFunctionParameters(clang::FunctionDecl *function_decl,
clang::ParmVarDecl **params, unsigned num_params);
@ -413,6 +447,7 @@ public:
// Enumeration Types
CompilerType CreateEnumerationType(const char *name,
clang::DeclContext *decl_ctx,
OptionalClangModuleID owning_module,
const Declaration &decl,
const CompilerType &integer_qual_type,
bool is_scoped);
@ -479,6 +514,10 @@ public:
/// TypeSystemClang.
CompilerDeclContext CreateDeclContext(clang::DeclContext *ctx);
/// Set the owning module for \p decl.
static void SetOwningModule(clang::Decl *decl,
OptionalClangModuleID owning_module);
std::vector<CompilerDecl>
DeclContextFindDeclByName(void *opaque_decl_ctx, ConstString name,
const bool ignore_using_decls) override;
@ -641,11 +680,13 @@ public:
// Creating related types
// Using the current type, create a new typedef to that type using
// "typedef_name" as the name and "decl_ctx" as the decl context.
/// Using the current type, create a new typedef to that type using
/// "typedef_name" as the name and "decl_ctx" as the decl context.
/// \param payload is an opaque TypePayloadClang.
static CompilerType
CreateTypedefType(const CompilerType &type, const char *typedef_name,
const CompilerDeclContext &compiler_decl_ctx);
const CompilerDeclContext &compiler_decl_ctx,
uint32_t opaque_payload);
CompilerType GetArrayElementType(lldb::opaque_compiler_type_t type,
uint64_t *stride) override;
@ -696,7 +737,8 @@ public:
CompilerType CreateTypedef(lldb::opaque_compiler_type_t type,
const char *name,
const CompilerDeclContext &decl_ctx) override;
const CompilerDeclContext &decl_ctx,
uint32_t opaque_payload) override;
// If the current object represents a typedef type, get the underlying type
CompilerType GetTypedefedType(lldb::opaque_compiler_type_t type) override;
@ -955,20 +997,24 @@ public:
GetAsObjCInterfaceDecl(const CompilerType &type);
clang::ClassTemplateDecl *ParseClassTemplateDecl(
clang::DeclContext *decl_ctx, lldb::AccessType access_type,
const char *parent_name, int tag_decl_kind,
clang::DeclContext *decl_ctx, OptionalClangModuleID owning_module,
lldb::AccessType access_type, const char *parent_name, int tag_decl_kind,
const TypeSystemClang::TemplateParameterInfos &template_param_infos);
clang::BlockDecl *CreateBlockDeclaration(clang::DeclContext *ctx);
clang::BlockDecl *CreateBlockDeclaration(clang::DeclContext *ctx,
OptionalClangModuleID owning_module);
clang::UsingDirectiveDecl *
CreateUsingDirectiveDeclaration(clang::DeclContext *decl_ctx,
OptionalClangModuleID owning_module,
clang::NamespaceDecl *ns_decl);
clang::UsingDecl *CreateUsingDeclaration(clang::DeclContext *current_decl_ctx,
OptionalClangModuleID owning_module,
clang::NamedDecl *target);
clang::VarDecl *CreateVariableDeclaration(clang::DeclContext *decl_context,
OptionalClangModuleID owning_module,
const char *name,
clang::QualType type);
@ -991,6 +1037,13 @@ public:
clang::DeclarationName
GetDeclarationName(const char *name, const CompilerType &function_clang_type);
clang::LangOptions *GetLangOpts() const {
return m_language_options_up.get();
}
clang::SourceManager *GetSourceMgr() const {
return m_source_manager_up.get();
}
private:
const clang::ClassTemplateSpecializationDecl *
GetAsTemplateSpecialization(lldb::opaque_compiler_type_t type);
@ -1008,6 +1061,8 @@ private:
std::unique_ptr<clang::IdentifierTable> m_identifier_table_up;
std::unique_ptr<clang::SelectorTable> m_selector_table_up;
std::unique_ptr<clang::Builtin::Context> m_builtins_up;
std::unique_ptr<clang::HeaderSearch> m_header_search_up;
std::unique_ptr<clang::ModuleMap> m_module_map_up;
std::unique_ptr<DWARFASTParserClang> m_dwarf_ast_parser_up;
std::unique_ptr<PDBASTParser> m_pdb_ast_parser_up;
std::unique_ptr<clang::MangleContext> m_mangle_ctx_up;

View File

@ -439,11 +439,11 @@ CompilerType CompilerType::AddRestrictModifier() const {
return CompilerType();
}
CompilerType
CompilerType::CreateTypedef(const char *name,
const CompilerDeclContext &decl_ctx) const {
CompilerType CompilerType::CreateTypedef(const char *name,
const CompilerDeclContext &decl_ctx,
uint32_t payload) const {
if (IsValid())
return m_type_system->CreateTypedef(m_type, name, decl_ctx);
return m_type_system->CreateTypedef(m_type, name, decl_ctx, payload);
else
return CompilerType();
}

View File

@ -505,7 +505,7 @@ bool Type::ResolveCompilerType(ResolveState compiler_type_resolve_state) {
case eEncodingIsTypedefUID:
m_compiler_type = encoding_type->GetForwardCompilerType().CreateTypedef(
m_name.AsCString("__lldb_invalid_typedef_name"),
GetSymbolFile()->GetDeclContextContainingUID(GetID()));
GetSymbolFile()->GetDeclContextContainingUID(GetID()), m_payload);
m_name.Clear();
break;
@ -563,7 +563,7 @@ bool Type::ResolveCompilerType(ResolveState compiler_type_resolve_state) {
case eEncodingIsTypedefUID:
m_compiler_type = void_compiler_type.CreateTypedef(
m_name.AsCString("__lldb_invalid_typedef_name"),
GetSymbolFile()->GetDeclContextContainingUID(GetID()));
GetSymbolFile()->GetDeclContextContainingUID(GetID()), m_payload);
break;
case eEncodingIsPointerUID:

View File

@ -113,7 +113,8 @@ TypeSystem::AddRestrictModifier(lldb::opaque_compiler_type_t type) {
CompilerType TypeSystem::CreateTypedef(lldb::opaque_compiler_type_t type,
const char *name,
const CompilerDeclContext &decl_ctx) {
const CompilerDeclContext &decl_ctx,
uint32_t opaque_payload) {
return CompilerType();
}

View File

@ -0,0 +1,29 @@
#include "B.h" // -*- ObjC -*-
typedef int Typedef;
struct TopLevelStruct {
int a;
};
typedef struct Struct_s {
int a;
} Struct;
struct Nested {
StructB fromb;
};
typedef enum Enum_e { a = 0 } Enum;
@interface SomeClass {
}
@end
template <typename T> struct Template { T field; };
extern template struct Template<int>;
namespace Namespace {
template <typename T> struct InNamespace { T field; };
extern template struct InNamespace<int>;
}

View File

@ -0,0 +1,8 @@
typedef struct {
int b;
} StructB;
namespace Namespace {
template <typename T> struct AlsoInNamespace { T field; };
extern template struct AlsoInNamespace<int>;
} // namespace Namespace

View File

@ -0,0 +1,6 @@
module A {
header "A.h"
module B {
header "B.h"
}
}

View File

@ -1 +1 @@
config.suffixes = ['.cpp', '.m', '.s', '.test', '.ll']
config.suffixes = ['.cpp', '.m', '.mm', '.s', '.test', '.ll']

View File

@ -0,0 +1,42 @@
// RUN: %clang --target=x86_64-apple-macosx -g -gmodules \
// RUN: -fmodules -fmodules-cache-path=%t.cache \
// RUN: -c -o %t.o %s -I%S/Inputs
// RUN: lldb-test symbols -dump-clang-ast %t.o | FileCheck %s
// Verify that the owning module information from DWARF is preserved in the AST.
@import A;
Typedef t1;
// CHECK-DAG: TypedefDecl {{.*}} imported in A Typedef
TopLevelStruct s1;
// CHECK-DAG: CXXRecordDecl {{.*}} imported in A struct TopLevelStruct
// CHECK-DAG: -FieldDecl {{.*}} in A a 'int'
Struct s2;
// CHECK-DAG: CXXRecordDecl {{.*}} imported in A struct
StructB s3;
// CHECK-DAG: CXXRecordDecl {{.*}} imported in A.B struct
// CHECK-DAG: -FieldDecl {{.*}} in A.B b 'int'
Nested s4;
// CHECK-DAG: CXXRecordDecl {{.*}} imported in A struct Nested
// CHECK-DAG: -FieldDecl {{.*}} in A fromb 'StructB'
Enum e1;
// CHECK-DAG: EnumDecl {{.*}} imported in A {{.*}} Enum_e
// FIXME: -EnumConstantDecl {{.*}} imported in A a
SomeClass *obj1;
// CHECK-DAG: ObjCInterfaceDecl {{.*}} imported in A {{.*}} SomeClass
// Template specializations are not yet supported, so they lack the ownership info:
Template<int> t2;
// CHECK-DAG: ClassTemplateSpecializationDecl {{.*}} struct Template
Namespace::InNamespace<int> t3;
// CHECK-DAG: ClassTemplateSpecializationDecl {{.*}} struct InNamespace
Namespace::AlsoInNamespace<int> t4;
// CHECK-DAG: ClassTemplateSpecializationDecl {{.*}} struct AlsoInNamespace

View File

@ -14,6 +14,7 @@
#include "lldb/Host/HostInfo.h"
#include "lldb/Symbol/Declaration.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/ExprCXX.h"
#include "gtest/gtest.h"
@ -257,9 +258,10 @@ TEST_F(TestTypeSystemClang, TestGetEnumIntegerTypeBasicTypes) {
CompilerType basic_compiler_type = ast.GetBasicType(basic_type);
EXPECT_TRUE(basic_compiler_type.IsValid());
CompilerType enum_type =
ast.CreateEnumerationType("my_enum", ast.GetTranslationUnitDecl(),
Declaration(), basic_compiler_type, scoped);
CompilerType enum_type = ast.CreateEnumerationType(
"my_enum", ast.GetTranslationUnitDecl(), OptionalClangModuleID(),
Declaration(), basic_compiler_type, scoped);
CompilerType t = ast.GetEnumerationIntegerType(enum_type);
// Check that the type we put in at the start is found again.
EXPECT_EQ(basic_compiler_type.GetTypeName(), t.GetTypeName());
@ -267,14 +269,39 @@ TEST_F(TestTypeSystemClang, TestGetEnumIntegerTypeBasicTypes) {
}
}
TEST_F(TestTypeSystemClang, TestOwningModule) {
TypeSystemClang ast("module_ast", HostInfo::GetTargetTriple());
CompilerType basic_compiler_type = ast.GetBasicType(BasicType::eBasicTypeInt);
CompilerType enum_type = ast.CreateEnumerationType(
"my_enum", ast.GetTranslationUnitDecl(), OptionalClangModuleID(100),
Declaration(), basic_compiler_type, false);
auto *ed = TypeSystemClang::GetAsEnumDecl(enum_type);
EXPECT_FALSE(!ed);
EXPECT_EQ(ed->getOwningModuleID(), 100u);
CompilerType record_type = ast.CreateRecordType(
nullptr, OptionalClangModuleID(200), lldb::eAccessPublic, "FooRecord",
clang::TTK_Struct, lldb::eLanguageTypeC_plus_plus, nullptr);
auto *rd = TypeSystemClang::GetAsRecordDecl(record_type);
EXPECT_FALSE(!rd);
EXPECT_EQ(rd->getOwningModuleID(), 200u);
CompilerType class_type =
ast.CreateObjCClass("objc_class", ast.GetTranslationUnitDecl(),
OptionalClangModuleID(300), false, false);
auto *cd = TypeSystemClang::GetAsObjCInterfaceDecl(class_type);
EXPECT_FALSE(!cd);
EXPECT_EQ(cd->getOwningModuleID(), 300u);
}
TEST_F(TestTypeSystemClang, TestIsClangType) {
clang::ASTContext &context = m_ast->getASTContext();
lldb::opaque_compiler_type_t bool_ctype =
TypeSystemClang::GetOpaqueCompilerType(&context, lldb::eBasicTypeBool);
CompilerType bool_type(m_ast.get(), bool_ctype);
CompilerType record_type = m_ast->CreateRecordType(
nullptr, lldb::eAccessPublic, "FooRecord", clang::TTK_Struct,
lldb::eLanguageTypeC_plus_plus, nullptr);
nullptr, OptionalClangModuleID(100), lldb::eAccessPublic, "FooRecord",
clang::TTK_Struct, lldb::eLanguageTypeC_plus_plus, nullptr);
// Clang builtin type and record type should pass
EXPECT_TRUE(ClangUtil::IsClangType(bool_type));
EXPECT_TRUE(ClangUtil::IsClangType(record_type));
@ -285,8 +312,8 @@ TEST_F(TestTypeSystemClang, TestIsClangType) {
TEST_F(TestTypeSystemClang, TestRemoveFastQualifiers) {
CompilerType record_type = m_ast->CreateRecordType(
nullptr, lldb::eAccessPublic, "FooRecord", clang::TTK_Struct,
lldb::eLanguageTypeC_plus_plus, nullptr);
nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "FooRecord",
clang::TTK_Struct, lldb::eLanguageTypeC_plus_plus, nullptr);
QualType qt;
qt = ClangUtil::GetQualType(record_type);
@ -357,8 +384,8 @@ TEST_F(TestTypeSystemClang, TestRecordHasFields) {
// Test that a record with no fields returns false
CompilerType empty_base = m_ast->CreateRecordType(
nullptr, lldb::eAccessPublic, "EmptyBase", clang::TTK_Struct,
lldb::eLanguageTypeC_plus_plus, nullptr);
nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "EmptyBase",
clang::TTK_Struct, lldb::eLanguageTypeC_plus_plus, nullptr);
TypeSystemClang::StartTagDeclarationDefinition(empty_base);
TypeSystemClang::CompleteTagDeclarationDefinition(empty_base);
@ -368,8 +395,8 @@ TEST_F(TestTypeSystemClang, TestRecordHasFields) {
// Test that a record with direct fields returns true
CompilerType non_empty_base = m_ast->CreateRecordType(
nullptr, lldb::eAccessPublic, "NonEmptyBase", clang::TTK_Struct,
lldb::eLanguageTypeC_plus_plus, nullptr);
nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "NonEmptyBase",
clang::TTK_Struct, lldb::eLanguageTypeC_plus_plus, nullptr);
TypeSystemClang::StartTagDeclarationDefinition(non_empty_base);
FieldDecl *non_empty_base_field_decl = m_ast->AddFieldToRecordType(
non_empty_base, "MyField", int_type, eAccessPublic, 0);
@ -384,8 +411,8 @@ TEST_F(TestTypeSystemClang, TestRecordHasFields) {
// Test that a record with no direct fields, but fields in a base returns true
CompilerType empty_derived = m_ast->CreateRecordType(
nullptr, lldb::eAccessPublic, "EmptyDerived", clang::TTK_Struct,
lldb::eLanguageTypeC_plus_plus, nullptr);
nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "EmptyDerived",
clang::TTK_Struct, lldb::eLanguageTypeC_plus_plus, nullptr);
TypeSystemClang::StartTagDeclarationDefinition(empty_derived);
std::unique_ptr<clang::CXXBaseSpecifier> non_empty_base_spec =
m_ast->CreateBaseClassSpecifier(non_empty_base.GetOpaqueQualType(),
@ -407,8 +434,8 @@ TEST_F(TestTypeSystemClang, TestRecordHasFields) {
// Test that a record with no direct fields, but fields in a virtual base
// returns true
CompilerType empty_derived2 = m_ast->CreateRecordType(
nullptr, lldb::eAccessPublic, "EmptyDerived2", clang::TTK_Struct,
lldb::eLanguageTypeC_plus_plus, nullptr);
nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "EmptyDerived2",
clang::TTK_Struct, lldb::eLanguageTypeC_plus_plus, nullptr);
TypeSystemClang::StartTagDeclarationDefinition(empty_derived2);
std::unique_ptr<CXXBaseSpecifier> non_empty_vbase_spec =
m_ast->CreateBaseClassSpecifier(non_empty_base.GetOpaqueQualType(),
@ -439,13 +466,15 @@ TEST_F(TestTypeSystemClang, TemplateArguments) {
// template<typename T, int I> struct foo;
ClassTemplateDecl *decl = m_ast->CreateClassTemplateDecl(
m_ast->GetTranslationUnitDecl(), eAccessPublic, "foo", TTK_Struct, infos);
m_ast->GetTranslationUnitDecl(), OptionalClangModuleID(), eAccessPublic,
"foo", TTK_Struct, infos);
ASSERT_NE(decl, nullptr);
// foo<int, 47>
ClassTemplateSpecializationDecl *spec_decl =
m_ast->CreateClassTemplateSpecializationDecl(
m_ast->GetTranslationUnitDecl(), decl, TTK_Struct, infos);
m_ast->GetTranslationUnitDecl(), OptionalClangModuleID(), decl,
TTK_Struct, infos);
ASSERT_NE(spec_decl, nullptr);
CompilerType type = m_ast->CreateClassTemplateSpecializationType(spec_decl);
ASSERT_TRUE(type);
@ -454,7 +483,8 @@ TEST_F(TestTypeSystemClang, TemplateArguments) {
// typedef foo<int, 47> foo_def;
CompilerType typedef_type = m_ast->CreateTypedefType(
type, "foo_def", m_ast->CreateDeclContext(m_ast->GetTranslationUnitDecl()));
type, "foo_def",
m_ast->CreateDeclContext(m_ast->GetTranslationUnitDecl()), 0);
CompilerType auto_type(
m_ast.get(),
@ -528,13 +558,14 @@ TEST_F(TestTypeSystemClang, TestFunctionTemplateConstruction) {
// Prepare the declarations/types we need for the template.
CompilerType clang_type =
m_ast->CreateFunctionType(int_type, nullptr, 0U, false, 0U);
FunctionDecl *func =
m_ast->CreateFunctionDeclaration(TU, "foo", clang_type, 0, false);
FunctionDecl *func = m_ast->CreateFunctionDeclaration(
TU, OptionalClangModuleID(), "foo", clang_type, 0, false);
TypeSystemClang::TemplateParameterInfos empty_params;
// Create the actual function template.
clang::FunctionTemplateDecl *func_template =
m_ast->CreateFunctionTemplateDecl(TU, func, "foo", empty_params);
m_ast->CreateFunctionTemplateDecl(TU, OptionalClangModuleID(), func,
"foo", empty_params);
EXPECT_EQ(TU, func_template->getDeclContext());
EXPECT_EQ("foo", func_template->getName());
@ -558,13 +589,14 @@ TEST_F(TestTypeSystemClang, TestFunctionTemplateInRecordConstruction) {
// We create the FunctionDecl for the template in the TU DeclContext because:
// 1. FunctionDecls can't be in a Record (only CXXMethodDecls can).
// 2. It is mirroring the behavior of DWARFASTParserClang::ParseSubroutine.
FunctionDecl *func =
m_ast->CreateFunctionDeclaration(TU, "foo", clang_type, 0, false);
FunctionDecl *func = m_ast->CreateFunctionDeclaration(
TU, OptionalClangModuleID(), "foo", clang_type, 0, false);
TypeSystemClang::TemplateParameterInfos empty_params;
// Create the actual function template.
clang::FunctionTemplateDecl *func_template =
m_ast->CreateFunctionTemplateDecl(record, func, "foo", empty_params);
m_ast->CreateFunctionTemplateDecl(record, OptionalClangModuleID(), func,
"foo", empty_params);
EXPECT_EQ(record, func_template->getDeclContext());
EXPECT_EQ("foo", func_template->getName());

View File

@ -28,6 +28,7 @@ inline std::unique_ptr<TypeSystemClang> createAST() {
inline CompilerType createRecord(TypeSystemClang &ast, llvm::StringRef name) {
return ast.CreateRecordType(ast.getASTContext().getTranslationUnitDecl(),
OptionalClangModuleID(),
lldb::AccessType::eAccessPublic, name, 0,
lldb::LanguageType::eLanguageTypeC);
}