On Thu, Feb 5, 2026 at 12:28 PM Jonathan Wakely <[email protected]> wrote:

> The new constructor added for Contracts support was not explicit, so
> caused ambiguities when arbitrary pointers were used in contexts which
> could convert to std::source_location.
>
> We don't actually need a constructor, the contract_violation::location()
> function can just set the data member directly.
>
> It might as well be marked noexcept too. And the comment on the friend
> declaration isn't accurate, the friend needs access to the private
> constructor, not the __impl type.
>
> libstdc++-v3/ChangeLog:
>
>         * include/std/contracts (contract_violation::location): Use
>         source_location default constructor and then set _M_impl.
>         * include/std/source_location (source_location(const void*)):
>         Remove constructor.
>         * testsuite/18_support/contracts/includes.cc: Move to...
>         * testsuite/18_support/contracts/srcloc.cc: ...here. Test for
>         ambiguity caused by new constructor.
> ---
>
> v2: remove the new constructor completely, and make contract_violation
> set the data member instead.
>
LGTM.

>
> Iain, Nina, is there a reason we need the new problematic constructor,
> or can we just do this instead? If we do need the constructor, does it
> need to take const void* or could it use const __impl* instead?
>
> I know there are differences between the __builtin_source_location()
> builtin's return type in GCC and Clang, but I don't think that matters
> here. All that matters is that the libstdc++ contract_violation is used
> alongside the libstdc++ source_location, but that should be guaranteed.
> You can't mix the libc++ <contracts> header with the libstdc++
> <source_location> header, or vice versa.
>
>  libstdc++-v3/include/std/contracts                     |  5 ++++-
>  libstdc++-v3/include/std/source_location               |  4 ----
>  .../18_support/contracts/{includes.cc => srcloc.cc}    | 10 ++++++++++
>  3 files changed, 14 insertions(+), 5 deletions(-)
>  rename libstdc++-v3/testsuite/18_support/contracts/{includes.cc =>
> srcloc.cc} (59%)
>
> diff --git a/libstdc++-v3/include/std/contracts
> b/libstdc++-v3/include/std/contracts
> index 0fd9b10247ea..c1fe54750af9 100644
> --- a/libstdc++-v3/include/std/contracts
> +++ b/libstdc++-v3/include/std/contracts
> @@ -92,7 +92,10 @@ namespace contracts
>      detection_mode mode() const noexcept { return _M_detection_mode; }
>      const char* comment() const noexcept { return _M_comment; }
>      std::source_location location() const noexcept {
> -      return std::source_location (_M_src_loc_ptr);
> +      std::source_location __loc;
> +      __loc._M_impl
> +          = static_cast<const source_location::__impl*>(_M_src_loc_ptr);
> +      return __loc;
>      }
>      bool is_terminating () const noexcept {
>        return _M_evaluation_semantic ==
> std::contracts::evaluation_semantic::enforce
> diff --git a/libstdc++-v3/include/std/source_location
> b/libstdc++-v3/include/std/source_location
> index f773879755c9..8115e059536d 100644
> --- a/libstdc++-v3/include/std/source_location
> +++ b/libstdc++-v3/include/std/source_location
> @@ -89,11 +89,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>    private:
>      const __impl* _M_impl = nullptr;
>
> -    constexpr source_location (const void *__t)
> -      : _M_impl (static_cast <const __impl*>(__t)) {}
> -
>  #ifdef __glibcxx_contracts
> -    /* To enable use of the source __impl*.  */
>      friend class std::contracts::contract_violation;
>  #endif
>    };
> diff --git a/libstdc++-v3/testsuite/18_support/contracts/includes.cc
> b/libstdc++-v3/testsuite/18_support/contracts/srcloc.cc
> similarity index 59%
> rename from libstdc++-v3/testsuite/18_support/contracts/includes.cc
> rename to libstdc++-v3/testsuite/18_support/contracts/srcloc.cc
> index 91f793f1e201..d616b5557db6 100644
> --- a/libstdc++-v3/testsuite/18_support/contracts/includes.cc
> +++ b/libstdc++-v3/testsuite/18_support/contracts/srcloc.cc
> @@ -4,3 +4,13 @@
>  // We should not get errors from including this before <contracts>:
>  #include <source_location>
>  #include <contracts>
> +
> +struct S { S(char const *); };
> +void f(S);
> +void f(std::source_location);
> +
> +void
> +test01()
> +{
> +  f(""); // { dg-bogus "ambiguous" }
> +}
> --
> 2.52.0
>
>

Reply via email to