Skip to content

[lldb][TypeSystem] Ensure that ParmVarDecls have the correct DeclContext #124279

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jan 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 16 additions & 20 deletions lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1272,7 +1272,7 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die,
return_clang_type = m_ast.GetBasicType(eBasicTypeVoid);

std::vector<CompilerType> function_param_types;
std::vector<clang::ParmVarDecl *> function_param_decls;
llvm::SmallVector<llvm::StringRef> function_param_names;

// Parse the function children for the parameters

Expand All @@ -1284,7 +1284,7 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die,
if (die.HasChildren()) {
ParseChildParameters(containing_decl_ctx, die, is_variadic,
has_template_params, function_param_types,
function_param_decls);
function_param_names);
}

bool is_cxx_method = DeclKindIsCXXClass(containing_decl_ctx->getDeclKind());
Expand Down Expand Up @@ -1414,12 +1414,14 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die,

LinkDeclContextToDIE(function_decl, die);

if (!function_param_decls.empty()) {
m_ast.SetFunctionParameters(function_decl, function_param_decls);
if (template_function_decl)
m_ast.SetFunctionParameters(template_function_decl,
function_param_decls);
}
const clang::FunctionProtoType *function_prototype(
llvm::cast<clang::FunctionProtoType>(
ClangUtil::GetQualType(clang_type).getTypePtr()));
const auto params = m_ast.CreateParameterDeclarations(
function_decl, *function_prototype, function_param_names);
function_decl->setParams(params);
if (template_function_decl)
template_function_decl->setParams(params);

ClangASTMetadata metadata;
metadata.SetUserID(die.GetID());
Expand Down Expand Up @@ -2380,7 +2382,7 @@ DWARFASTParserClang::ConstructDemangledNameFromDWARF(const DWARFDIE &die) {
bool is_variadic = false;
bool has_template_params = false;
std::vector<CompilerType> param_types;
std::vector<clang::ParmVarDecl *> param_decls;
llvm::SmallVector<llvm::StringRef> param_names;
StreamString sstr;

DWARFDeclContext decl_ctx = die.GetDWARFDeclContext();
Expand All @@ -2394,7 +2396,7 @@ DWARFASTParserClang::ConstructDemangledNameFromDWARF(const DWARFDIE &die) {
die, GetCXXObjectParameter(die, *containing_decl_ctx));

ParseChildParameters(containing_decl_ctx, die, is_variadic,
has_template_params, param_types, param_decls);
has_template_params, param_types, param_names);
sstr << "(";
for (size_t i = 0; i < param_types.size(); i++) {
if (i > 0)
Expand Down Expand Up @@ -3157,7 +3159,7 @@ void DWARFASTParserClang::ParseChildParameters(
clang::DeclContext *containing_decl_ctx, const DWARFDIE &parent_die,
bool &is_variadic, bool &has_template_params,
std::vector<CompilerType> &function_param_types,
std::vector<clang::ParmVarDecl *> &function_param_decls) {
llvm::SmallVectorImpl<llvm::StringRef> &function_param_names) {
if (!parent_die)
return;

Expand All @@ -3168,22 +3170,14 @@ void DWARFASTParserClang::ParseChildParameters(
if (die.GetAttributeValueAsUnsigned(DW_AT_artificial, 0))
continue;

const char *name = die.GetName();
DWARFDIE param_type_die = die.GetAttributeValueAsReferenceDIE(DW_AT_type);

Type *type = die.ResolveTypeUID(param_type_die);
if (!type)
break;

function_param_names.emplace_back(die.GetName());
function_param_types.push_back(type->GetForwardCompilerType());

clang::ParmVarDecl *param_var_decl = m_ast.CreateParameterDeclaration(
containing_decl_ctx, GetOwningClangModule(die), name,
type->GetForwardCompilerType(), clang::StorageClass::SC_None);
assert(param_var_decl);
function_param_decls.push_back(param_var_decl);

m_ast.SetMetadataAsUserID(param_var_decl, die.GetID());
} break;

case DW_TAG_unspecified_parameters:
Expand All @@ -3205,6 +3199,8 @@ void DWARFASTParserClang::ParseChildParameters(
break;
}
}

assert(function_param_names.size() == function_param_names.size());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like typo? Comparing with self.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hah good catch! yea that's meant to say:

assert(function_param_types.size() == function_param_names.size());

}

