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,
|
||||
size_t i,
|
||||
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;
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
//
|
||||
|
@ -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_--;
|
||||
}
|
||||
|
@ -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<Dummy*>(param.type()) ||
|
||||
dynamic_cast<DummyAllocator*>(param.type()) ||
|
||||
dynamic_cast<Container*>(param.type())) {
|
||||
if (dynamic_cast<Dummy*>(¶m.type()) ||
|
||||
dynamic_cast<DummyAllocator*>(¶m.type()) ||
|
||||
dynamic_cast<Container*>(¶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<Class*>(param.type())) {
|
||||
if (Class* paramClass = dynamic_cast<Class*>(¶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<Container>(info, param.type()->size());
|
||||
typeGraph_.makeType<Container>(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<Class*>(param.type()); // TODO please don't do this...
|
||||
Type& typeToAllocate = *allocator->templateParams.at(0).type();
|
||||
auto& dummy = typeGraph_.makeType<DummyAllocator>(
|
||||
typeToAllocate, size, param.type()->align());
|
||||
if (isAllocator(param.type())) {
|
||||
auto* allocator = dynamic_cast<Class*>(
|
||||
¶m.type()); // TODO please don't do this...
|
||||
Type& typeToAllocate = allocator->templateParams.at(0).type();
|
||||
auto& dummy = typeGraph_.makeType<DummyAllocator>(typeToAllocate, size,
|
||||
param.type().align());
|
||||
c.templateParams[i] = dummy;
|
||||
} else {
|
||||
auto& dummy = typeGraph_.makeType<Dummy>(size, param.type()->align());
|
||||
auto& dummy = typeGraph_.makeType<Dummy>(size, param.type().align());
|
||||
c.templateParams[i] = dummy;
|
||||
}
|
||||
}
|
||||
|
@ -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> type_;
|
||||
|
||||
public:
|
||||
QualifierSet qualifiers;
|
||||
|
@ -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;
|
||||
|
@ -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<ns_enums_params::MyNS::ScopedEnum::One> (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<ns_enums_params::MyNS::EnumWithGaps::Twenty> (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<ns_enums_params::MyNS::EnumWithGaps::MinusTwo> (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)
|
||||
)");
|
||||
}
|
||||
|
||||
|
@ -914,6 +914,7 @@ TEST(FlattenerTest, AllocatorUnfixableParentParamIsValue) {
|
||||
[2] Struct: MyAllocBase (size: 1)
|
||||
Param
|
||||
Value: 123
|
||||
Primitive: int32_t
|
||||
Function: allocate
|
||||
Function: deallocate
|
||||
Function: allocate
|
||||
|
@ -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>");
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user