From a2f7462a5d1b2d9b8408ec53947c7984b1cb279e Mon Sep 17 00:00:00 2001 From: Jake Hillion Date: Wed, 16 Aug 2023 12:44:58 -0700 Subject: [PATCH] DrgnParser: store type of template param value --- oi/type_graph/DrgnParser.cpp | 44 ++++++++++++++++---------------- oi/type_graph/Flattener.cpp | 6 ++--- oi/type_graph/NameGen.cpp | 2 +- oi/type_graph/Printer.cpp | 3 +-- oi/type_graph/TypeIdentifier.cpp | 26 +++++++++---------- oi/type_graph/Types.h | 14 +++++----- test/TypeGraphParser.cpp | 27 +++++++++----------- test/test_drgn_parser.cpp | 7 +++++ test/test_flattener.cpp | 1 + test/test_name_gen.cpp | 7 ++--- test/test_prune.cpp | 1 + test/test_topo_sorter.cpp | 3 ++- 12 files changed, 74 insertions(+), 67 deletions(-) diff --git a/oi/type_graph/DrgnParser.cpp b/oi/type_graph/DrgnParser.cpp index 21412b9..e9397a7 100644 --- a/oi/type_graph/DrgnParser.cpp +++ b/oi/type_graph/DrgnParser.cpp @@ -282,8 +282,27 @@ void DrgnParser::enumerateTemplateParam(struct drgn_type* type, drgn_type_template_parameter* tparams, size_t i, std::vector& params) { + drgn_qualified_type tparamQualType; + struct drgn_error* err = + drgn_template_parameter_type(&tparams[i], &tparamQualType); + if (err) { + warnForDrgnError( + type, + "Error looking up template parameter type (" + std::to_string(i) + ")", + err); + return; + } + + struct drgn_type* tparamType = tparamQualType.type; + + QualifierSet qualifiers; + qualifiers[Qualifier::Const] = + (tparamQualType.qualifiers & DRGN_QUALIFIER_CONST); + + auto& ttype = enumerateType(tparamType); + const drgn_object* obj = nullptr; - if (auto* err = drgn_template_parameter_object(&tparams[i], &obj)) { + if (err = drgn_template_parameter_object(&tparams[i], &obj); err != nullptr) { warnForDrgnError(type, "Error looking up template parameter object (" + std::to_string(i) + ")", @@ -291,26 +310,7 @@ void DrgnParser::enumerateTemplateParam(struct drgn_type* type, return; } - struct drgn_qualified_type tparamQualType; if (obj == nullptr) { - // This template parameter is a typename - struct drgn_error* err = - drgn_template_parameter_type(&tparams[i], &tparamQualType); - if (err) { - warnForDrgnError(type, - "Error looking up template parameter type (" + - std::to_string(i) + ")", - err); - return; - } - - struct drgn_type* tparamType = tparamQualType.type; - - QualifierSet qualifiers; - qualifiers[Qualifier::Const] = - (tparamQualType.qualifiers & DRGN_QUALIFIER_CONST); - - auto& ttype = enumerateType(tparamType); params.emplace_back(ttype, qualifiers); } else { // This template parameter is a value @@ -319,7 +319,7 @@ void DrgnParser::enumerateTemplateParam(struct drgn_type* type, if (drgn_type_kind(obj->type) == DRGN_TYPE_ENUM) { char* nameStr = nullptr; size_t length = 0; - auto* err = drgn_type_fully_qualified_name(obj->type, &nameStr, &length); + err = drgn_type_fully_qualified_name(obj->type, &nameStr, &length); if (err != nullptr || nameStr == nullptr) { throw DrgnParserError{"Failed to get enum's fully qualified name", err}; } @@ -383,7 +383,7 @@ void DrgnParser::enumerateTemplateParam(struct drgn_type* type, } } - params.emplace_back(std::move(value)); + params.emplace_back(ttype, std::move(value)); } } diff --git a/oi/type_graph/Flattener.cpp b/oi/type_graph/Flattener.cpp index 34b93f3..62a32e3 100644 --- a/oi/type_graph/Flattener.cpp +++ b/oi/type_graph/Flattener.cpp @@ -100,13 +100,13 @@ void fixAllocatorParams(Class& alloc) { return; } - Type* allocParam = parentClass->templateParams[0].type(); - if (!allocParam) { + if (parentClass->templateParams[0].value) { // Nothing we can do return; } - Type& typeToAllocate = stripTypedefs(*allocParam); + Type& allocParam = parentClass->templateParams[0].type(); + Type& typeToAllocate = stripTypedefs(allocParam); alloc.templateParams.push_back(TemplateParam{typeToAllocate}); } } // namespace diff --git a/oi/type_graph/NameGen.cpp b/oi/type_graph/NameGen.cpp index b1060a7..577f5c1 100644 --- a/oi/type_graph/NameGen.cpp +++ b/oi/type_graph/NameGen.cpp @@ -113,7 +113,7 @@ void NameGen::visit(Container& c) { if (param.value) { name += *param.value; } else { - name += param.type()->name(); + name += param.type().name(); // The "const" keyword must come after the type name so that pointers are // handled correctly. // diff --git a/oi/type_graph/Printer.cpp b/oi/type_graph/Printer.cpp index fdae0b0..574892a 100644 --- a/oi/type_graph/Printer.cpp +++ b/oi/type_graph/Printer.cpp @@ -162,9 +162,8 @@ void Printer::print_param(const TemplateParam& param) { out_ << "Param" << std::endl; if (param.value) { print_value(*param.value); - } else { - print(*param.type()); } + print(param.type()); print_qualifiers(param.qualifiers); depth_--; } diff --git a/oi/type_graph/TypeIdentifier.cpp b/oi/type_graph/TypeIdentifier.cpp index 8fb297f..b9e6f44 100644 --- a/oi/type_graph/TypeIdentifier.cpp +++ b/oi/type_graph/TypeIdentifier.cpp @@ -60,22 +60,22 @@ void TypeIdentifier::visit(Container& c) { // TODO these two arrays could be looped over in sync for better performance for (size_t i = 0; i < c.templateParams.size(); i++) { const auto& param = c.templateParams[i]; - if (dynamic_cast(param.type()) || - dynamic_cast(param.type()) || - dynamic_cast(param.type())) { + if (dynamic_cast(¶m.type()) || + dynamic_cast(¶m.type()) || + dynamic_cast(¶m.type())) { // In case the TypeIdentifier pass is run multiple times, we don't want to // replace dummies again as the context of the original replacement has // been lost. continue; } - if (Class* paramClass = dynamic_cast(param.type())) { + if (Class* paramClass = dynamic_cast(¶m.type())) { bool replaced = false; for (const auto& info : passThroughTypes_) { if (std::regex_search(paramClass->fqName(), info.matcher)) { // Create dummy containers auto& dummy = - typeGraph_.makeType(info, param.type()->size()); + typeGraph_.makeType(info, param.type().size()); dummy.templateParams = paramClass->templateParams; c.templateParams[i] = dummy; replaced = true; @@ -89,22 +89,22 @@ void TypeIdentifier::visit(Container& c) { if (std::find(stubParams.begin(), stubParams.end(), i) != stubParams.end()) { - size_t size = param.type()->size(); + size_t size = param.type().size(); if (size == 1) { // Hack: when we get a reported size of 1 for these parameters, it // turns out that a size of 0 is actually expected. size = 0; } - if (isAllocator(*param.type())) { - auto* allocator = - dynamic_cast(param.type()); // TODO please don't do this... - Type& typeToAllocate = *allocator->templateParams.at(0).type(); - auto& dummy = typeGraph_.makeType( - typeToAllocate, size, param.type()->align()); + if (isAllocator(param.type())) { + auto* allocator = dynamic_cast( + ¶m.type()); // TODO please don't do this... + Type& typeToAllocate = allocator->templateParams.at(0).type(); + auto& dummy = typeGraph_.makeType(typeToAllocate, size, + param.type().align()); c.templateParams[i] = dummy; } else { - auto& dummy = typeGraph_.makeType(size, param.type()->align()); + auto& dummy = typeGraph_.makeType(size, param.type().align()); c.templateParams[i] = dummy; } } diff --git a/oi/type_graph/Types.h b/oi/type_graph/Types.h index 141b695..7f43a9a 100644 --- a/oi/type_graph/Types.h +++ b/oi/type_graph/Types.h @@ -143,23 +143,23 @@ struct Parent { uint64_t bitOffset; }; -class TemplateParam { - public: +struct TemplateParam { // TODO make ctors explicit - TemplateParam(Type& type) : type_(&type) { + TemplateParam(Type& type) : type_(type) { } TemplateParam(Type& type, QualifierSet qualifiers) - : type_(&type), qualifiers(qualifiers) { + : type_(type), qualifiers(qualifiers) { } - TemplateParam(std::string value) : value(std::move(value)) { + TemplateParam(Type& type, std::string value) + : type_(type), value(std::move(value)) { } - Type* type() const { + Type& type() const { return type_; } private: - Type* type_ = nullptr; // Note: type is not set when this param holds a value + std::reference_wrapper type_; public: QualifierSet qualifiers; diff --git a/test/TypeGraphParser.cpp b/test/TypeGraphParser.cpp index 0afb233..803a186 100644 --- a/test/TypeGraphParser.cpp +++ b/test/TypeGraphParser.cpp @@ -314,22 +314,19 @@ void TypeGraphParser::parseParams(T& c, if (!tryRemovePrefix(line, "Param")) break; - if (auto value = tryParseStringValue(input, "Value: ", rootIndent + 2); - value) { - c.templateParams.emplace_back(std::string{*value}); - } else { - Type& type = parseType(input, rootIndent + 2); - TemplateParam param{type}; - - if (auto qualStr = - tryParseStringValue(input, "Qualifiers: ", rootIndent + 2); - qualStr) { - Qualifier qual = getQualifier(*qualStr); - param.qualifiers[qual] = true; - } - - c.templateParams.push_back(param); + auto value = tryParseStringValue(input, "Value: ", rootIndent + 2); + Type& type = parseType(input, rootIndent + 2); + TemplateParam param{type}; + if (value) + param.value = value; + if (auto qualStr = + tryParseStringValue(input, "Qualifiers: ", rootIndent + 2); + qualStr) { + Qualifier qual = getQualifier(*qualStr); + param.qualifiers[qual] = true; } + + c.templateParams.push_back(param); } // No more params for us - put back the line we just read input = origInput; diff --git a/test/test_drgn_parser.cpp b/test/test_drgn_parser.cpp index 4e8aedd..fd6498b 100644 --- a/test/test_drgn_parser.cpp +++ b/test/test_drgn_parser.cpp @@ -450,6 +450,7 @@ TEST_F(DrgnParserTest, ClassTemplateValue) { [0] Struct: TemplatedClassVal<3> (size: 12) Param Value: 3 + Primitive: int32_t Member: arr (offset: 0) [1] Array: (length: 3) Primitive: int32_t @@ -463,12 +464,14 @@ TEST_F(DrgnParserTest, TemplateEnumValue) { [0] Class: MyClass (size: 4) Param Value: ns_enums_params::MyNS::ScopedEnum::One + Enum: ScopedEnum (size: 4) )", R"( [1] Pointer [0] Class: MyClass<(ns_enums_params::MyNS::ScopedEnum)1> (size: 4) Param Value: ns_enums_params::MyNS::ScopedEnum::One + Enum: ScopedEnum (size: 4) )"); } @@ -479,12 +482,14 @@ TEST_F(DrgnParserTest, TemplateEnumValueGaps) { [0] Class: ClassGaps (size: 4) Param Value: ns_enums_params::MyNS::EnumWithGaps::Twenty + Enum: EnumWithGaps (size: 4) )", R"( [1] Pointer [0] Class: ClassGaps<(ns_enums_params::MyNS::EnumWithGaps)20> (size: 4) Param Value: ns_enums_params::MyNS::EnumWithGaps::Twenty + Enum: EnumWithGaps (size: 4) )"); } @@ -495,12 +500,14 @@ TEST_F(DrgnParserTest, TemplateEnumValueNegative) { [0] Class: ClassGaps (size: 4) Param Value: ns_enums_params::MyNS::EnumWithGaps::MinusTwo + Enum: EnumWithGaps (size: 4) )", R"( [1] Pointer [0] Class: ClassGaps<(ns_enums_params::MyNS::EnumWithGaps)-2> (size: 4) Param Value: ns_enums_params::MyNS::EnumWithGaps::MinusTwo + Enum: EnumWithGaps (size: 4) )"); } diff --git a/test/test_flattener.cpp b/test/test_flattener.cpp index b958b33..1b07341 100644 --- a/test/test_flattener.cpp +++ b/test/test_flattener.cpp @@ -914,6 +914,7 @@ TEST(FlattenerTest, AllocatorUnfixableParentParamIsValue) { [2] Struct: MyAllocBase (size: 1) Param Value: 123 + Primitive: int32_t Function: allocate Function: deallocate Function: allocate diff --git a/test/test_name_gen.cpp b/test/test_name_gen.cpp index e829a54..0ab4573 100644 --- a/test/test_name_gen.cpp +++ b/test/test_name_gen.cpp @@ -205,14 +205,15 @@ TEST(NameGenTest, ContainerParamsValue) { auto myenum = Enum{"MyEnum", 4}; auto mycontainer = getVector(); - mycontainer.templateParams.push_back(TemplateParam{"123"}); - mycontainer.templateParams.push_back(TemplateParam{"MyEnum::OptionC"}); + mycontainer.templateParams.push_back(TemplateParam{myint, "123"}); + mycontainer.templateParams.push_back( + TemplateParam{myenum, "MyEnum::OptionC"}); NameGen nameGen; nameGen.generateNames({mycontainer}); EXPECT_EQ(myint.name(), "int32_t"); - EXPECT_EQ(myenum.name(), "MyEnum"); + EXPECT_EQ(myenum.name(), "MyEnum_0"); EXPECT_EQ(mycontainer.name(), "std::vector<123, MyEnum::OptionC>"); } diff --git a/test/test_prune.cpp b/test/test_prune.cpp index ff948b1..0ab05ae 100644 --- a/test/test_prune.cpp +++ b/test/test_prune.cpp @@ -12,6 +12,7 @@ TEST(PruneTest, PruneClass) { Primitive: int32_t Param Value: "123" + Primitive: int32_t Parent (offset: 0) [1] Class: MyParent (size: 4) Member: a (offset: 0) diff --git a/test/test_topo_sorter.cpp b/test/test_topo_sorter.cpp index b7756f0..3c136b6 100644 --- a/test/test_topo_sorter.cpp +++ b/test/test_topo_sorter.cpp @@ -94,7 +94,8 @@ MyClass TEST(TopoSorterTest, TemplateParamValue) { auto myclass = Class{1, Class::Kind::Class, "MyClass", 69}; - myclass.templateParams.push_back(TemplateParam{"123"}); + auto myint = Primitive{Primitive::Kind::Int32}; + myclass.templateParams.push_back(TemplateParam{myint, "123"}); test({myclass}, R"( MyClass