Repository: microsoft/onnxruntime
File: onnxruntime/core/framework/tensor_type_and_shape.cc (C++)

Code before:
    dims[idx] = dim_values[idx];
  }

  shape_info.shape = onnxruntime::TensorShape(dims);

  info->SetShape(std::move(shape_info));

  return nullptr;
  API_IMPL_END
}

ORT_API_STATUS_IMPL(OrtApis::GetTensorElementType, _In_ const struct OrtTensorTypeAndShapeInfo* info,
                    _Out_ ONNXTensorElementDataType* out) {
  *out = info->GetElementType();
  return nullptr;
}

ORT_API_STATUS_IMPL(OrtApis::GetDimensionsCount, _In_ const struct OrtTensorTypeAndShapeInfo* info,
                    _Out_ size_t* out) {
  *out = (info->HasShape()) ? info->GetShape()->NumDimensions() : 0;
  return nullptr;
}

ORT_API_STATUS_IMPL(OrtApis::GetDimensions, _In_ const struct OrtTensorTypeAndShapeInfo* info,
                    _Out_ int64_t* dim_values, size_t dim_values_length) {
  if (info->HasShape()) {
    info->GetShape()->CopyDims(dim_values, dim_values_length);
  }
  // else we should probably return an error, but for backward compatibility with the previous implementation we don't.
  return nullptr;
}

ORT_API_STATUS_IMPL(OrtApis::GetSymbolicDimensions,
                    _In_ const struct OrtTensorTypeAndShapeInfo* info,
                    _Out_writes_all_(dim_params_length) const char** names, size_t dim_params_length) {
  if (info->HasShape()) {
    size_t end = info->GetShape()->NumDimensions();
    end = std::min(end, dim_params_length);
    const auto& symbolic_dims = *info->GetDimParams();
    for (size_t idx = 0; idx < end; ++idx) {
      names[idx] = symbolic_dims[idx].c_str();
    }
  }
  // else we should probably return an error, but for backward compatibility with the previous implementation we don't.
  return nullptr;
}

ORT_API(bool, OrtApis::TensorTypeAndShape_HasShape, _In_ const struct OrtTensorTypeAndShapeInfo* info) {
  return info->HasShape();
}


Review comment (suggestion):
Perhaps we should update our C++ APIs to not call GetDimensions if GetDimensionsCount returns 0 (which happens when there's no shape):
https://github.com/microsoft/onnxruntime/blob/0de21a7695290e8c904ce7f170f164b21da33675/include/onnxruntime/core/session/onnxruntime_cxx_inline.h#L2013-L2017

Code after:
  shape_info.shape = onnxruntime::TensorShape(dims);

  info->SetShape(std::move(shape_info));

  return nullptr;
  API_IMPL_END
}

ORT_API_STATUS_IMPL(OrtApis::GetTensorElementType, _In_ const struct OrtTensorTypeAndShapeInfo* info,
                    _Out_ ONNXTensorElementDataType* out) {
  *out = info->GetElementType();
  return nullptr;
}

ORT_API_STATUS_IMPL(OrtApis::GetDimensionsCount, _In_ const struct OrtTensorTypeAndShapeInfo* info,
                    _Out_ size_t* out) {
  *out = (info->HasShape()) ? info->GetShape()->NumDimensions() : 0;
  return nullptr;
}

ORT_API_STATUS_IMPL(OrtApis::GetDimensions, _In_ const struct OrtTensorTypeAndShapeInfo* info,
                    _Out_ int64_t* dim_values, size_t dim_values_length) {
  if (info->HasShape()) {
    info->GetShape()->CopyDims(dim_values, dim_values_length);
  }
  // else we should probably return an error, but for backward compatibility with the previous implementation we don't.
  return nullptr;
}

ORT_API_STATUS_IMPL(OrtApis::GetSymbolicDimensions,
                    _In_ const struct OrtTensorTypeAndShapeInfo* info,
                    _Out_writes_all_(dim_params_length) const char** names, size_t dim_params_length) {
  if (info->HasShape()) {
    size_t end = info->GetShape()->NumDimensions();
    end = std::min(end, dim_params_length);
    const auto& symbolic_dims = *info->GetDimParams();
    for (size_t idx = 0; idx < end; ++idx) {
      names[idx] = symbolic_dims[idx].c_str();
    }
  }
  // else we should probably return an error, but for backward compatibility with the previous implementation we don't.
  return nullptr;
}

ORT_API(bool, OrtApis::TensorTypeAndShape_HasShape, _In_ const struct OrtTensorTypeAndShapeInfo* info) {
  return info->HasShape();
}

ORT_API_STATUS_IMPL(OrtApis::SetSymbolicDimensions,
                    _In_ struct OrtTensorTypeAndShapeInfo* info,
                    _In_ const char** names, _In_ size_t dim_params_length) {