mirror of
https://github.com/JakeHillion/object-introspection.git
synced 2024-11-12 21:56:54 +00:00
TypeGraph: Fix handling for classes which inherit from containers
We previously moved container identification later in CodeGen in order to preserve information for AlignmentCalc. However, Flattener needs to know if a class is a container in order to apply its special handling for this case. This new approach moves container identification in front of Flattener, but has Container own a type node, representing its layout. This underlying type node can be used for calculating a container's alignment in a later pass.
This commit is contained in:
parent
aa87c3f2d1
commit
688d483c0c
@ -1157,9 +1157,9 @@ void CodeGen::transform(TypeGraph& typeGraph) {
|
||||
|
||||
// Simplify the type graph first so there is less work for later passes
|
||||
pm.addPass(RemoveTopLevelPointer::createPass());
|
||||
pm.addPass(IdentifyContainers::createPass(containerInfos_));
|
||||
pm.addPass(Flattener::createPass());
|
||||
pm.addPass(AlignmentCalc::createPass());
|
||||
pm.addPass(IdentifyContainers::createPass(containerInfos_));
|
||||
pm.addPass(TypeIdentifier::createPass(config_.passThroughTypes));
|
||||
if (config_.features[Feature::PruneTypeGraph])
|
||||
pm.addPass(Prune::createPass());
|
||||
@ -1173,9 +1173,9 @@ void CodeGen::transform(TypeGraph& typeGraph) {
|
||||
pm.addPass(AddChildren::createPass(drgnParser, symbols_));
|
||||
|
||||
// Re-run passes over newly added children
|
||||
pm.addPass(IdentifyContainers::createPass(containerInfos_));
|
||||
pm.addPass(Flattener::createPass());
|
||||
pm.addPass(AlignmentCalc::createPass());
|
||||
pm.addPass(IdentifyContainers::createPass(containerInfos_));
|
||||
pm.addPass(TypeIdentifier::createPass(config_.passThroughTypes));
|
||||
if (config_.features[Feature::PruneTypeGraph])
|
||||
pm.addPass(Prune::createPass());
|
||||
|
@ -48,15 +48,7 @@ void AlignmentCalc::accept(Type& type) {
|
||||
}
|
||||
|
||||
void AlignmentCalc::visit(Class& c) {
|
||||
for (const auto& param : c.templateParams) {
|
||||
accept(param.type());
|
||||
}
|
||||
for (const auto& parent : c.parents) {
|
||||
accept(parent.type());
|
||||
}
|
||||
for (const auto& child : c.children) {
|
||||
accept(child);
|
||||
}
|
||||
RecursiveVisitor::visit(c);
|
||||
|
||||
uint64_t alignment = 1;
|
||||
for (auto& member : c.members) {
|
||||
@ -82,4 +74,12 @@ void AlignmentCalc::visit(Class& c) {
|
||||
}
|
||||
}
|
||||
|
||||
void AlignmentCalc::visit(Container& c) {
|
||||
RecursiveVisitor::visit(c);
|
||||
|
||||
if (c.underlying()) {
|
||||
c.setAlign(c.underlying()->align());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace oi::detail::type_graph
|
||||
|
@ -41,6 +41,7 @@ class AlignmentCalc final : public RecursiveVisitor {
|
||||
|
||||
void accept(Type& type) override;
|
||||
void visit(Class& c) override;
|
||||
void visit(Container& c) override;
|
||||
|
||||
private:
|
||||
std::unordered_set<Type*> visited_;
|
||||
|
@ -81,7 +81,7 @@ class DrgnParser {
|
||||
template <typename T, typename... Args>
|
||||
T& makeType(struct drgn_type* drgnType, Args&&... args) {
|
||||
auto& newType = typeGraph_.makeType<T>(std::forward<Args>(args)...);
|
||||
drgn_types_.insert({drgnType, newType});
|
||||
drgn_types_.insert_or_assign(drgnType, newType);
|
||||
return newType;
|
||||
}
|
||||
bool chasePointer() const;
|
||||
|
@ -134,8 +134,6 @@ void Flattener::visit(Class& c) {
|
||||
// };
|
||||
// TODO comment about virtual inheritance
|
||||
|
||||
// TODO alignment of parent classes
|
||||
|
||||
// Flatten types referenced by template params, parents and members
|
||||
for (const auto& param : c.templateParams) {
|
||||
accept(param.type());
|
||||
@ -207,12 +205,4 @@ void Flattener::visit(Class& c) {
|
||||
}
|
||||
}
|
||||
|
||||
void Flattener::visit(Container& c) {
|
||||
// Containers themselves don't need to be flattened, but their template
|
||||
// parameters might need to be
|
||||
for (const auto& templateParam : c.templateParams) {
|
||||
accept(templateParam.type());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace oi::detail::type_graph
|
||||
|
@ -42,7 +42,6 @@ class Flattener : public RecursiveVisitor {
|
||||
|
||||
void accept(Type& type) override;
|
||||
void visit(Class& c) override;
|
||||
void visit(Container& c) override;
|
||||
|
||||
static const inline std::string ParentPrefix = "__oi_parent";
|
||||
|
||||
|
@ -57,11 +57,12 @@ Type& IdentifyContainers::visit(Class& c) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto& container = typeGraph_.makeType<Container>(*containerInfo, c.size());
|
||||
auto& container =
|
||||
typeGraph_.makeType<Container>(*containerInfo, c.size(), &c);
|
||||
container.templateParams = c.templateParams;
|
||||
|
||||
tracker_.set(c, &container);
|
||||
RecursiveMutator::visit(container);
|
||||
visit(container);
|
||||
return container;
|
||||
}
|
||||
|
||||
@ -70,4 +71,15 @@ Type& IdentifyContainers::visit(Class& c) {
|
||||
return c;
|
||||
}
|
||||
|
||||
Type& IdentifyContainers::visit(Container& c) {
|
||||
for (auto& param : c.templateParams) {
|
||||
param.setType(mutate(param.type()));
|
||||
}
|
||||
|
||||
// Do not mutate the underlying class further here as that would result in it
|
||||
// getting replaced with this Container node
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
} // namespace oi::detail::type_graph
|
||||
|
@ -48,6 +48,7 @@ class IdentifyContainers : public RecursiveMutator {
|
||||
|
||||
Type& mutate(Type& type) override;
|
||||
Type& visit(Class& c) override;
|
||||
Type& visit(Container& c) override;
|
||||
|
||||
private:
|
||||
ResultTracker<Type*> tracker_;
|
||||
|
@ -85,7 +85,7 @@ void Printer::visit(const Class& c) {
|
||||
print_function(function);
|
||||
}
|
||||
for (auto& child : c.children) {
|
||||
print_child(child);
|
||||
print_type("Child", child);
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,11 +93,14 @@ void Printer::visit(const Container& c) {
|
||||
if (prefix(c))
|
||||
return;
|
||||
|
||||
out_ << "Container: " << c.name() << " (size: " << c.size() << ")"
|
||||
<< std::endl;
|
||||
out_ << "Container: " << c.name() << " (size: " << c.size()
|
||||
<< align_str(c.align()) << ")" << std::endl;
|
||||
for (const auto& param : c.templateParams) {
|
||||
print_param(param);
|
||||
}
|
||||
if (c.underlying()) {
|
||||
print_type("Underlying", *c.underlying());
|
||||
}
|
||||
}
|
||||
|
||||
void Printer::visit(const Primitive& p) {
|
||||
@ -240,11 +243,11 @@ void Printer::print_function(const Function& function) {
|
||||
depth_--;
|
||||
}
|
||||
|
||||
void Printer::print_child(const Type& child) {
|
||||
void Printer::print_type(std::string_view header, const Type& type) {
|
||||
depth_++;
|
||||
prefix();
|
||||
out_ << "Child" << std::endl;
|
||||
print(child);
|
||||
out_ << header << std::endl;
|
||||
print(type);
|
||||
depth_--;
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@ class Printer : public ConstVisitor {
|
||||
void print_parent(const Parent& parent);
|
||||
void print_member(const Member& member);
|
||||
void print_function(const Function& function);
|
||||
void print_child(const Type& child);
|
||||
void print_type(std::string_view header, const Type& type);
|
||||
void print_value(const std::string& value);
|
||||
void print_qualifiers(const QualifierSet& qualifiers);
|
||||
void print_enumerator(int64_t val, const std::string& name);
|
||||
|
@ -39,18 +39,7 @@ void Prune::accept(Type& type) {
|
||||
}
|
||||
|
||||
void Prune::visit(Class& c) {
|
||||
for (const auto& param : c.templateParams) {
|
||||
accept(param.type());
|
||||
}
|
||||
for (const auto& parent : c.parents) {
|
||||
accept(parent.type());
|
||||
}
|
||||
for (const auto& member : c.members) {
|
||||
accept(member.type());
|
||||
}
|
||||
for (const auto& child : c.children) {
|
||||
accept(child);
|
||||
}
|
||||
RecursiveVisitor::visit(c);
|
||||
|
||||
c.templateParams.clear();
|
||||
c.parents.clear();
|
||||
@ -62,4 +51,10 @@ void Prune::visit(Class& c) {
|
||||
c.functions.shrink_to_fit();
|
||||
}
|
||||
|
||||
void Prune::visit(Container& c) {
|
||||
RecursiveVisitor::visit(c);
|
||||
|
||||
c.setUnderlying(nullptr);
|
||||
}
|
||||
|
||||
} // namespace oi::detail::type_graph
|
||||
|
@ -43,6 +43,7 @@ class Prune : public RecursiveVisitor {
|
||||
|
||||
void accept(Type& type) override;
|
||||
void visit(Class& c) override;
|
||||
void visit(Container& c) override;
|
||||
|
||||
private:
|
||||
NodeTracker& tracker_;
|
||||
|
@ -79,7 +79,8 @@ void TypeIdentifier::visit(Container& c) {
|
||||
it != passThroughTypeDummys_.end()) {
|
||||
dummy = &it->second.get();
|
||||
} else {
|
||||
dummy = &typeGraph_.makeType<Container>(info, param.type().size());
|
||||
dummy = &typeGraph_.makeType<Container>(
|
||||
info, param.type().size(), paramClass);
|
||||
dummy->templateParams = paramClass->templateParams;
|
||||
passThroughTypeDummys_.insert(it,
|
||||
{paramClass->id(), std::ref(*dummy)});
|
||||
|
@ -150,7 +150,6 @@ struct Function {
|
||||
int virtuality;
|
||||
};
|
||||
|
||||
class Class;
|
||||
struct Parent {
|
||||
Parent(Type& type, uint64_t bitOffset) : type_(type), bitOffset(bitOffset) {
|
||||
}
|
||||
@ -298,10 +297,6 @@ class Class : public Type {
|
||||
|
||||
DECLARE_ACCEPT
|
||||
|
||||
Kind kind() const {
|
||||
return kind_;
|
||||
}
|
||||
|
||||
virtual const std::string& name() const override {
|
||||
return name_;
|
||||
}
|
||||
@ -326,12 +321,16 @@ class Class : public Type {
|
||||
return align_;
|
||||
}
|
||||
|
||||
void setAlign(uint64_t alignment) {
|
||||
align_ = alignment;
|
||||
}
|
||||
|
||||
virtual NodeId id() const override {
|
||||
return id_;
|
||||
}
|
||||
|
||||
void setAlign(uint64_t alignment) {
|
||||
align_ = alignment;
|
||||
Kind kind() const {
|
||||
return kind_;
|
||||
}
|
||||
|
||||
int virtuality() const {
|
||||
@ -371,10 +370,19 @@ class Class : public Type {
|
||||
bool packed_ = false;
|
||||
};
|
||||
|
||||
/*
|
||||
* Container
|
||||
*
|
||||
* A type of class for which we can do special processing.
|
||||
*/
|
||||
class Container : public Type {
|
||||
public:
|
||||
Container(NodeId id, const ContainerInfo& containerInfo, size_t size)
|
||||
Container(NodeId id,
|
||||
const ContainerInfo& containerInfo,
|
||||
size_t size,
|
||||
Type* underlying)
|
||||
: containerInfo_(containerInfo),
|
||||
underlying_(underlying),
|
||||
name_(containerInfo.typeName),
|
||||
inputName_(containerInfo.typeName),
|
||||
size_(size),
|
||||
@ -386,6 +394,7 @@ class Container : public Type {
|
||||
const ContainerInfo& containerInfo)
|
||||
: templateParams(other.templateParams),
|
||||
containerInfo_(containerInfo),
|
||||
underlying_(other.underlying_),
|
||||
name_(other.name_),
|
||||
inputName_(other.inputName_),
|
||||
size_(other.size_),
|
||||
@ -396,22 +405,18 @@ class Container : public Type {
|
||||
|
||||
DECLARE_ACCEPT
|
||||
|
||||
const std::string& containerName() const {
|
||||
return containerInfo_.typeName;
|
||||
}
|
||||
|
||||
virtual const std::string& name() const override {
|
||||
return name_;
|
||||
}
|
||||
|
||||
void setName(std::string name) {
|
||||
name_ = std::move(name);
|
||||
}
|
||||
|
||||
virtual std::string_view inputName() const override {
|
||||
return inputName_;
|
||||
}
|
||||
|
||||
void setName(std::string name) {
|
||||
name_ = std::move(name);
|
||||
}
|
||||
|
||||
void setInputName(std::string name) {
|
||||
inputName_ = std::move(name);
|
||||
}
|
||||
@ -424,18 +429,31 @@ class Container : public Type {
|
||||
return align_;
|
||||
}
|
||||
|
||||
void setAlign(uint64_t alignment) {
|
||||
align_ = alignment;
|
||||
}
|
||||
|
||||
virtual NodeId id() const override {
|
||||
return id_;
|
||||
}
|
||||
|
||||
void setAlign(uint64_t alignment) {
|
||||
align_ = alignment;
|
||||
const std::string& containerName() const {
|
||||
return containerInfo_.typeName;
|
||||
}
|
||||
|
||||
Type* underlying() const {
|
||||
return underlying_;
|
||||
}
|
||||
|
||||
void setUnderlying(Type* underlying) {
|
||||
underlying_ = underlying;
|
||||
}
|
||||
|
||||
std::vector<TemplateParam> templateParams;
|
||||
const ContainerInfo& containerInfo_;
|
||||
|
||||
private:
|
||||
Type* underlying_;
|
||||
std::string name_;
|
||||
std::string inputName_;
|
||||
size_t size_;
|
||||
|
@ -93,6 +93,7 @@ class RecursiveVisitor : public Visitor<void> {
|
||||
for (const auto& param : c.templateParams) {
|
||||
accept(param.type());
|
||||
}
|
||||
accept(c.underlying());
|
||||
}
|
||||
virtual void visit(Primitive&) {
|
||||
}
|
||||
@ -126,6 +127,11 @@ class RecursiveMutator : public Visitor<Type&> {
|
||||
public:
|
||||
virtual ~RecursiveMutator() = default;
|
||||
virtual Type& mutate(Type&) = 0;
|
||||
virtual Type* mutate(Type* type) {
|
||||
if (type)
|
||||
return &mutate(*type);
|
||||
return nullptr;
|
||||
}
|
||||
virtual Type& visit(Incomplete& i) {
|
||||
return i;
|
||||
}
|
||||
@ -148,6 +154,7 @@ class RecursiveMutator : public Visitor<Type&> {
|
||||
for (auto& param : c.templateParams) {
|
||||
param.setType(mutate(param.type()));
|
||||
}
|
||||
c.setUnderlying(mutate(c.underlying()));
|
||||
return c;
|
||||
}
|
||||
virtual Type& visit(Primitive& p) {
|
||||
|
@ -265,10 +265,11 @@ Type& TypeGraphParser::parseType(std::string_view& input, size_t rootIndent) {
|
||||
|
||||
auto size = parseNumericAttribute(line, nodeTypeName, "size: ");
|
||||
|
||||
Container& c = typeGraph_.makeType<Container>(id, info, size);
|
||||
Container& c = typeGraph_.makeType<Container>(id, info, size, nullptr);
|
||||
nodesById_.insert({id, c});
|
||||
|
||||
parseParams(c, input, indent + 2);
|
||||
parseUnderlying(c, input, indent + 2);
|
||||
|
||||
type = &c;
|
||||
} else if (nodeTypeName == "Primitive") {
|
||||
@ -452,3 +453,26 @@ void TypeGraphParser::parseChildren(Class& c,
|
||||
// No more children for us - put back the line we just read
|
||||
input = origInput;
|
||||
}
|
||||
|
||||
void TypeGraphParser::parseUnderlying(Container& c,
|
||||
std::string_view& input,
|
||||
size_t rootIndent) {
|
||||
std::string_view origInput = input;
|
||||
std::string_view line;
|
||||
getline(input, line);
|
||||
|
||||
size_t indent = stripIndent(line);
|
||||
if (indent != rootIndent) {
|
||||
input = origInput;
|
||||
return;
|
||||
}
|
||||
|
||||
// Format: "Underlying"
|
||||
if (!tryRemovePrefix(line, "Underlying")) {
|
||||
input = origInput;
|
||||
return;
|
||||
}
|
||||
|
||||
Type& type = parseType(input, rootIndent + 2);
|
||||
c.setUnderlying(&type);
|
||||
}
|
||||
|
@ -34,6 +34,9 @@ class TypeGraphParser {
|
||||
void parseMembers(Class& c, std::string_view& input, size_t rootIndent);
|
||||
void parseFunctions(Class& c, std::string_view& input, size_t rootIndent);
|
||||
void parseChildren(Class& c, std::string_view& input, size_t rootIndent);
|
||||
void parseUnderlying(Container& c,
|
||||
std::string_view& input,
|
||||
size_t rootIndent);
|
||||
};
|
||||
|
||||
class TypeGraphParserError : public std::runtime_error {
|
||||
|
@ -106,7 +106,7 @@ TEST_F(AddChildrenTest, InheritancePolymorphic) {
|
||||
Function: ~allocator
|
||||
Function: allocate
|
||||
Function: deallocate
|
||||
*
|
||||
*
|
||||
Function: ~B (virtual)
|
||||
Function: myfunc (virtual)
|
||||
Function: B
|
||||
@ -159,7 +159,7 @@ TEST_F(AddChildrenTest, InheritancePolymorphic) {
|
||||
Function: ~allocator
|
||||
Function: allocate
|
||||
Function: deallocate
|
||||
*
|
||||
*
|
||||
Function: operator=
|
||||
Function: B
|
||||
Function: B
|
||||
|
@ -58,16 +58,16 @@ TEST(AlignmentCalcTest, StructInContainer) {
|
||||
Member: n (offset: 0)
|
||||
Primitive: int8_t
|
||||
Member: n (offset: 8)
|
||||
Primitive: int64_t
|
||||
Primitive: int32_t
|
||||
)",
|
||||
R"(
|
||||
[0] Container: std::vector (size: 8)
|
||||
Param
|
||||
[1] Class: MyClass (size: 16, align: 8)
|
||||
[1] Class: MyClass (size: 16, align: 4)
|
||||
Member: n (offset: 0, align: 1)
|
||||
Primitive: int8_t
|
||||
Member: n (offset: 8, align: 8)
|
||||
Primitive: int64_t
|
||||
Member: n (offset: 8, align: 4)
|
||||
Primitive: int32_t
|
||||
)");
|
||||
}
|
||||
|
||||
@ -264,3 +264,33 @@ TEST(AlignmentCalcTest, Typedef) {
|
||||
Primitive: int8_t
|
||||
)");
|
||||
}
|
||||
|
||||
TEST(AlignmentCalcTest, Container) {
|
||||
test(AlignmentCalc::createPass(),
|
||||
R"(
|
||||
[0] Container: std::vector (size: 24)
|
||||
Underlying
|
||||
[1] Class: vector (size: 24)
|
||||
Member: n (offset: 0)
|
||||
Primitive: int8_t
|
||||
Member: s (offset: 4)
|
||||
[2] Struct: MyStruct (size: 8)
|
||||
Member: n1 (offset: 0)
|
||||
Primitive: int32_t
|
||||
Member: n2 (offset: 4)
|
||||
Primitive: int32_t
|
||||
)",
|
||||
R"(
|
||||
[0] Container: std::vector (size: 24, align: 4)
|
||||
Underlying
|
||||
[1] Class: vector (size: 24, align: 4)
|
||||
Member: n (offset: 0, align: 1)
|
||||
Primitive: int8_t
|
||||
Member: s (offset: 4, align: 4)
|
||||
[2] Struct: MyStruct (size: 8, align: 4)
|
||||
Member: n1 (offset: 0, align: 4)
|
||||
Primitive: int32_t
|
||||
Member: n2 (offset: 4, align: 4)
|
||||
Primitive: int32_t
|
||||
)");
|
||||
}
|
||||
|
@ -45,6 +45,8 @@ void testTransform(OICodeGen::Config& config,
|
||||
|
||||
void testTransform(std::string_view input, std::string_view expectedAfter) {
|
||||
OICodeGen::Config config;
|
||||
config.features[Feature::PruneTypeGraph] = true;
|
||||
config.features[Feature::TreeBuilderV2] = true;
|
||||
testTransform(config, input, expectedAfter);
|
||||
}
|
||||
} // namespace
|
||||
@ -62,7 +64,7 @@ TEST(CodeGenTest, TransformContainerAllocator) {
|
||||
Function: deallocate
|
||||
)",
|
||||
R"(
|
||||
[2] Container: std::vector<int32_t, DummyAllocator<int32_t, 8, 1, 3>> (size: 24)
|
||||
[2] Container: std::vector<int32_t, DummyAllocator<int32_t, 8, 1, 3>> (size: 24, align: 1)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Param
|
||||
@ -95,14 +97,14 @@ TEST(CodeGenTest, TransformContainerAllocatorParamInParent) {
|
||||
Function: deallocate
|
||||
)",
|
||||
R"(
|
||||
[4] Container: std::map<int32_t, int32_t, DummyAllocator<std::pair<int32_t const, int32_t>, 0, 1, 6>> (size: 24)
|
||||
[4] Container: std::map<int32_t, int32_t, DummyAllocator<std::pair<int32_t const, int32_t>, 0, 1, 6>> (size: 24, align: 1)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Param
|
||||
[6] DummyAllocator [MyAlloc<std::pair<const int, int>>] (size: 0, align: 1)
|
||||
[5] Container: std::pair<int32_t const, int32_t> (size: 8)
|
||||
[5] Container: std::pair<int32_t const, int32_t> (size: 8, align: 1)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Qualifiers: const
|
||||
@ -168,7 +170,7 @@ TEST(CodeGenTest, ReplaceContainersAndDummies) {
|
||||
Function: deallocate
|
||||
)",
|
||||
R"(
|
||||
[2] Container: std::vector<uint32_t, DummyAllocator<uint32_t, 0, 1, 3>> (size: 24)
|
||||
[2] Container: std::vector<uint32_t, DummyAllocator<uint32_t, 0, 1, 3>> (size: 24, align: 1)
|
||||
Param
|
||||
Primitive: uint32_t
|
||||
Param
|
||||
@ -176,3 +178,73 @@ TEST(CodeGenTest, ReplaceContainersAndDummies) {
|
||||
Primitive: uint32_t
|
||||
)");
|
||||
}
|
||||
|
||||
TEST(CodeGenTest, ContainerAlignment) {
|
||||
testTransform(R"(
|
||||
[0] Class: MyClass (size: 24)
|
||||
Member: container (offset: 0)
|
||||
[1] Class: std::vector (size: 24)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Member: __impl__ (offset: 0)
|
||||
Primitive: StubbedPointer
|
||||
Member: __impl__ (offset: 8)
|
||||
Primitive: StubbedPointer
|
||||
Member: __impl__ (offset: 16)
|
||||
Primitive: StubbedPointer
|
||||
)",
|
||||
R"(
|
||||
[0] Class: MyClass_0 [MyClass] (size: 24, align: 8)
|
||||
Member: container_0 [container] (offset: 0, align: 8)
|
||||
[2] Container: std::vector<int32_t> (size: 24, align: 8)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
)");
|
||||
}
|
||||
|
||||
TEST(CodeGenTest, InheritFromContainer) {
|
||||
testTransform(R"(
|
||||
[0] Class: MyClass (size: 24)
|
||||
Parent (offset: 0)
|
||||
[1] Class: std::vector (size: 24)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Member: __impl__ (offset: 0)
|
||||
Primitive: StubbedPointer
|
||||
Member: __impl__ (offset: 8)
|
||||
Primitive: StubbedPointer
|
||||
Member: __impl__ (offset: 16)
|
||||
Primitive: StubbedPointer
|
||||
)",
|
||||
R"(
|
||||
[0] Class: MyClass_0 [MyClass] (size: 24, align: 8)
|
||||
Member: __oi_parent_0 [__oi_parent] (offset: 0, align: 8)
|
||||
[2] Container: std::vector<int32_t> (size: 24, align: 8)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
)");
|
||||
}
|
||||
|
||||
TEST(CodeGenTest, InheritFromContainerCompat) {
|
||||
OICodeGen::Config config;
|
||||
testTransform(config,
|
||||
R"(
|
||||
[0] Class: MyClass (size: 24)
|
||||
Parent (offset: 0)
|
||||
[1] Class: std::vector (size: 24)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Member: __impl__ (offset: 0)
|
||||
Primitive: StubbedPointer
|
||||
Member: __impl__ (offset: 8)
|
||||
Primitive: StubbedPointer
|
||||
Member: __impl__ (offset: 16)
|
||||
Primitive: StubbedPointer
|
||||
)",
|
||||
R"(
|
||||
[0] Class: MyClass_0 [MyClass] (size: 24, align: 8)
|
||||
Member: __oi_padding_0 (offset: 0)
|
||||
[3] Array: [int8_t[24]] (length: 24)
|
||||
Primitive: int8_t
|
||||
)");
|
||||
}
|
||||
|
@ -799,6 +799,27 @@ TEST(FlattenerTest, ParentClassAndContainer) {
|
||||
)");
|
||||
}
|
||||
|
||||
TEST(FlattenerTest, ContainerWithParent) {
|
||||
// This is necessary to correctly calculate container alignment
|
||||
test(Flattener::createPass(),
|
||||
R"(
|
||||
[0] Container: std::vector (size: 24)
|
||||
Underlying
|
||||
[1] Class: vector (size: 24)
|
||||
Parent (offset: 0)
|
||||
[2] Class: Parent (size: 4)
|
||||
Member: x (offset: 0)
|
||||
Primitive: int32_t
|
||||
)",
|
||||
R"(
|
||||
[0] Container: std::vector (size: 24)
|
||||
Underlying
|
||||
[1] Class: vector (size: 24)
|
||||
Member: x (offset: 0)
|
||||
Primitive: int32_t
|
||||
)");
|
||||
}
|
||||
|
||||
TEST(FlattenerTest, AllocatorParamInParent) {
|
||||
test(Flattener::createPass(),
|
||||
R"(
|
||||
@ -857,7 +878,7 @@ TEST(FlattenerTest, AllocatorUnfixableNoParent) {
|
||||
)");
|
||||
}
|
||||
|
||||
TEST(FlattenerTest, AllocatorUnfixableParentNotClass) {
|
||||
TEST(FlattenerTest, AllocatorParamInParentContainer) {
|
||||
// This could be supported if need-be, we just don't do it yet
|
||||
test(Flattener::createPass(),
|
||||
R"(
|
||||
|
@ -27,6 +27,12 @@ TEST(IdentifyContainers, Container) {
|
||||
[1] Container: std::vector (size: 24)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Underlying
|
||||
[0] Class: std::vector (size: 24)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Member: a (offset: 0)
|
||||
Primitive: int32_t
|
||||
)");
|
||||
}
|
||||
|
||||
@ -52,14 +58,26 @@ TEST(IdentifyContainers, ContainerInClass) {
|
||||
[4] Container: std::vector (size: 24)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Underlying
|
||||
[1] Class: std::vector (size: 24)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Parent (offset: 0)
|
||||
[5] Container: std::vector (size: 24)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Underlying
|
||||
[2] Class: std::vector (size: 24)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Member: a (offset: 0)
|
||||
[6] Container: std::vector (size: 24)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Underlying
|
||||
[3] Class: std::vector (size: 24)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
)");
|
||||
}
|
||||
|
||||
@ -77,6 +95,14 @@ TEST(IdentifyContainers, ContainerInContainer) {
|
||||
[3] Container: std::vector (size: 24)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Underlying
|
||||
[1] Class: std::vector (size: 24)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Underlying
|
||||
[0] Class: std::vector (size: 24)
|
||||
Param
|
||||
[1]
|
||||
)");
|
||||
}
|
||||
|
||||
@ -94,6 +120,10 @@ TEST(IdentifyContainers, ContainerInContainer2) {
|
||||
[2] Container: std::vector (size: 24)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Underlying
|
||||
[1] Class: std::vector (size: 24)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
)");
|
||||
}
|
||||
|
||||
@ -109,6 +139,10 @@ TEST(IdentifyContainers, ContainerInArray) {
|
||||
[2] Container: std::vector (size: 24)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Underlying
|
||||
[1] Class: std::vector (size: 24)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
)");
|
||||
}
|
||||
|
||||
@ -124,6 +158,10 @@ TEST(IdentifyContainers, ContainerInTypedef) {
|
||||
[2] Container: std::vector (size: 24)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Underlying
|
||||
[1] Class: std::vector (size: 24)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
)");
|
||||
}
|
||||
|
||||
@ -139,6 +177,10 @@ TEST(IdentifyContainers, ContainerInPointer) {
|
||||
[2] Container: std::vector (size: 24)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Underlying
|
||||
[1] Class: std::vector (size: 24)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
)");
|
||||
}
|
||||
|
||||
@ -155,6 +197,12 @@ TEST(IdentifyContainers, ContainerDuplicate) {
|
||||
[1] Container: std::vector (size: 24)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Underlying
|
||||
[0] Class: std::vector (size: 24)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Member: a (offset: 0)
|
||||
Primitive: int32_t
|
||||
[1]
|
||||
)");
|
||||
}
|
||||
@ -190,5 +238,9 @@ TEST(IdentifyContainers, CycleContainer) {
|
||||
[2] Container: std::vector (size: 0)
|
||||
Param
|
||||
[0]
|
||||
Underlying
|
||||
[1] Class: std::vector (size: 0)
|
||||
Param
|
||||
[0]
|
||||
)");
|
||||
}
|
||||
|
@ -63,3 +63,33 @@ TEST(PruneTest, RecurseClassChild) {
|
||||
[1] Class: ClassA (size: 12)
|
||||
)");
|
||||
}
|
||||
|
||||
TEST(PruneTest, PruneContainer) {
|
||||
test(Prune::createPass(),
|
||||
R"(
|
||||
[0] Container: std::vector (size: 24)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Param
|
||||
Value: "123"
|
||||
Primitive: int32_t
|
||||
Underlying
|
||||
[1] Class: vector<int32_t> (size: 24)
|
||||
Parent (offset: 0)
|
||||
[2] Class: MyParent (size: 4)
|
||||
Member: a (offset: 0)
|
||||
Primitive: int32_t
|
||||
Member: a (offset: 0)
|
||||
Primitive: int32_t
|
||||
Member: b (offset: 4)
|
||||
Primitive: int32_t
|
||||
)",
|
||||
R"(
|
||||
[0] Container: std::vector (size: 24)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Param
|
||||
Value: "123"
|
||||
Primitive: int32_t
|
||||
)");
|
||||
}
|
||||
|
@ -108,6 +108,12 @@ TEST(TypeIdentifierTest, PassThroughTypes) {
|
||||
[2] Container: std::allocator (size: 1)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Underlying
|
||||
[1] Class: std::allocator (size: 1)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Function: allocate
|
||||
Function: deallocate
|
||||
)");
|
||||
}
|
||||
|
||||
@ -137,6 +143,12 @@ TEST(TypeIdentifierTest, PassThroughSameType) {
|
||||
[2] Container: std::allocator (size: 1)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Underlying
|
||||
[1] Class: std::allocator (size: 1)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Function: allocate
|
||||
Function: deallocate
|
||||
Param
|
||||
[2]
|
||||
)");
|
||||
|
@ -86,22 +86,23 @@ std::vector<std::unique_ptr<ContainerInfo>> getContainerInfos() {
|
||||
Container getVector(NodeId id) {
|
||||
static ContainerInfo info{"std::vector", SEQ_TYPE, "vector"};
|
||||
info.stubTemplateParams = {1};
|
||||
return Container{id, info, 24};
|
||||
return Container{id, info, 24, nullptr};
|
||||
}
|
||||
|
||||
Container getMap(NodeId id) {
|
||||
static ContainerInfo info{"std::map", STD_MAP_TYPE, "map"};
|
||||
info.stubTemplateParams = {2, 3};
|
||||
return Container{id, info, 48};
|
||||
return Container{id, info, 48, nullptr};
|
||||
}
|
||||
|
||||
Container getList(NodeId id) {
|
||||
static ContainerInfo info{"std::list", LIST_TYPE, "list"};
|
||||
info.stubTemplateParams = {1};
|
||||
return Container{id, info, 24};
|
||||
return Container{id, info, 24, nullptr};
|
||||
}
|
||||
|
||||
Container getPair(NodeId id) {
|
||||
static ContainerInfo info{"std::pair", PAIR_TYPE, "utility"};
|
||||
return Container{id, info, 8}; // Nonsense size, shouldn't matter for tests
|
||||
return Container{
|
||||
id, info, 8, nullptr}; // Nonsense size, shouldn't matter for tests
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user