clang::Decl *DWARFASTParserClang::GetClangDeclForDIE(const DWARFDIE &die) {
Expand Down
12 changes: 6 additions & 6 deletions lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,12 +186,12 @@ class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser {
const lldb::AccessType default_accessibility,
lldb_private::ClangASTImporter::LayoutInfo &layout_info);

void
ParseChildParameters(clang::DeclContext *containing_decl_ctx,
const lldb_private::plugin::dwarf::DWARFDIE &parent_die,
bool &is_variadic, bool &has_template_params,
std::vector<lldb_private::CompilerType> &function_args,
std::vector<clang::ParmVarDecl *> &function_param_decls);
void ParseChildParameters(
clang::DeclContext *containing_decl_ctx,
const lldb_private::plugin::dwarf::DWARFDIE &parent_die,
bool &is_variadic, bool &has_template_params,
std::vector<lldb_private::CompilerType> &function_param_types,
llvm::SmallVectorImpl<llvm::StringRef> &function_param_names);

size_t ParseChildEnumerators(
const lldb_private::CompilerType &compiler_type, bool is_signed,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1137,7 +1137,7 @@ void PdbAstBuilder::CreateFunctionParameters(PdbCompilandSymId func_id,
}

if (!params.empty() && params.size() == param_count)
m_clang.SetFunctionParameters(&function_decl, params);
function_decl.setParams(params);
}

clang::QualType PdbAstBuilder::CreateEnumType(PdbTypeSymId id,
Expand Down
4 changes: 2 additions & 2 deletions lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -975,8 +975,8 @@ PDBASTParser::GetDeclForSymbol(const llvm::pdb::PDBSymbol &symbol) {
}
}
}
if (params.size())
m_ast.SetFunctionParameters(decl, params);
if (params.size() && decl)
decl->setParams(params);

m_uid_to_decl[sym_id] = decl;

Expand Down
50 changes: 30 additions & 20 deletions lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2217,12 +2217,6 @@ ParmVarDecl *TypeSystemClang::CreateParameterDeclaration(
return decl;
}

void TypeSystemClang::SetFunctionParameters(
FunctionDecl *function_decl, llvm::ArrayRef<ParmVarDecl *> params) {
if (function_decl)
function_decl->setParams(params);
}

CompilerType
TypeSystemClang::CreateBlockPointerType(const CompilerType &function_type) {
QualType block_type = m_ast_up->getBlockPointerType(
Expand Down Expand Up @@ -7708,6 +7702,32 @@ void TypeSystemClang::SetFloatingInitializerForVariable(
ast, init_value, true, qt.getUnqualifiedType(), SourceLocation()));
}

llvm::SmallVector<clang::ParmVarDecl *>
TypeSystemClang::CreateParameterDeclarations(
clang::FunctionDecl *func, const clang::FunctionProtoType &prototype,
const llvm::SmallVector<llvm::StringRef> &parameter_names) {
assert(func);
assert(parameter_names.empty() ||
parameter_names.size() == prototype.getNumParams());

llvm::SmallVector<clang::ParmVarDecl *, 12> params;
for (unsigned param_index = 0; param_index < prototype.getNumParams();
++param_index) {
llvm::StringRef name =
!parameter_names.empty() ? parameter_names[param_index] : "";

auto *param =
CreateParameterDeclaration(func, /*owning_module=*/{}, name.data(),
GetType(prototype.getParamType(param_index)),
clang::SC_None, /*add_decl=*/false);
assert(param);

params.push_back(param);
}

return params;
}

clang::CXXMethodDecl *TypeSystemClang::AddMethodToCXXRecordType(
lldb::opaque_compiler_type_t type, llvm::StringRef name,
const char *mangled_name, const CompilerType &method_clang_type,
Expand Down Expand Up @@ -7848,20 +7868,10 @@ clang::CXXMethodDecl *TypeSystemClang::AddMethodToCXXRecordType(
getASTContext(), mangled_name, /*literal=*/false));
}

// Populate the method decl with parameter decls

llvm::SmallVector<clang::ParmVarDecl *, 12> params;

for (unsigned param_index = 0; param_index < num_params; ++param_index) {
params.push_back(clang::ParmVarDecl::Create(
getASTContext(), cxx_method_decl, clang::SourceLocation(),
clang::SourceLocation(),
nullptr, // anonymous
method_function_prototype->getParamType(param_index), nullptr,
clang::SC_None, nullptr));
}

