<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/130396>130396</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            non-exported variable in module interface unit has multiple addresses
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          Diltsman
      </td>
    </tr>
</table>

<pre>
    I posted this on Stack Overflow and it was suggested that I post this to Clang somewhere.  I don't know if this is the correct place to do that.

---
I have a variable `exception_transformers` in coroutine.cpp.  If this variable is in an anonymous namespace, then the output shows that `register_exception_handler()` accesses it at an address 0x18 bytes beyond where every other function accesses it.  If `exception_transformers` is removed from the anonymous namespace, then it is accessed at the same address by all functions.

Is there some interaction between the C++ module and the anonymous namespace that is causing this?  Is there some other cause of this problem?

---
In n4928 (C++23-ish), 9.8.2.2 [namespace.unnamed]

> ...all occurrences of *unique* in a translation unit are replaced by the
> same identifier, and this identifier differs from all other
> identifiers in the translation unit.

To me, this indicates that both anonymous namespaces behave as if they have the same name, so having the declaration and definition of `transform_exception()` in two different anonymous namespaces in the same file shouldn't be causing an issue.

---

https://godbolt.org/z/59EWe5G3b

For clang 19:

    module;
    
    #include <coroutine>
    #include <expected>
    #include <functional>
    #include <iostream>
    #include <ranges>
    #include <stdexcept>
    #include <system_error>
    #include <type_traits>
    #include <vector>
    
    export module mycoroutine;
    export import :stdexception;
    
    export {
      namespace exco {
      template <typename T> using result_t = std::expected<T, std::error_code>;
      }
    }
    
    namespace {
    auto transform_exception() -> exco::result_t<void>;
    std::vector<std::function<exco::result_t<void>()>> exception_transformers{transform_exception};
    }
    
    export {
      namespace exco {
      auto register_exception_handler(std::function<exco::result_t<void>()> func) {
        std::cout << "register_exception_handler()" << &exception_transformers
                  << ' ' << exception_transformers.size() << '\n';
        exception_transformers.emplace_back(std::move(func));
        std::cout << "register_exception_handler()" << &exception_transformers
                  << ' ' << exception_transformers.size() << ' '
                  << sizeof(exception_transformers) << '\n';
      }
      inline auto unerr(auto const t) {
        return std::unexpected{make_error_code(t)};
      }
    
      template <typename T> struct expected_wrapper {
        // Initialize as errno 0 so there are no restrictions on T
        // caused by initializing this
        exco::result_t<T> m_result{exco::unerr(static_cast<std::errc>(0))};
        expected_wrapper<T> *&m_ptr_to_this;
        expected_wrapper(expected_wrapper<T> *&ptr_to_this)
            : m_ptr_to_this{ptr_to_this} {
          m_ptr_to_this = this;
        }
        operator result_t<T>() { return std::move(m_result); };
      };
      } // namespace exco
    
      namespace std {
      template <typename T, typename... Args>
      struct coroutine_traits<exco::result_t<T>, Args...> {
        class promise_type;
        template <typename T1> struct awaiter_type {
          exco::result_t<T1> &m_result;
          explicit awaiter_type(exco::result_t<T1> &result) noexcept
              : m_result{result} {}
          auto await_ready() { return m_result.has_value(); }
          auto await_suspend(std::coroutine_handle<promise_type> h) {
            // This should only happen when await_ready() returns false,
            // which means that has_value() returned false.
            h.destroy();
          }
          auto await_resume() {
            // This should only happen when await_ready() returns true,
            // which means that has_value() returned true.
            return m_result.value();
          }
        };
    
        class promise_type {
          exco::expected_wrapper<T> *m_ptr_to_wrapper;
    
        public:
          auto initial_suspend() noexcept -> std::suspend_never { return {}; }
          auto final_suspend() noexcept -> std::suspend_never { return {}; }
          auto return_value(std::error_code ec) {
            m_ptr_to_wrapper->m_result = std::unexpected{ec};
          }
          auto return_value(auto &&t) { m_ptr_to_wrapper->m_result = std::move(t); }
          auto get_return_object() {
            return exco::expected_wrapper<T>{m_ptr_to_wrapper};
          }
          auto unhandled_exception() {
            for (auto &f : exception_transformers | std::views::reverse) {
              try {
                auto result = f();
                if (!result.has_value()) {
                  m_ptr_to_wrapper->m_result = std::unexpected{result.error()};
                  return;
                }
              } catch (...) {
              }
            }
            m_ptr_to_wrapper->m_result = exco::unerr(exco::stdexception::unknown);
          }
          template <typename T1> auto await_transform(exco::result_t<T1> value) {
            m_ptr_to_wrapper->m_result = std::move(value);
            return awaiter_type<T1>{m_ptr_to_wrapper->m_result};
          }
        };
      };
      } // namespace std
    }
    
    namespace {
    auto transform_exception() -> exco::result_t<void> {
      std::cout << "transform_exception()" << &exception_transformers << ' '
                << exception_transformers.size() << '\n';
      try {
        throw;
      } catch (std::exception const &) {
        return exco::unerr(exco::stdexception::exception);
      }
    }
    }
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJzUWUuP27oV_jWczcEIsjR-LbywPZkiqy4aoEuDpo4tNhKpkpQd319f8KGXLXmSe9MCHSSwJZHn8Z3vPChTrflZIG7IfEfm7y-0NrlUm3deGF1S8XKU2W3zFSqpDWZgcq5BCviHoew7_P2C6lTIK1CRATdwpRp0fT5jWEsN-J1-n5GwL6g4g5YlXnNUGAF8hUwKkiwNfBfyCvzk19rlOQKTSiEzUBWUoRWQSSc3IvGWxNvX11cSb79CTi8IFC5UcXosEMgixh8MK8OlOBhFhT5JVaLSZBEDF1asrA0XGLGqskYEra0Aa4EAav9JcStlrUHQEnVFGZJkb20TzkBZm6o2oHN51d5jsogVnrk2qA6dETkVWYGKJCuSrK0VlDHUGrXFjRqnKssUag3xj9kKjjeDmuwTso2PeJMiAwcY4AXVDaTJUcGpFswK78vyzjz3X4PCUl4wg5OSpXPjmZvc2C1BR2aNtTs0LbE1-XgDWhStQTqE56sLokIXcODCoKLe4iOaKwYI9yTZkWQHpczqAh2XJkzyAHMNjNaai7MLGkk_AIaaPDx2EYIMoa2UPBZYkvRjQB0B4m2drIAkq2BHkr5yndsoJXtYR6soiRIg811rRVQL-z0j83cviqRfIIoii4BkrFYKBUNtNZNkWwv-7xpJsnWEAheMgjoQamFjrxAUOn5nFkeTYxDpEOYZCsNP3FJnH7Cx5GxvQ8ZPJ1Tax9LZYL0PMrp1jtAW13sLQqy-SShDzB35M86owcDpozT5WEA0HNHnnvaZizefiy1D7FIrVUv7wMcMIUNWUOVtsD5leOKCu0vp2NtytkuhLnWsI1cZHEdhxi0L7jorTrxAm6N1kflac8SWQ1QA17rGQUkh8TY3ptIk3ZLkgyQfZ5kdZWEiqc4k-fiDJB_z9Zd_4vxv6dEv_5AKmKtus7Xd5W4CQKA1SXfhuvlIUi5YUWcIJN23BYmkX0YX4I8KmcFs6nmTerSYWsGlNgppOfVcUXFGPfVUm8xHYnLBTRssD6iUVFNrzK1CW464mdRzQWYGAvwH_qikMk2JKG89vHbDJbx0HyTdtiZb8tzDH1aTZXMfemUGfzA5eGSwrApqWifsUvhmE8xzSKGuC3Owat9Bm8wSIN12Mdt_cznQPrAgHZjMXLjTTg9Zvjdmdt_8R2ddZxitjYTJVIFXa6D1xWttjLQoS54NVLemNfjv2zsNsxwJn8jy6WmFOqVjzWe5GzN2-d6Lzr3bvxYnB8jT7vun3XLNzaLa19cDjsnahn9P0j2QJPl0BEiSbvViAq9OTffXblr6__5yXECk-R8YyNDtI_O9LYJ93sGUAMd7hocjZd_76NnxgSSrgIlD6P8cFYfME9F2kzyRZDVh1WcQd8wG4KLgAj1ba4HKeu8umBR2WH6kmUJTK9HhWou2uCx3Jf2Oh15NSVZWwiCvRjLrWVXTRtXMQKPjcFW0qlDdGeU7I3y1nZsW_A83BqBSQkJsG76fyOyAI2xWaqO4Hw_tCeLboyA3sLkhiDci2yFvwNTHbHVWlwd_hyx33aIGX22o4ezAqDb96oZKMZ_mcSDyEDZ4AKHRRpItSRbloTLqYOTBj6JPN1ruPJPVl5Ss78hI0i0MlS13g6v3u-jAcLlrTY9G9mkJICtU1EgFd9A22bLcPTAxVIIWe1cKYIR8w8sm5sNifs_Q7qk22c90ZDu_hqsoimCrzr1JAxpet9NDO4yM9wDv-t6JiaLIRWqAMSuodkeLkms8WM1DdMetnPVSjF4ptwXRPn0I4LhRM8-YRQt5er-rKjjjQ9m-cD2R1oYPhAyT3n019BRsc6z54ok34FHoxM6Ag0Ka3R4Z1EiKcqoPF1rU2PTaHTyRpmtdocj6zagLp28mJN0PQ_IF8seS2is832x--OMBSFHYM0xVobBHbjHihHdAw4kW2h5uxoVec85yKJGKcIi68zOIsadwKye6k5JHma2Y8taiMljwFG9dl9gB_lt9Nqr-HS5bMfce3_NiyIkn3g8nyGfZ-STDnpTmto62j0aUVfWx4Myf_O7CErpZj7r9NPNjekvmsOgg8OIbboNLSLKp7Dhx8d9W4Ve1AR05zgCOjMjQb0UBQmtQE-jhoWkw2SB7aMcT1L-zzd0jyYIki2aa-gUbQk8zz6rRGW2COKXy-C9kZjLhArifUs1OcvdM-0nva-ErX_ZwBnw05yQV9BA6ubI-PtQCWfZOrReOV900kAsqW_vGFAAYdRu938aqhfw0nt_-j5_APZ5NNIoJ7X-Bb0GRf4nhlTxGYBjX8af3UQr3gFHDcuuVHScm7H_c-3jnU_8eB-DuzvDFiF_zXcir-Ik-82Si6bWglkTPx44QzL9WMEKyNrIe4xHybzANBQtGUq6v6NP0-xNjrrX7f_iKZwDt1LF8-m3rT5zHPz9D_553FI9FxeRKXu8BbzOs9xou6A3Ha9cWJg7Yv5Y2PbTWn77GW76_ZJs0W6dr-oKb2fJt9hav1qvZS75ZM4xPa0zfVulbOpszTLM4zhbLdDVbIV2lL3yTxMk8TuNV_PaWxnE0my2yIz2u5m_rE0U6J28xlpQXUVFcykiq84t7p72ZpXG6XrwU9IiFbn7iUxu76vVYnzV5iwuuje72GW4K3AgpXv2rN8x6v4qJ5g2s-y3nZKnqfsTIqYayLgyvivZHIdQvtSo2d6_RucnrY8RkSZIPqzN8vFZK-ib64QzXJPkItl82yX8CAAD__6ZzpN0">