Skip to content

Bug: Clang compilation error due to const-correctness in image.h #82

@dkar-sto

Description

@dkar-sto

Summary

When compiling code that uses nvblox with clang, a build error occurs in nvblox/sensors/internal/impl/image_impl.h. The error, cannot assign to return value because function 'operator()' returns a const value, is triggered because MaskedImageView::setMasked() attempts to modify a value returned by a const operator(). This issue is not present when compiling with gcc, indicating stricter const-correctness enforcement by clang.

Build Environment

  • Compiler: clang++ (LLVM version 18)
  • C++ Standard: C++20
  • Operating System: Linux

Steps to Reproduce

To reproduce the error, you can use the following minimal example. This code snippet isolates the problematic behavior by creating a MaskedImageView and calling setMasked(), which triggers the const-correctness error with clang.

1. Create a C++ source file

Create a file named repro.cpp:

#include <nvblox/sensors/image.h>

int main(int argc, char** argv) {
  // Dummy data
  constexpr int rows = 10;
  constexpr int cols = 10;
  float image_data[rows * cols] = {0.0f};
  unsigned char mask_data[rows * cols] = {0};

  // Create ImageViews (non-owning wrappers)
  nvblox::ImageView<float> image_view(rows, cols, image_data);
  nvblox::ImageView<const unsigned char> mask_view(rows, cols, mask_data);

  // Create a MaskedImageView
  nvblox::MaskedImageView<float> masked_image_view(image_view, mask_view);

  // This call fails to compile with clang because mask_view.operator() is const
  // and returns a const reference, which can't be assigned to.
  masked_image_view.setMasked(5, 5);

  return 0;
}

2. Create a CMakeLists.txt

Create a CMakeLists.txt file in the same directory:

cmake_minimum_required(VERSION 3.16)
project(nvblox_repro LANGUAGES CXX CUDA)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Find the dependencies for nvblox
find_package(glog REQUIRED)
find_package(gflags REQUIRED)
find_package(stdgpu REQUIRED)
find_package(CUDA REQUIRED)
find_package(nvblox REQUIRED)

add_executable(repro repro.cpp)

target_link_libraries(repro PRIVATE nvblox::nvblox_lib)

3. Configure and Build with Clang

Configure and build the project using clang as the compiler. This will fail at the build step.

export CC=/usr/bin/clang
export CXX=/usr/bin/clang++

cmake -B build
cmake --build build

The build will fail with the error described in the log below.

Build Error Log

Here is the relevant output from the build failure:

[ 50%] Building CXX object CMakeFiles/repro.dir/repro.cpp.o
In file included from /home/dkar/deps/nvblox/repro_test/repro.cpp:1:
In file included from /usr/local/include/nvblox/sensors/image.h:518:
/usr/local/include/nvblox/sensors/internal/impl/image_impl.h:265:27: error: cannot assign to return value because function 'operator()' returns a const value
  265 |   mask_(row_idx, col_idx) = image::kMaskedValue;
      |   ~~~~~~~~~~~~~~~~~~~~~~~ ^
/usr/local/include/nvblox/sensors/image.h:132:30: note: function 'operator()' which returns const-qualified type 'ElementType &' (aka 'const unsigned char &') declared here
  132 |   __host__ __device__ inline ElementType& operator()(const int row_idx,
      |                              ^~~~~~~~~~~~
1 error generated.
gmake[2]: *** [CMakeFiles/repro.dir/build.make:79: CMakeFiles/repro.dir/repro.cpp.o] Error 1
gmake[1]: *** [CMakeFiles/Makefile2:87: CMakeFiles/repro.dir/all] Error 2
gmake: *** [Makefile:91: all] Error 2

Code Analysis

The error occurs in nvblox/sensors/internal/impl/image_impl.h at line 265, within the MaskedImageView<ElementType>::setMasked function:

// nvblox/sensors/internal/impl/image_impl.h:265
mask_(row_idx, col_idx) = image::kMaskedValue;

The mask_ member is an ImageView<unsigned char>. Its operator() is defined in nvblox/sensors/image.h as a const method that returns a const reference, which prevents modification of the underlying data.

// nvblox/sensors/image.h:~132 (inside ImageView)
__host__ __device__ inline const ElementType& operator()(const int row_idx,
                                                      const int col_idx) const {
  return get(row_idx, col_idx);
}

To allow modification, a non-const overload of operator() is probably needed in the ImageView class.

Workaround

A temporary workaround that resolves the immediate compilation issue is to use const_cast at the call site in image_impl.h:

// nvblox/sensors/internal/impl/image_impl.h:265
const_cast<unsigned char&>(mask_(row_idx, col_idx)) = image::kMaskedValue;

While this works, adding the non-const overload is the more correct and robust solution.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions