TopoSorter: Only allow certain params to be incomplete

For the containers which are allowed to be declared with incomplete
types, it is only the contained types which are allowed to be
incomplete. Other template parameters (e.g. allocators) must always be
defined before use.
This commit is contained in:
Alastair Robertson 2023-10-24 09:49:46 -07:00 committed by Alastair Robertson
parent 5daed4cc72
commit e7581ad915
2 changed files with 15 additions and 11 deletions

View File

@ -85,7 +85,7 @@ namespace {
* Other containers are not required to do this, but might still have this * Other containers are not required to do this, but might still have this
* behaviour. * behaviour.
*/ */
bool containerAllowsIncompleteParams(const Container& c) { bool containerAllowsIncompleteParam(const Container& c, size_t i) {
switch (c.containerInfo_.ctype) { switch (c.containerInfo_.ctype) {
case SEQ_TYPE: case SEQ_TYPE:
case LIST_TYPE: case LIST_TYPE:
@ -93,7 +93,7 @@ bool containerAllowsIncompleteParams(const Container& c) {
case SHRD_PTR_TYPE: case SHRD_PTR_TYPE:
// Also std::forward_list, if we ever support that // Also std::forward_list, if we ever support that
// Would be good to have this as an option in the TOML files // Would be good to have this as an option in the TOML files
return true; return i == 0;
default: default:
return false; return false;
} }
@ -101,17 +101,15 @@ bool containerAllowsIncompleteParams(const Container& c) {
} // namespace } // namespace
void TopoSorter::visit(Container& c) { void TopoSorter::visit(Container& c) {
if (!containerAllowsIncompleteParams(c)) { for (size_t i = 0; i < c.templateParams.size(); i++) {
for (const auto& param : c.templateParams) { const auto& param = c.templateParams[i];
if (containerAllowsIncompleteParam(c, i)) {
acceptAfter(param.type());
} else {
accept(param.type()); accept(param.type());
} }
} }
sortedTypes_.push_back(c); sortedTypes_.push_back(c);
if (containerAllowsIncompleteParams(c)) {
for (const auto& param : c.templateParams) {
acceptAfter(param.type());
}
}
} }
void TopoSorter::visit(Enum& e) { void TopoSorter::visit(Enum& e) {

View File

@ -178,24 +178,30 @@ std::map
} }
TEST(TopoSorterTest, ContainersVector) { TEST(TopoSorterTest, ContainersVector) {
// std::vector allows forward declared template parameters // std::vector allows a forward declared type
auto myparam = Class{1, Class::Kind::Struct, "MyParam", 13}; auto myparam = Class{1, Class::Kind::Struct, "MyParam", 13};
auto myalloc = Class{1, Class::Kind::Struct, "MyAlloc", 0};
auto mycontainer = getVector(); auto mycontainer = getVector();
mycontainer.templateParams.push_back((myparam)); mycontainer.templateParams.push_back((myparam));
mycontainer.templateParams.push_back((myalloc));
test({mycontainer}, R"( test({mycontainer}, R"(
MyAlloc
std::vector std::vector
MyParam MyParam
)"); )");
} }
TEST(TopoSorterTest, ContainersList) { TEST(TopoSorterTest, ContainersList) {
// std::list allows forward declared template parameters // std::list allows a forward declared type
auto myparam = Class{1, Class::Kind::Struct, "MyParam", 13}; auto myparam = Class{1, Class::Kind::Struct, "MyParam", 13};
auto myalloc = Class{1, Class::Kind::Struct, "MyAlloc", 0};
auto mycontainer = getList(); auto mycontainer = getList();
mycontainer.templateParams.push_back((myparam)); mycontainer.templateParams.push_back((myparam));
mycontainer.templateParams.push_back((myalloc));
test({mycontainer}, R"( test({mycontainer}, R"(
MyAlloc
std::list std::list
MyParam MyParam
)"); )");