cxx_method_decl->setParams(llvm::ArrayRef<clang::ParmVarDecl *>(params));
// Parameters on member function declarations in DWARF generally don't
// have names, so we omit them when creating the ParmVarDecls.
cxx_method_decl->setParams(CreateParameterDeclarations(
cxx_method_decl, *method_function_prototype, /*parameter_names=*/{}));

AddAccessSpecifierDecl(cxx_record_decl, getASTContext(),
GetCXXRecordDeclAccess(cxx_record_decl),
Expand Down
21 changes: 18 additions & 3 deletions lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
Original file line number Diff line number Diff line change
Expand Up @@ -489,9 +489,6 @@ class TypeSystemClang : public TypeSystem {
const char *name, const CompilerType &param_type,
int storage, bool add_decl = false);

void SetFunctionParameters(clang::FunctionDecl *function_decl,
llvm::ArrayRef<clang::ParmVarDecl *> params);

CompilerType CreateBlockPointerType(const CompilerType &function_type);

// Array Types
Expand Down Expand Up @@ -976,6 +973,24 @@ class TypeSystemClang : public TypeSystem {
SetFloatingInitializerForVariable(clang::VarDecl *var,
const llvm::APFloat &init_value);

/// For each parameter type of \c prototype, creates a \c clang::ParmVarDecl
/// whose \c clang::DeclContext is \c context.
///
/// \param[in] context Non-null \c clang::FunctionDecl which will be the \c
/// clang::DeclContext of each parameter created/returned by this function.
/// \param[in] prototype The \c clang::FunctionProtoType of \c context.
/// \param[in] param_names The ith element of this vector contains the name
/// of the ith parameter. This parameter may be unnamed, in which case the
/// ith entry in \c param_names is an empty string. This vector is either
/// empty, or will have an entry for *each* parameter of the prototype
/// regardless of whether a parameter is unnamed or not.
///
/// \returns A list of newly created of non-null \c clang::ParmVarDecl (one
/// for each parameter of \c prototype).
llvm::SmallVector<clang::ParmVarDecl *> CreateParameterDeclarations(
clang::FunctionDecl *context, const clang::FunctionProtoType &prototype,
const llvm::SmallVector<llvm::StringRef> &param_names);

clang::CXXMethodDecl *AddMethodToCXXRecordType(
lldb::opaque_compiler_type_t type, llvm::StringRef name,
const char *mangled_name, const CompilerType &method_type,
Expand Down
42 changes: 42 additions & 0 deletions lldb/unittests/Symbol/TestTypeSystemClang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1040,3 +1040,45 @@ TEST_F(TestTypeSystemClang, GetDeclContextByNameWhenMissingSymbolFile) {

EXPECT_TRUE(decls.empty());
}

TEST_F(TestTypeSystemClang, AddMethodToCXXRecordType_ParmVarDecls) {
// Tests that AddMethodToCXXRecordType creates ParmVarDecl's with
// a correct clang::DeclContext.

llvm::StringRef class_name = "S";
CompilerType t = clang_utils::createRecord(*m_ast, class_name);
m_ast->StartTagDeclarationDefinition(t);

CompilerType return_type = m_ast->GetBasicType(lldb::eBasicTypeVoid);
const bool is_virtual = false;
const bool is_static = false;
const bool is_inline = false;
const bool is_explicit = true;
const bool is_attr_used = false;
const bool is_artificial = false;

llvm::SmallVector<CompilerType> param_types{
m_ast->GetBasicType(lldb::eBasicTypeInt),
m_ast->GetBasicType(lldb::eBasicTypeShort)};
CompilerType function_type = m_ast->CreateFunctionType(
return_type, param_types.data(), /*num_params*/ param_types.size(),
/*variadic=*/false, /*quals*/ 0U);
m_ast->AddMethodToCXXRecordType(
t.GetOpaqueQualType(), "myFunc", nullptr, function_type,
lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline,
is_explicit, is_attr_used, is_artificial);

// Complete the definition and check the created record.
m_ast->CompleteTagDeclarationDefinition(t);

auto *record = llvm::cast<CXXRecordDecl>(ClangUtil::GetAsTagDecl(t));

auto method_it = record->method_begin();
ASSERT_NE(method_it, record->method_end());

EXPECT_EQ(method_it->getNumParams(), param_types.size());

// DeclContext of each parameter should be the CXXMethodDecl itself.
EXPECT_EQ(method_it->getParamDecl(0)->getDeclContext(), *method_it);
EXPECT_EQ(method_it->getParamDecl(1)->getDeclContext(), *method_it);
}
Loading
Loading