diff --git a/oi/type_graph/TopoSorter.cpp b/oi/type_graph/TopoSorter.cpp index 4131a70..29df405 100644 --- a/oi/type_graph/TopoSorter.cpp +++ b/oi/type_graph/TopoSorter.cpp @@ -69,7 +69,7 @@ void TopoSorter::visit(Class& c) { // Same as pointers, children do not create a dependency so are delayed until // the end. for (const auto& child : c.children) { - visitAfter(child); + acceptAfter(child); } } @@ -103,7 +103,7 @@ void TopoSorter::visit(Container& c) { sortedTypes_.push_back(c); if (containerAllowsIncompleteParams(c)) { for (const auto& param : c.templateParams) { - visitAfter(param.type()); + acceptAfter(param.type()); } } } @@ -118,9 +118,16 @@ void TopoSorter::visit(Typedef& td) { } void TopoSorter::visit(Pointer& p) { + if (dynamic_cast(&p.pointeeType())) { + // Typedefs can not be forward declared, so we must sort them before + // pointers which reference them + accept(p.pointeeType()); + return; + } + // Pointers do not create a dependency, but we do still care about the types // they point to, so delay them until the end. - visitAfter(p.pointeeType()); + acceptAfter(p.pointeeType()); } /* @@ -131,13 +138,13 @@ void TopoSorter::visit(Pointer& p) { * program. This means we can delay processing them until after all of the true * dependencies have been sorted. */ -void TopoSorter::visitAfter(Type& type) { +void TopoSorter::acceptAfter(Type& type) { typesToSort_.push(type); } -void TopoSorter::visitAfter(Type* type) { +void TopoSorter::acceptAfter(Type* type) { if (type) { - visitAfter(*type); + acceptAfter(*type); } } diff --git a/oi/type_graph/TopoSorter.h b/oi/type_graph/TopoSorter.h index d9f8105..f17b12d 100644 --- a/oi/type_graph/TopoSorter.h +++ b/oi/type_graph/TopoSorter.h @@ -52,8 +52,8 @@ class TopoSorter : public RecursiveVisitor { std::vector> sortedTypes_; std::queue> typesToSort_; - void visitAfter(Type& type); - void visitAfter(Type* type); + void acceptAfter(Type& type); + void acceptAfter(Type* type); }; } // namespace type_graph diff --git a/test/test_topo_sorter.cpp b/test/test_topo_sorter.cpp index c033d6c..4560625 100644 --- a/test/test_topo_sorter.cpp +++ b/test/test_topo_sorter.cpp @@ -209,10 +209,16 @@ aliasA TEST(TopoSorterTest, Pointers) { // Pointers do not require pointee types to be defined first - auto myclass = Class{0, Class::Kind::Class, "MyClass", 69}; - auto mypointer = Pointer{1, myclass}; + auto classA = Class{0, Class::Kind::Class, "ClassA", 69}; + auto mypointer = Pointer{1, classA}; - test({mypointer}, "MyClass"); + auto myclass = Class{2, Class::Kind::Class, "MyClass", 69}; + myclass.members.push_back(Member{mypointer, "ptr", 0}); + + test({myclass}, R"( +MyClass +ClassA +)"); } TEST(TopoSorterTest, PointerCycle) { @@ -238,6 +244,22 @@ ClassA } } +TEST(TopoSorterTest, PointerToTypedef) { + auto classA = Class{0, Class::Kind::Class, "ClassA", 8}; + auto aliasA = Typedef{1, "aliasA", classA}; + + auto mypointer = Pointer{1, aliasA}; + + auto myclass = Class{2, Class::Kind::Class, "MyClass", 69}; + myclass.members.push_back(Member{mypointer, "ptrToTypedef", 0}); + + test({myclass}, R"( +ClassA +aliasA +MyClass +)"); +} + TEST(TopoSorterTest, TwoDeep) { auto myunion = Class{0, Class::Kind::Union, "MyUnion", 7}; auto mystruct = Class{1, Class::Kind::Struct, "MyStruct", 13};