mirror of
https://github.com/JakeHillion/object-introspection.git
synced 2024-11-09 21:24:14 +00:00
DrgnParser: store type of template param value
This commit is contained in:
parent
ca0c71fa40
commit
a2f7462a5d
@ -282,8 +282,27 @@ void DrgnParser::enumerateTemplateParam(struct drgn_type* type,
|
|||||||
drgn_type_template_parameter* tparams,
|
drgn_type_template_parameter* tparams,
|
||||||
size_t i,
|
size_t i,
|
||||||
std::vector<TemplateParam>& params) {
|
std::vector<TemplateParam>& 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;
|
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,
|
warnForDrgnError(type,
|
||||||
"Error looking up template parameter object (" +
|
"Error looking up template parameter object (" +
|
||||||
std::to_string(i) + ")",
|
std::to_string(i) + ")",
|
||||||
@ -291,26 +310,7 @@ void DrgnParser::enumerateTemplateParam(struct drgn_type* type,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct drgn_qualified_type tparamQualType;
|
|
||||||
if (obj == nullptr) {
|
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);
|
params.emplace_back(ttype, qualifiers);
|
||||||
} else {
|
} else {
|
||||||
// This template parameter is a value
|
// 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) {
|
if (drgn_type_kind(obj->type) == DRGN_TYPE_ENUM) {
|
||||||
char* nameStr = nullptr;
|
char* nameStr = nullptr;
|
||||||
size_t length = 0;
|
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) {
|
if (err != nullptr || nameStr == nullptr) {
|
||||||
throw DrgnParserError{"Failed to get enum's fully qualified name", err};
|
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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,13 +100,13 @@ void fixAllocatorParams(Class& alloc) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Type* allocParam = parentClass->templateParams[0].type();
|
if (parentClass->templateParams[0].value) {
|
||||||
if (!allocParam) {
|
|
||||||
// Nothing we can do
|
// Nothing we can do
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Type& typeToAllocate = stripTypedefs(*allocParam);
|
Type& allocParam = parentClass->templateParams[0].type();
|
||||||
|
Type& typeToAllocate = stripTypedefs(allocParam);
|
||||||
alloc.templateParams.push_back(TemplateParam{typeToAllocate});
|
alloc.templateParams.push_back(TemplateParam{typeToAllocate});
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -113,7 +113,7 @@ void NameGen::visit(Container& c) {
|
|||||||
if (param.value) {
|
if (param.value) {
|
||||||
name += *param.value;
|
name += *param.value;
|
||||||
} else {
|
} else {
|
||||||
name += param.type()->name();
|
name += param.type().name();
|
||||||
// The "const" keyword must come after the type name so that pointers are
|
// The "const" keyword must come after the type name so that pointers are
|
||||||
// handled correctly.
|
// handled correctly.
|
||||||
//
|
//
|
||||||
|
@ -162,9 +162,8 @@ void Printer::print_param(const TemplateParam& param) {
|
|||||||
out_ << "Param" << std::endl;
|
out_ << "Param" << std::endl;
|
||||||
if (param.value) {
|
if (param.value) {
|
||||||
print_value(*param.value);
|
print_value(*param.value);
|
||||||
} else {
|
|
||||||
print(*param.type());
|
|
||||||
}
|
}
|
||||||
|
print(param.type());
|
||||||
print_qualifiers(param.qualifiers);
|
print_qualifiers(param.qualifiers);
|
||||||
depth_--;
|
depth_--;
|
||||||
}
|
}
|
||||||
|
@ -60,22 +60,22 @@ void TypeIdentifier::visit(Container& c) {
|
|||||||
// TODO these two arrays could be looped over in sync for better performance
|
// TODO these two arrays could be looped over in sync for better performance
|
||||||
for (size_t i = 0; i < c.templateParams.size(); i++) {
|
for (size_t i = 0; i < c.templateParams.size(); i++) {
|
||||||
const auto& param = c.templateParams[i];
|
const auto& param = c.templateParams[i];
|
||||||
if (dynamic_cast<Dummy*>(param.type()) ||
|
if (dynamic_cast<Dummy*>(¶m.type()) ||
|
||||||
dynamic_cast<DummyAllocator*>(param.type()) ||
|
dynamic_cast<DummyAllocator*>(¶m.type()) ||
|
||||||
dynamic_cast<Container*>(param.type())) {
|
dynamic_cast<Container*>(¶m.type())) {
|
||||||
// In case the TypeIdentifier pass is run multiple times, we don't want to
|
// 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
|
// replace dummies again as the context of the original replacement has
|
||||||
// been lost.
|
// been lost.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Class* paramClass = dynamic_cast<Class*>(param.type())) {
|
if (Class* paramClass = dynamic_cast<Class*>(¶m.type())) {
|
||||||
bool replaced = false;
|
bool replaced = false;
|
||||||
for (const auto& info : passThroughTypes_) {
|
for (const auto& info : passThroughTypes_) {
|
||||||
if (std::regex_search(paramClass->fqName(), info.matcher)) {
|
if (std::regex_search(paramClass->fqName(), info.matcher)) {
|
||||||
// Create dummy containers
|
// Create dummy containers
|
||||||
auto& dummy =
|
auto& dummy =
|
||||||
typeGraph_.makeType<Container>(info, param.type()->size());
|
typeGraph_.makeType<Container>(info, param.type().size());
|
||||||
dummy.templateParams = paramClass->templateParams;
|
dummy.templateParams = paramClass->templateParams;
|
||||||
c.templateParams[i] = dummy;
|
c.templateParams[i] = dummy;
|
||||||
replaced = true;
|
replaced = true;
|
||||||
@ -89,22 +89,22 @@ void TypeIdentifier::visit(Container& c) {
|
|||||||
|
|
||||||
if (std::find(stubParams.begin(), stubParams.end(), i) !=
|
if (std::find(stubParams.begin(), stubParams.end(), i) !=
|
||||||
stubParams.end()) {
|
stubParams.end()) {
|
||||||
size_t size = param.type()->size();
|
size_t size = param.type().size();
|
||||||
if (size == 1) {
|
if (size == 1) {
|
||||||
// Hack: when we get a reported size of 1 for these parameters, it
|
// Hack: when we get a reported size of 1 for these parameters, it
|
||||||
// turns out that a size of 0 is actually expected.
|
// turns out that a size of 0 is actually expected.
|
||||||
size = 0;
|
size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isAllocator(*param.type())) {
|
if (isAllocator(param.type())) {
|
||||||
auto* allocator =
|
auto* allocator = dynamic_cast<Class*>(
|
||||||
dynamic_cast<Class*>(param.type()); // TODO please don't do this...
|
¶m.type()); // TODO please don't do this...
|
||||||
Type& typeToAllocate = *allocator->templateParams.at(0).type();
|
Type& typeToAllocate = allocator->templateParams.at(0).type();
|
||||||
auto& dummy = typeGraph_.makeType<DummyAllocator>(
|
auto& dummy = typeGraph_.makeType<DummyAllocator>(typeToAllocate, size,
|
||||||
typeToAllocate, size, param.type()->align());
|
param.type().align());
|
||||||
c.templateParams[i] = dummy;
|
c.templateParams[i] = dummy;
|
||||||
} else {
|
} else {
|
||||||
auto& dummy = typeGraph_.makeType<Dummy>(size, param.type()->align());
|
auto& dummy = typeGraph_.makeType<Dummy>(size, param.type().align());
|
||||||
c.templateParams[i] = dummy;
|
c.templateParams[i] = dummy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -143,23 +143,23 @@ struct Parent {
|
|||||||
uint64_t bitOffset;
|
uint64_t bitOffset;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TemplateParam {
|
struct TemplateParam {
|
||||||
public:
|
|
||||||
// TODO make ctors explicit
|
// TODO make ctors explicit
|
||||||
TemplateParam(Type& type) : type_(&type) {
|
TemplateParam(Type& type) : type_(type) {
|
||||||
}
|
}
|
||||||
TemplateParam(Type& type, QualifierSet qualifiers)
|
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_;
|
return type_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Type* type_ = nullptr; // Note: type is not set when this param holds a value
|
std::reference_wrapper<Type> type_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QualifierSet qualifiers;
|
QualifierSet qualifiers;
|
||||||
|
@ -314,22 +314,19 @@ void TypeGraphParser::parseParams(T& c,
|
|||||||
if (!tryRemovePrefix(line, "Param"))
|
if (!tryRemovePrefix(line, "Param"))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (auto value = tryParseStringValue(input, "Value: ", rootIndent + 2);
|
auto value = tryParseStringValue(input, "Value: ", rootIndent + 2);
|
||||||
value) {
|
Type& type = parseType(input, rootIndent + 2);
|
||||||
c.templateParams.emplace_back(std::string{*value});
|
TemplateParam param{type};
|
||||||
} else {
|
if (value)
|
||||||
Type& type = parseType(input, rootIndent + 2);
|
param.value = value;
|
||||||
TemplateParam param{type};
|
if (auto qualStr =
|
||||||
|
tryParseStringValue(input, "Qualifiers: ", rootIndent + 2);
|
||||||
if (auto qualStr =
|
qualStr) {
|
||||||
tryParseStringValue(input, "Qualifiers: ", rootIndent + 2);
|
Qualifier qual = getQualifier(*qualStr);
|
||||||
qualStr) {
|
param.qualifiers[qual] = true;
|
||||||
Qualifier qual = getQualifier(*qualStr);
|
|
||||||
param.qualifiers[qual] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
c.templateParams.push_back(param);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c.templateParams.push_back(param);
|
||||||
}
|
}
|
||||||
// No more params for us - put back the line we just read
|
// No more params for us - put back the line we just read
|
||||||
input = origInput;
|
input = origInput;
|
||||||
|
@ -450,6 +450,7 @@ TEST_F(DrgnParserTest, ClassTemplateValue) {
|
|||||||
[0] Struct: TemplatedClassVal<3> (size: 12)
|
[0] Struct: TemplatedClassVal<3> (size: 12)
|
||||||
Param
|
Param
|
||||||
Value: 3
|
Value: 3
|
||||||
|
Primitive: int32_t
|
||||||
Member: arr (offset: 0)
|
Member: arr (offset: 0)
|
||||||
[1] Array: (length: 3)
|
[1] Array: (length: 3)
|
||||||
Primitive: int32_t
|
Primitive: int32_t
|
||||||
@ -463,12 +464,14 @@ TEST_F(DrgnParserTest, TemplateEnumValue) {
|
|||||||
[0] Class: MyClass<ns_enums_params::MyNS::ScopedEnum::One> (size: 4)
|
[0] Class: MyClass<ns_enums_params::MyNS::ScopedEnum::One> (size: 4)
|
||||||
Param
|
Param
|
||||||
Value: ns_enums_params::MyNS::ScopedEnum::One
|
Value: ns_enums_params::MyNS::ScopedEnum::One
|
||||||
|
Enum: ScopedEnum (size: 4)
|
||||||
)",
|
)",
|
||||||
R"(
|
R"(
|
||||||
[1] Pointer
|
[1] Pointer
|
||||||
[0] Class: MyClass<(ns_enums_params::MyNS::ScopedEnum)1> (size: 4)
|
[0] Class: MyClass<(ns_enums_params::MyNS::ScopedEnum)1> (size: 4)
|
||||||
Param
|
Param
|
||||||
Value: ns_enums_params::MyNS::ScopedEnum::One
|
Value: ns_enums_params::MyNS::ScopedEnum::One
|
||||||
|
Enum: ScopedEnum (size: 4)
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -479,12 +482,14 @@ TEST_F(DrgnParserTest, TemplateEnumValueGaps) {
|
|||||||
[0] Class: ClassGaps<ns_enums_params::MyNS::EnumWithGaps::Twenty> (size: 4)
|
[0] Class: ClassGaps<ns_enums_params::MyNS::EnumWithGaps::Twenty> (size: 4)
|
||||||
Param
|
Param
|
||||||
Value: ns_enums_params::MyNS::EnumWithGaps::Twenty
|
Value: ns_enums_params::MyNS::EnumWithGaps::Twenty
|
||||||
|
Enum: EnumWithGaps (size: 4)
|
||||||
)",
|
)",
|
||||||
R"(
|
R"(
|
||||||
[1] Pointer
|
[1] Pointer
|
||||||
[0] Class: ClassGaps<(ns_enums_params::MyNS::EnumWithGaps)20> (size: 4)
|
[0] Class: ClassGaps<(ns_enums_params::MyNS::EnumWithGaps)20> (size: 4)
|
||||||
Param
|
Param
|
||||||
Value: ns_enums_params::MyNS::EnumWithGaps::Twenty
|
Value: ns_enums_params::MyNS::EnumWithGaps::Twenty
|
||||||
|
Enum: EnumWithGaps (size: 4)
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -495,12 +500,14 @@ TEST_F(DrgnParserTest, TemplateEnumValueNegative) {
|
|||||||
[0] Class: ClassGaps<ns_enums_params::MyNS::EnumWithGaps::MinusTwo> (size: 4)
|
[0] Class: ClassGaps<ns_enums_params::MyNS::EnumWithGaps::MinusTwo> (size: 4)
|
||||||
Param
|
Param
|
||||||
Value: ns_enums_params::MyNS::EnumWithGaps::MinusTwo
|
Value: ns_enums_params::MyNS::EnumWithGaps::MinusTwo
|
||||||
|
Enum: EnumWithGaps (size: 4)
|
||||||
)",
|
)",
|
||||||
R"(
|
R"(
|
||||||
[1] Pointer
|
[1] Pointer
|
||||||
[0] Class: ClassGaps<(ns_enums_params::MyNS::EnumWithGaps)-2> (size: 4)
|
[0] Class: ClassGaps<(ns_enums_params::MyNS::EnumWithGaps)-2> (size: 4)
|
||||||
Param
|
Param
|
||||||
Value: ns_enums_params::MyNS::EnumWithGaps::MinusTwo
|
Value: ns_enums_params::MyNS::EnumWithGaps::MinusTwo
|
||||||
|
Enum: EnumWithGaps (size: 4)
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -914,6 +914,7 @@ TEST(FlattenerTest, AllocatorUnfixableParentParamIsValue) {
|
|||||||
[2] Struct: MyAllocBase (size: 1)
|
[2] Struct: MyAllocBase (size: 1)
|
||||||
Param
|
Param
|
||||||
Value: 123
|
Value: 123
|
||||||
|
Primitive: int32_t
|
||||||
Function: allocate
|
Function: allocate
|
||||||
Function: deallocate
|
Function: deallocate
|
||||||
Function: allocate
|
Function: allocate
|
||||||
|
@ -205,14 +205,15 @@ TEST(NameGenTest, ContainerParamsValue) {
|
|||||||
auto myenum = Enum{"MyEnum", 4};
|
auto myenum = Enum{"MyEnum", 4};
|
||||||
|
|
||||||
auto mycontainer = getVector();
|
auto mycontainer = getVector();
|
||||||
mycontainer.templateParams.push_back(TemplateParam{"123"});
|
mycontainer.templateParams.push_back(TemplateParam{myint, "123"});
|
||||||
mycontainer.templateParams.push_back(TemplateParam{"MyEnum::OptionC"});
|
mycontainer.templateParams.push_back(
|
||||||
|
TemplateParam{myenum, "MyEnum::OptionC"});
|
||||||
|
|
||||||
NameGen nameGen;
|
NameGen nameGen;
|
||||||
nameGen.generateNames({mycontainer});
|
nameGen.generateNames({mycontainer});
|
||||||
|
|
||||||
EXPECT_EQ(myint.name(), "int32_t");
|
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>");
|
EXPECT_EQ(mycontainer.name(), "std::vector<123, MyEnum::OptionC>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ TEST(PruneTest, PruneClass) {
|
|||||||
Primitive: int32_t
|
Primitive: int32_t
|
||||||
Param
|
Param
|
||||||
Value: "123"
|
Value: "123"
|
||||||
|
Primitive: int32_t
|
||||||
Parent (offset: 0)
|
Parent (offset: 0)
|
||||||
[1] Class: MyParent (size: 4)
|
[1] Class: MyParent (size: 4)
|
||||||
Member: a (offset: 0)
|
Member: a (offset: 0)
|
||||||
|
@ -94,7 +94,8 @@ MyClass
|
|||||||
|
|
||||||
TEST(TopoSorterTest, TemplateParamValue) {
|
TEST(TopoSorterTest, TemplateParamValue) {
|
||||||
auto myclass = Class{1, Class::Kind::Class, "MyClass", 69};
|
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"(
|
test({myclass}, R"(
|
||||||
MyClass
|
MyClass
|
||||||
|
Loading…
Reference in New Issue
Block a user