Skip to content

Replace global Logging macros with inline functions - #7602

Open
tbhova wants to merge 1 commit into
isl-org:mainfrom
tbhova:fix/logging-macro-pollution
Open

tbhova wants to merge 1 commit into
isl-org:mainfrom
tbhova:fix/logging-macro-pollution

Conversation

@tbhova

@tbhova tbhova commented Oct 9, 2026

Copy link
Copy Markdown

Type

  • Bug fix (non-breaking change which fixes an issue): Fixes #
  • New feature (non-breaking change which adds functionality). Resolves #
  • Breaking change (fix or feature that would cause existing functionality to not work as expected) Resolves #

Motivation and Context

cpp/open3d/utility/Logging.h previously defined LogError, LogWarning, LogInfo, and LogDebug as unprefixed preprocessor macros in the global preprocessor scope (#define LogError(...) Logger::LogError_(...)) to mimic a "macro in namespace" when callers write utility::LogError(...).

Because C++ preprocessor macros do not respect namespaces, including any Open3D header that transitively includes open3d/utility/Logging.h (such as open3d/geometry/TriangleMesh.h or open3d/geometry/PointCloud.h) pollutes the global macro namespace for the remainder of the translation unit. Any subsequently included third-party or application header that declares a method, function, or enum named LogError, LogWarning, LogInfo, or LogDebug (for example, custom logger interfaces or Abseil logging utilities) fails to compile because the preprocessor rewrites foo.LogError(...) into foo.Logger::LogError_(__FILE__, __LINE__, ...).

Checklist:

  • I have run python util/check_style.py --apply to apply Open3D code style
    to my code.
  • This PR changes Open3D behavior or adds new functionality.
    • Both C++ (Doxygen) and Python (Sphinx / Google style) documentation is
      updated accordingly.
    • I have added or updated C++ and / or Python unit tests OR included test
      results
      (e.g. screenshots or numbers) here.
  • I will follow up and update the code if CI fails.
  • For fork PRs, I have selected Allow edits from maintainers.

Description

Replaces the global #define LogError, #define LogWarning, #define LogInfo, and #define LogDebug macros in cpp/open3d/utility/Logging.h with inline variadic template functions inside namespace open3d::utility.

Why This Is Possible Now (Without Requiring C++20):
When Logging.h was originally written in 2019 (targeting C++14 and older compilers), preprocessor macros (__FILE__, __LINE__, OPEN3D_FUNCTION) were the only portable way to capture caller source locations because Clang (< 9.0, Sept 2019) and MSVC (< VS 2019 16.6 / _MSC_VER 1926, May 2020) did not yet implement the compiler intrinsics (__builtin_FILE(), __builtin_LINE(), __builtin_FUNCTION()) created to back C++20 std::source_location. Even though the <source_location> header itself requires C++20, all toolchains supported by Open3D today (GCC 7+, Clang 9+, AppleClang, MSVC VS 2019 16.6+, and NVCC) expose __builtin_FILE(), __builtin_LINE(), and __builtin_FUNCTION() in C++17 mode.

Why Functionality Is Equivalent:

  1. Call-site syntax is unchanged: utility::LogError(...), open3d::utility::LogError(...), and unqualified LogError(...) (inside namespace open3d::utility or translation units with using namespace open3d::utility;) all resolve to the new inline function templates in namespace open3d::utility.
  2. Caller source location (file, line, function) is still captured at the call site without C++20 <source_location> or macros: open3d::utility::detail::LogLocation wraps const char *format with a non-explicit constexpr constructor whose default arguments (__builtin_FILE(), __builtin_LINE(), __builtin_FUNCTION()) are evaluated at the caller's source location in C++17 across GCC, Clang, AppleClang, MSVC (VS 2019 16.6+), and NVCC.
  3. Formatting and control-flow semantics are untouched: LogError, LogWarning, LogInfo, and LogDebug forward loc.file, loc.line, loc.function, loc.format, and std::forward<Args>(args)... directly to Logger::LogError_, Logger::LogWarning_, Logger::LogInfo_, and Logger::LogDebug_, preserving [[noreturn]] on LogError and existing fmt formatting behavior.

Testing:

  • Extended cpp/tests/utility/Logging.cpp to verify that utility::LogError captures the caller's filename (Logging.cpp) and formatted message in the thrown std::runtime_error.
  • Added Logging.NoGlobalMacroPollution in cpp/tests/utility/Logging.cpp to verify that a class defining LogError(), LogWarning(), LogInfo(), and LogDebug() member functions compiles and executes cleanly after including open3d/utility/Logging.h.

@update-docs

update-docs Bot commented Oct 9, 2026

Copy link
Copy Markdown

Thanks for submitting this pull request! The maintainers of this repository would appreciate if you could update the CHANGELOG.md based on your changes.

…e functions

Motivation:
`cpp/open3d/utility/Logging.h` previously defined `LogError`, `LogWarning`,
`LogInfo`, and `LogDebug` as unprefixed preprocessor macros in the global
preprocessor scope (`#define LogError(...) Logger::LogError_(...)`) to mimic
a "macro in namespace" when callers write `utility::LogError(...)`.

Because C++ preprocessor macros do not respect namespaces, including any Open3D
header that transitively includes `open3d/utility/Logging.h` (such as
`open3d/geometry/TriangleMesh.h` or `open3d/geometry/PointCloud.h`) pollutes
the global macro namespace for the remainder of the translation unit. Any
subsequently included third-party or application header that declares a method,
function, or enum named `LogError`, `LogWarning`, `LogInfo`, or `LogDebug`
(for example, custom logger interfaces or Abseil logging utilities) fails to
compile because the preprocessor rewrites `foo.LogError(...)` into
`foo.Logger::LogError_(__FILE__, __LINE__, ...)`.

Why This Is Possible Now (Without Requiring C++20):
When `Logging.h` was originally written in 2019 (targeting C++14 and older
compilers), preprocessor macros (`__FILE__`, `__LINE__`, `OPEN3D_FUNCTION`)
were the only portable way to capture caller source locations because Clang
(< 9.0, Sept 2019) and MSVC (< VS 2019 16.6 / `_MSC_VER 1926`, May 2020) did
not yet implement the compiler intrinsics (`__builtin_FILE()`,
`__builtin_LINE()`, `__builtin_FUNCTION()`) created to back C++20
`std::source_location`. Even though the `<source_location>` header itself
requires C++20, all toolchains supported by Open3D today (GCC 7+, Clang 9+,
AppleClang, MSVC VS 2019 16.6+, and NVCC) expose `__builtin_FILE()`,
`__builtin_LINE()`, and `__builtin_FUNCTION()` in C++17 mode.

Why Functionality Is Equivalent:
1. Call-site syntax is unchanged: `utility::LogError(...)`,
   `open3d::utility::LogError(...)`, and unqualified `LogError(...)` (inside
   `namespace open3d::utility` or translation units with
   `using namespace open3d::utility;`) all resolve to the new `inline` function
   templates in `namespace open3d::utility`.
2. Caller source location (`file`, `line`, `function`) is still captured at the
   call site without C++20 `<source_location>` or macros:
   `open3d::utility::detail::LogLocation` wraps `const char *format` with a
   non-explicit `constexpr` constructor whose default arguments
   (`__builtin_FILE()`, `__builtin_LINE()`, `__builtin_FUNCTION()`) are
   evaluated at the caller's source location in C++17 across GCC, Clang,
   AppleClang, MSVC (VS 2019 16.6+), and NVCC.
3. Formatting and control-flow semantics are untouched: `LogError`,
   `LogWarning`, `LogInfo`, and `LogDebug` forward `loc.file`, `loc.line`,
   `loc.function`, `loc.format`, and `std::forward<Args>(args)...` directly to
   `Logger::LogError_`, `Logger::LogWarning_`, `Logger::LogInfo_`, and
   `Logger::LogDebug_`, preserving `[[noreturn]]` on `LogError` and existing
   `fmt` formatting behavior.

Testing:
- Extended `cpp/tests/utility/Logging.cpp` to verify that `utility::LogError`
  captures the caller's filename (`Logging.cpp`) and formatted message in the
  thrown `std::runtime_error`.
- Added `Logging.NoGlobalMacroPollution` in `cpp/tests/utility/Logging.cpp` to
  verify that a class defining `LogError()`, `LogWarning()`, `LogInfo()`, and
  `LogDebug()` member functions compiles and executes cleanly after including
  `open3d/utility/Logging.h`.
@tbhova
tbhova force-pushed the fix/logging-macro-pollution branch from 9e84af0 to f7b5b9b Compare October 9, 2026 20:56
@tbhova

tbhova commented Oct 9, 2026

Copy link
Copy Markdown
Author

Thanks for submitting this pull request! The maintainers of this repository would appreciate if you could update the CHANGELOG.md based on your changes.

Done :)

@tbhova tbhova changed the title Replace global LogError/LogWarning/LogInfo/LogDebug macros with inline functions Replace global Logging macros with inline functions Oct 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant