Repository: google/flatbuffers
File: src/idl_parser.cpp (C++)

Code before:
      if (field && field->value.type.base_type == basetype)
        return Error("Field " + fname +
                     " would clash with generated functions for field " +
                     field->name);
    }
  }
  return NoError();
}

std::vector<IncludedFile> Parser::GetIncludedFiles() const {
  const auto it = files_included_per_file_.find(file_being_parsed_);
  if (it == files_included_per_file_.end()) {
    return {};
  }

  return {it->second.cbegin(), it->second.cend()};
}

bool Parser::HasCircularStructDependency() {
  std::function<bool(StructDef*)> visit =
      [&](StructDef* struct_def) {
        // Only consider fixed structs
        if (!struct_def->fixed) {
          return false;
        }

        if (struct_def->cycle_status == StructDef::CycleStatus::InProgress) {
          // cycle found
          return true;
        }

        struct_def->cycle_status = StructDef::CycleStatus::InProgress;

        for (const auto& field : struct_def->fields.vec) {
          if (field->value.type.base_type == BASE_TYPE_STRUCT) {
            if (visit(field->value.type.struct_def)) {
              return true;  // Cycle detected in recursion.
            }
          }
        }

        struct_def->cycle_status = StructDef::CycleStatus::Checked;
        return false;  // No cycle detected.
      };

  for (const auto& struct_def : structs_.vec) {
    if (visit(struct_def)) {
      return true;  // Cycle detected.
    }
  }


Review comment (suggestion):
Don't you also want to just return false if already `Checked` here? If not, this will doubly check every reference to a `struct` and could have explosive cost.

Code after:
      if (field && field->value.type.base_type == basetype)
        return Error("Field " + fname +
                     " would clash with generated functions for field " +
                     field->name);
    }
  }
  return NoError();
}

std::vector<IncludedFile> Parser::GetIncludedFiles() const {
  const auto it = files_included_per_file_.find(file_being_parsed_);
  if (it == files_included_per_file_.end()) {
    return {};
  }

  return {it->second.cbegin(), it->second.cend()};
}

bool Parser::HasCircularStructDependency() {
  std::function<bool(StructDef*)> visit =
      [&](StructDef* struct_def) {
        // Only consider fixed structs and structs we have yet to check
        if (!struct_def->fixed || struct_def->cycle_status == StructDef::CycleStatus::Checked) {
          return false;
        }

        if (struct_def->cycle_status == StructDef::CycleStatus::InProgress) {
          // cycle found
          return true;
        }

        struct_def->cycle_status = StructDef::CycleStatus::InProgress;

        for (const auto& field : struct_def->fields.vec) {
          if (field->value.type.base_type == BASE_TYPE_STRUCT) {
            if (visit(field->value.type.struct_def)) {
              return true;  // Cycle detected in recursion.
            }
          }
        }

        struct_def->cycle_status = StructDef::CycleStatus::Checked;
        return false;  // No cycle detected.
      };

  for (const auto& struct_def : structs_.vec) {
    if (visit(struct_def)) {
      return true;  // Cycle detected.
    }
  }